CharSequence (char @NotNull [] originalData, int start, int end) { if (myChanges.isEmpty()) { return new String(originalData, start, end - start); } if (end == start) { return ""; } int startChangeIndex = getChangeIndex(start); int endChangeIndex = getChangeIndex(end); boolean substringAffectedByChanges = startChangeIndex != endChangeIndex || startChangeIndex >= 0; int clientShift = 0; int originalStart = 0; if (startChangeIndex < 0) { startChangeIndex = -startChangeIndex - 1; if (startChangeIndex > 0 && startChangeIndex <= myChanges.size()) { ChangeEntry changeEntry = myChanges.get(startChangeIndex - 1); clientShift = changeEntry.clientStartOffset - changeEntry.change.getStart() + changeEntry.change.getDiff(); originalStart = changeEntry.change.getEnd(); } } else { ChangeEntry changeEntry = myChanges.get(startChangeIndex); clientShift = changeEntry.clientStartOffset - changeEntry.change.getStart(); } if (!substringAffectedByChanges) { return new String(originalData, start - clientShift, end - start); } char[] data = new char[end - start]; int outputOffset = 0; for (int i = startChangeIndex; i < myChanges.size() && outputOffset < data.length; i++) { ChangeEntry changeEntry = myChanges.get(i); int clientStart = changeEntry.clientStartOffset; if (clientStart >= end) { if (i == startChangeIndex) { return new String(originalData, start - clientShift, end - start); } System.arraycopy(originalData, originalStart, data, outputOffset, data.length - outputOffset); break; } int clientEnd = clientStart + changeEntry.change.getText().length(); if (clientEnd > start) { if (clientStart > start) { int length = Math.min(clientStart - start, changeEntry.change.getStart() - originalStart); length = Math.min(length, data.length - outputOffset); System.arraycopy(originalData, changeEntry.change.getStart() - length, data, outputOffset, length); outputOffset += length; if (outputOffset >= data.length) { break; } } if (clientStart < clientEnd) { int changeTextStartOffset = start <= clientStart ? 0 : start - clientStart; int length = Math.min(clientEnd, end) - Math.max(clientStart, start); CharArrayUtil.getChars(changeEntry.change.getText(), data, changeTextStartOffset, outputOffset, length); outputOffset += length; } } originalStart = changeEntry.change.getEnd(); } if (outputOffset < data.length) { System.arraycopy(originalData, originalStart, data, outputOffset, data.length - outputOffset); } return new String(data); }