#include "insets/insettext.h"
#include "mathed/math_data.h"
+#include "mathed/math_inset.h"
#include <boost/assert.hpp>
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)
{}
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);
}
}
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()) {
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)
asc = row.baseline();
desc = row.height() - asc;
} else {
- innerInset()->getCursorDim(asc, desc);
+ asc = 10;
+ desc = 10;
+ //innerInset()->getCursorDim(asc, desc);
}
}
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));
}
++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;
+}