+#ifndef CXX_GLOBAL_CSTD
+using std::isalpha;
+#endif
+using std::min;
+using std::swap;
+
+namespace {
+
+ bool
+ positionable(DocIterator const & cursor, DocIterator const & anchor)
+ {
+ // avoid deeper nested insets when selecting
+ if (cursor.depth() > anchor.depth())
+ return false;
+
+ // anchor might be deeper, should have same path then
+ for (size_t i = 0; i < cursor.depth(); ++i)
+ if (&cursor[i].inset() != &anchor[i].inset())
+ return false;
+
+ // position should be ok.
+ return true;
+ }
+
+
+ // Find position closest to (x, y) in cell given by iter.
+ // Used only in mathed
+ DocIterator bruteFind2(LCursor const & c, int x, int y)
+ {
+ double best_dist = std::numeric_limits<double>::max();
+
+ DocIterator result;
+
+ DocIterator it = c;
+ it.top().pos() = 0;
+ DocIterator et = c;
+ et.top().pos() = et.top().asMathInset()->cell(et.top().idx()).size();
+ for (int i = 0; ; ++i) {
+ int xo;
+ int yo;
+ it.inset().cursorPos(it.top(), c.boundary(), xo, yo);
+ double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+ // '<=' in order to take the last possible position
+ // this is important for clicking behind \sum in e.g. '\sum_i a'
+ lyxerr[Debug::DEBUG] << "i: " << i << " d: " << d
+ << " best: " << best_dist << endl;
+ if (d <= best_dist) {
+ best_dist = d;
+ result = it;
+ }
+ if (it == et)
+ break;
+ it.forwardPos();
+ }
+ return result;
+ }
+
+
+ /// moves position closest to (x, y) in given box
+ bool bruteFind(LCursor & cursor,
+ int x, int y, int xlow, int xhigh, int ylow, int yhigh)
+ {
+ BOOST_ASSERT(!cursor.empty());
+ CursorSlice bottom = cursor[0];
+
+ DocIterator it = doc_iterator_begin(bottom.inset());
+ DocIterator const et = doc_iterator_end(bottom.inset());
+
+ double best_dist = std::numeric_limits<double>::max();;
+ DocIterator best_cursor = et;
+
+ for ( ; it != et; it.forwardPos()) {
+ // avoid invalid nesting when selecting
+ if (bv_funcs::status(&cursor.bv(), it) == bv_funcs::CUR_INSIDE
+ && (!cursor.selection() || positionable(it, cursor.anchor_))) {
+ Point p = bv_funcs::getPos(it, false);
+ int xo = p.x_;
+ int yo = p.y_;
+ if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+ double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+ //lyxerr << "xo: " << xo << " yo: " << yo << " d: " << d << endl;
+ // '<=' in order to take the last possible position
+ // this is important for clicking behind \sum in e.g. '\sum_i a'
+ if (d <= best_dist) {
+ //lyxerr << "*" << endl;
+ best_dist = d;
+ best_cursor = it;
+ }
+ }
+ }
+ }
+
+ //lyxerr << "best_dist: " << best_dist << " cur:\n" << best_cursor << endl;
+ if (best_cursor != et) {
+ cursor.setCursor(best_cursor);
+ return true;
+ }
+
+ return false;
+ }
+
+} // namespace anon
+
+
+// be careful: this is called from the bv's constructor, too, so
+// bv functions are not yet available!
+LCursor::LCursor(BufferView & bv)
+ : DocIterator(), bv_(&bv), anchor_(), x_target_(-1),
+ selection_(false), mark_(false), logicalpos_(false)
+{}
+
+
+void LCursor::reset(InsetBase & inset)
+{
+ clear();
+ push_back(CursorSlice(inset));
+ anchor_ = DocIterator(inset);
+ clearTargetX();
+ selection_ = false;
+ mark_ = false;
+}
+
+
+// this (intentionally) does neither touch anchor nor selection status
+void LCursor::setCursor(DocIterator const & cur)
+{
+ DocIterator::operator=(cur);
+}
+
+
+void LCursor::dispatch(FuncRequest const & cmd0)
+{
+ lyxerr[Debug::DEBUG] << BOOST_CURRENT_FUNCTION
+ << " cmd: " << cmd0 << '\n'
+ << *this << endl;
+ if (empty())
+ return;
+
+ fixIfBroken();
+ FuncRequest cmd = cmd0;
+ LCursor safe = *this;
+
+ for (; depth(); pop()) {
+ lyxerr[Debug::DEBUG] << "LCursor::dispatch: cmd: "
+ << cmd0 << endl << *this << endl;
+ BOOST_ASSERT(pos() <= lastpos());
+ BOOST_ASSERT(idx() <= lastidx());
+ BOOST_ASSERT(pit() <= lastpit());
+
+ // The common case is 'LFUN handled, need update', so make the
+ // LFUN handler's life easier by assuming this as default value.
+ // The handler can reset the update and val flags if necessary.
+ disp_.update(true);
+ disp_.dispatched(true);
+ inset().dispatch(*this, cmd);
+ if (disp_.dispatched())
+ break;
+ }
+ // it completely to get a 'bomb early' behaviour in case this
+ // object will be used again.
+ if (!disp_.dispatched()) {
+ lyxerr[Debug::DEBUG] << "RESTORING OLD CURSOR!" << endl;
+ operator=(safe);
+ disp_.dispatched(false);
+ }
+}
+
+
+DispatchResult LCursor::result() const
+{
+ return disp_;
+}
+
+
+BufferView & LCursor::bv() const
+{
+ BOOST_ASSERT(bv_);
+ return *bv_;
+}
+
+
+Buffer & LCursor::buffer() const
+{
+ BOOST_ASSERT(bv_);
+ BOOST_ASSERT(bv_->buffer());
+ return *bv_->buffer();
+}
+
+
+void LCursor::pop()
+{
+ BOOST_ASSERT(depth() >= 1);
+ pop_back();
+}
+
+
+void LCursor::push(InsetBase & p)
+{
+ push_back(CursorSlice(p));
+}
+
+
+void LCursor::pushLeft(InsetBase & p)
+{
+ BOOST_ASSERT(!empty());
+ //lyxerr << "Entering inset " << t << " left" << endl;
+ push(p);
+ p.idxFirst(*this);
+}
+
+
+bool LCursor::popLeft()
+{
+ BOOST_ASSERT(!empty());
+ //lyxerr << "Leaving inset to the left" << endl;
+ inset().notifyCursorLeaves(*this);
+ if (depth() == 1)
+ return false;
+ pop();
+ return true;
+}
+
+
+bool LCursor::popRight()
+{
+ BOOST_ASSERT(!empty());
+ //lyxerr << "Leaving inset to the right" << endl;
+ inset().notifyCursorLeaves(*this);
+ if (depth() == 1)
+ return false;
+ pop();
+ ++pos();
+ return true;
+}
+
+
+int LCursor::currentMode()
+{
+ BOOST_ASSERT(!empty());
+ for (int i = depth() - 1; i >= 0; --i) {
+ int res = operator[](i).inset().currentMode();
+ if (res != InsetBase::UNDECIDED_MODE)
+ return res;
+ }
+ return InsetBase::TEXT_MODE;
+}
+
+
+void LCursor::getPos(int & x, int & y) const
+{
+ Point p = bv_funcs::getPos(*this, boundary());
+ x = p.x_;
+ y = p.y_;
+}
+
+
+void LCursor::paste(string const & data)
+{
+ dispatch(FuncRequest(LFUN_PASTE, data));
+}
+
+
+void LCursor::resetAnchor()
+{
+ anchor_ = *this;
+}
+
+
+
+bool LCursor::posLeft()
+{
+ if (pos() == 0)
+ return false;
+ --pos();
+ return true;
+}
+
+
+bool LCursor::posRight()
+{
+ if (pos() == lastpos())
+ return false;
+ ++pos();
+ return true;
+}
+
+
+CursorSlice LCursor::anchor() const
+{
+ BOOST_ASSERT(anchor_.depth() >= depth());
+ 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 LCursor::selBegin() const
+{
+ if (!selection())
+ return top();
+ return anchor() < top() ? anchor() : top();
+}
+
+
+CursorSlice LCursor::selEnd() const
+{
+ if (!selection())
+ return top();
+ return anchor() > top() ? anchor() : top();
+}
+
+
+DocIterator LCursor::selectionBegin() const
+{
+ if (!selection())
+ return *this;
+ return anchor() < top() ? anchor_ : *this;
+}
+
+
+DocIterator LCursor::selectionEnd() const
+{
+ if (!selection())
+ return *this;
+ return anchor() > top() ? anchor_ : *this;
+}
+
+
+void LCursor::setSelection()
+{
+ selection() = true;
+ // A selection with no contents is not a selection
+#ifdef WITH_WARNINGS
+#warning doesnt look ok
+#endif
+ if (pit() == anchor().pit() && pos() == anchor().pos())
+ selection() = false;
+}
+
+
+void LCursor::setSelection(DocIterator const & where, size_t n)
+{
+ setCursor(where);
+ selection() = true;
+ anchor_ = where;
+ pos() += n;
+ // Open all collapsed insets
+ for (int i = depth() - 1; i >= 0; --i)
+ operator[](i).inset().setStatus(*this, InsetBase::Open);
+}
+
+
+void LCursor::clearSelection()
+{
+ selection() = false;
+ mark() = false;
+ resetAnchor();
+ bv().unsetXSel();
+}
+
+
+int & LCursor::x_target()
+{
+ return x_target_;
+}
+
+
+int LCursor::x_target() const
+{
+ return x_target_;
+}
+
+
+void LCursor::clearTargetX()
+{
+ x_target_ = -1;
+}
+
+
+
+void LCursor::info(std::ostream & os) const
+{
+ for (int i = 1, n = depth(); i < n; ++i) {
+ operator[](i).inset().infoize(os);
+ os << " ";
+ }
+ if (pos() != 0)
+ prevInset()->infoize2(os);
+ // overwite old message
+ os << " ";
+}
+
+
+void LCursor::selHandle(bool sel)
+{
+ //lyxerr << "LCursor::selHandle" << endl;
+ if (sel == selection())
+ return;
+
+ resetAnchor();
+ selection() = sel;
+}