Logo Search packages:      
Sourcecode: eclipse-cdt version File versions  Download package

CEditor.java

/*******************************************************************************
 * Copyright (c) 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     QNX Software System
 *******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.CCorePreferenceConstants;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ISourceRange;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
import org.eclipse.cdt.internal.ui.actions.AddBlockCommentAction;
import org.eclipse.cdt.internal.ui.actions.FoldingActionGroup;
import org.eclipse.cdt.internal.ui.actions.GoToNextPreviousMemberAction;
import org.eclipse.cdt.internal.ui.actions.RemoveBlockCommentAction;
import org.eclipse.cdt.internal.ui.browser.typehierarchy.OpenTypeHierarchyAction;
import org.eclipse.cdt.internal.ui.search.actions.OpenDeclarationsAction;
import org.eclipse.cdt.internal.ui.search.actions.OpenDefinitionAction;
import org.eclipse.cdt.internal.ui.search.actions.SelectionSearchGroup;
import org.eclipse.cdt.internal.ui.text.CPairMatcher;
import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration;
import org.eclipse.cdt.internal.ui.text.CTextTools;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
import org.eclipse.cdt.internal.ui.util.CUIHelp;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IWorkingCopyManager;
import org.eclipse.cdt.ui.PreferenceConstants;
import org.eclipse.cdt.ui.actions.RefactoringActionGroup;
import org.eclipse.cdt.ui.actions.ShowInCViewAction;
import org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ILineTracker;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.jface.text.source.ISharedTextColors;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionSupport;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.part.EditorActionBarContributor;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.part.ShowInContext;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
import org.eclipse.ui.texteditor.AnnotationPreference;
import org.eclipse.ui.texteditor.ContentAssistAction;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IEditorStatusLine;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.texteditor.TextOperationAction;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;


/**
 * C specific text editor.
 */
00124 public class CEditor extends TextEditor implements ISelectionChangedListener, IShowInSource , IReconcilingParticipant{

      /**
       * Updates the Java outline page selection and this editor's range indicator.
       * 
       * @since 3.0
       */
00131       private class EditorSelectionChangedListener extends AbstractSelectionChangedListener {
            
            /**
             * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
             */
00136             public void selectionChanged(SelectionChangedEvent event) {
                  // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161
                  CEditor.this.selectionChanged();
            }
      }
      
      /**
       * The editor selection changed listener.
       * 
       * @since 3.0
       */
00147       private EditorSelectionChangedListener fEditorSelectionChangedListener;
      

      /** The outline page */
00151       protected CContentOutlinePage fOutlinePage;
      
      /** Search actions **/
00154       private ActionGroup fSelectionSearchGroup;
    /** Groups refactoring actions. */
00156       private ActionGroup fRefactoringActionGroup;
    /** Action which shows selected element in CView. */
00158       private ShowInCViewAction fShowInCViewAction;
      
      /** Activity Listeners **/
00161       protected ISelectionChangedListener fStatusLineClearer;
    protected ISelectionChangedListener fSelectionUpdateListener;
      
      /** Pairs of brackets, used to match. */
00165     protected final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']', '<', '>' };

      /** Matches the brackets. */
00168     protected CPairMatcher fBracketMatcher = new CPairMatcher(BRACKETS);

      /** The editor's tab converter */
00171       private TabConverter fTabConverter;

      /** Listener to annotation model changes that updates the error tick in the tab image */
00174       private CEditorErrorTickUpdater fCEditorErrorTickUpdater;

      /** Preference key for matching brackets */
00177       public final static String MATCHING_BRACKETS = "matchingBrackets"; //$NON-NLS-1$
      /** Preference key for matching brackets color */
00179       public final static String MATCHING_BRACKETS_COLOR = "matchingBracketsColor"; //$NON-NLS-1$
      /** Preference key for inserting spaces rather than tabs */
00181       public final static String SPACES_FOR_TABS = "spacesForTabs"; //$NON-NLS-1$
      /** Preference key for linked position color */
00183       public final static String LINKED_POSITION_COLOR = "linkedPositionColor"; //$NON-NLS-1$

    /** Preference key for compiler task tags */
00186     private final static String TRANSLATION_TASK_TAGS= CCorePreferenceConstants.TRANSLATION_TASK_TAGS;

      /** 
       * This editor's projection support 
       */
00191       private ProjectionSupport fProjectionSupport;
      /** 
       * This editor's projection model updater 
       */
00195       private ICFoldingStructureProvider fProjectionModelUpdater;

      /**
       * The action group for folding.
       *  
       */
00201       private FoldingActionGroup fFoldingGroup;

      /**
       * Indicates whether this editor is about to update any annotation views.
       * @since 3.0
       */
00207       private boolean fIsUpdatingAnnotationViews= false;
      /**
       * The marker that served as last target for a goto marker request.
       * @since 3.0
       */
00212       private IMarker fLastMarkerTarget= null;

      /**
       * Default constructor.
       */
00217       public CEditor() {
            super();
      }

      /**
       * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
       */
00224       protected void initializeEditor() {
            CTextTools textTools = CUIPlugin.getDefault().getTextTools();
            setSourceViewerConfiguration(new CSourceViewerConfiguration(textTools, this));
            setDocumentProvider(CUIPlugin.getDefault().getDocumentProvider());
      
            setEditorContextMenuId("#CEditorContext"); //$NON-NLS-1$
            setRulerContextMenuId("#CEditorRulerContext"); //$NON-NLS-1$
            setOutlinerContextMenuId("#CEditorOutlinerContext"); //$NON-NLS-1$

            setPreferenceStore(CUIPlugin.getDefault().getCombinedPreferenceStore());
            fCEditorErrorTickUpdater = new CEditorErrorTickUpdater(this);          
      }

      /**
       * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetInput(org.eclipse.ui.IEditorInput)
       */
00240       protected void doSetInput(IEditorInput input) throws CoreException {
            super.doSetInput(input);
            setOutlinePageInput(fOutlinePage, input);

            if (fProjectionModelUpdater != null) {
                  fProjectionModelUpdater.initialize();
            }
            if (fCEditorErrorTickUpdater != null) {
                  fCEditorErrorTickUpdater.updateEditorImage(getInputCElement());
            }
      }

      /**
       * Update the title image.
     * @param image Title image.
       */
00256       public void updatedTitleImage(Image image) {
            setTitleImage(image);
      }

      /**
       * Returns the C element wrapped by this editors input.
       *
       * @return the C element wrapped by this editors input.
       * @since 3.0
       */
00266       public ICElement getInputCElement () {
            return CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(getEditorInput());
      }

      /**
       * Gets the current IFile input.
       * This method will be remove after cdt-3.0.
       * We can not guaranty that the input is an IFile, it may
       * an external file.  Clients should test for <code>null<code> or use getInputCElement()
       * @deprecated use <code>CEditor.getInputCElement()</code>.
     * @return IFile Input file or null if input is not and IFileEditorInput.
       */
00278       public IFile getInputFile() {       
            IEditorInput editorInput = getEditorInput();
            if (editorInput != null) {
                  if ((editorInput instanceof IFileEditorInput)) {
                        return ((IFileEditorInput) editorInput).getFile();
                  }
            }
            return null;
      }

      /**
     * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
       */
00291     public boolean isSaveAsAllowed() {
            return true;
      }
      /**
       * Gets the outline page of the c-editor.
     * @return Outline page.
       */
00298       public CContentOutlinePage getOutlinePage() {
            if (fOutlinePage == null) {
                  fOutlinePage = new CContentOutlinePage(this);
                  fOutlinePage.addSelectionChangedListener(this);
            }
            setOutlinePageInput(fOutlinePage, getEditorInput());
            return fOutlinePage;
      }

      /**
       * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
       */
00310       public Object getAdapter(Class required) {
            if (IContentOutlinePage.class.equals(required)) {
                  return getOutlinePage();
            }
            if (required == IShowInTargetList.class) {
                  return new IShowInTargetList() {
                        public String[] getShowInTargetIds() {
                              return new String[] { CUIPlugin.CVIEW_ID, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
                        }

                  };
            }
            if (ProjectionAnnotationModel.class.equals(required)) {
                  if (fProjectionSupport != null) {
                        Object adapter= fProjectionSupport.getAdapter(getSourceViewer(), required);
                        if (adapter != null)
                              return adapter;
                  }
            }
            return super.getAdapter(required);
      }
      /**
       * Handles a property change event describing a change
       * of the editor's preference store and updates the preference
       * related editor properties.
       * 
       * @param event the property change event
       */
00338       protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
            CSourceViewer asv = (CSourceViewer) getSourceViewer();

            try {
                  if (asv != null) {

                        String property = event.getProperty();

                        if (AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
                              SourceViewerConfiguration configuration = getSourceViewerConfiguration();
                              String[] types = configuration.getConfiguredContentTypes(asv);
                              for (int i = 0; i < types.length; i++) {
                                    asv.setIndentPrefixes(configuration.getIndentPrefixes(asv, types[i]), types[i]);
                              }

                              if (fTabConverter != null) {
                                    fTabConverter.setNumberOfSpacesPerTab(configuration.getTabWidth(asv));
                              }
                              // the super class handles the reset of the tabsize.
                              return;
                        }

                        if (SPACES_FOR_TABS.equals(property)) {
                              if (isTabConversionEnabled())
                                    startTabConversion();
                              else
                                    stopTabConversion();
                              return;
                        }
                        
                        // Not implemented ... for the future.
                        if (TRANSLATION_TASK_TAGS.equals(event.getProperty())) {
                              ISourceViewer sourceViewer= getSourceViewer();
                              if (sourceViewer != null && affectsTextPresentation(event))
                                    sourceViewer.invalidateTextPresentation();
                        }

                        if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
                              if (fProjectionModelUpdater != null) {
                                    fProjectionModelUpdater.uninstall();
                              }
                              // either freshly enabled or provider changed
                              fProjectionModelUpdater= CUIPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
                              if (fProjectionModelUpdater != null) {
                                    fProjectionModelUpdater.install(this, asv);
                              }
                              return;
                        }

                        IContentAssistant c= asv.getContentAssistant();
                        if (c instanceof ContentAssistant) {
                              ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
                        }
                        
                  }
            } finally {
                  super.handlePreferenceStoreChanged(event);
            }
      }

      /**
       * React to changed selection.
       * 
       * @since 3.0
       */
00403       protected void selectionChanged() {
            if (getSelectionProvider() == null)
                  return;
            updateStatusLine();
      }

      /**
       * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
       */
00412       public void selectionChanged(SelectionChangedEvent event) {
            ISelection sel = event.getSelection();
            if (sel instanceof IStructuredSelection) {
                  IStructuredSelection selection = (IStructuredSelection) sel;
                  Object obj = selection.getFirstElement();
                  if (obj instanceof ISourceReference) {
                        try {
                              ISourceRange range = ((ISourceReference) obj).getSourceRange();
                              if (range != null) {
                                    setSelection(range, !isActivePart());
                              }
                        } catch (CModelException e) {
                    // Selection change not applied.
                        }
                  }
            }
      }

      /**
     * Sets selection for C element. 
     * @param element Element to select.
       */
00434     public void setSelection(ICElement element) {

            if (element == null || element instanceof ITranslationUnit) {
                  /*
                   * If the element is an ITranslationUnit this unit is either the input
                   * of this editor or not being displayed. In both cases, nothing should
                   * happened.
                   */
                  return;
            }
            if (element instanceof ISourceReference) {
                  ISourceReference reference = (ISourceReference) element;
                  // set hightlight range
                  setSelection(reference, true);
            }
      }

    /**
     * Sets selection for source reference.
     * @param element Source reference to set.
     * @param moveCursor Should cursor be moved.
     */
00456     public void setSelection(ISourceReference element, boolean moveCursor) {
            if (element != null) {
                  StyledText  textWidget= null;
                  
                  ISourceViewer sourceViewer= getSourceViewer();
                  if (sourceViewer != null)
                        textWidget= sourceViewer.getTextWidget();
                  
                  if (textWidget == null)
                        return;

                  try {
                        setSelection(element.getSourceRange(), moveCursor);
                  } catch (CModelException e) {
                // Selection not applied.
                  }
            }
      }

      /**
       * Sets the current editor selection to the source range. Optionally
       * sets the current editor position.
       *
       * @param element the source range to be shown in the editor, can be null.
       * @param moveCursor if true the editor is scrolled to show the range.
       */
00482       public void setSelection(ISourceRange element, boolean moveCursor) {

            if (element == null) {
                  return;
            }

            try {
                  IRegion alternateRegion = null;
                  int start = element.getStartPos();
                  int length = element.getLength();

                  // Sanity check sometimes the parser may throw wrong numbers.
                  if (start < 0 || length < 0) {
                        start = 0;
                        length = 0;
                  }

                  // 0 length and start and non-zero start line says we know
                  // the line for some reason, but not the offset.
                  if (length == 0 && start == 0 && element.getStartLine() > 0) {
                        // We have the information in term of lines, we can work it out.
                        // Binary elements return the first executable statement so we have to substract -1
                        start = getDocumentProvider().getDocument(getEditorInput()).getLineOffset(element.getStartLine() - 1);
                        if (element.getEndLine() > 0) {
                              length = getDocumentProvider().getDocument(getEditorInput()).getLineOffset(element.getEndLine()) - start;
                        } else {
                              length = start;
                        }
                        // create an alternate region for the keyword highlight.
                        alternateRegion = getDocumentProvider().getDocument(getEditorInput()).getLineInformation(element.getStartLine() - 1);
                        if (start == length || length < 0) {
                              if (alternateRegion != null) {
                                    start = alternateRegion.getOffset();
                                    length = alternateRegion.getLength();
                              }
                        }
                  }
                  setHighlightRange(start, length, moveCursor);

                  if (moveCursor) {
                        start = element.getIdStartPos();
                        length = element.getIdLength();
                        if (start == 0 && length == 0 && alternateRegion != null) {
                              start = alternateRegion.getOffset();
                              length = alternateRegion.getLength();
                        }
                        if (start > -1 && getSourceViewer() != null) {
                              getSourceViewer().revealRange(start, length);
                              getSourceViewer().setSelectedRange(start, length);
                        }
                        updateStatusField(CTextEditorActionConstants.STATUS_CURSOR_POS);
                  }
                  return;
            } catch (IllegalArgumentException x) {
            // No information to the user
            } catch (BadLocationException e) {
            // No information to the user
            }

            if (moveCursor)
                  resetHighlightRange();
      }

      /**
     * Checks is the editor active part. 
     * @return <code>true</code> if editor is the active part of the workbench.
       */
00549     private boolean isActivePart() {
            IWorkbenchWindow window = getSite().getWorkbenchWindow();
            IPartService service = window.getPartService();
            return (this == service.getActivePart());
      }

    /**
     * @see org.eclipse.ui.IWorkbenchPart#dispose()
     */
00558     public void dispose() {

            if (fProjectionModelUpdater != null) {
                  fProjectionModelUpdater.uninstall();
                  fProjectionModelUpdater= null;
            }
            
            if (fProjectionSupport != null) {
                  fProjectionSupport.dispose();
                  fProjectionSupport= null;
            }

            if (fCEditorErrorTickUpdater != null) {
                  fCEditorErrorTickUpdater.dispose();
                  fCEditorErrorTickUpdater = null;
            }
            
        final CSourceViewer sourceViewer = (CSourceViewer) getSourceViewer();
        if (fSelectionUpdateListener != null) {
                  getSelectionProvider().addSelectionChangedListener(fSelectionUpdateListener);
                  fSelectionUpdateListener = null;
        }
        
            if (fStatusLineClearer != null) {
                  ISelectionProvider provider = getSelectionProvider();
                  provider.removeSelectionChangedListener(fStatusLineClearer);
                  fStatusLineClearer = null;
            }
        
        if (fBracketMatcher != null) {
                  fBracketMatcher.dispose();
                  fBracketMatcher = null;
            }
            
            if (fOutlinePage != null) {
                  fOutlinePage.dispose();
                  fOutlinePage = null;
            }
            
            if (fShowInCViewAction != null) {
                  fShowInCViewAction.dispose();
                  fShowInCViewAction = null;
            }
            
            if (fRefactoringActionGroup != null) {
                  fRefactoringActionGroup.dispose();
                  fRefactoringActionGroup = null;
            }
            
            if (fSelectionSearchGroup != null) {
                  fSelectionSearchGroup.dispose();
                  fSelectionSearchGroup = null;
            }

            if (fEditorSelectionChangedListener != null)  {
                  fEditorSelectionChangedListener.uninstall(getSelectionProvider());
                  fEditorSelectionChangedListener= null;
            }

            stopTabConversion();
            
            super.dispose();
      }

      /**
       * @see org.eclipse.ui.texteditor.AbstractTextEditor#canHandleMove(org.eclipse.ui.IEditorInput, org.eclipse.ui.IEditorInput)
       */
00625       protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
            String oldLanguage = ""; //$NON-NLS-1$
            if (originalElement instanceof IFileEditorInput) {
                  IFile file= ((IFileEditorInput) originalElement).getFile();
                  if (file != null) {
                        IContentType type = CCorePlugin.getContentType(file.getProject(), file.getName());
                        if (type != null) {
                              oldLanguage = type.getId();
                        }
                        if (oldLanguage == null) {
                              return false;
                        }
                  }
            }

            String newLanguage = ""; //$NON-NLS-1$
            if (movedElement instanceof IFileEditorInput) {
                  IFile file = ((IFileEditorInput) movedElement).getFile();
                  if (file != null) {
                        IContentType type = CCorePlugin.getContentType(file.getProject(), file.getName());
                        if (type != null) {
                              newLanguage = type.getId();
                        }
                        if (newLanguage == null) {
                              return false;
                        }
                  }
            }
            return oldLanguage.equals(newLanguage);
      }

      /**
       * @see org.eclipse.ui.texteditor.AbstractTextEditor#createActions()
       */
00659       protected void createActions() {
            super.createActions();

            fFoldingGroup= new FoldingActionGroup(this, getSourceViewer());

            // Default text editing menu items
            Action action= new GotoMatchingBracketAction(this);
            action.setActionDefinitionId(ICEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);                      
            setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);

            action = new TextOperationAction(CEditorMessages.getResourceBundle(), "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
            action.setActionDefinitionId(ICEditorActionDefinitionIds.COMMENT);
            setAction("Comment", action); //$NON-NLS-1$
            markAsStateDependentAction("Comment", true); //$NON-NLS-1$

            action = new TextOperationAction(CEditorMessages.getResourceBundle(), "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
            action.setActionDefinitionId(ICEditorActionDefinitionIds.UNCOMMENT);
            setAction("Uncomment", action); //$NON-NLS-1$
            markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$

            action= new AddBlockCommentAction(CEditorMessages.getResourceBundle(), "AddBlockComment.", this);  //$NON-NLS-1$
            action.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_BLOCK_COMMENT);        
            setAction("AddBlockComment", action); //$NON-NLS-1$
            markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
            markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$        
            //WorkbenchHelp.setHelp(action, ICHelpContextIds.ADD_BLOCK_COMMENT_ACTION);

            action= new RemoveBlockCommentAction(CEditorMessages.getResourceBundle(), "RemoveBlockComment.", this);  //$NON-NLS-1$
            action.setActionDefinitionId(ICEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);           
            setAction("RemoveBlockComment", action); //$NON-NLS-1$
            markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
            markAsSelectionDependentAction("RemoveBlockComment", true); //$NON-NLS-1$           
            //WorkbenchHelp.setHelp(action, ICHelpContextIds.REMOVE_BLOCK_COMMENT_ACTION);

            action = new TextOperationAction(CEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
            action.setActionDefinitionId(ICEditorActionDefinitionIds.FORMAT);
            setAction("Format", action); //$NON-NLS-1$
            markAsStateDependentAction("Format", true); //$NON-NLS-1$

            action = new ContentAssistAction(CEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
            action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
            setAction("ContentAssistProposal", action); //$NON-NLS-1$
            markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$

            action = new TextOperationAction(CEditorMessages.getResourceBundle(), "ContentAssistTip.", this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
            action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
            setAction("ContentAssistTip", action); //$NON-NLS-1$

            action = new AddIncludeOnSelectionAction(this);
            action.setActionDefinitionId(ICEditorActionDefinitionIds.ADD_INCLUDE);
            setAction("AddIncludeOnSelection", action); //$NON-NLS-1$
      
            action = new OpenDeclarationsAction(this);
            action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_DECL);
            setAction("OpenDeclarations", action); //$NON-NLS-1$

        action = new OpenDefinitionAction(this);
        action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_DEF);
        setAction("OpenDefinition", action); //$NON-NLS-1$
        
//          action = new OpenTypeHierarchyAction(this);
//          action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_TYPE_HIERARCHY);
//          setAction("OpenTypeHierarchy", action); //$NON-NLS-1$

            fShowInCViewAction = new ShowInCViewAction(this);
            action = fShowInCViewAction;
            action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_CVIEW);
            setAction("ShowInCView", action); //$NON-NLS-1$
        
        action = new TextOperationAction(CEditorMessages.getResourceBundle(), "OpenOutline.", this, CSourceViewer.SHOW_OUTLINE); //$NON-NLS-1$
        action.setActionDefinitionId(ICEditorActionDefinitionIds.OPEN_OUTLINE);
        setAction("OpenOutline", action); //$NON-NLS-1$*/
        
        action = new GoToNextPreviousMemberAction(CEditorMessages.getResourceBundle(), "GotoNextMember.", this, true); //$NON-NLS-1$
        action.setActionDefinitionId(ICEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
        setAction("GotoNextMember", action); //$NON-NLS-1$*/

        action = new GoToNextPreviousMemberAction(CEditorMessages.getResourceBundle(), "GotoPrevMember.", this, false); //$NON-NLS-1$
        action.setActionDefinitionId(ICEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
        setAction("GotoPrevMember", action); //$NON-NLS-1$*/

        //Assorted action groupings
            fSelectionSearchGroup = new SelectionSearchGroup(this);
            fRefactoringActionGroup = new RefactoringActionGroup(this, null);       
      }

      /**
       * @see org.eclipse.ui.texteditor.AbstractTextEditor#editorContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
       */
00748       public void editorContextMenuAboutToShow(IMenuManager menu) {
            super.editorContextMenuAboutToShow(menu);

            addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_REORGANIZE);
            addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_GENERATE);
            addGroup(menu, ITextEditorActionConstants.GROUP_EDIT, IContextMenuConstants.GROUP_NEW);

            // Code formatting menu items -- only show in C perspective
            addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Comment"); //$NON-NLS-1$
            addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Uncomment"); //$NON-NLS-1$
            addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "AddBlockComment"); //$NON-NLS-1$
            addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "RemoveBlockComment"); //$NON-NLS-1$

            addAction(menu, ITextEditorActionConstants.GROUP_FIND, "OpenDeclarations"); //$NON-NLS-1$
        addAction(menu, ITextEditorActionConstants.GROUP_FIND, "OpenDefinition"); //$NON-NLS-1$

            addAction(menu, ITextEditorActionConstants.GROUP_FIND, "OpenTypeHierarchy"); //$NON-NLS-1$
        addAction(menu, ITextEditorActionConstants.GROUP_FIND, "GotoNextMember"); //$NON-NLS-1$
        addAction(menu, ITextEditorActionConstants.GROUP_FIND, "GotoPrevMember"); //$NON-NLS-1$

            addAction(menu, IContextMenuConstants.GROUP_GENERATE, "ContentAssistProposal"); //$NON-NLS-1$
            addAction(menu, IContextMenuConstants.GROUP_GENERATE, "AddIncludeOnSelection"); //$NON-NLS-1$
            addAction(menu, IContextMenuConstants.GROUP_GENERATE, "Format"); //$NON-NLS-1$
            
            addAction(menu, IContextMenuConstants.GROUP_GENERATE, "ShowInCView"); //$NON-NLS-1$

        fRefactoringActionGroup.fillContextMenu(menu);
            fSelectionSearchGroup.fillContextMenu(menu);
      
      }

      /**
     * Sets an input for the outline page.
       * @param page Page to set the input.
       * @param input Input to set.
       */
00784       public static void setOutlinePageInput(CContentOutlinePage page, IEditorInput input) {
            if (page != null) {
                  IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
                  page.setInput(manager.getWorkingCopy(input));
            }
      }

      /**
     * Determines is folding enabled.
       * @return <code>true</code> if folding is enabled, <code>false</code> otherwise.
       */
00795       boolean isFoldingEnabled() {
            return CUIPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
      }


      /**
       * The <code>AbstractTextEditor</code> implementation of this 
       * <code>IWorkbenchPart</code> method creates the vertical ruler and
       * source viewer. Subclasses may extend.
       * 
       * We attach our own mouseDown listener on the menu bar, 
       * and our own listener for cursor/key/selection events to update cursor position in
       * status bar.

     * @param parent Parent composite of the control.
       */
00811       public void createPartControl(Composite parent) {
            super.createPartControl(parent);

            ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer();
            
            fProjectionSupport= new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
            fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
            fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
            fProjectionSupport.install();
            
            fProjectionModelUpdater= CUIPlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
            if (fProjectionModelUpdater != null)
                  fProjectionModelUpdater.install(this, projectionViewer);

            if (isFoldingEnabled())
                  projectionViewer.doOperation(ProjectionViewer.TOGGLE);
            

            PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, ICHelpContextIds.CEDITOR_VIEW);

            fEditorSelectionChangedListener= new EditorSelectionChangedListener();
            fEditorSelectionChangedListener.install(getSelectionProvider());
            

            if (isTabConversionEnabled())
                  startTabConversion();
                  
      }

      /* (non-Javadoc)
       * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#gotoMarker(org.eclipse.core.resources.IMarker)
       */
      public void gotoMarker(IMarker marker) {
            fLastMarkerTarget= marker;
            if (!fIsUpdatingAnnotationViews) {
                super.gotoMarker(marker);
            }
      }
      
      /**
       * Jumps to the next enabled annotation according to the given direction.
       * An annotation type is enabled if it is configured to be in the
       * Next/Previous tool bar drop down menu and if it is checked.
       * 
       * @param forward <code>true</code> if search direction is forward, <code>false</code> if backward
       */
00857       public void gotoAnnotation(boolean forward) {
            ITextSelection selection= (ITextSelection) getSelectionProvider().getSelection();
            Position position= new Position(0, 0);
            if (false /* delayed - see bug 18316 */) {
                  getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
                  selectAndReveal(position.getOffset(), position.getLength());
            } else /* no delay - see bug 18316 */ {
                  Annotation annotation= getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
                  setStatusLineErrorMessage(null);
                  setStatusLineMessage(null);
                  if (annotation != null) {
                        updateAnnotationViews(annotation);
                        selectAndReveal(position.getOffset(), position.getLength());
                        setStatusLineMessage(annotation.getText());
                  }
            }
      }

      /**
       * Jumps to the matching bracket.
       */
00878       public void gotoMatchingBracket() {
            
            ISourceViewer sourceViewer= getSourceViewer();
            IDocument document= sourceViewer.getDocument();
            if (document == null)
                  return;
            
            IRegion selection= getSignedSelection(sourceViewer);

            int selectionLength= Math.abs(selection.getLength());
            if (selectionLength > 1) {
                  setStatusLineErrorMessage(CEditorMessages.getString("GotoMatchingBracket.error.invalidSelection"));   //$NON-NLS-1$           
                  sourceViewer.getTextWidget().getDisplay().beep();
                  return;
            }

            // #26314
            int sourceCaretOffset= selection.getOffset() + selection.getLength();
            if (isSurroundedByBrackets(document, sourceCaretOffset))
                  sourceCaretOffset -= selection.getLength();

            IRegion region= fBracketMatcher.match(document, sourceCaretOffset);
            if (region == null) {
                  setStatusLineErrorMessage(CEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket"));  //$NON-NLS-1$           
                  sourceViewer.getTextWidget().getDisplay().beep();
                  return;           
            }
            
            int offset= region.getOffset();
            int length= region.getLength();
            
            if (length < 1)
                  return;
                  
            int anchor= fBracketMatcher.getAnchor();
            // http://dev.eclipse.org/bugs/show_bug.cgi?id=34195
            int targetOffset= (ICharacterPairMatcher.RIGHT == anchor) ? offset + 1: offset + length;
            
            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) {
                  setStatusLineErrorMessage(CEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement"));  //$NON-NLS-1$           
                  sourceViewer.getTextWidget().getDisplay().beep();
                  return;
            }
            
            if (selection.getLength() < 0)
                  targetOffset -= selection.getLength();
                  
            sourceViewer.setSelectedRange(targetOffset, selection.getLength());
            sourceViewer.revealRange(targetOffset, selection.getLength());
      }


      /**
       * Returns whether the given annotation is configured as a target for the
       * "Go to Next/Previous Annotation" actions
       * 
       * @param annotation the annotation
       * @return <code>true</code> if this is a target, <code>false</code>
       *         otherwise
       * @since 3.0
       */
00949       private boolean isNavigationTarget(Annotation annotation) {
            Preferences preferences= EditorsUI.getPluginPreferences();
            AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
//          See bug 41689
//          String key= forward ? preference.getIsGoToNextNavigationTargetKey() : preference.getIsGoToPreviousNavigationTargetKey();
            String key= preference == null ? null : preference.getIsGoToNextNavigationTargetKey();
            return (key != null && preferences.getBoolean(key));
      }
      
      /**
       * Returns the annotation closest to the given range respecting the given
       * direction. If an annotation is found, the annotations current position
       * is copied into the provided annotation position.
       * 
       * @param offset the region offset
       * @param length the region length
       * @param forward <code>true</code> for forwards, <code>false</code> for backward
       * @param annotationPosition the position of the found annotation
       * @return the found annotation
       */
00969       private Annotation getNextAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) {
            
            Annotation nextAnnotation= null;
            Position nextAnnotationPosition= null;
            Annotation containingAnnotation= null;
            Position containingAnnotationPosition= null;
            boolean currentAnnotation= false;
            
            IDocument document= getDocumentProvider().getDocument(getEditorInput());
            int endOfDocument= document.getLength(); 
            int distance= Integer.MAX_VALUE;
            
            IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
            Iterator e= new CAnnotationIterator(model, true, true);
            while (e.hasNext()) {
                  Annotation a= (Annotation) e.next();
                  if ((a instanceof ICAnnotation) && ((ICAnnotation)a).hasOverlay() || !isNavigationTarget(a))
                        continue;
                        
                  Position p= model.getPosition(a);
                  if (p == null)
                        continue;
                  
                  if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || p.includes(offset)) {
                        if (containingAnnotation == null || (forward && p.length >= containingAnnotationPosition.length || !forward && p.length >= containingAnnotationPosition.length)) { 
                              containingAnnotation= a;
                              containingAnnotationPosition= p;
                              currentAnnotation= (p.length == length) || (p.length - 1 == length);
                        }
                  } else {
                        int currentDistance= 0;
                        
                        if (forward) {
                              currentDistance= p.getOffset() - offset;
                              if (currentDistance < 0)
                                    currentDistance= endOfDocument + currentDistance;
                              
                              if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
                                    distance= currentDistance;
                                    nextAnnotation= a;
                                    nextAnnotationPosition= p;
                              }
                        } else {
                              currentDistance= offset + length - (p.getOffset() + p.length);
                              if (currentDistance < 0)
                                    currentDistance= endOfDocument + currentDistance;
                              
                              if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
                                    distance= currentDistance;
                                    nextAnnotation= a;
                                    nextAnnotationPosition= p;
                              }
                        }
                  }
            }
            if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) {
                  annotationPosition.setOffset(containingAnnotationPosition.getOffset());
                  annotationPosition.setLength(containingAnnotationPosition.getLength());
                  return containingAnnotation;
            }
            if (nextAnnotationPosition != null) {
                  annotationPosition.setOffset(nextAnnotationPosition.getOffset());
                  annotationPosition.setLength(nextAnnotationPosition.getLength());
            }
            
            return nextAnnotation;
      }

      protected void updateStatusLine() {
            ITextSelection selection= (ITextSelection) getSelectionProvider().getSelection();
            Annotation annotation= getAnnotation(selection.getOffset(), selection.getLength());
            setStatusLineErrorMessage(null);
            setStatusLineMessage(null);
            if (annotation != null) {
                  try {
                        fIsUpdatingAnnotationViews= true;
                        updateAnnotationViews(annotation);
                  } finally {
                        fIsUpdatingAnnotationViews= false;
                  }
                  if (annotation instanceof ICAnnotation && ((ICAnnotation) annotation).isProblem())
                        setStatusLineMessage(annotation.getText());
            }
      }

      /**
       * Updates the annotation views that show the given annotation.
       * 
       * @param annotation the annotation
       */
01059       private void updateAnnotationViews(Annotation annotation) {
            IMarker marker= null;
            if (annotation instanceof MarkerAnnotation)
                  marker= ((MarkerAnnotation) annotation).getMarker();
            else if (annotation instanceof ICAnnotation) {
                  Iterator e= ((ICAnnotation) annotation).getOverlaidIterator();
                  if (e != null) {
                        while (e.hasNext()) {
                              Object o= e.next();
                              if (o instanceof MarkerAnnotation) {
                                    marker= ((MarkerAnnotation) o).getMarker();
                                    break;
                              }
                        }
                  }
            }
                  
            if (marker != null && !marker.equals(fLastMarkerTarget)) {
                  try {
                        boolean isProblem= marker.isSubtypeOf(IMarker.PROBLEM);
                        IWorkbenchPage page= getSite().getPage();
                        IViewPart view= page.findView(isProblem ? IPageLayout.ID_PROBLEM_VIEW: IPageLayout.ID_TASK_LIST); //$NON-NLS-1$  //$NON-NLS-2$
                        if (view != null) {
                              Method method= view.getClass().getMethod("setSelection", new Class[] { IStructuredSelection.class, boolean.class}); //$NON-NLS-1$
                              method.invoke(view, new Object[] {new StructuredSelection(marker), Boolean.TRUE });
                        }
                  } catch (CoreException x) {
                  } catch (NoSuchMethodException x) {
                  } catch (IllegalAccessException x) {
                  } catch (InvocationTargetException x) {
                  }
                  // ignore exceptions, don't update any of the lists, just set status line
            }                 
      }

      /**
       * Returns the annotation overlapping with the given range or <code>null</code>.
       * 
       * @param offset the region offset
       * @param length the region length
       * @return the found annotation or <code>null</code>
       * @since 3.0
       */
01102       private Annotation getAnnotation(int offset, int length) {
            IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
            Iterator e= new CAnnotationIterator(model, true, true);
            while (e.hasNext()) {
                  Annotation a= (Annotation) e.next();
                  if (!isNavigationTarget(a))
                        continue;
                        
                  Position p= model.getPosition(a);
                  if (p != null && p.overlapsWith(offset, length))
                        return a;
            }
            
            return null;
      }
      /* (non-Javadoc)
       * @see org.eclipse.ui.part.IShowInSource#getShowInContext()
       *
       * This is required by the IShowInSource interface for the "ShowIn"
      * navigation menu generalized in Eclipse.
       */
      public ShowInContext getShowInContext() {
            return new ShowInContext( getEditorInput(), null );
      }

      /*
       * Get the dektop's StatusLineManager
       */
      protected IStatusLineManager getStatusLineManager() {
            IEditorActionBarContributor contributor = getEditorSite().getActionBarContributor();
            if (contributor instanceof EditorActionBarContributor) {
                  return ((EditorActionBarContributor) contributor).getActionBars().getStatusLineManager();
            }
            return null;
      }

      private void configureTabConverter() {
            if (fTabConverter != null) {
                  IDocumentProvider provider= getDocumentProvider();
                  if (provider instanceof CDocumentProvider) {
                        CDocumentProvider prov= (CDocumentProvider) provider;
                        fTabConverter.setLineTracker(prov.createLineTracker(getEditorInput()));
                  } else {
                        fTabConverter.setLineTracker(new DefaultLineTracker());
                  }
            }
      }

      private void startTabConversion() {
            if (fTabConverter == null) {
                  CSourceViewer asv = (CSourceViewer) getSourceViewer();
                  SourceViewerConfiguration configuration = getSourceViewerConfiguration();
                  fTabConverter = new TabConverter();
                  configureTabConverter();
                  fTabConverter.setNumberOfSpacesPerTab(configuration.getTabWidth(asv));
                  asv.addTextConverter(fTabConverter);
            }
      }

      private void stopTabConversion() {
            if (fTabConverter != null) {
                  CSourceViewer asv = (CSourceViewer) getSourceViewer();
                  asv.removeTextConverter(fTabConverter);
                  fTabConverter = null;
            }
      }

      private boolean isTabConversionEnabled() {
            IPreferenceStore store = getPreferenceStore();
            return store.getBoolean(SPACES_FOR_TABS);
      }

      interface ITextConverter {
            void customizeDocumentCommand(IDocument document, DocumentCommand command);
      }

      static class TabConverter implements ITextConverter {
            private int fTabRatio;
            private ILineTracker fLineTracker;
            
            public TabConverter() {
            } 
            
            public void setNumberOfSpacesPerTab(int ratio) {
                  fTabRatio= ratio;
            }
            
            public void setLineTracker(ILineTracker lineTracker) {
                  fLineTracker= lineTracker;
            }
            
            private int insertTabString(StringBuffer buffer, int offsetInLine) {
                  
                  if (fTabRatio == 0)
                        return 0;
                        
                  int remainder= offsetInLine % fTabRatio;
                  remainder= fTabRatio - remainder;
                  for (int i= 0; i < remainder; i++)
                        buffer.append(' ');
                  return remainder;
            }
            
            public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
                  String text= command.text;
                  if (text == null)
                        return;
                        
                  int index= text.indexOf('\t');
                  if (index > -1) {
                        
                        StringBuffer buffer= new StringBuffer();
                        
                        fLineTracker.set(command.text);
                        int lines= fLineTracker.getNumberOfLines();
                        
                        try {
                                    
                                    for (int i= 0; i < lines; i++) {
                                          
                                          int offset= fLineTracker.getLineOffset(i);
                                          int endOffset= offset + fLineTracker.getLineLength(i);
                                          String line= text.substring(offset, endOffset);
                                          
                                          int position= 0;
                                          if (i == 0) {
                                                IRegion firstLine= document.getLineInformationOfOffset(command.offset);
                                                position= command.offset - firstLine.getOffset();     
                                          }
                                          
                                          int length= line.length();
                                          for (int j= 0; j < length; j++) {
                                                char c= line.charAt(j);
                                                if (c == '\t') {
                                                      position += insertTabString(buffer, position);
                                                } else {
                                                      buffer.append(c);
                                                      ++ position;
                                                }
                                          }
                                          
                                    }
                                    
                                    command.text= buffer.toString();
                                    
                        } catch (BadLocationException x) {
                        }
                  }
            }

      }

      /* Source code language to display */
      public final static String LANGUAGE_CPP = "CEditor.language.cpp"; //$NON-NLS-1$
      public final static String LANGUAGE_C = "CEditor.language.c"; //$NON-NLS-1$

      /*
       * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
       */
      protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
            // Figure out if this is a C or C++ source file
            IWorkingCopyManager mgr = CUIPlugin.getDefault().getWorkingCopyManager();
            ITranslationUnit unit = mgr.getWorkingCopy(getEditorInput());
            String fileType = LANGUAGE_CPP;
            if (unit != null) {
                  // default is C++ unless the project as C Nature Only
                  // we can then be smarter.
                  IProject p = unit.getCProject().getProject();
                  if (!CoreModel.hasCCNature(p)) {
                        fileType = unit.isCXXLanguage() ? LANGUAGE_CPP : LANGUAGE_C;
                  }
            }

            fAnnotationAccess = createAnnotationAccess();
            
            ISharedTextColors sharedColors = CUIPlugin.getDefault().getSharedTextColors();
            fOverviewRuler = createOverviewRuler(sharedColors);

            ISourceViewer sourceViewer =
                  new CSourceViewer(
                        this, parent,
                        ruler,
                        styles,
                        fOverviewRuler,
                        isOverviewRulerVisible(),
                        fileType);
            fSourceViewerDecorationSupport =
                  new SourceViewerDecorationSupport(sourceViewer, fOverviewRuler, fAnnotationAccess, sharedColors);
            
            configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);

            //Enhance the stock source viewer decorator with a bracket matcher
            fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
            fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);

            CUIHelp.setHelp(this, sourceViewer.getTextWidget(), ICHelpContextIds.CEDITOR_VIEW);

            return sourceViewer;
      }

      /** Outliner context menu Id */
01303       protected String fOutlinerContextMenuId;

      /**
       * Sets the outliner's context menu ID.
       */
01308       protected void setOutlinerContextMenuId(String menuId) {
            fOutlinerContextMenuId = menuId;
      }
      
      /* (non-Javadoc)
       * @see org.eclipse.ui.editors.text.TextEditor#initializeKeyBindingScopes()
       */
      protected void initializeKeyBindingScopes() {
            setKeyBindingScopes(new String [] { "org.eclipse.cdt.ui.cEditorScope" } ); //$NON-NLS-1$
      }

      /* (non-Javadoc)
       * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
       */
      protected boolean affectsTextPresentation(PropertyChangeEvent event) {
            SourceViewerConfiguration configuration = getSourceViewerConfiguration();
            if (configuration instanceof CSourceViewerConfiguration) {
                  return ((CSourceViewerConfiguration)configuration).affectsBehavior(event);
            }
            return false;
      }

      /**
       * Returns the folding action group, or <code>null</code> if there is none.
       * 
       * @return the folding action group, or <code>null</code> if there is none
       */
01335       protected FoldingActionGroup getFoldingActionGroup() {
            return fFoldingGroup;
      }

      /*
       * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert()
       */
      protected void performRevert() {
            ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer();
            projectionViewer.setRedraw(false);
            try {
                  
                  boolean projectionMode= projectionViewer.isProjectionMode();
                  if (projectionMode) {
                        projectionViewer.disableProjection();                       
                        if (fProjectionModelUpdater != null)
                              fProjectionModelUpdater.uninstall();
                  }
                  
                  super.performRevert();
                  
                  if (projectionMode) {
                        if (fProjectionModelUpdater != null)
                              fProjectionModelUpdater.install(this, projectionViewer);    
                        projectionViewer.enableProjection();
                  }
                  
            } finally {
                  projectionViewer.setRedraw(true);
            }
      }

    /**
     * Sets the given message as error message to this editor's status line.
     * 
     * @param msg message to be set
     */
01372     protected void setStatusLineErrorMessage(String msg) {
      IEditorStatusLine statusLine= (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
      if (statusLine != null)
            statusLine.setMessage(true, msg, null);   

    }  

      /**
       * Sets the given message as message to this editor's status line.
       * 
       * @param msg message to be set
       * @since 3.0
       */
01385       protected void setStatusLineMessage(String msg) {
            IEditorStatusLine statusLine= (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
            if (statusLine != null)
                  statusLine.setMessage(false, msg, null);  
      }

      /**
       * Returns the signed current selection.
       * The length will be negative if the resulting selection
       * is right-to-left (RtoL).
       * <p>
       * The selection offset is model based.
       * </p>
       * 
       * @param sourceViewer the source viewer
       * @return a region denoting the current signed selection, for a resulting RtoL selections length is < 0 
       */
01402       protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
            StyledText text= sourceViewer.getTextWidget();
            Point selection= text.getSelectionRange();
            
            if (text.getCaretOffset() == selection.x) {
                  selection.x= selection.x + selection.y;
                  selection.y= -selection.y;
            }
            
            selection.x= widgetOffset2ModelOffset(sourceViewer, selection.x);
            
            return new Region(selection.x, selection.y);
      }
      
      private static boolean isBracket(char character) {
            for (int i= 0; i != BRACKETS.length; ++i)
                  if (character == BRACKETS[i])
                        return true;
            return false;
      }

      private static boolean isSurroundedByBrackets(IDocument document, int offset) {
            if (offset == 0 || offset == document.getLength())
                  return false;

            try {
                  return
                        isBracket(document.getChar(offset - 1)) &&
                        isBracket(document.getChar(offset));
                  
            } catch (BadLocationException e) {
                  return false;     
            }
      }
            

      /* (non-Javadoc)
       * @see org.eclipse.cdt.internal.ui.editor.IReconcilingParticipant#reconciled()
       */
01441       public void reconciled(boolean somethingHasChanged) {
            // Do nothing the outliner is listener to the
            // CoreModel WorkingCopy changes instead.
            // It will allow more fined grained.
      }
}

Generated by  Doxygen 1.6.0   Back to index