int (final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) { int offset = 0; // running offset in the decoded fragment int endOffset = -1; for (Pair<TextRange, String> fragment : myHost.getDecodedFragments()) { final TextRange encodedTextRange = fragment.getFirst(); final TextRange intersection = encodedTextRange.intersection(rangeInsideHost); if (intersection != null && !intersection.isEmpty()) { final String value = fragment.getSecond(); final int valueLength = value.length(); final int intersectionLength = intersection.getLength(); if (valueLength == 0) { return -1; } // A long unicode escape of form \U01234567 can be decoded into a surrogate pair else if (value.codePointCount(0, valueLength) == 1) { if (offset == offsetInDecoded) { return intersection.getStartOffset(); } offset += valueLength; } else { // Literal fragment without escapes: it's safe to use intersection length instead of value length if (offset + intersectionLength >= offsetInDecoded) { final int delta = offsetInDecoded - offset; return intersection.getStartOffset() + delta; } offset += intersectionLength; } endOffset = intersection.getEndOffset(); } } // XXX: According to the real use of getOffsetInHost() it should return the correct host offset for the offset in decoded at the // end of the range inside host, not -1 if (offset == offsetInDecoded) { return endOffset; } return -1; }