void (CharSequence oldText, int newEndOffset, int oldEndOffset, int tabSize) { assert newEndOffset < oldEndOffset; int lineFeedsNumberAtRemovedText = 0; int spacesNumberAtRemovedText = 0; int indentSpacesNumberAtRemovedText = 0; int column = mySpaces + myIndentSpaces; for (int i = oldEndOffset - 1; i >= newEndOffset; i--) { switch (oldText.charAt(i)) { case LINE_FEED -> { ++lineFeedsNumberAtRemovedText; column = 0; } case ' ' -> { ++spacesNumberAtRemovedText; column--; } case '\t' -> { int change = column % tabSize; if (change == 0) { change = tabSize; } indentSpacesNumberAtRemovedText += change; column -= change; } } } // There are no line feeds at remained text, hence, we can just subtract number of spaces and indent spaces // from removed text and finish. if (getLineFeeds() - lineFeedsNumberAtRemovedText <= 0) { setLineFeeds(0); mySpaces -= spacesNumberAtRemovedText; myIndentSpaces -= indentSpacesNumberAtRemovedText; return; } // There are white spaces at remained text, hence, we need to calculate number of spaces and indent spaces between // last line feed and new end offset. int newLineFeedsNumber = getLineFeeds() - lineFeedsNumberAtRemovedText; assert newLineFeedsNumber >= 0; newLineFeedsNumber = Math.max(newLineFeedsNumber, 0); // Never expect the defense to be triggered. setLineFeeds(newLineFeedsNumber); int startOffset = CharArrayUtil.shiftForwardUntil(oldText, newEndOffset - 1, "\n") + 1; WhiteSpaceInfo info = parse(oldText, startOffset, newEndOffset, 0, tabSize); mySpaces = info.spaces; myIndentSpaces = info.indentSpaces; }