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