Package org.eclipse.wst.sse.ui

Source Code of org.eclipse.wst.sse.ui.StructuredTextEditor$StructuredSelectionProvider

/*******************************************************************************
* Copyright (c) 2001, 2011 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
*     Jens Lukowski/Innoopract - initial renaming/restructuring
*    
*******************************************************************************/
package org.eclipse.wst.sse.ui;

import java.io.IOException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget;
import org.eclipse.emf.common.command.Command;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IBlockTextSelection;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ISelectionValidator;
import org.eclipse.jface.text.ITextHover;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.information.IInformationPresenter;
import org.eclipse.jface.text.information.IInformationProvider;
import org.eclipse.jface.text.information.InformationPresenter;
import org.eclipse.jface.text.reconciler.IReconciler;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.ContentAssistantFacade;
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.LineChangeHover;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
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.util.SafeRunnable;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IPostSelectionProvider;
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.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.ITextEditorHelpContextIds;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.help.IWorkbenchHelpSystem;
import org.eclipse.ui.part.IShowInTargetList;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
import org.eclipse.ui.texteditor.ChainedPreferenceStore;
import org.eclipse.ui.texteditor.DefaultRangeIndicator;
import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IStatusField;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.ITextEditorExtension;
import org.eclipse.ui.texteditor.ITextEditorExtension2;
import org.eclipse.ui.texteditor.ITextEditorExtension3;
import org.eclipse.ui.texteditor.ITextEditorExtension4;
import org.eclipse.ui.texteditor.ITextEditorExtension5;
import org.eclipse.ui.texteditor.IUpdate;
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
import org.eclipse.ui.texteditor.TextOperationAction;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.document.IDocumentCharsetDetector;
import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
import org.eclipse.wst.sse.core.internal.provisional.IModelStateListener;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.text.IExecutionDelegatable;
import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
import org.eclipse.wst.sse.ui.internal.ExtendedEditorActionBuilder;
import org.eclipse.wst.sse.ui.internal.ExtendedEditorDropTargetAdapter;
import org.eclipse.wst.sse.ui.internal.IExtendedContributor;
import org.eclipse.wst.sse.ui.internal.IModelProvider;
import org.eclipse.wst.sse.ui.internal.IPopupMenuContributor;
import org.eclipse.wst.sse.ui.internal.IStructuredTextEditorActionConstants;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.ReadOnlyAwareDropTargetAdapter;
import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
import org.eclipse.wst.sse.ui.internal.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.StorageModelProvider;
import org.eclipse.wst.sse.ui.internal.StructuredTextViewer;
import org.eclipse.wst.sse.ui.internal.UnknownContentTypeDialog;
import org.eclipse.wst.sse.ui.internal.actions.ActionDefinitionIds;
import org.eclipse.wst.sse.ui.internal.actions.StructuredTextEditorActionConstants;
import org.eclipse.wst.sse.ui.internal.contentoutline.ConfigurableContentOutlinePage;
import org.eclipse.wst.sse.ui.internal.debug.BreakpointRulerAction;
import org.eclipse.wst.sse.ui.internal.debug.EditBreakpointAction;
import org.eclipse.wst.sse.ui.internal.debug.ManageBreakpointAction;
import org.eclipse.wst.sse.ui.internal.debug.ToggleBreakpointAction;
import org.eclipse.wst.sse.ui.internal.debug.ToggleBreakpointsTarget;
import org.eclipse.wst.sse.ui.internal.derived.HTMLTextPresenter;
import org.eclipse.wst.sse.ui.internal.editor.EditorModelUtil;
import org.eclipse.wst.sse.ui.internal.editor.IHelpContextIds;
import org.eclipse.wst.sse.ui.internal.editor.SelectionConvertor;
import org.eclipse.wst.sse.ui.internal.editor.StructuredModelDocumentProvider;
import org.eclipse.wst.sse.ui.internal.extension.BreakpointProviderBuilder;
import org.eclipse.wst.sse.ui.internal.handlers.AddBlockCommentHandler;
import org.eclipse.wst.sse.ui.internal.handlers.RemoveBlockCommentHandler;
import org.eclipse.wst.sse.ui.internal.handlers.ToggleLineCommentHandler;
import org.eclipse.wst.sse.ui.internal.hyperlink.OpenHyperlinkAction;
import org.eclipse.wst.sse.ui.internal.preferences.EditorPreferenceNames;
import org.eclipse.wst.sse.ui.internal.projection.AbstractStructuredFoldingStrategy;
import org.eclipse.wst.sse.ui.internal.properties.ConfigurablePropertySheetPage;
import org.eclipse.wst.sse.ui.internal.properties.ShowPropertiesAction;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.ConfigurationPointCalculator;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
import org.eclipse.wst.sse.ui.internal.provisional.extensions.breakpoint.NullSourceEditingTextTools;
import org.eclipse.wst.sse.ui.internal.provisional.preferences.CommonEditorPreferenceNames;
import org.eclipse.wst.sse.ui.internal.quickoutline.QuickOutlineHandler;
import org.eclipse.wst.sse.ui.internal.quickoutline.QuickOutlinePopupDialog;
import org.eclipse.wst.sse.ui.internal.reconcile.DocumentRegionProcessor;
import org.eclipse.wst.sse.ui.internal.selection.SelectionHistory;
import org.eclipse.wst.sse.ui.internal.style.SemanticHighlightingManager;
import org.eclipse.wst.sse.ui.internal.text.DocumentRegionEdgeMatcher;
import org.eclipse.wst.sse.ui.internal.text.SourceInfoProvider;
import org.eclipse.wst.sse.ui.internal.util.Assert;
import org.eclipse.wst.sse.ui.internal.util.EditorUtility;
import org.eclipse.wst.sse.ui.quickoutline.AbstractQuickOutlineConfiguration;
import org.eclipse.wst.sse.ui.reconcile.ISourceReconcilingListener;
import org.eclipse.wst.sse.ui.typing.AbstractCharacterPairInserter;
import org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration;
import org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration;

/**
* A Text Editor for editing structured models and structured documents.
* <p>
* This class is not meant to be subclassed.<br />
* New content types may associate source viewer, content outline, and
* property sheet configurations to extend the existing functionality.
* </p>
*
* @see org.eclipse.wst.sse.ui.StructuredTextViewerConfiguration
* @see org.eclipse.wst.sse.ui.views.contentoutline.ContentOutlineConfiguration
* @see org.eclipse.wst.sse.ui.views.properties.PropertySheetConfiguration
*
* @since 1.0
*/

public class StructuredTextEditor extends TextEditor {
  private class GotoMatchingBracketHandler extends AbstractHandler {
    public Object execute(ExecutionEvent arg0) throws ExecutionException {
      gotoMatchingBracket();
      return null;
    }
  }

  private class InternalModelStateListener implements IModelStateListener {
    public void modelAboutToBeChanged(IStructuredModel model) {
      if (getTextViewer() != null) {
        // getTextViewer().setRedraw(false);
      }
    }

    public void modelAboutToBeReinitialized(IStructuredModel structuredModel) {
      if (getTextViewer() != null) {
        // getTextViewer().setRedraw(false);
        getTextViewer().unconfigure();
        setStatusLineMessage(null);
      }
    }

    public void modelChanged(IStructuredModel model) {
      if (getSourceViewer() != null) {
        // getTextViewer().setRedraw(true);
        // Since the model can be changed on a background
        // thread, we will update menus on display thread,
        // if we are not already on display thread,
        // and if there is not an update already pending.
        // (we can get lots of 'modelChanged' events in rapid
        // succession, so only need to do one.
        if (!fUpdateMenuTextPending) {
          runOnDisplayThreadIfNeededed(new Runnable() {
            public void run() {
              updateMenuText();
              fUpdateMenuTextPending = false;
            }
          });
        }

      }
    }

    public void modelDirtyStateChanged(IStructuredModel model, boolean isDirty) {
      // do nothing
    }

    public void modelReinitialized(IStructuredModel structuredModel) {
      try {
        if (getSourceViewer() != null) {
          SourceViewerConfiguration cfg = getSourceViewerConfiguration();
          getSourceViewer().configure(cfg);
        }
      }
      catch (Exception e) {
        // https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=1166
        // investigate each error case post beta
        Logger.logException("problem trying to configure after model change", e); //$NON-NLS-1$
      }
      finally {
        // so we don't freeze workbench (eg. during page language or
        // content type change)
        ((ITextViewerExtension) getSourceViewer()).setRedraw(true);
       
        IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) getSite().getService(IWorkbenchSiteProgressService.class);
        if (service != null) {
          service.warnOfContentChange();
        }
      }
    }

    // Note: this one should probably be used to
    // control viewer
    // instead of viewer having its own listener
    public void modelResourceDeleted(IStructuredModel model) {
      // do nothing
    }

    public void modelResourceMoved(IStructuredModel originalmodel, IStructuredModel movedmodel) {
      // do nothing
    }

    /**
     * This 'Runnable' should be very brief, and should not "call out" to
     * other code especially if it depends on the state of the model.
     *
     * @param r
     */
    private void runOnDisplayThreadIfNeededed(Runnable r) {
      // if there is no Display at all (that is, running headless),
      // or if we are already running on the display thread, then
      // simply execute the runnable.
      if (getDisplay() == null || (Thread.currentThread() == getDisplay().getThread())) {
        r.run();
      }
      else {
        // otherwise force the runnable to run on the display thread.
        getDisplay().asyncExec(r);
      }
    }
  }
 
  /**
   * Listens to double-click and selection from the outline page
   */
  private class OutlinePageListener implements IDoubleClickListener, ISelectionChangedListener {
    public void doubleClick(DoubleClickEvent event) {
      if (event.getSelection().isEmpty())
        return;

      int start = -1;
      int length = 0;
      if (event.getSelection() instanceof IStructuredSelection) {
        ISelection currentSelection = getSelectionProvider().getSelection();
        if (currentSelection instanceof IStructuredSelection) {
          Object current = ((IStructuredSelection) currentSelection).toArray();
          Object newSelection = ((IStructuredSelection) event.getSelection()).toArray();
          if (!current.equals(newSelection)) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            Object o = selection.getFirstElement();
            if (o instanceof IndexedRegion) {
              start = ((IndexedRegion) o).getStartOffset();
              length = ((IndexedRegion) o).getEndOffset() - start;
            }
            else if (o instanceof ITextRegion) {
              start = ((ITextRegion) o).getStart();
              length = ((ITextRegion) o).getEnd() - start;
            }
            else if (o instanceof IRegion) {
              start = ((ITextRegion) o).getStart();
              length = ((ITextRegion) o).getLength();
            }
          }
        }
      }
      else if (event.getSelection() instanceof ITextSelection) {
        start = ((ITextSelection) event.getSelection()).getOffset();
        length = ((ITextSelection) event.getSelection()).getLength();
      }
      if (start > -1) {
        getSourceViewer().setRangeIndication(start, length, false);
        selectAndReveal(start, length);
      }
    }

    public void selectionChanged(SelectionChangedEvent event) {
      /*
       * Do not allow selection from other parts to affect selection in
       * the text widget if it has focus, or if we're still firing a
       * change of selection. Selection events "bouncing" off of other
       * parts are all that we can receive if we have focus (since we
       * forwarded our selection to the service just a moment ago), and
       * only the user should affect selection if we have focus.
       */

      /* The isFiringSelection check only works if a selection listener */
      if (event.getSelection().isEmpty() || fStructuredSelectionProvider.isFiringSelection())
        return;

      if (getSourceViewer() != null && getSourceViewer().getTextWidget() != null && !getSourceViewer().getTextWidget().isDisposed() && !getSourceViewer().getTextWidget().isFocusControl()) {
        int start = -1;
        int length = 0;
        if (event.getSelection() instanceof IStructuredSelection) {
          ISelection current = getSelectionProvider().getSelection();
          if (current instanceof IStructuredSelection) {
            Object[] currentSelection = ((IStructuredSelection) current).toArray();
            Object[] newSelection = ((IStructuredSelection) event.getSelection()).toArray();
            if (!Arrays.equals(currentSelection, newSelection)) {
              if (newSelection.length > 0) {
                /*
                 * No ordering is guaranteed for multiple
                 * selection
                 */
                Object o = newSelection[0];
                if (o instanceof IndexedRegion) {
                  start = ((IndexedRegion) o).getStartOffset();
                  int end = ((IndexedRegion) o).getEndOffset();
                  if (newSelection.length > 1) {
                    for (int i = 1; i < newSelection.length; i++) {
                      start = Math.min(start, ((IndexedRegion) newSelection[i]).getStartOffset());
                      end = Math.max(end, ((IndexedRegion) newSelection[i]).getEndOffset());
                    }
                    length = end - start;
                  }
                }
                else if (o instanceof ITextRegion) {
                  start = ((ITextRegion) o).getStart();
                  int end = ((ITextRegion) o).getEnd();
                  if (newSelection.length > 1) {
                    for (int i = 1; i < newSelection.length; i++) {
                      start = Math.min(start, ((ITextRegion) newSelection[i]).getStart());
                      end = Math.max(end, ((ITextRegion) newSelection[i]).getEnd());
                    }
                    length = end - start;
                  }
                }
                else if (o instanceof IRegion) {
                  start = ((IRegion) o).getOffset();
                  int end = start + ((IRegion) o).getLength();
                  if (newSelection.length > 1) {
                    for (int i = 1; i < newSelection.length; i++) {
                      start = Math.min(start, ((IRegion) newSelection[i]).getOffset());
                      end = Math.max(end, ((IRegion) newSelection[i]).getOffset() + ((IRegion) newSelection[i]).getLength());
                    }
                    length = end - start;
                  }
                }
              }
            }
          }
        }
        else if (event.getSelection() instanceof ITextSelection) {
          start = ((ITextSelection) event.getSelection()).getOffset();
        }
        if (start > -1) {
          updateRangeIndication(event.getSelection());
          selectAndReveal(start, length);
        }
      }
    }
  }

  private class ShowInTargetListAdapter implements IShowInTargetList {
    /**
     * Array of ID Strings that define the default show in targets for
     * this editor.
     *
     * @see org.eclipse.ui.part.IShowInTargetList#getShowInTargetIds()
     * @return the array of ID Strings that define the default show in
     *         targets for this editor.
     */
    public String[] getShowInTargetIds() {
      return fShowInTargetIds;
    }
  }

  /**
   * A post selection provider that wraps the provider implemented in
   * AbstractTextEditor to provide a StructuredTextSelection to post
   * selection listeners. Listens to selection changes from the source
   * viewer.
   */
  private static class StructuredSelectionProvider implements IPostSelectionProvider, ISelectionValidator {
    /**
     * A "hybrid" text and structured selection class containing the text
     * selection and a list of selected model objects. The determination
     * of which model objects matches the text selection is responsibility
     * of the StructuredSelectionProvider which created this selection
     * object.
     */
    private static class StructuredTextSelection extends TextSelection implements IStructuredSelection {
      private Object[] selectedStructured;

      StructuredTextSelection(IDocument document, int offset, int length, Object[] selectedObjects) {
        super(document, offset, length);
        selectedStructured = selectedObjects;
      }

      StructuredTextSelection(IDocument document, ITextSelection selection, Object[] selectedObjects) {
        this(document, selection.getOffset(), selection.getLength(), selectedObjects);
      }

      public Object getFirstElement() {
        Object[] selectedStructures = getSelectedStructures();
        return selectedStructures.length > 0 ? selectedStructures[0] : null;
      }

      private Object[] getSelectedStructures() {
        return (selectedStructured != null) ? selectedStructured : new Object[0];
      }

      public boolean isEmpty() {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=191327
        return super.isEmpty() || getSelectedStructures().length == 0;
      }

      public Iterator iterator() {
        return toList().iterator();
      }

      public int size() {
        return (selectedStructured != null) ? selectedStructured.length : 0;
      }

      public Object[] toArray() {
        return getSelectedStructures();
      }

      public List toList() {
        return Arrays.asList(getSelectedStructures());
      }

      public String toString() {
        return getOffset() + ":" + getLength() + "@" + getSelectedStructures(); //$NON-NLS-1$ //$NON-NLS-2$
      }
    }
   
    private ISelectionProvider fParentProvider = null;
    private boolean isFiringSelection = false;
    private ListenerList listeners = new ListenerList();
    private ListenerList postListeners = new ListenerList();
    private ISelection fLastSelection = null;
    private ISelectionProvider fLastSelectionProvider = null;
    private SelectionChangedEvent fLastUpdatedSelectionChangedEvent = null;
    private StructuredTextEditor fEditor;
    /*
     * Responsible for finding the selected objects within a text
     * selection. Set/reset by the StructuredTextEditor based on a
     * per-model adapter on input.
     */
    SelectionConvertor selectionConvertor = new SelectionConvertor();
   
    StructuredSelectionProvider(ISelectionProvider parentProvider, StructuredTextEditor structuredTextEditor) {
      fParentProvider = parentProvider;
      fEditor = structuredTextEditor;
      fParentProvider.addSelectionChangedListener(new ISelectionChangedListener() {
        public void selectionChanged(SelectionChangedEvent event) {
          handleSelectionChanged(event);
        }
      });
      if (fParentProvider instanceof IPostSelectionProvider) {
        ((IPostSelectionProvider) fParentProvider).addPostSelectionChangedListener(new ISelectionChangedListener() {
          public void selectionChanged(SelectionChangedEvent event) {
            handlePostSelectionChanged(event);
          }
        });
      }
    }

    public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
      postListeners.add(listener);
    }

    public void addSelectionChangedListener(ISelectionChangedListener listener) {
      listeners.add(listener);
    }

    public void dispose() {
      fEditor = null;
      listeners.clear();
      postListeners.clear();
      selectionConvertor = null;
    }

    private void fireSelectionChanged(final SelectionChangedEvent event, ListenerList listenerList) {
      Object[] listeners = listenerList.getListeners();
      isFiringSelection = true;
      for (int i = 0; i < listeners.length; ++i) {
        final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
        SafeRunner.run(new SafeRunnable() {
          public void run() {
            l.selectionChanged(event);
          }
        });
      }
      isFiringSelection = false;
    }

    private ISelectionProvider getParentProvider() {
      return fParentProvider;
    }

    public ISelection getSelection() {
      fLastSelection = null;
      fLastSelectionProvider = null;
      fLastUpdatedSelectionChangedEvent = null;

      /*
       * When a client explicitly asks for selection, provide the hybrid
       * result.
       */
      ISelection selection = getParentProvider().getSelection();
      if (!(selection instanceof IStructuredSelection) && selection instanceof ITextSelection) {
        IStructuredModel structuredModel = null;
        StructuredTextEditor localEditor = getStructuredTextEditor();
        if (localEditor != null) {
          structuredModel = localEditor.getInternalModel();
          if (structuredModel != null) {
            if (localEditor.isBlockSelectionModeEnabled()) {
              /*
               * Block selection handling - find the overlapping
               * objects on each line, keeping in mind that the
               * selected block may not overlap actual lines or
               * columns of the document.
               * IBlockTextSelection.getRegions() should handle
               * that for us...
               */
              IBlockTextSelection blockSelection = (IBlockTextSelection) selection;
              IRegion[] regions = blockSelection.getRegions();
              Set blockObjects = new LinkedHashSet();
              for (int i = 0; i < regions.length; i++) {
                Object[] objects = selectionConvertor.getElements(structuredModel, regions[i].getOffset(), regions[i].getLength());
                for (int j = 0; j < objects.length; j++) {
                  blockObjects.add(objects[j]);
                }
              }
              selection = new StructuredTextSelection(getDocument(), (ITextSelection) selection, blockObjects.toArray());
            }
            else {
              int start = ((ITextSelection) selection).getOffset();
              int end = start + ((ITextSelection) selection).getLength();
              selection = new StructuredTextSelection(getDocument(), (ITextSelection) selection, selectionConvertor.getElements(structuredModel, start, end));
            }
          }
        }
        if (selection == null) {
          selection = new StructuredTextSelection(getDocument(), (ITextSelection) selection, new Object[0]);
        }
      }
     
      return selection;
    }

    private StructuredTextEditor getStructuredTextEditor() {
      return fEditor;
    }

    void handlePostSelectionChanged(SelectionChangedEvent event) {
      SelectionChangedEvent updatedEvent = null;
      if (fLastSelection == event.getSelection() && fLastSelectionProvider == event.getSelectionProvider()) {
        updatedEvent = fLastUpdatedSelectionChangedEvent;
      }
      else {
        updatedEvent = updateEvent(event);
      }
      // only update the range indicator on post selection
      StructuredTextEditor localEditor = fEditor;

      if (localEditor != null) {
        localEditor.updateRangeIndication(updatedEvent.getSelection());
        fireSelectionChanged(updatedEvent, postListeners);
      }
    }

    void handleSelectionChanged(SelectionChangedEvent event) {
      SelectionChangedEvent updatedEvent = event;
      if (fLastSelection != event.getSelection() || fLastSelectionProvider != event.getSelectionProvider()) {
        fLastSelection = event.getSelection();
        fLastSelectionProvider = event.getSelectionProvider();
        fLastUpdatedSelectionChangedEvent = updatedEvent = updateEvent(event);
      }
      fireSelectionChanged(updatedEvent, listeners);
    }

    IDocument getDocument() {
      return fEditor.getDocumentProvider().getDocument(fEditor.getEditorInput());
    }


    boolean isFiringSelection() {
      return isFiringSelection;
    }

    public boolean isValid(ISelection selection) {
      // ISSUE: is not clear default behavior should be true?
      // But not clear is this default would apply for our editor.
      boolean result = true;
      // if editor is "gone", can not be valid
      StructuredTextEditor e = getStructuredTextEditor();
      if (e == null || e.fEditorDisposed) {
        result = false;
      }
      // else defer to parent
      else if (getParentProvider() instanceof ISelectionValidator) {
        result = ((ISelectionValidator) getParentProvider()).isValid(selection);
      }
      return result;
    }

    public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
      postListeners.remove(listener);
    }

    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
      listeners.remove(listener);
    }

    public void setSelection(ISelection selection) {
      if (isFiringSelection()) {
        return;
      }

      fLastSelection = null;
      fLastSelectionProvider = null;
      fLastUpdatedSelectionChangedEvent = null;

      ISelection textSelection = updateSelection(selection);
      getParentProvider().setSelection(textSelection);
      StructuredTextEditor localEditor = getStructuredTextEditor();
      if (localEditor != null) {
        localEditor.updateRangeIndication(textSelection);
      }
    }

    /**
     * Create a corresponding event that contains a
     * StructuredTextselection
     *
     * @param event
     * @return
     */
    private SelectionChangedEvent updateEvent(SelectionChangedEvent event) {
      ISelection selection = event.getSelection();
      if (selection instanceof ITextSelection && !(selection instanceof IStructuredSelection)) {
        IStructuredModel structuredModel = null;
        StructuredTextEditor localEditor = getStructuredTextEditor();
        if (localEditor != null) {
          structuredModel = localEditor.getInternalModel();
          if (structuredModel != null) {
            int start = ((ITextSelection) selection).getOffset();
            int end = start + ((ITextSelection) selection).getLength();
            selection = new StructuredTextSelection(getDocument(), (ITextSelection) event.getSelection(), selectionConvertor.getElements(structuredModel, start, end));
          }
        }
        if (selection == null)
          selection = new StructuredTextSelection(getDocument(), (ITextSelection) event.getSelection(), new Object[0]);
      }
      SelectionChangedEvent newEvent = new SelectionChangedEvent(event.getSelectionProvider(), selection);
      return newEvent;
    }

    /**
     * Create a corresponding StructuredTextselection
     *
     * @param selection
     * @return
     */
    private ISelection updateSelection(ISelection selection) {
      ISelection updated = selection;
      if (selection instanceof IStructuredSelection && !(selection instanceof ITextSelection) && !selection.isEmpty()) {
        Object[] selectedObjects = ((IStructuredSelection) selection).toArray();
        if (selectedObjects.length > 0) {
          int start = -1;
          int length = 0;

          // no ordering is guaranteed for multiple selection
          Object o = selectedObjects[0];
          if (o instanceof IndexedRegion) {
            start = ((IndexedRegion) o).getStartOffset();
            int end = ((IndexedRegion) o).getEndOffset();
            if (selectedObjects.length > 1) {
              for (int i = 1; i < selectedObjects.length; i++) {
                start = Math.min(start, ((IndexedRegion) selectedObjects[i]).getStartOffset());
                end = Math.max(end, ((IndexedRegion) selectedObjects[i]).getEndOffset());
              }
              length = end - start;
            }
          }
          else if (o instanceof ITextRegion) {
            start = ((ITextRegion) o).getStart();
            int end = ((ITextRegion) o).getEnd();
            if (selectedObjects.length > 1) {
              for (int i = 1; i < selectedObjects.length; i++) {
                start = Math.min(start, ((ITextRegion) selectedObjects[i]).getStart());
                end = Math.max(end, ((ITextRegion) selectedObjects[i]).getEnd());
              }
              length = end - start;
            }
          }

          if (start > -1) {
            updated = new StructuredTextSelection(getDocument(), start, length, selectedObjects);
          }
        }
      }
      return updated;
    }
  }

  class TimeOutExpired extends TimerTask {
    public void run() {
      final byte[] result = new byte[1]; // Did the busy state end successfully?
      getDisplay().syncExec(new Runnable() {
        public void run() {
          if (getDisplay() != null && !getDisplay().isDisposed())
            endBusyStateInternal(result);
        }
      });
      if (result[0] == 1) {
        fBusyTimer.cancel();
      }
    }

  }

  private class ConfigurationAndTarget {
    private String fTargetId;
    private StructuredTextViewerConfiguration fConfiguration;

    public ConfigurationAndTarget(String targetId, StructuredTextViewerConfiguration config) {
      fTargetId = targetId;
      fConfiguration = config;
    }

    public String getTargetId() {
      return fTargetId;
    }

    public StructuredTextViewerConfiguration getConfiguration() {
      return fConfiguration;
    }
  }

  private class CharacterPairListener implements VerifyKeyListener {
    private CharacterPairing[] fInserters = new CharacterPairing[0];
    private ICompletionListener fCompletionListener;
    private boolean fIsCompleting = false;

    public void installCompletionListener() {
      ISourceViewer viewer = getSourceViewer();
      if (viewer instanceof StructuredTextViewer) {
        fCompletionListener = new ICompletionListener() {

          public void assistSessionStarted(ContentAssistEvent event) {
            fIsCompleting = true;
          }

          public void assistSessionEnded(ContentAssistEvent event) {
            fIsCompleting = false;
          }

          public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
          }
         
        };
        ContentAssistantFacade facade = ((StructuredTextViewer) viewer).getContentAssistFacade();
        if (facade != null)
          facade.addCompletionListener(fCompletionListener);
      }
    }

    /**
     * Add the pairing to the list of inserters
     * @param pairing
     */
    void addInserter(CharacterPairing pairing) {
      List pairings = new ArrayList(Arrays.asList(fInserters));
      pairings.add(pairing);
      fInserters = (CharacterPairing[]) pairings.toArray(new CharacterPairing[pairings.size()]);
    }

    void prioritize() {
      Arrays.sort(fInserters);
    }

    /**
     * Perform cleanup on the character pair inserters
     */
    void dispose() {
      ISourceViewer viewer = getSourceViewer();
      if (viewer instanceof StructuredTextViewer) {
        ContentAssistantFacade facade = ((StructuredTextViewer) viewer).getContentAssistFacade();
        if (facade != null)
          facade.removeCompletionListener(fCompletionListener);
      }

      for (int i = 0; i < fInserters.length; i++) {
        final AbstractCharacterPairInserter inserter = fInserters[i].inserter;
        SafeRunner.run(new ISafeRunnable() {
          public void handleException(Throwable exception) {
            // rely on default logging
          }

          public void run() throws Exception {
            inserter.dispose();
          }
        });
      }
    }

    public void verifyKey(final VerifyEvent event) {
      if (!event.doit || getInsertMode() != SMART_INSERT || fIsCompleting || isBlockSelectionModeEnabled() && isMultilineSelection())
        return;
      final boolean[] paired = { false };
      for (int i = 0; i < fInserters.length; i++) {
        final CharacterPairing pairing = fInserters[i];
        // use a SafeRunner -- this is a critical function (typing)
        SafeRunner.run(new ISafeRunnable() {
          public void run() throws Exception {
            final AbstractCharacterPairInserter inserter = pairing.inserter;
            if (inserter.hasPair(event.character)) {
              if (pair(event, inserter, pairing.partitions))
                paired[0] = true;
            }
          }

          public void handleException(Throwable exception) {
            // rely on default logging
          }
        });
        if (paired[0])
          return;
      }
    }

    private boolean pair(VerifyEvent event, AbstractCharacterPairInserter inserter, Set partitions) {
      final ISourceViewer viewer = getSourceViewer();
      final IDocument document = getSourceViewer().getDocument();
      if (document != null) {
        try {
          final Point selection = viewer.getSelectedRange();
          final int offset = selection.x;
          final ITypedRegion partition = document.getPartition(offset);
          if (partitions.contains(partition.getType())) {
            // Don't modify if the editor input cannot be changed
            if (!validateEditorInputState())
              return false;
            event.doit = !inserter.pair(viewer, event.character);
            return true;
          }
        } catch (BadLocationException e) {
        }
      }
      return false;
    }

    private boolean isMultilineSelection() {
      ISelection selection = getSelectionProvider().getSelection();
      if (selection instanceof ITextSelection) {
        ITextSelection ts = (ITextSelection) selection;
        return ts.getStartLine() != ts.getEndLine();
      }
      return false;
    }
  }

  /**
   * Representation of a character pairing that includes its priority based on
   * its content type and how close it is to the content type of the file
   * in the editor.
   */
  private class CharacterPairing implements Comparable {
    int priority;
    AbstractCharacterPairInserter inserter;
    Set partitions;
    public int compareTo(Object o) {
      if (o == this)
        return 0;
      return this.priority - ((CharacterPairing) o).priority;
    }
  }
 
  private class PartListener implements IPartListener {

    private ITextEditor fEditor;

    public PartListener(ITextEditor editor) {
      fEditor = editor;
    }

    public void partActivated(IWorkbenchPart part) {
      if (part.getAdapter(ITextEditor.class) == fEditor) {
        IReconciler reconciler = getSourceViewerConfiguration().getReconciler(getSourceViewer());
        if (reconciler instanceof DocumentRegionProcessor) {
          ((DocumentRegionProcessor) reconciler).forceReconciling();
        }
      }
    }

    public void partBroughtToTop(IWorkbenchPart part) {
    }

    public void partClosed(IWorkbenchPart part) {
    }

    public void partDeactivated(IWorkbenchPart part) {
    }

    public void partOpened(IWorkbenchPart part) {
    }
   
  }

  /**
   * Not API. May be removed in the future.
   */
  protected final static char[] BRACKETS = {'{', '}', '(', ')', '[', ']'};

  private static final long BUSY_STATE_DELAY = 1000;
  /**
   * Not API. May be removed in the future.
   */
  protected static final String DOT = "."; //$NON-NLS-1$
  private static final String EDITOR_CONTEXT_MENU_ID = "org.eclipse.wst.sse.ui.StructuredTextEditor.EditorContext"; //$NON-NLS-1$
  private static final String EDITOR_CONTEXT_MENU_SUFFIX = ".source.EditorContext"; //$NON-NLS-1$

  /** Non-NLS strings */
  private static final String EDITOR_KEYBINDING_SCOPE_ID = "org.eclipse.wst.sse.ui.structuredTextEditorScope"; //$NON-NLS-1$
  /**
   * Not API. May be removed in the future.
   */
  public static final String GROUP_NAME_ADDITIONS = IWorkbenchActionConstants.MB_ADDITIONS; //$NON-NLS-1$

  private static final String REDO_ACTION_DESC = SSEUIMessages.Redo___0___UI_; //$NON-NLS-1$ = "Redo: {0}."
  private static final String REDO_ACTION_DESC_DEFAULT = SSEUIMessages.Redo_Text_Change__UI_; //$NON-NLS-1$ = "Redo Text Change."
  private static final String REDO_ACTION_TEXT = SSEUIMessages._Redo__0___Ctrl_Y_UI_; //$NON-NLS-1$ = "&Redo {0} @Ctrl+Y"
  private static final String REDO_ACTION_TEXT_DEFAULT = SSEUIMessages._Redo_Text_Change__Ctrl_Y_UI_; //$NON-NLS-1$ = "&Redo Text Change @Ctrl+Y"
  private static final String RULER_CONTEXT_MENU_ID = "org.eclipse.wst.sse.ui.StructuredTextEditor.RulerContext"; //$NON-NLS-1$
  private static final String RULER_CONTEXT_MENU_SUFFIX = ".source.RulerContext"; //$NON-NLS-1$

  private final static String UNDERSCORE = "_"; //$NON-NLS-1$
  /** Translatable strings */
  private static final String UNDO_ACTION_DESC = SSEUIMessages.Undo___0___UI_; //$NON-NLS-1$ = "Undo: {0}."

  private static final String UNDO_ACTION_DESC_DEFAULT = SSEUIMessages.Undo_Text_Change__UI_; //$NON-NLS-1$ = "Undo Text Change."
  private static final String UNDO_ACTION_TEXT = SSEUIMessages._Undo__0___Ctrl_Z_UI_; //$NON-NLS-1$ = "&Undo {0} @Ctrl+Z"
  private static final String UNDO_ACTION_TEXT_DEFAULT = SSEUIMessages._Undo_Text_Change__Ctrl_Z_UI_; //$NON-NLS-1$ = "&Undo Text Change @Ctrl+Z"
  // development time/debug variables only
  private int adapterRequests;

  private long adapterTime;
  private boolean fBackgroundJobEnded;
  private boolean fBusyState;
  private Timer fBusyTimer;
  boolean fDirtyBeforeDocumentEvent = false;
  int validateEditCount = 0;
  private ExtendedEditorDropTargetAdapter fDropAdapter;
  private DropTarget fDropTarget;
  boolean fEditorDisposed = false;
  private IEditorPart fEditorPart;
  private InternalModelStateListener fInternalModelStateListener;
  private IContentOutlinePage fOutlinePage;

  private OutlinePageListener fOutlinePageListener = null;
  /** This editor's projection support */
  private ProjectionSupport fProjectionSupport;
  private IPropertySheetPage fPropertySheetPage;

  private ISourceReconcilingListener[] fReconcilingListeners = new ISourceReconcilingListener[0];
  private IPartListener fPartListener;

  private String fRememberTitle;
  /** The ruler context menu to be disposed. */
  private Menu fRulerContextMenu;
  /** The ruler context menu manager to be disposed. */
  private MenuManager fRulerContextMenuManager;

  String[] fShowInTargetIds = new String[]{IPageLayout.ID_RES_NAV, IPageLayout.ID_PROJECT_EXPLORER, IPageLayout.ID_OUTLINE};

  private IAction fShowPropertiesAction = null;
  private IStructuredModel fStructuredModel;
  StructuredSelectionProvider fStructuredSelectionProvider = null;
  /** The text context menu to be disposed. */
  private Menu fTextContextMenu;
  /** The text context menu manager to be disposed. */
  private MenuManager fTextContextMenuManager;
  private String fViewerConfigurationTargetId;
  /** The selection history of the editor */
  private SelectionHistory fSelectionHistory;
  /** The information presenter. */
  private InformationPresenter fInformationPresenter;
  private boolean fUpdateMenuTextPending;
  /** The quick outline handler */
  private QuickOutlineHandler fOutlineHandler;

  private boolean shouldClose = false;
  private long startPerfTime;
  private boolean fisReleased;
  /**
   * The action group for folding.
   */
  private FoldingActionGroup fFoldingGroup;

  private ILabelProvider fStatusLineLabelProvider;

  private SemanticHighlightingManager fSemanticManager;
 
  private boolean fSelectionChangedFromGoto = false;

  private final CharacterPairListener fPairInserter = new CharacterPairListener();

  /**
   * Creates a new Structured Text Editor.
   */
  public StructuredTextEditor() {
    super();
    initializeDocumentProvider(null);
  }

  private IStructuredModel aboutToSaveModel() {
    IStructuredModel model = getInternalModel();
    if (model != null) {
      model.aboutToChangeModel();
    }
    return model;
  }

  protected void addSourceMenuActions(IMenuManager menu) {
    IMenuManager subMenu= new MenuManager(SSEUIMessages.SourceMenu_label, IStructuredTextEditorActionConstants.SOURCE_CONTEXT_MENU_ID);
    subMenu.add(new Separator(IStructuredTextEditorActionConstants.SOURCE_BEGIN));
    subMenu.add(new Separator(IStructuredTextEditorActionConstants.SOURCE_ADDITIONS));
    subMenu.add(new Separator(IStructuredTextEditorActionConstants.SOURCE_END));
    menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, subMenu);
  }

  protected void addRefactorMenuActions(IMenuManager menu) {
    IMenuManager subMenu = new MenuManager(SSEUIMessages.RefactorMenu_label, IStructuredTextEditorActionConstants.REFACTOR_CONTEXT_MENU_ID);
    menu.appendToGroup(ITextEditorActionConstants.GROUP_EDIT, subMenu);
  }

  protected void addContextMenuActions(IMenuManager menu) {
    // Only offer actions that affect the text if the viewer allows
    // modification and supports any of these operations

    // Some Design editors (DTD) rely on this view for their own uses
    menu.appendToGroup(IWorkbenchActionConstants.GROUP_ADD, fShowPropertiesAction);
  }

  private void addExtendedContextMenuActions(IMenuManager menu) {
    IEditorActionBarContributor c = getEditorSite().getActionBarContributor();
    if (c instanceof IPopupMenuContributor) {
      ((IPopupMenuContributor) c).contributeToPopupMenu(menu);
    }
    else {
      ExtendedEditorActionBuilder builder = new ExtendedEditorActionBuilder();
      IExtendedContributor pmc = builder.readActionExtensions(getConfigurationPoints());
      if (pmc != null) {
        pmc.setActiveEditor(this);
        pmc.contributeToPopupMenu(menu);
      }
    }
  }

  protected void addExtendedRulerContextMenuActions(IMenuManager menu) {
    // none at this level
  }



  /**
   * Starts background mode.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   */
  void beginBackgroundOperation() {
    fBackgroundJobEnded = false;
    // if already in busy state, no need to do anything
    // and, we only start, or reset, the timed busy
    // state when we get the "endBackgroundOperation" call.
    if (!inBusyState()) {
      beginBusyStateInternal();
    }
  }

  private void beginBusyStateInternal() {

    fBusyState = true;
    startBusyTimer();

    ISourceViewer viewer = getSourceViewer();
    if (viewer instanceof StructuredTextViewer) {
      ((StructuredTextViewer) viewer).beginBackgroundUpdate();

    }
    showBusy(true);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.ITextEditor#close(boolean)
   */
  public void close(final boolean save) {
    /*
     * Instead of us closing directly, we have to close with our
     * containing (multipage) editor, if it exists.
     */
    if (getSite() == null) {
      // if site hasn't been set yet, then we're not
      // completely open
      // so set a flag not to open
      shouldClose = true;
    }
    else {
      if (getEditorPart() != null) {
        Display display = getSite().getShell().getDisplay();
        display.asyncExec(new Runnable() {

          public void run() {
            getSite().getPage().closeEditor(getEditorPart(), save);
          }
        });
      }
      else {
        super.close(save);
      }
    }
  }
 
  private void activateContexts(IContextService service) {
    if(service == null)
      return;
   
    String[] definitions = getDefinitions(getConfigurationPoints());
   
    if(definitions != null) {
      String[] contexts = null;
      for(int i = 0; i < definitions.length; i++) {
        contexts = StringUtils.unpack(definitions[i]);
        for(int j = 0; j < contexts.length; j++)
          service.activateContext(contexts[j].trim());
      }
    }
   
  }
 
  private String[] getDefinitions(String[] ids) {
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] definitions = null;
   
    /* Iterate through the configuration ids until one is found that has
     * an activecontexts definition
     */
    for(int i = 0; i < ids.length; i++) {
      definitions = builder.getDefinitions("activecontexts", ids[i]); //$NON-NLS-1$
      if(definitions != null && definitions.length > 0)
        return definitions;
    }
    return null;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#collectContextMenuPreferencePages()
   */
  protected String[] collectContextMenuPreferencePages() {
    List allIds = new ArrayList(0);

    // get contributed preference pages
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] configurationIds = getConfigurationPoints();
    for (int i = 0; i < configurationIds.length; i++) {
      String[] definitions = builder.getDefinitions("preferencepages", configurationIds[i]); //$NON-NLS-1$
      for (int j = 0; j < definitions.length; j++) {
        String someIds = definitions[j];
        if (someIds != null && someIds.length() > 0) {
          // supports multiple comma-delimited page IDs in one
          // element
          String[] ids = StringUtils.unpack(someIds);
          for (int k = 0; k < ids.length; k++) {
            // trim, just to keep things clean
            String id = ids[k].trim();
            if (!allIds.contains(id)) {
              allIds.add(id);
            }
          }
        }
      }
    }

    // add pages contributed by super
    String[] superPages = super.collectContextMenuPreferencePages();
    for (int m = 0; m < superPages.length; m++) {
      // trim, just to keep things clean
      String id = superPages[m].trim();
      if (!allIds.contains(id)) {
        allIds.add(id);
      }
    }

    return (String[]) allIds.toArray(new String[0]);
  }

  /**
   * Compute and set double-click action for the vertical ruler
   */
  private void computeAndSetDoubleClickAction() {
    /*
     * Make double-clicking on the ruler toggle a breakpoint instead of
     * toggling a bookmark. For lines where a breakpoint won't be created,
     * create a bookmark through the contributed RulerDoubleClick action.
     */
    setAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK, new ToggleBreakpointAction(this, getVerticalRuler(), getAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK)));
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.ExtendedTextEditor#configureSourceViewerDecorationSupport(org.eclipse.ui.texteditor.SourceViewerDecorationSupport)
   */
  protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
    support.setCharacterPairMatcher(createCharacterPairMatcher());
    support.setMatchingCharacterPainterPreferenceKeys(EditorPreferenceNames.MATCHING_BRACKETS, EditorPreferenceNames.MATCHING_BRACKETS_COLOR);

    super.configureSourceViewerDecorationSupport(support);
  }

  protected void createActions() {
    super.createActions();
    ResourceBundle resourceBundle = SSEUIMessages.getResourceBundle();
    IWorkbenchHelpSystem helpSystem = SSEUIPlugin.getDefault().getWorkbench().getHelpSystem();
    // TextView Action - moving the selected text to
    // the clipboard
    // override the cut/paste/delete action to make
    // them run on read-only
    // files
    Action action = new TextOperationAction(resourceBundle, "Editor_Cut_", this, ITextOperationTarget.CUT); //$NON-NLS-1$
    action.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT);
    setAction(ITextEditorActionConstants.CUT, action);
    helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.CUT_ACTION);
    // TextView Action - inserting the clipboard
    // content at the current
    // position
    // override the cut/paste/delete action to make
    // them run on read-only
    // files
    action = new TextOperationAction(resourceBundle, "Editor_Paste_", this, ITextOperationTarget.PASTE); //$NON-NLS-1$
    action.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE);
    setAction(ITextEditorActionConstants.PASTE, action);
    helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.PASTE_ACTION);
    // TextView Action - deleting the selected text or
    // if selection is
    // empty the character at the right of the current
    // position
    // override the cut/paste/delete action to make
    // them run on read-only
    // files
    action = new TextOperationAction(resourceBundle, "Editor_Delete_", this, ITextOperationTarget.DELETE); //$NON-NLS-1$
    action.setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE);
    setAction(ITextEditorActionConstants.DELETE, action);
    helpSystem.setHelp(action, IAbstractTextEditorHelpContextIds.DELETE_ACTION);
    // SourceView Action - requesting content assist to
    // show completetion
    // proposals for the current insert position
    action = new TextOperationAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS + UNDERSCORE, this, ISourceViewer.CONTENTASSIST_PROPOSALS);
    helpSystem.setHelp(action, IHelpContextIds.CONTMNU_CONTENTASSIST_HELPID);
    action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
    setAction(StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS, action);
    markAsStateDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_PROPOSALS, true);
    // SourceView Action - requesting content assist to
    // show the content
    // information for the current insert position
    action = new TextOperationAction(SSEUIMessages.getResourceBundle(), StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_CONTEXT_INFORMATION + UNDERSCORE, this, ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION);
    action.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
    setAction(StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_CONTEXT_INFORMATION, action);
    markAsStateDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_CONTENTASSIST_CONTEXT_INFORMATION, true);
    // StructuredTextViewer Action - requesting format
    // of the whole
    // document
    action = new TextOperationAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT + UNDERSCORE, this, StructuredTextViewer.FORMAT_DOCUMENT);
    helpSystem.setHelp(action, IHelpContextIds.CONTMNU_FORMAT_DOC_HELPID);
    action.setActionDefinitionId(ActionDefinitionIds.FORMAT_DOCUMENT);
    setAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT, action);
    markAsStateDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT, true);
    markAsSelectionDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_DOCUMENT, true);
    // StructuredTextViewer Action - requesting format
    // of the active
    // elements
    action = new TextOperationAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS + UNDERSCORE, this, StructuredTextViewer.FORMAT_ACTIVE_ELEMENTS);
    helpSystem.setHelp(action, IHelpContextIds.CONTMNU_FORMAT_ELEMENTS_HELPID);
    action.setActionDefinitionId(ActionDefinitionIds.FORMAT_ACTIVE_ELEMENTS);
    setAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS, action);
    markAsStateDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS, true);
    markAsSelectionDependentAction(StructuredTextEditorActionConstants.ACTION_NAME_FORMAT_ACTIVE_ELEMENTS, true);

    // StructuredTextEditor Action - add breakpoints (falling back to the
    // current double-click if they can't be added)
    action = new ToggleBreakpointAction(this, getVerticalRuler());
    setAction(ActionDefinitionIds.TOGGLE_BREAKPOINTS, action);
    // StructuredTextEditor Action - manage breakpoints
    action = new ManageBreakpointAction(this, getVerticalRuler());
    setAction(ActionDefinitionIds.MANAGE_BREAKPOINTS, action);
    // StructuredTextEditor Action - edit breakpoints
    action = new EditBreakpointAction(this, getVerticalRuler());
    setAction(ActionDefinitionIds.EDIT_BREAKPOINTS, action);
    // StructuredTextViewer Action - open file on selection
    action = new OpenHyperlinkAction(resourceBundle, StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE + UNDERSCORE, this, getSourceViewer());
    action.setActionDefinitionId(ActionDefinitionIds.OPEN_FILE);
    setAction(StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE, action);

    computeAndSetDoubleClickAction();
   
    //add handlers to handler service
    IHandlerService handlerService = (IHandlerService) getSite().getService(IHandlerService.class);
    if (handlerService != null) {
     
      IHandler gotoHandler = new GotoMatchingBracketHandler();
      handlerService.activateHandler(ActionDefinitionIds.GOTO_MATCHING_BRACKET, gotoHandler);
     
      fOutlineHandler = new QuickOutlineHandler();
        handlerService.activateHandler(ActionDefinitionIds.SHOW_OUTLINE, fOutlineHandler);
     
      IHandler toggleCommentHandler = new ToggleLineCommentHandler();
      handlerService.activateHandler(ActionDefinitionIds.TOGGLE_COMMENT, toggleCommentHandler);
     
      IHandler addCommentBlockHandler = new AddBlockCommentHandler();
      handlerService.activateHandler(ActionDefinitionIds.ADD_BLOCK_COMMENT, addCommentBlockHandler);
     
      IHandler removeCommentBlockHandler = new RemoveBlockCommentHandler();
      handlerService.activateHandler(ActionDefinitionIds.REMOVE_BLOCK_COMMENT, removeCommentBlockHandler);
    }

    fShowPropertiesAction = new ShowPropertiesAction(getEditorPart(), getSelectionProvider());
    fFoldingGroup = new FoldingActionGroup(this, getSourceViewer());
  }

  protected LineChangeHover createChangeHover() {
    return super.createChangeHover(); //new StructuredLineChangeHover();
  }

  protected ICharacterPairMatcher createCharacterPairMatcher() {
    ICharacterPairMatcher matcher = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; matcher == null && i < ids.length; i++) {
      matcher = (ICharacterPairMatcher) builder.getConfiguration(DocumentRegionEdgeMatcher.ID, ids[i]);
    }
    if (matcher == null) {
      matcher = new DefaultCharacterPairMatcher(new char[]{'(', ')', '{', '}', '[', ']', '<', '>', '"', '"', '\'', '\''});
    }
    return matcher;
  }

  /**
   * Create a preference store that combines the source editor preferences
   * with the base editor's preferences.
   *
   * @return IPreferenceStore
   */
  private IPreferenceStore createCombinedPreferenceStore() {
    IPreferenceStore sseEditorPrefs = SSEUIPlugin.getDefault().getPreferenceStore();
    IPreferenceStore baseEditorPrefs = EditorsUI.getPreferenceStore();
    return new ChainedPreferenceStore(new IPreferenceStore[]{sseEditorPrefs, baseEditorPrefs});
  }

  private ContentOutlineConfiguration createContentOutlineConfiguration() {
    ContentOutlineConfiguration cfg = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; cfg == null && i < ids.length; i++) {
      cfg = (ContentOutlineConfiguration) builder.getConfiguration(ExtendedConfigurationBuilder.CONTENTOUTLINECONFIGURATION, ids[i]);
    }
    return cfg;
  }

  protected void createModelDependentFields() {
    if (fStructuredSelectionProvider != null) {
      SelectionConvertor convertor = (SelectionConvertor) fStructuredModel.getAdapter(SelectionConvertor.class);
      if (convertor != null)
        fStructuredSelectionProvider.selectionConvertor = convertor;
      else
        fStructuredSelectionProvider.selectionConvertor = new SelectionConvertor();
    }
  }

  /**
   * {@inheritDoc}
   * <p>
   * Use StructuredTextViewerConfiguration if a viewerconfiguration has not
   * already been set. Also initialize StructuredTextViewer.
   * </p>
   *
   * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createPartControl(org.eclipse.swt.widgets.Composite)
   */
  public void createPartControl(Composite parent) {
    IContextService contextService = (IContextService) getSite().getService(IContextService.class);
    if (contextService != null)
      contextService.activateContext(EDITOR_KEYBINDING_SCOPE_ID);

    if (getSourceViewerConfiguration() == null) {
      ConfigurationAndTarget cat = createSourceViewerConfiguration();
      fViewerConfigurationTargetId = cat.getTargetId();
      StructuredTextViewerConfiguration newViewerConfiguration = cat.getConfiguration();
      setSourceViewerConfiguration(newViewerConfiguration);
    }

    super.createPartControl(parent);

    // instead of calling setInput twice, use initializeSourceViewer() to
    // handle source viewer initialization previously handled by setInput
    initializeSourceViewer();

    // update editor context menu, vertical ruler context menu, infopop
    if (getInternalModel() != null) {
      updateEditorControlsForContentType(getInternalModel().getContentTypeIdentifier());
    }
    else {
      updateEditorControlsForContentType(null);
    }

    // used for Show Tooltip Description
    IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
      public IInformationControl createInformationControl(Shell shell) {
        boolean cutDown = false;
        int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
        return new DefaultInformationControl(shell, SWT.RESIZE | SWT.TOOL, style, new HTMLTextPresenter(cutDown));
      }
    };

    fInformationPresenter = new InformationPresenter(informationControlCreator);
    fInformationPresenter.setSizeConstraints(60, 10, true, true);
    fInformationPresenter.install(getSourceViewer());
    addReconcilingListeners(getSourceViewerConfiguration(), getTextViewer());
    fPartListener = new PartListener(this);
    getSite().getWorkbenchWindow().getPartService().addPartListener(fPartListener);
    installSemanticHighlighting();
    if (fOutlineHandler != null) {
      IInformationPresenter presenter = configureOutlinePresenter(getSourceViewer(), getSourceViewerConfiguration());
      if (presenter != null) {
        presenter.install(getSourceViewer());
        fOutlineHandler.configure(presenter);
      }
    }
    installCharacterPairing();
    ISourceViewer viewer = getSourceViewer();
    if (viewer instanceof ITextViewerExtension) {
      ((ITextViewerExtension) viewer).appendVerifyKeyListener(fPairInserter);
      fPairInserter.installCompletionListener();
    }
   
  }

  protected PropertySheetConfiguration createPropertySheetConfiguration() {
    PropertySheetConfiguration cfg = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; cfg == null && i < ids.length; i++) {
      cfg = (PropertySheetConfiguration) builder.getConfiguration(ExtendedConfigurationBuilder.PROPERTYSHEETCONFIGURATION, ids[i]);
    }
    return cfg;
  }

  /**
   * Loads the Show In Target IDs from the Extended Configuration extension
   * point.
   *
   * @return
   */
  private String[] createShowInTargetIds() {
    List allIds = new ArrayList(0);
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] configurationIds = getConfigurationPoints();
    for (int i = 0; i < configurationIds.length; i++) {
      String[] definitions = builder.getDefinitions("showintarget", configurationIds[i]); //$NON-NLS-1$
      for (int j = 0; j < definitions.length; j++) {
        String someIds = definitions[j];
        if (someIds != null && someIds.length() > 0) {
          String[] ids = StringUtils.unpack(someIds);
          for (int k = 0; k < ids.length; k++) {
            // trim, just to keep things clean
            String id = ids[k].trim();
            if (!allIds.contains(id)) {
              allIds.add(id);
            }
          }
        }
      }
    }

    if (!allIds.contains(IPageLayout.ID_RES_NAV)) {
      allIds.add(IPageLayout.ID_RES_NAV);
    }
    if (!allIds.contains(IPageLayout.ID_PROJECT_EXPLORER)) {
      allIds.add(IPageLayout.ID_PROJECT_EXPLORER);
    }
    if (!allIds.contains(IPageLayout.ID_OUTLINE)) {
      allIds.add(IPageLayout.ID_OUTLINE);
    }
    return (String[]) allIds.toArray(new String[0]);
  }

  /**
   * @return
   */
  private ISourceEditingTextTools createSourceEditingTextTools() {
    ISourceEditingTextTools tools = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; tools == null && i < ids.length; i++) {
      tools = (ISourceEditingTextTools) builder.getConfiguration(NullSourceEditingTextTools.ID, ids[i]);
    }
    if (tools == null) {
      tools = NullSourceEditingTextTools.getInstance();
      ((NullSourceEditingTextTools) tools).setTextEditor(this);
    }
    Method method = null; //$NON-NLS-1$
    try {
      method = tools.getClass().getMethod("setTextEditor", new Class[]{StructuredTextEditor.class}); //$NON-NLS-1$
    }
    catch (NoSuchMethodException e) {
    }
    if (method == null) {
      try {
        method = tools.getClass().getMethod("setTextEditor", new Class[]{ITextEditor.class}); //$NON-NLS-1$
      }
      catch (NoSuchMethodException e) {
      }
    }
    if (method == null) {
      try {
        method = tools.getClass().getMethod("setTextEditor", new Class[]{IEditorPart.class}); //$NON-NLS-1$
      }
      catch (NoSuchMethodException e) {
      }
    }
    if (method != null) {
      if (!method.isAccessible()) {
        method.setAccessible(true);
      }
      try {
        method.invoke(tools, new Object[]{this});
      }
      catch (Exception e) {
        Logger.logException("Problem creating ISourceEditingTextTools implementation", e); //$NON-NLS-1$
      }
    }

    return tools;
  }

  /**
   * Creates the source viewer to be used by this editor
   */
  protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
    fAnnotationAccess = createAnnotationAccess();
    fOverviewRuler = createOverviewRuler(getSharedColors());
    StructuredTextViewer sourceViewer = createStructedTextViewer(parent, verticalRuler, styles);
    initSourceViewer(sourceViewer);
    return sourceViewer;
  }

  private ConfigurationAndTarget createSourceViewerConfiguration() {
    ConfigurationAndTarget cat = null;
    StructuredTextViewerConfiguration cfg = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; cfg == null && i < ids.length; i++) {
      cfg = (StructuredTextViewerConfiguration) builder.getConfiguration(ExtendedConfigurationBuilder.SOURCEVIEWERCONFIGURATION, ids[i]);
      cat = new ConfigurationAndTarget(ids[i], cfg);
    }
    if (cfg == null) {
      cfg = new StructuredTextViewerConfiguration();
      String targetid = getClass().getName() + "#default"; //$NON-NLS-1$
      cat = new ConfigurationAndTarget(targetid, cfg);
    }
    return cat;
  }

  protected StructuredTextViewer createStructedTextViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
    return new StructuredTextViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles);
  }

  protected void createUndoRedoActions() {
    // overridden to add icons to actions
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=111877
    super.createUndoRedoActions();
    IAction action = getAction(ITextEditorActionConstants.UNDO);
    if (action != null) {
      action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_UNDO));
    }

    action = getAction(ITextEditorActionConstants.REDO);
    if (action != null) {
      action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_REDO));
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IWorkbenchPart#dispose()
   */
  public void dispose() {
    Logger.trace("Source Editor", "StructuredTextEditor::dispose entry"); //$NON-NLS-1$ //$NON-NLS-2$
    if (org.eclipse.wst.sse.core.internal.util.Debug.perfTestAdapterClassLoading) {
      System.out.println("Total calls to getAdapter: " + adapterRequests); //$NON-NLS-1$
      System.out.println("Total time in getAdapter: " + adapterTime); //$NON-NLS-1$
      System.out.println("Average time per call: " + (adapterTime / adapterRequests)); //$NON-NLS-1$
    }

    ISourceViewer viewer = getSourceViewer();
    if (viewer instanceof ITextViewerExtension)
      ((ITextViewerExtension) viewer).removeVerifyKeyListener(fPairInserter);

    // dispose of information presenter
    if (fInformationPresenter != null) {
      fInformationPresenter.dispose();
      fInformationPresenter = null;
    }

    if (fOutlineHandler != null) {
      fOutlineHandler.dispose();
    }
    // dispose of selection history
    if (fSelectionHistory != null) {
      fSelectionHistory.dispose();
      fSelectionHistory = null;
    }

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

    if (fFoldingGroup != null) {
      fFoldingGroup.dispose();
      fFoldingGroup = null;
    }

    // dispose of menus that were being tracked
    if (fTextContextMenu != null) {
      fTextContextMenu.dispose();
    }
    if (fRulerContextMenu != null) {
      fRulerContextMenu.dispose();
    }
    if (fTextContextMenuManager != null) {
      fTextContextMenuManager.removeMenuListener(getContextMenuListener());
      fTextContextMenuManager.removeAll();
      fTextContextMenuManager.dispose();
    }
    if (fRulerContextMenuManager != null) {
      fRulerContextMenuManager.removeMenuListener(getContextMenuListener());
      fRulerContextMenuManager.removeAll();
      fRulerContextMenuManager.dispose();
    }

    // added this 2/20/2004 based on probe results --
    // seems should be handled by setModel(null), but
    // that's a more radical change.
    // and, technically speaking, should not be needed,
    // but makes a memory leak
    // less severe.
    if (fStructuredModel != null) {
      fStructuredModel.removeModelStateListener(getInternalModelStateListener());
    }

    // BUG155335 - if there was no document provider, there was nothing
    // added
    // to document, so nothing to remove
    if (getDocumentProvider() != null) {
      IDocument doc = getDocumentProvider().getDocument(getEditorInput());
      if (doc != null) {
        if (doc instanceof IExecutionDelegatable) {
          ((IExecutionDelegatable) doc).setExecutionDelegate(null);
        }
      }
    }

    // some things in the configuration need to clean
    // up after themselves
    if (fOutlinePage != null) {
      if (fOutlinePage instanceof ConfigurableContentOutlinePage && fOutlinePageListener != null) {
        ((ConfigurableContentOutlinePage) fOutlinePage).removeDoubleClickListener(fOutlinePageListener);
      }
      if (fOutlinePageListener != null) {
        fOutlinePage.removeSelectionChangedListener(fOutlinePageListener);
      }
    }

    fEditorDisposed = true;
    disposeModelDependentFields();

    if (fDropTarget != null)
      fDropTarget.dispose();

    if (fPartListener != null) {
      getSite().getWorkbenchWindow().getPartService().removePartListener(fPartListener);
      fPartListener = null;
    }

    uninstallSemanticHighlighting();

    if (fPairInserter != null)
      fPairInserter.dispose();


    setPreferenceStore(null);

    /*
     * Strictly speaking, but following null outs should not be needed,
     * but in the event of a memory leak, they make the memory leak less
     * severe
     */
    fDropAdapter = null;
    fDropTarget = null;

    if (fStructuredSelectionProvider != null) {
      fStructuredSelectionProvider.dispose();
    }

    setStatusLineMessage(null);

    super.dispose();

    Logger.trace("Source Editor", "StructuredTextEditor::dispose exit"); //$NON-NLS-1$ //$NON-NLS-2$
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#disposeDocumentProvider()
   */
  protected void disposeDocumentProvider() {
    if (fStructuredModel != null && !fisReleased && !(getDocumentProvider() instanceof IModelProvider)) {
      fStructuredModel.releaseFromEdit();
      fisReleased = true;
    }
    super.disposeDocumentProvider();
  }

  /**
   * Disposes model specific editor helpers such as statusLineHelper.
   * Basically any code repeated in update() & dispose() should be placed
   * here.
   */
  private void disposeModelDependentFields() {
    if(fStructuredSelectionProvider != null)
      fStructuredSelectionProvider.selectionConvertor = new SelectionConvertor();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.ITextEditor#doRevertToSaved()
   */
  public void doRevertToSaved() {
    super.doRevertToSaved();
    if (fOutlinePage != null && fOutlinePage instanceof IUpdate) {
      ((IUpdate) fOutlinePage).update();
    }
    // reset undo
    IDocument doc = getDocumentProvider().getDocument(getEditorInput());
    if (doc instanceof IStructuredDocument) {
      ((IStructuredDocument) doc).getUndoManager().getCommandStack().flush();
    }

    // update menu text
    updateMenuText();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
   */
  public void doSave(IProgressMonitor progressMonitor) {
    IStructuredModel model = null;
    try {
      model = aboutToSaveModel();
      updateEncodingMemento();
      super.doSave(progressMonitor);
    }
    finally {
      savedModel(model);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetInput(org.eclipse.ui.IEditorInput)
   */
  protected void doSetInput(IEditorInput input) throws CoreException {
    IEditorInput oldInput = getEditorInput();
    if (oldInput != null) {
      IDocument olddoc = getDocumentProvider().getDocument(oldInput);
      if (olddoc != null && olddoc instanceof IExecutionDelegatable) {
        ((IExecutionDelegatable) olddoc).setExecutionDelegate(null);
      }
    }

    if (fStructuredModel != null && !(getDocumentProvider() instanceof IModelProvider)) {
      fStructuredModel.releaseFromEdit();
    }

    //attempt to get the model for the given input
    super.doSetInput(input);
    IStructuredModel model = tryToGetModel(input);
   
    /* if could not get the model prompt user to update content type
     * if preferences allow, then try to get model again
     */
    if(model == null &&  SSEUIPlugin.getDefault().getPreferenceStore().getBoolean(EditorPreferenceNames.SHOW_UNKNOWN_CONTENT_TYPE_MSG)) {
      // display a dialog informing user of unknown content type giving them chance to update preferences
      UnknownContentTypeDialog dialog = new UnknownContentTypeDialog(getSite().getShell(), SSEUIPlugin.getDefault().getPreferenceStore(), EditorPreferenceNames.SHOW_UNKNOWN_CONTENT_TYPE_MSG);
      dialog.open();

      //try to get model again in hopes user updated preferences
      super.doSetInput(input);
      model = tryToGetModel(input);
     
      //still could not get the model to open this editor so log
      if(model == null) {
        logUnexpectedDocumentKind(input);
      }
    }

    if (fStructuredModel != null || model != null) {
      setModel(model);
    }

    if (getInternalModel() != null) {
      updateEditorControlsForContentType(getInternalModel().getContentTypeIdentifier());
    }
    else {
      updateEditorControlsForContentType(null);
    }

    // start editor with smart insert mode
    setInsertMode(SMART_INSERT);
  }
 
  /**
   * <p>Attempts to get the {@link IStructuredModel} for the given {@link IEditorInput}</p>
   *
   * @param input the {@link IEditorInput} to try and get the {@link IStructuredModel} for
   *
   * @return The {@link IStructuredModel} associated with the given {@link IEditorInput} or
   * <code>null</code> if no associated {@link IStructuredModel} could be found.
   */
  private IStructuredModel tryToGetModel(IEditorInput input) {
    IStructuredModel model = null;
   
    IDocument newDocument = getDocumentProvider().getDocument(input);
    if (newDocument instanceof IExecutionDelegatable) {
      ((IExecutionDelegatable) newDocument).setExecutionDelegate(new EditorExecutionContext(this));
    }

    // if we have a Model provider, get the model from it
    if (getDocumentProvider() instanceof IModelProvider) {
      model = ((IModelProvider) getDocumentProvider()).getModel(getEditorInput());
      if (!model.isShared()) {
        EditorModelUtil.addFactoriesTo(model);
      }
    }
    else if (newDocument instanceof IStructuredDocument) {
      // corresponding releaseFromEdit occurs in dispose()
      model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) newDocument);
      EditorModelUtil.addFactoriesTo(model);
    }
   
    return model;
  }

  /**
   * Sets up this editor's context menu before it is made visible.
   * <p>
   * Not API. May be reduced to protected method in the future.
   * </p>
   *
   * @param menu
   *            the menu
   */
  public void editorContextMenuAboutToShow(IMenuManager menu) {
    /*
     * To be consistent with the Java Editor, we want to remove ShiftRight
     * and ShiftLeft from the context menu.
     */
    super.editorContextMenuAboutToShow(menu);
    menu.remove(ITextEditorActionConstants.SHIFT_LEFT);
    menu.remove(ITextEditorActionConstants.SHIFT_RIGHT);

    addContextMenuActions(menu);
    addSourceMenuActions(menu);
    addRefactorMenuActions(menu);
    addExtendedContextMenuActions(menu);
  }

  /**
   * End background mode.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   */
  void endBackgroundOperation() {
    fBackgroundJobEnded = true;
    // note, we don't immediately end our 'internal busy' state,
    // since we may get many calls in a short period of
    // time. We always wait for the time out.
    resetBusyState();
  }

  /**
   * Note this method can be called indirectly from background job operation
   * ... but expected to be gaurded there with ILock, plus, can be called
   * directly from timer thread, so the timer's run method guards with ILock
   * too.
   *
   * Set result[0] to 1 if the busy state was ended successfully
   */
  private void endBusyStateInternal(byte[] result) {
    if (fBackgroundJobEnded) {
      result[0] = 1;
      showBusy(false);

      ISourceViewer viewer = getSourceViewer();
      if (viewer instanceof StructuredTextViewer) {
        ((StructuredTextViewer) viewer).endBackgroundUpdate();
      }
      fBusyState = false;
    }
    else {
      // we will only be in this branch for a back ground job that is
      // taking
      // longer than our normal time-out period (meaning we got notified
      // of
      // the timeout "inbetween" calls to 'begin' and
      // 'endBackgroundOperation'.
      // (which, remember, can only happen since there are many calls to
      // begin/end in a short period of time, and we only "reset" on the
      // 'ends').
      // In this event, there's really nothing to do, we're still in
      // "busy state"
      // and should start a new reset cycle once endBackgroundjob is
      // called.
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
   */
  public Object getAdapter(Class required) {
    if (org.eclipse.wst.sse.core.internal.util.Debug.perfTestAdapterClassLoading) {
      startPerfTime = System.currentTimeMillis();
    }
    Object result = null;
    // text editor
    IStructuredModel internalModel = getInternalModel();
    if (ITextEditor.class.equals(required) || ITextEditorExtension5.class.equals(required) || ITextEditorExtension4.class.equals(required) || ITextEditorExtension3.class.equals(required) || ITextEditorExtension2.class.equals(required) || ITextEditorExtension.class.equals(required)) {
      result = this;
    }
    else if (IWorkbenchSiteProgressService.class.equals(required)) {
      return getEditorPart().getSite().getAdapter(IWorkbenchSiteProgressService.class);
    }
    // content outline page
    else if (IContentOutlinePage.class.equals(required)) {
      if (fOutlinePage == null || fOutlinePage.getControl() == null || fOutlinePage.getControl().isDisposed()) {
        ContentOutlineConfiguration cfg = createContentOutlineConfiguration();
        if (cfg != null) {
          ConfigurableContentOutlinePage outlinePage = new ConfigurableContentOutlinePage();
          outlinePage.setConfiguration(cfg);
          if (internalModel != null) {
            outlinePage.setInputContentTypeIdentifier(internalModel.getContentTypeIdentifier());
            outlinePage.setInput(internalModel);
          }

          if (fOutlinePageListener == null) {
            fOutlinePageListener = new OutlinePageListener();
          }

          outlinePage.addSelectionChangedListener(fOutlinePageListener);
          outlinePage.addDoubleClickListener(fOutlinePageListener);

          fOutlinePage = outlinePage;
        }
      }
      result = fOutlinePage;
    }
    // property sheet page, but only if the input's editable
    else if (IPropertySheetPage.class.equals(required) && isEditable()) {
      if (fPropertySheetPage == null || fPropertySheetPage.getControl() == null || fPropertySheetPage.getControl().isDisposed()) {
        PropertySheetConfiguration cfg = createPropertySheetConfiguration();
        if (cfg != null) {
          ConfigurablePropertySheetPage propertySheetPage = new ConfigurablePropertySheetPage();
          propertySheetPage.setConfiguration(cfg);
          fPropertySheetPage = propertySheetPage;
        }
      }
      result = fPropertySheetPage;
    }
    else if (IDocument.class.equals(required)) {
      result = getDocumentProvider().getDocument(getEditorInput());
    }
    else if (ISourceEditingTextTools.class.equals(required)) {
      result = createSourceEditingTextTools();
    }
    else if (IToggleBreakpointsTarget.class.equals(required)) {
      result = ToggleBreakpointsTarget.getInstance();
    }
    else if (ITextEditorExtension4.class.equals(required)) {
      result = this;
    }
    else if (IShowInTargetList.class.equals(required)) {
      result = new ShowInTargetListAdapter();
    }
    else if (IVerticalRuler.class.equals(required)) {
      return getVerticalRuler();
    }
    else if (SelectionHistory.class.equals(required)) {
      if (fSelectionHistory == null)
        fSelectionHistory = new SelectionHistory(this);
      result = fSelectionHistory;
    }
    else if (IResource.class.equals(required)) {
      IEditorInput input = getEditorInput();
      if (input != null) {
        result = input.getAdapter(required);
      }
    }
    else {
      if (result == null && internalModel != null) {
        result = internalModel.getAdapter(required);
      }
      // others
      if (result == null)
        result = super.getAdapter(required);
    }
    if (result == null) {
//      Logger.log(Logger.INFO_DEBUG, "StructuredTextEditor.getAdapter returning null for " + required); //$NON-NLS-1$
    }
    if (org.eclipse.wst.sse.core.internal.util.Debug.perfTestAdapterClassLoading) {
      long stop = System.currentTimeMillis();
      adapterRequests++;
      adapterTime += (stop - startPerfTime);
    }
    if (org.eclipse.wst.sse.core.internal.util.Debug.perfTestAdapterClassLoading) {
      System.out.println("Total calls to getAdapter: " + adapterRequests); //$NON-NLS-1$
      System.out.println("Total time in getAdapter: " + adapterTime); //$NON-NLS-1$
      System.out.println("Average time per call: " + (adapterTime / adapterRequests)); //$NON-NLS-1$
    }
    return result;
  }

  private String[] getConfigurationPoints() {
    String contentTypeIdentifierID = null;
    if (getInternalModel() != null) {
      contentTypeIdentifierID = getInternalModel().getContentTypeIdentifier();
    }
    return ConfigurationPointCalculator.getConfigurationPoints(this, contentTypeIdentifierID, ConfigurationPointCalculator.SOURCE, StructuredTextEditor.class);
  }

  /**
   * added checks to overcome bug such that if we are shutting down in an
   * error condition, then viewer will have already been disposed.
   */
  protected String getCursorPosition() {
    String result = null;
    // this may be too expensive in terms of
    // performance, to do this check
    // every time, just to gaurd against error
    // condition.
    // perhaps there's a better way?
    if (getSourceViewer() != null && getSourceViewer().getTextWidget() != null && !getSourceViewer().getTextWidget().isDisposed()) {
      result = super.getCursorPosition();
    }
    else {
      result = "0:0"; //$NON-NLS-1$
    }
    return result;
  }


  Display getDisplay() {
    return PlatformUI.getWorkbench().getDisplay();
  }

  /**
   * Returns this editor part.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   *
   * @return this editor part
   */
  public IEditorPart getEditorPart() {
    if (fEditorPart == null)
      return this;
    return fEditorPart;
  }

  IStructuredModel getInternalModel() {
    return fStructuredModel;
  }

  private InternalModelStateListener getInternalModelStateListener() {
    if (fInternalModelStateListener == null) {
      fInternalModelStateListener = new InternalModelStateListener();
    }
    return fInternalModelStateListener;
  }

  /**
   * Returns this editor's StructuredModel.
   * <p>
   * Not API. Will be removed in the future.
   * </p>
   *
   * @return returns this editor's IStructuredModel
   * @deprecated - This method allowed for uncontrolled access to the model
   *             instance and will be removed in the future. It is
   *             recommended that the current document provider be asked for
   *             the current document and the IModelManager then asked for
   *             the corresponding model with
   *             getExistingModelFor*(IDocument). Supported document
   *             providers ensure that the document maps to a shared
   *             structured model.
   */
  public IStructuredModel getModel() {
    IDocumentProvider documentProvider = getDocumentProvider();
   
    if (documentProvider == null) {
      // this indicated an error in startup sequence
      Logger.trace(getClass().getName(), "Program Info Only: document provider was null when model requested"); //$NON-NLS-1$ //$NON-NLS-2$
    }
   
    // Remember if we entered this method without a model existing
    boolean initialModelNull = (fStructuredModel == null);
   
    if (fStructuredModel == null && documentProvider != null) {
      // lazily set the model instance, although this is an ABNORMAL
      // CODE PATH
      if (documentProvider instanceof IModelProvider) {
        fStructuredModel = ((IModelProvider) documentProvider).getModel(getEditorInput());
        fisReleased = false;
      }
      else {
        IDocument doc = documentProvider.getDocument(getEditorInput());
        if (doc instanceof IStructuredDocument) {
          /*
           * Called in this manner because getExistingModel can skip
           * some calculations always performed in getModelForEdit
           */
          IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForEdit(doc);
          if (model == null) {
            model = StructuredModelManager.getModelManager().getModelForEdit((IStructuredDocument) doc);
          }
          fStructuredModel = model;
          fisReleased = false;
        }
      }

      EditorModelUtil.addFactoriesTo(fStructuredModel);

      if (initialModelNull && fStructuredModel != null) {
        /*
         * DMW: 9/1/2002 -- why is update called here? No change has
         * been indicated? I'd like to remove, but will leave for now
         * to avoid breaking this hack. Should measure/breakpoint to
         * see how large the problem is. May cause performance
         * problems.
         *
         * DMW: 9/8/2002 -- not sure why this was here initially, but
         * the intent/hack must have been to call update if this was
         * the first time fStructuredModel was set. So, I added the
         * logic to check for that "first time" case. It would appear
         * we don't really need. may remove in future when can test
         * more.
         */
        update();
      }
    }
    return fStructuredModel;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.part.IWorkbenchPartOrientation#getOrientation()
   */
  public int getOrientation() {
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=88714
    return SWT.LEFT_TO_RIGHT;
  }
 
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.ITextEditor#getSelectionProvider()
   */
  public ISelectionProvider getSelectionProvider() {
    if (fStructuredSelectionProvider == null) {
      ISelectionProvider parentProvider = super.getSelectionProvider();
      if (parentProvider != null) {
        fStructuredSelectionProvider = new StructuredSelectionProvider(parentProvider, this);
        fStructuredSelectionProvider.addPostSelectionChangedListener(new ISelectionChangedListener() {
          public void selectionChanged(SelectionChangedEvent event) {
            updateStatusLine(event.getSelection());
          }
        });
        if (fStructuredModel != null) {
          SelectionConvertor convertor = (SelectionConvertor) fStructuredModel.getAdapter(SelectionConvertor.class);
          if (convertor != null) {
            fStructuredSelectionProvider.selectionConvertor = convertor;
          }
        }
      }
    }
    if (fStructuredSelectionProvider == null) {
      return super.getSelectionProvider();
    }
    return fStructuredSelectionProvider;
  }

  /* (non-Javadoc)
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#getStatusLineManager()
   *
   * Overridden to use the top-level editor part's status line
   */
  protected IStatusLineManager getStatusLineManager() {
    return getEditorPart().getEditorSite().getActionBars().getStatusLineManager();
  }

  /**
   * Returns the editor's source viewer. This method was created to expose
   * the protected final getSourceViewer() method.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   *
   * @return the editor's source viewer
   */
  public StructuredTextViewer getTextViewer() {
    return (StructuredTextViewer) getSourceViewer();
  }

  /**
   * Jumps to the matching bracket.
   */
  void gotoMatchingBracket() {
    ICharacterPairMatcher matcher = createCharacterPairMatcher();
    if (matcher == null)
      return;

    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(SSEUIMessages.GotoMatchingBracket_error_invalidSelection);
      sourceViewer.getTextWidget().getDisplay().beep();
      return;
    }

    int sourceCaretOffset = selection.getOffset() + selection.getLength();
    IRegion region = matcher.match(document, sourceCaretOffset);
    if (region == null) {
      setStatusLineErrorMessage(SSEUIMessages.GotoMatchingBracket_error_noMatchingBracket);
      sourceViewer.getTextWidget().getDisplay().beep();
      return;
    }

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

    if (length < 1)
      return;

    int anchor = matcher.getAnchor();

    // go to after the match if matching to the right
    int targetOffset = (ICharacterPairMatcher.RIGHT == anchor) ? offset : 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(SSEUIMessages.GotoMatchingBracket_error_bracketOutsideSelectedElement);
      sourceViewer.getTextWidget().getDisplay().beep();
      return;
    }

    if (selection.getLength() < 0)
      targetOffset -= selection.getLength();

    if (sourceViewer != null) {
      sourceViewer.setSelectedRange(targetOffset, selection.getLength());
      sourceViewer.revealRange(targetOffset, selection.getLength());
    }
  }
 
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleCursorPositionChanged()
   */
  protected void handleCursorPositionChanged() {
    super.handleCursorPositionChanged();
    updateStatusField(StructuredTextEditorActionConstants.STATUS_CATEGORY_OFFSET);
  }
 
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#handlePreferenceStoreChanged(org.eclipse.jface.util.PropertyChangeEvent)
   */
  protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
    String property = event.getProperty();

    if (EditorPreferenceNames.EDITOR_TEXT_HOVER_MODIFIERS.equals(property)) {
      updateHoverBehavior();
    }
   
    //enable or disable as you type validation
    else if(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS.equals(property)) {
      IReconciler reconciler = this.getSourceViewerConfiguration().getReconciler(this.getSourceViewer());
      if (reconciler instanceof DocumentRegionProcessor) {
        ((DocumentRegionProcessor) reconciler).setValidatorStrategyEnabled(isValidationEnabled());
      }
    }

    else if (AbstractStructuredFoldingStrategy.FOLDING_ENABLED.equals(property)) {
      if (getSourceViewer() instanceof ProjectionViewer) {
        // install projection support if it has not even been
        // installed yet
        if (isFoldingEnabled() && (fProjectionSupport == null)) {
          installProjectionSupport();
        }
        ProjectionViewer pv = (ProjectionViewer) getSourceViewer();
        if (pv.isProjectionMode() != isFoldingEnabled()) {
          if (pv.canDoOperation(ProjectionViewer.TOGGLE)) {
            pv.doOperation(ProjectionViewer.TOGGLE);
          }
        }
      }
    }

    // update content assist preferences
    else if (EditorPreferenceNames.CODEASSIST_PROPOSALS_BACKGROUND.equals(property)) {
      ISourceViewer sourceViewer = getSourceViewer();
      if (sourceViewer != null) {
        SourceViewerConfiguration configuration = getSourceViewerConfiguration();
        if (configuration != null) {
          IContentAssistant contentAssistant = configuration.getContentAssistant(sourceViewer);
          if (contentAssistant instanceof ContentAssistant) {
            ContentAssistant assistant = (ContentAssistant) contentAssistant;
            RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), EditorPreferenceNames.CODEASSIST_PROPOSALS_BACKGROUND);
            Color color = EditorUtility.getColor(rgb);
            assistant.setProposalSelectorBackground(color);
          }
        }
      }
    }

    // update content assist preferences
    else if (EditorPreferenceNames.CODEASSIST_PROPOSALS_FOREGROUND.equals(property)) {
      ISourceViewer sourceViewer = getSourceViewer();
      if (sourceViewer != null) {
        SourceViewerConfiguration configuration = getSourceViewerConfiguration();
        if (configuration != null) {
          IContentAssistant contentAssistant = configuration.getContentAssistant(sourceViewer);
          if (contentAssistant instanceof ContentAssistant) {
            ContentAssistant assistant = (ContentAssistant) contentAssistant;
            RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), EditorPreferenceNames.CODEASSIST_PROPOSALS_FOREGROUND);
            Color color = EditorUtility.getColor(rgb);
            assistant.setProposalSelectorForeground(color);
          }
        }
      }
    }

    // update content assist preferences
    else if (EditorPreferenceNames.CODEASSIST_PARAMETERS_BACKGROUND.equals(property)) {
      ISourceViewer sourceViewer = getSourceViewer();
      if (sourceViewer != null) {
        SourceViewerConfiguration configuration = getSourceViewerConfiguration();
        if (configuration != null) {
          IContentAssistant contentAssistant = configuration.getContentAssistant(sourceViewer);
          if (contentAssistant instanceof ContentAssistant) {
            ContentAssistant assistant = (ContentAssistant) contentAssistant;
            RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), EditorPreferenceNames.CODEASSIST_PARAMETERS_BACKGROUND);
            Color color = EditorUtility.getColor(rgb);
            assistant.setContextInformationPopupBackground(color);
            assistant.setContextSelectorBackground(color);
          }
        }
      }
    }

    // update content assist preferences
    else if (EditorPreferenceNames.CODEASSIST_PARAMETERS_FOREGROUND.equals(property)) {
      ISourceViewer sourceViewer = getSourceViewer();
      if (sourceViewer != null) {
        SourceViewerConfiguration configuration = getSourceViewerConfiguration();
        if (configuration != null) {
          IContentAssistant contentAssistant = configuration.getContentAssistant(sourceViewer);
          if (contentAssistant instanceof ContentAssistant) {
            ContentAssistant assistant = (ContentAssistant) contentAssistant;
            RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), EditorPreferenceNames.CODEASSIST_PARAMETERS_FOREGROUND);
            Color color = EditorUtility.getColor(rgb);
            assistant.setContextInformationPopupForeground(color);
            assistant.setContextSelectorForeground(color);
          }
        }
      }
    }

    super.handlePreferenceStoreChanged(event);
  }

  private boolean inBusyState() {
    return fBusyState;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite,
   *      org.eclipse.ui.IEditorInput)
   */
  public void init(IEditorSite site, IEditorInput input) throws PartInitException {
    // if we've gotten an error elsewhere, before
    // we've actually opened, then don't open.
    if (shouldClose) {
      setSite(site);
      close(false);
    }
    else {
      super.init(site, input);
    }
  }

  /**
   * Set the document provider for this editor.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   *
   * @param documentProvider
   *            documentProvider to initialize
   */
  public void initializeDocumentProvider(IDocumentProvider documentProvider) {
    if (documentProvider != null) {
      setDocumentProvider(documentProvider);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#initializeDragAndDrop(org.eclipse.jface.text.source.ISourceViewer)
   */
  protected void initializeDragAndDrop(ISourceViewer viewer) {
    IPreferenceStore store = getPreferenceStore();
    if (store != null && store.getBoolean(PREFERENCE_TEXT_DRAG_AND_DROP_ENABLED))
      initializeDrop(viewer);
  }

  protected void initializeDrop(ITextViewer textViewer) {
    int operations = DND.DROP_COPY | DND.DROP_MOVE;
    fDropTarget = new DropTarget(textViewer.getTextWidget(), operations);
    fDropAdapter = new ReadOnlyAwareDropTargetAdapter(true);
    fDropAdapter.setTargetEditor(this);
    fDropAdapter.setTargetIDs(getConfigurationPoints());
    fDropAdapter.setTextViewer(textViewer);
    fDropTarget.setTransfer(fDropAdapter.getTransfers());
    fDropTarget.addDropListener(fDropAdapter);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
   */
  protected void initializeEditor() {
    super.initializeEditor();

    setPreferenceStore(createCombinedPreferenceStore());

    setRangeIndicator(new DefaultRangeIndicator());
    setEditorContextMenuId(EDITOR_CONTEXT_MENU_ID);
    initializeDocumentProvider(null);
    // set the infopop for source viewer
    String helpId = getHelpContextId();
    // no infopop set or using default text editor help, use default
    if (helpId == null || ITextEditorHelpContextIds.TEXT_EDITOR.equals(helpId))
      helpId = IHelpContextIds.XML_SOURCE_VIEW_HELPID;
    setHelpContextId(helpId);
    // defect 203158 - disable ruler context menu for
    // beta
    // setRulerContextMenuId(RULER_CONTEXT_MENU_ID);
    configureInsertMode(SMART_INSERT, true);

    // enable the base source editor activity when editor opens
    try {
      // FIXME: - commented out to avoid minor dependancy during
      // transition to org.eclipse
      // WTPActivityBridge.getInstance().enableActivity(CORE_SSE_ACTIVITY_ID,
      // true);
    }
    catch (Exception t) {
      // if something goes wrong with enabling activity, just log the
      // error but dont
      // have it break the editor
      Logger.log(Logger.WARNING_DEBUG, t.getMessage(), t);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.editors.text.TextEditor#initializeKeyBindingScopes()
   */
  protected void initializeKeyBindingScopes() {
    setKeyBindingScopes(new String[]{EDITOR_KEYBINDING_SCOPE_ID});
  }

  /**
   * Initializes the editor's source viewer and other items that were source
   * viewer-dependent.
   */
  private void initializeSourceViewer() {
    IAction openHyperlinkAction = getAction(StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE);
    if (openHyperlinkAction instanceof OpenHyperlinkAction) {
      ((OpenHyperlinkAction) openHyperlinkAction).setHyperlinkDetectors(getSourceViewerConfiguration().getHyperlinkDetectors(getSourceViewer()));
    }

    // do not even install projection support until folding is actually
    // enabled
    if (isFoldingEnabled()) {
      installProjectionSupport();
    }
  }

  protected void initSourceViewer(StructuredTextViewer sourceViewer) {
    // ensure decoration support is configured
    getSourceViewerDecorationSupport(sourceViewer);
  }

  protected void installTextDragAndDrop(ISourceViewer viewer) {
    // do nothing
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.editors.text.TextEditor#installEncodingSupport()
   */
  protected void installEncodingSupport() {
    fEncodingSupport = new EncodingSupport(getConfigurationPoints());
    fEncodingSupport.initialize(this);
  }

  /**
   * Install everything necessary to get document folding working and enable
   * document folding
   */
  private void installProjectionSupport() {
    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.setHoverControlCreator(new IInformationControlCreator() {
      public IInformationControl createInformationControl(Shell parent) {
        return new DefaultInformationControl(parent);
      }
    });
    fProjectionSupport.install();

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

  /**
   * Return whether document folding should be enabled according to the
   * preference store settings.
   *
   * @return <code>true</code> if document folding should be enabled
   */
  private boolean isFoldingEnabled() {
    IPreferenceStore store = getPreferenceStore();
    // check both preference store and vm argument
    return (store.getBoolean(AbstractStructuredFoldingStrategy.FOLDING_ENABLED));
  }
 
  /**
   * Determine if the user preference for as you type validation is enabled or not
   */
  private boolean isValidationEnabled() {
    return getPreferenceStore().getBoolean(CommonEditorPreferenceNames.EVALUATE_TEMPORARY_PROBLEMS);
  }

  /**
   * <p>Logs a warning about how this {@link StructuredTextEditor} just opened an {@link IEditorInput}
   * it was not designed to open.</p>
   *
   * @param input the {@link IEditorInput} this {@link StructuredTextEditor} was not designed to open
   * to log the message about.
   */
  private void logUnexpectedDocumentKind(IEditorInput input) {
    Logger.log(Logger.WARNING, "StructuredTextEditor being used without StructuredDocument"); //$NON-NLS-1$
    String name = null;
    if (input != null) {
      name = input.getName();
    }
    else {
      name = "input was null"; //$NON-NLS-1$
    }
    Logger.log(Logger.WARNING, "         Input Name: " + name); //$NON-NLS-1$
    String implClass = null;
    IDocument document = getDocumentProvider().getDocument(input);
    if (document != null) {
      implClass = document.getClass().getName();
    }
    else {
      implClass = "document was null"; //$NON-NLS-1$
    }
    Logger.log(Logger.WARNING, "Unexpected IDocument implementation: " + implClass + "\n\tIDocumentProvider implementation: " + getDocumentProvider().getClass().getName()); //$NON-NLS-1$  //$NON-NLS-2$
  }

  /*
   * @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();
      }

      super.performRevert();

      if (projectionMode) {
        projectionViewer.enableProjection();
      }

    }
    finally {
      projectionViewer.setRedraw(true);
    }
  }

  /**
   * {@inheritDoc}
   * <p>
   * Not API. May be reduced to protected method in the future.
   * </p>
   */
  public void rememberSelection() {
    /*
     * This method was made public for use by editors that use
     * StructuredTextEditor (like some clients)
     */
    super.rememberSelection();
  }


  /**
   * both starts and resets the busy state timer
   */
  private void resetBusyState() {
    // reset the "busy" timeout
    if (fBusyTimer != null) {
      fBusyTimer.cancel();
    }
    startBusyTimer();
  }

  /**
   * {@inheritDoc}
   * <p>
   * Not API. May be reduced to protected method in the future.
   * </p>
   */
  public void restoreSelection() {
    /*
     * This method was made public for use by editors that use
     * StructuredTextEditor (like some clients)
     */
    // catch odd case where source viewer has no text
    // widget (defect
    // 227670)
    if ((getSourceViewer() != null) && (getSourceViewer().getTextWidget() != null))
      super.restoreSelection();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#rulerContextMenuAboutToShow(org.eclipse.jface.action.IMenuManager)
   */
  protected void rulerContextMenuAboutToShow(IMenuManager menu) {
    super.rulerContextMenuAboutToShow(menu);

    IMenuManager foldingMenu = new MenuManager(SSEUIMessages.Folding, "projection"); //$NON-NLS-1$
    menu.appendToGroup(ITextEditorActionConstants.GROUP_RULERS, foldingMenu);

    IAction action = getAction("FoldingToggle"); //$NON-NLS-1$
    foldingMenu.add(action);
    action = getAction("FoldingExpandAll"); //$NON-NLS-1$
    foldingMenu.add(action);
    action = getAction("FoldingCollapseAll"); //$NON-NLS-1$
    foldingMenu.add(action);

    IStructuredModel internalModel = getInternalModel();
    if (internalModel != null) {
      boolean debuggingAvailable = BreakpointProviderBuilder.getInstance().isAvailable(internalModel.getContentTypeIdentifier(), BreakpointRulerAction.getFileExtension(getEditorInput()));
      if (debuggingAvailable) {
        // append actions to "debug" group (created in
        // AbstractDecoratedTextEditor.rulerContextMenuAboutToShow(IMenuManager)
        menu.appendToGroup("debug", getAction(ActionDefinitionIds.TOGGLE_BREAKPOINTS)); //$NON-NLS-1$
        menu.appendToGroup("debug", getAction(ActionDefinitionIds.MANAGE_BREAKPOINTS)); //$NON-NLS-1$
        menu.appendToGroup("debug", getAction(ActionDefinitionIds.EDIT_BREAKPOINTS)); //$NON-NLS-1$
      }
      addExtendedRulerContextMenuActions(menu);
    }
  }

  /**
   * {@inheritDoc}
   * <p>
   * Overridden to expose part activation handling for multi-page editors.
   * </p>
   * <p>
   * Not API. May be reduced to protected method in the future.
   * </p>
   *
   * @see org.eclipse.ui.texteditor.AbstractTextEditor#safelySanityCheckState(org.eclipse.ui.IEditorInput)
   */
  public void safelySanityCheckState(IEditorInput input) {
    super.safelySanityCheckState(input);
  }
 
  protected void sanityCheckState(IEditorInput input) {
    try {
      ++validateEditCount;
      super.sanityCheckState(input);
    }
    finally {
      --validateEditCount;
    }
  }

  private void savedModel(IStructuredModel model) {
    if (model != null) {
      model.changedModel();
    }
  }

  /**
   * Ensure that the correct IDocumentProvider is used. For direct models, a
   * special provider is used. For StorageEditorInputs, use a custom
   * provider that creates a usable ResourceAnnotationModel. For everything
   * else, use the base support.
   *
   * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#setDocumentProvider(org.eclipse.ui.IEditorInput)
   */
  protected void setDocumentProvider(IEditorInput input) {
    if (input instanceof IStructuredModel) {
      // largely untested
      setDocumentProvider(StructuredModelDocumentProvider.getInstance());
    }
    else if (input instanceof IStorageEditorInput && !(input instanceof IFileEditorInput)) {
      setDocumentProvider(StorageModelProvider.getInstance());
    }
    else {
      super.setDocumentProvider(input);
    }
  }

  /**
   * Set editor part associated with this editor.
   * <p>
   * Not API. May be removed in the future.
   * </p>
   *
   * @param editorPart
   *            editor part associated with this editor
   */
  public void setEditorPart(IEditorPart editorPart) {
    fEditorPart = editorPart;
  }

  /**
   * Sets the model field within this editor.
   *
   * @deprecated - can eventually be eliminated
   */
  private void setModel(IStructuredModel newModel) {
    Assert.isNotNull(getDocumentProvider(), "document provider can not be null when setting model"); //$NON-NLS-1$
    if (fStructuredModel != null) {
      fStructuredModel.removeModelStateListener(getInternalModelStateListener());
    }
    fStructuredModel = newModel;
    if (fStructuredModel != null) {
      fStructuredModel.addModelStateListener(getInternalModelStateListener());
    }
    // update() should be called whenever the model is
    // set or changed
    update();
  }

  /**
   * Sets the editor's source viewer configuration which it uses to
   * configure it's internal source viewer. This method was overwritten so
   * that viewer configuration could be set after editor part was created.
   */
  protected void setSourceViewerConfiguration(SourceViewerConfiguration config) {
    SourceViewerConfiguration oldSourceViewerConfiguration = getSourceViewerConfiguration();
    super.setSourceViewerConfiguration(config);
    StructuredTextViewer stv = getTextViewer();
    if (stv != null) {
      /*
       * There should be no need to unconfigure before configure because
       * configure will also unconfigure before configuring
       */
      removeReconcilingListeners(oldSourceViewerConfiguration, stv);
      stv.unconfigure();
      setStatusLineMessage(null);
      stv.configure(config);
      addReconcilingListeners(config, stv);
    }
  }
 
  private void removeReconcilingListeners(SourceViewerConfiguration config, StructuredTextViewer stv) {
    IReconciler reconciler = config.getReconciler(stv);
    if (reconciler instanceof DocumentRegionProcessor) {
      for (int i = 0; i < fReconcilingListeners.length; i++) {
        ((DocumentRegionProcessor) reconciler).removeReconcilingListener(fReconcilingListeners[i]);
      }
    }
  }

  private void addReconcilingListeners(SourceViewerConfiguration config, StructuredTextViewer stv) {
    try {
      List reconcilingListeners = new ArrayList(fReconcilingListeners.length);
      String[] ids = getConfigurationPoints();
      for (int i = 0; i < ids.length; i++) {
        reconcilingListeners.addAll(ExtendedConfigurationBuilder.getInstance().getConfigurations("sourceReconcilingListener", ids[i])); //$NON-NLS-1$
      }
      fReconcilingListeners = (ISourceReconcilingListener[]) reconcilingListeners.toArray(new ISourceReconcilingListener[reconcilingListeners.size()]);
    }
    catch (ClassCastException e) {
      Logger.log(Logger.ERROR, "Configuration has a reconciling listener that does not implement ISourceReconcilingListener."); //$NON-NLS-1$
    }

    IReconciler reconciler = config.getReconciler(stv);
    if (reconciler instanceof DocumentRegionProcessor) {
      for (int i = 0; i < fReconcilingListeners.length; i++)
        ((DocumentRegionProcessor) reconciler).addReconcilingListener(fReconcilingListeners[i]);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.part.WorkbenchPart#showBusy(boolean)
   */
  public void showBusy(boolean busy) {
    if (busy) {
      fRememberTitle = getPartName();
      // update title and/or fonts and/or background
      //
      // temp solution, for testing, uses "busy"
      setPartName(SSEUIMessages.busy); //$NON-NLS-1$
    }
    else {
      // reset to what it was
      setPartName(fRememberTitle);
    }
  }

  private void startBusyTimer() {
    // TODO: we need a resettable timer, so not so
    // many are created
    fBusyTimer = new Timer(true);
    fBusyTimer.schedule(new TimeOutExpired(), BUSY_STATE_DELAY);
  }

  protected void uninstallTextDragAndDrop(ISourceViewer viewer) {
    // do nothing
  }

  /**
   * Update should be called whenever the model is set or changed (as in
   * swapped)
   * <p>
   * Not API. May be removed in the future.
   * </p>
   */
  public void update() {
    if (fOutlinePage != null && fOutlinePage instanceof ConfigurableContentOutlinePage) {
      ContentOutlineConfiguration cfg = createContentOutlineConfiguration();
      ((ConfigurableContentOutlinePage) fOutlinePage).setConfiguration(cfg);
      IStructuredModel internalModel = getInternalModel();
      ((ConfigurableContentOutlinePage) fOutlinePage).setInputContentTypeIdentifier(internalModel.getContentTypeIdentifier());
      ((ConfigurableContentOutlinePage) fOutlinePage).setInput(internalModel);
    }
    if (fPropertySheetPage != null && fPropertySheetPage instanceof ConfigurablePropertySheetPage) {
      PropertySheetConfiguration cfg = createPropertySheetConfiguration();
      ((ConfigurablePropertySheetPage) fPropertySheetPage).setConfiguration(cfg);
    }
    disposeModelDependentFields();

    fShowInTargetIds = createShowInTargetIds();

    if (getSourceViewerConfiguration() instanceof StructuredTextViewerConfiguration && fStatusLineLabelProvider != null) {
      fStatusLineLabelProvider.dispose();
    }

    String configurationId = fViewerConfigurationTargetId;
    updateSourceViewerConfiguration();

    /* Only reinstall if the configuration id has changed */
    if (configurationId != null && !configurationId.equals(fViewerConfigurationTargetId)) {
      uninstallSemanticHighlighting();
      installSemanticHighlighting();
    }

    if (getSourceViewerConfiguration() instanceof StructuredTextViewerConfiguration) {
      fStatusLineLabelProvider = ((StructuredTextViewerConfiguration) getSourceViewerConfiguration()).getStatusLineLabelProvider(getSourceViewer());
      updateStatusLine(null);
    }

    if (fEncodingSupport != null && fEncodingSupport instanceof EncodingSupport) {
      ((EncodingSupport) fEncodingSupport).reinitialize(getConfigurationPoints());
    }

    createModelDependentFields();
  }

  /**
   * Updates all content dependent actions.
   */
  protected void updateContentDependentActions() {
    super.updateContentDependentActions();
    // super.updateContentDependentActions only updates
    // the enable/disable
    // state of all
    // the content dependent actions.
    // StructuredTextEditor's undo and redo actions
    // have a detail label and
    // description.
    // They needed to be updated.
    if (!fEditorDisposed)
      updateMenuText();
  }


  /**
   * Updates the editor context menu by creating a new context menu with the
   * given menu id
   *
   * @param contextMenuId
   *            Cannot be null
   */
  private void updateEditorContextMenuId(String contextMenuId) {
    // update editor context menu id if updating to a new id or if context
    // menu is not already set up
    if (!contextMenuId.equals(getEditorContextMenuId()) || (fTextContextMenu == null)) {
      setEditorContextMenuId(contextMenuId);

      if (getSourceViewer() != null) {
        StyledText styledText = getSourceViewer().getTextWidget();
        if (styledText != null) {
          // dispose of previous context menu
          if (fTextContextMenu != null) {
            fTextContextMenu.dispose();
          }
          if (fTextContextMenuManager != null) {
            fTextContextMenuManager.removeMenuListener(getContextMenuListener());
            fTextContextMenuManager.removeAll();
            fTextContextMenuManager.dispose();
          }

          fTextContextMenuManager = new MenuManager(getEditorContextMenuId(), getEditorContextMenuId());
          fTextContextMenuManager.setRemoveAllWhenShown(true);
          fTextContextMenuManager.addMenuListener(getContextMenuListener());

          fTextContextMenu = fTextContextMenuManager.createContextMenu(styledText);
          styledText.setMenu(fTextContextMenu);

          getSite().registerContextMenu(getEditorContextMenuId(), fTextContextMenuManager, getSelectionProvider());

          // also register this menu for source page part and
          // structured text editor ids
          String partId = getSite().getId();
          if (partId != null) {
            getSite().registerContextMenu(partId + EDITOR_CONTEXT_MENU_SUFFIX, fTextContextMenuManager, getSelectionProvider());
          }
          getSite().registerContextMenu(EDITOR_CONTEXT_MENU_ID, fTextContextMenuManager, getSelectionProvider());
        }
      }
    }
  }

  /**
   * Updates editor context menu, vertical ruler menu, help context id for
   * new content type
   *
   * @param contentType
   */
  private void updateEditorControlsForContentType(String contentType) {
    if (contentType == null) {
      updateEditorContextMenuId(EDITOR_CONTEXT_MENU_ID);
      updateRulerContextMenuId(RULER_CONTEXT_MENU_ID);
      updateHelpContextId(ITextEditorHelpContextIds.TEXT_EDITOR);
    }
    else {
      updateEditorContextMenuId(contentType + EDITOR_CONTEXT_MENU_SUFFIX);
      updateRulerContextMenuId(contentType + RULER_CONTEXT_MENU_SUFFIX);
      updateHelpContextId(contentType + "_source_HelpId"); //$NON-NLS-1$
     
      /* Activate the contexts defined for this editor */
      activateContexts((IContextService) getSite().getService(IContextService.class));
    }
  }
 
  private void updateEncodingMemento() {
    boolean failed = false;
    IStructuredModel internalModel = getInternalModel();
    if (internalModel != null) {
      IStructuredDocument doc = internalModel.getStructuredDocument();
      EncodingMemento memento = doc.getEncodingMemento();
      IDocumentCharsetDetector detector = internalModel.getModelHandler().getEncodingDetector();
      if (memento != null && detector != null) {
        detector.set(doc);
        try {
          String newEncoding = detector.getEncoding();
          if (newEncoding != null) {
            memento.setDetectedCharsetName(newEncoding);
          }
        }
        catch (IOException e) {
          failed = true;
        }
      }
      /**
       * Be sure to use the new value but only if no exception
       * occurred. (we may find cases we need to do more error recovery
       * there) should be near impossible to get IOException from
       * processing the _document_
       */
      if (!failed) {
        doc.setEncodingMemento(memento);
      }
    }
  }

  /**
   * Updates the help context of the editor with the given help context id
   *
   * @param helpContextId
   *            Cannot be null
   */
  private void updateHelpContextId(String helpContextId) {
    if (!helpContextId.equals(getHelpContextId())) {
      setHelpContextId(helpContextId);

      if (getSourceViewer() != null) {
        StyledText styledText = getSourceViewer().getTextWidget();
        if (styledText != null) {
          IWorkbenchHelpSystem helpSystem = PlatformUI.getWorkbench().getHelpSystem();
          helpSystem.setHelp(styledText, getHelpContextId());
        }
      }
    }
  }

  /*
   * Update the hovering behavior depending on the preferences.
   */
  private void updateHoverBehavior() {
    SourceViewerConfiguration configuration = getSourceViewerConfiguration();
    String[] types = configuration.getConfiguredContentTypes(getSourceViewer());

    for (int i = 0; i < types.length; i++) {

      String t = types[i];

      ISourceViewer sourceViewer = getSourceViewer();
      if (sourceViewer instanceof ITextViewerExtension2) {
        // Remove existing hovers
        ((ITextViewerExtension2) sourceViewer).removeTextHovers(t);

        int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);

        if (stateMasks != null) {
          for (int j = 0; j < stateMasks.length; j++) {
            int stateMask = stateMasks[j];
            ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
            ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
          }
        }
        else {
          ITextHover textHover = configuration.getTextHover(sourceViewer, t);
          ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
        }
      }
      else
        sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
    }
  }

  private void updateMenuText() {
    ITextViewer viewer = getTextViewer();
    StyledText widget = null;
    if (viewer != null)
      widget = viewer.getTextWidget();

    if (fStructuredModel != null && !fStructuredModel.isModelStateChanging() && viewer != null && widget != null && !widget.isDisposed()) {
      // performance: don't force an update of the action bars unless
      // required as it is expensive
      String previousUndoText = null;
      String previousUndoDesc = null;
      String previousRedoText = null;
      String previousRedoDesc = null;
      boolean updateActions = false;
      IAction undoAction = getAction(ITextEditorActionConstants.UNDO);
      IAction redoAction = getAction(ITextEditorActionConstants.REDO);
      if (undoAction != null) {
        previousUndoText = undoAction.getText();
        previousUndoDesc = undoAction.getDescription();
        updateActions = updateActions || previousUndoText == null || previousUndoDesc == null;
        undoAction.setText(UNDO_ACTION_TEXT_DEFAULT);
        undoAction.setDescription(UNDO_ACTION_DESC_DEFAULT);
      }
      if (redoAction != null) {
        previousRedoText = redoAction.getText();
        previousRedoDesc = redoAction.getDescription();
        updateActions = updateActions || previousRedoText == null || previousRedoDesc == null;
        redoAction.setText(REDO_ACTION_TEXT_DEFAULT);
        redoAction.setDescription(REDO_ACTION_DESC_DEFAULT);
      }
      if (fStructuredModel.getUndoManager() != null) {
        IStructuredTextUndoManager undoManager = fStructuredModel.getUndoManager();
        // get undo command
        Command undoCommand = undoManager.getUndoCommand();
        // set undo label and description
        if (undoAction != null) {
          undoAction.setEnabled(undoManager.undoable());
          if (undoCommand != null) {
            String label = undoCommand.getLabel();
            if (label != null) {
              String customText = MessageFormat.format(UNDO_ACTION_TEXT, new String[]{label});
              updateActions = updateActions || customText == null || previousUndoText == null || !customText.equals(previousUndoText);
              undoAction.setText(customText);
            }
            String desc = undoCommand.getDescription();
            if (desc != null) {
              String customDesc = MessageFormat.format(UNDO_ACTION_DESC, new String[]{desc});
              updateActions = updateActions || customDesc == null || previousRedoDesc == null || !customDesc.equals(previousUndoDesc);
              undoAction.setDescription(customDesc);
            }
          }
        }
        // get redo command
        Command redoCommand = undoManager.getRedoCommand();
        // set redo label and description
        if (redoAction != null) {
          redoAction.setEnabled(undoManager.redoable());
          if (redoCommand != null) {
            String label = redoCommand.getLabel();
            if (label != null) {
              String customText = MessageFormat.format(REDO_ACTION_TEXT, new String[]{label});
              updateActions = updateActions || customText == null || previousRedoText == null || !customText.equals(previousRedoText);
              redoAction.setText(customText);
            }
            String desc = redoCommand.getDescription();
            if (desc != null) {
              String customDesc = MessageFormat.format(REDO_ACTION_DESC, new String[]{desc});
              updateActions = updateActions || customDesc == null || previousRedoDesc == null || !customDesc.equals(previousRedoDesc);
              redoAction.setDescription(customDesc);
            }
          }
        }
      }
      // tell the action bars to update
      if (updateActions) {
        if (getEditorSite().getActionBars() != null) {
          getEditorSite().getActionBars().updateActionBars();
        }
        else if (getEditorPart() != null && getEditorPart().getEditorSite().getActionBars() != null) {
          getEditorPart().getEditorSite().getActionBars().updateActionBars();
        }
      }
    }
  }

  void updateRangeIndication(ISelection selection) {
    boolean rangeUpdated = false;
    if (selection instanceof IStructuredSelection && !((IStructuredSelection) selection).isEmpty()) {
      Object[] objects = ((IStructuredSelection) selection).toArray();
      if (objects.length > 0 && objects[0] instanceof IndexedRegion) {
        int start = ((IndexedRegion) objects[0]).getStartOffset();
        int end = ((IndexedRegion) objects[0]).getEndOffset();
        if (objects.length > 1) {
          for (int i = 1; i < objects.length; i++) {
            start = Math.min(start, ((IndexedRegion) objects[i]).getStartOffset());
            end = Math.max(end, ((IndexedRegion) objects[i]).getEndOffset());
          }
        }
        getSourceViewer().setRangeIndication(start, end - start, false);
        rangeUpdated = true;
      }
    }
    if (!rangeUpdated && getSourceViewer() != null) {
      if (selection instanceof ITextSelection) {
        getSourceViewer().setRangeIndication(((ITextSelection) selection).getOffset(), ((ITextSelection) selection).getLength(), false);
      }
      else {
        getSourceViewer().removeRangeIndication();
      }
    }
  }


  /**
   * Updates the editor vertical ruler menu by creating a new vertical ruler
   * context menu with the given menu id
   *
   * @param rulerMenuId
   *            Cannot be null
   */
  private void updateRulerContextMenuId(String rulerMenuId) {
    // update ruler context menu id if updating to a new id or if context
    // menu is not already set up
    if (!rulerMenuId.equals(getRulerContextMenuId()) || (fRulerContextMenu == null)) {
      setRulerContextMenuId(rulerMenuId);

      if (getVerticalRuler() != null) {
        // dispose of previous ruler context menu
        if (fRulerContextMenu != null) {
          fRulerContextMenu.dispose();
        }
        if (fRulerContextMenuManager != null) {
          fRulerContextMenuManager.removeMenuListener(getContextMenuListener());
          fRulerContextMenuManager.removeAll();
          fRulerContextMenuManager.dispose();
        }

        fRulerContextMenuManager = new MenuManager(getRulerContextMenuId(), getRulerContextMenuId());
        fRulerContextMenuManager.setRemoveAllWhenShown(true);
        fRulerContextMenuManager.addMenuListener(getContextMenuListener());

        Control rulerControl = getVerticalRuler().getControl();
        fRulerContextMenu = fRulerContextMenuManager.createContextMenu(rulerControl);
        rulerControl.setMenu(fRulerContextMenu);

        getSite().registerContextMenu(getRulerContextMenuId(), fRulerContextMenuManager, getSelectionProvider());

        // also register this menu for source page part and structured
        // text editor ids
        String partId = getSite().getId();
        if (partId != null) {
          getSite().registerContextMenu(partId + RULER_CONTEXT_MENU_SUFFIX, fRulerContextMenuManager, getSelectionProvider());
        }
        getSite().registerContextMenu(RULER_CONTEXT_MENU_ID, fRulerContextMenuManager, getSelectionProvider());
      }
    }
  }

  private void updateSourceViewerConfiguration() {
    SourceViewerConfiguration configuration = getSourceViewerConfiguration();
    // no need to update source viewer configuration if one does not exist
    // yet
    if (configuration == null) {
      return;
    }
    // do not configure source viewer configuration twice
    boolean configured = false;

    // structuredtextviewer only works with
    // structuredtextviewerconfiguration
    if (!(configuration instanceof StructuredTextViewerConfiguration)) {
      ConfigurationAndTarget cat = createSourceViewerConfiguration();
      fViewerConfigurationTargetId = cat.getTargetId();
      configuration = cat.getConfiguration();
      setSourceViewerConfiguration(configuration);
      configured = true;
    }
    else {
      ConfigurationAndTarget cat = createSourceViewerConfiguration();
      StructuredTextViewerConfiguration newViewerConfiguration = cat.getConfiguration();
      if (!(cat.getTargetId().equals(fViewerConfigurationTargetId))) {
        // d282894 use newViewerConfiguration
        fViewerConfigurationTargetId = cat.getTargetId();
        configuration = newViewerConfiguration;
        setSourceViewerConfiguration(configuration);
        configured = true;
      }
    }

    if (getSourceViewer() != null) {
      // not sure if really need to reconfigure when input changes
      // (maybe only need to reset viewerconfig's document)
      if (!configured)
        getSourceViewer().configure(configuration);
      IAction openHyperlinkAction = getAction(StructuredTextEditorActionConstants.ACTION_NAME_OPEN_FILE);
      if (openHyperlinkAction instanceof OpenHyperlinkAction) {
        ((OpenHyperlinkAction) openHyperlinkAction).setHyperlinkDetectors(getSourceViewerConfiguration().getHyperlinkDetectors(getSourceViewer()));
      }
    }
  }

  protected void updateStatusField(String category) {
    super.updateStatusField(category);

    if (category == null)
      return;

    if (StructuredTextEditorActionConstants.STATUS_CATEGORY_OFFSET.equals(category)) {
      IStatusField field = getStatusField(category);
      ISourceViewer sourceViewer = getSourceViewer();
      if (field != null && sourceViewer != null) {
        Point selection = sourceViewer.getTextWidget().getSelection();
        int offset1 = widgetOffset2ModelOffset(sourceViewer, selection.x);
        int offset2 = widgetOffset2ModelOffset(sourceViewer, selection.y);
        String text = null;
        if (offset1 != offset2)
          text = "[" + offset1 + "-" + offset2 + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        else
          text = "[ " + offset1 + " ]"; //$NON-NLS-1$ //$NON-NLS-2$
        field.setText(text == null ? fErrorLabel : text);
      }
    }
  }
 
  public Annotation gotoAnnotation(boolean forward) {
    Annotation result = super.gotoAnnotation(forward);
    if(result != null)
      fSelectionChangedFromGoto = true;
    return result;
  }

  void updateStatusLine(ISelection selection) {
    // Bug 210481 - Don't update the status line if the selection
    // was caused by go to navigation
    if(fSelectionChangedFromGoto) {
      fSelectionChangedFromGoto = false;
      return;
    }
    IStatusLineManager statusLineManager = getEditorSite().getActionBars().getStatusLineManager();
    if (fStatusLineLabelProvider != null && statusLineManager != null) {
      String text = null;
      Image image = null;
      if (selection instanceof IStructuredSelection && !selection.isEmpty()) {
        Object firstElement = ((IStructuredSelection) selection).getFirstElement();
        if (firstElement != null) {
          text = fStatusLineLabelProvider.getText(firstElement);
          image = fStatusLineLabelProvider.getImage((firstElement));
        }
      }
      if (image == null) {
        statusLineManager.setMessage(text);
      }
      else {
        statusLineManager.setMessage(image, text);
      }
    }
  }

  /**
   * 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
   */
  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);
  }

  protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) {
    /* Removed workaround for Bug [206913] source annotations are not painting in source editors.
     * With the new presentation reconciler, we no longer need to force the painting. This
     * actually caused Bug [219776] Wrong annotation display on macs. We forced the
     * Squiggles strategy, even when the native problem underline was specified for annotations */
    return super.getSourceViewerDecorationSupport(viewer);
  }

  private void installCharacterPairing() {
    IStructuredModel model = getInternalModel();
    if (model != null) {
      IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(SSEUIPlugin.ID, "characterPairing"); //$NON-NLS-1$
      IContentTypeManager mgr = Platform.getContentTypeManager();
      IContentType type = mgr.getContentType(model.getContentTypeIdentifier());
      if (type != null) {
        for (int i = 0; i < elements.length; i++) {
          // Create the inserter
          IConfigurationElement element = elements[i];
          try {
            IConfigurationElement[] contentTypes = element.getChildren("contentTypeIdentifier");
            for (int j = 0; j < contentTypes.length; j++) {
              String id = contentTypes[j].getAttribute("id");
              if (id != null) {
                IContentType targetType = mgr.getContentType(id);
                int priority = calculatePriority(type, targetType, 0);
                if (priority >= 0) {
                  final CharacterPairing pairing = new CharacterPairing();
                  pairing.priority = priority;
                  String[] partitions = StringUtils.unpack(contentTypes[j].getAttribute("partitions"));
                  pairing.partitions = new HashSet(partitions.length);
                  // Only add the inserter if there is at least one partition for the content type
                  for (int k = 0; k < partitions.length; k++) {
                    pairing.partitions.add(partitions[k]);
                  }

                  pairing.inserter = (AbstractCharacterPairInserter) element.createExecutableExtension("class");
                  if (pairing.inserter != null && partitions.length > 0) {
                    fPairInserter.addInserter(pairing);
                    /* use a SafeRunner since this method is also invoked during Part creation */
                    SafeRunner.run(new ISafeRunnable() {
                      public void run() throws Exception {
                        pairing.inserter.initialize();
                      }

                      public void handleException(Throwable exception) {
                        // rely on default logging
                      }
                    });
                  }
                }
              }
            }
          } catch (CoreException e) {
            Logger.logException(e);
          }
        }
        fPairInserter.prioritize();
      }
    }
  }

  /**
   * Calculates the priority of the target content type. The closer <code>targetType</code>
   * is to <code>type</code> the higher its priority.
   *
   * @param type
   * @param targetType
   * @param priority
   * @return
   */
  private int calculatePriority(IContentType type, IContentType targetType, int priority) {
    if (type == null || targetType == null)
      return -1;
    if (type.getId().equals(targetType.getId()))
      return priority;
    return calculatePriority(type.getBaseType(), targetType, ++priority);
  }

  /**
   * Installs semantic highlighting on the editor
   */
  private void installSemanticHighlighting() {
    IStructuredModel model = getInternalModel();
    if (fSemanticManager == null && model != null) {
      fSemanticManager = new SemanticHighlightingManager();
      fSemanticManager.install(getSourceViewer(), getPreferenceStore(), getSourceViewerConfiguration(), model.getContentTypeIdentifier());
    }
  }
 
  /**
   * Uninstalls semantic highlighting on the editor and performs cleanup
   */
  private void uninstallSemanticHighlighting() {
    if (fSemanticManager != null) {
      fSemanticManager.uninstall();
      fSemanticManager = null;
    }
  }

  private IInformationPresenter configureOutlinePresenter(ISourceViewer sourceViewer, SourceViewerConfiguration config) {
    InformationPresenter presenter = null;

    // Get the quick outline configuration
    AbstractQuickOutlineConfiguration cfg = null;
    ExtendedConfigurationBuilder builder = ExtendedConfigurationBuilder.getInstance();
    String[] ids = getConfigurationPoints();
    for (int i = 0; cfg == null && i < ids.length; i++) {
      cfg = (AbstractQuickOutlineConfiguration) builder.getConfiguration(ExtendedConfigurationBuilder.QUICKOUTLINECONFIGURATION, ids[i]);
    }

    if (cfg != null) {
      presenter = new InformationPresenter(getOutlinePresenterControlCreator(cfg));
      presenter.setDocumentPartitioning(config.getConfiguredDocumentPartitioning(sourceViewer));
      presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
      IInformationProvider provider = new SourceInfoProvider(this);
      String[] contentTypes = config.getConfiguredContentTypes(sourceViewer);
      for (int i = 0; i < contentTypes.length; i++) {
        presenter.setInformationProvider(provider, contentTypes[i]);
      }
      presenter.setSizeConstraints(50, 20, true, false);
    }
    return presenter;
  }

  /**
   * Returns the outline presenter control creator. The creator is a
   * factory creating outline presenter controls for the given source viewer.
   *
   * @param sourceViewer the source viewer to be configured by this configuration
   * @return an information control creator
   */
  private IInformationControlCreator getOutlinePresenterControlCreator(final AbstractQuickOutlineConfiguration config) {
    return new IInformationControlCreator() {
      public IInformationControl createInformationControl(Shell parent) {
        int shellStyle = SWT.RESIZE;
        return new QuickOutlinePopupDialog(parent, shellStyle, getInternalModel(), config);
      }
    };
  }
}
TOP

Related Classes of org.eclipse.wst.sse.ui.StructuredTextEditor$StructuredSelectionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.