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