From 22590a98b36977c2257c66dc2d2a72741432d261 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Tue, 3 Feb 2004 08:56:28 +0000 Subject: [PATCH] remove math cursor plus * BufferView.C: * cursor.[Ch]: some additional asserts * undo.[Ch]: remove LyXText dependency in interface * lyxfunc.C: adjust * lyxtext.h (firstPar, lastPar): remove dead functions * text.C: * text2.C: * text3.C: * paragraph.[Ch]: adjust git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8386 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/BufferView.C | 4 +- src/ChangeLog | 17 + src/cursor.C | 48 +- src/cursor.h | 13 +- src/lyxfind.C | 2 +- src/lyxfunc.C | 18 +- src/lyxtext.h | 23 +- src/mathed/math_cursor.C | 1400 ----------------------------------- src/mathed/math_cursor.h | 209 ------ src/mathed/math_gridinset.C | 4 +- src/mathed/math_hullinset.C | 8 +- src/mathed/math_nestinset.C | 34 +- src/paragraph.C | 12 + src/paragraph.h | 2 + src/text.C | 36 +- src/text2.C | 66 +- src/text3.C | 4 +- src/undo.C | 69 +- src/undo.h | 49 +- 19 files changed, 224 insertions(+), 1794 deletions(-) delete mode 100644 src/mathed/math_cursor.C delete mode 100644 src/mathed/math_cursor.h diff --git a/src/BufferView.C b/src/BufferView.C index a04f019931..d1ff326a34 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -333,7 +333,7 @@ void BufferView::undo() owner()->message(_("Undo")); cursor().clearSelection(); - if (!textUndo(this)) + if (!textUndo(*this)) owner()->message(_("No further undo information")); update(); switchKeyMap(); @@ -347,7 +347,7 @@ void BufferView::redo() owner()->message(_("Redo")); cursor().clearSelection(); - if (!textRedo(this)) + if (!textRedo(*this)) owner()->message(_("No further redo information")); update(); switchKeyMap(); diff --git a/src/ChangeLog b/src/ChangeLog index eb48c693ee..3a61399644 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ + +2004-02-03 André Pönitz + + * BufferView.C: + * cursor.[Ch]: some additional asserts + + * undo.[Ch]: remove LyXText dependency in interface + + * lyxfunc.C: adjust + + * lyxtext.h (firstPar, lastPar): remove dead functions + + * text.C: + * text2.C: + * text3.C: + * paragraph.[Ch]: adjust + 2004-02-03 Alfredo Braunstein * lyxfind.C (find): fix argument order in call to ::find diff --git a/src/cursor.C b/src/cursor.C index 5c74ebebb6..0722215073 100644 --- a/src/cursor.C +++ b/src/cursor.C @@ -482,16 +482,24 @@ LyXText * LCursor::text() const Paragraph & LCursor::paragraph() { + BOOST_ASSERT(!inMathed()); return current_ ? current().paragraph() : *bv_->text()->getPar(par()); } Paragraph const & LCursor::paragraph() const { + BOOST_ASSERT(!inMathed()); return current_ ? current().paragraph() : *bv_->text()->getPar(par()); } +LCursor::par_type LCursor::lastpar() const +{ + return inMathed() ? 0 : text()->paragraphs().size() - 1; +} + + LCursor::pos_type LCursor::lastpos() const { InsetBase * inset = current().inset(); @@ -499,6 +507,18 @@ LCursor::pos_type LCursor::lastpos() const } +LCursor::row_type LCursor::crow() const +{ + return paragraph().row(pos()); +} + + +LCursor::row_type LCursor::lastcrow() const +{ + return paragraph().rows.size(); +} + + size_t LCursor::nargs() const { // assume 1x1 grid for 'plain text' @@ -1096,9 +1116,8 @@ bool LCursor::erase() } // delete empty cells if possible -#warning FIXME - //if (cell().empty() && inset()->idxDelete(idx())) - // return true; + if (pos() == lastpos() && inset()->idxDelete(idx())) + return true; // special behaviour when in last position of cell if (pos() == lastpos()) { @@ -1789,3 +1808,26 @@ bool LCursor::inMathed() const { return formula(); } + + +InsetBase * LCursor::nextInset() +{ + if (pos() == lastpos()) + return 0; + if (inMathed()) + return nextAtom().nucleus(); + Paragraph & par = paragraph(); + return par.isInset(pos()) ? par.getInset(pos()) : 0; +} + + +InsetBase * LCursor::prevInset() +{ + if (pos() == 0) + return 0; + if (inMathed()) + return prevAtom().nucleus(); + Paragraph & par = paragraph(); + return par.isInset(pos() - 1) ? par.getInset(pos() - 1) : 0; +} + diff --git a/src/cursor.h b/src/cursor.h index e4d1ebc2a1..0d316b2fac 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -137,7 +137,7 @@ public: // // access to the 'current' cursor slice // - /// the current inset + /// the containing inset InsetBase * inset() const { return current().inset(); } /// return the cell of the inset this cursor is in idx_type idx() const { return current().idx(); } @@ -149,12 +149,19 @@ public: par_type par() const { return current().par(); } /// return the paragraph this cursor is in par_type & par() { return current().par(); } + /// return the last possible paragraph in this inset + par_type lastpar() const; /// return the position within the paragraph pos_type pos() const { return current().pos(); } /// return the position within the paragraph pos_type & pos() { return current().pos(); } /// return the last position within the paragraph pos_type lastpos() const; + /// return the display row of the cursor with in the current par + row_type crow() const; + /// return the display row of the cursor with in the current par + row_type lastcrow() const; + /// return the number of embedded cells size_t nargs() const; /// return the number of embedded cells @@ -165,6 +172,10 @@ public: row_type row() const; /// return the grid row of the current cell col_type col() const; + /// the inset just behind the cursor + InsetBase * nextInset(); + /// the inset just in front of the cursor + InsetBase * prevInset(); // // math-specific part diff --git a/src/lyxfind.C b/src/lyxfind.C index e731579dd2..b7869ba327 100644 --- a/src/lyxfind.C +++ b/src/lyxfind.C @@ -330,7 +330,7 @@ int replaceAll(BufferView * bv, if (!searchAllowed(bv, searchstr) || buf.isReadonly()) return 0; - recordUndo(Undo::ATOMIC, bv->text(), 0, buf.paragraphs().size() - 1); + recordUndoFullDocument(bv->cursor()); PosIterator cur = buf.pos_iterator_begin(); PosIterator const end = buf.pos_iterator_end(); diff --git a/src/lyxfunc.C b/src/lyxfunc.C index a4fe32bcf8..8cd5687b7e 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -685,7 +685,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & ev) const code = InsetOld::SPACE_CODE; break; case LFUN_INSET_DIALOG_SHOW: { - InsetBase * inset = view()->getLyXText()->getInset(); + InsetBase * inset = view()->cursor().nextInset(); disable = !inset; if (inset) { code = inset->lyxCode(); @@ -835,14 +835,6 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) // we have not done anything wrong yet. errorstat = false; dispatch_buffer.erase(); - -#ifdef NEW_DISPATCHER - // We try do call the most specific dispatcher first: - // 1. the lockinginset's dispatch - // 2. the bufferview's dispatch - // 3. the lyxview's dispatch -#endif - selection_possible = false; // We cannot use this function here @@ -1284,7 +1276,7 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) break; case LFUN_INSET_DIALOG_SHOW: { - InsetBase * inset = view()->getLyXText()->getInset(); + InsetBase * inset = view()->cursor().nextInset(); if (inset) inset->dispatch(view()->cursor(), FuncRequest(LFUN_INSET_DIALOG_SHOW)); break; @@ -1443,7 +1435,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) } } - view()->owner()->updateLayoutChoice(); + if (!view()->cursor().inMathed()) + view()->owner()->updateLayoutChoice(); if (view()->available()) { view()->fitCursor(); @@ -1456,7 +1449,8 @@ void LyXFunc::dispatch(FuncRequest const & cmd, bool verbose) view()->buffer()->markDirty(); } - sendDispatchMessage(getMessage(), cmd, verbose); + if (!view()->cursor().inMathed()) + sendDispatchMessage(getMessage(), cmd, verbose); } diff --git a/src/lyxtext.h b/src/lyxtext.h index 4a29e3022d..1555db6af0 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -161,12 +161,9 @@ public: void getWord(CursorSlice & from, CursorSlice & to, lyx::word_location const); /// just selects the word the cursor is in void selectWord(lyx::word_location loc); - /// returns the inset at cursor (if it exists), 0 otherwise - InsetBase * getInset() const; /// accept selected change void acceptChange(); - /// reject selected change void rejectChange(); @@ -322,12 +319,6 @@ public: ParagraphList & paragraphs() const; /// return true if this is owned by an inset. bool isInInset() const; - /// the first of our paragraphs - ParagraphList::iterator firstPar() const; - /// the last of our paragraphs - ParagraphList::iterator lastPar() const; - /// one past the last of our paragraphs - ParagraphList::iterator endPar() const; /// return first row of text RowList::iterator firstRow() const; @@ -387,9 +378,9 @@ public: /// int cursorY(CursorSlice const & cursor) const; - /// the topmost cursor slice + /// the current cursor slice CursorSlice & cursor(); - /// the topmost cursor slice + /// the current cursor slice CursorSlice const & cursor() const; friend class LyXScreen; @@ -460,16 +451,10 @@ private: /// sets row.end to the pos value *after* which a row should break. /// for example, the pos after which isNewLine(pos) == true void rowBreakPoint(ParagraphList::iterator pit, Row & row) const; - /// sets row.witdh to the minimum space a row needs on the screen in pixel void fill(ParagraphList::iterator pit, Row & row, int workwidth) const; - - /** - * returns the minimum space a manual label needs on the - * screen in pixels - */ + /// the minimum space a manual label needs on the screen in pixels int labelFill(ParagraphList::iterator pit, Row const & row) const; - /// FIXME int labelEnd(ParagraphList::iterator pit) const; @@ -482,7 +467,7 @@ private: }; /// return the default height of a row in pixels, considering font zoom -extern int defaultRowHeight(); +int defaultRowHeight(); /// std::string expandLabel(LyXTextClass const & textclass, diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C deleted file mode 100644 index b8766d4f1a..0000000000 --- a/src/mathed/math_cursor.C +++ /dev/null @@ -1,1400 +0,0 @@ -/** - * \file math_cursor.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Alejandro Aguilar Sierra - * \author André Pönitz - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "math_cursor.h" -#include "BufferView.h" -#include "cursor.h" -#include "debug.h" -#include "dispatchresult.h" -#include "formulabase.h" -#include "funcrequest.h" -#include "lyxrc.h" -#include "math_braceinset.h" -#include "math_commentinset.h" -#include "math_charinset.h" -#include "math_factory.h" -#include "math_gridinset.h" -#include "math_macroarg.h" -#include "math_macrotemplate.h" -#include "math_mathmlstream.h" -#include "math_scriptinset.h" -#include "math_spaceinset.h" -#include "math_support.h" -#include "math_unknowninset.h" - -#include "support/limited_stack.h" -#include "support/std_sstream.h" - -#include - -//#define FILEDEBUG 1 - -using std::string; -using std::endl; -#ifndef CXX_GLOBAL_CSTD -using std::isalpha; -#endif -using std::min; -using std::swap; -using std::ostringstream; - - -// matheds own cut buffer -limited_stack theCutBuffer; - - -namespace mathcursor { - - //front ? first(cur) : last(cur); - - - /// moves cursor index one cell to the left - bool idxLeft(LCursor & cur); - /// moves cursor index one cell to the right - bool idxRight(LCursor & cur); - /// moves cursor to end of last cell of current line - bool idxLineLast(LCursor & cur); - /// moves position somehow up or down - bool goUpDown(LCursor & cur, bool up); - /// moves position closest to (x, y) in given box - bool bruteFind(LCursor & cur, - int x, int y, int xlow, int xhigh, int ylow, int yhigh); - /// moves position closest to (x, y) in current cell - void bruteFind2(LCursor & cur, int x, int y); - /// are we in a nucleus of a script inset? - bool inNucleus(LCursor & cur); - - /// erase the selected part and re-sets the cursor - void eraseSelection(LCursor & cur); - - /// the name of the macro we are currently inputting - string macroName(LCursor & cur); - /// where in the curent cell does the macro name start? - difference_type macroNamePos(LCursor & cur); - /// can we enter the inset? - bool openable(MathAtom const &, bool selection); - - /// pointer to enclsing LyX inset - InsetFormulaBase * formula_; - - -void push(LCursor & cur, MathAtom & t) -{ - cur.push(t.nucleus()); -} - - -void pushLeft(LCursor & cur, MathAtom & t) -{ - //lyxerr << "Entering atom " << t << " left" << endl; - push(cur, t); - t->idxFirst(cur); -} - - -void pushRight(LCursor & cur, MathAtom & t) -{ - //lyxerr << "Entering atom " << t << " right" << endl; - cur.posLeft(); - push(cur, t); - t->idxLast(cur); -} - - -bool popLeft(LCursor & cur) -{ - //lyxerr << "Leaving atom to the left" << endl; - if (cur.depth() <= 1) { - if (cur.depth() == 1) - cur.inset()->asMathInset()->notifyCursorLeaves(cur.idx()); - return false; - } - cur.inset()->asMathInset()->notifyCursorLeaves(cur.idx()); - cur.pop(); - return true; -} - - -bool popRight(LCursor & cur) -{ - //lyxerr << "Leaving atom "; bv.inset->asMathInset()->write(cerr, false); cerr << " right" << endl; - if (cur.depth() <= 1) { - if (cur.depth() == 1) - cur.inset()->asMathInset()->notifyCursorLeaves(cur.idx()); - return false; - } - cur.inset()->asMathInset()->notifyCursorLeaves(cur.idx()); - cur.pop(); - cur.posRight(); - return true; -} - - - -#if FILEDEBUG - void dump(char const * what) - { - lyxerr << "MC: " << what << endl; - lyxerr << " Cursor: " << cur.depth() << endl; - for (unsigned i = 0; i < cur.depth(); ++i) - lyxerr << " i: " << i << ' ' << Cursor_[i] << endl; - lyxerr << " Anchor: " << Anchor_.size() << endl; - for (unsigned i = 0; i < Anchor_.size(); ++i) - lyxerr << " i: " << i << ' ' << Anchor_[i] << endl; - lyxerr << " sel: " << cur.selection() << endl; - } -#else - void dump(char const *) {} -#endif - - -bool isInside(MathInset const *) -{ -#warning FIXME -/* - for (unsigned i = 0; i < cur.depth(); ++i) - if (Cursor_[i].asMathInset() == p) - return true; -*/ - return false; -} - - -bool openable(MathAtom const & t, bool sel) -{ - if (!t->isActive()) - return false; - - if (t->lock()) - return false; - -#warning FIXME -#if 0 - if (sel) { - // we can't move into anything new during selection - if (cur.depth() == Anchor_.size()) - return false; - if (t.nucleus() != Anchor_[cur.depth()].asMathInset()) - return false; - } -#else - if (sel) - return false; -#endif - - return true; -} - - -bool inNucleus(LCursor & cur) -{ - return cur.inset()->asMathInset()->asScriptInset() && cur.idx() == 2; -} - - -bool left(LCursor & cur, bool sel) -{ - dump("Left 1"); - cur.autocorrect() = false; - cur.x_target(-1); // "no target" - if (inMacroMode(cur)) { - macroModeClose(cur); - return true; - } - selHandle(cur, sel); - - if (cur.pos() != 0 && openable(cur.prevAtom(), sel)) { - pushRight(cur, cur.prevAtom()); - return true; - } - - return cur.posLeft() || idxLeft(cur) || popLeft(cur) || cur.selection(); -} - - -bool right(LCursor & cur, bool sel) -{ - dump("Right 1"); - cur.autocorrect() = false; - cur.x_target(-1); // "no target" - if (inMacroMode(cur)) { - macroModeClose(cur); - return true; - } - selHandle(cur, sel); - - if (cur.pos() != cur.lastpos() && openable(cur.nextAtom(), sel)) { - pushLeft(cur, cur.nextAtom()); - return true; - } - - return cur.posRight() || idxRight(cur) || popRight(cur) || cur.selection(); -} - - -bool positionable(CursorBase const & cursor, CursorBase const & anchor) -{ - // avoid deeper nested insets when selecting - if (cursor.size() > anchor.size()) - return false; - - // anchor might be deeper, should have same path then - for (CursorBase::size_type i = 0; i < cursor.size(); ++i) - if (cursor[i].asMathInset() != anchor[i].asMathInset()) - return false; - - // position should be ok. - return true; -} - - -void setScreenPos(LCursor & cur, int x, int y) -{ - dump("setScreenPos 1"); - bool res = bruteFind(cur, x, y, - formula()->xlow(), formula()->xhigh(), - formula()->ylow(), formula()->yhigh()); - if (!res) { - // this can happen on creation of "math-display" - dump("setScreenPos 1.5"); - cur.idx() = 0; - cur.pos() = 0; - } - cur.x_target(-1); // "no target" - dump("setScreenPos 2"); -} - - - -bool home(LCursor & cur, bool sel) -{ - dump("home 1"); - cur.autocorrect() = false; - selHandle(cur, sel); - macroModeClose(cur); - if (!cur.inset()->asMathInset()->idxHome(cur)) - return popLeft(cur); - dump("home 2"); - cur.x_target(-1); // "no target" - return true; -} - - -bool end(LCursor & cur, bool sel) -{ - dump("end 1"); - cur.autocorrect() = false; - selHandle(cur, sel); - macroModeClose(cur); - if (!cur.inset()->asMathInset()->idxEnd(cur)) - return popRight(cur); - dump("end 2"); - cur.x_target(-1); // "no target" - return true; -} - - -void plainErase(LCursor & cur) -{ - cur.cell().erase(cur.pos()); -} - - -void markInsert(LCursor & cur) -{ - //lyxerr << "inserting mark" << endl; - cur.cell().insert(cur.pos(), MathAtom(new MathCharInset(0))); -} - - -void markErase(LCursor & cur) -{ - //lyxerr << "deleting mark" << endl; - cur.cell().erase(cur.pos()); -} - - -void plainInsert(LCursor & cur, MathAtom const & t) -{ - dump("plainInsert"); - cur.cell().insert(cur.pos(), t); - ++cur.pos(); -} - - -void insert2(LCursor & cur, string const & str) -{ - MathArray ar; - asArray(str, ar); - insert(cur, ar); -} - - -void insert(LCursor & cur, string const & str) -{ - //lyxerr << "inserting '" << str << "'" << endl; - selClearOrDel(cur); - for (string::const_iterator it = str.begin(); it != str.end(); ++it) - plainInsert(cur, MathAtom(new MathCharInset(*it))); -} - - -void insert(LCursor & cur, char c) -{ - //lyxerr << "inserting '" << c << "'" << endl; - selClearOrDel(cur); - plainInsert(cur, MathAtom(new MathCharInset(c))); -} - - -void insert(LCursor & cur, MathAtom const & t) -{ - macroModeClose(cur); - selClearOrDel(cur); - plainInsert(cur, t); -} - - -void niceInsert(LCursor & cur, string const & t) -{ - MathArray ar; - asArray(t, ar); - if (ar.size() == 1) - niceInsert(cur, ar[0]); - else - insert(cur, ar); -} - - -void niceInsert(LCursor & cur, MathAtom const & t) -{ - macroModeClose(cur); - string safe = grabAndEraseSelection(cur); - plainInsert(cur, t); - // enter the new inset and move the contents of the selection if possible - if (t->isActive()) { - cur.posLeft(); - pushLeft(cur, cur.nextAtom()); - paste(cur, safe); - } -} - - -void insert(LCursor & cur, MathArray const & ar) -{ - macroModeClose(cur); - if (cur.selection()) - eraseSelection(cur); - cur.cell().insert(cur.pos(), ar); - cur.pos() += ar.size(); -} - - -void paste(LCursor & cur, string const & data) -{ - dispatch(cur, FuncRequest(LFUN_PASTE, data)); -} - - -bool backspace(LCursor & cur) -{ - cur.autocorrect() = false; - - if (cur.selection()) { - selDel(cur); - return true; - } - - if (cur.pos() == 0) { - if (cur.inset()->asMathInset()->nargs() == 1 && - cur.depth() == 1 && - cur.lastpos() == 0) - return false; - pullArg(cur); - return true; - } - - if (inMacroMode(cur)) { - MathUnknownInset * p = activeMacro(cur); - if (p->name().size() > 1) { - p->setName(p->name().substr(0, p->name().size() - 1)); - return true; - } - } - - if (cur.pos() != 0 && cur.prevAtom()->nargs() > 0) { - // let's require two backspaces for 'big stuff' and - // highlight on the first - left(cur, true); - } else { - --cur.pos(); - plainErase(cur); - } - return true; -} - - -bool erase(LCursor & cur) -{ - cur.autocorrect() = false; - if (inMacroMode(cur)) - return true; - - if (cur.selection()) { - selDel(cur); - return true; - } - - // delete empty cells if possible -#warning FIXME - //if (cur.cell().empty() && cur.inset()->idxDelete(cur.idx())) - // return true; - - // special behaviour when in last position of cell - if (cur.pos() == cur.lastpos()) { - bool one_cell = cur.inset()->asMathInset()->nargs() == 1; - if (one_cell && cur.depth() == 1 && cur.lastpos() == 0) - return false; - // remove markup - if (one_cell) - pullArg(cur); - else - cur.inset()->asMathInset()->idxGlue(cur.idx()); - return true; - } - - if (cur.pos() != cur.lastpos() && cur.nextAtom()->nargs() > 0) - right(cur, true); - else - plainErase(cur); - - return true; -} - - -bool up(LCursor & cur, bool sel) -{ - dump("up 1"); - macroModeClose(cur); - selHandle(cur, sel); -#warning look here - //CursorBase save = cur.cursor_; - if (goUpDown(cur, true)) - return true; - //cur.cursor_ = save; - cur.autocorrect() = false; - return cur.selection(); -} - - -bool down(LCursor & cur, bool sel) -{ - dump("down 1"); - macroModeClose(cur); - selHandle(cur, sel); -#warning look here - //CursorBase save = cur.cursor_; - if (goUpDown(cur, false)) - return true; - //cur.cursor_ = save; - cur.autocorrect() = false; - return cur.selection(); -} - - -void macroModeClose(LCursor & cur) -{ - if (!inMacroMode(cur)) - return; - MathUnknownInset * p = activeMacro(cur); - p->finalize(); - string s = p->name(); - --cur.pos(); - cur.cell().erase(cur.pos()); - - // do nothing if the macro name is empty - if (s == "\\") - return; - - string const name = s.substr(1); - - // prevent entering of recursive macros - if (formula()->lyxCode() == InsetOld::MATHMACRO_CODE - && formula()->getInsetName() == name) - lyxerr << "can't enter recursive macro" << endl; - - niceInsert(cur, createMathInset(name)); -} - - -string macroName(LCursor & cur) -{ - return inMacroMode(cur) ? activeMacro(cur)->name() : string(); -} - - -void selClear(LCursor & cur) -{ - cur.resetAnchor(); - cur.clearSelection(); -} - - -void selCopy(LCursor & cur) -{ - dump("selCopy"); - if (cur.selection()) { - theCutBuffer.push(grabSelection(cur)); - cur.selection() = false; - } else { - //theCutBuffer.erase(); - } -} - - -void selCut(LCursor & cur) -{ - dump("selCut"); - theCutBuffer.push(grabAndEraseSelection(cur)); -} - - -void selDel(LCursor & cur) -{ - dump("selDel"); - if (cur.selection()) { - eraseSelection(cur); - cur.selection() = false; - } -} - - -void selPaste(LCursor & cur, size_t n) -{ - dump("selPaste"); - selClearOrDel(cur); - if (n < theCutBuffer.size()) - paste(cur, theCutBuffer[n]); - //grabSelection(cur); - cur.selection() = false; -} - - -void selHandle(LCursor & cur, bool sel) -{ - if (sel == cur.selection()) - return; - //clear(); - cur.resetAnchor(); - cur.selection() = sel; -} - - -void selStart(LCursor & cur) -{ - dump("selStart 1"); - //clear(); - cur.resetAnchor(); - cur.selection() = true; - dump("selStart 2"); -} - - -void selClearOrDel(LCursor & cur) -{ - if (lyxrc.auto_region_delete) - selDel(cur); - else - cur.selection() = false; -} - - -void drawSelection(PainterInfo & pi) -{ - if (!pi.base.bv->cursor().selection()) - return; - CursorSlice i1 = pi.base.bv->cursor().selStart(); - CursorSlice i2 = pi.base.bv->cursor().selEnd(); - i1.asMathInset()->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_); -} - - -void handleNest(LCursor & cur, MathAtom const & a, int c) -{ - MathAtom at = a; - asArray(grabAndEraseSelection(cur), at.nucleus()->cell(c)); - insert(cur, at); - pushRight(cur, cur.prevAtom()); -} - - -void getScreenPos(LCursor & cur, int & x, int & y) -{ - cur.inset()->asMathInset()->getScreenPos(cur.idx(), cur.pos(), x, y); -} - - -int targetX(LCursor & cur) -{ - if (cur.x_target() != -1) - return cur.x_target(); - int x = 0; - int y = 0; - getScreenPos(cur, x, y); - return x; -} - - -InsetFormulaBase * formula() -{ - return formula_; -} - - -void adjust(LCursor & cur, pos_type from, difference_type diff) -{ - if (cur.pos() > from) - cur.pos() += diff; - if (cur.anchor().pos_ > from) - cur.anchor().pos_ += diff; - // just to be on the safe side - // theoretically unecessary - normalize(cur); -} - - -bool inMacroMode(LCursor & cur) -{ - if (!cur.pos() != 0) - return false; - MathUnknownInset const * p = cur.prevAtom()->asUnknownInset(); - return p && !p->final(); -} - - -MathUnknownInset * activeMacro(LCursor & cur) -{ - return inMacroMode(cur) ? cur.prevAtom().nucleus()->asUnknownInset() : 0; -} - - -bool inMacroArgMode(LCursor & cur) -{ - return cur.pos() > 0 && cur.prevAtom()->getChar() == '#'; -} - - -MathGridInset * enclosingGrid(LCursor & cur, idx_type & idx) -{ - for (MathInset::difference_type i = cur.depth() - 1; i >= 0; --i) { - MathInset * m = cur.cursor_[i].inset()->asMathInset(); - if (!m) - return 0; - MathGridInset * p = m->asGridInset(); - if (p) { - idx = cur.cursor_[i].idx_; - return p; - } - } - return 0; -} - - -void popToHere(LCursor & cur, MathInset const * p) -{ - while (cur.depth() && cur.inset()->asMathInset() != p) - cur.pop(); -} - - -void popToEnclosingGrid(LCursor & cur) -{ - while (cur.depth() && !cur.inset()->asMathInset()->asGridInset()) - cur.pop(); -} - - -void popToEnclosingHull(LCursor & cur) -{ - while (cur.depth() && !cur.inset()->asMathInset()->asGridInset()) - cur.pop(); -} - - -void pullArg(LCursor & cur) -{ - dump("pullarg"); - MathArray ar = cur.cell(); - if (popLeft(cur)) { - plainErase(cur); - cur.cell().insert(cur.pos(), ar); - cur.resetAnchor(); - } else { - formula()->mutateToText(); - } -} - - -void touch() -{ -#warning -#if 0 - CursorBase::const_iterator it = Cursor_.begin(); - CursorBase::const_iterator et = Cursor_.end(); - for ( ; it != et; ++it) - it->cell().touch(); -#endif -} - - -void normalize(LCursor & cur) -{ -#warning FIXME -#if 0 - if (cur.idx() >= cur.nargs()) { - lyxerr << "this should not really happen - 1: " - << cur.idx() << ' ' << cur.nargs() - << " in: " << cur.inset() << endl; - dump("error 2"); - } - cur.idx() = min(cur.idx(), cur.nargs() - 1); - - if (cur.pos() > cur.lastpos()) { - lyxerr << "this should not really happen - 2: " - << cur.pos() << ' ' << cur.lastpos() << " in idx: " << cur.idx() - << " in atom: '"; - WriteStream wi(lyxerr, false, true); - cur.inset()->asMathInset()->write(wi); - lyxerr << endl; - dump("error 4"); - } - cur.pos() = min(cur.pos(), cur.lastpos()); -#endif -} - - -void idxNext(LCursor & cur) -{ - cur.inset()->asMathInset()->idxNext(cur); -} - - -void idxPrev(LCursor & cur) -{ - cur.inset()->asMathInset()->idxPrev(cur); -} - - -char valign(LCursor & cur) -{ - idx_type idx; - MathGridInset * p = enclosingGrid(cur, idx); - return p ? p->valign() : '\0'; -} - - -char halign(LCursor & cur) -{ - idx_type idx; - MathGridInset * p = enclosingGrid(cur, idx); - return p ? p->halign(idx % p->ncols()) : '\0'; -} - - -bool goUpDown(LCursor & cur, bool up) -{ - // Be warned: The 'logic' implemented in this function is highly fragile. - // A distance of one pixel or a '<' vs '<=' _really_ matters. - // So fiddle around with it only if you know what you are doing! - int xo = 0; - int yo = 0; - getScreenPos(cur, xo, yo); - - // check if we had something else in mind, if not, this is the future goal - if (cur.x_target() == -1) - cur.x_target(xo); - else - xo = cur.x_target(); - - // try neigbouring script insets - if (!cur.selection()) { - // try left - if (cur.pos() != 0) { - MathScriptInset const * p = cur.prevAtom()->asScriptInset(); - if (p && p->has(up)) { - --cur.pos(); - push(cur, cur.nextAtom()); - cur.idx() = up; // the superscript has index 1 - cur.pos() = cur.lastpos(); - //lyxerr << "updown: handled by scriptinset to the left" << endl; - return true; - } - } - - // try right - if (cur.pos() != cur.lastpos()) { - MathScriptInset const * p = cur.nextAtom()->asScriptInset(); - if (p && p->has(up)) { - push(cur, cur.nextAtom()); - cur.idx() = up; - cur.pos() = 0; - //lyxerr << "updown: handled by scriptinset to the right" << endl; - return true; - } - } - } - - // try current cell for e.g. text insets - if (cur.inset()->asMathInset()->idxUpDown2(cur, up, cur.x_target())) - return true; - - //xarray().boundingBox(xlow, xhigh, ylow, yhigh); - //if (up) - // yhigh = yo - 4; - //else - // ylow = yo + 4; - //if (bruteFind(xo, yo, xlow, xhigh, ylow, yhigh)) { - // lyxerr << "updown: handled by brute find in the same cell" << endl; - // return true; - //} - - // try to find an inset that knows better then we - while (1) { - //lyxerr << "updown: We are in " << inset() << " idx: " << idx() << endl; - // ask inset first - if (cur.inset()->asMathInset()->idxUpDown(cur, up, cur.x_target())) { - // try to find best position within this inset - if (!cur.selection()) - bruteFind2(cur, xo, yo); - return true; - } - - // no such inset found, just take something "above" - //lyxerr << "updown: handled by strange case" << endl; - if (!popLeft(cur)) - return - bruteFind(cur, xo, yo, - formula()->xlow(), - formula()->xhigh(), - up ? formula()->ylow() : yo + 4, - up ? yo - 4 : formula()->yhigh() - ); - - // any improvement so far? - int xnew, ynew; - getScreenPos(cur, xnew, ynew); - if (up ? ynew < yo : ynew > yo) - return true; - } -} - - -bool bruteFind - (LCursor & cur, int x, int y, int xlow, int xhigh, int ylow, int yhigh) -{ - CursorBase best_cursor; - double best_dist = 1e10; - - CursorBase it = ibegin(formula()->par().nucleus()); - CursorBase et = iend(formula()->par().nucleus()); - while (1) { - // avoid invalid nesting when selecting - if (!cur.selection() || positionable(it, cur.anchor_)) { - int xo, yo; - it.back().getScreenPos(xo, yo); - if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) { - double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); - //lyxerr << "x: " << x << " y: " << y << " d: " << endl; - // '<=' in order to take the last possible position - // this is important for clicking behind \sum in e.g. '\sum_i a' - if (d <= best_dist) { - best_dist = d; - best_cursor = it; - } - } - } - - if (it == et) - break; - increment(it); - } - - if (best_dist < 1e10) - cur.cursor_ = best_cursor; - return best_dist < 1e10; -} - - -void bruteFind2(LCursor & cur, int x, int y) -{ - double best_dist = 1e10; - - CursorBase it = cur.cursor_; - it.back().pos(0); - CursorBase et = cur.cursor_; - int n = et.back().asMathInset()->cell(et.back().idx_).size(); - et.back().pos(n); - for (int i = 0; ; ++i) { - int xo, yo; - it.back().getScreenPos(xo, yo); - double d = (x - xo) * (x - xo) + (y - yo) * (y - yo); - // '<=' in order to take the last possible position - // this is important for clicking behind \sum in e.g. '\sum_i a' - lyxerr << "i: " << i << " d: " << d << " best: " << best_dist << endl; - if (d <= best_dist) { - best_dist = d; - cur.cursor_ = it; - } - if (it == et) - break; - increment(it); - } -} - - -bool idxLineLast(LCursor & cur) -{ - cur.idx() -= cur.idx() % cur.ncols(); - cur.idx() += cur.ncols() - 1; - cur.pos() = cur.lastpos(); - return true; -} - - -bool idxLeft(LCursor & cur) -{ - return cur.inset()->asMathInset()->idxLeft(cur); -} - - -bool idxRight(LCursor & cur) -{ - return cur.inset()->asMathInset()->idxRight(cur); -} - - -bool script(LCursor & cur, bool up) -{ - // Hack to get \\^ and \\_ working - if (inMacroMode(cur) && macroName(cur) == "\\") { - if (up) - niceInsert(cur, createMathInset("mathcircumflex")); - else - interpret(cur, '_'); - return true; - } - - macroModeClose(cur); - string safe = grabAndEraseSelection(cur); - if (inNucleus(cur)) { - // we are in a nucleus of a script inset, move to _our_ script - cur.inset()->asMathInset()->asScriptInset()->ensure(up); - cur.idx() = up; - cur.pos() = 0; - } else if (cur.pos() != 0 && cur.prevAtom()->asScriptInset()) { - cur.prevAtom().nucleus()->asScriptInset()->ensure(up); - pushRight(cur, cur.prevAtom()); - cur.idx() = up; - cur.pos() = cur.lastpos(); - } else if (cur.pos() != 0) { - --cur.pos(); - cur.cell()[cur.pos()] - = MathAtom(new MathScriptInset(cur.nextAtom(), up)); - pushLeft(cur, cur.nextAtom()); - cur.idx() = up; - cur.pos() = 0; - } else { - plainInsert(cur, MathAtom(new MathScriptInset(up))); - cur.prevAtom().nucleus()->asScriptInset()->ensure(up); - pushRight(cur, cur.prevAtom()); - cur.idx() = up; - cur.pos() = 0; - } - paste(cur, safe); - dump("1"); - return true; -} - - -bool interpret(LCursor & cur, char c) -{ - //lyxerr << "interpret 2: '" << c << "'" << endl; - cur.x_target(-1); // "no target" - if (inMacroArgMode(cur)) { - --cur.pos(); - plainErase(cur); - int n = c - '0'; - MathMacroTemplate const * p = formula()->par()->asMacroTemplate(); - if (p && 1 <= n && n <= p->numargs()) - insert(cur, MathAtom(new MathMacroArgument(c - '0'))); - else { - insert(cur, createMathInset("#")); - interpret(cur, c); // try again - } - return true; - } - - // handle macroMode - if (inMacroMode(cur)) { - string name = macroName(cur); - //lyxerr << "interpret name: '" << name << "'" << endl; - - if (isalpha(c)) { - activeMacro(cur)->setName(activeMacro(cur)->name() + c); - return true; - } - - // handle 'special char' macros - if (name == "\\") { - // remove the '\\' - backspace(cur); - if (c == '\\') { - if (currentMode(cur) == MathInset::TEXT_MODE) - niceInsert(cur, createMathInset("textbackslash")); - else - niceInsert(cur, createMathInset("backslash")); - } else if (c == '{') { - niceInsert(cur, MathAtom(new MathBraceInset)); - } else { - niceInsert(cur, createMathInset(string(1, c))); - } - return true; - } - - // leave macro mode and try again if necessary - macroModeClose(cur); - if (c == '{') - niceInsert(cur, MathAtom(new MathBraceInset)); - else if (c != ' ') - interpret(cur, c); - return true; - } - - // This is annoying as one has to press far too often. - // Disable it. - - if (0) { - // leave autocorrect mode if necessary - if (cur.autocorrect() && c == ' ') { - cur.autocorrect() = false; - return true; - } - } - - // just clear selection on pressing the space bar - if (cur.selection() && c == ' ') { - cur.selection() = false; - return true; - } - - selClearOrDel(cur); - - if (c == '\\') { - //lyxerr << "starting with macro" << endl; - insert(cur, MathAtom(new MathUnknownInset("\\", false))); - return true; - } - - if (c == '\n') { - if (currentMode(cur) == MathInset::TEXT_MODE) - insert(cur, c); - return true; - } - - if (c == ' ') { - if (currentMode(cur) == MathInset::TEXT_MODE) { - // insert spaces in text mode, - // but suppress direct insertion of two spaces in a row - // the still allows typing 'a' and deleting the 'a', but - // it is better than nothing... - if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ') - insert(cur, c); - return true; - } - if (cur.pos() != 0 && cur.prevAtom()->asSpaceInset()) { - cur.prevAtom().nucleus()->asSpaceInset()->incSpace(); - return true; - } - if (popRight(cur)) - return true; - // if are at the very end, leave the formula - return cur.pos() != cur.lastpos(); - } - - if (c == '_') { - script(cur, false); - return true; - } - - if (c == '^') { - script(cur, true); - return true; - } - - if (c == '{' || c == '}' || c == '#' || c == '&' || c == '$') { - niceInsert(cur, createMathInset(string(1, c))); - return true; - } - - if (c == '%') { - niceInsert(cur, MathAtom(new MathCommentInset)); - return true; - } - - // try auto-correction - //if (cur.autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c)) - // return true; - - // no special circumstances, so insert the character without any fuss - insert(cur, c); - cur.autocorrect() = true; - return true; -} - - -void setSelection(LCursor & cur, CursorBase const & where, size_t n) -{ - cur.selection() = true; - cur.cursor_ = where; - cur.anchor_ = where; - cur.pos() += n; -} - - -void insetToggle(LCursor & cur) -{ - if (cur.pos() != cur.lastpos()) { - // toggle previous inset ... - cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock()); - } else if (popLeft(cur) && cur.pos() != cur.lastpos()) { - // ... or enclosing inset if we are in the last inset position - cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock()); - cur.posRight(); - } -} - - -namespace { - -void region(CursorSlice const & i1, CursorSlice const & i2, - MathInset::row_type & r1, MathInset::row_type & r2, - MathInset::col_type & c1, MathInset::col_type & c2) -{ - MathInset * p = i1.asMathInset(); - c1 = p->col(i1.idx_); - c2 = p->col(i2.idx_); - if (c1 > c2) - swap(c1, c2); - r1 = p->row(i1.idx_); - r2 = p->row(i2.idx_); - if (r1 > r2) - swap(r1, r2); -} - -} - - -string grabSelection(LCursor & cur) -{ - if (!cur.selection()) - return string(); - - CursorSlice i1 = cur.selStart(); - CursorSlice i2 = cur.selEnd(); - - if (i1.idx_ == i2.idx_) { - MathArray::const_iterator it = i1.cell().begin(); - return asString(MathArray(it + i1.pos_, it + i2.pos_)); - } - - row_type r1, r2; - col_type c1, c2; - region(i1, i2, r1, r2, c1, c2); - - string data; - for (row_type row = r1; row <= r2; ++row) { - if (row > r1) - data += "\\\\"; - for (col_type col = c1; col <= c2; ++col) { - if (col > c1) - data += '&'; - data += asString(i1.asMathInset()->cell(i1.asMathInset()->index(row, col))); - } - } - return data; -} - - -void eraseSelection(LCursor & cur) -{ - CursorSlice i1 = cur.selStart(); - CursorSlice i2 = cur.selEnd(); - if (i1.idx_ == i2.idx_) - i1.cell().erase(i1.pos_, i2.pos_); - else { - MathInset * p = i1.asMathInset(); - row_type r1, r2; - col_type c1, c2; - region(i1, i2, r1, r2, c1, c2); - for (row_type row = r1; row <= r2; ++row) - for (col_type col = c1; col <= c2; ++col) - p->cell(p->index(row, col)).clear(); - } - cur.current() = i1; -} - - -string grabAndEraseSelection(LCursor & cur) -{ - if (!cur.selection()) - return string(); - string res = grabSelection(cur); - eraseSelection(cur); - cur.selection() = false; - return res; -} - - -CursorSlice normalAnchor(LCursor & cur) -{ -#warning FIXME -#if 0 - if (Anchor_.size() < cur.depth()) { - cur.resetAnchor(); - lyxerr << "unusual Anchor size" << endl; - } - //lyx::BOOST_ASSERT(Anchor_.size() >= cursor.cur.depth()); - // use Anchor on the same level as Cursor - CursorSlice normal = Anchor_[cur.depth() - 1]; - if (cur.depth() < Anchor_.size() && !(normal < cursor())) { - // anchor is behind cursor -> move anchor behind the inset - ++normal.pos_; - } - return normal; -#else - return cur.anchor_.back(); -#endif -} - - -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 = cur.cursor_.back(); - int x = 0; - int y = 0; - getScreenPos(x, y); - if (x < cmd.x && cur.hasPrevAtom()) { - DispatchResult const res = - cur.prevAtom().nucleus()->dispatch(cur, cmd); - if (res.dispatched()) - return res; - } - if (x > cmd.x && cur.hasNextAtom()) { - DispatchResult const res = - cur.nextAtom().nucleus()->dispatch(cur, cmd); - if (res.dispatched()) - return res; - } - } - default: - break; - } - - for (int i = cur.depth() - 1; i >= 0; --i) { - CursorBase tmp = cur->cursor_; - CursorSlice & pos = tmp.back() - DispatchResult const res = pos.asMathInset()->dispatch(cur, cmd); - if (res.dispatched()) { - if (res.val() == FINISHED) { - if (i + 1 < Cursor_.size()) - Cursor_.erase(Cursor_.begin() + i + 1, Cursor_.end()); - selClear(); - } - return res; - } - } -*/ - return DispatchResult(false); -} - - -MathInset::mode_type currentMode(LCursor &) -{ -#if 0 - for (int i = Cursor_.size() - 1; i >= 0; --i) { - MathInset::mode_type res = Cursor_[i].asMathInset()->currentMode(); - if (res != MathInset::UNDECIDED_MODE) - return res; - } -#endif - return MathInset::UNDECIDED_MODE; -} - - -void handleFont(LCursor & cur, string const & font) -{ - string safe; - if (cur.selection()) { - macroModeClose(cur); - safe = grabAndEraseSelection(cur); - } - - if (cur.lastpos() != 0) { - // something left in the cell - if (cur.pos() == 0) { - // cursor in first position - popLeft(cur); - } else if (cur.pos() == cur.lastpos()) { - // cursor in last position - popRight(cur); - } else { - // cursor in between. split cell - MathArray::iterator bt = cur.cell().begin(); - MathAtom at = createMathInset(font); - at.nucleus()->cell(0) = MathArray(bt, bt + cur.pos()); - cur.cell().erase(bt, bt + cur.pos()); - popLeft(cur); - plainInsert(cur, at); - } - } else { - // nothing left in the cell - pullArg(cur); - plainErase(cur); - } - insert(cur, safe); -} - -} - - -void releaseMathCursor(LCursor & cur) -{ - if (inMathed()) { - mathcursor::formula_->insetUnlock(cur.bv()); - mathcursor::formula_ = 0; - } -} - - -bool inMathed() -{ - return mathcursor::formula_; -} diff --git a/src/mathed/math_cursor.h b/src/mathed/math_cursor.h deleted file mode 100644 index 32a8e52108..0000000000 --- a/src/mathed/math_cursor.h +++ /dev/null @@ -1,209 +0,0 @@ -// -*- C++ -*- -/** - * \file math_cursor.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Alejandro Aguilar Sierra - * \author André Pönitz - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef MATH_CURSOR -#define MATH_CURSOR - -#include "cursor.h" -#include "math_inset.h" -#include "math_data.h" - -#include - -class InsetFormulaBase; -class BufferView; -class PainterInfo; -class MathUnknownInset; - -/** - -[Have a look at math_inset.h first] - -The MathCursor is different from the kind of cursor used in the Outer -World. It contains a stack of CursorSlice, each of which is made -up of a inset pointer, an index and a position offset, marking a path from -this formula's MathHullInset to the current position. - -*/ - - -namespace mathcursor { - /// short of anything else reasonable - typedef size_t size_type; - /// type for column numbers - typedef ptrdiff_t difference_type; - /// type for cursor positions within a cell - typedef lyx::pos_type pos_type; - /// type for cell indices - typedef size_t idx_type; - /// type for row numbers - typedef size_t row_type; - /// type for column numbers - typedef size_t col_type; - - /// - void insert(LCursor & cur, MathAtom const &); - /// - void insert(LCursor & cur, MathArray const &); - /// - void insert2(LCursor & cur, std::string const &); - /// - void paste(LCursor & cur, std::string const & data); - /// return false for empty math insets - bool erase(LCursor & cur); - /// return false for empty math insets - bool backspace(LCursor & cur); - /// called for LFUN_HOME etc - bool home(LCursor & cur, bool sel = false); - /// called for LFUN_END etc - bool end(LCursor & cur, bool sel = false); - /// called for LFUN_RIGHT and LFUN_RIGHTSEL - bool right(LCursor & cur, bool sel = false); - /// called for LFUN_LEFT etc - bool left(LCursor & cur, bool sel = false); - /// called for LFUN_UP etc - bool up(LCursor & cur, bool sel = false); - /// called for LFUN_DOWN etc - bool down(LCursor & cur, bool sel = false); - /// move to next cell in current inset - void idxNext(LCursor & bv); - /// move to previous cell in current inset - void idxPrev(LCursor & bv); - /// - void plainErase(LCursor & cur); - /// - void plainInsert(LCursor & cur, MathAtom const & at); - /// - void niceInsert(LCursor & cur, MathAtom const & at); - /// - void niceInsert(LCursor & cur, std::string const & str); - - /// in pixels from top of screen - void setScreenPos(LCursor & cur, int x, int y); - /// in pixels from top of screen - void getScreenPos(LCursor & cur, int & x, int & y); - /// in pixels from left of screen - int targetX(LCursor & cur); - /// return the next enclosing grid inset and the cursor's index in it - MathGridInset * enclosingGrid(LCursor & cur, idx_type & idx); - /// go up to enclosing grid - void popToEnclosingGrid(LCursor & cur); - /// go up to the hull inset - void popToEnclosingHull(LCursor & cur); - /// go up to the hull inset - void popToHere(LCursor & cur, MathInset const * p); - /// adjust anchor position after deletions/insertions - void adjust(LCursor & cur, pos_type from, difference_type diff); - /// - InsetFormulaBase * formula(); - /// current offset in the current cell - /// - bool script(LCursor & cur, bool); - /// - bool interpret(LCursor & cur, char); - /// interpret name a name of a macro - void macroModeClose(LCursor & cur); - /// are we currently typing the name of a macro? - bool inMacroMode(LCursor & cur); - /// get access to the macro we are currently typing - MathUnknownInset * activeMacro(LCursor & cur); - /// are we currently typing '#1' or '#2' or...? - bool inMacroArgMode(LCursor & cur); - /// are we in math mode (1), text mode (-1) or unsure? - MathInset::mode_type currentMode(LCursor & cur); - - // Local selection methods - /// - void selCopy(LCursor & cur); - /// - void selCut(LCursor & cur); - /// - void selDel(LCursor & cur); - /// pastes n-th element of cut buffer - void selPaste(LCursor & cur, size_t n); - /// - void selHandle(LCursor & cur, bool); - /// - void selStart(LCursor & cur); - /// - void selClear(LCursor & cur); - /// clears or deletes selection depending on lyxrc setting - void selClearOrDel(LCursor & cur); - /// draws light-blue selection background - void drawSelection(PainterInfo & pi); - /// replace selected stuff with at, placing the former - // selection in given cell of atom - void handleNest(LCursor & cur, MathAtom const & at, int cell = 0); - /// remove this as soon as LyXFunc::getStatus is "localized" - inline std::string getLastCode() { return "mathnormal"; } - /// - bool isInside(MathInset const *); - /// - char valign(LCursor & cur); - /// - char halign(LCursor & cur); - - /// make sure cursor position is valid - void normalize(LCursor & cur); - /// mark current cursor trace for redraw - void touch(); - - /// enter a MathInset - void push(LCursor & cur, MathAtom & par); - /// enter a MathInset from the front - void pushLeft(LCursor & cur, MathAtom & par); - /// enter a MathInset from the back - void pushRight(LCursor & cur, MathAtom & par); - /// leave current MathInset to the left - bool popLeft(LCursor & cur); - /// leave current MathInset to the left - bool popRight(LCursor & cur); - - /// returns the normalized anchor of the selection - CursorSlice normalAnchor(LCursor & cur); - - /// dump selection information for debugging - void seldump(char const * str); - /// dump selection information for debugging - void dump(char const * str); - /// moves on - void setSelection(LCursor & cur, CursorBase const & where, size_type n); - /// grab selection marked by anchor and current cursor - std::string grabSelection(LCursor & cur); - /// guess what - std::string grabAndEraseSelection(LCursor & cur); - /// - void insert(LCursor & cur, char c); - /// - void insert(LCursor & cur, std::string const & str); - /// lock/unlock inset - void insetToggle(LCursor & cur); - - /// hack for reveal codes - void markInsert(LCursor & cur); - void markErase(LCursor & cur); - /// injects content of a cell into parent - void pullArg(LCursor & cur); - /// split font inset etc - void handleFont(LCursor & cur, std::string const & font); - /// - DispatchResult dispatch(LCursor & cur, FuncRequest const & cmd); - - /// pointer to enclsing LyX inset - extern InsetFormulaBase * formula_; -} - -void releaseMathCursor(LCursor & cur); - -bool inMathed(); - -#endif diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index 20cd11011c..1de21ee856 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -1077,12 +1077,12 @@ MathGridInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) return DispatchResult(true, FINISHED); case LFUN_CELL_SPLIT: - //recordUndo(cur, Undo::ATOMIC); + ////recordUndo(cur, Undo::ATOMIC); splitCell(cur); return DispatchResult(true, FINISHED); case LFUN_BREAKLINE: { - //recordUndo(cur, Undo::INSERT); + ////recordUndo(cur, Undo::INSERT); row_type const r = cur.row(); addRow(r); diff --git a/src/mathed/math_hullinset.C b/src/mathed/math_hullinset.C index 65a5075d87..0d3dadbccd 100644 --- a/src/mathed/math_hullinset.C +++ b/src/mathed/math_hullinset.C @@ -803,7 +803,7 @@ MathHullInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_MATH_NUMBER: //lyxerr << "toggling all numbers" << endl; if (display()) { - //recordUndo(cur, Undo::INSERT); + ////recordUndo(cur, Undo::INSERT); bool old = numberedType(); if (type_ == "multline") numbered(nrows() - 1, !old); @@ -817,7 +817,7 @@ MathHullInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_MATH_NONUMBER: if (display()) { row_type r = (type_ == "multline") ? nrows() - 1 : cur.row(); - //recordUndo(cur, Undo::INSERT); + ////recordUndo(cur, Undo::INSERT); bool old = numbered(r); //cur.bv()->owner()->message(old ? _("No number") : _("Number")); numbered(r, !old); @@ -969,7 +969,7 @@ void MathHullInset::handleFont { // 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); @@ -982,7 +982,7 @@ void MathHullInset::handleFont void MathHullInset::handleFont2(LCursor & cur, string const & arg) { - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); LyXFont font; bool b; bv_funcs::string2font(arg, font, b); diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index 48825c1569..d99f9fa30e 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -318,7 +318,7 @@ void MathNestInset::handleFont { // 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); @@ -331,7 +331,7 @@ void MathNestInset::handleFont 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); @@ -370,7 +370,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) is >> n; if (was_macro) cur.macroModeClose(); - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.selPaste(n); return DispatchResult(true, true); } @@ -462,13 +462,13 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_DELETE_WORD_BACKWARD: case LFUN_BACKSPACE: - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.backspace(); return DispatchResult(true, true); case LFUN_DELETE_WORD_FORWARD: case LFUN_DELETE: - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.erase(); return DispatchResult(true, FINISHED); @@ -484,7 +484,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_SELFINSERT: if (!cmd.argument.empty()) { - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); if (cmd.argument.size() == 1) { if (cur.interpret(cmd.argument[0])) return DispatchResult(true, true); @@ -535,7 +535,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) switch (cmd.action) { case LFUN_MATH_LIMITS: - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.dispatch(cmd); break; #endif @@ -555,7 +555,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) } case LFUN_CUT: - recordUndo(cur, Undo::DELETE); + //recordUndo(cur, Undo::DELETE); cur.selCut(); return DispatchResult(true, true); @@ -570,7 +570,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) if (cmd.argument.empty()) { // do superscript if LyX handles // deadkeys - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.script(true); } return DispatchResult(true, true); @@ -634,7 +634,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) cur.selClearOrDel(); cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv()))); cur.posLeft(); - cur.pushLeft(cur.nextAtom().nucleus()); + cur.pushLeft(cur.nextInset()); #else if (cur.currentMode() == InsetBase::TEXT_MODE) cur.niceInsert(MathAtom(new MathHullInset("simple"))); @@ -647,14 +647,14 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_MATH_SIZE: #if 0 if (!arg.empty()) { - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.setSize(arg); } #endif return DispatchResult(true, true); case LFUN_INSERT_MATRIX: { - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); unsigned int m = 1; unsigned int n = 1; string v_align; @@ -680,14 +680,14 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) ls = '('; if (rs.empty()) rs = ')'; - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.handleNest(MathAtom(new MathDelimInset(ls, rs))); return DispatchResult(true, true); } case LFUN_SPACE_INSERT: case LFUN_MATH_SPACE: - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.insert(MathAtom(new MathSpaceInset(","))); return DispatchResult(true, true); @@ -698,7 +698,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_INSET_ERT: // interpret this as if a backslash was typed - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.interpret('\\'); return DispatchResult(true, true); @@ -707,7 +707,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) case LFUN_BREAKPARAGRAPHKEEPLAYOUT: case LFUN_BREAKPARAGRAPH_SKIP: cmd.argument = "\n"; - recordUndo(cur, Undo::ATOMIC); + //recordUndo(cur, Undo::ATOMIC); cur.niceInsert(argument); return DispatchResult(true, true); #endif @@ -716,7 +716,7 @@ MathNestInset::priv_dispatch(LCursor & cur, FuncRequest const & cmd) // 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); return DispatchResult(true, true); diff --git a/src/paragraph.C b/src/paragraph.C index ce19157b87..9f0d646d8e 100644 --- a/src/paragraph.C +++ b/src/paragraph.C @@ -1833,6 +1833,18 @@ RowList::iterator Paragraph::getRow(pos_type pos) } +size_t Paragraph::row(pos_type pos) const +{ + RowList::const_iterator rit = rows.end(); + RowList::const_iterator const begin = rows.begin(); + + for (--rit; rit != begin && rit->pos() > pos; --rit) + ; + + return rit - begin; +} + + unsigned char Paragraph::transformChar(unsigned char c, pos_type pos) const { if (!Encodings::is_arabic(c)) diff --git a/src/paragraph.h b/src/paragraph.h index b604b37da3..614da77c99 100644 --- a/src/paragraph.h +++ b/src/paragraph.h @@ -329,6 +329,8 @@ public: /// RowList::iterator getRow(lyx::pos_type pos); + /// + size_t row(lyx::pos_type pos) const; /// InsetList insetlist; diff --git a/src/text.C b/src/text.C index 78874de8a2..5f53767f14 100644 --- a/src/text.C +++ b/src/text.C @@ -845,7 +845,7 @@ void LyXText::redoParagraph() // same Paragraph one to the right and make a rebreak void LyXText::insertChar(char c) { - recordUndo(Undo::INSERT, this, cursor().par(), cursor().par()); + recordUndo(bv()->cursor(), Undo::INSERT); // When the free-spacing option is set for the current layout, // disable the double-space checking @@ -1132,7 +1132,7 @@ void LyXText::acceptChange() if (cur.selBegin().par() == cur.par()) { CursorSlice const & startc = cur.selBegin(); CursorSlice const & endc = cur.selEnd(); - recordUndo(Undo::INSERT, this, startc.par()); + recordUndo(cur, Undo::INSERT, cur.anchor().par()); getPar(startc)->acceptChange(startc.pos(), endc.pos()); finishUndo(); cur.clearSelection(); @@ -1152,7 +1152,7 @@ void LyXText::rejectChange() if (cur.selBegin().par() == cur.selEnd().par()) { CursorSlice const & startc = cur.selBegin(); CursorSlice const & endc = cur.selEnd(); - recordUndo(Undo::INSERT, this, startc.par()); + recordUndo(cur, Undo::INSERT, cur.anchor().par()); getPar(startc)->rejectChange(startc.pos(), endc.pos()); finishUndo(); cur.clearSelection(); @@ -1240,7 +1240,7 @@ void LyXText::changeCase(LyXText::TextCase action) setCursor(to.par(), to.pos() + 1); } - recordUndo(Undo::ATOMIC, this, from.par(), to.par()); + recordUndo(cur, Undo::ATOMIC, cur.anchor().par()); pos_type pos = from.pos(); int par = from.par(); @@ -1284,9 +1284,9 @@ void LyXText::Delete() cursorRight(true); // if you had success make a backspace - if (old_cursor.par() != cursor().par() || old_cursor.pos() != -cursor().pos()) { - recordUndo(Undo::DELETE, this, old_cursor.par()); + if (old_cursor.par() != cursor().par() + || old_cursor.pos() != cursor().pos()) { + recordUndo(bv()->cursor(), Undo::DELETE, old_cursor.par()); backspace(); } } @@ -1325,7 +1325,7 @@ void LyXText::backspace() } if (cursor().par() != 0) - recordUndo(Undo::DELETE, this, cursor().par() - 1, cursor().par()); + recordUndo(bv()->cursor(), Undo::DELETE, cursor().par() - 1); ParagraphList::iterator tmppit = cursorPar(); // We used to do cursorLeftIntern() here, but it is @@ -1364,7 +1364,7 @@ void LyXText::backspace() } else { // this is the code for a normal backspace, not pasting // any paragraphs - recordUndo(Undo::DELETE, this, cursor().par()); + recordUndo(bv()->cursor(), Undo::DELETE); // We used to do cursorLeftIntern() here, but it is // not a good idea since it triggers the auto-delete // mechanism. So we do a cursorLeftIntern()-lite, @@ -1457,36 +1457,18 @@ RowList::iterator LyXText::firstRow() const } -ParagraphList::iterator LyXText::firstPar() const -{ - return paragraphs().begin(); -} - - RowList::iterator LyXText::lastRow() const { return boost::prior(endRow()); } -ParagraphList::iterator LyXText::lastPar() const -{ - return boost::prior(endPar()); -} - - RowList::iterator LyXText::endRow() const { return paragraphs().back().rows.end(); } -ParagraphList::iterator LyXText::endPar() const -{ - return paragraphs().end(); -} - - void LyXText::nextRow(ParagraphList::iterator & pit, RowList::iterator & rit) const { diff --git a/src/text2.C b/src/text2.C index 8e0afeab87..e15775524e 100644 --- a/src/text2.C +++ b/src/text2.C @@ -213,38 +213,6 @@ void LyXText::setCharFont( } -InsetBase * LyXText::getInset() const -{ - ParagraphList::iterator pit = cursorPar(); - pos_type const pos = cursor().pos(); - - if (pos < pit->size() && pit->isInset(pos)) { - return pit->getInset(pos); - } - return 0; -} - - -bool LyXText::toggleInset() -{ - InsetBase * inset = getInset(); - // is there an editable inset at cursor position? - if (!isEditableInset(inset)) - return false; - //bv()->owner()->message(inset->editMessage()); - - // do we want to keep this?? (JMarc) - if (!isHighlyEditableInset(inset)) - recUndo(cursor().par()); - - if (inset->isOpen()) - inset->close(); - else - inset->open(); - return true; -} - - // used in setLayout // Asger is not sure we want to do this... void LyXText::makeFontEntriesLayoutSpecific(BufferParams const & params, @@ -1086,8 +1054,7 @@ void LyXText::insertStringAsLines(string const & str) ParagraphList::iterator pit = cursorPar(); pos_type pos = cursor().pos(); ParagraphList::iterator endpit = boost::next(cursorPar()); - - recUndo(cursor().par()); + recordUndo(cur, Undo::ATOMIC); // only to be sure, should not be neccessary cur.clearSelection(); @@ -1457,10 +1424,11 @@ DispatchResult LyXText::moveLeftIntern(bool front, DispatchResult LyXText::moveUp() { - if (cursorPar() == firstPar() && cursorRow() == firstRow()) + LCursor & cur = bv()->cursor(); + if (cur.par() == 0 && cursorRow() == firstRow()) return DispatchResult(false, FINISHED_UP); cursorUp(false); - bv()->cursor().clearSelection(); + cur.clearSelection(); return DispatchResult(true); } @@ -1468,7 +1436,7 @@ DispatchResult LyXText::moveUp() DispatchResult LyXText::moveDown() { LCursor & cur = bv()->cursor(); - if (cursorPar() == lastPar() && cursorRow() == lastRow()) + if (cur.par() == cur.lastpar() && cursorRow() == lastRow()) return DispatchResult(false, FINISHED_DOWN); cursorDown(false); cur.clearSelection(); @@ -1738,13 +1706,13 @@ ParagraphList & LyXText::paragraphs() const void LyXText::recUndo(paroffset_type first, paroffset_type last) const { - recordUndo(Undo::ATOMIC, this, first, last); + recordUndo(bv()->cursor(), Undo::ATOMIC, first, last); } void LyXText::recUndo(lyx::paroffset_type par) const { - recordUndo(Undo::ATOMIC, this, par, par); + recordUndo(bv()->cursor(), Undo::ATOMIC, par, par); } @@ -1754,6 +1722,26 @@ bool LyXText::isInInset() const } +bool LyXText::toggleInset() +{ + InsetBase * inset = bv()->cursor().nextInset(); + // is there an editable inset at cursor position? + if (!isEditableInset(inset)) + return false; + //bv()->owner()->message(inset->editMessage()); + + // do we want to keep this?? (JMarc) + if (!isHighlyEditableInset(inset)) + recUndo(cursor().par()); + + if (inset->isOpen()) + inset->close(); + else + inset->open(); + return true; +} + + int defaultRowHeight() { return int(font_metrics::maxHeight(LyXFont(LyXFont::ALL_SANE)) * 1.2); diff --git a/src/text3.C b/src/text3.C index ccd48cb57b..a5432ea4e0 100644 --- a/src/text3.C +++ b/src/text3.C @@ -670,7 +670,7 @@ DispatchResult LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) if (!cur.mark()) cur.clearSelection(); finishChange(bv, false); - if (cursorPar() == firstPar() && cursorRow() == firstRow()) + if (cur.par() == 0 && cursorRow() == firstRow()) return DispatchResult(false, FINISHED_UP); cursorPrevious(); break; @@ -679,7 +679,7 @@ DispatchResult LyXText::dispatch(LCursor & cur, FuncRequest const & cmd) if (!cur.mark()) cur.clearSelection(); finishChange(bv, false); - if (cursorPar() == lastPar() && cursorRow() == lastRow()) + if (cur.par() == cur.lastpar() && cursorRow() == lastRow()) return DispatchResult(false, FINISHED_DOWN); cursorNext(); break; diff --git a/src/undo.C b/src/undo.C index f517f2ab0e..5c44ed5459 100644 --- a/src/undo.C +++ b/src/undo.C @@ -24,8 +24,6 @@ #include "lyxtext.h" #include "paragraph.h" -#include "insets/updatableinset.h" // for dynamic_cast - using lyx::paroffset_type; @@ -96,12 +94,17 @@ ParIterator num2pit(Buffer & buf, int num) void recordUndo(Undo::undo_kind kind, - LyXText * text, paroffset_type first_par, paroffset_type last_par, + LCursor & cur, paroffset_type first_par, paroffset_type last_par, limited_stack & stack) { - Buffer & buf = *text->bv()->buffer(); + if (first_par > last_par) { + paroffset_type t = first_par; + first_par = last_par; + last_par = t; + } - int const end_par = text->paragraphs().size() - last_par; + Buffer & buf = *cur.bv().buffer(); + int const end_par = cur.lastpar() + 1 - last_par; // Undo::ATOMIC are always recorded (no overlapping there). // overlapping only with insert and delete inside one paragraph: @@ -120,9 +123,11 @@ void recordUndo(Undo::undo_kind kind, // make and push the Undo entry int textnum; + LyXText * text = cur.text(); + BOOST_ASSERT(text); // not in mathed (yet) ParIterator pit = text2pit(buf, text, textnum); stack.push(Undo(kind, textnum, pit.index(), - first_par, end_par, text->cursor().par(), text->cursor().pos())); + first_par, end_par, cur.par(), cur.pos())); //lyxerr << "undo record: " << stack.top() << std::endl; // record the relevant paragraphs @@ -144,9 +149,9 @@ void recordUndo(Undo::undo_kind kind, // returns false if no undo possible -bool performUndoOrRedo(BufferView * bv, Undo const & undo) +bool performUndoOrRedo(BufferView & bv, Undo const & undo) { - Buffer & buf = *bv->buffer(); + Buffer & buf = *bv.buffer(); lyxerr << "undo, performing: " << undo << std::endl; ParIterator pit = num2pit(buf, undo.text); LyXText * text = pit.text(buf); @@ -185,7 +190,7 @@ bool performUndoOrRedo(BufferView * bv, Undo const & undo) ParIterator pit2 = num2pit(buf, undo.text); advance(pit2, undo.cursor_par); - bv->setCursor(pit2, undo.cursor_pos); + bv.setCursor(pit2, undo.cursor_pos); finishUndo(); return true; @@ -193,10 +198,10 @@ bool performUndoOrRedo(BufferView * bv, Undo const & undo) // returns false if no undo possible -bool textUndoOrRedo(BufferView * bv, +bool textUndoOrRedo(BufferView & bv, limited_stack & stack, limited_stack & otherstack) { - Buffer & buf = *bv->buffer(); + Buffer & buf = *bv.buffer(); if (stack.empty()) { // nothing to do finishUndo(); @@ -219,8 +224,8 @@ bool textUndoOrRedo(BufferView * bv, advance(last, plist.size() - undo.end_par + 1); otherstack.top().pars.insert(otherstack.top().pars.begin(), first, last); } - otherstack.top().cursor_pos = bv->cursor().pos(); - otherstack.top().cursor_par = bv->cursor().par(); + otherstack.top().cursor_pos = bv.cursor().pos(); + otherstack.top().cursor_par = bv.cursor().par(); lyxerr << " undo other: " << otherstack.top() << std::endl; } @@ -254,44 +259,52 @@ void finishUndo() } -bool textUndo(BufferView * bv) +bool textUndo(BufferView & bv) { - return textUndoOrRedo(bv, bv->buffer()->undostack(), - bv->buffer()->redostack()); + return textUndoOrRedo(bv, bv.buffer()->undostack(), + bv.buffer()->redostack()); } -bool textRedo(BufferView * bv) +bool textRedo(BufferView & bv) { - return textUndoOrRedo(bv, bv->buffer()->redostack(), - bv->buffer()->undostack()); + return textUndoOrRedo(bv, bv.buffer()->redostack(), + bv.buffer()->undostack()); } void recordUndo(Undo::undo_kind kind, - LyXText const * text, paroffset_type first, paroffset_type last) + LCursor & cur, paroffset_type first, paroffset_type last) { if (undo_frozen) return; - Buffer * buf = text->bv()->buffer(); - recordUndo(kind, const_cast(text), first, last, buf->undostack()); + Buffer * buf = cur.bv().buffer(); + recordUndo(kind, cur, first, last, buf->undostack()); buf->redostack().clear(); } -void recordUndo(Undo::undo_kind kind, LyXText const * text, paroffset_type par) +void recordUndo(LCursor & cur, Undo::undo_kind kind) { - recordUndo(kind, text, par, par); + recordUndo(kind, cur, cur.par(), cur.par()); } -void recordUndo(BufferView * bv, Undo::undo_kind kind) +void recordUndo(LCursor & cur, Undo::undo_kind kind, paroffset_type from) { - recordUndo(bv->cursor(), kind); + recordUndo(kind, cur, cur.par(), from); } -void recordUndo(LCursor & cur, Undo::undo_kind kind) +void recordUndo(LCursor & cur, Undo::undo_kind kind, + paroffset_type from, paroffset_type to) +{ + recordUndo(kind, cur, from, to); +} + + +void recordUndoFullDocument(LCursor &) { - recordUndo(kind, cur.bv().text(), cur.bv().text()->cursor().par()); + //recordUndo(Undo::ATOMIC, + // cur, 0, cur.bv().text()->paragraphs().size() - 1); } diff --git a/src/undo.h b/src/undo.h index 925d87d20b..e5060add60 100644 --- a/src/undo.h +++ b/src/undo.h @@ -20,9 +20,9 @@ #include "support/types.h" class LCursor; -class LyXText; class BufferView; + /** * These are the elements put on the undo stack. Each object * contains complete paragraphs and sufficient information @@ -30,61 +30,51 @@ class BufferView; */ class Undo { public: - /** - * The undo kinds are used to combine consecutive undo recordings - * of the same kind. - */ + /// This is used to combine consecutive undo recordings of the same kind. enum undo_kind { /** * Insert something - these will combine to one big chunk * when many inserts come after each other. */ INSERT, - /** * Delete something - these will combine to one big chunk * when many deletes come after each other. */ DELETE, - /// Atomic - each of these will have its own entry in the stack ATOMIC }; + /// constructor Undo(undo_kind kind, int text, int index, int first_par, int end_par, int cursor_par, int cursor_pos); +public: /// 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 parargraph list + /// 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 contents of the paragraphs saved ParagraphList pars; }; /// this will undo the last action - returns false if no undo possible -bool textUndo(BufferView *); +bool textUndo(BufferView &); /// this will redo the last undo - returns false if no redo possible -bool textRedo(BufferView *); +bool textRedo(BufferView &); /// makes sure the next operation will be stored void finishUndo(); @@ -95,23 +85,26 @@ void freezeUndo(); /// track undos again void unFreezeUndo(); + /** - * Record undo information - call with the first paragraph that will be changed - * and the last paragraph that will be changed. So we give an inclusive - * range. + * Record undo information - call with the current cursor and the 'other + * end' of the range of changed paragraphs. So we give an inclusive range. * This is called before you make the changes to the paragraph, and it * will record the original information of the paragraphs in the undo stack. */ -void recordUndo(Undo::undo_kind kind, - LyXText const * text, lyx::paroffset_type first, lyx::paroffset_type last); -/// convienience: prepare undo when change in a single paragraph -void recordUndo(Undo::undo_kind kind, - LyXText const * text, lyx::paroffset_type par); +/// the common case: prepare undo for an arbitrary range +void recordUndo(LCursor & cur, Undo::undo_kind kind, + lyx::paroffset_type from, lyx::paroffset_type to); + +/// convienience: prepare undo for the range between 'from' and cursor. +void recordUndo(LCursor & cur, Undo::undo_kind kind, lyx::paroffset_type from); + +/// convienience: prepare undo for the single paragraph containing the cursor +void recordUndo(LCursor & cur, Undo::undo_kind kind); -/// convienience: prepare undo for the paragraph that contains the cursor -void recordUndo(BufferView *, Undo::undo_kind kind); -void recordUndo(LCursor &, Undo::undo_kind kind); +/// convienience: prepare undo for the single paragraph containing the cursor +void recordUndoFullDocument(LCursor & cur); /// are we avoiding tracking undos currently? extern bool undo_frozen; -- 2.39.2