/** Select the word at the current selection. */
  protected void selectWord() {
    if (matchWord()) {

      if (fStartPos == fEndPos) fText.setSelectedRange(fStartPos, 0);
      else fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
    }
  }
  /**
   * Select the area between the selected bracket and the closing bracket. Return true if
   * successful.
   */
  protected boolean selectBracketBlock() {
    if (matchBracketsAt()) {

      if (fStartPos == fEndPos) fText.setSelectedRange(fStartPos, 0);
      else fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);

      return true;
    }
    return false;
  }
 private void restorePosition() {
   if (fPosition != null && !fPosition.isDeleted() && fViewer.getDocument() != null) {
     fViewer.setSelectedRange(fPosition.offset, fPosition.length);
     fViewer.revealRange(fPosition.offset, fPosition.length);
   }
   fPosition = null;
 }
  /**
   * Show completions at caret position. If current position does not contain quick fixes look for
   * next quick fix on same line by moving from left to right and restarting at end of line if the
   * beginning of the line is reached.
   *
   * @see org.eclipse.jface.text.quickassist.IQuickAssistAssistant#showPossibleQuickAssists()
   */
  public String showPossibleQuickAssists() {
    fPosition = null;
    fCurrentAnnotations = null;

    if (fViewer == null || fViewer.getDocument() == null)
      // Let superclass deal with this
      return super.showPossibleQuickAssists();

    ArrayList resultingAnnotations = new ArrayList(20);
    try {
      Point selectedRange = fViewer.getSelectedRange();
      int currOffset = selectedRange.x;
      int currLength = selectedRange.y;
      boolean goToClosest = (currLength == 0);

      int newOffset =
          collectQuickFixableAnnotations(fEditor, currOffset, goToClosest, resultingAnnotations);
      if (newOffset != currOffset) {
        storePosition(currOffset, currLength);
        fViewer.setSelectedRange(newOffset, 0);
        fViewer.revealRange(newOffset, 0);
      }
    } catch (BadLocationException e) {
      JavaScriptPlugin.log(e);
    }
    fCurrentAnnotations =
        (Annotation[]) resultingAnnotations.toArray(new Annotation[resultingAnnotations.size()]);

    return super.showPossibleQuickAssists();
  }
  protected boolean selectComment(int caretPos) {
    IDocument doc = fText.getDocument();
    int startPos, endPos;

    try {
      int pos = caretPos;
      char c = ' ';

      while (pos >= 0) {
        c = doc.getChar(pos);
        if (c == '\\') {
          pos -= 2;
          continue;
        }
        if (c == Character.LINE_SEPARATOR || c == '\"') {
          break;
        }
        --pos;
      }

      if (c != '\"') {
        return false;
      }

      startPos = pos;

      pos = caretPos;
      int length = doc.getLength();
      c = ' ';

      while (pos < length) {
        c = doc.getChar(pos);
        if (c == Character.LINE_SEPARATOR || c == '\"') {
          break;
        }
        ++pos;
      }
      if (c != '\"') {
        return false;
      }

      endPos = pos;

      int offset = startPos + 1;
      int len = endPos - offset;
      fText.setSelectedRange(offset, len);
      return true;
    } catch (BadLocationException x) {
    }

    return false;
  }
  private static void applyProposal(
      ICompletionProposal proposal,
      ITextViewer viewer,
      char trigger,
      int stateMask,
      final int offset) {
    Assert.isTrue(proposal instanceof ICompletionProposalExtension2);

    IRewriteTarget target = null;
    IEditingSupportRegistry registry = null;
    IEditingSupport helper =
        new IEditingSupport() {

          public boolean isOriginator(DocumentEvent event, IRegion focus) {
            return focus.getOffset() <= offset && focus.getOffset() + focus.getLength() >= offset;
          }

          public boolean ownsFocusShell() {
            return false;
          }
        };

    try {
      IDocument document = viewer.getDocument();

      if (viewer instanceof ITextViewerExtension) {
        ITextViewerExtension extension = (ITextViewerExtension) viewer;
        target = extension.getRewriteTarget();
      }

      if (target != null) target.beginCompoundChange();

      if (viewer instanceof IEditingSupportRegistry) {
        registry = (IEditingSupportRegistry) viewer;
        registry.register(helper);
      }

      ((ICompletionProposalExtension2) proposal).apply(viewer, trigger, stateMask, offset);

      Point selection = proposal.getSelection(document);
      if (selection != null) {
        viewer.setSelectedRange(selection.x, selection.y);
        viewer.revealRange(selection.x, selection.y);
      }
    } finally {
      if (target != null) target.endCompoundChange();

      if (registry != null) registry.unregister(helper);
    }
  }
  // similar to
  // org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor.removeOverrideAnnotationProposal(..)
  public void removeDeprecatedAnnotation(
      IDocument document, ICompilationUnit cu, BodyDeclaration decl) {
    Annotation annot = findAnnotation(decl.modifiers());
    if (annot != null) {
      ASTRewrite rewrite = ASTRewrite.create(annot.getAST());
      rewrite.remove(annot, null);

      callASTRewriteCorrectionProposal(getDisplayString(), cu, rewrite, 6, getImage(), document);

      ITextViewer viewer = getViewer(JavaPlugin.getActivePage().getActiveEditor());
      ITrackedNodePosition trackPos = rewrite.track(decl);
      if (trackPos != null && viewer != null) {
        viewer.setSelectedRange(trackPos.getStartPosition(), 0);
      }
    }
  }
 private void selectRange(int startPos, int stopPos) {
   int offset = startPos + 1;
   int length = stopPos - offset;
   fText.setSelectedRange(offset, length);
 }
  @Override
  public void apply(final ITextViewer viewer, char trigger, int stateMask, final int offset) {
    try {
      fLocations = null;
      Point selection = viewer.getSelectedRange();
      final int secectionOffset = selection.x;
      final int selectionLength = selection.y;

      ASTProvider.getASTProvider()
          .runOnAST(
              fTranslationUnit,
              ASTProvider.WAIT_ACTIVE_ONLY,
              new NullProgressMonitor(),
              new ASTRunnable() {
                @Override
                public IStatus runOnAST(ILanguage lang, IASTTranslationUnit astRoot)
                    throws CoreException {
                  if (astRoot == null) return Status.CANCEL_STATUS;

                  IASTNodeSelector selector = astRoot.getNodeSelector(null);
                  IASTName name = selector.findEnclosingName(secectionOffset, selectionLength);
                  if (name != null) {
                    fLocations = LinkedNamesFinder.findByName(astRoot, name);
                  }
                  return Status.OK_STATUS;
                }
              });

      if (fLocations == null || fLocations.length == 0) {
        return;
      }

      // Sort the locations starting with the one @ offset.
      Arrays.sort(
          fLocations,
          new Comparator<IRegion>() {
            @Override
            public int compare(IRegion n1, IRegion n2) {
              return rank(n1) - rank(n2);
            }

            /**
             * Returns the absolute rank of a location. Location preceding {@code offset} are ranked
             * last.
             *
             * @param location the location to compute the rank for
             * @return the rank of the location with respect to the invocation offset
             */
            private int rank(IRegion location) {
              int relativeRank = location.getOffset() + location.getLength() - offset;
              if (relativeRank < 0) {
                return Integer.MAX_VALUE + relativeRank;
              } else {
                return relativeRank;
              }
            }
          });

      IDocument document = viewer.getDocument();
      LinkedPositionGroup group = new LinkedPositionGroup();
      for (int i = 0; i < fLocations.length; i++) {
        IRegion item = fLocations[i];
        group.addPosition(new LinkedPosition(document, item.getOffset(), item.getLength(), i));
      }

      LinkedModeModel model = new LinkedModeModel();
      model.addGroup(group);
      model.forceInstall();
      CEditor editor = getCEditor();
      if (editor != null) {
        model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
      }

      LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
      ui.setExitPolicy(new DeleteBlockingExitPolicy(document));
      ui.setExitPosition(viewer, offset, 0, LinkedPositionGroup.NO_STOP);
      ui.enter();

      if (fValueSuggestion != null) {
        document.replace(fLocations[0].getOffset(), fLocations[0].getLength(), fValueSuggestion);
        IRegion selectedRegion = ui.getSelectedRegion();
        selection = new Point(selectedRegion.getOffset(), fValueSuggestion.length());
      }

      viewer.setSelectedRange(
          selection.x, selection.y); // By default full word is selected, restore original selection
    } catch (BadLocationException e) {
      CUIPlugin.log(e);
    }
  }
  /** @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent) */
  public void verifyKey(VerifyEvent event) {
    // early pruning to slow down normal typing as little as possible
    if (!event.doit || !isAutoInsertEnabled() || !isAutoInsertCharacter(event.character)) {
      return;
    }

    IDocument document = textViewer.getDocument();
    final Point selection = textViewer.getSelectedRange();
    final int offset = selection.x;
    final int length = selection.y;

    try {

      String scope = getScopeAtOffset(document, offset);
      if (fgCommentSelector.matches(scope)) {
        return;
      }

      if (length > 0) {
        wrapSelection(event, document, offset, length);
        return;
      }

      // Don't auto-close if next char is a letter or digit
      if (document.getLength() > offset) {
        char nextChar = document.getChar(offset);
        if (Character.isJavaIdentifierPart(nextChar)) {
          return;
        }
      }

      // Don't auto-close if we have an open pair!
      if (isUnclosedPair(
          event, document, offset)) // We have an open string or pair, just insert the single
      // character, don't do anything special
      {
        return;
      }

      final char closingCharacter = getPeerCharacter(event.character);
      // If this is the start char and there's no unmatched close char, insert the close char
      if (unpairedClose(event.character, closingCharacter, document, offset)) {
        return;
      }

      final StringBuffer buffer = new StringBuffer();
      buffer.append(event.character);
      buffer.append(closingCharacter);
      if (offset == document.getLength()) {
        String delim = null;
        if (document instanceof IDocumentExtension4) {
          delim = ((IDocumentExtension4) document).getDefaultLineDelimiter();
        }
        if (delim == null) {
          delim = System.getProperty("line.separator", "\r\n"); // $NON-NLS-1$ //$NON-NLS-2$
        }
        buffer.append(delim);
      }

      document.replace(offset, length, buffer.toString());

      BracketLevel level = new BracketLevel();
      fBracketLevelStack.push(level);

      LinkedPositionGroup group = new LinkedPositionGroup();
      group.addPosition(new LinkedPosition(document, offset + 1, 0, LinkedPositionGroup.NO_STOP));

      LinkedModeModel model = new LinkedModeModel();
      model.addLinkingListener(this);
      model.addGroup(group);
      model.forceInstall();

      // set up position tracking for our magic peers
      if (fBracketLevelStack.size() == 1) {
        document.addPositionCategory(CATEGORY);
        document.addPositionUpdater(fUpdater);
      }
      level.fFirstPosition = new Position(offset, 1);
      level.fSecondPosition = new Position(offset + 1, 1);
      document.addPosition(CATEGORY, level.fFirstPosition);
      document.addPosition(CATEGORY, level.fSecondPosition);

      level.fUI = new EditorLinkedModeUI(model, textViewer);
      level.fUI.setSimpleMode(true);
      level.fUI.setExitPolicy(
          new ExitPolicy(
              textViewer,
              closingCharacter,
              getEscapeCharacter(closingCharacter),
              fBracketLevelStack));
      level.fUI.setExitPosition(textViewer, offset + 2, 0, Integer.MAX_VALUE);
      level.fUI.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
      level.fUI.enter();

      IRegion newSelection = level.fUI.getSelectedRegion();
      textViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());

      event.doit = false;
    } catch (BadLocationException e) {
      CommonEditorPlugin.logError(e);
    } catch (BadPositionCategoryException e) {
      CommonEditorPlugin.logError(e);
    }
  }
  public void gotoMatchingBracket() {
    ITextViewer sourceViewer = langEditor.getSourceViewer_();

    IDocument document = sourceViewer.getDocument();
    if (document == null) return;

    IRegion selection = EditorUtils.getSignedSelection(sourceViewer);
    if (fPreviousSelections == null) initializePreviousSelectionList();

    IRegion region =
        getBracketMatcher().match(document, selection.getOffset(), selection.getLength());
    if (region == null) {
      region =
          getBracketMatcher()
              .findEnclosingPeerCharacters(document, selection.getOffset(), selection.getLength());
      initializePreviousSelectionList();
      fPreviousSelections.add(selection);
    } else {
      if (fPreviousSelections.size() == 2) {
        if (!selection.equals(fPreviousSelections.get(1))) {
          initializePreviousSelectionList();
        }
      } else if (fPreviousSelections.size() == 3) {
        if (selection.equals(fPreviousSelections.get(2))
            && !selection.equals(fPreviousSelections.get(0))) {
          IRegion originalSelection = fPreviousSelections.get(0);
          sourceViewer.setSelectedRange(
              originalSelection.getOffset(), originalSelection.getLength());
          sourceViewer.revealRange(originalSelection.getOffset(), originalSelection.getLength());
          initializePreviousSelectionList();
          return;
        }
        initializePreviousSelectionList();
      }
    }

    if (region == null) {
      langEditor.setStatusLineErrorMessage(
          LangEditorMessages.GotoMatchingBracket_error_noMatchingBracket);
      sourceViewer.getTextWidget().getDisplay().beep();
      return;
    }

    int offset = region.getOffset();
    int length = region.getLength();

    if (length < 1) return;

    int anchor = getBracketMatcher().getAnchor();
    // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
    int targetOffset = (ICharacterPairMatcher.RIGHT == anchor) ? offset + 1 : offset + length - 1;

    boolean visible = false;
    if (sourceViewer instanceof ITextViewerExtension5) {
      ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
      visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
    } else {
      IRegion visibleRegion = sourceViewer.getVisibleRegion();
      // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
      visible =
          (targetOffset >= visibleRegion.getOffset()
              && targetOffset <= visibleRegion.getOffset() + visibleRegion.getLength());
    }

    if (!visible) {
      langEditor.setStatusLineErrorMessage(
          LangEditorMessages.GotoMatchingBracket_error_bracketOutsideSelectedElement);
      sourceViewer.getTextWidget().getDisplay().beep();
      return;
    }

    int adjustment =
        getBracketMatcher()
            .getOffsetAdjustment(
                document, selection.getOffset() + selection.getLength(), selection.getLength());
    targetOffset += adjustment;
    int direction = (selection.getLength() == 0) ? 0 : ((selection.getLength() > 0) ? 1 : -1);
    if (fPreviousSelections.size() == 1 && direction < 0) {
      targetOffset++;
    }

    if (fPreviousSelections.size() > 0) {
      fPreviousSelections.add(new Region(targetOffset, direction));
    }
    sourceViewer.setSelectedRange(targetOffset, direction);
    sourceViewer.revealRange(targetOffset, direction);
  }
  public void selectionChanged(SelectionChangedEvent event) {
    if (!VrapperPlugin.isVrapperEnabled()
        || !(event.getSelection() instanceof TextSelection)
        || selectionService.isSelectionInProgress()) {
      return;
    }

    TextSelection selection = (TextSelection) event.getSelection();
    // selection.isEmpty() is false even if length == 0, don't use it
    if (selection.getLength() == 0) {
      // Explicitly reset selection. EclipseCursorAndSelection's SelectionChangeListener is
      // only fired after this listener, returning a stale selection during a mode switch.
      selectionService.setSelection(null);
      try {
        int offset = selection.getOffset();
        IRegion lineInfo = textViewer.getDocument().getLineInformationOfOffset(offset);
        // Checks if cursor is just before line end because Normalmode will move it.
        if (lineInfo.getOffset() + lineInfo.getLength() == offset) {
          selectionResetOffset = offset;
        } else {
          selectionResetOffset = -1;
        }
      } catch (BadLocationException e) {
        VrapperLog.error("Received bad selection offset in selectionchange handler", e);
      }
      EditorMode currentMode = editorAdaptor.getMode(editorAdaptor.getCurrentModeName());
      // User cleared selection or moved caret with mouse in a temporary mode.
      if (currentMode instanceof TemporaryMode) {
        editorAdaptor.changeModeSafely(InsertMode.NAME);
      } else if (currentMode instanceof AbstractVisualMode) {
        editorAdaptor.changeModeSafely(NormalMode.NAME);
        // Cursor can be after the line if an Eclipse operation cleared the selection, e.g. undo
      } else if (currentMode instanceof CommandBasedMode) {
        CommandBasedMode commandMode = (CommandBasedMode) currentMode;
        commandMode.placeCursor(StickyColumnPolicy.RESET_EOL);
      }
    } else if (!VrapperPlugin.isMouseDown()
        || !editorAdaptor.getConfiguration().get(Options.VISUAL_MOUSE)) {
      // Mark selection as "conflicted" - we're in Normal mode but somehow a selection exists
      if (NormalMode.NAME.equals(editorAdaptor.getCurrentModeName())) {
        editorAdaptor.getCursorService().setCaret(CaretType.UNDERLINE);
      }
      return;
      // Detect if a reverse selection got its last character chopped off.
    } else if (selectionResetOffset != -1
        && (selection.getOffset() + selection.getLength() + 1) == selectionResetOffset) {
      textViewer.setSelectedRange(selectionResetOffset, -(selection.getLength() + 1));
      selectionResetOffset = -1;
    } else if (selection.getLength() != 0) {
      if (NormalMode.NAME.equals(editorAdaptor.getCurrentModeName())) {
        editorAdaptor.changeModeSafely(VisualMode.NAME, AbstractVisualMode.KEEP_SELECTION_HINT);
      } else if (InsertMode.NAME.equals(editorAdaptor.getCurrentModeName())) {
        editorAdaptor.changeModeSafely(
            TempVisualMode.NAME,
            AbstractVisualMode.KEEP_SELECTION_HINT,
            InsertMode.DONT_MOVE_CURSOR);
      }
      // Store the selection - user might click with mouse and immediately destroy selection
      editorAdaptor.rememberLastActiveSelection();
    }
  }