(cm, prepared, ch, bias)
| 2575 | } |
| 2576 | |
| 2577 | function measureCharInner(cm, prepared, ch, bias) { |
| 2578 | var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); |
| 2579 | var node = place.node, start = place.start, end = place.end, collapse = place.collapse; |
| 2580 | |
| 2581 | var rect; |
| 2582 | if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. |
| 2583 | for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned |
| 2584 | while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start; |
| 2585 | while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end; |
| 2586 | if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { |
| 2587 | rect = node.parentNode.getBoundingClientRect(); |
| 2588 | } else if (ie && cm.options.lineWrapping) { |
| 2589 | var rects = range(node, start, end).getClientRects(); |
| 2590 | if (rects.length) |
| 2591 | rect = rects[bias == "right" ? rects.length - 1 : 0]; |
| 2592 | else |
| 2593 | rect = nullRect; |
| 2594 | } else { |
| 2595 | rect = range(node, start, end).getBoundingClientRect() || nullRect; |
| 2596 | } |
| 2597 | if (rect.left || rect.right || start == 0) break; |
| 2598 | end = start; |
| 2599 | start = start - 1; |
| 2600 | collapse = "right"; |
| 2601 | } |
| 2602 | if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); |
| 2603 | } else { // If it is a widget, simply get the box for the whole widget. |
| 2604 | if (start > 0) collapse = bias = "right"; |
| 2605 | var rects; |
| 2606 | if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) |
| 2607 | rect = rects[bias == "right" ? rects.length - 1 : 0]; |
| 2608 | else |
| 2609 | rect = node.getBoundingClientRect(); |
| 2610 | } |
| 2611 | if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { |
| 2612 | var rSpan = node.parentNode.getClientRects()[0]; |
| 2613 | if (rSpan) |
| 2614 | rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; |
| 2615 | else |
| 2616 | rect = nullRect; |
| 2617 | } |
| 2618 | |
| 2619 | var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; |
| 2620 | var mid = (rtop + rbot) / 2; |
| 2621 | var heights = prepared.view.measure.heights; |
| 2622 | for (var i = 0; i < heights.length - 1; i++) |
| 2623 | if (mid < heights[i]) break; |
| 2624 | var top = i ? heights[i - 1] : 0, bot = heights[i]; |
| 2625 | var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, |
| 2626 | right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, |
| 2627 | top: top, bottom: bot}; |
| 2628 | if (!rect.left && !rect.right) result.bogus = true; |
| 2629 | if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } |
| 2630 | |
| 2631 | return result; |
| 2632 | } |
| 2633 | |
| 2634 | // Work around problem with bounding client rects on ranges being |
no test coverage detected