+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;
+ }
+