public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
    Position[] positions = null;
    FormatterPrefs formatterPrefs = getFormatterPrefs();
    StringBuffer buffer = new StringBuffer();

    buffer.append(fProposal.getName());

    if (formatterPrefs.beforeOpeningParen) buffer.append(SPACE);

    buffer.append(LPAREN);

    if (formatterPrefs.afterOpeningParen) buffer.append(SPACE);

    if (Signature.getParameterCount(fProposal.getSignature()) > 0) {
      char[][] parameters = fProposal.findParameterNames(null);
      if (parameters != null) {
        positions = new Position[parameters.length];

        int base = getReplacementOffset();
        for (int i = 0; i < parameters.length; i++) {
          if (i != 0) {
            if (formatterPrefs.beforeComma) buffer.append(SPACE);

            buffer.append(COMMA);

            if (formatterPrefs.afterComma) buffer.append(SPACE);
          }
          Position position = new Position(0, 0);
          position.setOffset(base + buffer.length());
          position.setLength(parameters[i].length);
          positions[i] = position;
          buffer.append(parameters[i]);
        }
      }
    }

    if (formatterPrefs.beforeClosingParen) buffer.append(SPACE);

    buffer.append(RPAREN);
    setReplacementString(buffer.toString());

    super.apply(viewer, trigger, stateMask, offset);

    try {
      if (positions != null) {
        LinkedModeModel model = new LinkedModeModel();

        for (int i = 0; i < positions.length; i++) {
          LinkedPositionGroup group = new LinkedPositionGroup();
          Position position = positions[i];
          group.addPosition(
              new LinkedPosition(
                  viewer.getDocument(), position.getOffset(), position.getLength(), i));
          model.addGroup(group);
        }
        model.forceInstall();

        LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
        ui.setExitPosition(
            viewer, getReplacementOffset() + getReplacementString().length(), 0, Integer.MAX_VALUE);
        ui.setExitPolicy(new ExitPolicy(')', viewer.getDocument()));
        ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
        ui.setDoContextInfo(true);
        ui.enter();
        fSelectedRegion = ui.getSelectedRegion();
      }
    } catch (BadLocationException e) {

    }
  }