]> git.lyx.org Git - features.git/blobdiff - src/cursor.C
Part of IU.
[features.git] / src / cursor.C
index 47b1d22152c6a37e369dd97716dcf5b00a666034..bc541b4472eb5e1a2009f6c5ff5d33c610e85998 100644 (file)
@@ -27,6 +27,7 @@
 #include "insets/insettext.h"
 
 #include "mathed/math_data.h"
+#include "mathed/math_inset.h"
 
 #include <boost/assert.hpp>
 
@@ -34,22 +35,10 @@ using std::vector;
 using std::endl;
 
 
-std::ostream & operator<<(std::ostream & os, LCursor const & cur)
-{
-       os << "\n";
-       for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i)
-               os << "   (" << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n";
-       return os;
-}
-
-
-LCursor::LCursor()
-       : cursor_(1), anchor_(1), bv_(0)
-{}
-
-
 LCursor::LCursor(BufferView & bv)
-       : cursor_(1), anchor_(1), bv_(&bv)
+       : cursor_(1), anchor_(1), bv_(&bv), current_(0),
+         cached_y_(0), x_target_(-1),
+         selection_(false), mark_(false)
 {}
 
 
@@ -59,9 +48,10 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
        FuncRequest cmd = cmd0;
 
        for (int i = cursor_.size() - 1; i >= 1; --i) {
+               current_ = i;
                CursorSlice const & citem = cursor_[i];
                lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
-               DispatchResult res = citem.inset_->dispatch(*bv_, cmd);
+               DispatchResult res = inset()->dispatch(*this, cmd);
                if (res.dispatched()) {
                        lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
                        return DispatchResult(true, true);
@@ -90,7 +80,7 @@ DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
                }
        }
        lyxerr << "trying to dispatch to main text " << bv_->text() << endl;
-       DispatchResult res = bv_->text()->dispatch(*bv_, cmd);
+       DispatchResult res = bv_->text()->dispatch(*this, cmd);
        lyxerr << "   result: " << res.val() << endl;
 
        if (!res.dispatched()) {
@@ -109,43 +99,53 @@ void LCursor::push(InsetBase * inset)
        lyxerr << "LCursor::push()  inset: " << inset << endl;
        cursor_.push_back(CursorSlice(inset));
        anchor_.push_back(CursorSlice(inset));
+       ++current_;
        updatePos();
 }
 
 
-
 void LCursor::pop(int depth)
 {
-       lyxerr << "LCursor::pop() to " << depth << endl;
-       while (cursor_.size() > 1 && depth < cursor_.size()) {
-               lyxerr <<   "LCursor::pop a level " << endl;
-               cursor_.pop_back();
-               anchor_.pop_back();
-       }
+       lyxerr << "LCursor::pop() to depth " << depth << endl;
+       while (cursor_.size() > depth)
+               pop();
 }
 
 
 void LCursor::pop()
 {
-       lyxerr << "LCursor::pop() " << endl;
+       lyxerr << "LCursor::pop() a level" << endl;
        //BOOST_ASSERT(!cursor_.empty());
        if (cursor_.size() <= 1)
                lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
        else {
                cursor_.pop_back();
                anchor_.pop_back();
+               current_ = cursor_.size() - 1;
        }
+       lyxerr << "LCursor::pop() current now: " << current_ << endl;
+}
+
+
+CursorSlice & LCursor::current()
+{
+       //lyxerr << "accessing cursor slice " << current_
+       //      << ": " << cursor_[current_] << endl;
+       return cursor_[current_];
 }
 
 
-UpdatableInset * LCursor::innerInset() const
+CursorSlice const & LCursor::current() const
 {
-       return cursor_.size() <= 1 ? 0 : cursor_.back().asUpdatableInset();
+       //lyxerr << "accessing cursor slice " << current_
+       //      << ": " << cursor_[current_] << endl;
+       return cursor_[current_];
 }
 
 
 LyXText * LCursor::innerText() const
 {
+       //lyxerr << "LCursor::innerText()  depth: " << cursor_.size() << endl;
        if (cursor_.size() > 1) {
                // go up until first non-0 text is hit
                // (innermost text is 0 e.g. for mathed and the outer tabular level)
@@ -173,7 +173,9 @@ void LCursor::getDim(int & asc, int & desc) const
                asc = row.baseline();
                desc = row.height() - asc;
        } else {
-               innerInset()->getCursorDim(asc, desc);
+               asc = 10;
+               desc = 10;
+               //innerInset()->getCursorDim(asc, desc);
        }
 }
 
@@ -185,37 +187,42 @@ void LCursor::getPos(int & x, int & y) const
                y = bv_->text()->cursorY();
 //             y -= bv_->top_y();
        } else {
-               // Would be nice to clean this up to make some understandable sense...
-               UpdatableInset * inset = innerInset();
-               // Non-obvious. The reason we have to have these
-               // extra checks is that the ->getCursor() calls rely
-               // on the inset's own knowledge of its screen position.
-               // If we scroll up or down in a big enough increment, the
-               // inset->draw() is not called: this doesn't update
-               // inset.top_baseline, so getCursor() returns an old value.
-               // Ugly as you like.
-               if (inset) {
-                       inset->getCursorPos(cursor_.back().idx_, x, y);
-                       x += inset->x();
+               if (inset()->asUpdatableInset()) {
+                       // Would be nice to clean this up to make some understandable sense...
+                       // Non-obvious. The reason we have to have these
+                       // extra checks is that the ->getCursor() calls rely
+                       // on the inset's own knowledge of its screen position.
+                       // If we scroll up or down in a big enough increment, the
+                       // inset->draw() is not called: this doesn't update
+                       // inset.top_baseline, so getCursor() returns an old value.
+                       // Ugly as you like.
+                       inset()->asUpdatableInset()->getCursorPos(cursor_.back().idx_, x, y);
+                       x += inset()->asUpdatableInset()->x();
                        y += cached_y_;
+               } else if (inset()->asMathInset()) {
+#warning FIXME
+                       x = 100;
+                       y = 100;
+               } else {
+                       // this should not happen
+                       BOOST_ASSERT(false);
                }
        }
 }
 
 
-UpdatableInset * LCursor::innerInsetOfType(int code) const
+InsetBase * LCursor::innerInsetOfType(int code) const
 {
        for (int i = cursor_.size() - 1; i >= 1; --i)
-               if (cursor_[i].asUpdatableInset()->lyxCode() == code)
-                       return cursor_[i].asUpdatableInset();
+               if (cursor_[i].inset_->lyxCode() == code)
+                       return cursor_[i].inset_;
        return 0;
 }
 
 
 InsetTabular * LCursor::innerInsetTabular() const
 {
-       return static_cast<InsetTabular *>
-               (innerInsetOfType(InsetOld::TABULAR_CODE));
+       return static_cast<InsetTabular *>(innerInsetOfType(InsetBase::TABULAR_CODE));
 }
 
 
@@ -275,3 +282,233 @@ bool LCursor::posRight()
        ++pos();
        return true;
 }
+
+
+CursorSlice & LCursor::anchor()
+{
+       return anchor_.back();
+}
+
+
+CursorSlice const & LCursor::anchor() const
+{
+       return anchor_.back();
+}
+
+
+CursorSlice const & LCursor::selStart() const
+{
+       if (!selection())
+               return cursor_.back();
+       // can't use std::min as this creates a new object
+       return anchor() < cursor_.back() ? anchor() : cursor_.back();
+}
+
+
+CursorSlice const & LCursor::selEnd() const
+{
+       if (!selection())
+               return cursor_.back();
+       return anchor() > cursor_.back() ? anchor() : cursor_.back();
+}
+
+
+CursorSlice & LCursor::selStart()
+{
+       if (!selection())
+               return cursor_.back();
+       return anchor() < cursor_.back() ? anchor() : cursor_.back();
+}
+
+
+CursorSlice & LCursor::selEnd()
+{
+       if (selection())
+               return cursor_.back();
+       return anchor() > cursor_.back() ? anchor() : cursor_.back();
+}
+
+
+void LCursor::setSelection()
+{
+       selection() = true;
+       // a selection with no contents is not a selection
+       if (par() == anchor().par() && pos() == anchor().pos())
+               selection() = false;
+}
+
+
+void LCursor::clearSelection()
+{
+       selection() = false;
+       mark() = false;
+       resetAnchor();
+       bv().unsetXSel();
+}
+
+
+
+//
+// CursorBase
+//
+
+
+void increment(CursorBase & it)
+{
+       CursorSlice & top = it.back();
+       MathArray & ar = top.asMathInset()->cell(top.idx_);
+
+       // move into the current inset if possible
+       // it is impossible for pos() == size()!
+       MathInset * n = 0;
+       if (top.pos() != top.lastpos())
+               n = (ar.begin() + top.pos_)->nucleus();
+       if (n && n->isActive()) {
+               it.push_back(CursorSlice(n));
+               return;
+       }
+
+       // otherwise move on one cell back if possible
+       if (top.pos() < top.lastpos()) {
+               // pos() == lastpos() is valid!
+               ++top.pos_;
+               return;
+       }
+
+       // otherwise try to move on one cell if possible
+       while (top.idx_ + 1 < top.asMathInset()->nargs()) {
+               // idx() == nargs() is _not_ valid!
+               ++top.idx_;
+               if (top.asMathInset()->validCell(top.idx_)) {
+                       top.pos_ = 0;
+                       return;
+               }
+       }
+
+       // otherwise leave array, move on one back
+       // this might yield pos() == size(), but that's a ok.
+       it.pop_back();
+       // it certainly invalidates top
+       ++it.back().pos_;
+}
+
+
+CursorBase ibegin(InsetBase * p)
+{
+       CursorBase it;
+       it.push_back(CursorSlice(p));
+       return it;
+}
+
+
+CursorBase iend(InsetBase * p)
+{
+       CursorBase it;
+       it.push_back(CursorSlice(p));
+       CursorSlice & top = it.back();
+       top.idx_ = top.asMathInset()->nargs() - 1;
+       top.pos_ = top.asMathInset()->cell(top.idx_).size();
+       return it;
+}
+
+
+void LCursor::x_target(int x)
+{
+       x_target_ = x;
+}
+
+
+int LCursor::x_target() const
+{
+       return x_target_;
+}
+
+
+Paragraph & LCursor::paragraph()
+{
+       return current_ ? current().paragraph() : *bv_->text()->getPar(par());
+}
+
+
+Paragraph const & LCursor::paragraph() const
+{
+       return current_ ? current().paragraph() : *bv_->text()->getPar(par());
+}
+
+
+LCursor::pos_type LCursor::lastpos() const
+{
+       return current_ ? current().lastpos() : bv_->text()->getPar(par())->size();
+}
+
+
+size_t LCursor::nargs() const
+{
+       // assume 1x1 grid for 'plain text'
+       return current_ ? current().nargs() : 1;
+}
+
+
+size_t LCursor::ncols() const
+{
+       // assume 1x1 grid for 'plain text'
+       return current_ ? current().ncols() : 1;
+}
+
+
+size_t LCursor::nrows() const
+{
+       // assume 1x1 grid for 'plain text'
+       return current_ ? current().nrows() : 1;
+}
+
+
+LCursor::row_type LCursor::row() const
+{
+       BOOST_ASSERT(current_ > 0);
+       return current().row();
+}
+
+
+LCursor::col_type LCursor::col() const
+{
+       BOOST_ASSERT(current_ > 0);
+       return current().col();
+}
+
+
+MathArray const & LCursor::cell() const
+{
+       BOOST_ASSERT(current_ > 0);
+       return current().cell();
+}
+
+
+MathArray & LCursor::cell()
+{
+       BOOST_ASSERT(current_ > 0);
+       return current().cell();
+}
+
+
+void LCursor::info(std::ostream & os)
+{
+       for (int i = 1, n = depth(); i < n; ++i) {
+               cursor_[i].inset()->infoize(os);
+               os << "  ";
+       }
+#warning FIXME
+       //if (pos() != 0)
+       //      prevAtom()->infoize2(os);
+       // overwite old message
+       os << "                    ";
+}
+
+
+std::ostream & operator<<(std::ostream & os, LCursor const & cur)
+{
+       os << "\n";
+       for (size_t i = 0, n = cur.cursor_.size(); i != n; ++i)
+               os << "  (" << cur.cursor_[i] << " | " << cur.anchor_[i] << "\n";
+       return os;
+}