misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPUnitEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.text.MessageFormat;
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 import java.util.List;
7
8 import net.sourceforge.phpdt.core.ICompilationUnit;
9 import net.sourceforge.phpdt.core.IJavaElement;
10 import net.sourceforge.phpdt.core.IMember;
11 import net.sourceforge.phpdt.core.ISourceRange;
12 import net.sourceforge.phpdt.core.ISourceReference;
13 import net.sourceforge.phpdt.core.JavaCore;
14 import net.sourceforge.phpdt.core.JavaModelException;
15 import net.sourceforge.phpdt.core.dom.CompilationUnit;
16 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
17 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
18 import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
19 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
20 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
21 import net.sourceforge.phpdt.internal.ui.text.SmartBackspaceManager;
22 import net.sourceforge.phpdt.internal.ui.text.java.IJavaReconcilingListener;
23 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
24 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
25 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI.ExitFlags;
26 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
27 import net.sourceforge.phpdt.ui.PreferenceConstants;
28 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
29 import net.sourceforge.phpdt.ui.text.JavaTextTools;
30 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
31
32 import org.eclipse.core.internal.runtime.ListenerList;
33 import org.eclipse.core.resources.IFile;
34 import org.eclipse.core.resources.IWorkspaceRoot;
35 import org.eclipse.core.resources.ResourcesPlugin;
36 import org.eclipse.core.runtime.CoreException;
37 import org.eclipse.core.runtime.IPath;
38 import org.eclipse.core.runtime.IProgressMonitor;
39 import org.eclipse.core.runtime.IStatus;
40 import org.eclipse.core.runtime.Preferences;
41 import org.eclipse.jface.action.Action;
42 import org.eclipse.jface.action.IAction;
43 import org.eclipse.jface.action.IMenuManager;
44 import org.eclipse.jface.dialogs.ErrorDialog;
45 import org.eclipse.jface.dialogs.IMessageProvider;
46 import org.eclipse.jface.dialogs.MessageDialog;
47 import org.eclipse.jface.preference.IPreferenceStore;
48 import org.eclipse.jface.preference.PreferenceConverter;
49 import org.eclipse.jface.text.BadLocationException;
50 import org.eclipse.jface.text.DocumentCommand;
51 import org.eclipse.jface.text.IDocument;
52 import org.eclipse.jface.text.ILineTracker;
53 import org.eclipse.jface.text.IRegion;
54 import org.eclipse.jface.text.ITextOperationTarget;
55 import org.eclipse.jface.text.ITextViewerExtension;
56 import org.eclipse.jface.text.ITypedRegion;
57 import org.eclipse.jface.text.IWidgetTokenKeeper;
58 import org.eclipse.jface.text.contentassist.ContentAssistant;
59 import org.eclipse.jface.text.contentassist.IContentAssistant;
60 import org.eclipse.jface.text.source.IOverviewRuler;
61 import org.eclipse.jface.text.source.ISourceViewer;
62 import org.eclipse.jface.text.source.IVerticalRuler;
63 import org.eclipse.jface.text.source.SourceViewerConfiguration;
64 import org.eclipse.jface.util.PropertyChangeEvent;
65 import org.eclipse.jface.window.Window;
66 import org.eclipse.swt.SWT;
67 import org.eclipse.swt.custom.VerifyKeyListener;
68 import org.eclipse.swt.events.VerifyEvent;
69 import org.eclipse.swt.graphics.Color;
70 import org.eclipse.swt.graphics.Point;
71 import org.eclipse.swt.graphics.RGB;
72 import org.eclipse.swt.widgets.Composite;
73 import org.eclipse.swt.widgets.Display;
74 import org.eclipse.swt.widgets.Shell;
75 import org.eclipse.ui.IEditorInput;
76 import org.eclipse.ui.IEditorPart;
77 import org.eclipse.ui.IFileEditorInput;
78 import org.eclipse.ui.IWorkbenchPage;
79 import org.eclipse.ui.IWorkbenchWindow;
80 import org.eclipse.ui.actions.ActionContext;
81 import org.eclipse.ui.actions.ActionGroup;
82 import org.eclipse.ui.dialogs.SaveAsDialog;
83 import org.eclipse.ui.editors.text.IStorageDocumentProvider;
84 import org.eclipse.ui.help.WorkbenchHelp;
85 import org.eclipse.ui.part.FileEditorInput;
86 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
87 import org.eclipse.ui.texteditor.ContentAssistAction;
88 import org.eclipse.ui.texteditor.IDocumentProvider;
89 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
90 import org.eclipse.ui.texteditor.TextOperationAction;
91
92 /*******************************************************************************
93  * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This
94  * program and the accompanying materials are made available under the terms of
95  * the Common Public License v1.0 which accompanies this distribution, and is
96  * available at http://www.eclipse.org/legal/cpl-v10.html
97  * 
98  * Contributors: IBM Corporation - Initial implementation Klaus Hartlage -
99  * www.eclipseproject.de
100  ******************************************************************************/
101 /**
102  * PHP specific text editor.
103  */
104 public class PHPUnitEditor extends PHPEditor { //implements
105   // IJavaReconcilingListener {
106   interface ITextConverter {
107     void customizeDocumentCommand(IDocument document, DocumentCommand command);
108   };
109
110   //  class AdaptedRulerLayout extends Layout {
111   //
112   //    protected int fGap;
113   //    protected AdaptedSourceViewer fAdaptedSourceViewer;
114   //
115   //    protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
116   //      fGap = gap;
117   //      fAdaptedSourceViewer = asv;
118   //    }
119   //
120   //    protected Point computeSize(Composite composite, int wHint, int hHint,
121   // boolean flushCache) {
122   //      Control[] children = composite.getChildren();
123   //      Point s = children[children.length - 1].computeSize(SWT.DEFAULT,
124   // SWT.DEFAULT, flushCache);
125   //      if (fAdaptedSourceViewer.isVerticalRulerVisible())
126   //        s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
127   //      return s;
128   //    }
129   //
130   //    protected void layout(Composite composite, boolean flushCache) {
131   //      Rectangle clArea = composite.getClientArea();
132   //      if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
133   //
134   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
135   //        Rectangle trim = textWidget.computeTrim(0, 0, 0, 0);
136   //        int scrollbarHeight = trim.height;
137   //
138   //        IVerticalRuler vr = fAdaptedSourceViewer.getVerticalRuler();
139   //        int vrWidth = vr.getWidth();
140   //
141   //        int orWidth = 0;
142   //        if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
143   //          OverviewRuler or = fAdaptedSourceViewer.getOverviewRuler();
144   //          orWidth = or.getWidth();
145   //          or.getControl().setBounds(clArea.width - orWidth, scrollbarHeight,
146   // orWidth, clArea.height - 3 * scrollbarHeight);
147   //        }
148   //
149   //        textWidget.setBounds(vrWidth + fGap, 0, clArea.width - vrWidth - orWidth
150   // -
151   // 2 * fGap, clArea.height);
152   //        vr.getControl().setBounds(0, 0, vrWidth, clArea.height -
153   // scrollbarHeight);
154   //
155   //      } else {
156   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
157   //        textWidget.setBounds(0, 0, clArea.width, clArea.height);
158   //      }
159   //    }
160   //  };
161   //
162   //  class AdaptedSourceViewer extends SourceViewer { // extends
163   // JavaCorrectionSourceViewer {
164   //
165   //    private List fTextConverters;
166   //
167   //    private OverviewRuler fOverviewRuler;
168   //    private boolean fIsOverviewRulerVisible;
169   //    /** The viewer's overview ruler hovering controller */
170   //    private AbstractHoverInformationControlManager
171   // fOverviewRulerHoveringController;
172   //
173   //    private boolean fIgnoreTextConverters = false;
174   //
175   //    private IVerticalRuler fCachedVerticalRuler;
176   //    private boolean fCachedIsVerticalRulerVisible;
177   //
178   //    public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int
179   // styles) {
180   //      super(parent, ruler, styles); //, CompilationUnitEditor.this);
181   //
182   //      fCachedVerticalRuler = ruler;
183   //      fCachedIsVerticalRulerVisible = (ruler != null);
184   //      fOverviewRuler = new OverviewRuler(VERTICAL_RULER_WIDTH);
185   //
186   //      delayedCreateControl(parent, styles);
187   //    }
188   //
189   //    /*
190   //     * @see ISourceViewer#showAnnotations(boolean)
191   //     */
192   //    public void showAnnotations(boolean show) {
193   //      fCachedIsVerticalRulerVisible = (show && fCachedVerticalRuler != null);
194   //      // super.showAnnotations(show);
195   //    }
196   //
197   //    public IContentAssistant getContentAssistant() {
198   //      return fContentAssistant;
199   //    }
200   //
201   //    /*
202   //     * @see ITextOperationTarget#doOperation(int)
203   //     */
204   //    public void doOperation(int operation) {
205   //
206   //      if (getTextWidget() == null)
207   //        return;
208   //
209   //      switch (operation) {
210   //        case CONTENTASSIST_PROPOSALS :
211   //          String msg = fContentAssistant.showPossibleCompletions();
212   //          setStatusLineErrorMessage(msg);
213   //          return;
214   //        case UNDO :
215   //          fIgnoreTextConverters = true;
216   //          break;
217   //        case REDO :
218   //          fIgnoreTextConverters = true;
219   //          break;
220   //      }
221   //
222   //      super.doOperation(operation);
223   //    }
224   //
225   //    public void insertTextConverter(ITextConverter textConverter, int index)
226   // {
227   //      throw new UnsupportedOperationException();
228   //    }
229   //
230   //    public void addTextConverter(ITextConverter textConverter) {
231   //      if (fTextConverters == null) {
232   //        fTextConverters = new ArrayList(1);
233   //        fTextConverters.add(textConverter);
234   //      } else if (!fTextConverters.contains(textConverter))
235   //        fTextConverters.add(textConverter);
236   //    }
237   //
238   //    public void removeTextConverter(ITextConverter textConverter) {
239   //      if (fTextConverters != null) {
240   //        fTextConverters.remove(textConverter);
241   //        if (fTextConverters.size() == 0)
242   //          fTextConverters = null;
243   //      }
244   //    }
245   //
246   //    /*
247   //     * @see TextViewer#customizeDocumentCommand(DocumentCommand)
248   //     */
249   //    protected void customizeDocumentCommand(DocumentCommand command) {
250   //      super.customizeDocumentCommand(command);
251   //      if (!fIgnoreTextConverters && fTextConverters != null) {
252   //        for (Iterator e = fTextConverters.iterator(); e.hasNext();)
253   //           ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(),
254   // command);
255   //      }
256   //      fIgnoreTextConverters = false;
257   //    }
258   //
259   //    public IVerticalRuler getVerticalRuler() {
260   //      return fCachedVerticalRuler;
261   //    }
262   //
263   //    public boolean isVerticalRulerVisible() {
264   //      return fCachedIsVerticalRulerVisible;
265   //    }
266   //
267   //    public OverviewRuler getOverviewRuler() {
268   //      return fOverviewRuler;
269   //    }
270   //
271   //    /*
272   //     * @see TextViewer#createControl(Composite, int)
273   //     */
274   //    protected void createControl(Composite parent, int styles) {
275   //      // do nothing here
276   //    }
277   //
278   //    protected void delayedCreateControl(Composite parent, int styles) {
279   //      //create the viewer
280   //      super.createControl(parent, styles);
281   //
282   //      Control control = getControl();
283   //      if (control instanceof Composite) {
284   //        Composite composite = (Composite) control;
285   //        composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this));
286   //        fOverviewRuler.createControl(composite, this);
287   //      }
288   //    }
289   //    protected void ensureOverviewHoverManagerInstalled() {
290   //      if (fOverviewRulerHoveringController == null && fAnnotationHover != null
291   // && fHoverControlCreator != null) {
292   //        fOverviewRulerHoveringController =
293   //          new OverviewRulerHoverManager(fOverviewRuler, this, fAnnotationHover,
294   // fHoverControlCreator);
295   //        fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
296   //      }
297   //    }
298   //
299   //    public void hideOverviewRuler() {
300   //      fIsOverviewRulerVisible = false;
301   //      Control control = getControl();
302   //      if (control instanceof Composite) {
303   //        Composite composite = (Composite) control;
304   //        composite.layout();
305   //      }
306   //      if (fOverviewRulerHoveringController != null) {
307   //        fOverviewRulerHoveringController.dispose();
308   //        fOverviewRulerHoveringController = null;
309   //      }
310   //    }
311   //
312   //    public void showOverviewRuler() {
313   //      fIsOverviewRulerVisible = true;
314   //      Control control = getControl();
315   //      if (control instanceof Composite) {
316   //        Composite composite = (Composite) control;
317   //        composite.layout();
318   //      }
319   //      ensureOverviewHoverManagerInstalled();
320   //    }
321   //
322   //    public boolean isOverviewRulerVisible() {
323   //      return fIsOverviewRulerVisible;
324   //    }
325   //
326   //    /*
327   //     * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
328   //     */
329   //    public void setDocument(
330   //      IDocument document,
331   //      IAnnotationModel annotationModel,
332   //      int visibleRegionOffset,
333   //      int visibleRegionLength) {
334   //      super.setDocument(document, annotationModel, visibleRegionOffset,
335   // visibleRegionLength);
336   //      fOverviewRuler.setModel(annotationModel);
337   //    }
338   //
339   //    // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
340   //    public void updateIndentationPrefixes() {
341   //      SourceViewerConfiguration configuration = getSourceViewerConfiguration();
342   //      String[] types = configuration.getConfiguredContentTypes(this);
343   //      for (int i = 0; i < types.length; i++) {
344   //        String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
345   //        if (prefixes != null && prefixes.length > 0)
346   //          setIndentPrefixes(prefixes, types[i]);
347   //      }
348   //    }
349   //
350   //    /*
351   //     * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
352   //     */
353   //    public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
354   //      if (WorkbenchHelp.isContextHelpDisplayed())
355   //        return false;
356   //      return super.requestWidgetToken(requester);
357   //    }
358   //
359   //    /*
360   //     * @see
361   // org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
362   //     */
363   //    public void configure(SourceViewerConfiguration configuration) {
364   //      super.configure(configuration);
365   //      // prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this),
366   // IDocument.DEFAULT_CONTENT_TYPE);
367   //    }
368   //
369   //    protected void handleDispose() {
370   //      fOverviewRuler = null;
371   //
372   //      if (fOverviewRulerHoveringController != null) {
373   //        fOverviewRulerHoveringController.dispose();
374   //        fOverviewRulerHoveringController = null;
375   //      }
376   //
377   //      super.handleDispose();
378   //    }
379   //
380   //  };
381   class AdaptedSourceViewer extends JavaSourceViewer {
382     private List fTextConverters;
383
384     private boolean fIgnoreTextConverters = false;
385
386     //                  private JavaCorrectionAssistant fCorrectionAssistant;
387     public AdaptedSourceViewer(Composite parent, IVerticalRuler verticalRuler,
388         IOverviewRuler overviewRuler, boolean showAnnotationsOverview,
389         int styles, IPreferenceStore store) {
390       super(parent, verticalRuler, overviewRuler, showAnnotationsOverview,
391           styles, store);
392     }
393
394     //          public AdaptedSourceViewer(Composite parent,
395     //                          IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
396     //                          boolean showAnnotationsOverview, int styles) {
397     //                  super(parent, verticalRuler, overviewRuler,
398     //                                  showAnnotationsOverview, styles);
399     //          }
400     public IContentAssistant getContentAssistant() {
401       return fContentAssistant;
402     }
403
404     /*
405      * @see ITextOperationTarget#doOperation(int)
406      */
407     public void doOperation(int operation) {
408       if (getTextWidget() == null)
409         return;
410       switch (operation) {
411       case CONTENTASSIST_PROPOSALS:
412         String msg = fContentAssistant.showPossibleCompletions();
413         setStatusLineErrorMessage(msg);
414         return;
415       //                                        case CORRECTIONASSIST_PROPOSALS:
416       //                                                fCorrectionAssistant.showPossibleCompletions();
417       //                                                return;
418       case UNDO:
419         fIgnoreTextConverters = true;
420         break;
421       case REDO:
422         fIgnoreTextConverters = true;
423         break;
424       }
425       super.doOperation(operation);
426     }
427
428     /*
429      * @see ITextOperationTarget#canDoOperation(int)
430      */
431     public boolean canDoOperation(int operation) {
432       //                                if (operation == CORRECTIONASSIST_PROPOSALS)
433       //                                        return isEditable();
434       return super.canDoOperation(operation);
435     }
436
437     /*
438      * @see TextViewer#handleDispose()
439      */
440     protected void handleDispose() {
441       //                                if (fCorrectionAssistant != null) {
442       //                                        fCorrectionAssistant.uninstall();
443       //                                        fCorrectionAssistant= null;
444       //                                }
445       super.handleDispose();
446     }
447
448     public void insertTextConverter(ITextConverter textConverter, int index) {
449       throw new UnsupportedOperationException();
450     }
451
452     public void addTextConverter(ITextConverter textConverter) {
453       if (fTextConverters == null) {
454         fTextConverters = new ArrayList(1);
455         fTextConverters.add(textConverter);
456       } else if (!fTextConverters.contains(textConverter))
457         fTextConverters.add(textConverter);
458     }
459
460     public void removeTextConverter(ITextConverter textConverter) {
461       if (fTextConverters != null) {
462         fTextConverters.remove(textConverter);
463         if (fTextConverters.size() == 0)
464           fTextConverters = null;
465       }
466     }
467
468     /*
469      * @see TextViewer#customizeDocumentCommand(DocumentCommand)
470      */
471     protected void customizeDocumentCommand(DocumentCommand command) {
472       super.customizeDocumentCommand(command);
473       if (!fIgnoreTextConverters && fTextConverters != null) {
474         for (Iterator e = fTextConverters.iterator(); e.hasNext();)
475           ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(),
476               command);
477       }
478       fIgnoreTextConverters = false;
479     }
480
481     // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
482     public void updateIndentationPrefixes() {
483       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
484       String[] types = configuration.getConfiguredContentTypes(this);
485       for (int i = 0; i < types.length; i++) {
486         String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
487         if (prefixes != null && prefixes.length > 0)
488           setIndentPrefixes(prefixes, types[i]);
489       }
490     }
491
492     /*
493      * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
494      */
495     public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
496       if (WorkbenchHelp.isContextHelpDisplayed())
497         return false;
498       return super.requestWidgetToken(requester);
499     }
500
501     /*
502      * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
503      */
504     public void configure(SourceViewerConfiguration configuration) {
505       super.configure(configuration);
506       //                                fCorrectionAssistant= new
507       // JavaCorrectionAssistant(CompilationUnitEditor.this);
508       //                                fCorrectionAssistant.install(this);
509       //TODO install SmartBracesAutoEditStrategy
510       //                                prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this),
511       // IDocument.DEFAULT_CONTENT_TYPE);
512     }
513   };
514   /**
515          * Remembers data related to the current selection to be able to
516          * restore it later.
517          * 
518          * @since 3.0
519          */
520         private class RememberedSelection {
521                 /** The remembered selection start. */
522                 private RememberedOffset fStartOffset= new RememberedOffset();
523                 /** The remembered selection end. */
524                 private RememberedOffset fEndOffset= new RememberedOffset();
525
526                 /**
527                  * Remember current selection.
528                  */
529                 public void remember() {
530                         /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257
531                          * This method may be called inside an async call posted
532                          * to the UI thread, so protect against intermediate disposal
533                          * of the editor. 
534                          */
535                         ISourceViewer viewer= getSourceViewer();
536                         if (viewer != null) {
537                                 IRegion selection= getSignedSelection(viewer);
538                                 int startOffset= selection.getOffset();
539                                 int endOffset= startOffset + selection.getLength();
540                                 
541                                 fStartOffset.setOffset(startOffset);
542                                 fEndOffset.setOffset(endOffset);
543                         }
544                 }
545
546                 /**
547                  * Restore remembered selection.
548                  */
549                 public void restore() {
550                         /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=52257
551                          * This method may be called inside an async call posted
552                          * to the UI thread, so protect against intermediate disposal
553                          * of the editor.
554                          */
555                         if (getSourceViewer() == null)
556                                 return;
557                         
558                         try {
559                                 
560                                 int startOffset, endOffset;
561                                 int revealStartOffset, revealEndOffset; 
562                                 if (showsHighlightRangeOnly()) {
563                                         IJavaElement newStartElement= fStartOffset.getElement();
564                                         startOffset= fStartOffset.getRememberedOffset(newStartElement);
565                                         revealStartOffset= fStartOffset.getRevealOffset(newStartElement, startOffset);
566                                         if (revealStartOffset == -1)
567                                                 startOffset= -1;
568                                         
569                                         IJavaElement newEndElement= fEndOffset.getElement();
570                                         endOffset= fEndOffset.getRememberedOffset(newEndElement);
571                                         revealEndOffset= fEndOffset.getRevealOffset(newEndElement, endOffset);
572                                         if (revealEndOffset == -1)
573                                                 endOffset= -1;
574                                 } else {
575                                         startOffset= fStartOffset.getOffset();
576                                         revealStartOffset= startOffset;
577                                         endOffset= fEndOffset.getOffset();
578                                         revealEndOffset= endOffset;
579                                 }
580                                 
581                                 if (startOffset == -1) {
582                                         startOffset= endOffset; // fallback to caret offset
583                                         revealStartOffset= revealEndOffset;
584                                 }
585                                 
586                                 if (endOffset == -1) {
587                                         endOffset= startOffset; // fallback to other offset
588                                         revealEndOffset= revealStartOffset;
589                                 }
590                                 
591                                 IJavaElement element;
592                                 if (endOffset == -1) {
593                                          // fallback to element selection
594                                         element= fEndOffset.getElement();
595                                         if (element == null)
596                                                 element= fStartOffset.getElement();
597                                         if (element != null)
598                                                 setSelection(element);
599                                         return;
600                                 }
601                                                         
602                                 if (isValidSelection(revealStartOffset, revealEndOffset - revealStartOffset) && isValidSelection(startOffset, endOffset - startOffset))
603                                         selectAndReveal(startOffset, endOffset - startOffset, revealStartOffset, revealEndOffset - revealStartOffset);
604                         } finally {
605                                 fStartOffset.clear();
606                                 fEndOffset.clear();
607                         }
608                 }
609
610                 private boolean isValidSelection(int offset, int length) {
611                         IDocumentProvider provider= getDocumentProvider();
612                         if (provider != null) {
613                                 IDocument document= provider.getDocument(getEditorInput());
614                                 if (document != null) {
615                                         int end= offset + length;
616                                         int documentLength= document.getLength();
617                                         return 0 <= offset  && offset <= documentLength && 0 <= end && end <= documentLength;
618                                 }
619                         }
620                         return false;
621                 }
622                 
623         }
624
625         /**
626          * Remembers additional data for a given
627          * offset to be able restore it later.
628          * 
629          * @since 3.0
630          */
631         private class RememberedOffset {
632                 /** Remembered line for the given offset */
633                 private int fLine;
634                 /** Remembered column for the given offset*/
635                 private int fColumn;
636                 /** Remembered Java element for the given offset*/
637                 private IJavaElement fElement;
638                 /** Remembered Java element line for the given offset*/
639                 private int fElementLine;
640                 
641                 /**
642                  * Store visual properties of the given offset.  
643                  * 
644                  * @param offset Offset in the document
645                  */
646                 public void setOffset(int offset) {
647                         try {
648                                 IDocument document= getSourceViewer().getDocument();
649                                 fLine= document.getLineOfOffset(offset);
650                                 fColumn= offset - document.getLineOffset(fLine);
651                                 fElement= getElementAt(offset, true);
652
653                                 fElementLine= -1;
654                                 if (fElement instanceof IMember) {
655                                         ISourceRange range= ((IMember) fElement).getNameRange();
656                                         if (range != null)
657                                                 fElementLine= document.getLineOfOffset(range.getOffset());
658                                 }
659                                 if (fElementLine == -1)
660                                         fElementLine= document.getLineOfOffset(getOffset(fElement));
661                         } catch (BadLocationException e) {
662                                 // should not happen
663                                 PHPeclipsePlugin.log(e);
664                                 clear();
665                         } catch (JavaModelException e) {
666                                 // should not happen
667                           PHPeclipsePlugin.log(e.getStatus());
668                                 clear();
669                         }
670                 }
671
672                 /**
673                  * Return offset recomputed from stored visual properties.  
674                  * 
675                  * @return Offset in the document
676                  */
677                 public int getOffset() {
678                         IJavaElement newElement= getElement();
679                         
680                         int offset= getRememberedOffset(newElement);
681                         
682                         if (offset != -1 && !containsOffset(newElement, offset) && (offset == 0 || !containsOffset(newElement, offset - 1)))
683                                 return -1;
684                         
685                         return offset;
686                 }
687                 
688                 /**
689                  * Return offset recomputed from stored visual properties.  
690                  * 
691                  * @param newElement Enclosing element
692                  * @return Offset in the document
693                  */
694                 public int getRememberedOffset(IJavaElement newElement) {
695                         try {
696                                 if (newElement == null)
697                                         return -1;
698                                 
699                                 IDocument document= getSourceViewer().getDocument();
700                                 int newElementLine= -1;
701                                 if (newElement instanceof IMember) {
702                                         ISourceRange range= ((IMember) newElement).getNameRange();
703                                         if (range != null)
704                                                 newElementLine= document.getLineOfOffset(range.getOffset());
705                                 }
706                                 if (newElementLine == -1)
707                                         newElementLine= document.getLineOfOffset(getOffset(newElement));
708                                 if (newElementLine == -1)
709                                         return -1;
710
711                                 int newLine= fLine + newElementLine - fElementLine;
712                                 if (newLine < 0 || newLine >= document.getNumberOfLines())
713                                         return -1;
714                                 int maxColumn= document.getLineLength(newLine);
715                                 String lineDelimiter= document.getLineDelimiter(newLine);
716                                 if (lineDelimiter != null)
717                                         maxColumn= maxColumn - lineDelimiter.length();
718                                 int offset;
719                                 if (fColumn > maxColumn)
720                                         offset= document.getLineOffset(newLine) + maxColumn;
721                                 else
722                                         offset= document.getLineOffset(newLine) + fColumn;
723
724                                 return offset;
725                         } catch (BadLocationException e) {
726                                 // should not happen
727                           PHPeclipsePlugin.log(e);
728                                 return -1;
729                         } catch (JavaModelException e) {
730                                 // should not happen
731                           PHPeclipsePlugin.log(e.getStatus());
732                                 return -1;
733                         }
734                 }
735                 
736                 /**
737                  * Returns the offset used to reveal the given element based on the given selection offset.
738                  * @param element the element
739                  * @param offset the selection offset
740                  * @return the offset to reveal the given element based on the given selection offset
741                  */
742                 public int getRevealOffset(IJavaElement element, int offset) {
743                         if (element == null || offset == -1)
744                                 return -1;
745
746                         if (containsOffset(element, offset)) {
747                                 if (offset > 0) {
748                                         IJavaElement alternateElement= getElementAt(offset, false);
749                                         if (element.getHandleIdentifier().equals(alternateElement.getParent().getHandleIdentifier()))
750                                                 return offset - 1; // Solves test case 2 from https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
751                                 }
752                                 return offset;
753                         } else if (offset > 0 && containsOffset(element, offset - 1))
754                                 return offset - 1; // Solves test case 1 from https://bugs.eclipse.org/bugs/show_bug.cgi?id=47727#c3
755                         
756                         return -1;
757                 }
758
759                 /**
760                  * Return Java element recomputed from stored visual properties.  
761                  * 
762                  * @return Java element
763                  */
764                 public IJavaElement getElement() {
765                         if (fElement == null)
766                                 return null;
767                         
768                         return findElement(fElement);
769                 }
770
771                 /**
772                  * Clears the stored position 
773                  */
774                 public void clear() {
775                         fLine= -1;
776                         fColumn= -1;
777                         fElement= null;
778                         fElementLine= -1;
779                 }
780                 
781                 /**
782                  * Does the given Java element contain the given offset?
783                  * @param element Java element
784                  * @param offset Offset
785                  * @return <code>true</code> iff the Java element contains the offset
786                  */
787                 private boolean containsOffset(IJavaElement element, int offset) {
788                         int elementOffset= getOffset(element);
789                         int elementLength= getLength(element);
790                         return (elementOffset > -1 && elementLength > -1) ? (offset >= elementOffset && offset < elementOffset + elementLength) : false;
791                 }
792                 /**
793                  * Returns the offset of the given Java element.
794                  * 
795                  * @param element       Java element
796                  * @return Offset of the given Java element
797                  */
798                 private int getOffset(IJavaElement element) {
799                         if (element instanceof ISourceReference) {
800                                 ISourceReference sr= (ISourceReference) element;
801                                 try {
802                                         ISourceRange srcRange= sr.getSourceRange();
803                                         if (srcRange != null)
804                                                 return srcRange.getOffset();
805                                 } catch (JavaModelException e) {
806                                 }
807                         }
808                         return -1;      
809                 }
810                 
811                 /**
812                  * Returns the length of the given Java element.
813                  * 
814                  * @param element       Java element
815                  * @return Length of the given Java element
816                  */
817                 private int getLength(IJavaElement element) {
818                         if (element instanceof ISourceReference) {
819                                 ISourceReference sr= (ISourceReference) element;
820                                 try {
821                                         ISourceRange srcRange= sr.getSourceRange();
822                                         if (srcRange != null)
823                                                 return srcRange.getLength();
824                                 } catch (JavaModelException e) {
825                                 }
826                         }
827                         return -1;      
828                 }
829                 
830                 /**
831                  * Returns the updated java element for the old java element.
832                  * 
833                  * @param element Old Java element
834                  * @return Updated Java element
835                  */
836                 private IJavaElement findElement(IJavaElement element) {
837                         
838                         if (element == null)
839                                 return null;
840                         
841                         IWorkingCopyManager manager= PHPeclipsePlugin.getDefault().getWorkingCopyManager();
842                         ICompilationUnit unit= manager.getWorkingCopy(getEditorInput());
843                         
844                         if (unit != null) {
845                                 try {
846                                         
847                                         synchronized (unit) {
848 //                                              unit.reconcile(ICompilationUnit.NO_AST, false, null, null);
849                                                 unit.reconcile();
850                                         }
851                                         IJavaElement[] findings= unit.findElements(element);
852                                         if (findings != null && findings.length > 0)
853                                                 return findings[0];
854                                 
855                                 } catch (JavaModelException x) {
856                                   PHPeclipsePlugin.log(x.getStatus());
857                                         // nothing found, be tolerant and go on
858                                 }
859                         }
860                         
861                         return null;
862                 }
863                 
864         }
865         
866   static class TabConverter implements ITextConverter {
867     private int fTabRatio;
868
869     private ILineTracker fLineTracker;
870
871     public TabConverter() {
872     }
873
874     public void setNumberOfSpacesPerTab(int ratio) {
875       fTabRatio = ratio;
876     }
877
878     public void setLineTracker(ILineTracker lineTracker) {
879       fLineTracker = lineTracker;
880     }
881
882     private int insertTabString(StringBuffer buffer, int offsetInLine) {
883       if (fTabRatio == 0)
884         return 0;
885       int remainder = offsetInLine % fTabRatio;
886       remainder = fTabRatio - remainder;
887       for (int i = 0; i < remainder; i++)
888         buffer.append(' ');
889       return remainder;
890     }
891
892     public void customizeDocumentCommand(IDocument document,
893         DocumentCommand command) {
894       String text = command.text;
895       if (text == null)
896         return;
897       int index = text.indexOf('\t');
898       if (index > -1) {
899         StringBuffer buffer = new StringBuffer();
900         fLineTracker.set(command.text);
901         int lines = fLineTracker.getNumberOfLines();
902         try {
903           for (int i = 0; i < lines; i++) {
904             int offset = fLineTracker.getLineOffset(i);
905             int endOffset = offset + fLineTracker.getLineLength(i);
906             String line = text.substring(offset, endOffset);
907             int position = 0;
908             if (i == 0) {
909               IRegion firstLine = document
910                   .getLineInformationOfOffset(command.offset);
911               position = command.offset - firstLine.getOffset();
912             }
913             int length = line.length();
914             for (int j = 0; j < length; j++) {
915               char c = line.charAt(j);
916               if (c == '\t') {
917                 position += insertTabString(buffer, position);
918               } else {
919                 buffer.append(c);
920                 ++position;
921               }
922             }
923           }
924           command.text = buffer.toString();
925         } catch (BadLocationException x) {
926         }
927       }
928     }
929   };
930
931   private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
932     final char fExitCharacter;
933
934     public ExitPolicy(char exitCharacter) {
935       fExitCharacter = exitCharacter;
936     }
937
938     /*
939      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionManager,
940      *      org.eclipse.swt.events.VerifyEvent, int, int)
941      */
942     public ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event,
943         int offset, int length) {
944       if (event.character == fExitCharacter) {
945         if (manager.anyPositionIncludes(offset, length))
946           return new ExitFlags(LinkedPositionUI.COMMIT
947               | LinkedPositionUI.UPDATE_CARET, false);
948         else
949           return new ExitFlags(LinkedPositionUI.COMMIT, true);
950       }
951       switch (event.character) {
952       case '\b':
953         if (manager.getFirstPosition().length == 0)
954           return new ExitFlags(0, false);
955         else
956           return null;
957       case '\n':
958       case '\r':
959         return new ExitFlags(LinkedPositionUI.COMMIT, true);
960       default:
961         return null;
962       }
963     }
964   }
965
966   private static class BracketLevel {
967     int fOffset;
968
969     int fLength;
970
971     LinkedPositionManager fManager;
972
973     LinkedPositionUI fEditor;
974   };
975
976   private class BracketInserter implements VerifyKeyListener,
977       LinkedPositionUI.ExitListener {
978     private boolean fCloseBracketsPHP = true;
979
980     private boolean fCloseStringsPHP = true;
981
982     private boolean fCloseBracketsHTML = true;
983
984     private boolean fCloseStringsHTML = true;
985
986     private int fOffset;
987
988     private int fLength;
989
990     public void setCloseBracketsPHPEnabled(boolean enabled) {
991       fCloseBracketsPHP = enabled;
992     }
993
994     public void setCloseStringsPHPEnabled(boolean enabled) {
995       fCloseStringsPHP = enabled;
996     }
997
998     public void setCloseBracketsHTMLEnabled(boolean enabled) {
999       fCloseBracketsHTML = enabled;
1000     }
1001
1002     public void setCloseStringsHTMLEnabled(boolean enabled) {
1003       fCloseStringsHTML = enabled;
1004     }
1005
1006     private boolean hasIdentifierToTheRight(IDocument document, int offset) {
1007       try {
1008         int end = offset;
1009         IRegion endLine = document.getLineInformationOfOffset(end);
1010         int maxEnd = endLine.getOffset() + endLine.getLength();
1011         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
1012           ++end;
1013         return end != maxEnd
1014             && Scanner.isPHPIdentifierPart(document.getChar(end));
1015       } catch (BadLocationException e) {
1016         // be conservative
1017         return true;
1018       }
1019     }
1020
1021     private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
1022       try {
1023         int start = offset;
1024         IRegion startLine = document.getLineInformationOfOffset(start);
1025         int minStart = startLine.getOffset();
1026         while (start != minStart
1027             && Character.isWhitespace(document.getChar(start - 1)))
1028           --start;
1029         return start != minStart
1030             && Scanner.isPHPIdentifierPart(document.getChar(start - 1));
1031       } catch (BadLocationException e) {
1032         return true;
1033       }
1034     }
1035
1036     private boolean hasCharacterToTheRight(IDocument document, int offset,
1037         char character) {
1038       try {
1039         int end = offset;
1040         IRegion endLine = document.getLineInformationOfOffset(end);
1041         int maxEnd = endLine.getOffset() + endLine.getLength();
1042         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
1043           ++end;
1044         return end != maxEnd && document.getChar(end) == character;
1045       } catch (BadLocationException e) {
1046         // be conservative
1047         return true;
1048       }
1049     }
1050
1051     /*
1052      * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
1053      */
1054     public void verifyKey(VerifyEvent event) {
1055       if (!event.doit)
1056         return;
1057       final ISourceViewer sourceViewer = getSourceViewer();
1058       IDocument document = sourceViewer.getDocument();
1059       final Point selection = sourceViewer.getSelectedRange();
1060       final int offset = selection.x;
1061       final int length = selection.y;
1062       try {
1063         ITypedRegion partition = document.getPartition(offset);
1064         String type = partition.getType();
1065         if (type.equals(IPHPPartitions.PHP_PARTITIONING)) {
1066           switch (event.character) {
1067           case '(':
1068             if (hasCharacterToTheRight(document, offset + length, '('))
1069               return;
1070           // fall through
1071           case '[':
1072             if (!fCloseBracketsPHP)
1073               return;
1074             if (hasIdentifierToTheRight(document, offset + length))
1075               return;
1076           // fall through
1077           case '"':
1078             if (event.character == '"') {
1079               if (!fCloseStringsPHP)
1080                 return;
1081               // changed for statements like echo "" print ""
1082               //    if (hasIdentifierToTheLeft(document, offset)
1083               // ||
1084               // hasIdentifierToTheRight(document, offset +
1085               // length))
1086               if (hasIdentifierToTheRight(document, offset + length))
1087                 return;
1088             }
1089             //     ITypedRegion partition=
1090             // document.getPartition(offset);
1091             //       if (!
1092             // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
1093             // &&
1094             // (partition.getOffset() != offset))
1095             //         return;
1096             final char character = event.character;
1097             final char closingCharacter = getPeerCharacter(character);
1098             final StringBuffer buffer = new StringBuffer();
1099             buffer.append(character);
1100             buffer.append(closingCharacter);
1101             document.replace(offset, length, buffer.toString());
1102             LinkedPositionManager manager = new LinkedPositionManager(document);
1103             manager.addPosition(offset + 1, 0);
1104             fOffset = offset;
1105             fLength = 2;
1106             LinkedPositionUI editor = new LinkedPositionUI(sourceViewer,
1107                 manager);
1108             editor.setCancelListener(this);
1109             editor.setExitPolicy(new ExitPolicy(closingCharacter));
1110             editor.setFinalCaretOffset(offset + 2);
1111             editor.enter();
1112             IRegion newSelection = editor.getSelectedRegion();
1113             sourceViewer.setSelectedRange(newSelection.getOffset(),
1114                 newSelection.getLength());
1115             event.doit = false;
1116           }
1117         } else if (type.equals(IPHPPartitions.HTML)
1118             || type.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
1119           switch (event.character) {
1120           case '(':
1121             if (hasCharacterToTheRight(document, offset + length, '('))
1122               return;
1123           // fall through
1124           case '[':
1125             if (!fCloseBracketsHTML)
1126               return;
1127             if (hasIdentifierToTheRight(document, offset + length))
1128               return;
1129           // fall through
1130           case '"':
1131             if (event.character == '"') {
1132               if (!fCloseStringsHTML)
1133                 return;
1134               if (hasIdentifierToTheLeft(document, offset)
1135                   || hasIdentifierToTheRight(document, offset + length))
1136                 return;
1137             }
1138             //     ITypedRegion partition=
1139             // document.getPartition(offset);
1140             //       if (!
1141             // IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType())
1142             // &&
1143             // (partition.getOffset() != offset))
1144             //         return;
1145             final char character = event.character;
1146             final char closingCharacter = getPeerCharacter(character);
1147             final StringBuffer buffer = new StringBuffer();
1148             buffer.append(character);
1149             buffer.append(closingCharacter);
1150             document.replace(offset, length, buffer.toString());
1151             LinkedPositionManager manager = new LinkedPositionManager(document);
1152             manager.addPosition(offset + 1, 0);
1153             fOffset = offset;
1154             fLength = 2;
1155             LinkedPositionUI editor = new LinkedPositionUI(sourceViewer,
1156                 manager);
1157             editor.setCancelListener(this);
1158             editor.setExitPolicy(new ExitPolicy(closingCharacter));
1159             editor.setFinalCaretOffset(offset + 2);
1160             editor.enter();
1161             IRegion newSelection = editor.getSelectedRegion();
1162             sourceViewer.setSelectedRange(newSelection.getOffset(),
1163                 newSelection.getLength());
1164             event.doit = false;
1165           }
1166         }
1167       } catch (BadLocationException e) {
1168       }
1169     }
1170
1171     /*
1172      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
1173      */
1174     public void exit(boolean accept) {
1175       if (accept)
1176         return;
1177       // remove brackets
1178       try {
1179         final ISourceViewer sourceViewer = getSourceViewer();
1180         IDocument document = sourceViewer.getDocument();
1181         document.replace(fOffset, fLength, null);
1182       } catch (BadLocationException e) {
1183       }
1184     }
1185   }
1186
1187   /** The editor's save policy */
1188   protected ISavePolicy fSavePolicy;
1189
1190   /**
1191    * Listener to annotation model changes that updates the error tick in the tab
1192    * image
1193    */
1194   private JavaEditorErrorTickUpdater fJavaEditorErrorTickUpdater;
1195
1196   /** The editor's paint manager */
1197   //  private PaintManager fPaintManager;
1198   /** The editor's bracket painter */
1199   private BracketPainter fBracketPainter;
1200
1201   /** The editor's bracket matcher */
1202   private PHPPairMatcher fBracketMatcher;
1203
1204   /** The editor's line painter */
1205   private LinePainter fLinePainter;
1206
1207   /** The editor's print margin ruler painter */
1208   private PrintMarginPainter fPrintMarginPainter;
1209
1210   /** The editor's problem painter */
1211   //  private ProblemPainter fProblemPainter;
1212   /** The editor's tab converter */
1213   private TabConverter fTabConverter;
1214
1215   /** History for structure select action */
1216   //private SelectionHistory fSelectionHistory;
1217   /** The preference property change listener for php core. */
1218   //  private IPropertyChangeListener fPropertyChangeListener = new
1219   // PropertyChangeListener();
1220   /** The remembered java element */
1221   private IJavaElement fRememberedElement;
1222
1223   /**
1224          * The remembered selection.
1225          * @since 3.0
1226          */
1227  private RememberedSelection fRememberedSelection= new RememberedSelection();
1228         
1229
1230   /** The remembered php element offset */
1231   private int fRememberedElementOffset;
1232
1233   /** The bracket inserter. */
1234   private BracketInserter fBracketInserter = new BracketInserter();
1235
1236   /** The standard action groups added to the menu */
1237   private GenerateActionGroup fGenerateActionGroup;
1238
1239   private CompositeActionGroup fContextMenuGroup;
1240
1241   //  private class PropertyChangeListener implements IPropertyChangeListener {
1242   //    /*
1243   //     * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
1244   //     */
1245   //    public void
1246   // propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
1247   // event) {
1248   //      handlePreferencePropertyChanged(event);
1249   //    }
1250   //  }
1251   /* Preference key for code formatter tab size */
1252   private final static String CODE_FORMATTER_TAB_SIZE = JavaCore.FORMATTER_TAB_SIZE;
1253
1254   /** Preference key for matching brackets */
1255   private final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
1256
1257   /** Preference key for matching brackets color */
1258   private final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
1259
1260   /** Preference key for highlighting current line */
1261   private final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
1262
1263   /** Preference key for highlight color of current line */
1264   private final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
1265
1266   /** Preference key for showing print marging ruler */
1267   private final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
1268
1269   /** Preference key for print margin ruler color */
1270   private final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
1271
1272   /** Preference key for print margin ruler column */
1273   private final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
1274
1275   /** Preference key for inserting spaces rather than tabs */
1276   private final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
1277
1278   /** Preference key for error indication */
1279   //  private final static String ERROR_INDICATION =
1280   // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
1281   /** Preference key for error color */
1282   //  private final static String ERROR_INDICATION_COLOR =
1283   // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
1284   /** Preference key for warning indication */
1285   //  private final static String WARNING_INDICATION =
1286   // PreferenceConstants.EDITOR_WARNING_INDICATION;
1287   /** Preference key for warning color */
1288   //  private final static String WARNING_INDICATION_COLOR =
1289   // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
1290   /** Preference key for task indication */
1291   private final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
1292
1293   /** Preference key for task color */
1294   private final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
1295
1296   /** Preference key for bookmark indication */
1297   private final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
1298
1299   /** Preference key for bookmark color */
1300   private final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
1301
1302   /** Preference key for search result indication */
1303   private final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
1304
1305   /** Preference key for search result color */
1306   private final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
1307
1308   /** Preference key for unknown annotation indication */
1309   private final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
1310
1311   /** Preference key for unknown annotation color */
1312   private final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
1313
1314   /** Preference key for linked position color */
1315   private final static String LINKED_POSITION_COLOR = PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
1316
1317   /** Preference key for shwoing the overview ruler */
1318   private final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
1319
1320   /** Preference key for error indication in overview ruler */
1321   private final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
1322
1323   /** Preference key for warning indication in overview ruler */
1324   private final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
1325
1326   /** Preference key for task indication in overview ruler */
1327   private final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
1328
1329   /** Preference key for bookmark indication in overview ruler */
1330   private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
1331
1332   /** Preference key for search result indication in overview ruler */
1333   private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
1334
1335   /** Preference key for unknown annotation indication in overview ruler */
1336   private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
1337
1338   /** Preference key for automatically closing strings */
1339   private final static String CLOSE_STRINGS_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_PHP;
1340
1341   /** Preference key for automatically wrapping Java strings */
1342   private final static String WRAP_STRINGS = PreferenceConstants.EDITOR_WRAP_STRINGS;
1343
1344   /** Preference key for automatically closing brackets and parenthesis */
1345   private final static String CLOSE_BRACKETS_PHP = PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP;
1346
1347   /** Preference key for automatically closing phpdocs and comments */
1348   private final static String CLOSE_JAVADOCS = PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
1349
1350   /** Preference key for automatically adding phpdoc tags */
1351   private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
1352
1353   /** Preference key for automatically formatting phpdocs */
1354   private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
1355
1356   /** Preference key for automatically closing strings */
1357   private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
1358
1359   /** Preference key for automatically closing brackets and parenthesis */
1360   private final static String CLOSE_BRACKETS_HTML = PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML;
1361
1362   /** Preference key for smart paste */
1363   private final static String SMART_PASTE = PreferenceConstants.EDITOR_SMART_PASTE;
1364
1365   //  private final static class AnnotationInfo {
1366   //    public String fColorPreference;
1367   //    public String fOverviewRulerPreference;
1368   //    public String fEditorPreference;
1369   //  };
1370   //  private final static Map ANNOTATION_MAP;
1371   //  static {
1372   //
1373   //    AnnotationInfo info;
1374   //    ANNOTATION_MAP = new HashMap();
1375   //
1376   //    info = new AnnotationInfo();
1377   //    info.fColorPreference = TASK_INDICATION_COLOR;
1378   //    info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
1379   //    info.fEditorPreference = TASK_INDICATION;
1380   //    ANNOTATION_MAP.put(AnnotationType.TASK, info);
1381   //
1382   //    info = new AnnotationInfo();
1383   //    info.fColorPreference = ERROR_INDICATION_COLOR;
1384   //    info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
1385   //    info.fEditorPreference = ERROR_INDICATION;
1386   //    ANNOTATION_MAP.put(AnnotationType.ERROR, info);
1387   //
1388   //    info = new AnnotationInfo();
1389   //    info.fColorPreference = WARNING_INDICATION_COLOR;
1390   //    info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
1391   //    info.fEditorPreference = WARNING_INDICATION;
1392   //    ANNOTATION_MAP.put(AnnotationType.WARNING, info);
1393   //
1394   //    info = new AnnotationInfo();
1395   //    info.fColorPreference = BOOKMARK_INDICATION_COLOR;
1396   //    info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
1397   //    info.fEditorPreference = BOOKMARK_INDICATION;
1398   //    ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
1399   //
1400   //    info = new AnnotationInfo();
1401   //    info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
1402   //    info.fOverviewRulerPreference =
1403   // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
1404   //    info.fEditorPreference = SEARCH_RESULT_INDICATION;
1405   //    ANNOTATION_MAP.put(AnnotationType.SEARCH, info);
1406   //
1407   //    info = new AnnotationInfo();
1408   //    info.fColorPreference = UNKNOWN_INDICATION_COLOR;
1409   //    info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
1410   //    info.fEditorPreference = UNKNOWN_INDICATION;
1411   //    ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
1412   //  };
1413   //
1414   //  private final static AnnotationType[] ANNOTATION_LAYERS =
1415   //    new AnnotationType[] {
1416   //      AnnotationType.UNKNOWN,
1417   //      AnnotationType.BOOKMARK,
1418   //      AnnotationType.TASK,
1419   //      AnnotationType.SEARCH,
1420   //      AnnotationType.WARNING,
1421   //      AnnotationType.ERROR };
1422   /**
1423    * Creates a new php unit editor.
1424    */
1425   
1426   /**
1427          * Reconciling listeners.
1428          * @since 3.0
1429          */
1430         private ListenerList fReconcilingListeners= new ListenerList();
1431
1432         /**
1433          * Mutex for the reconciler. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
1434          * for a description of the problem.
1435          * <p>
1436          * TODO remove once the underlying problem is solved.
1437          * </p>
1438          */
1439         private final Object fReconcilerLock= new Object();
1440   
1441   public PHPUnitEditor() {
1442     super();
1443     setDocumentProvider(PHPeclipsePlugin.getDefault()
1444         .getCompilationUnitDocumentProvider());
1445     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
1446     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
1447     setOutlinerContextMenuId("#PHPOutlinerContext"); //$NON-NLS-1$
1448     // don't set help contextId, we install our own help context
1449     fSavePolicy = null;
1450     fJavaEditorErrorTickUpdater = new JavaEditorErrorTickUpdater(this);
1451   }
1452
1453   /*
1454    * @see AbstractTextEditor#createActions()
1455    */
1456   protected void createActions() {
1457     super.createActions();
1458     Action action;
1459     //          Action action= new
1460     // TextOperationAction(PHPEditorMessages.getResourceBundle(),
1461     // "CorrectionAssistProposal.", this, CORRECTIONASSIST_PROPOSALS);
1462     // //$NON-NLS-1$
1463     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.CORRECTION_ASSIST_PROPOSALS);
1464     //          setAction("CorrectionAssistProposal", action); //$NON-NLS-1$
1465     //          markAsStateDependentAction("CorrectionAssistProposal", true);
1466     // //$NON-NLS-1$
1467     //// WorkbenchHelp.setHelp(action,
1468     // IJavaHelpContextIds.QUICK_FIX_ACTION);
1469     action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(),
1470         "ContentAssistProposal.", this); //$NON-NLS-1$
1471     action
1472         .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
1473     setAction("ContentAssistProposal", action); //$NON-NLS-1$
1474     markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
1475     //          WorkbenchHelp.setHelp(action,
1476     // IJavaHelpContextIds.CONTENT_ASSIST_ACTION);
1477     //          action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1478     //                          "ContentAssistContextInformation.", this,
1479     //                          ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION); //$NON-NLS-1$
1480     //          action
1481     //                          .setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_CONTEXT_INFORMATION);
1482     //          setAction("ContentAssistContextInformation", action); //$NON-NLS-1$
1483     //          markAsStateDependentAction("ContentAssistContextInformation", true);
1484     // //$NON-NLS-1$
1485     //          WorkbenchHelp.setHelp(action,
1486     // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
1487     //          action= new
1488     // TextOperationAction(PHPEditorMessages.getResourceBundle(),
1489     // "ContentAssistCompletePrefix.", this, CONTENTASSIST_COMPLETE_PREFIX);
1490     // //$NON-NLS-1$
1491     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.CONTENT_ASSIST_COMPLETE_PREFIX);
1492     //          setAction("ContentAssistCompletePrefix", action); //$NON-NLS-1$
1493     //          markAsStateDependentAction("ContentAssistCompletePrefix", true);
1494     // //$NON-NLS-1$
1495     //// WorkbenchHelp.setHelp(action,
1496     // IJavaHelpContextIds.PARAMETER_HINTS_ACTION);
1497     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1498         "Comment.", this, ITextOperationTarget.PREFIX); //$NON-NLS-1$
1499     action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
1500     setAction("Comment", action); //$NON-NLS-1$
1501     markAsStateDependentAction("Comment", true); //$NON-NLS-1$
1502     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.COMMENT_ACTION);
1503     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1504         "Uncomment.", this, ITextOperationTarget.STRIP_PREFIX); //$NON-NLS-1$
1505     action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
1506     setAction("Uncomment", action); //$NON-NLS-1$
1507     markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
1508     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.UNCOMMENT_ACTION);
1509
1510     action = new ToggleCommentAction(PHPEditorMessages.getResourceBundle(),
1511         "ToggleComment.", this); //$NON-NLS-1$
1512     action.setActionDefinitionId(PHPEditorActionDefinitionIds.TOGGLE_COMMENT);
1513     setAction("ToggleComment", action); //$NON-NLS-1$
1514     markAsStateDependentAction("ToggleComment", true); //$NON-NLS-1$
1515     //WorkbenchHelp.setHelp(action,
1516     // IJavaHelpContextIds.TOGGLE_COMMENT_ACTION);
1517     configureToggleCommentAction();
1518         
1519     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1520         "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
1521     action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
1522     setAction("Format", action); //$NON-NLS-1$
1523     markAsStateDependentAction("Format", true); //$NON-NLS-1$
1524     markAsSelectionDependentAction("Format", true); //$NON-NLS-1$               
1525     //          WorkbenchHelp.setHelp(action, IJavaHelpContextIds.FORMAT_ACTION);
1526
1527 //    action = new AddBlockCommentAction(PHPEditorMessages.getResourceBundle(),
1528 //        "AddBlockComment.", this); //$NON-NLS-1$
1529 //    action
1530 //        .setActionDefinitionId(PHPEditorActionDefinitionIds.ADD_BLOCK_COMMENT);
1531 //    setAction("AddBlockComment", action); //$NON-NLS-1$
1532 //    markAsStateDependentAction("AddBlockComment", true); //$NON-NLS-1$
1533 //    markAsSelectionDependentAction("AddBlockComment", true); //$NON-NLS-1$            
1534 //    //                WorkbenchHelp.setHelp(action,
1535 //    // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
1536 //    action = new RemoveBlockCommentAction(
1537 //        PHPEditorMessages.getResourceBundle(), "RemoveBlockComment.", this); //$NON-NLS-1$
1538 //    action
1539 //        .setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_BLOCK_COMMENT);
1540 //    setAction("RemoveBlockComment", action); //$NON-NLS-1$
1541 //    markAsStateDependentAction("RemoveBlockComment", true); //$NON-NLS-1$
1542 //    markAsSelectionDependentAction("RemoveBlockComment", true); //$NON-NLS-1$         
1543     //          WorkbenchHelp.setHelp(action,
1544     // IJavaHelpContextIds.ADD_BLOCK_COMMENT_ACTION);
1545     //          action= new IndentAction(PHPEditorMessages.getResourceBundle(),
1546     // "Indent.", this, false); //$NON-NLS-1$
1547     //          action.setActionDefinitionId(PHPEditorActionDefinitionIds.INDENT);
1548     //          setAction("Indent", action); //$NON-NLS-1$
1549     //          markAsStateDependentAction("Indent", true); //$NON-NLS-1$
1550     //          markAsSelectionDependentAction("Indent", true); //$NON-NLS-1$
1551     //// WorkbenchHelp.setHelp(action, IJavaHelpContextIds.INDENT_ACTION);
1552     //          
1553     //          action= new IndentAction(PHPEditorMessages.getResourceBundle(),
1554     // "Indent.", this, true); //$NON-NLS-1$
1555     //          setAction("IndentOnTab", action); //$NON-NLS-1$
1556     //          markAsStateDependentAction("IndentOnTab", true); //$NON-NLS-1$
1557     //          markAsSelectionDependentAction("IndentOnTab", true); //$NON-NLS-1$
1558     //          
1559     if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_TAB)) {
1560       // don't replace Shift Right - have to make sure their enablement is
1561       // mutually exclusive
1562       //                        removeActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT);
1563       setActionActivationCode("IndentOnTab", '\t', -1, SWT.NONE); //$NON-NLS-1$
1564     }
1565     fGenerateActionGroup = new GenerateActionGroup(this,
1566         ITextEditorActionConstants.GROUP_EDIT);
1567     fActionGroups = new CompositeActionGroup(
1568         new ActionGroup[] { fGenerateActionGroup });
1569     //    We have to keep the context menu group separate to have better
1570     // control
1571     // over positioning
1572     fContextMenuGroup = new CompositeActionGroup(
1573         new ActionGroup[] { fGenerateActionGroup });
1574     //      rg,
1575     //      new LocalHistoryActionGroup(this,
1576     // ITextEditorActionConstants.GROUP_EDIT)});
1577
1578   }
1579
1580   /*
1581    * @see JavaEditor#getElementAt(int)
1582    */
1583   protected IJavaElement getElementAt(int offset) {
1584     return getElementAt(offset, true);
1585   }
1586
1587   /**
1588    * Returns the most narrow element including the given offset. If
1589    * <code>reconcile</code> is <code>true</code> the editor's input element
1590    * is reconciled in advance. If it is <code>false</code> this method only
1591    * returns a result if the editor's input element does not need to be
1592    * reconciled.
1593    * 
1594    * @param offset
1595    *          the offset included by the retrieved element
1596    * @param reconcile
1597    *          <code>true</code> if working copy should be reconciled
1598    */
1599   protected IJavaElement getElementAt(int offset, boolean reconcile) {
1600     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
1601         .getWorkingCopyManager();
1602     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
1603     if (unit != null) {
1604       try {
1605         if (reconcile) {
1606           synchronized (unit) {
1607             unit.reconcile();
1608           }
1609           return unit.getElementAt(offset);
1610         } else if (unit.isConsistent())
1611           return unit.getElementAt(offset);
1612       } catch (JavaModelException x) {
1613         PHPeclipsePlugin.log(x.getStatus());
1614         // nothing found, be tolerant and go on
1615       }
1616     }
1617     return null;
1618   }
1619
1620   /*
1621    * @see JavaEditor#getCorrespondingElement(IJavaElement)
1622    */
1623   protected IJavaElement getCorrespondingElement(IJavaElement element) {
1624     try {
1625       return EditorUtility.getWorkingCopy(element, true);
1626     } catch (JavaModelException x) {
1627       PHPeclipsePlugin.log(x.getStatus());
1628       // nothing found, be tolerant and go on
1629     }
1630     return null;
1631   }
1632
1633   public void createPartControl(Composite parent) {
1634     super.createPartControl(parent);
1635     //    fPaintManager = new PaintManager(getSourceViewer());
1636     LinePainter linePainter;
1637     linePainter = new LinePainter(getSourceViewer());
1638     linePainter
1639         .setHighlightColor(new Color(Display.getCurrent(), 225, 235, 224));
1640     //    fPaintManager.addPainter(linePainter);
1641     if (isBracketHighlightingEnabled())
1642       startBracketHighlighting();
1643     if (isLineHighlightingEnabled())
1644       startLineHighlighting();
1645     if (isPrintMarginVisible())
1646       showPrintMargin();
1647     //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1648     //    while (e.hasNext()) {
1649     //      AnnotationType type = (AnnotationType) e.next();
1650     //      if (isAnnotationIndicationEnabled(type))
1651     //        startAnnotationIndication(type);
1652     //    }
1653     if (isTabConversionEnabled())
1654       startTabConversion();
1655     //    if (isOverviewRulerVisible())
1656     //      showOverviewRuler();
1657     //
1658     //    Preferences preferences =
1659     // PHPeclipsePlugin.getDefault().getPluginPreferences();
1660     //    preferences.addPropertyChangeListener(fPropertyChangeListener);
1661     IPreferenceStore preferenceStore = getPreferenceStore();
1662     boolean closeBracketsPHP = preferenceStore.getBoolean(CLOSE_BRACKETS_PHP);
1663     boolean closeStringsPHP = preferenceStore.getBoolean(CLOSE_STRINGS_PHP);
1664     boolean closeBracketsHTML = preferenceStore.getBoolean(CLOSE_BRACKETS_HTML);
1665     boolean closeStringsHTML = preferenceStore.getBoolean(CLOSE_STRINGS_HTML);
1666     fBracketInserter.setCloseBracketsPHPEnabled(closeBracketsPHP);
1667     fBracketInserter.setCloseStringsPHPEnabled(closeStringsPHP);
1668     fBracketInserter.setCloseBracketsHTMLEnabled(closeBracketsHTML);
1669     fBracketInserter.setCloseStringsHTMLEnabled(closeStringsHTML);
1670     ISourceViewer sourceViewer = getSourceViewer();
1671     if (sourceViewer instanceof ITextViewerExtension)
1672       ((ITextViewerExtension) sourceViewer)
1673           .prependVerifyKeyListener(fBracketInserter);
1674   }
1675
1676   private static char getPeerCharacter(char character) {
1677     switch (character) {
1678     case '(':
1679       return ')';
1680     case ')':
1681       return '(';
1682     case '[':
1683       return ']';
1684     case ']':
1685       return '[';
1686     case '"':
1687       return character;
1688     default:
1689       throw new IllegalArgumentException();
1690     }
1691   }
1692
1693   private void startBracketHighlighting() {
1694     if (fBracketPainter == null) {
1695       ISourceViewer sourceViewer = getSourceViewer();
1696       fBracketPainter = new BracketPainter(sourceViewer);
1697       fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1698       //      fPaintManager.addPainter(fBracketPainter);
1699     }
1700   }
1701
1702   private void stopBracketHighlighting() {
1703     if (fBracketPainter != null) {
1704       //      fPaintManager.removePainter(fBracketPainter);
1705       fBracketPainter.deactivate(true);
1706       fBracketPainter.dispose();
1707       fBracketPainter = null;
1708     }
1709   }
1710
1711   private boolean isBracketHighlightingEnabled() {
1712     IPreferenceStore store = getPreferenceStore();
1713     return store.getBoolean(MATCHING_BRACKETS);
1714   }
1715
1716   private void startLineHighlighting() {
1717     if (fLinePainter == null) {
1718       ISourceViewer sourceViewer = getSourceViewer();
1719       fLinePainter = new LinePainter(sourceViewer);
1720       fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
1721       //      fPaintManager.addPainter(fLinePainter);
1722     }
1723   }
1724
1725   private void stopLineHighlighting() {
1726     if (fLinePainter != null) {
1727       //      fPaintManager.removePainter(fLinePainter);
1728       fLinePainter.deactivate(true);
1729       fLinePainter.dispose();
1730       fLinePainter = null;
1731     }
1732   }
1733
1734   private boolean isLineHighlightingEnabled() {
1735     IPreferenceStore store = getPreferenceStore();
1736     return store.getBoolean(CURRENT_LINE);
1737   }
1738
1739   private void showPrintMargin() {
1740     if (fPrintMarginPainter == null) {
1741       fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
1742       fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1743       fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(
1744           PRINT_MARGIN_COLUMN));
1745       //      fPaintManager.addPainter(fPrintMarginPainter);
1746     }
1747   }
1748
1749   private void hidePrintMargin() {
1750     if (fPrintMarginPainter != null) {
1751       //      fPaintManager.removePainter(fPrintMarginPainter);
1752       fPrintMarginPainter.deactivate(true);
1753       fPrintMarginPainter.dispose();
1754       fPrintMarginPainter = null;
1755     }
1756   }
1757
1758   private boolean isPrintMarginVisible() {
1759     IPreferenceStore store = getPreferenceStore();
1760     return store.getBoolean(PRINT_MARGIN);
1761   }
1762
1763   //  private void startAnnotationIndication(AnnotationType annotationType) {
1764   //    if (fProblemPainter == null) {
1765   //      fProblemPainter = new ProblemPainter(this, getSourceViewer());
1766   //// fPaintManager.addPainter(fProblemPainter);
1767   //    }
1768   //    fProblemPainter.setColor(annotationType, getColor(annotationType));
1769   //    fProblemPainter.paintAnnotations(annotationType, true);
1770   //    fProblemPainter.paint(IPainter.CONFIGURATION);
1771   //  }
1772   //
1773   //  private void shutdownAnnotationIndication() {
1774   //    if (fProblemPainter != null) {
1775   //
1776   //      if (!fProblemPainter.isPaintingAnnotations()) {
1777   //// fPaintManager.removePainter(fProblemPainter);
1778   //        fProblemPainter.deactivate(true);
1779   //        fProblemPainter.dispose();
1780   //        fProblemPainter = null;
1781   //      } else {
1782   //        fProblemPainter.paint(IPainter.CONFIGURATION);
1783   //      }
1784   //    }
1785   //  }
1786   //
1787   //  private void stopAnnotationIndication(AnnotationType annotationType) {
1788   //    if (fProblemPainter != null) {
1789   //      fProblemPainter.paintAnnotations(annotationType, false);
1790   //      shutdownAnnotationIndication();
1791   //    }
1792   //  }
1793   //
1794   //  private boolean isAnnotationIndicationEnabled(AnnotationType
1795   // annotationType) {
1796   //    IPreferenceStore store = getPreferenceStore();
1797   //    AnnotationInfo info = (AnnotationInfo)
1798   // ANNOTATION_MAP.get(annotationType);
1799   //    if (info != null)
1800   //      return store.getBoolean(info.fEditorPreference);
1801   //    return false;
1802   //  }
1803   //
1804   //  private boolean
1805   // isAnnotationIndicationInOverviewRulerEnabled(AnnotationType
1806   // annotationType) {
1807   //    IPreferenceStore store = getPreferenceStore();
1808   //    AnnotationInfo info = (AnnotationInfo)
1809   // ANNOTATION_MAP.get(annotationType);
1810   //    if (info != null)
1811   //      return store.getBoolean(info.fOverviewRulerPreference);
1812   //    return false;
1813   //  }
1814   //
1815   //  private void showAnnotationIndicationInOverviewRuler(AnnotationType
1816   // annotationType, boolean show) {
1817   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1818   //    OverviewRuler ruler = asv.getOverviewRuler();
1819   //    if (ruler != null) {
1820   //      ruler.setColor(annotationType, getColor(annotationType));
1821   //      ruler.showAnnotation(annotationType, show);
1822   //      ruler.update();
1823   //    }
1824   //  }
1825   //
1826   //  private void setColorInOverviewRuler(AnnotationType annotationType, Color
1827   // color) {
1828   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1829   //    OverviewRuler ruler = asv.getOverviewRuler();
1830   //    if (ruler != null) {
1831   //      ruler.setColor(annotationType, color);
1832   //      ruler.update();
1833   //    }
1834   //  }
1835
1836   private int getTabSize() {
1837     Preferences preferences = PHPeclipsePlugin.getDefault()
1838         .getPluginPreferences();
1839     return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1840   }
1841
1842   private boolean isTabConversionEnabled() {
1843     IPreferenceStore store = getPreferenceStore();
1844     return store.getBoolean(SPACES_FOR_TABS);
1845   }
1846
1847   //  private void showOverviewRuler() {
1848   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1849   //    asv.showOverviewRuler();
1850   //
1851   //    OverviewRuler overviewRuler = asv.getOverviewRuler();
1852   //    if (overviewRuler != null) {
1853   //      for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1854   //        AnnotationType type = ANNOTATION_LAYERS[i];
1855   //        overviewRuler.setLayer(type, i);
1856   //        if (isAnnotationIndicationInOverviewRulerEnabled(type))
1857   //          showAnnotationIndicationInOverviewRuler(type, true);
1858   //      }
1859   //    }
1860   //  }
1861   //
1862   //  private void hideOverviewRuler() {
1863   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1864   //    asv.hideOverviewRuler();
1865   //  }
1866   //
1867   //  private boolean isOverviewRulerVisible() {
1868   //    IPreferenceStore store = getPreferenceStore();
1869   //    return store.getBoolean(OVERVIEW_RULER);
1870   //  }
1871   private Color getColor(String key) {
1872     RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1873     return getColor(rgb);
1874   }
1875
1876   private Color getColor(RGB rgb) {
1877     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1878     return textTools.getColorManager().getColor(rgb);
1879   }
1880
1881   //  private Color getColor(AnnotationType annotationType) {
1882   //    AnnotationInfo info = (AnnotationInfo)
1883   // ANNOTATION_MAP.get(annotationType);
1884   //    if (info != null)
1885   //      return getColor(info.fColorPreference);
1886   //    return null;
1887   //  }
1888   public void dispose() {
1889     ISourceViewer sourceViewer = getSourceViewer();
1890     if (sourceViewer instanceof ITextViewerExtension)
1891       ((ITextViewerExtension) sourceViewer)
1892           .removeVerifyKeyListener(fBracketInserter);
1893     //    if (fPropertyChangeListener != null) {
1894     //      Preferences preferences =
1895     // PHPeclipsePlugin.getDefault().getPluginPreferences();
1896     //      preferences.removePropertyChangeListener(fPropertyChangeListener);
1897     //      fPropertyChangeListener = null;
1898     //    }
1899     if (fJavaEditorErrorTickUpdater != null) {
1900       fJavaEditorErrorTickUpdater.dispose();
1901       fJavaEditorErrorTickUpdater = null;
1902     }
1903     //    if (fSelectionHistory != null)
1904     //      fSelectionHistory.dispose();
1905     //    if (fPaintManager != null) {
1906     //      fPaintManager.dispose();
1907     //      fPaintManager = null;
1908     //    }
1909     if (fActionGroups != null) {
1910       fActionGroups.dispose();
1911       fActionGroups = null;
1912     }
1913     super.dispose();
1914   }
1915
1916   //  protected AnnotationType getAnnotationType(String preferenceKey) {
1917   //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1918   //    while (e.hasNext()) {
1919   //      AnnotationType type = (AnnotationType) e.next();
1920   //      AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1921   //      if (info != null) {
1922   //        if (preferenceKey.equals(info.fColorPreference)
1923   //          || preferenceKey.equals(info.fEditorPreference)
1924   //          || preferenceKey.equals(info.fOverviewRulerPreference))
1925   //          return type;
1926   //      }
1927   //    }
1928   //    return null;
1929   //  }
1930   /*
1931    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1932    */
1933   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1934     try {
1935       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1936       if (asv != null) {
1937         String p = event.getProperty();
1938         if (CLOSE_BRACKETS_PHP.equals(p)) {
1939           fBracketInserter.setCloseBracketsPHPEnabled(getPreferenceStore()
1940               .getBoolean(p));
1941           return;
1942         }
1943         if (CLOSE_STRINGS_PHP.equals(p)) {
1944           fBracketInserter.setCloseStringsPHPEnabled(getPreferenceStore()
1945               .getBoolean(p));
1946           return;
1947         }
1948         if (CLOSE_BRACKETS_HTML.equals(p)) {
1949           fBracketInserter.setCloseBracketsHTMLEnabled(getPreferenceStore()
1950               .getBoolean(p));
1951           return;
1952         }
1953         if (CLOSE_STRINGS_HTML.equals(p)) {
1954           fBracketInserter.setCloseStringsHTMLEnabled(getPreferenceStore()
1955               .getBoolean(p));
1956           return;
1957         }
1958         if (SPACES_FOR_TABS.equals(p)) {
1959           if (isTabConversionEnabled())
1960             startTabConversion();
1961           else
1962             stopTabConversion();
1963           return;
1964         }
1965         if (MATCHING_BRACKETS.equals(p)) {
1966           if (isBracketHighlightingEnabled())
1967             startBracketHighlighting();
1968           else
1969             stopBracketHighlighting();
1970           return;
1971         }
1972         if (MATCHING_BRACKETS_COLOR.equals(p)) {
1973           if (fBracketPainter != null)
1974             fBracketPainter
1975                 .setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1976           return;
1977         }
1978         if (CURRENT_LINE.equals(p)) {
1979           if (isLineHighlightingEnabled())
1980             startLineHighlighting();
1981           else
1982             stopLineHighlighting();
1983           return;
1984         }
1985         if (CURRENT_LINE_COLOR.equals(p)) {
1986           if (fLinePainter != null) {
1987             stopLineHighlighting();
1988             startLineHighlighting();
1989           }
1990           return;
1991         }
1992         if (PRINT_MARGIN.equals(p)) {
1993           if (isPrintMarginVisible())
1994             showPrintMargin();
1995           else
1996             hidePrintMargin();
1997           return;
1998         }
1999         if (PRINT_MARGIN_COLOR.equals(p)) {
2000           if (fPrintMarginPainter != null)
2001             fPrintMarginPainter
2002                 .setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
2003           return;
2004         }
2005         if (PRINT_MARGIN_COLUMN.equals(p)) {
2006           if (fPrintMarginPainter != null)
2007             fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore()
2008                 .getInt(PRINT_MARGIN_COLUMN));
2009           return;
2010         }
2011         //        if (OVERVIEW_RULER.equals(p)) {
2012         //          if (isOverviewRulerVisible())
2013         //            showOverviewRuler();
2014         //          else
2015         //            hideOverviewRuler();
2016         //          return;
2017         //        }
2018         //        AnnotationType type = getAnnotationType(p);
2019         //        if (type != null) {
2020         //
2021         //          AnnotationInfo info = (AnnotationInfo)
2022         // ANNOTATION_MAP.get(type);
2023         //          if (info.fColorPreference.equals(p)) {
2024         //            Color color = getColor(type);
2025         //            if (fProblemPainter != null) {
2026         //              fProblemPainter.setColor(type, color);
2027         //              fProblemPainter.paint(IPainter.CONFIGURATION);
2028         //            }
2029         //            setColorInOverviewRuler(type, color);
2030         //            return;
2031         //          }
2032         //
2033         //          if (info.fEditorPreference.equals(p)) {
2034         //            if (isAnnotationIndicationEnabled(type))
2035         //              startAnnotationIndication(type);
2036         //            else
2037         //              stopAnnotationIndication(type);
2038         //            return;
2039         //          }
2040         //
2041         //          if (info.fOverviewRulerPreference.equals(p)) {
2042         //            if (isAnnotationIndicationInOverviewRulerEnabled(type))
2043         //              showAnnotationIndicationInOverviewRuler(type, true);
2044         //            else
2045         //              showAnnotationIndicationInOverviewRuler(type, false);
2046         //            return;
2047         //          }
2048         //        }
2049         IContentAssistant c = asv.getContentAssistant();
2050         if (c instanceof ContentAssistant)
2051           ContentAssistPreference.changeConfiguration((ContentAssistant) c,
2052               getPreferenceStore(), event);
2053       }
2054     } finally {
2055       super.handlePreferenceStoreChanged(event);
2056     }
2057   }
2058
2059   /*
2060    * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
2061    */
2062   protected void handlePreferencePropertyChanged(
2063       org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
2064     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2065     if (asv != null) {
2066       String p = event.getProperty();
2067       if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
2068         asv.updateIndentationPrefixes();
2069         if (fTabConverter != null)
2070           fTabConverter.setNumberOfSpacesPerTab(getTabSize());
2071       }
2072     }
2073     super.handlePreferencePropertyChanged(event);
2074   }
2075
2076   /**
2077    * Handles a property change event describing a change of the php core's
2078    * preferences and updates the preference related editor properties.
2079    * 
2080    * @param event
2081    *          the property change event
2082    */
2083   //  protected void
2084   // handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent
2085   // event) {
2086   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2087   //    if (asv != null) {
2088   //      String p = event.getProperty();
2089   //      if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
2090   //        asv.updateIndentationPrefixes();
2091   //        if (fTabConverter != null)
2092   //          fTabConverter.setNumberOfSpacesPerTab(getTabSize());
2093   //      }
2094   //    }
2095   //  }
2096   /*
2097    * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#createJavaSourceViewer(org.eclipse.swt.widgets.Composite,
2098    *      org.eclipse.jface.text.source.IVerticalRuler,
2099    *      org.eclipse.jface.text.source.IOverviewRuler, boolean, int)
2100    */
2101   protected ISourceViewer createJavaSourceViewer(Composite parent,
2102       IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
2103       boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
2104     return new AdaptedSourceViewer(parent, verticalRuler, overviewRuler,
2105         isOverviewRulerVisible, styles, store);
2106   }
2107
2108   //  protected ISourceViewer createJavaSourceViewer(Composite parent,
2109   // IVerticalRuler ruler, int styles) {
2110   //    return new AdaptedSourceViewer(parent, ruler, styles);
2111   //  }
2112   private boolean isValidSelection(int offset, int length) {
2113     IDocumentProvider provider = getDocumentProvider();
2114     if (provider != null) {
2115       IDocument document = provider.getDocument(getEditorInput());
2116       if (document != null) {
2117         int end = offset + length;
2118         int documentLength = document.getLength();
2119         return 0 <= offset && offset <= documentLength && 0 <= end
2120             && end <= documentLength;
2121       }
2122     }
2123     return false;
2124   }
2125
2126   /*
2127          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#getInputElement()
2128          */
2129         protected IJavaElement getInputJavaElement() {
2130                 return PHPeclipsePlugin.getDefault().getWorkingCopyManager().getWorkingCopy(getEditorInput());
2131         }
2132   /*
2133    * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
2134    */
2135   public void editorContextMenuAboutToShow(IMenuManager menu) {
2136     super.editorContextMenuAboutToShow(menu);
2137     ActionContext context = new ActionContext(getSelectionProvider()
2138         .getSelection());
2139     fContextMenuGroup.setContext(context);
2140     fContextMenuGroup.fillContextMenu(menu);
2141     fContextMenuGroup.setContext(null);
2142   }
2143
2144   /*
2145    * @see JavaEditor#setOutlinePageInput(JavaOutlinePage, IEditorInput)
2146    */
2147   protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input) {
2148     if (page != null) {
2149       IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
2150           .getWorkingCopyManager();
2151       page.setInput(manager.getWorkingCopy(input));
2152     }
2153   }
2154   
2155
2156   /*
2157    * @see AbstractTextEditor#performSaveOperation(WorkspaceModifyOperation,
2158    *      IProgressMonitor)
2159    */
2160   //  protected void performSaveOperation(WorkspaceModifyOperation operation,
2161   // IProgressMonitor progressMonitor) {
2162   //    IDocumentProvider p = getDocumentProvider();
2163   //    if (p instanceof PHPDocumentProvider) {
2164   //      PHPDocumentProvider cp = (PHPDocumentProvider) p;
2165   //      cp.setSavePolicy(fSavePolicy);
2166   //    }
2167   //
2168   //    try {
2169   //      super.performSaveOperation(operation, progressMonitor);
2170   //    } finally {
2171   //      if (p instanceof PHPDocumentProvider) {
2172   //        PHPDocumentProvider cp = (PHPDocumentProvider) p;
2173   //        cp.setSavePolicy(null);
2174   //      }
2175   //    }
2176   //  }
2177   /*
2178    * @see AbstractTextEditor#doSave(IProgressMonitor)
2179    */
2180   public void doSave(IProgressMonitor progressMonitor) {
2181
2182     IDocumentProvider p = getDocumentProvider();
2183     if (p == null) {
2184       // editor has been closed
2185       return;
2186     }
2187
2188     if (p.isDeleted(getEditorInput())) {
2189
2190       if (isSaveAsAllowed()) {
2191
2192         /*
2193          * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the
2194          * editors. Changed Behavior to make sure that if called inside a
2195          * regular save (because of deletion of input element) there is a way to
2196          * report back to the caller.
2197          */
2198         performSaveAs(progressMonitor);
2199
2200       } else {
2201
2202         /*
2203          * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there
2204          * Missing resources.
2205          */
2206         Shell shell = getSite().getShell();
2207         MessageDialog
2208             .openError(
2209                 shell,
2210                 PHPEditorMessages
2211                     .getString("PHPUnitEditor.error.saving.title1"), PHPEditorMessages.getString("PHPUnitEditor.error.saving.message1")); //$NON-NLS-1$ //$NON-NLS-2$
2212       }
2213
2214     } else {
2215
2216       setStatusLineErrorMessage(null);
2217
2218       updateState(getEditorInput());
2219       validateState(getEditorInput());
2220
2221       IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
2222           .getWorkingCopyManager();
2223       ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
2224
2225       if (unit != null) {
2226         synchronized (unit) {
2227           performSave(false, progressMonitor);
2228         }
2229       } else
2230         performSave(false, progressMonitor);
2231     }
2232     ShowExternalPreviewAction a = ShowExternalPreviewAction.getInstance();
2233     if (a != null) {
2234       a.refresh();
2235     }
2236   }
2237
2238   public boolean isSaveAsAllowed() {
2239     return true;
2240   }
2241
2242   /**
2243    * The compilation unit editor implementation of this
2244    * <code>AbstractTextEditor</code> method asks the user for the workspace
2245    * path of a file resource and saves the document there. See
2246    * http://dev.eclipse.org/bugs/show_bug.cgi?id=6295
2247    * 
2248    * @param progressMonitor
2249    *          the progress monitor
2250    */
2251   protected void performSaveAs(IProgressMonitor progressMonitor) {
2252
2253     Shell shell = getSite().getShell();
2254     IEditorInput input = getEditorInput();
2255
2256     SaveAsDialog dialog = new SaveAsDialog(shell);
2257
2258     IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input)
2259         .getFile()
2260         : null;
2261     if (original != null)
2262       dialog.setOriginalFile(original);
2263
2264     dialog.create();
2265
2266     IDocumentProvider provider = getDocumentProvider();
2267     if (provider == null) {
2268       // editor has been programmatically closed while the dialog was open
2269       return;
2270     }
2271
2272     if (provider.isDeleted(input) && original != null) {
2273       String message = PHPEditorMessages
2274           .getFormattedString(
2275               "CompilationUnitEditor.warning.save.delete", new Object[] { original.getName() }); //$NON-NLS-1$
2276       dialog.setErrorMessage(null);
2277       dialog.setMessage(message, IMessageProvider.WARNING);
2278     }
2279
2280     if (dialog.open() == Window.CANCEL) {
2281       if (progressMonitor != null)
2282         progressMonitor.setCanceled(true);
2283       return;
2284     }
2285
2286     IPath filePath = dialog.getResult();
2287     if (filePath == null) {
2288       if (progressMonitor != null)
2289         progressMonitor.setCanceled(true);
2290       return;
2291     }
2292
2293     IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
2294     IFile file = workspaceRoot.getFile(filePath);
2295     final IEditorInput newInput = new FileEditorInput(file);
2296
2297     boolean success = false;
2298     try {
2299
2300       provider.aboutToChange(newInput);
2301       getDocumentProvider().saveDocument(progressMonitor, newInput,
2302           getDocumentProvider().getDocument(getEditorInput()), true);
2303       success = true;
2304
2305     } catch (CoreException x) {
2306       IStatus status = x.getStatus();
2307       if (status == null || status.getSeverity() != IStatus.CANCEL)
2308         ErrorDialog
2309             .openError(
2310                 shell,
2311                 PHPEditorMessages
2312                     .getString("CompilationUnitEditor.error.saving.title2"), PHPEditorMessages.getString("CompilationUnitEditor.error.saving.message2"), x.getStatus()); //$NON-NLS-1$ //$NON-NLS-2$
2313     } finally {
2314       provider.changed(newInput);
2315       if (success)
2316         setInput(newInput);
2317     }
2318
2319     if (progressMonitor != null)
2320       progressMonitor.setCanceled(!success);
2321   }
2322
2323   /*
2324    * @see AbstractTextEditor#doSetInput(IEditorInput)
2325    */
2326   protected void doSetInput(IEditorInput input) throws CoreException {
2327     super.doSetInput(input);
2328     configureTabConverter();
2329     configureToggleCommentAction();
2330   }
2331
2332   //    /*
2333   //     * @see
2334   // org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#installOverrideIndicator(boolean)
2335   //     * @since 3.0
2336   //     */
2337   //    protected void installOverrideIndicator(boolean waitForReconcilation) {
2338   //            IAnnotationModel model=
2339   // getDocumentProvider().getAnnotationModel(getEditorInput());
2340   //            if (!waitForReconcilation)
2341   //                    super.installOverrideIndicator(false);
2342   //            else {
2343   //                    uninstallOverrideIndicator();
2344   //                    IJavaElement inputElement= getInputJavaElement();
2345   //                    if (model == null || inputElement == null)
2346   //                            return;
2347   //                    
2348   //                    fOverrideIndicatorManager= new OverrideIndicatorManager(model,
2349   // inputElement, null);
2350   //                    addReconcileListener(fOverrideIndicatorManager);
2351   //            }
2352   //    }
2353   //    
2354   //    /*
2355   //     * @see
2356   // org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#uninstallOverrideIndicator()
2357   //     * @since 3.0
2358   //     */
2359   //    protected void uninstallOverrideIndicator() {
2360   //            if (fOverrideIndicatorManager != null)
2361   //                    removeReconcileListener(fOverrideIndicatorManager);
2362   //            super.uninstallOverrideIndicator();
2363   //    }
2364
2365   /**
2366    * Configures the toggle comment action
2367    * 
2368    * @since 3.0
2369    */
2370   private void configureToggleCommentAction() {
2371     IAction action = getAction("ToggleComment"); //$NON-NLS-1$
2372     if (action instanceof ToggleCommentAction) {
2373       ISourceViewer sourceViewer = getSourceViewer();
2374       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
2375       ((ToggleCommentAction) action).configure(sourceViewer, configuration);
2376     }
2377   }
2378
2379   private void configureTabConverter() {
2380     if (fTabConverter != null) {
2381       IDocumentProvider provider = getDocumentProvider();
2382       if (provider instanceof PHPDocumentProvider) {
2383         PHPDocumentProvider cup = (PHPDocumentProvider) provider;
2384         fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
2385       }
2386     }
2387   }
2388
2389   private void startTabConversion() {
2390     if (fTabConverter == null) {
2391       fTabConverter = new TabConverter();
2392       configureTabConverter();
2393       fTabConverter.setNumberOfSpacesPerTab(getTabSize());
2394       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2395       asv.addTextConverter(fTabConverter);
2396       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
2397       asv.updateIndentationPrefixes();
2398     }
2399   }
2400
2401   private void stopTabConversion() {
2402     if (fTabConverter != null) {
2403       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
2404       asv.removeTextConverter(fTabConverter);
2405       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
2406       asv.updateIndentationPrefixes();
2407       fTabConverter = null;
2408     }
2409   }
2410
2411   /*
2412    * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean,
2413    *      org.eclipse.core.runtime.IProgressMonitor)
2414    */
2415   protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
2416     IDocumentProvider p = getDocumentProvider();
2417     if (p instanceof PHPDocumentProvider) {
2418       PHPDocumentProvider cp = (PHPDocumentProvider) p;
2419       cp.setSavePolicy(fSavePolicy);
2420     }
2421     try {
2422       super.performSave(overwrite, progressMonitor);
2423     } finally {
2424       if (p instanceof PHPDocumentProvider) {
2425         PHPDocumentProvider cp = (PHPDocumentProvider) p;
2426         cp.setSavePolicy(null);
2427       }
2428     }
2429   }
2430
2431   /*
2432    * @see AbstractTextEditor#doSaveAs
2433    */
2434   public void doSaveAs() {
2435     if (askIfNonWorkbenchEncodingIsOk()) {
2436       super.doSaveAs();
2437     }
2438   }
2439
2440   /**
2441    * Asks the user if it is ok to store in non-workbench encoding.
2442    * 
2443    * @return <true>if the user wants to continue
2444    */
2445   private boolean askIfNonWorkbenchEncodingIsOk() {
2446     IDocumentProvider provider = getDocumentProvider();
2447     if (provider instanceof IStorageDocumentProvider) {
2448       IEditorInput input = getEditorInput();
2449       IStorageDocumentProvider storageProvider = (IStorageDocumentProvider) provider;
2450       String encoding = storageProvider.getEncoding(input);
2451       String defaultEncoding = storageProvider.getDefaultEncoding();
2452       if (encoding != null && !encoding.equals(defaultEncoding)) {
2453         Shell shell = getSite().getShell();
2454         String title = PHPEditorMessages
2455             .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.title"); //$NON-NLS-1$
2456         String msg;
2457         if (input != null)
2458           msg = MessageFormat
2459               .format(
2460                   PHPEditorMessages
2461                       .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message1"),
2462                   new String[] { input.getName(), encoding }); //$NON-NLS-1$
2463         else
2464           msg = MessageFormat
2465               .format(
2466                   PHPEditorMessages
2467                       .getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message2"),
2468                   new String[] { encoding }); //$NON-NLS-1$
2469         return MessageDialog.openQuestion(shell, title, msg);
2470       }
2471     }
2472     return true;
2473   }
2474
2475         /*
2476          * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
2477          * @since 3.0
2478          */
2479         public void aboutToBeReconciled() {
2480
2481                 // Notify AST provider
2482 //              PHPeclipsePlugin.getDefault().getASTProvider().aboutToBeReconciled(getInputJavaElement());
2483                 
2484                 // Notify listeners
2485                 Object[] listeners = fReconcilingListeners.getListeners();
2486                 for (int i = 0, length= listeners.length; i < length; ++i)
2487                         ((IJavaReconcilingListener)listeners[i]).aboutToBeReconciled();
2488         }
2489         
2490   /*
2491          * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit, boolean, IProgressMonitor)
2492          * @since 3.0
2493          */
2494         public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor progressMonitor) {
2495
2496                 // Always notify AST provider
2497 //              PHPeclipsePlugin.getDefault().getASTProvider().reconciled(ast, getInputJavaElement());
2498                 
2499                 // Notify listeners
2500 //              Object[] listeners = fReconcilingListeners.getListeners();
2501 //              for (int i = 0, length= listeners.length; i < length; ++i)
2502 //                      ((IJavaReconcilingListener)listeners[i]).reconciled(ast, forced, progressMonitor);
2503
2504                 // Update Java Outline page selection
2505                 if (!forced && !progressMonitor.isCanceled()) {
2506                         Shell shell= getSite().getShell();
2507                         if (shell != null && !shell.isDisposed()) {
2508                                 shell.getDisplay().asyncExec(new Runnable() {
2509                                         public void run() {
2510                                                 selectionChanged();
2511                                         }
2512                                 });
2513                         }
2514                 }
2515         }
2516
2517   private boolean synchronizeOutlineOnCursorMove() {
2518     return PreferenceConstants.getPreferenceStore().getBoolean(
2519         PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE);
2520   }
2521
2522   /**
2523    * Returns the updated java element for the old java element.
2524    */
2525   private IJavaElement findElement(IJavaElement element) {
2526     if (element == null)
2527       return null;
2528     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
2529         .getWorkingCopyManager();
2530     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
2531     if (unit != null) {
2532       try {
2533         synchronized (unit) {
2534           unit.reconcile();
2535         }
2536         IJavaElement[] findings = unit.findElements(element);
2537         if (findings != null && findings.length > 0)
2538           return findings[0];
2539       } catch (JavaModelException x) {
2540         PHPeclipsePlugin.log(x.getStatus());
2541         // nothing found, be tolerant and go on
2542       }
2543     }
2544     return null;
2545   }
2546
2547   /**
2548    * Returns the offset of the given Java element.
2549    */
2550   private int getOffset(IJavaElement element) {
2551     if (element instanceof ISourceReference) {
2552       ISourceReference sr = (ISourceReference) element;
2553       try {
2554         ISourceRange srcRange = sr.getSourceRange();
2555         if (srcRange != null)
2556           return srcRange.getOffset();
2557       } catch (JavaModelException e) {
2558       }
2559     }
2560     return -1;
2561   }
2562
2563   
2564
2565   /*
2566    * @see AbstractTextEditor#restoreSelection()
2567    */
2568 //  protected void restoreSelection() {
2569 //    try {
2570 //      if (getSourceViewer() == null || fRememberedSelection == null)
2571 //        return;
2572 //      IJavaElement newElement = findElement(fRememberedElement);
2573 //      int newOffset = getOffset(newElement);
2574 //      int delta = (newOffset > -1 && fRememberedElementOffset > -1) ? newOffset
2575 //          - fRememberedElementOffset : 0;
2576 //      if (isValidSelection(delta + fRememberedSelection.getOffset(),
2577 //          fRememberedSelection.getLength()))
2578 //        selectAndReveal(delta + fRememberedSelection.getOffset(),
2579 //            fRememberedSelection.getLength());
2580 //    } finally {
2581 //      fRememberedSelection = null;
2582 //      fRememberedElement = null;
2583 //      fRememberedElementOffset = -1;
2584 //    }
2585 //  }
2586
2587   /**
2588          * Tells whether this is the active editor in the active page.
2589          *
2590          * @return <code>true</code> if this is the active editor in the active page
2591          * @see IWorkbenchPage#getActiveEditor();
2592          */
2593         protected final boolean isActiveEditor() {
2594                 IWorkbenchWindow window= getSite().getWorkbenchWindow();
2595                 IWorkbenchPage page= window.getActivePage();
2596                 if (page == null)
2597                         return false;
2598                 IEditorPart activeEditor= page.getActiveEditor();
2599                 return activeEditor != null && activeEditor.equals(this);
2600         }
2601         
2602         /**
2603          * Adds the given listener.
2604          * Has no effect if an identical listener was not already registered.
2605          * 
2606          * @param listener      The reconcile listener to be added
2607          * @since 3.0
2608          */
2609         final void addReconcileListener(IJavaReconcilingListener listener) {
2610                 synchronized (fReconcilingListeners) {
2611                         fReconcilingListeners.add(listener);
2612                 }
2613         }
2614         
2615         /**
2616          * Removes the given listener.
2617          * Has no effect if an identical listener was not already registered.
2618          * 
2619          * @param listener      the reconcile listener to be removed
2620          * @since 3.0
2621          */
2622         final void removeReconcileListener(IJavaReconcilingListener listener) {
2623                 synchronized (fReconcilingListeners) {
2624                         fReconcilingListeners.remove(listener);
2625                 }
2626         }
2627                 
2628         protected void updateStateDependentActions() {
2629                 super.updateStateDependentActions();
2630                 fGenerateActionGroup.editorStateChanged();
2631         }
2632         
2633         /*
2634          * @see AbstractTextEditor#rememberSelection()
2635          */
2636         protected void rememberSelection() {
2637                 fRememberedSelection.remember();
2638         }
2639         
2640         /*
2641          * @see AbstractTextEditor#restoreSelection()
2642          */
2643         protected void restoreSelection() {
2644                 fRememberedSelection.restore();
2645         }
2646         
2647         /*
2648          * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
2649          */
2650         protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
2651                 
2652                 String oldExtension= ""; //$NON-NLS-1$
2653                 if (originalElement instanceof IFileEditorInput) {
2654                         IFile file= ((IFileEditorInput) originalElement).getFile();
2655                         if (file != null) {
2656                                 String ext= file.getFileExtension();
2657                                 if (ext != null)
2658                                         oldExtension= ext;
2659                         }
2660                 }
2661                 
2662                 String newExtension= ""; //$NON-NLS-1$
2663                 if (movedElement instanceof IFileEditorInput) {
2664                         IFile file= ((IFileEditorInput) movedElement).getFile();
2665                         if (file != null)
2666                                 newExtension= file.getFileExtension();
2667                 }
2668                 
2669                 return oldExtension.equals(newExtension);
2670         }
2671
2672         /*
2673          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#isPrefQuickDiffAlwaysOn()
2674          */
2675         protected boolean isPrefQuickDiffAlwaysOn() {
2676                 // reestablishes the behaviour from AbstractDecoratedTextEditor which was hacked by JavaEditor
2677                 // to disable the change bar for the class file (attached source) java editor.
2678                 IPreferenceStore store= getPreferenceStore();
2679                 return store.getBoolean(AbstractDecoratedTextEditorPreferenceConstants.QUICK_DIFF_ALWAYS_ON);
2680         }
2681         
2682         /*
2683          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#getAdapter(java.lang.Class)
2684          */
2685         public Object getAdapter(Class required) {
2686                 if (SmartBackspaceManager.class.equals(required)) {
2687                         if (getSourceViewer() instanceof JavaSourceViewer) {
2688                                 return ((JavaSourceViewer) getSourceViewer()).getBackspaceManager();
2689                         }
2690                 }
2691
2692                 return super.getAdapter(required);
2693         }
2694   /**
2695          * Returns the mutex for the reconciler. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=63898
2696          * for a description of the problem.
2697          * <p>
2698          * TODO remove once the underlying problem is solved.
2699          * </p>
2700          * @return the lock reconcilers may use to synchronize on
2701          */
2702         public Object getReconcilerLock() {
2703                 return fReconcilerLock;
2704         }
2705         
2706 }