Eclipse 3.x compatible;
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPUnitEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.text.MessageFormat;
5 import java.util.ArrayList;
6 import java.util.Iterator;
7 import java.util.List;
8
9 import net.sourceforge.phpdt.core.ICompilationUnit;
10 import net.sourceforge.phpdt.core.IJavaElement;
11 import net.sourceforge.phpdt.core.ISourceRange;
12 import net.sourceforge.phpdt.core.ISourceReference;
13 import net.sourceforge.phpdt.core.JavaModelException;
14 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
15 import net.sourceforge.phpdt.internal.ui.text.ContentAssistPreference;
16 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
17 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
18 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
19 import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI.ExitFlags;
20 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
21 import net.sourceforge.phpdt.ui.PreferenceConstants;
22 import net.sourceforge.phpdt.ui.text.JavaTextTools;
23 import net.sourceforge.phpeclipse.PHPCore;
24 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
25 import net.sourceforge.phpeclipse.phpeditor.php.IPHPPartitionScannerConstants;
26
27 import org.eclipse.core.resources.IFile;
28 import org.eclipse.core.resources.IWorkspace;
29 import org.eclipse.core.resources.ResourcesPlugin;
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IPath;
32 import org.eclipse.core.runtime.IProgressMonitor;
33 import org.eclipse.core.runtime.Preferences;
34 import org.eclipse.jface.action.IMenuManager;
35 import org.eclipse.jface.dialogs.Dialog;
36 import org.eclipse.jface.dialogs.ErrorDialog;
37 import org.eclipse.jface.dialogs.IMessageProvider;
38 import org.eclipse.jface.dialogs.MessageDialog;
39 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
40 import org.eclipse.jface.preference.IPreferenceStore;
41 import org.eclipse.jface.preference.PreferenceConverter;
42 import org.eclipse.jface.text.BadLocationException;
43 import org.eclipse.jface.text.DocumentCommand;
44 import org.eclipse.jface.text.IDocument;
45 import org.eclipse.jface.text.ILineTracker;
46 import org.eclipse.jface.text.IRegion;
47 import org.eclipse.jface.text.ITextSelection;
48 import org.eclipse.jface.text.ITextViewerExtension;
49 import org.eclipse.jface.text.ITypedRegion;
50 import org.eclipse.jface.text.IWidgetTokenKeeper;
51 import org.eclipse.jface.text.contentassist.ContentAssistant;
52 import org.eclipse.jface.text.contentassist.IContentAssistant;
53 import org.eclipse.jface.text.source.IOverviewRuler;
54 import org.eclipse.jface.text.source.ISourceViewer;
55 import org.eclipse.jface.text.source.IVerticalRuler;
56 import org.eclipse.jface.text.source.SourceViewerConfiguration;
57 import org.eclipse.jface.util.PropertyChangeEvent;
58 import org.eclipse.jface.viewers.ISelectionProvider;
59 import org.eclipse.swt.custom.VerifyKeyListener;
60 import org.eclipse.swt.events.VerifyEvent;
61 import org.eclipse.swt.graphics.Color;
62 import org.eclipse.swt.graphics.Point;
63 import org.eclipse.swt.graphics.RGB;
64 import org.eclipse.swt.widgets.Composite;
65 import org.eclipse.swt.widgets.Display;
66 import org.eclipse.swt.widgets.Shell;
67 import org.eclipse.ui.IEditorInput;
68 import org.eclipse.ui.IFileEditorInput;
69 import org.eclipse.ui.actions.ActionContext;
70 import org.eclipse.ui.actions.WorkspaceModifyOperation;
71 import org.eclipse.ui.dialogs.SaveAsDialog;
72 import org.eclipse.ui.editors.text.IStorageDocumentProvider;
73 import org.eclipse.ui.help.WorkbenchHelp;
74 import org.eclipse.ui.part.FileEditorInput;
75 import org.eclipse.ui.texteditor.IDocumentProvider;
76
77 /**********************************************************************
78 Copyright (c) 2000, 2002 IBM Corp. and others.
79 All rights reserved. This program and the accompanying materials
80 are made available under the terms of the Common Public License v1.0
81 which accompanies this distribution, and is available at
82 http://www.eclipse.org/legal/cpl-v10.html
83
84 Contributors:
85     IBM Corporation - Initial implementation
86     Klaus Hartlage - www.eclipseproject.de
87 **********************************************************************/
88 /**
89  * PHP specific text editor.
90  */
91 public class PHPUnitEditor extends PHPEditor {
92
93   interface ITextConverter {
94     void customizeDocumentCommand(IDocument document, DocumentCommand command);
95   };
96
97   //  class AdaptedRulerLayout extends Layout {
98   //
99   //    protected int fGap;
100   //    protected AdaptedSourceViewer fAdaptedSourceViewer;
101   //
102   //    protected AdaptedRulerLayout(int gap, AdaptedSourceViewer asv) {
103   //      fGap = gap;
104   //      fAdaptedSourceViewer = asv;
105   //    }
106   //
107   //    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
108   //      Control[] children = composite.getChildren();
109   //      Point s = children[children.length - 1].computeSize(SWT.DEFAULT, SWT.DEFAULT, flushCache);
110   //      if (fAdaptedSourceViewer.isVerticalRulerVisible())
111   //        s.x += fAdaptedSourceViewer.getVerticalRuler().getWidth() + fGap;
112   //      return s;
113   //    }
114   //
115   //    protected void layout(Composite composite, boolean flushCache) {
116   //      Rectangle clArea = composite.getClientArea();
117   //      if (fAdaptedSourceViewer.isVerticalRulerVisible()) {
118   //
119   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
120   //        Rectangle trim = textWidget.computeTrim(0, 0, 0, 0);
121   //        int scrollbarHeight = trim.height;
122   //
123   //        IVerticalRuler vr = fAdaptedSourceViewer.getVerticalRuler();
124   //        int vrWidth = vr.getWidth();
125   //
126   //        int orWidth = 0;
127   //        if (fAdaptedSourceViewer.isOverviewRulerVisible()) {
128   //          OverviewRuler or = fAdaptedSourceViewer.getOverviewRuler();
129   //          orWidth = or.getWidth();
130   //          or.getControl().setBounds(clArea.width - orWidth, scrollbarHeight, orWidth, clArea.height - 3 * scrollbarHeight);
131   //        }
132   //
133   //        textWidget.setBounds(vrWidth + fGap, 0, clArea.width - vrWidth - orWidth - 2 * fGap, clArea.height);
134   //        vr.getControl().setBounds(0, 0, vrWidth, clArea.height - scrollbarHeight);
135   //
136   //      } else {
137   //        StyledText textWidget = fAdaptedSourceViewer.getTextWidget();
138   //        textWidget.setBounds(0, 0, clArea.width, clArea.height);
139   //      }
140   //    }
141   //  };
142   //
143   //  class AdaptedSourceViewer extends SourceViewer { // extends JavaCorrectionSourceViewer  {
144   //
145   //    private List fTextConverters;
146   //
147   //    private OverviewRuler fOverviewRuler;
148   //    private boolean fIsOverviewRulerVisible;
149   //    /** The viewer's overview ruler hovering controller */
150   //    private AbstractHoverInformationControlManager fOverviewRulerHoveringController;
151   //
152   //    private boolean fIgnoreTextConverters = false;
153   //
154   //    private IVerticalRuler fCachedVerticalRuler;
155   //    private boolean fCachedIsVerticalRulerVisible;
156   //
157   //    public AdaptedSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
158   //      super(parent, ruler, styles); //, CompilationUnitEditor.this);
159   //
160   //      fCachedVerticalRuler = ruler;
161   //      fCachedIsVerticalRulerVisible = (ruler != null);
162   //      fOverviewRuler = new OverviewRuler(VERTICAL_RULER_WIDTH);
163   //
164   //      delayedCreateControl(parent, styles);
165   //    }
166   //
167   //    /*
168   //     * @see ISourceViewer#showAnnotations(boolean)
169   //     */
170   //    public void showAnnotations(boolean show) {
171   //      fCachedIsVerticalRulerVisible = (show && fCachedVerticalRuler != null);
172   //      //   super.showAnnotations(show);
173   //    }
174   //
175   //    public IContentAssistant getContentAssistant() {
176   //      return fContentAssistant;
177   //    }
178   //
179   //    /*
180   //     * @see ITextOperationTarget#doOperation(int)
181   //     */
182   //    public void doOperation(int operation) {
183   //
184   //      if (getTextWidget() == null)
185   //        return;
186   //
187   //      switch (operation) {
188   //        case CONTENTASSIST_PROPOSALS :
189   //          String msg = fContentAssistant.showPossibleCompletions();
190   //          setStatusLineErrorMessage(msg);
191   //          return;
192   //        case UNDO :
193   //          fIgnoreTextConverters = true;
194   //          break;
195   //        case REDO :
196   //          fIgnoreTextConverters = true;
197   //          break;
198   //      }
199   //
200   //      super.doOperation(operation);
201   //    }
202   //
203   //    public void insertTextConverter(ITextConverter textConverter, int index) {
204   //      throw new UnsupportedOperationException();
205   //    }
206   //
207   //    public void addTextConverter(ITextConverter textConverter) {
208   //      if (fTextConverters == null) {
209   //        fTextConverters = new ArrayList(1);
210   //        fTextConverters.add(textConverter);
211   //      } else if (!fTextConverters.contains(textConverter))
212   //        fTextConverters.add(textConverter);
213   //    }
214   //
215   //    public void removeTextConverter(ITextConverter textConverter) {
216   //      if (fTextConverters != null) {
217   //        fTextConverters.remove(textConverter);
218   //        if (fTextConverters.size() == 0)
219   //          fTextConverters = null;
220   //      }
221   //    }
222   //
223   //    /*
224   //     * @see TextViewer#customizeDocumentCommand(DocumentCommand)
225   //     */
226   //    protected void customizeDocumentCommand(DocumentCommand command) {
227   //      super.customizeDocumentCommand(command);
228   //      if (!fIgnoreTextConverters && fTextConverters != null) {
229   //        for (Iterator e = fTextConverters.iterator(); e.hasNext();)
230   //           ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(), command);
231   //      }
232   //      fIgnoreTextConverters = false;
233   //    }
234   //
235   //    public IVerticalRuler getVerticalRuler() {
236   //      return fCachedVerticalRuler;
237   //    }
238   //
239   //    public boolean isVerticalRulerVisible() {
240   //      return fCachedIsVerticalRulerVisible;
241   //    }
242   //
243   //    public OverviewRuler getOverviewRuler() {
244   //      return fOverviewRuler;
245   //    }
246   //
247   //    /*
248   //     * @see TextViewer#createControl(Composite, int)
249   //     */
250   //    protected void createControl(Composite parent, int styles) {
251   //      // do nothing here
252   //    }
253   //
254   //    protected void delayedCreateControl(Composite parent, int styles) {
255   //      //create the viewer
256   //      super.createControl(parent, styles);
257   //
258   //      Control control = getControl();
259   //      if (control instanceof Composite) {
260   //        Composite composite = (Composite) control;
261   //        composite.setLayout(new AdaptedRulerLayout(GAP_SIZE, this));
262   //        fOverviewRuler.createControl(composite, this);
263   //      }
264   //    }
265
266   //    protected void ensureOverviewHoverManagerInstalled() {
267   //      if (fOverviewRulerHoveringController == null && fAnnotationHover != null && fHoverControlCreator != null) {
268   //        fOverviewRulerHoveringController =
269   //          new OverviewRulerHoverManager(fOverviewRuler, this, fAnnotationHover, fHoverControlCreator);
270   //        fOverviewRulerHoveringController.install(fOverviewRuler.getControl());
271   //      }
272   //    }
273   //
274   //    public void hideOverviewRuler() {
275   //      fIsOverviewRulerVisible = false;
276   //      Control control = getControl();
277   //      if (control instanceof Composite) {
278   //        Composite composite = (Composite) control;
279   //        composite.layout();
280   //      }
281   //      if (fOverviewRulerHoveringController != null) {
282   //        fOverviewRulerHoveringController.dispose();
283   //        fOverviewRulerHoveringController = null;
284   //      }
285   //    }
286   //
287   //    public void showOverviewRuler() {
288   //      fIsOverviewRulerVisible = true;
289   //      Control control = getControl();
290   //      if (control instanceof Composite) {
291   //        Composite composite = (Composite) control;
292   //        composite.layout();
293   //      }
294   //      ensureOverviewHoverManagerInstalled();
295   //    }
296   //
297   //    public boolean isOverviewRulerVisible() {
298   //      return fIsOverviewRulerVisible;
299   //    }
300   //
301   //    /*
302   //     * @see ISourceViewer#setDocument(IDocument, IAnnotationModel, int, int)
303   //     */
304   //    public void setDocument(
305   //      IDocument document,
306   //      IAnnotationModel annotationModel,
307   //      int visibleRegionOffset,
308   //      int visibleRegionLength) {
309   //      super.setDocument(document, annotationModel, visibleRegionOffset, visibleRegionLength);
310   //      fOverviewRuler.setModel(annotationModel);
311   //    }
312   //
313   //    // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
314   //    public void updateIndentationPrefixes() {
315   //      SourceViewerConfiguration configuration = getSourceViewerConfiguration();
316   //      String[] types = configuration.getConfiguredContentTypes(this);
317   //      for (int i = 0; i < types.length; i++) {
318   //        String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
319   //        if (prefixes != null && prefixes.length > 0)
320   //          setIndentPrefixes(prefixes, types[i]);
321   //      }
322   //    }
323   //
324   //    /*
325   //     * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
326   //     */
327   //    public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
328   //      if (WorkbenchHelp.isContextHelpDisplayed())
329   //        return false;
330   //      return super.requestWidgetToken(requester);
331   //    }
332   //
333   //    /*
334   //     * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
335   //     */
336   //    public void configure(SourceViewerConfiguration configuration) {
337   //      super.configure(configuration);
338   //      //      prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this), IDocument.DEFAULT_CONTENT_TYPE);
339   //    }
340   //
341   //    protected void handleDispose() {
342   //      fOverviewRuler = null;
343   //
344   //      if (fOverviewRulerHoveringController != null) {
345   //        fOverviewRulerHoveringController.dispose();
346   //        fOverviewRulerHoveringController = null;
347   //      }
348   //
349   //      super.handleDispose();
350   //    }
351   //
352   //  };
353
354   class AdaptedSourceViewer extends JavaSourceViewer {
355
356     private List fTextConverters;
357     private boolean fIgnoreTextConverters = false;
358     //                  private JavaCorrectionAssistant fCorrectionAssistant;
359
360     public AdaptedSourceViewer(
361       Composite parent,
362       IVerticalRuler verticalRuler,
363       IOverviewRuler overviewRuler,
364       boolean showAnnotationsOverview,
365       int styles) {
366       super(parent, verticalRuler, overviewRuler, showAnnotationsOverview, styles);
367     }
368
369     public IContentAssistant getContentAssistant() {
370       return fContentAssistant;
371     }
372
373     /*
374      * @see ITextOperationTarget#doOperation(int)
375      */
376     public void doOperation(int operation) {
377
378       if (getTextWidget() == null)
379         return;
380
381       switch (operation) {
382         case CONTENTASSIST_PROPOSALS :
383           String msg = fContentAssistant.showPossibleCompletions();
384           setStatusLineErrorMessage(msg);
385           return;
386           //                                    case CORRECTIONASSIST_PROPOSALS:
387           //                                            fCorrectionAssistant.showPossibleCompletions();
388           //                                            return;
389         case UNDO :
390           fIgnoreTextConverters = true;
391           break;
392         case REDO :
393           fIgnoreTextConverters = true;
394           break;
395       }
396
397       super.doOperation(operation);
398     }
399
400     /*
401      * @see ITextOperationTarget#canDoOperation(int)
402      */
403     public boolean canDoOperation(int operation) {
404       //                                if (operation == CORRECTIONASSIST_PROPOSALS)
405       //                                        return isEditable();
406       return super.canDoOperation(operation);
407     }
408
409     /*
410      * @see TextViewer#handleDispose()
411      */
412     protected void handleDispose() {
413       //                                if (fCorrectionAssistant != null) {
414       //                                        fCorrectionAssistant.uninstall();
415       //                                        fCorrectionAssistant= null;
416       //                                }
417       super.handleDispose();
418     }
419
420     public void insertTextConverter(ITextConverter textConverter, int index) {
421       throw new UnsupportedOperationException();
422     }
423
424     public void addTextConverter(ITextConverter textConverter) {
425       if (fTextConverters == null) {
426         fTextConverters = new ArrayList(1);
427         fTextConverters.add(textConverter);
428       } else if (!fTextConverters.contains(textConverter))
429         fTextConverters.add(textConverter);
430     }
431
432     public void removeTextConverter(ITextConverter textConverter) {
433       if (fTextConverters != null) {
434         fTextConverters.remove(textConverter);
435         if (fTextConverters.size() == 0)
436           fTextConverters = null;
437       }
438     }
439
440     /*
441      * @see TextViewer#customizeDocumentCommand(DocumentCommand)
442      */
443     protected void customizeDocumentCommand(DocumentCommand command) {
444       super.customizeDocumentCommand(command);
445       if (!fIgnoreTextConverters && fTextConverters != null) {
446         for (Iterator e = fTextConverters.iterator(); e.hasNext();)
447            ((ITextConverter) e.next()).customizeDocumentCommand(getDocument(), command);
448       }
449       fIgnoreTextConverters = false;
450     }
451
452     // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
453     public void updateIndentationPrefixes() {
454       SourceViewerConfiguration configuration = getSourceViewerConfiguration();
455       String[] types = configuration.getConfiguredContentTypes(this);
456       for (int i = 0; i < types.length; i++) {
457         String[] prefixes = configuration.getIndentPrefixes(this, types[i]);
458         if (prefixes != null && prefixes.length > 0)
459           setIndentPrefixes(prefixes, types[i]);
460       }
461     }
462
463     /*
464      * @see IWidgetTokenOwner#requestWidgetToken(IWidgetTokenKeeper)
465      */
466     public boolean requestWidgetToken(IWidgetTokenKeeper requester) {
467       if (WorkbenchHelp.isContextHelpDisplayed())
468         return false;
469       return super.requestWidgetToken(requester);
470     }
471
472     /*
473      * @see org.eclipse.jface.text.source.ISourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
474      */
475     public void configure(SourceViewerConfiguration configuration) {
476       super.configure(configuration);
477       //                                fCorrectionAssistant= new JavaCorrectionAssistant(CompilationUnitEditor.this);
478       //                                fCorrectionAssistant.install(this);
479       //TODO install SmartBracesAutoEditStrategy
480       //                                prependAutoEditStrategy(new SmartBracesAutoEditStrategy(this), IDocument.DEFAULT_CONTENT_TYPE);
481     }
482   };
483   static class TabConverter implements ITextConverter {
484
485     private int fTabRatio;
486     private ILineTracker fLineTracker;
487
488     public TabConverter() {
489     }
490
491     public void setNumberOfSpacesPerTab(int ratio) {
492       fTabRatio = ratio;
493     }
494
495     public void setLineTracker(ILineTracker lineTracker) {
496       fLineTracker = lineTracker;
497     }
498
499     private int insertTabString(StringBuffer buffer, int offsetInLine) {
500
501       if (fTabRatio == 0)
502         return 0;
503
504       int remainder = offsetInLine % fTabRatio;
505       remainder = fTabRatio - remainder;
506       for (int i = 0; i < remainder; i++)
507         buffer.append(' ');
508       return remainder;
509     }
510
511     public void customizeDocumentCommand(IDocument document, DocumentCommand command) {
512       String text = command.text;
513       if (text == null)
514         return;
515
516       int index = text.indexOf('\t');
517       if (index > -1) {
518
519         StringBuffer buffer = new StringBuffer();
520
521         fLineTracker.set(command.text);
522         int lines = fLineTracker.getNumberOfLines();
523
524         try {
525
526           for (int i = 0; i < lines; i++) {
527
528             int offset = fLineTracker.getLineOffset(i);
529             int endOffset = offset + fLineTracker.getLineLength(i);
530             String line = text.substring(offset, endOffset);
531
532             int position = 0;
533             if (i == 0) {
534               IRegion firstLine = document.getLineInformationOfOffset(command.offset);
535               position = command.offset - firstLine.getOffset();
536             }
537
538             int length = line.length();
539             for (int j = 0; j < length; j++) {
540               char c = line.charAt(j);
541               if (c == '\t') {
542                 position += insertTabString(buffer, position);
543               } else {
544                 buffer.append(c);
545                 ++position;
546               }
547             }
548
549           }
550
551           command.text = buffer.toString();
552
553         } catch (BadLocationException x) {
554         }
555       }
556     }
557   };
558
559   private static class ExitPolicy implements LinkedPositionUI.ExitPolicy {
560
561     final char fExitCharacter;
562
563     public ExitPolicy(char exitCharacter) {
564       fExitCharacter = exitCharacter;
565     }
566
567     /*
568      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionManager, org.eclipse.swt.events.VerifyEvent, int, int)
569      */
570     public ExitFlags doExit(LinkedPositionManager manager, VerifyEvent event, int offset, int length) {
571
572       if (event.character == fExitCharacter) {
573         if (manager.anyPositionIncludes(offset, length))
574           return new ExitFlags(LinkedPositionUI.COMMIT | LinkedPositionUI.UPDATE_CARET, false);
575         else
576           return new ExitFlags(LinkedPositionUI.COMMIT, true);
577       }
578
579       switch (event.character) {
580         case '\b' :
581           if (manager.getFirstPosition().length == 0)
582             return new ExitFlags(0, false);
583           else
584             return null;
585
586         case '\n' :
587         case '\r' :
588           return new ExitFlags(LinkedPositionUI.COMMIT, true);
589
590         default :
591           return null;
592       }
593     }
594
595   }
596
597   private static class BracketLevel {
598     int fOffset;
599     int fLength;
600     LinkedPositionManager fManager;
601     LinkedPositionUI fEditor;
602   };
603
604   private class BracketInserter implements VerifyKeyListener, LinkedPositionUI.ExitListener {
605
606     private boolean fCloseBracketsPHP = true;
607     private boolean fCloseStringsPHP = true;
608     private boolean fCloseBracketsHTML = true;
609     private boolean fCloseStringsHTML = true;
610
611     private int fOffset;
612     private int fLength;
613
614     public void setCloseBracketsPHPEnabled(boolean enabled) {
615       fCloseBracketsPHP = enabled;
616     }
617
618     public void setCloseStringsPHPEnabled(boolean enabled) {
619       fCloseStringsPHP = enabled;
620     }
621
622     public void setCloseBracketsHTMLEnabled(boolean enabled) {
623       fCloseBracketsHTML = enabled;
624     }
625
626     public void setCloseStringsHTMLEnabled(boolean enabled) {
627       fCloseStringsHTML = enabled;
628     }
629
630     private boolean hasIdentifierToTheRight(IDocument document, int offset) {
631       try {
632         int end = offset;
633         IRegion endLine = document.getLineInformationOfOffset(end);
634         int maxEnd = endLine.getOffset() + endLine.getLength();
635         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
636           ++end;
637
638         return end != maxEnd && Scanner.isPHPIdentifierPart(document.getChar(end));
639
640       } catch (BadLocationException e) {
641         // be conservative
642         return true;
643       }
644     }
645
646     private boolean hasIdentifierToTheLeft(IDocument document, int offset) {
647       try {
648         int start = offset;
649         IRegion startLine = document.getLineInformationOfOffset(start);
650         int minStart = startLine.getOffset();
651         while (start != minStart && Character.isWhitespace(document.getChar(start - 1)))
652           --start;
653
654         return start != minStart && Scanner.isPHPIdentifierPart(document.getChar(start - 1));
655
656       } catch (BadLocationException e) {
657         return true;
658       }
659     }
660
661     private boolean hasCharacterToTheRight(IDocument document, int offset, char character) {
662       try {
663         int end = offset;
664         IRegion endLine = document.getLineInformationOfOffset(end);
665         int maxEnd = endLine.getOffset() + endLine.getLength();
666         while (end != maxEnd && Character.isWhitespace(document.getChar(end)))
667           ++end;
668
669         return end != maxEnd && document.getChar(end) == character;
670
671       } catch (BadLocationException e) {
672         // be conservative
673         return true;
674       }
675     }
676
677     /*
678      * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
679      */
680     public void verifyKey(VerifyEvent event) {
681
682       if (!event.doit)
683         return;
684
685       final ISourceViewer sourceViewer = getSourceViewer();
686       IDocument document = sourceViewer.getDocument();
687
688       final Point selection = sourceViewer.getSelectedRange();
689       final int offset = selection.x;
690       final int length = selection.y;
691
692       try {
693         ITypedRegion partition = document.getPartition(offset);
694         String type = partition.getType();
695         if (type.equals(IPHPPartitionScannerConstants.PHP)) {
696           switch (event.character) {
697             case '(' :
698               if (hasCharacterToTheRight(document, offset + length, '('))
699                 return;
700
701               // fall through
702
703             case '[' :
704               if (!fCloseBracketsPHP)
705                 return;
706               if (hasIdentifierToTheRight(document, offset + length))
707                 return;
708
709               // fall through
710
711             case '"' :
712               if (event.character == '"') {
713                 if (!fCloseStringsPHP)
714                   return;
715                 // changed for statements like echo ""  print ""
716                 //    if (hasIdentifierToTheLeft(document, offset) || hasIdentifierToTheRight(document, offset + length))
717                 if (hasIdentifierToTheRight(document, offset + length))
718                   return;
719               }
720
721               //     ITypedRegion partition= document.getPartition(offset);
722               //       if (! IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) &&  (partition.getOffset() != offset))
723               //         return;
724
725               final char character = event.character;
726               final char closingCharacter = getPeerCharacter(character);
727               final StringBuffer buffer = new StringBuffer();
728               buffer.append(character);
729               buffer.append(closingCharacter);
730
731               document.replace(offset, length, buffer.toString());
732
733               LinkedPositionManager manager = new LinkedPositionManager(document);
734               manager.addPosition(offset + 1, 0);
735
736               fOffset = offset;
737               fLength = 2;
738
739               LinkedPositionUI editor = new LinkedPositionUI(sourceViewer, manager);
740               editor.setCancelListener(this);
741               editor.setExitPolicy(new ExitPolicy(closingCharacter));
742               editor.setFinalCaretOffset(offset + 2);
743               editor.enter();
744
745               IRegion newSelection = editor.getSelectedRegion();
746               sourceViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());
747
748               event.doit = false;
749           }
750         } else if (type.equals(IPHPPartitionScannerConstants.HTML) || type.equals(IDocument.DEFAULT_CONTENT_TYPE)) {
751           switch (event.character) {
752             case '(' :
753               if (hasCharacterToTheRight(document, offset + length, '('))
754                 return;
755
756               // fall through
757
758             case '[' :
759               if (!fCloseBracketsHTML)
760                 return;
761               if (hasIdentifierToTheRight(document, offset + length))
762                 return;
763
764               // fall through
765
766             case '"' :
767               if (event.character == '"') {
768                 if (!fCloseStringsHTML)
769                   return;
770
771                 if (hasIdentifierToTheLeft(document, offset) || hasIdentifierToTheRight(document, offset + length))
772                   return;
773               }
774
775               //     ITypedRegion partition= document.getPartition(offset);
776               //       if (! IDocument.DEFAULT_CONTENT_TYPE.equals(partition.getType()) &&  (partition.getOffset() != offset))
777               //         return;
778
779               final char character = event.character;
780               final char closingCharacter = getPeerCharacter(character);
781               final StringBuffer buffer = new StringBuffer();
782               buffer.append(character);
783               buffer.append(closingCharacter);
784
785               document.replace(offset, length, buffer.toString());
786
787               LinkedPositionManager manager = new LinkedPositionManager(document);
788               manager.addPosition(offset + 1, 0);
789
790               fOffset = offset;
791               fLength = 2;
792
793               LinkedPositionUI editor = new LinkedPositionUI(sourceViewer, manager);
794               editor.setCancelListener(this);
795               editor.setExitPolicy(new ExitPolicy(closingCharacter));
796               editor.setFinalCaretOffset(offset + 2);
797               editor.enter();
798
799               IRegion newSelection = editor.getSelectedRegion();
800               sourceViewer.setSelectedRange(newSelection.getOffset(), newSelection.getLength());
801
802               event.doit = false;
803           }
804         }
805       } catch (BadLocationException e) {
806       }
807
808     }
809
810     /*
811      * @see org.phpeclipse.phpdt.internal.ui.text.link.LinkedPositionUI.ExitListener#exit(boolean)
812      */
813     public void exit(boolean accept) {
814       if (accept)
815         return;
816
817       // remove brackets
818       try {
819         final ISourceViewer sourceViewer = getSourceViewer();
820         IDocument document = sourceViewer.getDocument();
821         document.replace(fOffset, fLength, null);
822       } catch (BadLocationException e) {
823       }
824     }
825
826   }
827
828   /** The editor's save policy */
829   protected ISavePolicy fSavePolicy;
830   /** Listener to annotation model changes that updates the error tick in the tab image */
831   private JavaEditorErrorTickUpdater fJavaEditorErrorTickUpdater;
832
833   /** The editor's paint manager */
834   //  private PaintManager fPaintManager;
835   /** The editor's bracket painter */
836   private BracketPainter fBracketPainter;
837   /** The editor's bracket matcher */
838   private PHPPairMatcher fBracketMatcher;
839   /** The editor's line painter */
840   private LinePainter fLinePainter;
841   /** The editor's print margin ruler painter */
842   private PrintMarginPainter fPrintMarginPainter;
843   /** The editor's problem painter */
844   //  private ProblemPainter fProblemPainter;
845   /** The editor's tab converter */
846   private TabConverter fTabConverter;
847   /** History for structure select action */
848   //private SelectionHistory fSelectionHistory;
849
850   /** The preference property change listener for php core. */
851   //  private IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
852   /** The remembered java element */
853   private IJavaElement fRememberedElement;
854   /** The remembered selection */
855   private ITextSelection fRememberedSelection;
856   /** The remembered php element offset */
857   private int fRememberedElementOffset;
858   /** The bracket inserter. */
859   private BracketInserter fBracketInserter = new BracketInserter();
860
861   //  private class PropertyChangeListener implements IPropertyChangeListener {
862   //    /*
863   //     * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
864   //     */
865   //    public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
866   //      handlePreferencePropertyChanged(event);
867   //    }
868   //  }
869   /* Preference key for code formatter tab size */
870   private final static String CODE_FORMATTER_TAB_SIZE = PHPCore.FORMATTER_TAB_SIZE;
871   /** Preference key for matching brackets */
872   private final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
873   /** Preference key for matching brackets color */
874   private final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
875   /** Preference key for highlighting current line */
876   private final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
877   /** Preference key for highlight color of current line */
878   private final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
879   /** Preference key for showing print marging ruler */
880   private final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
881   /** Preference key for print margin ruler color */
882   private final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
883   /** Preference key for print margin ruler column */
884   private final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
885   /** Preference key for inserting spaces rather than tabs */
886   private final static String SPACES_FOR_TABS = PreferenceConstants.EDITOR_SPACES_FOR_TABS;
887   /** Preference key for error indication */
888   private final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION;
889   /** Preference key for error color */
890   private final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
891   /** Preference key for warning indication */
892   private final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION;
893   /** Preference key for warning color */
894   private final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
895   /** Preference key for task indication */
896   private final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
897   /** Preference key for task color */
898   private final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
899   /** Preference key for bookmark indication */
900   private final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
901   /** Preference key for bookmark color */
902   private final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
903   /** Preference key for search result indication */
904   private final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
905   /** Preference key for search result color */
906   private final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
907   /** Preference key for unknown annotation indication */
908   private final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
909   /** Preference key for unknown annotation color */
910   private final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
911   /** Preference key for linked position color */
912   private final static String LINKED_POSITION_COLOR = PreferenceConstants.EDITOR_LINKED_POSITION_COLOR;
913   /** Preference key for shwoing the overview ruler */
914   private final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
915
916   /** Preference key for error indication in overview ruler */
917   private final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
918   /** Preference key for warning indication in overview ruler */
919   private final static String WARNING_INDICATION_IN_OVERVIEW_RULER =
920     PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
921   /** Preference key for task indication in overview ruler */
922   private final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
923   /** Preference key for bookmark indication in overview ruler */
924   private final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER =
925     PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
926   /** Preference key for search result indication in overview ruler */
927   private final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER =
928     PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
929   /** Preference key for unknown annotation indication in overview ruler */
930   private final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER =
931     PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
932   /** Preference key for automatically closing strings */
933   private final static String CLOSE_STRINGS_PHP = PreferenceConstants.EDITOR_CLOSE_STRINGS_PHP;
934   /** Preference key for automatically wrapping Java strings */
935   private final static String WRAP_STRINGS = PreferenceConstants.EDITOR_WRAP_STRINGS;
936   /** Preference key for automatically closing brackets and parenthesis */
937   private final static String CLOSE_BRACKETS_PHP = PreferenceConstants.EDITOR_CLOSE_BRACKETS_PHP;
938   /** Preference key for automatically closing phpdocs and comments */
939   private final static String CLOSE_JAVADOCS = PreferenceConstants.EDITOR_CLOSE_JAVADOCS;
940   /** Preference key for automatically adding phpdoc tags */
941   private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
942   /** Preference key for automatically formatting phpdocs */
943   private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
944   /** Preference key for automatically closing strings */
945   private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
946   /** Preference key for automatically closing brackets and parenthesis */
947   private final static String CLOSE_BRACKETS_HTML = PreferenceConstants.EDITOR_CLOSE_BRACKETS_HTML;
948
949   /** Preference key for smart paste */
950   private final static String SMART_PASTE = PreferenceConstants.EDITOR_SMART_PASTE;
951   //  private final static class AnnotationInfo {
952   //    public String fColorPreference;
953   //    public String fOverviewRulerPreference;
954   //    public String fEditorPreference;
955   //  };
956
957   //  private final static Map ANNOTATION_MAP;
958   //  static {
959   //
960   //    AnnotationInfo info;
961   //    ANNOTATION_MAP = new HashMap();
962   //
963   //    info = new AnnotationInfo();
964   //    info.fColorPreference = TASK_INDICATION_COLOR;
965   //    info.fOverviewRulerPreference = TASK_INDICATION_IN_OVERVIEW_RULER;
966   //    info.fEditorPreference = TASK_INDICATION;
967   //    ANNOTATION_MAP.put(AnnotationType.TASK, info);
968   //
969   //    info = new AnnotationInfo();
970   //    info.fColorPreference = ERROR_INDICATION_COLOR;
971   //    info.fOverviewRulerPreference = ERROR_INDICATION_IN_OVERVIEW_RULER;
972   //    info.fEditorPreference = ERROR_INDICATION;
973   //    ANNOTATION_MAP.put(AnnotationType.ERROR, info);
974   //
975   //    info = new AnnotationInfo();
976   //    info.fColorPreference = WARNING_INDICATION_COLOR;
977   //    info.fOverviewRulerPreference = WARNING_INDICATION_IN_OVERVIEW_RULER;
978   //    info.fEditorPreference = WARNING_INDICATION;
979   //    ANNOTATION_MAP.put(AnnotationType.WARNING, info);
980   //
981   //    info = new AnnotationInfo();
982   //    info.fColorPreference = BOOKMARK_INDICATION_COLOR;
983   //    info.fOverviewRulerPreference = BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
984   //    info.fEditorPreference = BOOKMARK_INDICATION;
985   //    ANNOTATION_MAP.put(AnnotationType.BOOKMARK, info);
986   //
987   //    info = new AnnotationInfo();
988   //    info.fColorPreference = SEARCH_RESULT_INDICATION_COLOR;
989   //    info.fOverviewRulerPreference = SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
990   //    info.fEditorPreference = SEARCH_RESULT_INDICATION;
991   //    ANNOTATION_MAP.put(AnnotationType.SEARCH, info);
992   //
993   //    info = new AnnotationInfo();
994   //    info.fColorPreference = UNKNOWN_INDICATION_COLOR;
995   //    info.fOverviewRulerPreference = UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
996   //    info.fEditorPreference = UNKNOWN_INDICATION;
997   //    ANNOTATION_MAP.put(AnnotationType.UNKNOWN, info);
998   //  };
999   //
1000   //  private final static AnnotationType[] ANNOTATION_LAYERS =
1001   //    new AnnotationType[] {
1002   //      AnnotationType.UNKNOWN,
1003   //      AnnotationType.BOOKMARK,
1004   //      AnnotationType.TASK,
1005   //      AnnotationType.SEARCH,
1006   //      AnnotationType.WARNING,
1007   //      AnnotationType.ERROR };
1008   /**
1009    * Creates a new php unit editor.
1010    */
1011   public PHPUnitEditor() {
1012     super();
1013     setDocumentProvider(PHPeclipsePlugin.getDefault().getCompilationUnitDocumentProvider());
1014     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
1015     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
1016     setOutlinerContextMenuId("#PHPOutlinerContext"); //$NON-NLS-1$
1017     // don't set help contextId, we install our own help context
1018     fSavePolicy = null;
1019
1020     fJavaEditorErrorTickUpdater = new JavaEditorErrorTickUpdater(this);
1021   }
1022
1023   /*
1024          * @see JavaEditor#getElementAt(int)
1025          */
1026   protected IJavaElement getElementAt(int offset) {
1027     return getElementAt(offset, true);
1028   }
1029
1030   /**
1031    * Returns the most narrow element including the given offset.  If <code>reconcile</code>
1032    * is <code>true</code> the editor's input element is reconciled in advance. If it is 
1033    * <code>false</code> this method only returns a result if the editor's input element
1034    * does not need to be reconciled.
1035    * 
1036    * @param offset the offset included by the retrieved element
1037    * @param reconcile <code>true</code> if working copy should be reconciled
1038    */
1039   protected IJavaElement getElementAt(int offset, boolean reconcile) {
1040     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
1041     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
1042
1043     if (unit != null) {
1044       try {
1045         if (reconcile) {
1046           synchronized (unit) {
1047             unit.reconcile();
1048           }
1049           return unit.getElementAt(offset);
1050         } else if (unit.isConsistent())
1051           return unit.getElementAt(offset);
1052
1053       } catch (JavaModelException x) {
1054         PHPeclipsePlugin.log(x.getStatus());
1055         // nothing found, be tolerant and go on
1056       }
1057     }
1058
1059     return null;
1060   }
1061
1062   /*
1063    * @see JavaEditor#getCorrespondingElement(IJavaElement)
1064    */
1065   protected IJavaElement getCorrespondingElement(IJavaElement element) {
1066     try {
1067       return EditorUtility.getWorkingCopy(element, true);
1068     } catch (JavaModelException x) {
1069       PHPeclipsePlugin.log(x.getStatus());
1070       // nothing found, be tolerant and go on
1071     }
1072     return null;
1073   }
1074
1075   public void createPartControl(Composite parent) {
1076     super.createPartControl(parent);
1077
1078     //    fPaintManager = new PaintManager(getSourceViewer());
1079
1080     LinePainter linePainter;
1081     linePainter = new LinePainter(getSourceViewer());
1082
1083     linePainter.setHighlightColor(new Color(Display.getCurrent(), 225, 235, 224));
1084
1085     //    fPaintManager.addPainter(linePainter);
1086
1087     if (isBracketHighlightingEnabled())
1088       startBracketHighlighting();
1089     if (isLineHighlightingEnabled())
1090       startLineHighlighting();
1091     if (isPrintMarginVisible())
1092       showPrintMargin();
1093
1094     //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1095     //    while (e.hasNext()) {
1096     //      AnnotationType type = (AnnotationType) e.next();
1097     //      if (isAnnotationIndicationEnabled(type))
1098     //        startAnnotationIndication(type);
1099     //    }
1100
1101     if (isTabConversionEnabled())
1102       startTabConversion();
1103
1104     //    if (isOverviewRulerVisible())
1105     //      showOverviewRuler();
1106     //
1107     //    Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1108     //    preferences.addPropertyChangeListener(fPropertyChangeListener);
1109
1110     IPreferenceStore preferenceStore = getPreferenceStore();
1111     boolean closeBracketsPHP = preferenceStore.getBoolean(CLOSE_BRACKETS_PHP);
1112     boolean closeStringsPHP = preferenceStore.getBoolean(CLOSE_STRINGS_PHP);
1113     boolean closeBracketsHTML = preferenceStore.getBoolean(CLOSE_BRACKETS_HTML);
1114     boolean closeStringsHTML = preferenceStore.getBoolean(CLOSE_STRINGS_HTML);
1115
1116     fBracketInserter.setCloseBracketsPHPEnabled(closeBracketsPHP);
1117     fBracketInserter.setCloseStringsPHPEnabled(closeStringsPHP);
1118     fBracketInserter.setCloseBracketsHTMLEnabled(closeBracketsHTML);
1119     fBracketInserter.setCloseStringsHTMLEnabled(closeStringsHTML);
1120
1121     ISourceViewer sourceViewer = getSourceViewer();
1122     if (sourceViewer instanceof ITextViewerExtension)
1123        ((ITextViewerExtension) sourceViewer).prependVerifyKeyListener(fBracketInserter);                        
1124                         
1125   }
1126
1127   private static char getPeerCharacter(char character) {
1128     switch (character) {
1129       case '(' :
1130         return ')';
1131
1132       case ')' :
1133         return '(';
1134
1135       case '[' :
1136         return ']';
1137
1138       case ']' :
1139         return '[';
1140
1141       case '"' :
1142         return character;
1143
1144       default :
1145         throw new IllegalArgumentException();
1146     }
1147   }
1148   /**
1149          * The compilation unit editor implementation of this  <code>AbstractTextEditor</code>
1150          * method asks the user for the workspace path of a file resource and saves the document
1151          * there. See http://dev.eclipse.org/bugs/show_bug.cgi?id=6295
1152          */
1153   protected void performSaveAs(IProgressMonitor progressMonitor) {
1154
1155     Shell shell = getSite().getShell();
1156     IEditorInput input = getEditorInput();
1157
1158     SaveAsDialog dialog = new SaveAsDialog(shell);
1159
1160     IFile original = (input instanceof IFileEditorInput) ? ((IFileEditorInput) input).getFile() : null;
1161     if (original != null)
1162       dialog.setOriginalFile(original);
1163
1164     dialog.create();
1165
1166     IDocumentProvider provider = getDocumentProvider();
1167     if (provider == null) {
1168       // editor has been programmatically closed while the dialog was open
1169       return;
1170     }
1171
1172     if (provider.isDeleted(input) && original != null) {
1173       String message = PHPEditorMessages.getFormattedString("CompilationUnitEditor.warning.save.delete", new Object[] { original.getName()}); //$NON-NLS-1$
1174       dialog.setErrorMessage(null);
1175       dialog.setMessage(message, IMessageProvider.WARNING);
1176     }
1177
1178     if (dialog.open() == Dialog.CANCEL) {
1179       if (progressMonitor != null)
1180         progressMonitor.setCanceled(true);
1181       return;
1182     }
1183
1184     IPath filePath = dialog.getResult();
1185     if (filePath == null) {
1186       if (progressMonitor != null)
1187         progressMonitor.setCanceled(true);
1188       return;
1189     }
1190
1191     IWorkspace workspace = ResourcesPlugin.getWorkspace();
1192     IFile file = workspace.getRoot().getFile(filePath);
1193     final IEditorInput newInput = new FileEditorInput(file);
1194
1195     WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
1196       public void execute(final IProgressMonitor monitor) throws CoreException {
1197         getDocumentProvider().saveDocument(monitor, newInput, getDocumentProvider().getDocument(getEditorInput()), true);
1198       }
1199     };
1200
1201     boolean success = false;
1202     try {
1203
1204       provider.aboutToChange(newInput);
1205       new ProgressMonitorDialog(shell).run(false, true, op);
1206       success = true;
1207
1208     } catch (InterruptedException x) {
1209     } catch (InvocationTargetException x) {
1210
1211       Throwable t = x.getTargetException();
1212       if (t instanceof CoreException) {
1213         CoreException cx = (CoreException) t;
1214         ErrorDialog.openError(shell, PHPEditorMessages.getString("CompilationUnitEditor.error.saving.title2"), PHPEditorMessages.getString("CompilationUnitEditor.error.saving.message2"), cx.getStatus()); //$NON-NLS-1$ //$NON-NLS-2$
1215       } else {
1216         MessageDialog.openError(shell, PHPEditorMessages.getString("CompilationUnitEditor.error.saving.title3"), PHPEditorMessages.getString("CompilationUnitEditor.error.saving.message3") + t.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
1217       }
1218
1219     } finally {
1220       provider.changed(newInput);
1221       if (success)
1222         setInput(newInput);
1223     }
1224
1225     if (progressMonitor != null)
1226       progressMonitor.setCanceled(!success);
1227   }
1228   /*
1229    * @see AbstractTextEditor#doSetInput(IEditorInput)
1230    */
1231   protected void doSetInput(IEditorInput input) throws CoreException {
1232     super.doSetInput(input);
1233     configureTabConverter();
1234   }
1235
1236   private void startBracketHighlighting() {
1237     if (fBracketPainter == null) {
1238       ISourceViewer sourceViewer = getSourceViewer();
1239       fBracketPainter = new BracketPainter(sourceViewer);
1240       fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1241       //      fPaintManager.addPainter(fBracketPainter);
1242     }
1243   }
1244
1245   private void stopBracketHighlighting() {
1246     if (fBracketPainter != null) {
1247       //      fPaintManager.removePainter(fBracketPainter);
1248       fBracketPainter.deactivate(true);
1249       fBracketPainter.dispose();
1250       fBracketPainter = null;
1251     }
1252   }
1253
1254   private boolean isBracketHighlightingEnabled() {
1255     IPreferenceStore store = getPreferenceStore();
1256     return store.getBoolean(MATCHING_BRACKETS);
1257   }
1258
1259   private void startLineHighlighting() {
1260     if (fLinePainter == null) {
1261       ISourceViewer sourceViewer = getSourceViewer();
1262       fLinePainter = new LinePainter(sourceViewer);
1263       fLinePainter.setHighlightColor(getColor(CURRENT_LINE_COLOR));
1264       //      fPaintManager.addPainter(fLinePainter);
1265     }
1266   }
1267
1268   private void stopLineHighlighting() {
1269     if (fLinePainter != null) {
1270       //      fPaintManager.removePainter(fLinePainter);
1271       fLinePainter.deactivate(true);
1272       fLinePainter.dispose();
1273       fLinePainter = null;
1274     }
1275   }
1276
1277   private boolean isLineHighlightingEnabled() {
1278     IPreferenceStore store = getPreferenceStore();
1279     return store.getBoolean(CURRENT_LINE);
1280   }
1281
1282   private void showPrintMargin() {
1283     if (fPrintMarginPainter == null) {
1284       fPrintMarginPainter = new PrintMarginPainter(getSourceViewer());
1285       fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1286       fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
1287       //      fPaintManager.addPainter(fPrintMarginPainter);
1288     }
1289   }
1290
1291   private void hidePrintMargin() {
1292     if (fPrintMarginPainter != null) {
1293       //      fPaintManager.removePainter(fPrintMarginPainter);
1294       fPrintMarginPainter.deactivate(true);
1295       fPrintMarginPainter.dispose();
1296       fPrintMarginPainter = null;
1297     }
1298   }
1299
1300   private boolean isPrintMarginVisible() {
1301     IPreferenceStore store = getPreferenceStore();
1302     return store.getBoolean(PRINT_MARGIN);
1303   }
1304
1305   //  private void startAnnotationIndication(AnnotationType annotationType) {
1306   //    if (fProblemPainter == null) {
1307   //      fProblemPainter = new ProblemPainter(this, getSourceViewer());
1308   ////      fPaintManager.addPainter(fProblemPainter);
1309   //    }
1310   //    fProblemPainter.setColor(annotationType, getColor(annotationType));
1311   //    fProblemPainter.paintAnnotations(annotationType, true);
1312   //    fProblemPainter.paint(IPainter.CONFIGURATION);
1313   //  }
1314   //
1315   //  private void shutdownAnnotationIndication() {
1316   //    if (fProblemPainter != null) {
1317   //
1318   //      if (!fProblemPainter.isPaintingAnnotations()) {
1319   ////        fPaintManager.removePainter(fProblemPainter);
1320   //        fProblemPainter.deactivate(true);
1321   //        fProblemPainter.dispose();
1322   //        fProblemPainter = null;
1323   //      } else {
1324   //        fProblemPainter.paint(IPainter.CONFIGURATION);
1325   //      }
1326   //    }
1327   //  }
1328   //
1329   //  private void stopAnnotationIndication(AnnotationType annotationType) {
1330   //    if (fProblemPainter != null) {
1331   //      fProblemPainter.paintAnnotations(annotationType, false);
1332   //      shutdownAnnotationIndication();
1333   //    }
1334   //  }
1335   //
1336   //  private boolean isAnnotationIndicationEnabled(AnnotationType annotationType) {
1337   //    IPreferenceStore store = getPreferenceStore();
1338   //    AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1339   //    if (info != null)
1340   //      return store.getBoolean(info.fEditorPreference);
1341   //    return false;
1342   //  }
1343   //
1344   //  private boolean isAnnotationIndicationInOverviewRulerEnabled(AnnotationType annotationType) {
1345   //    IPreferenceStore store = getPreferenceStore();
1346   //    AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1347   //    if (info != null)
1348   //      return store.getBoolean(info.fOverviewRulerPreference);
1349   //    return false;
1350   //  }
1351   //
1352   //  private void showAnnotationIndicationInOverviewRuler(AnnotationType annotationType, boolean show) {
1353   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1354   //    OverviewRuler ruler = asv.getOverviewRuler();
1355   //    if (ruler != null) {
1356   //      ruler.setColor(annotationType, getColor(annotationType));
1357   //      ruler.showAnnotation(annotationType, show);
1358   //      ruler.update();
1359   //    }
1360   //  }
1361   //
1362   //  private void setColorInOverviewRuler(AnnotationType annotationType, Color color) {
1363   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1364   //    OverviewRuler ruler = asv.getOverviewRuler();
1365   //    if (ruler != null) {
1366   //      ruler.setColor(annotationType, color);
1367   //      ruler.update();
1368   //    }
1369   //  }
1370
1371   private void configureTabConverter() {
1372     if (fTabConverter != null) {
1373       IDocumentProvider provider = getDocumentProvider();
1374       if (provider instanceof PHPDocumentProvider) {
1375         PHPDocumentProvider cup = (PHPDocumentProvider) provider;
1376         fTabConverter.setLineTracker(cup.createLineTracker(getEditorInput()));
1377       }
1378     }
1379   }
1380
1381   private int getTabSize() {
1382     Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1383     return preferences.getInt(CODE_FORMATTER_TAB_SIZE);
1384   }
1385
1386   private void startTabConversion() {
1387     if (fTabConverter == null) {
1388       fTabConverter = new TabConverter();
1389       configureTabConverter();
1390       fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1391       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1392       asv.addTextConverter(fTabConverter);
1393       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1394       asv.updateIndentationPrefixes();
1395     }
1396   }
1397
1398   private void stopTabConversion() {
1399     if (fTabConverter != null) {
1400       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1401       asv.removeTextConverter(fTabConverter);
1402       // http://dev.eclipse.org/bugs/show_bug.cgi?id=19270
1403       asv.updateIndentationPrefixes();
1404       fTabConverter = null;
1405     }
1406   }
1407
1408   private boolean isTabConversionEnabled() {
1409     IPreferenceStore store = getPreferenceStore();
1410     return store.getBoolean(SPACES_FOR_TABS);
1411   }
1412
1413   //  private void showOverviewRuler() {
1414   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1415   //    asv.showOverviewRuler();
1416   //
1417   //    OverviewRuler overviewRuler = asv.getOverviewRuler();
1418   //    if (overviewRuler != null) {
1419   //      for (int i = 0; i < ANNOTATION_LAYERS.length; i++) {
1420   //        AnnotationType type = ANNOTATION_LAYERS[i];
1421   //        overviewRuler.setLayer(type, i);
1422   //        if (isAnnotationIndicationInOverviewRulerEnabled(type))
1423   //          showAnnotationIndicationInOverviewRuler(type, true);
1424   //      }
1425   //    }
1426   //  }
1427   //
1428   //  private void hideOverviewRuler() {
1429   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1430   //    asv.hideOverviewRuler();
1431   //  }
1432   //
1433   //  private boolean isOverviewRulerVisible() {
1434   //    IPreferenceStore store = getPreferenceStore();
1435   //    return store.getBoolean(OVERVIEW_RULER);
1436   //  }
1437
1438   private Color getColor(String key) {
1439     RGB rgb = PreferenceConverter.getColor(getPreferenceStore(), key);
1440     return getColor(rgb);
1441   }
1442
1443   private Color getColor(RGB rgb) {
1444     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1445     return textTools.getColorManager().getColor(rgb);
1446   }
1447
1448   //  private Color getColor(AnnotationType annotationType) {
1449   //    AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(annotationType);
1450   //    if (info != null)
1451   //      return getColor(info.fColorPreference);
1452   //    return null;
1453   //  }
1454
1455   public void dispose() {
1456     ISourceViewer sourceViewer = getSourceViewer();
1457     if (sourceViewer instanceof ITextViewerExtension)
1458        ((ITextViewerExtension) sourceViewer).removeVerifyKeyListener(fBracketInserter);
1459
1460     //    if (fPropertyChangeListener != null) {
1461     //      Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1462     //      preferences.removePropertyChangeListener(fPropertyChangeListener);
1463     //      fPropertyChangeListener = null;
1464     //    }
1465
1466     if (fJavaEditorErrorTickUpdater != null) {
1467       fJavaEditorErrorTickUpdater.dispose();
1468       fJavaEditorErrorTickUpdater = null;
1469     }
1470
1471     //    if (fSelectionHistory != null)
1472     //      fSelectionHistory.dispose();
1473
1474     //    if (fPaintManager != null) {
1475     //      fPaintManager.dispose();
1476     //      fPaintManager = null;
1477     //    }
1478
1479     if (fActionGroups != null) {
1480       fActionGroups.dispose();
1481       fActionGroups = null;
1482     }
1483
1484     super.dispose();
1485   }
1486
1487   //  protected AnnotationType getAnnotationType(String preferenceKey) {
1488   //    Iterator e = ANNOTATION_MAP.keySet().iterator();
1489   //    while (e.hasNext()) {
1490   //      AnnotationType type = (AnnotationType) e.next();
1491   //      AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1492   //      if (info != null) {
1493   //        if (preferenceKey.equals(info.fColorPreference)
1494   //          || preferenceKey.equals(info.fEditorPreference)
1495   //          || preferenceKey.equals(info.fOverviewRulerPreference))
1496   //          return type;
1497   //      }
1498   //    }
1499   //    return null;
1500   //  }
1501
1502   /*
1503    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1504    */
1505   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1506
1507     try {
1508
1509       AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1510       if (asv != null) {
1511
1512         String p = event.getProperty();
1513
1514         if (CLOSE_BRACKETS_PHP.equals(p)) {
1515           fBracketInserter.setCloseBracketsPHPEnabled(getPreferenceStore().getBoolean(p));
1516           return;
1517         }
1518
1519         if (CLOSE_STRINGS_PHP.equals(p)) {
1520           fBracketInserter.setCloseStringsPHPEnabled(getPreferenceStore().getBoolean(p));
1521           return;
1522         }
1523
1524         if (CLOSE_BRACKETS_HTML.equals(p)) {
1525           fBracketInserter.setCloseBracketsHTMLEnabled(getPreferenceStore().getBoolean(p));
1526           return;
1527         }
1528
1529         if (CLOSE_STRINGS_HTML.equals(p)) {
1530           fBracketInserter.setCloseStringsHTMLEnabled(getPreferenceStore().getBoolean(p));
1531           return;
1532         }
1533
1534         if (SPACES_FOR_TABS.equals(p)) {
1535           if (isTabConversionEnabled())
1536             startTabConversion();
1537           else
1538             stopTabConversion();
1539           return;
1540         }
1541
1542         if (MATCHING_BRACKETS.equals(p)) {
1543           if (isBracketHighlightingEnabled())
1544             startBracketHighlighting();
1545           else
1546             stopBracketHighlighting();
1547           return;
1548         }
1549
1550         if (MATCHING_BRACKETS_COLOR.equals(p)) {
1551           if (fBracketPainter != null)
1552             fBracketPainter.setHighlightColor(getColor(MATCHING_BRACKETS_COLOR));
1553           return;
1554         }
1555
1556         if (CURRENT_LINE.equals(p)) {
1557           if (isLineHighlightingEnabled())
1558             startLineHighlighting();
1559           else
1560             stopLineHighlighting();
1561           return;
1562         }
1563
1564         if (CURRENT_LINE_COLOR.equals(p)) {
1565           if (fLinePainter != null) {
1566             stopLineHighlighting();
1567             startLineHighlighting();
1568           }
1569           return;
1570         }
1571
1572         if (PRINT_MARGIN.equals(p)) {
1573           if (isPrintMarginVisible())
1574             showPrintMargin();
1575           else
1576             hidePrintMargin();
1577           return;
1578         }
1579
1580         if (PRINT_MARGIN_COLOR.equals(p)) {
1581           if (fPrintMarginPainter != null)
1582             fPrintMarginPainter.setMarginRulerColor(getColor(PRINT_MARGIN_COLOR));
1583           return;
1584         }
1585
1586         if (PRINT_MARGIN_COLUMN.equals(p)) {
1587           if (fPrintMarginPainter != null)
1588             fPrintMarginPainter.setMarginRulerColumn(getPreferenceStore().getInt(PRINT_MARGIN_COLUMN));
1589           return;
1590         }
1591
1592         //        if (OVERVIEW_RULER.equals(p)) {
1593         //          if (isOverviewRulerVisible())
1594         //            showOverviewRuler();
1595         //          else
1596         //            hideOverviewRuler();
1597         //          return;
1598         //        }
1599
1600         //        AnnotationType type = getAnnotationType(p);
1601         //        if (type != null) {
1602         //
1603         //          AnnotationInfo info = (AnnotationInfo) ANNOTATION_MAP.get(type);
1604         //          if (info.fColorPreference.equals(p)) {
1605         //            Color color = getColor(type);
1606         //            if (fProblemPainter != null) {
1607         //              fProblemPainter.setColor(type, color);
1608         //              fProblemPainter.paint(IPainter.CONFIGURATION);
1609         //            }
1610         //            setColorInOverviewRuler(type, color);
1611         //            return;
1612         //          }
1613         //
1614         //          if (info.fEditorPreference.equals(p)) {
1615         //            if (isAnnotationIndicationEnabled(type))
1616         //              startAnnotationIndication(type);
1617         //            else
1618         //              stopAnnotationIndication(type);
1619         //            return;
1620         //          }
1621         //
1622         //          if (info.fOverviewRulerPreference.equals(p)) {
1623         //            if (isAnnotationIndicationInOverviewRulerEnabled(type))
1624         //              showAnnotationIndicationInOverviewRuler(type, true);
1625         //            else
1626         //              showAnnotationIndicationInOverviewRuler(type, false);
1627         //            return;
1628         //          }
1629         //        }
1630
1631         IContentAssistant c = asv.getContentAssistant();
1632         if (c instanceof ContentAssistant)
1633           ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
1634       }
1635
1636     } finally {
1637       super.handlePreferenceStoreChanged(event);
1638     }
1639   }
1640
1641   /*
1642          * @see org.eclipse.jdt.internal.ui.javaeditor.JavaEditor#handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
1643          */
1644   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1645     AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1646     if (asv != null) {
1647       String p = event.getProperty();
1648       if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1649         asv.updateIndentationPrefixes();
1650         if (fTabConverter != null)
1651           fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1652       }
1653     }
1654     super.handlePreferencePropertyChanged(event);
1655   }
1656
1657   /**
1658    * Handles a property change event describing a change
1659    * of the php core's preferences and updates the preference
1660    * related editor properties.
1661    * 
1662    * @param event the property change event
1663    */
1664   //  protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1665   //    AdaptedSourceViewer asv = (AdaptedSourceViewer) getSourceViewer();
1666   //    if (asv != null) {
1667   //      String p = event.getProperty();
1668   //      if (CODE_FORMATTER_TAB_SIZE.equals(p)) {
1669   //        asv.updateIndentationPrefixes();
1670   //        if (fTabConverter != null)
1671   //          fTabConverter.setNumberOfSpacesPerTab(getTabSize());
1672   //      }
1673   //    }
1674   //  }
1675
1676   /*
1677    * @see PHPEditor#createJavaSourceViewer(Composite, IVerticalRuler, int)
1678    */
1679   protected ISourceViewer createJavaSourceViewer(
1680     Composite parent,
1681     IVerticalRuler verticalRuler,
1682     IOverviewRuler overviewRuler,
1683     boolean isOverviewRulerVisible,
1684     int styles) {
1685     return new AdaptedSourceViewer(parent, verticalRuler, overviewRuler, isOverviewRulerVisible, styles);
1686   }
1687   //  protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
1688   //    return new AdaptedSourceViewer(parent, ruler, styles);
1689   //  }
1690
1691   private boolean isValidSelection(int offset, int length) {
1692     IDocumentProvider provider = getDocumentProvider();
1693     if (provider != null) {
1694       IDocument document = provider.getDocument(getEditorInput());
1695       if (document != null) {
1696         int end = offset + length;
1697         int documentLength = document.getLength();
1698         return 0 <= offset && offset <= documentLength && 0 <= end && end <= documentLength;
1699       }
1700     }
1701     return false;
1702   }
1703
1704   /*
1705    * @see AbstractTextEditor#canHandleMove(IEditorInput, IEditorInput)
1706    */
1707   protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
1708
1709     String oldExtension = ""; //$NON-NLS-1$
1710     if (originalElement instanceof IFileEditorInput) {
1711       IFile file = ((IFileEditorInput) originalElement).getFile();
1712       if (file != null) {
1713         String ext = file.getFileExtension();
1714         if (ext != null)
1715           oldExtension = ext;
1716       }
1717     }
1718
1719     String newExtension = ""; //$NON-NLS-1$
1720     if (movedElement instanceof IFileEditorInput) {
1721       IFile file = ((IFileEditorInput) movedElement).getFile();
1722       if (file != null)
1723         newExtension = file.getFileExtension();
1724     }
1725
1726     return oldExtension.equals(newExtension);
1727   }
1728
1729   /*
1730    * @see AbstractTextEditor#editorContextMenuAboutToShow(IMenuManager)
1731    */
1732   public void editorContextMenuAboutToShow(IMenuManager menu) {
1733     super.editorContextMenuAboutToShow(menu);
1734
1735     ActionContext context = new ActionContext(getSelectionProvider().getSelection());
1736     fContextMenuGroup.setContext(context);
1737     fContextMenuGroup.fillContextMenu(menu);
1738     fContextMenuGroup.setContext(null);
1739   }
1740
1741   /*
1742    * @see JavaEditor#setOutlinePageInput(JavaOutlinePage, IEditorInput)
1743    */
1744   protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input) {
1745     if (page != null) {
1746       IWorkingCopyManager manager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
1747       page.setInput(manager.getWorkingCopy(input));
1748     }
1749   }
1750
1751   /*
1752    * @see AbstractTextEditor#performSaveOperation(WorkspaceModifyOperation, IProgressMonitor)
1753    */
1754 //  protected void performSaveOperation(WorkspaceModifyOperation operation, IProgressMonitor progressMonitor) {
1755 //    IDocumentProvider p = getDocumentProvider();
1756 //    if (p instanceof PHPDocumentProvider) {
1757 //      PHPDocumentProvider cp = (PHPDocumentProvider) p;
1758 //      cp.setSavePolicy(fSavePolicy);
1759 //    }
1760 //
1761 //    try {
1762 //      super.performSaveOperation(operation, progressMonitor);
1763 //    } finally {
1764 //      if (p instanceof PHPDocumentProvider) {
1765 //        PHPDocumentProvider cp = (PHPDocumentProvider) p;
1766 //        cp.setSavePolicy(null);
1767 //      }
1768 //    }
1769 //  }
1770   
1771   /*
1772    * @see org.eclipse.ui.texteditor.AbstractTextEditor#performSave(boolean, org.eclipse.core.runtime.IProgressMonitor)
1773    */
1774   protected void performSave(boolean overwrite, IProgressMonitor progressMonitor) {
1775     IDocumentProvider p= getDocumentProvider();
1776     if (p instanceof PHPDocumentProvider) {
1777       PHPDocumentProvider cp= (PHPDocumentProvider) p;
1778       cp.setSavePolicy(fSavePolicy);
1779     }
1780     try {
1781       super.performSave(overwrite, progressMonitor);
1782     } finally {
1783       if (p instanceof PHPDocumentProvider) {
1784         PHPDocumentProvider cp= (PHPDocumentProvider) p;
1785         cp.setSavePolicy(null);
1786       }
1787     }
1788   }
1789   /*
1790    * @see AbstractTextEditor#doSaveAs
1791    */
1792   public void doSaveAs() {
1793     if (askIfNonWorkbenchEncodingIsOk()) {
1794       super.doSaveAs();
1795     }
1796   }
1797
1798   /*
1799          * @see AbstractTextEditor#doSave(IProgressMonitor)
1800          */
1801   public void doSave(IProgressMonitor progressMonitor) {
1802
1803     IDocumentProvider p = getDocumentProvider();
1804     if (p == null) {
1805       // editor has been closed
1806       return;
1807     }
1808
1809     if (!askIfNonWorkbenchEncodingIsOk()) {
1810       progressMonitor.setCanceled(true);
1811       return;
1812     }
1813
1814     if (p.isDeleted(getEditorInput())) {
1815
1816       if (isSaveAsAllowed()) {
1817
1818         /*
1819          * 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
1820          * Changed Behavior to make sure that if called inside a regular save (because
1821          * of deletion of input element) there is a way to report back to the caller.
1822          */
1823         //                                       performSaveAs(progressMonitor);
1824         super.doSave(progressMonitor);
1825       } else {
1826
1827         /* 
1828          * 1GF5YOX: ITPJUI:ALL - Save of delete file claims it's still there
1829          * Missing resources.
1830          */
1831         Shell shell = getSite().getShell();
1832         MessageDialog.openError(shell, PHPEditorMessages.getString("PHPUnitEditor.error.saving.title1"), PHPEditorMessages.getString("PHPUnitEditor.error.saving.message1")); //$NON-NLS-1$ //$NON-NLS-2$
1833       }
1834
1835     } else {
1836
1837       setStatusLineErrorMessage(null);
1838       super.doSave(progressMonitor);
1839
1840       //                                IWorkingCopyManager manager= JavaPlugin.getDefault().getWorkingCopyManager();
1841       //                                ICompilationUnit unit= manager.getWorkingCopy(getEditorInput());
1842       //                        
1843       //                                if (unit != null) {
1844       //                                        synchronized (unit) { 
1845       //                                                performSaveOperation(createSaveOperation(false), progressMonitor); 
1846       //                                        }
1847       //                                } else 
1848       //                                        performSaveOperation(createSaveOperation(false), progressMonitor);
1849     }
1850   }
1851   /**
1852    * Asks the user if it is ok to store in non-workbench encoding.
1853    * @return <true> if the user wants to continue
1854    */
1855   private boolean askIfNonWorkbenchEncodingIsOk() {
1856     IDocumentProvider provider = getDocumentProvider();
1857     if (provider instanceof IStorageDocumentProvider) {
1858       IEditorInput input = getEditorInput();
1859       IStorageDocumentProvider storageProvider = (IStorageDocumentProvider) provider;
1860       String encoding = storageProvider.getEncoding(input);
1861       String defaultEncoding = storageProvider.getDefaultEncoding();
1862       if (encoding != null && !encoding.equals(defaultEncoding)) {
1863         Shell shell = getSite().getShell();
1864         String title = PHPEditorMessages.getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.title"); //$NON-NLS-1$
1865         String msg;
1866         if (input != null)
1867           msg = MessageFormat.format(PHPEditorMessages.getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message1"), new String[] { input.getName(), encoding }); //$NON-NLS-1$
1868         else
1869           msg = MessageFormat.format(PHPEditorMessages.getString("PHPUnitEditor.warning.save.nonWorkbenchEncoding.message2"), new String[] { encoding }); //$NON-NLS-1$
1870         return MessageDialog.openQuestion(shell, title, msg);
1871       }
1872     }
1873     return true;
1874   }
1875   /*
1876          * @see IReconcilingParticipant#reconciled()
1877          */
1878   public void reconciled() {
1879     if (synchronizeOutlineOnCursorMove()) {
1880       Shell shell = getSite().getShell();
1881       if (shell != null && !shell.isDisposed()) {
1882         shell.getDisplay().asyncExec(new Runnable() {
1883           public void run() {
1884             synchronizeOutlinePageSelection();
1885           }
1886         });
1887       }
1888     }
1889   }
1890
1891   private boolean synchronizeOutlineOnCursorMove() {
1892     return PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE);
1893   }
1894   protected void updateStateDependentActions() {
1895     super.updateStateDependentActions();
1896     fGenerateActionGroup.editorStateChanged();
1897   }
1898
1899   /**
1900    * Returns the updated java element for the old java element.
1901    */
1902   private IJavaElement findElement(IJavaElement element) {
1903
1904     if (element == null)
1905       return null;
1906
1907     IWorkingCopyManager manager = PHPeclipsePlugin.getDefault().getWorkingCopyManager();
1908     ICompilationUnit unit = manager.getWorkingCopy(getEditorInput());
1909
1910     if (unit != null) {
1911       try {
1912
1913         synchronized (unit) {
1914           unit.reconcile();
1915         }
1916         IJavaElement[] findings = unit.findElements(element);
1917         if (findings != null && findings.length > 0)
1918           return findings[0];
1919
1920       } catch (JavaModelException x) {
1921         PHPeclipsePlugin.log(x.getStatus());
1922         // nothing found, be tolerant and go on
1923       }
1924     }
1925
1926     return null;
1927   }
1928
1929   /**
1930    * Returns the offset of the given Java element.
1931    */
1932   private int getOffset(IJavaElement element) {
1933     if (element instanceof ISourceReference) {
1934       ISourceReference sr = (ISourceReference) element;
1935       try {
1936         ISourceRange srcRange = sr.getSourceRange();
1937         if (srcRange != null)
1938           return srcRange.getOffset();
1939       } catch (JavaModelException e) {
1940       }
1941     }
1942     return -1;
1943   }
1944
1945   /*
1946    * @see AbstractTextEditor#rememberSelection()
1947    */
1948   protected void rememberSelection() {
1949     ISelectionProvider sp = getSelectionProvider();
1950     fRememberedSelection = (sp == null ? null : (ITextSelection) sp.getSelection());
1951     if (fRememberedSelection != null) {
1952       fRememberedElement = getElementAt(fRememberedSelection.getOffset(), true);
1953       fRememberedElementOffset = getOffset(fRememberedElement);
1954     }
1955   }
1956
1957   /*
1958    * @see AbstractTextEditor#restoreSelection()
1959    */
1960   protected void restoreSelection() {
1961
1962     try {
1963
1964       if (getSourceViewer() == null || fRememberedSelection == null)
1965         return;
1966
1967       IJavaElement newElement = findElement(fRememberedElement);
1968       int newOffset = getOffset(newElement);
1969       int delta = (newOffset > -1 && fRememberedElementOffset > -1) ? newOffset - fRememberedElementOffset : 0;
1970       if (isValidSelection(delta + fRememberedSelection.getOffset(), fRememberedSelection.getLength()))
1971         selectAndReveal(delta + fRememberedSelection.getOffset(), fRememberedSelection.getLength());
1972
1973     } finally {
1974       fRememberedSelection = null;
1975       fRememberedElement = null;
1976       fRememberedElementOffset = -1;
1977     }
1978   }
1979
1980 }