void doSetSelection(final @NotNull VisualPosition startPosition,
                      final int _startOffset,
                      final @NotNull VisualPosition endPosition,
                      final int _endOffset,
                      final boolean visualPositionAware,
                      final boolean updateSystemSelection,
                      final boolean fireListeners) {
    myCaretModel.doWithCaretMerging(() -> {
      int startOffset = DocumentUtil.alignToCodePointBoundary(myEditor.getDocument(), _startOffset);
      int endOffset = DocumentUtil.alignToCodePointBoundary(myEditor.getDocument(), _endOffset);
      myUnknownDirection = false;
      final Document doc = myEditor.getDocument();

      ThreadingAssertions.assertEventDispatchThread();

      int textLength = doc.getTextLength();
      if (startOffset < 0 || startOffset > textLength) {
        LOG.error("Wrong startOffset: " + startOffset + ", textLength=" + textLength);
      }
      if (endOffset < 0 || endOffset > textLength) {
        LOG.error("Wrong endOffset: " + endOffset + ", textLength=" + textLength);
      }

      if (!visualPositionAware && startOffset == endOffset) {
        removeSelection();
        return;
      }

  /* Normalize selection */
      boolean switchedOffsets = false;
      if (startOffset > endOffset) {
        int tmp = startOffset;
        startOffset = endOffset;
        endOffset = tmp;
        switchedOffsets = true;
      }

      FoldingModelEx foldingModel = myEditor.getFoldingModel();
      FoldRegion startFold = foldingModel.getCollapsedRegionAtOffset(startOffset);
      if (startFold != null && startFold.getStartOffset() < startOffset) {
        startOffset = startFold.getStartOffset();
      }

      FoldRegion endFold = foldingModel.getCollapsedRegionAtOffset(endOffset);
      if (endFold != null && endFold.getStartOffset() < endOffset) {
        // All visual positions that lay at collapsed fold region placeholder are mapped to the same offset. Hence, there are
        // at least two distinct situations - selection end is located inside collapsed fold region placeholder and just before it.
        // We want to expand selection to the fold region end at the former case and keep selection as-is at the latest one.
        endOffset = endFold.getEndOffset();
      }

      int oldSelectionStart;
      int oldSelectionEnd;

      if (hasSelection()) {
        oldSelectionStart = getSelectionStart();
        oldSelectionEnd = getSelectionEnd();
        if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset && !visualPositionAware) return;
      }
      else {
        oldSelectionStart = oldSelectionEnd = getOffset();
      }

      SelectionMarker marker = new SelectionMarker(startOffset, endOffset);
      if (visualPositionAware) {
        if (endPosition.after(startPosition)) {
          setRangeMarkerStartPosition(startPosition);
          setRangeMarkerEndPosition(endPosition);
          setRangeMarkerEndPositionIsLead(false);
        }
        else {
          setRangeMarkerStartPosition(endPosition);
          setRangeMarkerEndPosition(startPosition);
          setRangeMarkerEndPositionIsLead(true);
        }

        if (isVirtualSelectionEnabled() &&
            myEditor.getDocument().getLineNumber(startOffset) == myEditor.getDocument().getLineNumber(endOffset)) {
          int endLineColumn = myEditor.offsetToVisualPosition(endOffset).column;
          int startDiff =
            EditorUtil.isAtLineEnd(myEditor, switchedOffsets ? endOffset : startOffset) ? startPosition.column - endLineColumn : 0;
          int endDiff =
            EditorUtil.isAtLineEnd(myEditor, switchedOffsets ? startOffset : endOffset) ? endPosition.column - endLineColumn : 0;
          marker.startVirtualOffset = Math.max(0, Math.min(startDiff, endDiff));
          marker.endVirtualOffset = Math.max(0, Math.max(startDiff, endDiff));
        }
      }
      else {
        setRangeMarkerEndPositionIsLead(endOffset != getOffset());
      }
      SelectionMarker selectionMarker = mySelectionMarker;
      if (selectionMarker != null) {
        selectionMarker.dispose();
      }
      mySelectionMarker = marker;

      if (fireListeners) {
        myEditor.getSelectionModel().fireSelectionChanged(new SelectionEvent(myEditor,
                                                                             oldSelectionStart, oldSelectionEnd, startOffset, endOffset));
      }

      if (updateSystemSelection) {
        myCaretModel.updateSystemSelection();
      }
    });
  }
void doSetSelection(final @NotNull VisualPosition startPosition,
                      final int _startOffset,
                      final @NotNull VisualPosition endPosition,
                      final int _endOffset,
                      final boolean visualPositionAware,
                      final boolean updateSystemSelection,
                      final boolean fireListeners)