(cm, lineObj, lineNo, x, y)
| 2741 | } |
| 2742 | |
| 2743 | function coordsCharInner(cm, lineObj, lineNo, x, y) { |
| 2744 | // Move y into line-local coordinate space |
| 2745 | y -= heightAtLine(lineObj); |
| 2746 | var preparedMeasure = prepareMeasureForLine(cm, lineObj); |
| 2747 | // When directly calling `measureCharPrepared`, we have to adjust |
| 2748 | // for the widgets at this line. |
| 2749 | var widgetHeight = widgetTopHeight(lineObj); |
| 2750 | var begin = 0, end = lineObj.text.length, ltr = true; |
| 2751 | |
| 2752 | var order = getOrder(lineObj, cm.doc.direction); |
| 2753 | // If the line isn't plain left-to-right text, first figure out |
| 2754 | // which bidi section the coordinates fall into. |
| 2755 | if (order) { |
| 2756 | var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) |
| 2757 | (cm, lineObj, lineNo, preparedMeasure, order, x, y); |
| 2758 | ltr = part.level != 1; |
| 2759 | // The awkward -1 offsets are needed because findFirst (called |
| 2760 | // on these below) will treat its first bound as inclusive, |
| 2761 | // second as exclusive, but we want to actually address the |
| 2762 | // characters in the part's range |
| 2763 | begin = ltr ? part.from : part.to - 1; |
| 2764 | end = ltr ? part.to : part.from - 1; |
| 2765 | } |
| 2766 | |
| 2767 | // A binary search to find the first character whose bounding box |
| 2768 | // starts after the coordinates. If we run across any whose box wrap |
| 2769 | // the coordinates, store that. |
| 2770 | var chAround = null, boxAround = null; |
| 2771 | var ch = findFirst(function (ch) { |
| 2772 | var box = measureCharPrepared(cm, preparedMeasure, ch); |
| 2773 | box.top += widgetHeight; box.bottom += widgetHeight; |
| 2774 | if (!boxIsAfter(box, x, y, false)) { return false } |
| 2775 | if (box.top <= y && box.left <= x) { |
| 2776 | chAround = ch; |
| 2777 | boxAround = box; |
| 2778 | } |
| 2779 | return true |
| 2780 | }, begin, end); |
| 2781 | |
| 2782 | var baseX, sticky, outside = false; |
| 2783 | // If a box around the coordinates was found, use that |
| 2784 | if (boxAround) { |
| 2785 | // Distinguish coordinates nearer to the left or right side of the box |
| 2786 | var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; |
| 2787 | ch = chAround + (atStart ? 0 : 1); |
| 2788 | sticky = atStart ? "after" : "before"; |
| 2789 | baseX = atLeft ? boxAround.left : boxAround.right; |
| 2790 | } else { |
| 2791 | // (Adjust for extended bound, if necessary.) |
| 2792 | if (!ltr && (ch == end || ch == begin)) { ch++; } |
| 2793 | // To determine which side to associate with, get the box to the |
| 2794 | // left of the character and compare it's vertical position to the |
| 2795 | // coordinates |
| 2796 | sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : |
| 2797 | (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? |
| 2798 | "after" : "before"; |
| 2799 | // Now get accurate coordinates for this place, in order to get a |
| 2800 | // base X position |
no test coverage detected