private LineSet genericUpdate(int startOffset, int endOffset, CharSequence replacement) {
    int startLine = findLineIndex(startOffset);
    int endLine = findLineIndex(endOffset);

    LineSet patch = createLineSet(replacement, true);

    int lengthShift = patch.myLength - (endOffset - startOffset);

    int startLineStart = getLineStart(startLine);
    boolean addStartLine = startOffset - startLineStart > 0 || patch.myStarts.length > 0 || endOffset < myLength;
    boolean addEndLine = endOffset < myLength && patch.myLength > 0 && patch.getSeparatorLength(patch.myStarts.length - 1) > 0;
    int newLineCount = startLine + (addStartLine ? 1 : 0) +
                       Math.max(patch.myStarts.length - 1, 0) +
                       (addEndLine ? 1 : 0) + Math.max(myStarts.length - endLine - 1, 0);

    int[] starts = ArrayUtil.newIntArray(newLineCount);
    byte[] flags = ArrayUtil.newByteArray(newLineCount);

    if (startLine > 0) {
      System.arraycopy(myStarts, 0, starts, 0, startLine);
      System.arraycopy(myFlags, 0, flags, 0, startLine);
    }

    int toIndex = startLine;
    if (addStartLine) {
      starts[toIndex] = startLineStart;
      flags[toIndex] = patch.myStarts.length > 0 ? patch.myFlags[0] : MODIFIED_MASK;
      toIndex++;
    }

    toIndex = patch.shiftData(starts, flags, 1, toIndex, patch.myStarts.length - 1, startOffset);

    if (endOffset < myLength) {
      if (addEndLine) {
        starts[toIndex] = endOffset + lengthShift;
        flags[toIndex] = (byte) (myFlags[endLine] | MODIFIED_MASK);
        toIndex++;
      } else if (toIndex > 0) {
        flags[toIndex - 1] = (byte) (myFlags[endLine] | MODIFIED_MASK);
      }
    }

    shiftData(starts, flags, endLine + 1, toIndex, myStarts.length - (endLine + 1), lengthShift);

    return new LineSet(starts, flags, myLength + lengthShift);
  }
private LineSet genericUpdate(int startOffset, int endOffset, CharSequence replacement)