FindResult (@NotNull Project project, @NotNull final Editor editor, int offset, boolean toWarn, @NotNull FindModel model, boolean adjustEditor) { FindManager findManager = FindManager.getInstance(project); Document document = editor.getDocument(); final FindResult result = findManager.findString(document.getCharsSequence(), offset, model, getVirtualFile(editor)); boolean isFound = result.isStringFound(); final SelectionModel selection = editor.getSelectionModel(); if (isFound && !model.isGlobal()) { if (!selectionMayContainRange(selection, result)) { isFound = false; } else if (!selectionStrictlyContainsRange(selection, result)) { final int[] starts = selection.getBlockSelectionStarts(); for (int newOffset : starts) { if (newOffset > result.getStartOffset()) { return doSearch(project, editor, newOffset, toWarn, model, adjustEditor); } } } } if (!isFound) { if (toWarn) { processNotFound(editor, editor.getCaretModel().getOffset(), model.getStringToFind(), model, project); } return null; } if (adjustEditor) { final CaretModel caretModel = editor.getCaretModel(); final ScrollingModel scrollingModel = editor.getScrollingModel(); int oldCaretOffset = caretModel.getOffset(); boolean forward = oldCaretOffset < result.getStartOffset(); final ScrollType scrollType = forward ? ScrollType.CENTER_DOWN : ScrollType.CENTER_UP; if (model.isGlobal()) { int targetCaretPosition = result.getEndOffset(); if (selection.getSelectionEnd() - selection.getSelectionStart() == result.getLength()) { // keeping caret's position relative to selection // use case: FindNext is used after SelectNextOccurrence action targetCaretPosition = caretModel.getOffset() - selection.getSelectionStart() + result.getStartOffset(); } if (caretModel.getCaretAt(editor.offsetToVisualPosition(targetCaretPosition)) != null) { // if there's a different caret at target position, don't move current caret/selection // use case: FindNext is used after SelectNextOccurrence action return result; } caretModel.moveToOffset(targetCaretPosition); selection.removeSelection(); scrollingModel.scrollToCaret(scrollType); scrollingModel.runActionOnScrollingFinished( () -> { scrollingModel.scrollTo(editor.offsetToLogicalPosition(result.getStartOffset()), scrollType); scrollingModel.scrollTo(editor.offsetToLogicalPosition(result.getEndOffset()), scrollType); } ); } else { moveCaretAndDontChangeSelection(editor, result.getStartOffset(), scrollType); moveCaretAndDontChangeSelection(editor, result.getEndOffset(), scrollType); } IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); if (!model.isGlobal()) { final RangeHighlighterEx segmentHighlighter = (RangeHighlighterEx)editor.getMarkupModel().addRangeHighlighter( EditorColors.SEARCH_RESULT_ATTRIBUTES, result.getStartOffset(), result.getEndOffset(), HighlighterLayer.SELECTION + 1, HighlighterTargetArea.EXACT_RANGE); MyListener listener = new MyListener(editor, segmentHighlighter); caretModel.addCaretListener(listener); } else { selection.setSelection(result.getStartOffset(), result.getEndOffset()); EditorSearchSession.logSelectionUpdate(); } } return result; }