+using std::for_each;
+
+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().asInsetMath()->cell(et.top().idx()).size();
+ for (size_t i = 0; ; ++i) {
+ int xo;
+ int yo;
+ InsetBase const * inset = &it.inset();
+ std::map<InsetBase const *, Point> const & data =
+ c.bv().coordCache().getInsets().getData();
+ std::map<InsetBase const *, Point>::const_iterator I = data.find(inset);
+
+ // FIXME: in the case where the inset is not in the cache, this
+ // means that no part of it is visible on screen. In this case
+ // we don't do elaborate search and we just return the forwarded
+ // DocIterator at its beginning.
+ if (I == data.end()) {
+ it.top().pos() = 0;
+ return it;
+ }
+
+ Point o = I->second;
+ inset->cursorPos(c.bv(), it.top(), c.boundary(), xo, yo);
+ // Convert to absolute
+ xo += o.x_;
+ yo += o.y_;
+ 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());
+ InsetBase & inset = cursor[0].inset();
+ BufferView & bv = cursor.bv();
+
+ CoordCache::InnerParPosCache const & cache =
+ bv.coordCache().getParPos().find(cursor.bottom().text())->second;
+ // Get an iterator on the first paragraph in the cache
+ DocIterator it(inset);
+ it.push_back(CursorSlice(inset));
+ it.pit() = cache.begin()->first;
+ // Get an iterator after the last paragraph in the cache
+ DocIterator et(inset);
+ et.push_back(CursorSlice(inset));
+ et.pit() = boost::prior(cache.end())->first;
+ if (et.pit() >= et.lastpit())
+ et = doc_iterator_end(inset);
+ else
+ ++et.pit();
+
+ double best_dist = std::numeric_limits<double>::max();;
+ DocIterator best_cursor = et;
+
+ for ( ; it != et; it.forwardPos(true)) {
+ // avoid invalid nesting when selecting
+ if (!cursor.selection() || positionable(it, cursor.anchor_)) {
+ Point p = bv_funcs::getPos(bv, it, false);
+ int xo = p.x_;
+ int yo = p.y_;
+ if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+ double const dx = xo - x;
+ double const dy = yo - y;
+ double const d = dx * dx + dy * dy;
+ // '<=' 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;
+ }
+ }
+ }
+ }
+
+ if (best_cursor != et) {
+ cursor.setCursor(best_cursor);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /// moves position closest to (x, y) in given box
+ bool bruteFind3(LCursor & cur, int x, int y, bool up)
+ {
+ BufferView & bv = cur.bv();
+ int ylow = up ? 0 : y + 1;
+ int yhigh = up ? y - 1 : bv.workHeight();
+ int xlow = 0;
+ int xhigh = bv.workWidth();
+
+// FIXME: bit more work needed to get 'from' and 'to' right.
+ pit_type from = cur.bottom().pit();
+ //pit_type to = cur.bottom().pit();
+ //lyxerr << "Pit start: " << from << endl;
+
+ //lyxerr << "bruteFind3: x: " << x << " y: " << y
+ // << " xlow: " << xlow << " xhigh: " << xhigh
+ // << " ylow: " << ylow << " yhigh: " << yhigh
+ // << endl;
+ InsetBase & inset = bv.buffer()->inset();
+ DocIterator it = doc_iterator_begin(inset);
+ it.pit() = from;
+ DocIterator et = doc_iterator_end(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(&bv, it) == bv_funcs::CUR_INSIDE
+ && (!cur.selection() || positionable(it, cur.anchor_))) {
+ Point p = bv_funcs::getPos(bv, it, false);
+ int xo = p.x_;
+ int yo = p.y_;
+ if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+ double const dx = xo - x;
+ double const dy = yo - y;
+ double const d = dx * dx + dy * dy;
+ //lyxerr << "itx: " << xo << " ity: " << yo << " d: " << d
+ // << " dx: " << dx << " dy: " << dy
+ // << " idx: " << it.idx() << " pos: " << it.pos()
+ // << " it:\n" << it
+ // << 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)
+ return false;
+ cur.setCursor(best_cursor);
+ return true;
+ }
+
+} // namespace anon