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