protected LangSourceViewer getEditorSourceViewer() throws CommonException {
   if (editor instanceof AbstractLangEditor) {
     AbstractLangEditor langEditor = (AbstractLangEditor) editor;
     return langEditor.getSourceViewer_();
   } else {
     throw new CommonException("Possible internal error: SourceViewer not available.");
   }
 }
  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);
  }
 protected LangPairMatcher getBracketMatcher() {
   return langEditor.getBracketMatcher();
 }