]> git.lyx.org Git - lyx.git/commitdiff
Move some Cursor methods to CursorData
authorJean-Marc Lasgouttes <lasgouttes@lyx.org>
Sun, 23 Jul 2017 16:13:33 +0000 (18:13 +0200)
committerJean-Marc Lasgouttes <lasgouttes@lyx.org>
Wed, 25 Oct 2017 14:20:27 +0000 (16:20 +0200)
Basically, everything that does not depend on a BufferView should move
there. Some methods that do not seem to need a BufferView, like
selHandle or IdxFirst or push actually depend on it and could not be
moved.

This allows to simplify a few uses of recordUndo helpers.

- Move some methods to DocIterator: nextMath, prevMath, getPossibleLabel,
  getEncoding;

- Move some methods to CursorData: setCursor, setCursorSelectionTo,
  (setCursorTo|normal|reset)Anchor, (set|clear)Selection,
  sel(|ection)(Begin|End), selectionAsString, info, currentState,
  (mark|clear|check)NewWordPosition, fixIfBroken, sanitize, all undo
  related methods, reset, isInside, leaveInset, current mode;

- kill some unused methods: macromode, replaceWord, setScreenPos, touch,
  markInsert, markErase;

- Move code around to group things, and add a few comments (a lot remains to be done).

This changes lead to some related changes in other classes: removal,
change of parameter.

No intended change.

16 files changed:
src/Buffer.cpp
src/Cursor.cpp
src/Cursor.h
src/CutAndPaste.cpp
src/CutAndPaste.h
src/DocIterator.cpp
src/DocIterator.h
src/Text.cpp
src/Text.h
src/insets/InsetGraphics.cpp
src/insets/InsetLabel.cpp
src/mathed/InsetMathHull.cpp
src/mathed/InsetMathHull.h
src/mathed/InsetMathNest.cpp
src/mathed/MathData.cpp
src/mathed/MathData.h

index c564a7dccf22e2164b9f65f8d74e40044e977743..a781f2ada35ccb34191845b6c5c3f15330e92e57 100644 (file)
@@ -5011,7 +5011,7 @@ void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
                         * non-const. This would however be costly in
                         * terms of code duplication.
                         */
-                       const_cast<Buffer *>(this)->undo().recordUndo(CursorData(parit));
+                       CursorData(parit).recordUndo();
                        parit->params().depth(maxdepth);
                }
                maxdepth = parit->getMaxDepthAfter();
index cc9b76eee08e58ba07961239b4f52488e8d4e18b..3f5bff854cfabe9c5506ca6637658748f8168539 100644 (file)
 #include <config.h>
 
 #include "Buffer.h"
-#include "BufferParams.h"
 #include "BufferView.h"
 #include "CoordCache.h"
 #include "Cursor.h"
 #include "CutAndPaste.h"
 #include "DispatchResult.h"
-#include "Encoding.h"
-#include "Font.h"
 #include "FuncCode.h"
 #include "FuncRequest.h"
-#include "Language.h"
 #include "Layout.h"
 #include "LyXAction.h"
 #include "LyXRC.h"
@@ -118,27 +114,26 @@ DocIterator bruteFind(Cursor const & c, int x, int y)
 } // namespace
 
 
+//
+// CursorData
+//
+
+
 CursorData::CursorData()
-       : DocIterator(), anchor_(),
-         selection_(false), mark_(false), word_selection_(false),
-         current_font(inherit_font),
-         autocorrect_(false), macromode_(false)
+       : DocIterator(), anchor_(), selection_(false), mark_(false),
+         word_selection_(false), current_font(inherit_font), autocorrect_(false)
 {}
 
 
 CursorData::CursorData(Buffer * buffer)
-       : DocIterator(buffer), anchor_(),
-         selection_(false), mark_(false), word_selection_(false),
-         current_font(inherit_font),
-         autocorrect_(false), macromode_(false)
+       : DocIterator(buffer), anchor_(), selection_(false), mark_(false),
+         word_selection_(false), current_font(inherit_font), autocorrect_(false)
 {}
 
 
 CursorData::CursorData(DocIterator const & dit)
-       : DocIterator(dit), anchor_(),
-         selection_(false), mark_(false), word_selection_(false),
-         current_font(inherit_font),
-         autocorrect_(false), macromode_(false)
+       : DocIterator(dit), anchor_(), selection_(false), mark_(false),
+         word_selection_(false), current_font(inherit_font), autocorrect_(false)
 {}
 
 
@@ -165,11 +160,510 @@ ostream & operator<<(ostream & os, CursorData const & cur)
 }
 
 
-LyXErr & operator<<(LyXErr & os, CursorData const & cur)
-{
-       os.stream() << cur;
-       return os;
-}
+LyXErr & operator<<(LyXErr & os, CursorData const & cur)
+{
+       os.stream() << cur;
+       return os;
+}
+
+
+void CursorData::reset()
+{
+       clear();
+       push_back(CursorSlice(buffer()->inset()));
+       anchor_ = doc_iterator_begin(buffer());
+       anchor_.clear();
+       new_word_ = doc_iterator_begin(buffer());
+       new_word_.clear();
+       selection_ = false;
+       mark_ = false;
+}
+
+
+void CursorData::setCursor(DocIterator const & cur)
+{
+       DocIterator::operator=(cur);
+}
+
+
+void CursorData::setCursorSelectionTo(DocIterator dit)
+{
+       size_t i = 0;
+       // normalise dit
+       while (i < dit.depth() && i < anchor_.depth() && dit[i] == anchor_[i])
+               ++i;
+       if (i != dit.depth()) {
+               // otherwise the cursor is already normal
+               if (i == anchor_.depth())
+                       // dit is a proper extension of the anchor_
+                       dit.cutOff(i - 1);
+               else if (i + 1 < dit.depth()) {
+                       // one has dit[i] != anchor_[i] but either dit[i-1] == anchor_[i-1]
+                       // or i == 0. Remove excess.
+                       dit.cutOff(i);
+                       if (dit[i] > anchor_[i])
+                               // place dit after the inset it was in
+                               ++dit.pos();
+               }
+       }
+       setCursor(dit);
+       setSelection();
+}
+
+
+void CursorData::setCursorToAnchor()
+{
+       if (selection()) {
+               DocIterator normal = anchor_;
+               while (depth() < normal.depth())
+                       normal.pop_back();
+               if (depth() < anchor_.depth() && top() <= anchor_[depth() - 1])
+                       ++normal.pos();
+               setCursor(normal);
+       }
+}
+
+
+CursorSlice CursorData::normalAnchor() const
+{
+       if (!selection())
+               return top();
+       // LASSERT: There have been several bugs around this code, that seem
+       // to involve failures to reset the anchor. We can at least not crash
+       // in release mode by resetting it ourselves.
+       if (anchor_.depth() < depth()) {
+               LYXERR0("Cursor is deeper than anchor. PLEASE REPORT.\nCursor is"
+                       << *this);
+               const_cast<DocIterator &>(anchor_) = *this;
+       }
+
+       CursorSlice normal = anchor_[depth() - 1];
+       if (depth() < anchor_.depth() && top() <= normal) {
+               // anchor is behind cursor -> move anchor behind the inset
+               ++normal.pos();
+       }
+       return normal;
+}
+
+
+void CursorData::setSelection()
+{
+       selection(true);
+       if (idx() == normalAnchor().idx() &&
+           pit() == normalAnchor().pit() &&
+           pos() == normalAnchor().pos())
+               selection(false);
+}
+
+
+void CursorData::setSelection(DocIterator const & where, int n)
+{
+       setCursor(where);
+       selection(true);
+       anchor_ = where;
+       pos() += n;
+}
+
+
+void CursorData::resetAnchor()
+{
+       anchor_ = *this;
+       checkNewWordPosition();
+}
+
+
+CursorSlice CursorData::selBegin() const
+{
+       if (!selection())
+               return top();
+       return normalAnchor() < top() ? normalAnchor() : top();
+}
+
+
+CursorSlice CursorData::selEnd() const
+{
+       if (!selection())
+               return top();
+       return normalAnchor() > top() ? normalAnchor() : top();
+}
+
+
+DocIterator CursorData::selectionBegin() const
+{
+       if (!selection())
+               return *this;
+
+       DocIterator di;
+       // FIXME: This is a work-around for the problem that
+       // CursorSlice doesn't keep track of the boundary.
+       if (normalAnchor() == top())
+               di = anchor_.boundary() > boundary() ? anchor_ : *this;
+       else
+               di = normalAnchor() < top() ? anchor_ : *this;
+       di.resize(depth());
+       return di;
+}
+
+
+DocIterator CursorData::selectionEnd() const
+{
+       if (!selection())
+               return *this;
+
+       DocIterator di;
+       // FIXME: This is a work-around for the problem that
+       // CursorSlice doesn't keep track of the boundary.
+       if (normalAnchor() == top())
+               di = anchor_.boundary() < boundary() ? anchor_ : *this;
+       else
+               di = normalAnchor() > top() ? anchor_ : *this;
+
+       if (di.depth() > depth()) {
+               di.resize(depth());
+               ++di.pos();
+       }
+       return di;
+}
+
+
+namespace {
+
+docstring parbreak(CursorData const * cur)
+{
+       odocstringstream os;
+       os << '\n';
+       // only add blank line if we're not in a ParbreakIsNewline situation
+       if (!cur->inset().getLayout().parbreakIsNewline()
+           && !cur->paragraph().layout().parbreak_is_newline)
+               os << '\n';
+       return os.str();
+}
+
+}
+
+
+docstring CursorData::selectionAsString(bool with_label) const
+{
+       if (!selection())
+               return docstring();
+
+       if (inMathed())
+               return cap::grabSelection(*this);
+
+       int const label = with_label
+               ? AS_STR_LABEL | AS_STR_INSETS : AS_STR_INSETS;
+
+       idx_type const startidx = selBegin().idx();
+       idx_type const endidx = selEnd().idx();
+       if (startidx != endidx) {
+               // multicell selection
+               InsetTabular * table = inset().asInsetTabular();
+               LASSERT(table, return docstring());
+               return table->asString(startidx, endidx);
+       }
+
+       ParagraphList const & pars = text()->paragraphs();
+
+       pit_type const startpit = selBegin().pit();
+       pit_type const endpit = selEnd().pit();
+       size_t const startpos = selBegin().pos();
+       size_t const endpos = selEnd().pos();
+
+       if (startpit == endpit)
+               return pars[startpit].asString(startpos, endpos, label);
+
+       // First paragraph in selection
+       docstring result = pars[startpit].
+               asString(startpos, pars[startpit].size(), label)
+               + parbreak(this);
+
+       // The paragraphs in between (if any)
+       for (pit_type pit = startpit + 1; pit != endpit; ++pit) {
+               Paragraph const & par = pars[pit];
+               result += par.asString(0, par.size(), label)
+                       + parbreak(this);
+       }
+
+       // Last paragraph in selection
+       result += pars[endpit].asString(0, endpos, label);
+
+       return result;
+}
+
+
+void CursorData::info(odocstream & os, bool devel_mode) const
+{
+       for (int i = 1, n = depth(); i < n; ++i) {
+               operator[](i).inset().infoize(os);
+               os << "  ";
+       }
+       if (pos() != 0) {
+               Inset const * inset = prevInset();
+               // prevInset() can return 0 in certain case.
+               if (inset)
+                       prevInset()->infoize2(os);
+       }
+       if (devel_mode) {
+               InsetMath * math = inset().asInsetMath();
+               if (math)
+                       os << _(", Inset: ") << math->id();
+               os << _(", Cell: ") << idx();
+               os << _(", Position: ") << pos();
+       }
+
+}
+
+docstring CursorData::currentState(bool devel_mode) const
+{
+       if (inMathed()) {
+               odocstringstream os;
+               info(os, devel_mode);
+               return os.str();
+       }
+
+       if (inTexted())
+               return text()->currentState(*this, devel_mode);
+
+       return docstring();
+}
+
+
+void CursorData::markNewWordPosition()
+{
+       if (lyxrc.spellcheck_continuously && inTexted() && new_word_.empty()) {
+               FontSpan nw = locateWord(WHOLE_WORD);
+               if (nw.size() == 1) {
+                       LYXERR(Debug::DEBUG, "start new word: "
+                               << " par: " << pit()
+                               << " pos: " << nw.first);
+                       new_word_ = *this;
+               }
+       }
+}
+
+
+void CursorData::clearNewWordPosition()
+{
+       if (!new_word_.empty()) {
+               LYXERR(Debug::DEBUG, "clear new word: "
+                       << " par: " << pit()
+                       << " pos: " << pos());
+               new_word_.resize(0);
+       }
+}
+
+
+void CursorData::checkNewWordPosition()
+{
+       if (!lyxrc.spellcheck_continuously || new_word_.empty())
+               return ;
+       if (!inTexted())
+               clearNewWordPosition();
+       else {
+               // forget the position of the current new word if
+               // 1) the paragraph changes or
+               // 2) the count of nested insets changes or
+               // 3) the cursor pos is out of paragraph bound
+               if (pit() != new_word_.pit() ||
+                       depth() != new_word_.depth() ||
+                       new_word_.pos() > new_word_.lastpos()) {
+                       clearNewWordPosition();
+               } else if (new_word_.fixIfBroken())
+                       // 4) or the remembered position was "broken"
+                       clearNewWordPosition();
+               else {
+                       FontSpan nw = locateWord(WHOLE_WORD);
+                       if (!nw.empty()) {
+                               FontSpan ow = new_word_.locateWord(WHOLE_WORD);
+                               if (nw.intersect(ow).empty())
+                                       clearNewWordPosition();
+                               else
+                                       LYXERR(Debug::DEBUG, "new word: "
+                                                  << " par: " << pit()
+                                                  << " pos: " << nw.first << ".." << nw.last);
+                       } else {
+                               clearNewWordPosition();
+                       }
+               }
+       }
+}
+
+
+void CursorData::clearSelection()
+{
+       selection(false);
+       setWordSelection(false);
+       setMark(false);
+       resetAnchor();
+}
+
+
+bool CursorData::fixIfBroken()
+{
+       bool const broken_cursor = DocIterator::fixIfBroken();
+       bool const broken_anchor = anchor_.fixIfBroken();
+
+       if (broken_cursor || broken_anchor) {
+               clearNewWordPosition();
+               clearSelection();
+               return true;
+       }
+       return false;
+}
+
+
+void CursorData::sanitize()
+{
+       DocIterator::sanitize();
+       if (selection())
+               anchor_.sanitize();
+       else
+               resetAnchor();
+}
+
+
+bool CursorData::isInside(Inset const * p) const
+{
+       for (size_t i = 0; i != depth(); ++i)
+               if (&operator[](i).inset() == p)
+                       return true;
+       return false;
+}
+
+
+void CursorData::leaveInset(Inset const & inset)
+{
+       for (size_t i = 0; i != depth(); ++i) {
+               if (&operator[](i).inset() == &inset) {
+                       resize(i);
+                       return;
+               }
+       }
+}
+
+
+bool CursorData::textUndo()
+{
+       if (!buffer()->undo().textUndo(*this))
+               return false;
+       sanitize();
+       return true;
+}
+
+
+bool CursorData::textRedo()
+{
+       if (!buffer()->undo().textRedo(*this))
+               return false;
+       sanitize();
+       return true;
+}
+
+
+void CursorData::finishUndo() const
+{
+       buffer()->undo().finishUndo();
+}
+
+
+void CursorData::beginUndoGroup() const
+{
+       buffer()->undo().beginUndoGroup(*this);
+}
+
+
+void CursorData::endUndoGroup() const
+{
+       buffer()->undo().endUndoGroup(*this);
+}
+
+
+void CursorData::recordUndo(pit_type from, pit_type to) const
+{
+       buffer()->undo().recordUndo(*this, from, to);
+}
+
+
+void CursorData::recordUndo(pit_type from) const
+{
+       buffer()->undo().recordUndo(*this, from, pit());
+}
+
+
+void CursorData::recordUndo(UndoKind kind) const
+{
+       buffer()->undo().recordUndo(*this, kind);
+}
+
+
+void CursorData::recordUndoInset(Inset const * in) const
+{
+       buffer()->undo().recordUndoInset(*this, in);
+}
+
+
+void CursorData::recordUndoFullBuffer() const
+{
+       buffer()->undo().recordUndoFullBuffer(*this);
+}
+
+
+void CursorData::recordUndoBufferParams() const
+{
+       buffer()->undo().recordUndoBufferParams(*this);
+}
+
+
+void CursorData::recordUndoSelection() const
+{
+       if (inMathed()) {
+               if (cap::multipleCellsSelected(*this))
+                       recordUndoInset();
+               else
+                       recordUndo();
+       } else {
+               buffer()->undo().recordUndo(*this,
+                       selBegin().pit(), selEnd().pit());
+       }
+}
+
+
+int CursorData::currentMode()
+{
+       LASSERT(!empty(), return Inset::UNDECIDED_MODE);
+       for (int i = depth() - 1; i >= 0; --i) {
+               int res = operator[](i).inset().currentMode();
+               bool locked_mode = operator[](i).inset().lockedMode();
+               // Also return UNDECIDED_MODE when the mode is locked,
+               // as in this case it is treated the same as TEXT_MODE
+               if (res != Inset::UNDECIDED_MODE || locked_mode)
+                       return res;
+       }
+       return Inset::TEXT_MODE;
+}
+
+
+bool CursorData::confirmDeletion(bool const before) const
+{
+       if (!selection()) {
+               if (Inset const * inset = before ? prevInset() : nextInset())
+                       return inset->confirmDeletion();
+       } else {
+               DocIterator dit = selectionBegin();
+               CursorSlice const end = selectionEnd().top();
+               for (; dit.top() < end; dit.top().forwardPos())
+                       if (Inset const * inset = dit.nextInset())
+                               if (inset->confirmDeletion())
+                                       return true;
+       }
+       return false;
+}
+
+
+
+//
+// Cursor
+//
 
 
 // be careful: this is called from the bv's constructor, too, so
@@ -183,59 +677,8 @@ Cursor::Cursor(BufferView & bv)
 
 void Cursor::reset()
 {
-       clear();
-       push_back(CursorSlice(buffer()->inset()));
-       anchor_ = doc_iterator_begin(buffer());
-       anchor_.clear();
-       new_word_ = doc_iterator_begin(buffer());
-       new_word_.clear();
+       CursorData::reset();
        clearTargetX();
-       selection_ = false;
-       mark_ = false;
-}
-
-
-void Cursor::setCursor(DocIterator const & cur)
-{
-       DocIterator::operator=(cur);
-}
-
-
-void Cursor::setCursorSelectionTo(DocIterator dit)
-{
-       size_t i = 0;
-       // normalise dit
-       while (i < dit.depth() && i < anchor_.depth() && dit[i] == anchor_[i])
-               ++i;
-       if (i != dit.depth()) {
-               // otherwise the cursor is already normal
-               if (i == anchor_.depth())
-                       // dit is a proper extension of the anchor_
-                       dit.cutOff(i - 1);
-               else if (i + 1 < dit.depth()) {
-                       // one has dit[i] != anchor_[i] but either dit[i-1] == anchor_[i-1]
-                       // or i == 0. Remove excess.
-                       dit.cutOff(i);
-                       if (dit[i] > anchor_[i])
-                               // place dit after the inset it was in
-                               ++dit.pos();
-               }
-       }
-       setCursor(dit);
-       setSelection();
-}
-
-
-void Cursor::setCursorToAnchor()
-{
-       if (selection()) {
-               DocIterator normal = anchor_;
-               while (depth() < normal.depth())
-                       normal.pop_back();
-               if (depth() < anchor_.depth() && top() <= anchor_[depth() - 1])
-                       ++normal.pos();
-               setCursor(normal);
-       }
 }
 
 
@@ -386,6 +829,19 @@ DispatchResult const & Cursor::result() const
 }
 
 
+void Cursor::message(docstring const & msg) const
+{
+       disp_.setMessage(msg);
+}
+
+
+void Cursor::errorMessage(docstring const & msg) const
+{
+       disp_.setMessage(msg);
+       disp_.setError(true);
+}
+
+
 BufferView & Cursor::bv() const
 {
        LBUFERR(bv_);
@@ -439,21 +895,6 @@ bool Cursor::popForward()
 }
 
 
-int Cursor::currentMode()
-{
-       LASSERT(!empty(), return Inset::UNDECIDED_MODE);
-       for (int i = depth() - 1; i >= 0; --i) {
-               int res = operator[](i).inset().currentMode();
-               bool locked_mode = operator[](i).inset().lockedMode();
-               // Also return UNDECIDED_MODE when the mode is locked,
-               // as in this case it is treated the same as TEXT_MODE
-               if (res != Inset::UNDECIDED_MODE || locked_mode)
-                       return res;
-       }
-       return Inset::TEXT_MODE;
-}
-
-
 void Cursor::getPos(int & x, int & y) const
 {
        Point p = bv().getPos(*this);
@@ -470,74 +911,6 @@ Row const & Cursor::textRow() const
 }
 
 
-void Cursor::resetAnchor()
-{
-       anchor_ = *this;
-       checkNewWordPosition();
-}
-
-
-void Cursor::markNewWordPosition()
-{
-       if (lyxrc.spellcheck_continuously && inTexted() && new_word_.empty()) {
-               FontSpan nw = locateWord(WHOLE_WORD);
-               if (nw.size() == 1) {
-                       LYXERR(Debug::DEBUG, "start new word: "
-                               << " par: " << pit()
-                               << " pos: " << nw.first);
-                       new_word_ = *this;
-               }
-       }
-}
-
-
-void Cursor::clearNewWordPosition()
-{
-       if (!new_word_.empty()) {
-               LYXERR(Debug::DEBUG, "clear new word: "
-                       << " par: " << pit()
-                       << " pos: " << pos());
-               new_word_.resize(0);
-       }
-}
-
-
-void Cursor::checkNewWordPosition()
-{
-       if (!lyxrc.spellcheck_continuously || new_word_.empty())
-               return ;
-       if (!inTexted())
-               clearNewWordPosition();
-       else {
-               // forget the position of the current new word if
-               // 1) the paragraph changes or
-               // 2) the count of nested insets changes or
-               // 3) the cursor pos is out of paragraph bound
-               if (pit() != new_word_.pit() ||
-                       depth() != new_word_.depth() ||
-                       new_word_.pos() > new_word_.lastpos()) {
-                       clearNewWordPosition();
-               } else if (new_word_.fixIfBroken())
-                       // 4) or the remembered position was "broken"
-                       clearNewWordPosition();
-               else {
-                       FontSpan nw = locateWord(WHOLE_WORD);
-                       if (!nw.empty()) {
-                               FontSpan ow = new_word_.locateWord(WHOLE_WORD);
-                               if (nw.intersect(ow).empty())
-                                       clearNewWordPosition();
-                               else
-                                       LYXERR(Debug::DEBUG, "new word: "
-                                                  << " par: " << pit()
-                                                  << " pos: " << nw.first << ".." << nw.last);
-                       } else {
-                               clearNewWordPosition();
-                       }
-               }
-       }
-}
-
-
 bool Cursor::posVisRight(bool skip_inset)
 {
        Cursor new_cur = *this; // where we will move to
@@ -870,148 +1243,44 @@ bool Cursor::posVisToNewRow(bool movingLeft)
                } else { // move to next row in this par
                        pos() = row.endpos();
                        boundary(false);
-               }
-       }
-
-       // make sure we're at left-/right-most pos in new row
-       posVisToRowExtremity(!movingLeft);
-
-       return true;
-}
-
-
-void Cursor::posVisToRowExtremity(bool left)
-{
-       LYXERR(Debug::RTL, "entering extremity: " << pit() << "," << pos() << ","
-               << (boundary() ? 1 : 0));
-
-       TextMetrics const & tm = bv_->textMetrics(text());
-       // Looking for extremities is like clicking on the left or the
-       // right of the row.
-       int x = tm.origin().x_ + (left ? 0 : textRow().width());
-       bool b = false;
-       pos() = tm.getPosNearX(textRow(), x, b);
-       boundary(b);
-
-       LYXERR(Debug::RTL, "leaving extremity: " << pit() << "," << pos() << ","
-               << (boundary() ? 1 : 0));
-}
-
-
-bool Cursor::reverseDirectionNeeded() const
-{
-       /*
-        * We determine the directions based on the direction of the
-        * bottom() --- i.e., outermost --- paragraph, because that is
-        * the only way to achieve consistency of the arrow's movements
-        * within a paragraph, and thus avoid situations in which the
-        * cursor gets stuck.
-        */
-       return bottom().paragraph().isRTL(bv().buffer().params());
-}
-
-
-CursorSlice Cursor::normalAnchor() const
-{
-       if (!selection())
-               return top();
-       // LASSERT: There have been several bugs around this code, that seem
-       // to involve failures to reset the anchor. We can at least not crash
-       // in release mode by resetting it ourselves.
-       if (anchor_.depth() < depth()) {
-               LYXERR0("Cursor is deeper than anchor. PLEASE REPORT.\nCursor is"
-                       << *this);
-               const_cast<DocIterator &>(anchor_) = *this;
-       }
-
-       CursorSlice normal = anchor_[depth() - 1];
-       if (depth() < anchor_.depth() && top() <= normal) {
-               // anchor is behind cursor -> move anchor behind the inset
-               ++normal.pos();
-       }
-       return normal;
-}
-
-
-CursorSlice Cursor::selBegin() const
-{
-       if (!selection())
-               return top();
-       return normalAnchor() < top() ? normalAnchor() : top();
-}
-
-
-CursorSlice Cursor::selEnd() const
-{
-       if (!selection())
-               return top();
-       return normalAnchor() > top() ? normalAnchor() : top();
-}
-
-
-DocIterator Cursor::selectionBegin() const
-{
-       if (!selection())
-               return *this;
-
-       DocIterator di;
-       // FIXME: This is a work-around for the problem that
-       // CursorSlice doesn't keep track of the boundary.
-       if (normalAnchor() == top())
-               di = anchor_.boundary() > boundary() ? anchor_ : *this;
-       else
-               di = normalAnchor() < top() ? anchor_ : *this;
-       di.resize(depth());
-       return di;
-}
-
-
-DocIterator Cursor::selectionEnd() const
-{
-       if (!selection())
-               return *this;
-
-       DocIterator di;
-       // FIXME: This is a work-around for the problem that
-       // CursorSlice doesn't keep track of the boundary.
-       if (normalAnchor() == top())
-               di = anchor_.boundary() < boundary() ? anchor_ : *this;
-       else
-               di = normalAnchor() > top() ? anchor_ : *this;
-
-       if (di.depth() > depth()) {
-               di.resize(depth());
-               ++di.pos();
+               }
        }
-       return di;
-}
 
+       // make sure we're at left-/right-most pos in new row
+       posVisToRowExtremity(!movingLeft);
 
-void Cursor::setSelection()
-{
-       selection(true);
-       if (idx() == normalAnchor().idx() &&
-           pit() == normalAnchor().pit() &&
-           pos() == normalAnchor().pos())
-               selection(false);
+       return true;
 }
 
 
-void Cursor::setSelection(DocIterator const & where, int n)
+void Cursor::posVisToRowExtremity(bool left)
 {
-       setCursor(where);
-       selection(true);
-       anchor_ = where;
-       pos() += n;
+       LYXERR(Debug::RTL, "entering extremity: " << pit() << "," << pos() << ","
+               << (boundary() ? 1 : 0));
+
+       TextMetrics const & tm = bv_->textMetrics(text());
+       // Looking for extremities is like clicking on the left or the
+       // right of the row.
+       int x = tm.origin().x_ + (left ? 0 : textRow().width());
+       bool b = false;
+       pos() = tm.getPosNearX(textRow(), x, b);
+       boundary(b);
+
+       LYXERR(Debug::RTL, "leaving extremity: " << pit() << "," << pos() << ","
+               << (boundary() ? 1 : 0));
 }
 
 
-void Cursor::clearSelection()
+bool Cursor::reverseDirectionNeeded() const
 {
-       selection(false);
-       setWordSelection(false);
-       setMark(false);
-       resetAnchor();
+       /*
+        * We determine the directions based on the direction of the
+        * bottom() --- i.e., outermost --- paragraph, because that is
+        * the only way to achieve consistency of the arrow's movements
+        * within a paragraph, and thus avoid situations in which the
+        * cursor gets stuck.
+        */
+       return bottom().paragraph().isRTL(bv().buffer().params());
 }
 
 
@@ -1044,29 +1313,6 @@ void Cursor::updateTextTargetOffset()
 }
 
 
-void Cursor::info(odocstream & os, bool devel_mode) const
-{
-       for (int i = 1, n = depth(); i < n; ++i) {
-               operator[](i).inset().infoize(os);
-               os << "  ";
-       }
-       if (pos() != 0) {
-               Inset const * inset = prevInset();
-               // prevInset() can return 0 in certain case.
-               if (inset)
-                       prevInset()->infoize2(os);
-       }
-       if (devel_mode) {
-               InsetMath * math = inset().asInsetMath();
-               if (math)
-                       os << _(", Inset: ") << math->id();
-               os << _(", Cell: ") << idx();
-               os << _(", Position: ") << pos();
-       }
-
-}
-
-
 bool Cursor::selHandle(bool sel)
 {
        //lyxerr << "Cursor::selHandle" << endl;
@@ -1082,6 +1328,31 @@ bool Cursor::selHandle(bool sel)
        selection(sel);
        return true;
 }
+
+
+bool Cursor::atFirstOrLastRow(bool up)
+{
+       TextMetrics const & tm = bv_->textMetrics(text());
+       ParagraphMetrics const & pm = tm.parMetrics(pit());
+
+       int row;
+       if (pos() && boundary())
+               row = pm.pos2row(pos() - 1);
+       else
+               row = pm.pos2row(pos());
+
+       if (up) {
+               if (pit() == 0 && row == 0)
+                       return true;
+       } else {
+               if (pit() + 1 >= int(text()->paragraphs().size()) &&
+                       row + 1 >= int(pm.rows().size()))
+                       return true;
+       }
+       return false;
+}
+
+
 } // namespace lyx
 
 
@@ -1105,26 +1376,6 @@ bool Cursor::selHandle(bool sel)
 
 namespace lyx {
 
-bool Cursor::isInside(Inset const * p) const
-{
-       for (size_t i = 0; i != depth(); ++i)
-               if (&operator[](i).inset() == p)
-                       return true;
-       return false;
-}
-
-
-void Cursor::leaveInset(Inset const & inset)
-{
-       for (size_t i = 0; i != depth(); ++i) {
-               if (&operator[](i).inset() == &inset) {
-                       resize(i);
-                       return;
-               }
-       }
-}
-
-
 bool Cursor::openable(MathAtom const & t) const
 {
        if (!t->isActive())
@@ -1146,32 +1397,12 @@ bool Cursor::openable(MathAtom const & t) const
 }
 
 
-void Cursor::setScreenPos(int x, int /*y*/)
-{
-       setTargetX(x);
-       //bruteFind(*this, x, y, 0, bv().workWidth(), 0, bv().workHeight());
-}
-
-
-
 void Cursor::plainErase()
 {
        cell().erase(pos());
 }
 
 
-void Cursor::markInsert()
-{
-       insert(char_type(0));
-}
-
-
-void Cursor::markErase()
-{
-       cell().erase(pos());
-}
-
-
 void Cursor::plainInsert(MathAtom const & t)
 {
        cell().insert(pos(), t);
@@ -1182,13 +1413,6 @@ void Cursor::plainInsert(MathAtom const & t)
 }
 
 
-void Cursor::insert(docstring const & str)
-{
-       for (char_type c : str)
-               insert(c);
-}
-
-
 void Cursor::insert(char_type c)
 {
        //lyxerr << "Cursor::insert char '" << c << "'" << endl;
@@ -1202,12 +1426,10 @@ void Cursor::insert(char_type c)
 }
 
 
-void Cursor::insert(MathAtom const & t)
+void Cursor::insert(docstring const & str)
 {
-       //lyxerr << "Cursor::insert MathAtom '" << t << "'" << endl;
-       macroModeClose();
-       cap::selClearOrDel(*this);
-       plainInsert(t);
+       for (char_type c : str)
+               insert(c);
 }
 
 
@@ -1226,8 +1448,32 @@ void Cursor::insert(Inset * inset0)
 }
 
 
+void Cursor::insert(MathAtom const & t)
+{
+       LATTEST(inMathed());
+       //lyxerr << "Cursor::insert MathAtom '" << t << "'" << endl;
+       macroModeClose();
+       cap::selClearOrDel(*this);
+       plainInsert(t);
+}
+
+
+void Cursor::insert(MathData const & ar)
+{
+       LATTEST(inMathed());
+       macroModeClose();
+       if (selection())
+               cap::eraseSelection(*this);
+       cell().insert(pos(), ar);
+       pos() += ar.size();
+       // FIXME audit setBuffer calls
+       inset().setBuffer(bv_->buffer());
+}
+
+
 int Cursor::niceInsert(docstring const & t, Parse::flags f, bool enter)
 {
+       LATTEST(inMathed());
        MathData ar(buffer());
        asArray(t, ar, f);
        if (ar.size() == 1 && (enter || selection()))
@@ -1240,6 +1486,7 @@ int Cursor::niceInsert(docstring const & t, Parse::flags f, bool enter)
 
 void Cursor::niceInsert(MathAtom const & t)
 {
+       LATTEST(inMathed());
        macroModeClose();
        docstring const safe = cap::grabAndEraseSelection(*this);
        plainInsert(t);
@@ -1266,18 +1513,6 @@ void Cursor::niceInsert(MathAtom const & t)
 }
 
 
-void Cursor::insert(MathData const & ar)
-{
-       macroModeClose();
-       if (selection())
-               cap::eraseSelection(*this);
-       cell().insert(pos(), ar);
-       pos() += ar.size();
-       // FIXME audit setBuffer calls
-       inset().setBuffer(bv_->buffer());
-}
-
-
 bool Cursor::backspace(bool const force)
 {
        if (selection()) {
@@ -1401,6 +1636,43 @@ bool Cursor::down()
 }
 
 
+void Cursor::handleNest(MathAtom const & a, int c)
+{
+       //lyxerr << "Cursor::handleNest: " << c << endl;
+       MathAtom t = a;
+       asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(c));
+       insert(t);
+       posBackward();
+       pushBackward(*nextInset());
+}
+
+
+int Cursor::targetX() const
+{
+       if (x_target() != -1)
+               return x_target();
+       int x = 0;
+       int y = 0;
+       getPos(x, y);
+       return x;
+}
+
+
+int Cursor::textTargetOffset() const
+{
+       return textTargetOffset_;
+}
+
+
+void Cursor::setTargetX()
+{
+       int x;
+       int y;
+       getPos(x, y);
+       setTargetX(x);
+}
+
+
 bool Cursor::macroModeClose()
 {
        if (!inMacroMode())
@@ -1477,55 +1749,12 @@ bool Cursor::macroModeClose()
        // finally put the macro argument behind, if needed
        if (macroArg) {
                if (selection.size() > 1 || selection[0]->asScriptInset())
-                       plainInsert(MathAtom(new InsetMathBrace(selection)));
-               else
-                       insert(selection);
-       }
-
-       return true;
-}
-
-
-docstring Cursor::macroName()
-{
-       return inMacroMode() ? activeMacro()->name() : docstring();
-}
-
-
-void Cursor::handleNest(MathAtom const & a, int c)
-{
-       //lyxerr << "Cursor::handleNest: " << c << endl;
-       MathAtom t = a;
-       asArray(cap::grabAndEraseSelection(*this), t.nucleus()->cell(c));
-       insert(t);
-       posBackward();
-       pushBackward(*nextInset());
-}
-
-
-int Cursor::targetX() const
-{
-       if (x_target() != -1)
-               return x_target();
-       int x = 0;
-       int y = 0;
-       getPos(x, y);
-       return x;
-}
-
-
-int Cursor::textTargetOffset() const
-{
-       return textTargetOffset_;
-}
-
-
-void Cursor::setTargetX()
-{
-       int x;
-       int y;
-       getPos(x, y);
-       setTargetX(x);
+                       plainInsert(MathAtom(new InsetMathBrace(selection)));
+               else
+                       insert(selection);
+       }
+
+       return true;
 }
 
 
@@ -1552,6 +1781,12 @@ InsetMathUnknown const * Cursor::activeMacro() const
 }
 
 
+docstring Cursor::macroName()
+{
+       return inMacroMode() ? activeMacro()->name() : docstring();
+}
+
+
 void Cursor::pullArg()
 {
        // FIXME: Look here
@@ -1566,18 +1801,6 @@ void Cursor::pullArg()
 }
 
 
-void Cursor::touch()
-{
-       // FIXME: look here
-#if 0
-       DocIterator::const_iterator it = begin();
-       DocIterator::const_iterator et = end();
-       for ( ; it != et; ++it)
-               it->cell().touch();
-#endif
-}
-
-
 void Cursor::normalize()
 {
        if (idx() > lastidx()) {
@@ -1717,18 +1940,6 @@ bool Cursor::upDownInMath(bool up)
 }
 
 
-InsetMath & Cursor::nextMath()
-{
-       return *nextAtom().nucleus();
-}
-
-
-InsetMath & Cursor::prevMath()
-{
-       return *prevAtom().nucleus();
-}
-
-
 bool Cursor::mathForward(bool word)
 {
        LASSERT(inMathed(), return false);
@@ -1806,29 +2017,6 @@ bool Cursor::mathBackward(bool word)
 }
 
 
-bool Cursor::atFirstOrLastRow(bool up)
-{
-       TextMetrics const & tm = bv_->textMetrics(text());
-       ParagraphMetrics const & pm = tm.parMetrics(pit());
-
-       int row;
-       if (pos() && boundary())
-               row = pm.pos2row(pos() - 1);
-       else
-               row = pm.pos2row(pos());
-
-       if (up) {
-               if (pit() == 0 && row == 0)
-                       return true;
-       } else {
-               if (pit() + 1 >= int(text()->paragraphs().size()) &&
-                               row + 1 >= int(pm.rows().size()))
-                       return true;
-       }
-       return false;
-}
-
-
 bool Cursor::upDownInText(bool up, bool & updateNeeded)
 {
        LASSERT(text(), return false);
@@ -2026,121 +2214,6 @@ void Cursor::handleFont(string const & font)
 }
 
 
-void Cursor::message(docstring const & msg) const
-{
-       disp_.setMessage(msg);
-}
-
-
-void Cursor::errorMessage(docstring const & msg) const
-{
-       disp_.setMessage(msg);
-       disp_.setError(true);
-}
-
-
-namespace {
-
-docstring parbreak(Cursor const * cur)
-{
-       odocstringstream os;
-       os << '\n';
-       // only add blank line if we're not in a ParbreakIsNewline situation
-       if (!cur->inset().getLayout().parbreakIsNewline()
-           && !cur->paragraph().layout().parbreak_is_newline)
-               os << '\n';
-       return os.str();
-}
-
-} // namespace
-
-
-docstring Cursor::selectionAsString(bool with_label) const
-{
-       if (!selection())
-               return docstring();
-
-       if (inMathed())
-               return cap::grabSelection(*this);
-
-       int const label = with_label
-               ? AS_STR_LABEL | AS_STR_INSETS : AS_STR_INSETS;
-
-       idx_type const startidx = selBegin().idx();
-       idx_type const endidx = selEnd().idx();
-       if (startidx != endidx) {
-               // multicell selection
-               InsetTabular * table = inset().asInsetTabular();
-               LASSERT(table, return docstring());
-               return table->asString(startidx, endidx);
-       }
-
-       ParagraphList const & pars = text()->paragraphs();
-
-       pit_type const startpit = selBegin().pit();
-       pit_type const endpit = selEnd().pit();
-       size_t const startpos = selBegin().pos();
-       size_t const endpos = selEnd().pos();
-
-       if (startpit == endpit)
-               return pars[startpit].asString(startpos, endpos, label);
-
-       // First paragraph in selection
-       docstring result = pars[startpit].
-               asString(startpos, pars[startpit].size(), label)
-               + parbreak(this);
-
-       // The paragraphs in between (if any)
-       for (pit_type pit = startpit + 1; pit != endpit; ++pit) {
-               Paragraph const & par = pars[pit];
-               result += par.asString(0, par.size(), label)
-                       + parbreak(this);
-       }
-
-       // Last paragraph in selection
-       result += pars[endpit].asString(0, endpos, label);
-
-       return result;
-}
-
-
-docstring Cursor::currentState(bool devel_mode) const
-{
-       if (inMathed()) {
-               odocstringstream os;
-               info(os, devel_mode);
-               return os.str();
-       }
-
-       if (inTexted())
-               return text()->currentState(*this, devel_mode);
-
-       return docstring();
-}
-
-
-docstring Cursor::getPossibleLabel() const
-{
-       return inMathed() ? from_ascii("eq:") : text()->getPossibleLabel(*this);
-}
-
-
-Encoding const * Cursor::getEncoding() const
-{
-       if (empty())
-               return 0;
-       BufferParams const & bp = bv().buffer().params();
-       if (bp.useNonTeXFonts)
-               return encodings.fromLyXName("utf8-plain");
-
-       CursorSlice const & sl = innerTextSlice();
-       Text const & text = *sl.text();
-       Font font = text.getPar(sl.pit()).getFont(bp, sl.pos(),
-                                                 text.outerFont(sl.pit()));
-       return font.language()->encoding();
-}
-
-
 void Cursor::undispatched() const
 {
        disp_.dispatched(false);
@@ -2218,29 +2291,11 @@ Font Cursor::getFont() const
 }
 
 
-bool Cursor::fixIfBroken()
-{
-       bool const broken_cursor = DocIterator::fixIfBroken();
-       bool const broken_anchor = anchor_.fixIfBroken();
-
-       if (broken_cursor || broken_anchor) {
-               clearNewWordPosition();
-               clearSelection();
-               return true;
-       }
-       return false;
-}
-
-
 void Cursor::sanitize()
 {
-       setBuffer(&bv_->buffer());
-       DocIterator::sanitize();
+       setBuffer(buffer());
+       CursorData::sanitize();
        new_word_.sanitize();
-       if (selection())
-               anchor_.sanitize();
-       else
-               resetAnchor();
 }
 
 
@@ -2327,92 +2382,6 @@ void Cursor::setCurrentFont()
 }
 
 
-bool Cursor::textUndo()
-{
-       if (!buffer()->undo().textUndo(*this))
-               return false;
-       sanitize();
-       return true;
-}
-
-
-bool Cursor::textRedo()
-{
-       if (!buffer()->undo().textRedo(*this))
-               return false;
-       sanitize();
-       return true;
-}
-
-
-void Cursor::finishUndo() const
-{
-       buffer()->undo().finishUndo();
-}
-
-
-void Cursor::beginUndoGroup() const
-{
-       buffer()->undo().beginUndoGroup(*this);
-}
-
-
-void Cursor::endUndoGroup() const
-{
-       buffer()->undo().endUndoGroup(*this);
-}
-
-
-void Cursor::recordUndo(pit_type from, pit_type to) const
-{
-       buffer()->undo().recordUndo(*this, from, to);
-}
-
-
-void Cursor::recordUndo(pit_type from) const
-{
-       buffer()->undo().recordUndo(*this, from, pit());
-}
-
-
-void Cursor::recordUndo(UndoKind kind) const
-{
-       buffer()->undo().recordUndo(*this, kind);
-}
-
-
-void Cursor::recordUndoInset(Inset const * in) const
-{
-       buffer()->undo().recordUndoInset(*this, in);
-}
-
-
-void Cursor::recordUndoFullBuffer() const
-{
-       buffer()->undo().recordUndoFullBuffer(*this);
-}
-
-
-void Cursor::recordUndoBufferParams() const
-{
-       buffer()->undo().recordUndoBufferParams(*this);
-}
-
-
-void Cursor::recordUndoSelection() const
-{
-       if (inMathed()) {
-               if (cap::multipleCellsSelected(*this))
-                       recordUndoInset();
-               else
-                       recordUndo();
-       } else {
-               buffer()->undo().recordUndo(*this,
-                       selBegin().pit(), selEnd().pit());
-       }
-}
-
-
 void Cursor::checkBufferStructure()
 {
        Buffer const * master = buffer()->masterBuffer();
@@ -2430,23 +2399,6 @@ void Cursor::checkBufferStructure()
 }
 
 
-bool Cursor::confirmDeletion(bool const before) const
-{
-       if (!selection()) {
-               if (Inset const * inset = before ? prevInset() : nextInset())
-                       return inset->confirmDeletion();
-       } else {
-               DocIterator dit = selectionBegin();
-               CursorSlice const end = selectionEnd().top();
-               for (; dit.top() < end; dit.top().forwardPos())
-                       if (Inset const * inset = dit.nextInset())
-                               if (inset->confirmDeletion())
-                                       return true;
-       }
-       return false;
-}
-
-
 void Cursor::moveToClosestEdge(int const x, bool const edit)
 {
        if (Inset const * inset = nextInset()) {
index 4c9d41d0cfe41ba4bbddb528725c473eb211fd29..6c5e5e67838bf51709bdbd0a5f7392021f9a10c2 100644 (file)
@@ -72,7 +72,6 @@ class Row;
 
 // these should go
 class InsetMathUnknown;
-class Encoding;
 
 /**
  * This class describes the position of a cursor within a document,
@@ -93,7 +92,136 @@ public:
        friend std::ostream & operator<<(std::ostream & os, CursorData const & cur);
        friend LyXErr & operator<<(LyXErr & os, CursorData const & cur);
 
+       /// reset cursor bottom to the beginning of the top inset
+       // (sort of 'chroot' environment...)
+       void reset();
+       /// sets cursor part
+       /// this (intentionally) does neither touch anchor nor selection status
+       void setCursor(DocIterator const & it);
+       /// set the cursor to dit normalised against the anchor, and set selection.
+       void setCursorSelectionTo(DocIterator dit);
+       /// sets the cursor to the normalized selection anchor
+       void setCursorToAnchor();
+
+       //
+       // selection
+       //
+       /// selection active?
+       bool selection() const { return selection_; }
+       /// set selection; this is lower level than (set|clear)Selection
+       void selection(bool sel) { selection_ = sel; }
+       /// do we have a multicell selection?
+       bool selIsMultiCell() const
+               { return selection_ && selBegin().idx() != selEnd().idx(); }
+       /// do we have a multiline selection?
+       bool selIsMultiLine() const
+               { return selection_ && selBegin().pit() != selEnd().pit(); }
+       ///
+       void setWordSelection(bool set) { word_selection_ = set; }
+       ///
+       bool wordSelection() { return word_selection_; }
+       /// did we place the anchor?
+       bool mark() const { return mark_; }
+       /// did we place the anchor?
+       void setMark(bool mark) { mark_ = mark; }
+       ///
+       void setSelection();
+       /// set selection at given position
+       void setSelection(DocIterator const & where, int n);
+       ///
+       void clearSelection();
+
+       /// access to normalized selection anchor
+       CursorSlice normalAnchor() const;
+       /// access to real selection anchor
+       DocIterator const & realAnchor() const { return anchor_; }
+       DocIterator & realAnchor() { return anchor_; }
+       /// sets anchor to cursor position
+       void resetAnchor();
+       /// access to owning BufferView
+
+       /// access start of selection
+       CursorSlice selBegin() const;
+       /// access end of selection
+       CursorSlice selEnd() const;
+       /// access start of selection
+       DocIterator selectionBegin() const;
+       /// access end of selection
+       DocIterator selectionEnd() const;
+
+       ///
+       docstring selectionAsString(bool with_label) const;
+       /// get some interesting description of top position
+       void info(odocstream & os, bool devel_mode) const;
+       ///
+       docstring currentState(bool devel_mode) const;
+
+       /// auto-correct mode
+       bool autocorrect() const { return autocorrect_; }
+       /// auto-correct mode
+       bool & autocorrect() { return autocorrect_; }
+
+       /// fix cursor in circumstances that should never happen.
+       /// \retval true if a fix occurred.
+       bool fixIfBroken();
+       /// Repopulate the slices insets from bottom to top. Useful
+       /// for stable iterators or Undo data.
+       void sanitize();
+       ///
+       bool isInside(Inset const *) const;
+       /// make sure we are outside of given inset
+       void leaveInset(Inset const & inset);
+
+       ///
+       bool textUndo();
+       ///
+       bool textRedo();
+
+       /// makes sure the next operation will be stored
+       void finishUndo() const;
+       /// open a new group of undo operations. Groups can be nested.
+       void beginUndoGroup() const;
+       /// end the current undo group
+       void endUndoGroup() const;
+
+       /// The general case: prepare undo for an arbitrary range.
+       void recordUndo(pit_type from, pit_type to) const;
+       /// Convenience: prepare undo for the range between 'from' and cursor.
+       void recordUndo(pit_type from) const;
+       /// Convenience: prepare undo for the single paragraph or cell
+       /// containing the cursor
+       void recordUndo(UndoKind kind = ATOMIC_UNDO) const;
+       /// Convenience: prepare undo for the inset containing the cursor
+       void recordUndoInset(Inset const * inset = 0) const;
+       /// Convenience: prepare undo for the whole buffer
+       void recordUndoFullBuffer() const;
+       /// Convenience: prepare undo for buffer parameters
+       void recordUndoBufferParams() const;
+       /// Convenience: prepare undo for the selected paragraphs or cells
+       void recordUndoSelection() const;
+
+       /// hook for text input to maintain the "new born word"
+       void markNewWordPosition();
+       /// The position of the new born word
+       /// As the user is entering a word without leaving it
+       /// the result is not empty. When not in text mode
+       /// and after leaving the word the result is empty.
+       DocIterator newWord() const { return new_word_; }
+
+       /// are we in math mode (2), text mode (1) or unsure (0)?
+       int currentMode();
+
+       /// Return true if the next or previous inset has confirmDeletion depending
+       /// on the boolean before. If there is a selection, return true if at least
+       /// one inset in the selection has confirmDeletion.
+       bool confirmDeletion(bool before = false) const;
+
 protected:
+       /// validate the "new born word" position
+       void checkNewWordPosition();
+       /// clear the "new born word" position
+       void clearNewWordPosition();
+
        /// the anchor position
        DocIterator anchor_;
        /// do we have a selection?
@@ -112,13 +240,13 @@ public:
 
 protected:
 
+       /// the start of the new born word
+       DocIterator new_word_;
        //
        // math specific stuff that could be promoted to "global" later
        //
        /// do we allow autocorrection
        bool autocorrect_;
-       /// are we entering a macro name?
-       bool macromode_;
 };
 
 
@@ -129,12 +257,6 @@ public:
        /// create the cursor of a BufferView
        explicit Cursor(BufferView & bv);
 
-       /// returns true if we made a decision
-       bool getStatus(FuncRequest const & cmd, FuncStatus & flag) const;
-       /// dispatch from innermost inset upwards
-       void dispatch(FuncRequest const & cmd);
-       /// get the resut of the last dispatch
-       DispatchResult const & result() const;
        /// add a new cursor slice
        void push(Inset & inset);
        /// add a new cursor slice, place cursor at front (move backwards)
@@ -145,56 +267,23 @@ public:
        bool popBackward();
        /// pop one slice off the cursor stack and go forward
        bool popForward();
-       /// make sure we are outside of given inset
-       void leaveInset(Inset const & inset);
        /// set the cursor data
        void setCursorData(CursorData const & data);
-       /// sets cursor part
-       /// this (intentionally) does neither touch anchor nor selection status
-       void setCursor(DocIterator const & it);
-       /// set the cursor to dit normalised against the anchor, and set selection.
-       void setCursorSelectionTo(DocIterator dit);
-       /// sets the cursor to the normalized selection anchor
-       void setCursorToAnchor();
+
+       /// returns true if we made a decision
+       bool getStatus(FuncRequest const & cmd, FuncStatus & flag) const;
+       /// dispatch from innermost inset upwards
+       void dispatch(FuncRequest const & cmd);
+       /// display a message
+       void message(docstring const & msg) const;
+       /// display an error message
+       void errorMessage(docstring const & msg) const;
+       /// get the resut of the last dispatch
+       DispatchResult const & result() const;
 
        ///
        void setCurrentFont();
 
-       //
-       // selection
-       //
-       /// selection active?
-       bool selection() const { return selection_; }
-       /// set selection; this is lower level than (set|clear)Selection
-       void selection(bool sel) { selection_ = sel; }
-       /// do we have a multicell selection?
-       bool selIsMultiCell() const
-               { return selection_ && selBegin().idx() != selEnd().idx(); }
-       /// do we have a multiline selection?
-       bool selIsMultiLine() const
-               { return selection_ && selBegin().pit() != selEnd().pit(); }
-       ///
-       void setWordSelection(bool set) { word_selection_ = set; }
-       ///
-       bool wordSelection() { return word_selection_; }
-       /// did we place the anchor?
-       bool mark() const { return mark_; }
-       /// did we place the anchor?
-       void setMark(bool mark) { mark_ = mark; }
-       ///
-       void setSelection();
-       /// set selection at given position
-       void setSelection(DocIterator const & where, int n);
-       ///
-       void clearSelection();
-       /// access start of selection
-       CursorSlice selBegin() const;
-       /// access end of selection
-       CursorSlice selEnd() const;
-       /// access start of selection
-       DocIterator selectionBegin() const;
-       /// access end of selection
-       DocIterator selectionEnd() const;
        /**
         * Update the selection status and save permanent
         * selection if needed.
@@ -202,19 +291,6 @@ public:
         * @return whether the selection status has changed
         */
        bool selHandle(bool selecting);
-       ///
-       docstring selectionAsString(bool with_label) const;
-       ///
-       docstring currentState(bool devel_mode) const;
-
-       /// auto-correct mode
-       bool autocorrect() const { return autocorrect_; }
-       /// auto-correct mode
-       bool & autocorrect() { return autocorrect_; }
-       /// are we entering a macro name?
-       bool macromode() const { return macromode_; }
-       /// are we entering a macro name?
-       bool & macromode() { return macromode_; }
 
        /// returns x,y position
        void getPos(int & x, int & y) const;
@@ -265,12 +341,28 @@ public:
        /// Should interpretation of the arrow keys be reversed?
        bool reverseDirectionNeeded() const;
 
-       /// insert an inset
-       void insert(Inset *);
+       ///
+       ///  Insertion (mathed and texted)
+       ///
        /// insert a single char
        void insert(char_type c);
        /// insert a string
        void insert(docstring const & str);
+       /// insert an inset
+       void insert(Inset *);
+       ///
+       ///  Insertion (mathed only)
+       ///
+       /// insert a math atom
+       void insert(MathAtom const &);
+       /// insert a string of atoms
+       void insert(MathData const &);
+       /// Like insert, but moves the selection inside the inset if possible
+       void niceInsert(MathAtom const & at);
+       /// return the number of inserted array items
+       /// FIXME: document properly
+       int niceInsert(docstring const & str, Parse::flags f = Parse::NORMAL,
+                       bool enter = true);
 
        /// FIXME: rename to something sensible showing difference to x_target()
        /// in pixels from left of screen, set to current position if unset
@@ -288,24 +380,11 @@ public:
        /// distance between actual and targeted position during last up/down in text
        int textTargetOffset() const;
 
-       /// access to normalized selection anchor
-       CursorSlice normalAnchor() const;
-       /// access to real selection anchor
-       DocIterator const & realAnchor() const { return anchor_; }
-       DocIterator & realAnchor() { return anchor_; }
-       /// sets anchor to cursor position
-       void resetAnchor();
-       /// access to owning BufferView
        BufferView & bv() const;
-       /// get some interesting description of top position
-       void info(odocstream & os, bool devel_mode) const;
-       /// are we in math mode (2), text mode (1) or unsure (0)?
-       int currentMode();
        /// reset cursor bottom to the beginning of the top inset
        // (sort of 'chroot' environment...)
        void reset();
-       /// for spellchecking
-       void replaceWord(std::string const & replacestring);
+
        /**
         * the event was not (yet) dispatched.
         *
@@ -337,72 +416,23 @@ public:
         * Not using noScreenUpdate() should never be wrong.
         */
        void noScreenUpdate() const;
-       /// fix cursor in circumstances that should never happen.
-       /// \retval true if a fix occurred.
-       bool fixIfBroken();
+
        /// Repopulate the slices insets from bottom to top. Useful
        /// for stable iterators or Undo data.
        void sanitize();
 
-       ///
-       bool textUndo();
-       ///
-       bool textRedo();
-
-       /// makes sure the next operation will be stored
-       void finishUndo() const;
-
-       /// open a new group of undo operations. Groups can be nested.
-       void beginUndoGroup() const;
-
-       /// end the current undo group
-       void endUndoGroup() const;
-
-       /// The general case: prepare undo for an arbitrary range.
-       void recordUndo(pit_type from, pit_type to) const;
-
-       /// Convenience: prepare undo for the range between 'from' and cursor.
-       void recordUndo(pit_type from) const;
-
-       /// Convenience: prepare undo for the single paragraph or cell
-       /// containing the cursor
-       void recordUndo(UndoKind kind = ATOMIC_UNDO) const;
-
-       /// Convenience: prepare undo for the inset containing the cursor
-       void recordUndoInset(Inset const * inset = 0) const;
-
-       /// Convenience: prepare undo for the whole buffer
-       void recordUndoFullBuffer() const;
-
-       /// Convenience: prepare undo for buffer parameters
-       void recordUndoBufferParams() const;
-
-       /// Convenience: prepare undo for the selected paragraphs or cells
-       void recordUndoSelection() const;
-
        ///
        void checkBufferStructure();
 
-       /// hook for text input to maintain the "new born word"
-       void markNewWordPosition();
-
-       /// The position of the new born word
-       /// As the user is entering a word without leaving it
-       /// the result is not empty. When not in text mode
-       /// and after leaving the word the result is empty.
-       DocIterator newWord() const { return new_word_; }
-
-       /// Return true if the next or previous inset has confirmDeletion depending
-       /// on the boolean before. If there is a selection, return true if at least
-       /// one inset in the selection has confirmDeletion.
-       bool confirmDeletion(bool before = false) const;
-
        /// Determine if x falls to the left or to the side of the middle of the
        /// inset, and advance the cursor to match this position. If edit is true,
        /// keep the cursor in front of the inset if it matter for dialogs.
        /// Note: it does not handle RTL text yet, and is only used in math for now.
        void moveToClosestEdge(int x, bool edit = false);
 
+       /// whether the cursor is either at the first or last row
+       bool atFirstOrLastRow(bool up);
+
 public:
 //private:
 
@@ -411,12 +441,6 @@ public:
        ///
        void saveBeforeDispatchPosXY();
 
-private:
-       /// validate the "new born word" position
-       void checkNewWordPosition();
-       /// clear the "new born word" position
-       void clearNewWordPosition();
-
 private:
        ///
        BufferView * bv_;
@@ -437,8 +461,6 @@ private:
        int x_target_;
        /// if a x_target cannot be hit exactly in a text, put the difference here
        int textTargetOffset_;
-       /// the start of the new born word
-       DocIterator new_word_;
        /// position before dispatch started
        DocIterator beforeDispatchCursor_;
        /// cursor screen coordinates before dispatch started
@@ -454,10 +476,6 @@ private:
 ///////////////////////////////////////////////////////////////////
 
 public:
-       ///
-       void insert(MathAtom const &);
-       ///
-       void insert(MathData const &);
        /// return false for empty math insets
        /// Use force to skip the confirmDeletion check.
        bool erase(bool force = false);
@@ -469,8 +487,6 @@ public:
        /// move the cursor up by sending an internal LFUN_DOWN,
        /// return true if fullscreen update is needed
        bool down();
-       /// whether the cursor is either at the first or last row
-       bool atFirstOrLastRow(bool up);
        /// move up/down in a text inset, called for LFUN_UP/DOWN,
        /// return true if successful, updateNeeded set to true if fullscreen
        /// update is needed, otherwise it's not touched
@@ -478,10 +494,6 @@ public:
        /// move up/down in math or any non text inset, call for LFUN_UP/DOWN
        /// return true if successful
        bool upDownInMath(bool up);
-       ///
-       InsetMath & nextMath();
-       ///
-       InsetMath & prevMath();
        /// move forward in math. word: whether to skip a whole "word" (insets with
        /// the same mathclass)
        bool mathForward(bool word);
@@ -491,18 +503,9 @@ public:
        void plainErase();
        ///
        void plainInsert(MathAtom const & at);
-       ///
-       void niceInsert(MathAtom const & at);
-       /// return the number of inserted array items
-       int niceInsert(docstring const & str, Parse::flags f = Parse::NORMAL,
-                       bool enter = true);
 
-       /// in pixels from top of screen
-       void setScreenPos(int x, int y);
-       /// current offset in the top cell
-
-       /// interpret name a name of a macro. Returns true if
-       /// something got inserted.
+       /// interpret name of a macro. Returns true if something got
+       /// inserted.
        bool macroModeClose();
        /// are we currently typing the name of a macro?
        bool inMacroMode() const;
@@ -510,42 +513,25 @@ public:
        InsetMathUnknown * activeMacro();
        /// get access to the macro we are currently typing
        InsetMathUnknown const * activeMacro() const;
+       /// the name of the macro we are currently inputting
+       docstring macroName();
+
 
        /// replace selected stuff with at, placing the former
        // selection in given cell of atom
        void handleNest(MathAtom const & at, int cell = 0);
-       ///
-       bool isInside(Inset const *) const;
 
        /// make sure cursor position is valid
        /// FIXME: It does a subset of fixIfBroken. Maybe merge them?
        void normalize();
-       /// mark current cursor trace for redraw
-       void touch();
 
-       /// hack for reveal codes
-       void markInsert();
-       void markErase();
        /// injects content of a cell into parent
        void pullArg();
        /// split font inset etc
        void handleFont(std::string const & font);
 
-       /// display a message
-       void message(docstring const & msg) const;
-       /// display an error message
-       void errorMessage(docstring const & msg) const;
-       ///
-       docstring getPossibleLabel() const;
-
-       /// the name of the macro we are currently inputting
-       docstring macroName();
-       /// where in the curent cell does the macro name start?
-       int macroNamePos();
        /// can we enter the inset?
        bool openable(MathAtom const &) const;
-       ///
-       Encoding const * getEncoding() const;
        /// font at cursor position
        Font getFont() const;
 };
index daa647591e66b0f46105eae69d62db919b559154..6d9bf101f40a8cf918b486ce9a18a03cd896d0f9 100644 (file)
@@ -690,7 +690,7 @@ docstring grabAndEraseSelection(Cursor & cur)
 }
 
 
-bool reduceSelectionToOneCell(Cursor & cur)
+bool reduceSelectionToOneCell(CursorData & cur)
 {
        if (!cur.selection() || !cur.inMathed())
                return false;
@@ -712,7 +712,7 @@ bool reduceSelectionToOneCell(Cursor & cur)
 }
 
 
-bool multipleCellsSelected(Cursor const & cur)
+bool multipleCellsSelected(CursorData const & cur)
 {
        if (!cur.selection() || !cur.inMathed())
                return false;
@@ -969,7 +969,7 @@ void copyInset(Cursor const & cur, Inset * inset, docstring const & plaintext)
 
 namespace {
 
-void copySelectionToStack(Cursor const & cur, CutStack & cutstack)
+void copySelectionToStack(CursorData const & cur, CutStack & cutstack)
 {
        // this doesn't make sense, if there is no selection
        if (!cur.selection())
@@ -1369,7 +1369,7 @@ void selClearOrDel(Cursor & cur)
 }
 
 
-docstring grabSelection(Cursor const & cur)
+docstring grabSelection(CursorData const & cur)
 {
        if (!cur.selection())
                return docstring();
index 43a89c33d05c521aca67a9998c16a8dcf9886388..66df6b590406973bdbbe52bf40406651566cbb42 100644 (file)
@@ -127,7 +127,7 @@ void switchBetweenClasses(DocumentClassConstPtr c1,
 
 /// Get the current selection as a string. Does not change the selection.
 /// Does only work if the whole selection is in mathed.
-docstring grabSelection(Cursor const & cur);
+docstring grabSelection(CursorData const & cur);
 /// Erase the current selection.
 /// Does not handle undo. Does only work if the whole selection is in mathed.
 /// Calls saveSelection.
@@ -136,9 +136,9 @@ void eraseSelection(Cursor & cur);
 /// cells, the cursor is moved the end of the current cell and the anchor to the
 /// start. If the selection is inside only one cell, nothing is done. Return
 /// true if the selection now does not span multiple cells anymore.
-bool reduceSelectionToOneCell(Cursor & cur);
+bool reduceSelectionToOneCell(CursorData & cur);
 /// Returns true if multiple cells are selected in mathed.
-bool multipleCellsSelected(Cursor const & cur);
+bool multipleCellsSelected(CursorData const & cur);
 /// Erase the selection and return it as a string.
 /// Does not handle undo. Does only work if the whole selection is in mathed.
 docstring grabAndEraseSelection(Cursor & cur);
index 38f2393224b1e37b1839537f12ea6b85008ec8d8..58b91dff3620f43a258b2a84daa056413c1da3d9 100644 (file)
 #include "DocIterator.h"
 
 #include "Buffer.h"
+#include "BufferParams.h"
+#include "Encoding.h"
+#include "Font.h"
 #include "InsetList.h"
+#include "Language.h"
 #include "Paragraph.h"
-#include "LyXRC.h"
 #include "Text.h"
 
 #include "mathed/MathData.h"
@@ -156,6 +159,18 @@ Inset * DocIterator::realInset() const
 }
 
 
+InsetMath & DocIterator::nextMath()
+{
+       return *nextAtom().nucleus();
+}
+
+
+InsetMath & DocIterator::prevMath()
+{
+       return *prevAtom().nucleus();
+}
+
+
 MathAtom & DocIterator::prevAtom() const
 {
        LASSERT(!empty(), /**/);
@@ -688,6 +703,28 @@ void DocIterator::append(DocIterator::idx_type idx, pos_type pos)
 }
 
 
+docstring DocIterator::getPossibleLabel() const
+{
+       return inMathed() ? from_ascii("eq:") : text()->getPossibleLabel(*this);
+}
+
+
+Encoding const * DocIterator::getEncoding() const
+{
+       if (empty())
+               return 0;
+       BufferParams const & bp = buffer()->params();
+       if (bp.useNonTeXFonts)
+               return encodings.fromLyXName("utf8-plain");
+
+       CursorSlice const & sl = innerTextSlice();
+       Text const & text = *sl.text();
+       Font font = text.getPar(sl.pit()).getFont(bp, sl.pos(),
+                                                 text.outerFont(sl.pit()));
+       return font.language()->encoding();
+}
+
+
 ostream & operator<<(ostream & os, DocIterator const & dit)
 {
        for (size_t i = 0, n = dit.depth(); i != n; ++i)
index 4aff05cd0b62e43a5cd27bb4a241f7d5bdfcd568..9582ea30f95b6e4fdd6fe9913c7c7e5c4d771ea7 100644 (file)
 namespace lyx {
 
 class DocIterator;
+class Encoding;
+class FontSpan;
+class InsetIterator;
 class LyXErr;
 class MathAtom;
 class Paragraph;
 class Text;
-class InsetIterator;
-class FontSpan;
 
 DocIterator doc_iterator_begin(Buffer const * buf, Inset const * inset = 0);
 DocIterator doc_iterator_end(Buffer const * buf, Inset const * inset = 0);
@@ -149,6 +150,10 @@ public:
        //
        /// return the mathed cell this cursor is in
        MathData & cell() const;
+       ///
+       InsetMath & nextMath();
+       ///
+       InsetMath & prevMath();
        /// the mathatom left of the cursor
        MathAtom & prevAtom() const;
        /// the mathatom right of the cursor
@@ -257,6 +262,11 @@ public:
        /// push one CursorSlice on top and set its index and position
        void append(idx_type idx, pos_type pos);
 
+       ///
+       docstring getPossibleLabel() const;
+
+       ///
+       Encoding const * getEncoding() const;
 private:
        friend class InsetIterator;
        friend DocIterator doc_iterator_begin(Buffer const * buf, Inset const * inset);
index e1c37faf3ab2700376d70f2d2f2e0ca2b4e3fc8a..84f7857678f63144e564407bdbae52ec713a688a 100644 (file)
@@ -1896,7 +1896,7 @@ bool Text::read(Lexer & lex,
 
 
 // Returns the current font and depth as a message.
-docstring Text::currentState(Cursor const & cur, bool devel_mode) const
+docstring Text::currentState(CursorData const & cur, bool devel_mode) const
 {
        LBUFERR(this == cur.text());
        Buffer & buf = *cur.buffer();
@@ -1973,7 +1973,7 @@ docstring Text::currentState(Cursor const & cur, bool devel_mode) const
 }
 
 
-docstring Text::getPossibleLabel(Cursor const & cur) const
+docstring Text::getPossibleLabel(DocIterator const & cur) const
 {
        pit_type pit = cur.pit();
 
index 8621e883a797523e3b2964ae74efe833eddeab1d..4fc86ff72a2e15a1230b6e7919b8868380f73872 100644 (file)
@@ -24,6 +24,7 @@ class BufferParams;
 class BufferView;
 class CompletionList;
 class Cursor;
+class CursorData;
 class CursorSlice;
 class DocIterator;
 class ErrorList;
@@ -158,7 +159,7 @@ public:
        Paragraph & getPar(pit_type pit) { return pars_[pit]; }
        // Returns the current font and depth as a message.
        // When \param devel_mode is true, add more precise information
-       docstring currentState(Cursor const & cur, bool devel_mode) const;
+       docstring currentState(CursorData const & cur, bool devel_mode) const;
 
        /** Find the word under \c from in the relative location
         *  defined by \c word_location.
@@ -280,7 +281,7 @@ public:
        double spacing(Paragraph const & par) const;
        /// make a suggestion for a label
        /// FIXME: replace Cursor with DocIterator.
-       docstring getPossibleLabel(Cursor const & cur) const;
+       docstring getPossibleLabel(DocIterator const & cur) const;
        /// is this paragraph right-to-left?
        bool isRTL(Paragraph const & par) const;
 
index 94182a73269fa5585adf4cce8de06e6d5d149b59..9c63adeb136d3264872a93e2abd3c1479e6460a5 100644 (file)
@@ -1159,7 +1159,7 @@ void unifyGraphicsGroups(Buffer & b, string const & argument)
                        InsetGraphics & ins = static_cast<InsetGraphics &>(*it);
                        InsetGraphicsParams inspar = ins.getParams();
                        if (params.groupId == inspar.groupId) {
-                               b.undo().recordUndo(CursorData(it));
+                               CursorData(it).recordUndo();
                                params.filename = inspar.filename;
                                ins.setParams(params);
                        }
index 789a774ac6b993ecc2114cf9091c3ad56ecdb913..b9e8f103839f99702ed472d1631ed9ec53021286 100644 (file)
@@ -115,7 +115,7 @@ void InsetLabel::updateReferences(docstring const & old_label,
        Buffer::References::const_iterator end = refs.end();
        for (; it != end; ++it) {
                ugh.resetBuffer(it->second.buffer());
-               it->second.buffer()->undo().recordUndo(CursorData(it->second));
+               CursorData(it->second).recordUndo();
                if (it->first->lyxCode() == MATH_REF_CODE) {
                        InsetMathRef * mi = it->first->asInsetMath()->asRefInset();
                        mi->changeTarget(new_label);
index 78175f3f70d524f1145829c77afc17dbe2f07e05..892b9df44be7c10ea9c4b6871fff2f775dfc0e0b 100644 (file)
@@ -2243,42 +2243,6 @@ void InsetMathHull::edit(Cursor & cur, bool front, EntryDirection entry_from)
 }
 
 
-void InsetMathHull::revealCodes(Cursor & cur) const
-{
-       if (!cur.inMathed())
-               return;
-       odocstringstream os;
-       cur.info(os, false);
-       cur.message(os.str());
-/*
-       // write something to the minibuffer
-       // translate to latex
-       cur.markInsert(bv);
-       ostringstream os;
-       write(os);
-       string str = os.str();
-       cur.markErase(bv);
-       string::size_type pos = 0;
-       string res;
-       for (string::iterator it = str.begin(); it != str.end(); ++it) {
-               if (*it == '\n')
-                       res += ' ';
-               else if (*it == '\0') {
-                       res += "  -X-  ";
-                       pos = it - str.begin();
-               }
-               else
-                       res += *it;
-       }
-       if (pos > 30)
-               res = res.substr(pos - 30);
-       if (res.size() > 60)
-               res = res.substr(0, 60);
-       cur.message(res);
-*/
-}
-
-
 /////////////////////////////////////////////////////////////////////
 
 
index 183b851ba515450114ae5c6396e1c148fce1c434..7f1b916702e033d42900dd1c37f5cc182a9aa3d5 100644 (file)
@@ -284,8 +284,6 @@ public:
        ///
        virtual void mutateToText();
        ///
-       virtual void revealCodes(Cursor & cur) const;
-       ///
        bool editable() const { return true; }
        ///
        void edit(Cursor & cur, bool front,
index 8d7c110a4ab3c25717827f84f779bfbef73b2e03..803c9465511eee55bfbc03415d7249e9d383c7b4 100644 (file)
@@ -896,7 +896,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                int y = 0;
                istringstream is(to_utf8(cmd.argument()));
                is >> x >> y;
-               cur.setScreenPos(x, y);
+               cur.setTargetX(x);
                break;
        }
 
index beb1299b9afa565a3f63a1cb9f3d00683fd87218..d242a86f72c2d228c16a6a98b399e9457d4251a9 100644 (file)
@@ -212,11 +212,6 @@ bool MathData::contains(MathData const & ar) const
 }
 
 
-void MathData::touch() const
-{
-}
-
-
 bool MathData::addToMathRow(MathRow & mrow, MetricsInfo & mi) const
 {
        bool has_contents = false;
index 2f6ab22acd3967d76fad2b55b1405422343251a6..f8c35ccab31097187458a66b25db98d34ba2b93d 100644 (file)
@@ -137,8 +137,6 @@ public:
        void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
        /// redraw cell using cache metrics information
        void drawT(TextPainter & pi, int x, int y) const;
-       /// mark cell for re-drawing
-       void touch() const;
        /// approximate the math class of the data
        MathClass mathClass() const;