Beispiel #1
0
 /** Patches attributes to be visible under debugger active line */
 @SuppressWarnings("UseJBColor")
 private static TextAttributes patchAttributesColor(
     TextAttributes attributes, TextRange range, Editor editor) {
   int line = editor.offsetToLogicalPosition(range.getStartOffset()).line;
   for (RangeHighlighter highlighter : editor.getMarkupModel().getAllHighlighters()) {
     if (!highlighter.isValid()) continue;
     if (highlighter.getTargetArea() == HighlighterTargetArea.LINES_IN_RANGE
         && editor.offsetToLogicalPosition(highlighter.getStartOffset()).line == line) {
       TextAttributes textAttributes = highlighter.getTextAttributes();
       if (textAttributes != null) {
         Color color = textAttributes.getBackgroundColor();
         if (color != null
             && color.getBlue() > 128
             && color.getRed() < 128
             && color.getGreen() < 128) {
           TextAttributes clone = attributes.clone();
           clone.setForegroundColor(Color.orange);
           clone.setEffectColor(Color.orange);
           return clone;
         }
       }
     }
   }
   return attributes;
 }
 public void cleanUp() {
   unsubscribe();
   searchResults.clear();
   if (editor != null) {
     editor.getMarkupModel().removeAllHighlighters();
   }
 }
  private List<HighlightInfo> getHighlights() {
    if (myReadAccessRanges.isEmpty() && myWriteAccessRanges.isEmpty()) {
      return Collections.emptyList();
    }
    Set<Pair<Object, TextRange>> existingMarkupTooltips = new HashSet<Pair<Object, TextRange>>();
    for (RangeHighlighter highlighter : myEditor.getMarkupModel().getAllHighlighters()) {
      existingMarkupTooltips.add(
          Pair.create(
              highlighter.getErrorStripeTooltip(),
              new TextRange(highlighter.getStartOffset(), highlighter.getEndOffset())));
    }

    List<HighlightInfo> result =
        new ArrayList<HighlightInfo>(myReadAccessRanges.size() + myWriteAccessRanges.size());
    for (TextRange range : myReadAccessRanges) {
      ContainerUtil.addIfNotNull(
          createHighlightInfo(
              range, HighlightInfoType.ELEMENT_UNDER_CARET_READ, existingMarkupTooltips),
          result);
    }
    for (TextRange range : myWriteAccessRanges) {
      ContainerUtil.addIfNotNull(
          createHighlightInfo(
              range, HighlightInfoType.ELEMENT_UNDER_CARET_WRITE, existingMarkupTooltips),
          result);
    }
    return result;
  }
 void hide() {
   if (myHighlighter != null) {
     LOG.assertTrue(myEditor != null);
     myEditor.getMarkupModel().removeHighlighter(myHighlighter);
     myHighlighter = null;
   }
 }
Beispiel #5
0
  private HighlightersSet installHighlighterSet(Info info, Editor editor) {
    final JComponent internalComponent = editor.getContentComponent();
    internalComponent.addKeyListener(myEditorKeyListener);
    editor.getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
    final Cursor cursor = internalComponent.getCursor();
    internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    myFileEditorManager.addFileEditorManagerListener(myFileEditorManagerListener);

    List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
    TextAttributes attributes =
        myEditorColorsManager
            .getGlobalScheme()
            .getAttributes(EditorColors.REFERENCE_HYPERLINK_COLOR);
    for (TextRange range : info.getRanges()) {
      TextAttributes attr = patchAttributesColor(attributes, range, editor);
      final RangeHighlighter highlighter =
          editor
              .getMarkupModel()
              .addRangeHighlighter(
                  range.getStartOffset(),
                  range.getEndOffset(),
                  HighlighterLayer.SELECTION + 1,
                  attr,
                  HighlighterTargetArea.EXACT_RANGE);
      highlighters.add(highlighter);
    }

    return new HighlightersSet(highlighters, editor, cursor, info);
  }
 public void set() {
   if (myEditor == null) return;
   hide();
   final int line = myEditor.getCaretModel().getLogicalPosition().line;
   myHighlighter =
       line < myEditor.getDocument().getLineCount()
           ? myEditor.getMarkupModel().addLineHighlighter(line, LAYER, null)
           : null;
 }
  public void removeComment(
      Editor editor, RangeHighlighter lineHighlighter, RangeHighlighter rangeHighlighter) {
    editor.getMarkupModel().removeHighlighter(lineHighlighter);
    lineHighlighter.dispose();

    if (rangeHighlighter != null) {
      HighlightManager highlightManager = HighlightManager.getInstance(project);
      highlightManager.removeSegmentHighlighter(editor, rangeHighlighter);
    }
  }
 void repaintErrorStripeRenderer(Editor editor) {
   if (!myProject.isInitialized()) return;
   final Document document = editor.getDocument();
   final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
   final EditorMarkupModel markup = (EditorMarkupModel) editor.getMarkupModel();
   markup.setErrorPanelPopupHandler(new DaemonEditorPopup(psiFile));
   markup.setErrorStripTooltipRendererProvider(new DaemonTooltipRendererProvider(myProject));
   markup.setMinMarkHeight(DaemonCodeAnalyzerSettings.getInstance().ERROR_STRIPE_MARK_MIN_HEIGHT);
   TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markup, myProject, document, psiFile);
 }
Beispiel #9
0
 @NotNull
 public static RangeHighlighter highlightMatch(@NotNull Editor editor, int start, int end) {
   TextAttributes color =
       editor.getColorsScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
   return editor
       .getMarkupModel()
       .addRangeHighlighter(
           start,
           end,
           HighlighterLayer.ADDITIONAL_SYNTAX + 1,
           color,
           HighlighterTargetArea.EXACT_RANGE);
 }
  public static RangeHighlighter highlightRangeComment(
      Comment.Range range, Editor editor, Project project) {
    CharSequence charsSequence = editor.getMarkupModel().getDocument().getCharsSequence();

    RangeUtils.Offset offset = RangeUtils.rangeToTextOffset(charsSequence, range);

    TextAttributes attributes = new TextAttributes();
    attributes.setBackgroundColor(JBColor.YELLOW);
    ArrayList<RangeHighlighter> highlighters = Lists.newArrayList();
    HighlightManager highlightManager = HighlightManager.getInstance(project);
    highlightManager.addRangeHighlight(
        editor, offset.start, offset.end, attributes, false, highlighters);
    return highlighters.get(0);
  }
Beispiel #11
0
  private static void removeSearchHighlight(@NotNull Editor editor) {
    Collection<RangeHighlighter> ehl = EditorData.getLastHighlights(editor);
    if (ehl == null) {
      return;
    }

    for (RangeHighlighter rh : ehl) {
      editor.getMarkupModel().removeHighlighter(rh);
    }

    ehl.clear();

    EditorData.setLastHighlights(editor, null);
    EditorData.setLastSearch(editor, null);
  }
  private static void clearLineMarkers(Editor editor) {
    final List<RangeHighlighter> oldHighlighters =
        editor.getUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY);

    if (oldHighlighters != null) {
      final MarkupModelEx markupModel = (MarkupModelEx) editor.getMarkupModel();

      for (RangeHighlighter highlighter : oldHighlighters) {
        if (markupModel.containsHighlighter(highlighter)) {
          highlighter.dispose();
        }
      }
      editor.putUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY, null);
    }
  }
Beispiel #13
0
 @NotNull
 private RangeHighlighter highlightConfirm(@NotNull Editor editor, int start, int end) {
   TextAttributes color =
       new TextAttributes(
           editor.getColorsScheme().getColor(EditorColors.SELECTION_FOREGROUND_COLOR),
           editor.getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR),
           null,
           null,
           0);
   return editor
       .getMarkupModel()
       .addRangeHighlighter(
           start,
           end,
           HighlighterLayer.ADDITIONAL_SYNTAX + 2,
           color,
           HighlighterTargetArea.EXACT_RANGE);
 }
 @Nullable
 public Editor getEditor() {
   if (project == null) return null;
   FileEditorManagerEx instanceEx = FileEditorManagerEx.getInstanceEx(project);
   if (instanceEx != null) {
     FileEditor[] editors = instanceEx.getEditors(instanceEx.getCurrentFile());
     if (editors.length > 0) {
       FileEditor fileEditor = editors[0];
       if (fileEditor instanceof TextEditor) {
         Editor editor1 = ((TextEditor) fileEditor).getEditor();
         if (editor != null) {
           editor.getMarkupModel().removeAllHighlighters();
         }
         editor = editor1;
       }
     }
   }
   return editor;
 }
  /**
   * @return created editor. This editor should be released by {@link #disposeEditor(Editor) }
   *     method.
   */
  @NotNull
  private Editor createEditor() {
    Editor editor = EditorFactory.getInstance().createEditor(myDocument, myProject);
    ((EditorMarkupModel) editor.getMarkupModel()).setErrorStripeVisible(true);
    EditorHighlighter highlighter =
        EditorHighlighterFactory.getInstance()
            .createEditorHighlighter(
                myFile, EditorColorsManager.getInstance().getGlobalScheme(), myProject);
    ((EditorEx) editor).setHighlighter(highlighter);
    ((EditorEx) editor).setFile(myFile);

    editor.addEditorMouseListener(myEditorMouseListener);
    ((EditorEx) editor).addPropertyChangeListener(myEditorPropertyChangeListener);

    ((EditorImpl) editor).setDropHandler(new FileDropHandler(editor));

    TextEditorProvider.putTextEditor(editor, myTextEditor);
    return editor;
  }
Beispiel #16
0
    public void documentChanged(@NotNull DocumentEvent event) {
      if (!VimPlugin.isEnabled()) {
        return;
      }

      Project[] projs = ProjectManager.getInstance().getOpenProjects();
      for (Project proj : projs) {
        Editor[] editors = EditorFactory.getInstance().getEditors(event.getDocument(), proj);
        for (Editor editor : editors) {
          Collection hls = EditorData.getLastHighlights(editor);
          if (hls == null) {
            continue;
          }

          int soff = event.getOffset();
          int eoff = soff + event.getNewLength();

          if (logger.isDebugEnabled()) {
            logger.debug("hls=" + hls);
            logger.debug("event=" + event);
          }
          Iterator iter = hls.iterator();
          while (iter.hasNext()) {
            RangeHighlighter rh = (RangeHighlighter) iter.next();
            if (!rh.isValid() || (eoff >= rh.getStartOffset() && soff <= rh.getEndOffset())) {
              iter.remove();
              editor.getMarkupModel().removeHighlighter(rh);
            }
          }

          int sl = editor.offsetToLogicalPosition(soff).line;
          int el = editor.offsetToLogicalPosition(eoff).line;
          VimPlugin.getSearch().highlightSearchLines(editor, false, sl, el);
          hls = EditorData.getLastHighlights(editor);
          if (logger.isDebugEnabled()) {
            logger.debug("sl=" + sl + ", el=" + el);
            logger.debug("hls=" + hls);
          }
        }
      }
    }
 private RangeHighlighter addSegmentHighlighter(
     @NotNull Editor editor,
     int startOffset,
     int endOffset,
     TextAttributes attributes,
     @HideFlags int flags) {
   RangeHighlighter highlighter =
       editor
           .getMarkupModel()
           .addRangeHighlighter(
               startOffset,
               endOffset,
               HighlighterLayer.SELECTION - 1,
               attributes,
               HighlighterTargetArea.EXACT_RANGE);
   HighlightInfo info =
       new HighlightInfo(
           editor instanceof EditorWindow ? ((EditorWindow) editor).getDelegate() : editor, flags);
   Map<RangeHighlighter, HighlightInfo> map = getHighlightInfoMap(editor, true);
   map.put(highlighter, info);
   return highlighter;
 }
 /**
  * Gets highlighted information from test console. Some parts of output (like file links) may be
  * highlighted, and you need to check them.
  *
  * @return pair of [[ranges], [texts]] where range is [from,to] in doc. for each region, and
  *     "text" is text extracted from this region. For example assume that in document "spam eggs
  *     ham" words "ham" and "spam" are highlighted. You should have 2 ranges (0, 4) and (10, 13)
  *     and 2 strings (spam and ham)
  */
 @NotNull
 public Pair<List<Pair<Integer, Integer>>, List<String>> getHighlightedStringsInConsole() {
   final List<String> resultStrings = new ArrayList<>();
   final List<Pair<Integer, Integer>> resultRanges = new ArrayList<>();
   ApplicationManager.getApplication()
       .invokeAndWait(
           () -> {
             myConsole.flushDeferredText();
             final Editor editor = myConsole.getEditor();
             for (final RangeHighlighter highlighter :
                 editor.getMarkupModel().getAllHighlighters()) {
               if (highlighter instanceof RangeHighlighterEx) {
                 final int start = ((RangeHighlighterEx) highlighter).getAffectedAreaStartOffset();
                 final int end = ((RangeHighlighterEx) highlighter).getAffectedAreaEndOffset();
                 resultRanges.add(Pair.create(start, end));
                 resultStrings.add(editor.getDocument().getText().substring(start, end));
               }
             }
           },
           ModalityState.NON_MODAL);
   return Pair.create(resultRanges, resultStrings);
 }
  private Editor createLogEditor() {
    Project project = myProjectModel.getProject();
    final Editor editor = ConsoleViewUtil.setupConsoleEditor(project, false, false);
    myProjectModel
        .getProject()
        .getMessageBus()
        .connect()
        .subscribe(
            ProjectManager.TOPIC,
            new ProjectManagerAdapter() {
              @Override
              public void projectClosed(Project project) {
                if (project == myProjectModel.getProject()) {
                  EditorFactory.getInstance().releaseEditor(editor);
                }
              }
            });

    ((EditorMarkupModel) editor.getMarkupModel()).setErrorStripeVisible(true);

    final ClearLogAction clearLog = new ClearLogAction(this);
    clearLog.registerCustomShortcutSet(
        ActionManager.getInstance().getAction(IdeActions.CONSOLE_CLEAR_ALL).getShortcutSet(),
        editor.getContentComponent());

    editor.addEditorMouseListener(
        new EditorPopupHandler() {
          public void invokePopup(final EditorMouseEvent event) {
            final ActionManager actionManager = ActionManager.getInstance();
            final ActionPopupMenu menu =
                actionManager.createActionPopupMenu(
                    ActionPlaces.EDITOR_POPUP, createPopupActions(actionManager, clearLog));
            final MouseEvent mouseEvent = event.getMouseEvent();
            menu.getComponent()
                .show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
          }
        });
    return editor;
  }
  private void updateChangesForDocument(@NotNull final Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (DaemonListeners.isUnderIgnoredAction(null) || myProject.isDisposed()) return;
    List<Pair<PsiElement, Boolean>> toUpdate = changedElements.get(document);
    if (toUpdate == null) {
      // The document has been changed, but psi hasn't
      // We may still need to rehighlight the file if there were changes inside highlighted ranges.
      if (UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document)) return;

      // don't create PSI for files in other projects
      PsiElement file = PsiDocumentManager.getInstance(myProject).getCachedPsiFile(document);
      if (file == null) return;

      toUpdate = Collections.singletonList(Pair.create(file, true));
    }
    Application application = ApplicationManager.getApplication();
    final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
    if (editor != null && !application.isUnitTestMode()) {
      application.invokeLater(
          () -> {
            if (!editor.isDisposed()) {
              EditorMarkupModel markupModel = (EditorMarkupModel) editor.getMarkupModel();
              PsiFile file =
                  PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
              TrafficLightRenderer.setOrRefreshErrorStripeRenderer(
                  markupModel, myProject, editor.getDocument(), file);
            }
          },
          ModalityState.stateForComponent(editor.getComponent()),
          myProject.getDisposed());
    }

    for (Pair<PsiElement, Boolean> changedElement : toUpdate) {
      PsiElement element = changedElement.getFirst();
      Boolean whiteSpaceOptimizationAllowed = changedElement.getSecond();
      updateByChange(element, document, whiteSpaceOptimizationAllowed);
    }
    changedElements.remove(document);
  }
  private void highlightUsages() {
    Editor e = getEditor();
    if (e == null) return;
    boolean foundVisibleElement = false;
    int offset = Integer.MAX_VALUE;
    for (SearchResult sr : searchResults.values()) {
      Map<Node, PsiElement> match = sr.getMatch();
      TextAttributes textAttributes = createUniqueTextAttrsFor(sr);
      PsiElement targetElement = match.get(pattern.getTheOne());

      if (!foundVisibleElement && insideVisibleArea(e, targetElement)) {
        foundVisibleElement = true;
      }
      if (!foundVisibleElement && targetElement.getTextOffset() < offset) {
        offset = targetElement.getTextOffset();
      }
      for (PsiElement element : match.values()) {
        TextAttributes attributes = textAttributes;
        if (element == targetElement) {
          attributes = MAIN_TARGET_ATTRIBUTES;
        }
        if (element instanceof XmlTag) {
          element = element.getFirstChild().getNextSibling();
        }
        TextRange textRange = element.getTextRange();

        e.getMarkupModel()
            .addRangeHighlighter(
                textRange.getStartOffset(),
                textRange.getEndOffset(),
                HighlighterLayer.SELECTION + 1,
                attributes,
                HighlighterTargetArea.EXACT_RANGE);
      }
    }
    if (!foundVisibleElement && offset != Integer.MAX_VALUE) {
      e.getScrollingModel().scrollTo(e.offsetToLogicalPosition(offset), ScrollType.CENTER);
    }
  }
  public void addComment(
      Editor editor, ChangeInfo changeInfo, String revisionId, Project project, Comment comment) {
    if (editor == null) return;
    MarkupModel markup = editor.getMarkupModel();

    RangeHighlighter rangeHighlighter = null;
    if (comment.range != null) {
      rangeHighlighter = highlightRangeComment(comment.range, editor, project);
    }

    int lineCount = markup.getDocument().getLineCount();

    int line = comment.line - 1;
    if (line < 0) {
      line = 0;
    }
    if (line > lineCount - 1) {
      line = lineCount - 1;
    }
    if (line >= 0) {
      final RangeHighlighter highlighter =
          markup.addLineHighlighter(line, HighlighterLayer.ERROR + 1, null);
      CommentGutterIconRenderer iconRenderer =
          new CommentGutterIconRenderer(
              this,
              editor,
              gerritUtil,
              selectedRevisions,
              addCommentActionBuilder,
              comment,
              changeInfo,
              revisionId,
              highlighter,
              rangeHighlighter);
      highlighter.setGutterIconRenderer(iconRenderer);
    }
  }
  private HighlightersSet installHighlighterSet(Info info, Editor editor) {
    final JComponent internalComponent = editor.getContentComponent();
    internalComponent.addKeyListener(myEditorKeyListener);
    editor.getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
    final Cursor cursor = internalComponent.getCursor();
    internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    myFileEditorManager.addFileEditorManagerListener(myFileEditorManagerListener);

    List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
    for (TextRange range : info.getRanges()) {
      final RangeHighlighter highlighter =
          editor
              .getMarkupModel()
              .addRangeHighlighter(
                  range.getStartOffset(),
                  range.getEndOffset(),
                  HighlighterLayer.SELECTION + 1,
                  ourReferenceAttributes,
                  HighlighterTargetArea.EXACT_RANGE);
      highlighters.add(highlighter);
    }

    return new HighlightersSet(highlighters, editor, cursor, info);
  }
  private void addVCGutterIcons(
      VCOutputFile vco, Editor editor, Project project, MyProverListener listener) {
    if (!editor.isDisposed()) {
      highlighters.clear();
      MarkupModel markup = editor.getMarkupModel();
      RESOLVEPluginController controller = RESOLVEPluginController.getInstance(project);
      markup.removeAllHighlighters();

      // A mapping from [line number] -> [vc_1, .., vc_j]
      Map<Integer, List<VC>> byLine = vco.getVCsGroupedByLineNumber();
      List<RangeHighlighter> vcRelatedHighlighters = new ArrayList<>();

      for (Map.Entry<Integer, List<VC>> vcsByLine : byLine.entrySet()) {
        List<AnAction> actionsPerVC = new ArrayList<>();
        // create clickable actions for each vc
        for (VC vc : vcsByLine.getValue()) {
          actionsPerVC.add(
              new VCNavigationAction(listener, vc.getNumber() + "", vc.getExplanation()));
        }

        highlighter =
            markup.addLineHighlighter(
                vcsByLine.getKey() - 1, HighlighterLayer.ELEMENT_UNDER_CARET, null);
        highlighter.setGutterIconRenderer(
            new GutterIconRenderer() {
              @NotNull
              @Override
              public Icon getIcon() {
                return RESOLVEIcons.VC;
              }

              @Override
              public boolean equals(Object obj) {
                return false;
              }

              @Override
              public int hashCode() {
                return 0;
              }

              @Override
              public boolean isNavigateAction() {
                return true;
              }

              @Nullable
              public ActionGroup getPopupMenuActions() {
                DefaultActionGroup g = new DefaultActionGroup();
                g.addAll(actionsPerVC);
                return g;
              }

              @Nullable
              public AnAction getClickAction() {
                return null;
              }
            });
        vcRelatedHighlighters.add(highlighter);
        highlighters.add(highlighter);
      }

      editor
          .getDocument()
          .addDocumentListener(
              new DocumentListener() {
                @Override
                public void beforeDocumentChange(DocumentEvent event) {}

                @Override
                public void documentChanged(DocumentEvent event) {
                  // remove all highlighters
                  for (RangeHighlighter h : vcRelatedHighlighters) {
                    markup.removeHighlighter(h);
                  }
                  VerifierPanel verifierPanel = controller.getVerifierPanel();
                  controller.getVerifierWindow().hide(null);
                  verifierPanel.revertToBaseGUI();
                }
              });
    }
  }
Beispiel #25
0
  public boolean searchAndReplace(
      @NotNull Editor editor, @NotNull LineRange range, @NotNull String excmd, String exarg) {
    boolean res = true;

    // Explicitly exit visual mode here, so that visual mode marks don't change when we move the
    // cursor to a match.
    if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) {
      VimPlugin.getMotion().exitVisual(editor);
    }

    CharPointer cmd = new CharPointer(new StringBuffer(exarg));
    // sub_nsubs = 0;
    // sub_nlines = 0;

    int which_pat;
    if (excmd.equals("~")) {
      which_pat = RE_LAST; /* use last used regexp */
    } else {
      which_pat = RE_SUBST; /* use last substitute regexp */
    }

    CharPointer pat;
    CharPointer sub;
    char delimiter;
    /* new pattern and substitution */
    if (excmd.charAt(0) == 's'
        && !cmd.isNul()
        && !Character.isWhitespace(cmd.charAt())
        && "0123456789cegriIp|\"".indexOf(cmd.charAt()) == -1) {
      /* don't accept alphanumeric for separator */
      if (CharacterClasses.isAlpha(cmd.charAt())) {
        VimPlugin.showMessage(MessageHelper.message(Msg.E146));
        return false;
      }
      /*
       * undocumented vi feature:
       *  "\/sub/" and "\?sub?" use last used search pattern (almost like
       *  //sub/r).  "\&sub&" use last substitute pattern (like //sub/).
       */
      if (cmd.charAt() == '\\') {
        cmd.inc();
        if ("/?&".indexOf(cmd.charAt()) == -1) {
          VimPlugin.showMessage(MessageHelper.message(Msg.e_backslash));
          return false;
        }
        if (cmd.charAt() != '&') {
          which_pat = RE_SEARCH; /* use last '/' pattern */
        }
        pat = new CharPointer(""); /* empty search pattern */
        delimiter = cmd.charAt(); /* remember delimiter character */
        cmd.inc();
      } else /* find the end of the regexp */ {
        which_pat = RE_LAST; /* use last used regexp */
        delimiter = cmd.charAt(); /* remember delimiter character */
        cmd.inc();
        pat = cmd.ref(0); /* remember start of search pat */
        cmd = RegExp.skip_regexp(cmd, delimiter, true);
        if (cmd.charAt() == delimiter) /* end delimiter found */ {
          cmd.set('\u0000').inc(); /* replace it with a NUL */
        }
      }

      /*
       * Small incompatibility: vi sees '\n' as end of the command, but in
       * Vim we want to use '\n' to find/substitute a NUL.
       */
      sub = cmd.ref(0); /* remember the start of the substitution */

      while (!cmd.isNul()) {
        if (cmd.charAt() == delimiter) /* end delimiter found */ {
          cmd.set('\u0000').inc(); /* replace it with a NUL */
          break;
        }
        if (cmd.charAt(0) == '\\' && cmd.charAt(1) != 0) /* skip escaped characters */ {
          cmd.inc();
        }
        cmd.inc();
      }
    } else /* use previous pattern and substitution */ {
      if (lastReplace == null) /* there is no previous command */ {
        VimPlugin.showMessage(MessageHelper.message(Msg.e_nopresub));
        return false;
      }
      pat = null; /* search_regcomp() will use previous pattern */
      sub = new CharPointer(lastReplace);
    }

    /*
     * Find trailing options.  When '&' is used, keep old options.
     */
    if (cmd.charAt() == '&') {
      cmd.inc();
    } else {
      do_all = Options.getInstance().isSet("gdefault");
      do_ask = false;
      do_error = true;
      // do_print = false;
      do_ic = 0;
    }
    while (!cmd.isNul()) {
      /*
       * Note that 'g' and 'c' are always inverted, also when p_ed is off.
       * 'r' is never inverted.
       */
      if (cmd.charAt() == 'g') {
        do_all = !do_all;
      } else if (cmd.charAt() == 'c') {
        do_ask = !do_ask;
      } else if (cmd.charAt() == 'e') {
        do_error = !do_error;
      } else if (cmd.charAt() == 'r') /* use last used regexp */ {
        which_pat = RE_LAST;
      } else if (cmd.charAt() == 'i') /* ignore case */ {
        do_ic = 'i';
      } else if (cmd.charAt() == 'I') /* don't ignore case */ {
        do_ic = 'I';
      } else if (cmd.charAt() != 'p') {
        break;
      }
      cmd.inc();
    }

    int line1 = range.getStartLine();
    int line2 = range.getEndLine();

    /*
     * check for a trailing count
     */
    cmd = CharHelper.skipwhite(cmd);
    if (CharacterClasses.isDigit(cmd.charAt())) {
      int i = CharHelper.getdigits(cmd);
      if (i <= 0 && do_error) {
        VimPlugin.showMessage(MessageHelper.message(Msg.e_zerocount));
        return false;
      }
      line1 = line2;
      line2 = EditorHelper.normalizeLine(editor, line1 + i - 1);
    }

    /*
     * check for trailing command or garbage
     */
    cmd = CharHelper.skipwhite(cmd);
    if (!cmd.isNul() && cmd.charAt() != '"') /* if not end-of-line or comment */ {
      VimPlugin.showMessage(MessageHelper.message(Msg.e_trailing));
      return false;
    }

    String pattern = "";
    if (pat == null || pat.isNul()) {
      switch (which_pat) {
        case RE_LAST:
          pattern = lastPattern;
          break;
        case RE_SEARCH:
          pattern = lastSearch;
          break;
        case RE_SUBST:
          pattern = lastSubstitute;
          break;
      }
    } else {
      pattern = pat.toString();
    }

    lastSubstitute = pattern;
    if (pattern != null) {
      setLastPattern(editor, pattern);
    }

    // int start = editor.logicalPositionToOffset(new LogicalPosition(line1, 0));
    // int end = editor.logicalPositionToOffset(new LogicalPosition(line2,
    // EditorHelper.getLineLength(editor, line2)));
    int start = editor.getDocument().getLineStartOffset(line1);
    int end = editor.getDocument().getLineEndOffset(line2);

    RegExp sp;
    RegExp.regmmatch_T regmatch = new RegExp.regmmatch_T();
    sp = new RegExp();
    regmatch.regprog = sp.vim_regcomp(pattern, 1);
    if (regmatch.regprog == null) {
      if (do_error) {
        VimPlugin.showMessage(MessageHelper.message(Msg.e_invcmd));
      }
      return false;
    }

    /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
    if (do_ic == 'i') {
      regmatch.rmm_ic = true;
    } else if (do_ic == 'I') {
      regmatch.rmm_ic = false;
    }

    /*
     * ~ in the substitute pattern is replaced with the old pattern.
     * We do it here once to avoid it to be replaced over and over again.
     * But don't do it when it starts with "\=", then it's an expression.
     */
    if (!(sub.charAt(0) == '\\' && sub.charAt(1) == '=') && lastReplace != null) {
      StringBuffer tmp = new StringBuffer(sub.toString());
      int pos = 0;
      while ((pos = tmp.indexOf("~", pos)) != -1) {
        if (pos == 0 || tmp.charAt(pos - 1) != '\\') {
          tmp.replace(pos, pos + 1, lastReplace);
          pos += lastReplace.length();
        }
        pos++;
      }
      sub = new CharPointer(tmp);
    }

    lastReplace = sub.toString();

    searchHighlight(false);

    if (logger.isDebugEnabled()) {
      logger.debug("search range=[" + start + "," + end + "]");
      logger.debug("pattern=" + pattern + ", replace=" + sub);
    }
    int lastMatch = -1;
    int lastLine = -1;
    int searchcol = 0;
    boolean firstMatch = true;
    boolean got_quit = false;
    int lcount = EditorHelper.getLineCount(editor);
    for (int lnum = line1; lnum <= line2 && !got_quit; ) {
      CharacterPosition newpos = null;
      int nmatch = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, searchcol);
      if (nmatch > 0) {
        if (firstMatch) {
          VimPlugin.getMark().saveJumpLocation(editor);
          firstMatch = false;
        }

        String match = sp.vim_regsub_multi(regmatch, lnum, sub, 1, false);
        // logger.debug("found match[" + spos + "," + epos + "] - replace " + match);

        int line = lnum + regmatch.startpos[0].lnum;
        CharacterPosition startpos =
            new CharacterPosition(lnum + regmatch.startpos[0].lnum, regmatch.startpos[0].col);
        CharacterPosition endpos =
            new CharacterPosition(lnum + regmatch.endpos[0].lnum, regmatch.endpos[0].col);
        int startoff = EditorHelper.characterPositionToOffset(editor, startpos);
        int endoff = EditorHelper.characterPositionToOffset(editor, endpos);
        int newend = startoff + match.length();

        if (do_all || line != lastLine) {
          boolean doReplace = true;
          if (do_ask) {
            // editor.getSelectionModel().setSelection(startoff, endoff);
            RangeHighlighter hl = highlightConfirm(editor, startoff, endoff);
            int choice = getConfirmChoice(match);
            // editor.getSelectionModel().removeSelection();
            editor.getMarkupModel().removeHighlighter(hl);
            switch (choice) {
              case 0: // Yes
                doReplace = true;
                break;
              case 1: // No
                doReplace = false;
                break;
              case 2: // All
                do_ask = false;
                break;
              case JOptionPane.CLOSED_OPTION:
              case 3: // Quit
                doReplace = false;
                got_quit = true;
                break;
              case 4: // Last
                do_all = false;
                line2 = lnum;
                doReplace = true;
                break;
            }
          }

          if (doReplace) {
            editor.getDocument().replaceString(startoff, endoff, match);
            lastMatch = startoff;
            newpos = EditorHelper.offsetToCharacterPosition(editor, newend);

            lnum += newpos.line - endpos.line;
            line2 += newpos.line - endpos.line;
          }
        }

        lastLine = line;

        lnum += nmatch - 1;
        if (do_all && startoff != endoff) {
          if (newpos != null) {
            lnum = newpos.line;
            searchcol = newpos.column;
          } else {
            searchcol = endpos.column;
          }
        } else {
          searchcol = 0;
          lnum++;
        }
      } else {
        lnum++;
        searchcol = 0;
      }
    }

    if (lastMatch != -1) {
      MotionGroup.moveCaret(
          editor,
          VimPlugin.getMotion()
              .moveCaretToLineStartSkipLeading(
                  editor, editor.offsetToLogicalPosition(lastMatch).line));
    } else {
      VimPlugin.showMessage(MessageHelper.message(Msg.e_patnotf2, pattern));
    }

    return res;
  }
  void doPrintNotification(final Notification notification) {
    Editor editor = myLogEditor.getValue();
    if (editor.isDisposed()) {
      return;
    }

    Document document = editor.getDocument();
    boolean scroll =
        document.getTextLength() == editor.getCaretModel().getOffset()
            || !editor.getContentComponent().hasFocus();

    Long notificationTime = myProjectModel.getNotificationTime(notification);
    if (notificationTime == null) {
      return;
    }

    String date = DateFormatUtil.formatTimeWithSeconds(notificationTime) + " ";
    append(document, date);

    int startLine = document.getLineCount() - 1;

    EventLog.LogEntry pair =
        EventLog.formatForLog(notification, StringUtil.repeatSymbol(' ', date.length()));

    final NotificationType type = notification.getType();
    TextAttributesKey key =
        type == NotificationType.ERROR
            ? ConsoleViewContentType.LOG_ERROR_OUTPUT_KEY
            : type == NotificationType.INFORMATION
                ? ConsoleViewContentType.NORMAL_OUTPUT_KEY
                : ConsoleViewContentType.LOG_WARNING_OUTPUT_KEY;

    int msgStart = document.getTextLength();
    String message = pair.message;
    append(document, message);

    TextAttributes attributes =
        EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key);
    int layer = HighlighterLayer.CARET_ROW + 1;
    editor
        .getMarkupModel()
        .addRangeHighlighter(
            msgStart,
            document.getTextLength(),
            layer,
            attributes,
            HighlighterTargetArea.EXACT_RANGE);

    for (Pair<TextRange, HyperlinkInfo> link : pair.links) {
      myHyperlinkSupport
          .getValue()
          .addHyperlink(
              link.first.getStartOffset() + msgStart,
              link.first.getEndOffset() + msgStart,
              null,
              link.second);
    }

    append(document, "\n");

    if (scroll) {
      editor.getCaretModel().moveToOffset(document.getTextLength());
      editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
    }

    if (notification.isImportant()) {
      highlightNotification(notification, pair.status, startLine, document.getLineCount() - 1);
    }
  }
  private void dumpEditorMarkupAndSelection(PrintStream dumpStream) {
    dumpStream.println(mySearchResults.getFindModel());
    if (myReplacementPreviewText != null) {
      dumpStream.println("--");
      dumpStream.println("Replacement Preview: " + myReplacementPreviewText);
    }
    dumpStream.println("--");

    Editor editor = mySearchResults.getEditor();

    RangeHighlighter[] highlighters = editor.getMarkupModel().getAllHighlighters();
    List<Pair<Integer, Character>> ranges = new ArrayList<Pair<Integer, Character>>();
    for (RangeHighlighter highlighter : highlighters) {
      ranges.add(new Pair<Integer, Character>(highlighter.getStartOffset(), '['));
      ranges.add(new Pair<Integer, Character>(highlighter.getEndOffset(), ']'));
    }

    SelectionModel selectionModel = editor.getSelectionModel();

    if (selectionModel.getSelectionStart() != selectionModel.getSelectionEnd()) {
      ranges.add(new Pair<Integer, Character>(selectionModel.getSelectionStart(), '<'));
      ranges.add(new Pair<Integer, Character>(selectionModel.getSelectionEnd(), '>'));
    }
    ranges.add(new Pair<Integer, Character>(-1, '\n'));
    ranges.add(new Pair<Integer, Character>(editor.getDocument().getTextLength() + 1, '\n'));
    ContainerUtil.sort(
        ranges,
        new Comparator<Pair<Integer, Character>>() {
          @Override
          public int compare(Pair<Integer, Character> pair, Pair<Integer, Character> pair2) {
            int res = pair.first - pair2.first;
            if (res == 0) {

              Character c1 = pair.second;
              Character c2 = pair2.second;
              if (c1 == '<' && c2 == '[') {
                return 1;
              } else if (c1 == '[' && c2 == '<') {
                return -1;
              }
              return c1.compareTo(c2);
            }
            return res;
          }
        });

    Document document = editor.getDocument();
    for (int i = 0; i < ranges.size() - 1; ++i) {
      Pair<Integer, Character> pair = ranges.get(i);
      Pair<Integer, Character> pair1 = ranges.get(i + 1);
      dumpStream.print(
          pair.second
              + document.getText(
                  TextRange.create(
                      Math.max(pair.first, 0), Math.min(pair1.first, document.getTextLength()))));
    }
    dumpStream.println("\n--");

    if (NotFound) {
      dumpStream.println("Not Found");
      dumpStream.println("--");
      NotFound = false;
    }

    for (RangeHighlighter highlighter : highlighters) {
      dumpStream.println(highlighter + " : " + highlighter.getTextAttributes());
    }
    dumpStream.println("------------");
  }