private boolean getStringToReplace(
      int textOffset,
      int textEndOffset,
      Document document,
      FindModel findModel,
      Ref<String> stringToReplace)
      throws FindManager.MalformedReplacementStringException {
    if (textOffset < 0 || textOffset >= document.getTextLength()) {
      return false;
    }
    if (textEndOffset < 0 || textOffset > document.getTextLength()) {
      return false;
    }
    FindManager findManager = FindManager.getInstance(myProject);
    final CharSequence foundString =
        document.getCharsSequence().subSequence(textOffset, textEndOffset);
    PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
    FindResult findResult =
        findManager.findString(
            document.getCharsSequence(),
            textOffset,
            findModel,
            file != null ? file.getVirtualFile() : null);
    if (!findResult.isStringFound()) {
      return false;
    }

    stringToReplace.set(
        FindManager.getInstance(myProject)
            .getStringToReplace(foundString.toString(), findModel, textOffset, document.getText()));

    return true;
  }
  public void replaceInProject(@NotNull DataContext dataContext) {
    final FindManager findManager = FindManager.getInstance(myProject);
    final FindModel findModel = (FindModel) findManager.getFindInProjectModel().clone();
    findModel.setReplaceState(true);
    FindInProjectUtil.setDirectoryName(findModel, dataContext);

    Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
    FindUtil.initStringToFindWithSelection(findModel, editor);

    findManager.showFindDialog(
        findModel,
        new Runnable() {
          @Override
          public void run() {
            final PsiDirectory psiDirectory =
                FindInProjectUtil.getPsiDirectory(findModel, myProject);
            if (!findModel.isProjectScope()
                && psiDirectory == null
                && findModel.getModuleName() == null
                && findModel.getCustomScope() == null) {
              return;
            }

            UsageViewManager manager = UsageViewManager.getInstance(myProject);

            if (manager == null) return;
            findManager.getFindInProjectModel().copyFrom(findModel);
            final FindModel findModelCopy = (FindModel) findModel.clone();

            final UsageViewPresentation presentation =
                FindInProjectUtil.setupViewPresentation(true, findModelCopy);
            final FindUsagesProcessPresentation processPresentation =
                FindInProjectUtil.setupProcessPresentation(myProject, true, presentation);

            UsageSearcherFactory factory =
                new UsageSearcherFactory(findModelCopy, psiDirectory, processPresentation);
            searchAndShowUsages(
                manager, factory, findModelCopy, presentation, processPresentation, findManager);
          }
        });
  }
  private void replaceWithPrompt(final ReplaceContext replaceContext) {
    final List<Usage> _usages = replaceContext.getUsageView().getSortedUsages();

    if (hasReadOnlyUsages(_usages)) {
      WindowManager.getInstance()
          .getStatusBar(myProject)
          .setInfo(FindBundle.message("find.replace.occurrences.found.in.read.only.files.status"));
      return;
    }

    final Usage[] usages = _usages.toArray(new Usage[_usages.size()]);

    // usageView.expandAll();
    for (int i = 0; i < usages.length; ++i) {
      final Usage usage = usages[i];
      final UsageInfo usageInfo = ((UsageInfo2UsageAdapter) usage).getUsageInfo();

      final PsiElement elt = usageInfo.getElement();
      if (elt == null) continue;
      final PsiFile psiFile = elt.getContainingFile();
      if (!psiFile.isWritable()) continue;

      Runnable selectOnEditorRunnable =
          new Runnable() {
            @Override
            public void run() {
              final VirtualFile virtualFile = psiFile.getVirtualFile();

              if (virtualFile != null
                  && ApplicationManager.getApplication()
                      .runReadAction(
                          new Computable<Boolean>() {
                            @Override
                            public Boolean compute() {
                              return virtualFile.isValid() ? Boolean.TRUE : Boolean.FALSE;
                            }
                          })
                      .booleanValue()) {

                if (usage.isValid()) {
                  usage.highlightInEditor();
                  replaceContext.getUsageView().selectUsages(new Usage[] {usage});
                }
              }
            }
          };

      CommandProcessor.getInstance()
          .executeCommand(
              myProject,
              selectOnEditorRunnable,
              FindBundle.message("find.replace.select.on.editor.command"),
              null);
      String title = FindBundle.message("find.replace.found.usage.title", i + 1, usages.length);

      int result;
      try {
        replaceUsage(
            usage, replaceContext.getFindModel(), replaceContext.getExcludedSetCached(), true);
        result =
            FindManager.getInstance(myProject)
                .showPromptDialog(replaceContext.getFindModel(), title);
      } catch (FindManager.MalformedReplacementStringException e) {
        markAsMalformedReplacement(replaceContext, usage);
        result =
            FindManager.getInstance(myProject)
                .showMalformedReplacementPrompt(replaceContext.getFindModel(), title, e);
      }

      if (result == FindManager.PromptResult.CANCEL) {
        return;
      }
      if (result == FindManager.PromptResult.SKIP) {
        continue;
      }

      final int currentNumber = i;
      if (result == FindManager.PromptResult.OK) {
        final Ref<Boolean> success = Ref.create();
        Runnable runnable =
            new Runnable() {
              @Override
              public void run() {
                success.set(replaceUsageAndRemoveFromView(usage, replaceContext));
              }
            };
        CommandProcessor.getInstance()
            .executeCommand(myProject, runnable, FindBundle.message("find.replace.command"), null);
        if (closeUsageViewIfEmpty(replaceContext.getUsageView(), success.get())) {
          return;
        }
      }

      if (result == FindManager.PromptResult.ALL_IN_THIS_FILE) {
        final int[] nextNumber = new int[1];

        Runnable runnable =
            new Runnable() {
              @Override
              public void run() {
                int j = currentNumber;
                boolean success = true;
                for (; j < usages.length; j++) {
                  final Usage usage = usages[j];
                  final UsageInfo usageInfo = ((UsageInfo2UsageAdapter) usage).getUsageInfo();

                  final PsiElement elt = usageInfo.getElement();
                  if (elt == null) continue;
                  PsiFile otherPsiFile = elt.getContainingFile();
                  if (!otherPsiFile.equals(psiFile)) {
                    break;
                  }
                  if (!replaceUsageAndRemoveFromView(usage, replaceContext)) {
                    success = false;
                  }
                }
                closeUsageViewIfEmpty(replaceContext.getUsageView(), success);
                nextNumber[0] = j;
              }
            };

        CommandProcessor.getInstance()
            .executeCommand(myProject, runnable, FindBundle.message("find.replace.command"), null);

        //noinspection AssignmentToForLoopParameter
        i = nextNumber[0] - 1;
      }

      if (result == FindManager.PromptResult.ALL_FILES) {
        CommandProcessor.getInstance()
            .executeCommand(
                myProject,
                new Runnable() {
                  @Override
                  public void run() {
                    final boolean success = replaceUsages(replaceContext, _usages);
                    closeUsageViewIfEmpty(replaceContext.getUsageView(), success);
                  }
                },
                FindBundle.message("find.replace.command"),
                null);
        break;
      }
    }
  }