added file extension php5
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 /**********************************************************************
4 Copyright (c) 2000, 2002 IBM Corp. and others.
5 All rights reserved. This program and the accompanying materials
6 are made available under the terms of the Common Public License v1.0
7 which accompanies this distribution, and is available at
8 http://www.eclipse.org/legal/cpl-v10.html
9
10 Contributors:
11     IBM Corporation - Initial implementation
12     Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.ResourceBundle;
20 import java.util.StringTokenizer;
21
22 import net.sourceforge.phpdt.core.ICompilationUnit;
23 import net.sourceforge.phpdt.core.IJavaElement;
24 import net.sourceforge.phpdt.core.IJavaProject;
25 import net.sourceforge.phpdt.core.IMember;
26 import net.sourceforge.phpdt.core.ISourceRange;
27 import net.sourceforge.phpdt.core.ISourceReference;
28 import net.sourceforge.phpdt.core.JavaCore;
29 import net.sourceforge.phpdt.core.JavaModelException;
30 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
31 import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup;
32 import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl;
33 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
34 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
35 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
36 import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
37 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
38 import net.sourceforge.phpdt.ui.IContextMenuConstants;
39 import net.sourceforge.phpdt.ui.JavaUI;
40 import net.sourceforge.phpdt.ui.PreferenceConstants;
41 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
42 import net.sourceforge.phpdt.ui.text.JavaTextTools;
43 import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
44 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
45
46 import org.eclipse.core.resources.IMarker;
47 import org.eclipse.core.resources.IResource;
48 import org.eclipse.core.runtime.CoreException;
49 import org.eclipse.core.runtime.IProgressMonitor;
50 import org.eclipse.core.runtime.IStatus;
51 import org.eclipse.core.runtime.Preferences;
52 import org.eclipse.core.runtime.Status;
53 import org.eclipse.core.runtime.jobs.Job;
54 import org.eclipse.jface.action.Action;
55 import org.eclipse.jface.action.GroupMarker;
56 import org.eclipse.jface.action.IAction;
57 import org.eclipse.jface.action.MenuManager;
58 import org.eclipse.jface.action.Separator;
59 import org.eclipse.jface.preference.IPreferenceStore;
60 import org.eclipse.jface.preference.PreferenceConverter;
61 import org.eclipse.jface.text.BadLocationException;
62 import org.eclipse.jface.text.DefaultInformationControl;
63 import org.eclipse.jface.text.DocumentEvent;
64 import org.eclipse.jface.text.IDocument;
65 import org.eclipse.jface.text.IDocumentListener;
66 import org.eclipse.jface.text.IInformationControl;
67 import org.eclipse.jface.text.IInformationControlCreator;
68 import org.eclipse.jface.text.IRegion;
69 import org.eclipse.jface.text.ITextHover;
70 import org.eclipse.jface.text.ITextInputListener;
71 import org.eclipse.jface.text.ITextSelection;
72 import org.eclipse.jface.text.ITextViewer;
73 import org.eclipse.jface.text.ITextViewerExtension2;
74 import org.eclipse.jface.text.ITextViewerExtension3;
75 import org.eclipse.jface.text.ITypedRegion;
76 import org.eclipse.jface.text.Position;
77 import org.eclipse.jface.text.Region;
78 import org.eclipse.jface.text.TextSelection;
79 import org.eclipse.jface.text.information.IInformationProvider;
80 import org.eclipse.jface.text.information.InformationPresenter;
81 import org.eclipse.jface.text.source.Annotation;
82 import org.eclipse.jface.text.source.IAnnotationModel;
83 import org.eclipse.jface.text.source.IAnnotationModelExtension;
84 import org.eclipse.jface.text.source.IOverviewRuler;
85 import org.eclipse.jface.text.source.ISourceViewer;
86 import org.eclipse.jface.text.source.IVerticalRuler;
87 import org.eclipse.jface.text.source.OverviewRuler;
88 import org.eclipse.jface.text.source.SourceViewerConfiguration;
89 import org.eclipse.jface.text.source.projection.ProjectionSupport;
90 import org.eclipse.jface.text.source.projection.ProjectionViewer;
91 import org.eclipse.jface.util.IPropertyChangeListener;
92 import org.eclipse.jface.util.ListenerList;
93 import org.eclipse.jface.util.PropertyChangeEvent;
94 import org.eclipse.jface.viewers.ISelection;
95 import org.eclipse.jface.viewers.ISelectionChangedListener;
96 import org.eclipse.jface.viewers.ISelectionProvider;
97 import org.eclipse.jface.viewers.IStructuredSelection;
98 import org.eclipse.jface.viewers.SelectionChangedEvent;
99 import org.eclipse.jface.viewers.StructuredSelection;
100 import org.eclipse.swt.SWT;
101 import org.eclipse.swt.custom.BidiSegmentEvent;
102 import org.eclipse.swt.custom.BidiSegmentListener;
103 import org.eclipse.swt.custom.StyleRange;
104 import org.eclipse.swt.custom.StyledText;
105 import org.eclipse.swt.events.FocusEvent;
106 import org.eclipse.swt.events.FocusListener;
107 import org.eclipse.swt.events.KeyEvent;
108 import org.eclipse.swt.events.KeyListener;
109 import org.eclipse.swt.events.MouseEvent;
110 import org.eclipse.swt.events.MouseListener;
111 import org.eclipse.swt.events.MouseMoveListener;
112 import org.eclipse.swt.events.PaintEvent;
113 import org.eclipse.swt.events.PaintListener;
114 import org.eclipse.swt.graphics.Color;
115 import org.eclipse.swt.graphics.Cursor;
116 import org.eclipse.swt.graphics.GC;
117 import org.eclipse.swt.graphics.Image;
118 import org.eclipse.swt.graphics.Point;
119 import org.eclipse.swt.graphics.RGB;
120 import org.eclipse.swt.widgets.Composite;
121 import org.eclipse.swt.widgets.Control;
122 import org.eclipse.swt.widgets.Display;
123 import org.eclipse.swt.widgets.Shell;
124 import org.eclipse.ui.IEditorInput;
125 import org.eclipse.ui.IPageLayout;
126 import org.eclipse.ui.IPartService;
127 import org.eclipse.ui.IViewPart;
128 import org.eclipse.ui.IWorkbenchPage;
129 import org.eclipse.ui.IWorkbenchPart;
130 import org.eclipse.ui.IWorkbenchWindow;
131 import org.eclipse.ui.actions.ActionContext;
132 import org.eclipse.ui.actions.ActionGroup;
133 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
134 import org.eclipse.ui.editors.text.EditorsUI;
135 import org.eclipse.ui.editors.text.IEncodingSupport;
136 import org.eclipse.ui.part.IShowInTargetList;
137 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
138 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
139 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
140 import org.eclipse.ui.texteditor.IDocumentProvider;
141 import org.eclipse.ui.texteditor.IEditorStatusLine;
142 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
143 import org.eclipse.ui.texteditor.MarkerAnnotation;
144 import org.eclipse.ui.texteditor.ResourceAction;
145 import org.eclipse.ui.texteditor.TextEditorAction;
146 import org.eclipse.ui.texteditor.TextOperationAction;
147 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
148 import org.eclipse.ui.views.tasklist.TaskList;
149
150 /**
151  * PHP specific text editor.
152  */
153 public abstract class PHPEditor  extends AbstractDecoratedTextEditor implements IViewPartInputProvider {
154 //extends StatusTextEditor implements IViewPartInputProvider { // extends TextEditor {
155   /**
156          * "Smart" runnable for updating the outline page's selection.
157          */
158   class OutlinePageSelectionUpdater implements Runnable {
159
160     /** Has the runnable already been posted? */
161     private boolean fPosted = false;
162
163     public OutlinePageSelectionUpdater() {
164     }
165
166     /*
167      * @see Runnable#run()
168      */
169     public void run() {
170       synchronizeOutlinePageSelection();
171       fPosted = false;
172     }
173
174     /**
175      * Posts this runnable into the event queue.
176      */
177     public void post() {
178       if (fPosted)
179         return;
180
181       Shell shell = getSite().getShell();
182       if (shell != null & !shell.isDisposed()) {
183         fPosted = true;
184         shell.getDisplay().asyncExec(this);
185       }
186     }
187   };
188   class SelectionChangedListener implements ISelectionChangedListener {
189     public void selectionChanged(SelectionChangedEvent event) {
190       doSelectionChanged(event);
191     }
192   };
193
194   /**
195          * Adapts an options {@link java.util.Map} to {@link org.eclipse.jface.preference.IPreferenceStore}.
196          * <p>
197          * This preference store is read-only i.e. write access
198          * throws an {@link java.lang.UnsupportedOperationException}.
199          * </p>
200          * 
201          * @since 3.0
202          */
203         private static class OptionsAdapter implements IPreferenceStore {
204
205
206                 /**
207                  * A property change event filter.
208                  */
209                 public interface IPropertyChangeEventFilter {
210
211                         /**
212                          * Should the given event be filtered?
213                          * @param event The property change event.
214                          * @return <code>true</code> iff the given event should be filtered.
215                          */
216                         public boolean isFiltered(PropertyChangeEvent event);
217
218                 }
219                 /**
220                  * Property change listener. Listens for events in the options Map and
221                  * fires a {@link org.eclipse.jface.util.PropertyChangeEvent}
222                  * on this adapter with arguments from the received event.
223                  */
224                 private class PropertyChangeListener implements IPropertyChangeListener {
225
226                         /**
227                          * {@inheritDoc}
228                          */
229                         public void propertyChange(PropertyChangeEvent event) {
230                                 if (getFilter().isFiltered(event))
231                                         return;
232                                 
233                                 if (event.getNewValue() == null)
234                                         fOptions.remove(event.getProperty());
235                                 else
236                                         fOptions.put(event.getProperty(), event.getNewValue());
237                                 
238                                 firePropertyChangeEvent(event.getProperty(), event.getOldValue(), event.getNewValue());
239                         }
240                 }
241
242                 /** Listeners on this adapter */
243                 private ListenerList fListeners= new ListenerList();
244
245                 /** Listener on the adapted options Map */
246                 private IPropertyChangeListener fListener= new PropertyChangeListener();
247
248                 /** Adapted options Map */
249                 private Map fOptions;
250
251                 /** Preference store through which events are received. */
252                 private IPreferenceStore fMockupPreferenceStore;
253
254                 /** Property event filter. */
255                 private IPropertyChangeEventFilter fFilter;
256                 
257                 /**
258                  * Initialize with the given options.
259                  * 
260                  * @param options The options to wrap
261                  * @param mockupPreferenceStore the mock-up preference store
262                  * @param filter the property change filter
263                  */
264                 public OptionsAdapter(Map options, IPreferenceStore mockupPreferenceStore, IPropertyChangeEventFilter filter) {
265                         fMockupPreferenceStore= mockupPreferenceStore;
266                         fOptions= options;
267                         setFilter(filter);
268                 }
269
270                 /**
271                  * {@inheritDoc}
272                  */
273                 public void addPropertyChangeListener(IPropertyChangeListener listener) {
274                         if (fListeners.size() == 0)
275                                 fMockupPreferenceStore.addPropertyChangeListener(fListener);
276                         fListeners.add(listener);
277                 }
278
279                 /**
280                  * {@inheritDoc}
281                  */
282                 public void removePropertyChangeListener(IPropertyChangeListener listener) {
283                         fListeners.remove(listener);
284                         if (fListeners.size() == 0)
285                                 fMockupPreferenceStore.removePropertyChangeListener(fListener);
286                 }
287
288                 /**
289                  * {@inheritDoc}
290                  */
291                 public boolean contains(String name) {
292                         return fOptions.containsKey(name);
293                 }
294
295                 /**
296                  * {@inheritDoc}
297                  */
298                 public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
299                         PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue);
300                         Object[] listeners= fListeners.getListeners();
301                         for (int i= 0; i < listeners.length; i++)
302                                 ((IPropertyChangeListener) listeners[i]).propertyChange(event);
303                 }
304
305                 /**
306                  * {@inheritDoc}
307                  */
308                 public boolean getBoolean(String name) {
309                         boolean value= BOOLEAN_DEFAULT_DEFAULT;
310                         String s= (String) fOptions.get(name);
311                         if (s != null)
312                                 value= s.equals(TRUE);
313                         return value;
314                 }
315
316                 /**
317                  * {@inheritDoc}
318                  */
319                 public boolean getDefaultBoolean(String name) {
320                         return BOOLEAN_DEFAULT_DEFAULT;
321                 }
322
323                 /**
324                  * {@inheritDoc}
325                  */
326                 public double getDefaultDouble(String name) {
327                         return DOUBLE_DEFAULT_DEFAULT;
328                 }
329
330                 /**
331                  * {@inheritDoc}
332                  */
333                 public float getDefaultFloat(String name) {
334                         return FLOAT_DEFAULT_DEFAULT;
335                 }
336
337                 /**
338                  * {@inheritDoc}
339                  */
340                 public int getDefaultInt(String name) {
341                         return INT_DEFAULT_DEFAULT;
342                 }
343
344                 /**
345                  * {@inheritDoc}
346                  */
347                 public long getDefaultLong(String name) {
348                         return LONG_DEFAULT_DEFAULT;
349                 }
350
351                 /**
352                  * {@inheritDoc}
353                  */
354                 public String getDefaultString(String name) {
355                         return STRING_DEFAULT_DEFAULT;
356                 }
357
358                 /**
359                  * {@inheritDoc}
360                  */
361                 public double getDouble(String name) {
362                         double value= DOUBLE_DEFAULT_DEFAULT;
363                         String s= (String) fOptions.get(name);
364                         if (s != null) {
365                                 try {
366                                         value= new Double(s).doubleValue();
367                                 } catch (NumberFormatException e) {
368                                 }
369                         }
370                         return value;
371                 }
372
373                 /**
374                  * {@inheritDoc}
375                  */
376                 public float getFloat(String name) {
377                         float value= FLOAT_DEFAULT_DEFAULT;
378                         String s= (String) fOptions.get(name);
379                         if (s != null) {
380                                 try {
381                                         value= new Float(s).floatValue();
382                                 } catch (NumberFormatException e) {
383                                 }
384                         }
385                         return value;
386                 }
387
388                 /**
389                  * {@inheritDoc}
390                  */
391                 public int getInt(String name) {
392                         int value= INT_DEFAULT_DEFAULT;
393                         String s= (String) fOptions.get(name);
394                         if (s != null) {
395                                 try {
396                                         value= new Integer(s).intValue();
397                                 } catch (NumberFormatException e) {
398                                 }
399                         }
400                         return value;
401                 }
402
403                 /**
404                  * {@inheritDoc}
405                  */
406                 public long getLong(String name) {
407                         long value= LONG_DEFAULT_DEFAULT;
408                         String s= (String) fOptions.get(name);
409                         if (s != null) {
410                                 try {
411                                         value= new Long(s).longValue();
412                                 } catch (NumberFormatException e) {
413                                 }
414                         }
415                         return value;
416                 }
417
418                 /**
419                  * {@inheritDoc}
420                  */
421                 public String getString(String name) {
422                         String value= (String) fOptions.get(name);
423                         if (value == null)
424                                 value= STRING_DEFAULT_DEFAULT;
425                         return value;
426                 }
427
428                 /**
429                  * {@inheritDoc}
430                  */
431                 public boolean isDefault(String name) {
432                         return false;
433                 }
434
435                 /**
436                  * {@inheritDoc}
437                  */
438                 public boolean needsSaving() {
439                         return !fOptions.isEmpty();
440                 }
441
442                 /**
443                  * {@inheritDoc}
444                  */
445                 public void putValue(String name, String value) {
446                         throw new UnsupportedOperationException();
447                 }
448
449                 /**
450                  * {@inheritDoc}
451                  */
452                 public void setDefault(String name, double value) {
453                         throw new UnsupportedOperationException();
454                 }
455
456                 /**
457                  * {@inheritDoc}
458                  */
459                 public void setDefault(String name, float value) {
460                         throw new UnsupportedOperationException();
461                 }
462
463                 /**
464                  * {@inheritDoc}
465                  */
466                 public void setDefault(String name, int value) {
467                         throw new UnsupportedOperationException();
468                 }
469
470                 /**
471                  * {@inheritDoc}
472                  */
473                 public void setDefault(String name, long value) {
474                         throw new UnsupportedOperationException();
475                 }
476
477                 /**
478                  * {@inheritDoc}
479                  */
480                 public void setDefault(String name, String defaultObject) {
481                         throw new UnsupportedOperationException();
482                 }
483
484                 /**
485                  * {@inheritDoc}
486                  */
487                 public void setDefault(String name, boolean value) {
488                         throw new UnsupportedOperationException();
489                 }
490
491                 /**
492                  * {@inheritDoc}
493                  */
494                 public void setToDefault(String name) {
495                         throw new UnsupportedOperationException();
496                 }
497
498                 /**
499                  * {@inheritDoc}
500                  */
501                 public void setValue(String name, double value) {
502                         throw new UnsupportedOperationException();
503                 }
504
505                 /**
506                  * {@inheritDoc}
507                  */
508                 public void setValue(String name, float value) {
509                         throw new UnsupportedOperationException();
510                 }
511
512                 /**
513                  * {@inheritDoc}
514                  */
515                 public void setValue(String name, int value) {
516                         throw new UnsupportedOperationException();
517                 }
518
519                 /**
520                  * {@inheritDoc}
521                  */
522                 public void setValue(String name, long value) {
523                         throw new UnsupportedOperationException();
524                 }
525
526                 /**
527                  * {@inheritDoc}
528                  */
529                 public void setValue(String name, String value) {
530                         throw new UnsupportedOperationException();
531                 }
532
533                 /**
534                  * {@inheritDoc}
535                  */
536                 public void setValue(String name, boolean value) {
537                         throw new UnsupportedOperationException();
538                 }
539
540                 /**
541                  * Returns the adapted options Map.
542                  * 
543                  * @return Returns the adapted options Map.
544                  */
545                 public Map getOptions() {
546                         return fOptions;
547                 }
548
549                 /**
550                  * Returns the mock-up preference store, events are received through this preference store.
551                  * @return Returns the mock-up preference store.
552                  */
553                 public IPreferenceStore getMockupPreferenceStore() {
554                         return fMockupPreferenceStore;
555                 }
556
557                 /**
558                  * Set the event filter to the given filter.
559                  * 
560                  * @param filter The new filter.
561                  */
562                 public void setFilter(IPropertyChangeEventFilter filter) {
563                         fFilter= filter;
564                 }
565                 
566                 /**
567                  * Returns the event filter.
568                  * 
569                  * @return The event filter.
570                  */
571                 public IPropertyChangeEventFilter getFilter() {
572                         return fFilter;
573                 }
574         }
575   /*
576   * Link mode.  
577   */
578   class MouseClickListener
579     implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener, IPropertyChangeListener, IDocumentListener, ITextInputListener {
580
581     /** The session is active. */
582     private boolean fActive;
583
584     /** The currently active style range. */
585     private IRegion fActiveRegion;
586     /** The currently active style range as position. */
587     private Position fRememberedPosition;
588     /** The hand cursor. */
589     private Cursor fCursor;
590
591     /** The link color. */
592     private Color fColor;
593     /** The key modifier mask. */
594     private int fKeyModifierMask;
595
596     public void deactivate() {
597       deactivate(false);
598     }
599
600     public void deactivate(boolean redrawAll) {
601       if (!fActive)
602         return;
603
604       repairRepresentation(redrawAll);
605       fActive = false;
606     }
607
608     public void install() {
609
610       ISourceViewer sourceViewer = getSourceViewer();
611       if (sourceViewer == null)
612         return;
613
614       StyledText text = sourceViewer.getTextWidget();
615       if (text == null || text.isDisposed())
616         return;
617
618       updateColor(sourceViewer);
619
620       sourceViewer.addTextInputListener(this);
621
622       IDocument document = sourceViewer.getDocument();
623       if (document != null)
624         document.addDocumentListener(this);
625
626       text.addKeyListener(this);
627       text.addMouseListener(this);
628       text.addMouseMoveListener(this);
629       text.addFocusListener(this);
630       text.addPaintListener(this);
631
632       updateKeyModifierMask();
633
634       IPreferenceStore preferenceStore = getPreferenceStore();
635       preferenceStore.addPropertyChangeListener(this);
636     }
637
638     private void updateKeyModifierMask() {
639       String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
640       fKeyModifierMask = computeStateMask(modifiers);
641       if (fKeyModifierMask == -1) {
642         // Fallback to stored state mask
643         fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
644       };
645     }
646
647     private int computeStateMask(String modifiers) {
648       if (modifiers == null)
649         return -1;
650
651       if (modifiers.length() == 0)
652         return SWT.NONE;
653
654       int stateMask = 0;
655       StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$
656       while (modifierTokenizer.hasMoreTokens()) {
657         int modifier = EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
658         if (modifier == 0 || (stateMask & modifier) == modifier)
659           return -1;
660         stateMask = stateMask | modifier;
661       }
662       return stateMask;
663     }
664
665     public void uninstall() {
666
667       if (fColor != null) {
668         fColor.dispose();
669         fColor = null;
670       }
671
672       if (fCursor != null) {
673         fCursor.dispose();
674         fCursor = null;
675       }
676
677       ISourceViewer sourceViewer = getSourceViewer();
678       if (sourceViewer == null)
679         return;
680
681       sourceViewer.removeTextInputListener(this);
682
683       IDocument document = sourceViewer.getDocument();
684       if (document != null)
685         document.removeDocumentListener(this);
686
687       IPreferenceStore preferenceStore = getPreferenceStore();
688       if (preferenceStore != null)
689         preferenceStore.removePropertyChangeListener(this);
690
691       StyledText text = sourceViewer.getTextWidget();
692       if (text == null || text.isDisposed())
693         return;
694
695       text.removeKeyListener(this);
696       text.removeMouseListener(this);
697       text.removeMouseMoveListener(this);
698       text.removeFocusListener(this);
699       text.removePaintListener(this);
700     }
701
702     /*
703      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
704      */
705     public void propertyChange(PropertyChangeEvent event) {
706       if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
707         ISourceViewer viewer = getSourceViewer();
708         if (viewer != null)
709           updateColor(viewer);
710       } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
711         updateKeyModifierMask();
712       }
713     }
714
715     private void updateColor(ISourceViewer viewer) {
716       if (fColor != null)
717         fColor.dispose();
718
719       StyledText text = viewer.getTextWidget();
720       if (text == null || text.isDisposed())
721         return;
722
723       Display display = text.getDisplay();
724       fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display);
725     }
726
727     /**
728      * Creates a color from the information stored in the given preference store.
729      * Returns <code>null</code> if there is no such information available.
730      */
731     private Color createColor(IPreferenceStore store, String key, Display display) {
732
733       RGB rgb = null;
734
735       if (store.contains(key)) {
736
737         if (store.isDefault(key))
738           rgb = PreferenceConverter.getDefaultColor(store, key);
739         else
740           rgb = PreferenceConverter.getColor(store, key);
741
742         if (rgb != null)
743           return new Color(display, rgb);
744       }
745
746       return null;
747     }
748
749     private void repairRepresentation() {
750       repairRepresentation(false);
751     }
752
753     private void repairRepresentation(boolean redrawAll) {
754
755       if (fActiveRegion == null)
756         return;
757
758       ISourceViewer viewer = getSourceViewer();
759       if (viewer != null) {
760         resetCursor(viewer);
761
762         int offset = fActiveRegion.getOffset();
763         int length = fActiveRegion.getLength();
764
765         // remove style
766         if (!redrawAll && viewer instanceof ITextViewerExtension2)
767            ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length);
768         else
769           viewer.invalidateTextPresentation();
770
771         // remove underline                             
772         if (viewer instanceof ITextViewerExtension3) {
773           ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
774           offset = extension.modelOffset2WidgetOffset(offset);
775         } else {
776           offset -= viewer.getVisibleRegion().getOffset();
777         }
778
779         StyledText text = viewer.getTextWidget();
780         try {
781           text.redrawRange(offset, length, true);
782         } catch (IllegalArgumentException x) {
783           PHPeclipsePlugin.log(x);
784         }
785       }
786
787       fActiveRegion = null;
788     }
789
790     // will eventually be replaced by a method provided by jdt.core             
791     private IRegion selectWord(IDocument document, int anchor) {
792
793       try {
794         int offset = anchor;
795         char c;
796
797         while (offset >= 0) {
798           c = document.getChar(offset);
799           if (!Character.isJavaIdentifierPart(c))
800             break;
801           --offset;
802         }
803
804         int start = offset;
805
806         offset = anchor;
807         int length = document.getLength();
808
809         while (offset < length) {
810           c = document.getChar(offset);
811           if (!Character.isJavaIdentifierPart(c))
812             break;
813           ++offset;
814         }
815
816         int end = offset;
817
818         if (start == end)
819           return new Region(start, 0);
820         else
821           return new Region(start + 1, end - start - 1);
822
823       } catch (BadLocationException x) {
824         return null;
825       }
826     }
827
828     IRegion getCurrentTextRegion(ISourceViewer viewer) {
829
830       int offset = getCurrentTextOffset(viewer);
831       if (offset == -1)
832         return null;
833
834       return null;
835       //                                IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
836       //                                if (input == null)
837       //                                        return null;
838       //      
839       //                                try {
840       //                                
841       //                                        IJavaElement[] elements= null;
842       //                                        synchronized (input) {
843       //                                                elements= ((ICodeAssist) input).codeSelect(offset, 0);
844       //                                        }
845       //                                
846       //                                        if (elements == null || elements.length == 0)
847       //                                                return null;
848       //                                        
849       //                                        return selectWord(viewer.getDocument(), offset);
850       //                                        
851       //                                } catch (JavaModelException e) {
852       //                                        return null;    
853       //                                }
854     }
855
856     private int getCurrentTextOffset(ISourceViewer viewer) {
857
858       try {
859         StyledText text = viewer.getTextWidget();
860         if (text == null || text.isDisposed())
861           return -1;
862
863         Display display = text.getDisplay();
864         Point absolutePosition = display.getCursorLocation();
865         Point relativePosition = text.toControl(absolutePosition);
866
867         int widgetOffset = text.getOffsetAtLocation(relativePosition);
868         if (viewer instanceof ITextViewerExtension3) {
869           ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
870           return extension.widgetOffset2ModelOffset(widgetOffset);
871         } else {
872           return widgetOffset + viewer.getVisibleRegion().getOffset();
873         }
874
875       } catch (IllegalArgumentException e) {
876         return -1;
877       }
878     }
879
880     private void highlightRegion(ISourceViewer viewer, IRegion region) {
881
882       if (region.equals(fActiveRegion))
883         return;
884
885       repairRepresentation();
886
887       StyledText text = viewer.getTextWidget();
888       if (text == null || text.isDisposed())
889         return;
890
891       // highlight region
892       int offset = 0;
893       int length = 0;
894
895       if (viewer instanceof ITextViewerExtension3) {
896         ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
897         IRegion widgetRange = extension.modelRange2WidgetRange(region);
898         if (widgetRange == null)
899           return;
900
901         offset = widgetRange.getOffset();
902         length = widgetRange.getLength();
903
904       } else {
905         offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
906         length = region.getLength();
907       }
908
909       StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
910       Color foregroundColor = fColor;
911       Color backgroundColor = oldStyleRange == null ? text.getBackground() : oldStyleRange.background;
912       StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor);
913       text.setStyleRange(styleRange);
914
915       // underline
916       text.redrawRange(offset, length, true);
917
918       fActiveRegion = region;
919     }
920
921     private void activateCursor(ISourceViewer viewer) {
922       StyledText text = viewer.getTextWidget();
923       if (text == null || text.isDisposed())
924         return;
925       Display display = text.getDisplay();
926       if (fCursor == null)
927         fCursor = new Cursor(display, SWT.CURSOR_HAND);
928       text.setCursor(fCursor);
929     }
930
931     private void resetCursor(ISourceViewer viewer) {
932       StyledText text = viewer.getTextWidget();
933       if (text != null && !text.isDisposed())
934         text.setCursor(null);
935
936       if (fCursor != null) {
937         fCursor.dispose();
938         fCursor = null;
939       }
940     }
941
942     /*
943      * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
944      */
945     public void keyPressed(KeyEvent event) {
946
947       if (fActive) {
948         deactivate();
949         return;
950       }
951
952       if (event.keyCode != fKeyModifierMask) {
953         deactivate();
954         return;
955       }
956
957       fActive = true;
958
959       //                                removed for #25871                      
960       //
961       //                                ISourceViewer viewer= getSourceViewer();
962       //                                if (viewer == null)
963       //                                        return;
964       //                        
965       //                                IRegion region= getCurrentTextRegion(viewer);
966       //                                if (region == null)
967       //                                        return;
968       //                        
969       //                                highlightRegion(viewer, region);
970       //                                activateCursor(viewer);                                                                                         
971     }
972
973     /*
974      * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
975      */
976     public void keyReleased(KeyEvent event) {
977
978       if (!fActive)
979         return;
980
981       deactivate();
982     }
983
984     /*
985      * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
986      */
987     public void mouseDoubleClick(MouseEvent e) {
988     }
989     /*
990      * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
991      */
992     public void mouseDown(MouseEvent event) {
993
994       if (!fActive)
995         return;
996
997       if (event.stateMask != fKeyModifierMask) {
998         deactivate();
999         return;
1000       }
1001
1002       if (event.button != 1) {
1003         deactivate();
1004         return;
1005       }
1006     }
1007
1008     /*
1009      * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
1010      */
1011     public void mouseUp(MouseEvent e) {
1012
1013       if (!fActive)
1014         return;
1015
1016       if (e.button != 1) {
1017         deactivate();
1018         return;
1019       }
1020
1021       boolean wasActive = fCursor != null;
1022
1023       deactivate();
1024
1025       if (wasActive) {
1026         IAction action = getAction("OpenEditor"); //$NON-NLS-1$
1027         if (action != null)
1028           action.run();
1029       }
1030     }
1031
1032     /*
1033      * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
1034      */
1035     public void mouseMove(MouseEvent event) {
1036
1037       if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) {
1038         deactivate();
1039         return;
1040       }
1041
1042       if (!fActive) {
1043         if (event.stateMask != fKeyModifierMask)
1044           return;
1045         // modifier was already pressed
1046         fActive = true;
1047       }
1048
1049       ISourceViewer viewer = getSourceViewer();
1050       if (viewer == null) {
1051         deactivate();
1052         return;
1053       }
1054
1055       StyledText text = viewer.getTextWidget();
1056       if (text == null || text.isDisposed()) {
1057         deactivate();
1058         return;
1059       }
1060
1061       if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0) {
1062         deactivate();
1063         return;
1064       }
1065
1066       IRegion region = getCurrentTextRegion(viewer);
1067       if (region == null || region.getLength() == 0) {
1068         repairRepresentation();
1069         return;
1070       }
1071
1072       highlightRegion(viewer, region);
1073       activateCursor(viewer);
1074     }
1075
1076     /*
1077      * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
1078      */
1079     public void focusGained(FocusEvent e) {
1080     }
1081
1082     /*
1083      * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
1084      */
1085     public void focusLost(FocusEvent event) {
1086       deactivate();
1087     }
1088
1089     /*
1090      * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1091      */
1092     public void documentAboutToBeChanged(DocumentEvent event) {
1093       if (fActive && fActiveRegion != null) {
1094         fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength());
1095         try {
1096           event.getDocument().addPosition(fRememberedPosition);
1097         } catch (BadLocationException x) {
1098           fRememberedPosition = null;
1099         }
1100       }
1101     }
1102
1103     /*
1104      * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1105      */
1106     public void documentChanged(DocumentEvent event) {
1107       if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
1108         event.getDocument().removePosition(fRememberedPosition);
1109         fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength());
1110       }
1111       fRememberedPosition = null;
1112
1113       ISourceViewer viewer = getSourceViewer();
1114       if (viewer != null) {
1115         StyledText widget = viewer.getTextWidget();
1116         if (widget != null && !widget.isDisposed()) {
1117           widget.getDisplay().asyncExec(new Runnable() {
1118             public void run() {
1119               deactivate();
1120             }
1121           });
1122         }
1123       }
1124     }
1125
1126     /*
1127      * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
1128      */
1129     public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
1130       if (oldInput == null)
1131         return;
1132       deactivate();
1133       oldInput.removeDocumentListener(this);
1134     }
1135
1136     /*
1137      * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
1138      */
1139     public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
1140       if (newInput == null)
1141         return;
1142       newInput.addDocumentListener(this);
1143     }
1144
1145     /*
1146      * @see PaintListener#paintControl(PaintEvent)
1147      */
1148     public void paintControl(PaintEvent event) {
1149       if (fActiveRegion == null)
1150         return;
1151
1152       ISourceViewer viewer = getSourceViewer();
1153       if (viewer == null)
1154         return;
1155
1156       StyledText text = viewer.getTextWidget();
1157       if (text == null || text.isDisposed())
1158         return;
1159
1160       int offset = 0;
1161       int length = 0;
1162
1163       if (viewer instanceof ITextViewerExtension3) {
1164
1165         ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
1166         IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length));
1167         if (widgetRange == null)
1168           return;
1169
1170         offset = widgetRange.getOffset();
1171         length = widgetRange.getLength();
1172
1173       } else {
1174
1175         IRegion region = viewer.getVisibleRegion();
1176         if (!includes(region, fActiveRegion))
1177           return;
1178
1179         offset = fActiveRegion.getOffset() - region.getOffset();
1180         length = fActiveRegion.getLength();
1181       }
1182
1183       // support for bidi
1184       Point minLocation = getMinimumLocation(text, offset, length);
1185       Point maxLocation = getMaximumLocation(text, offset, length);
1186
1187       int x1 = minLocation.x;
1188       int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
1189       int y = minLocation.y + text.getLineHeight() - 1;
1190
1191       GC gc = event.gc;
1192       if (fColor != null && !fColor.isDisposed())
1193         gc.setForeground(fColor);
1194       gc.drawLine(x1, y, x2, y);
1195     }
1196
1197     private boolean includes(IRegion region, IRegion position) {
1198       return position.getOffset() >= region.getOffset() && position.getOffset() + position.getLength() <= region.getOffset() + region.getLength();
1199     }
1200
1201     private Point getMinimumLocation(StyledText text, int offset, int length) {
1202       Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
1203
1204       for (int i = 0; i <= length; i++) {
1205         Point location = text.getLocationAtOffset(offset + i);
1206
1207         if (location.x < minLocation.x)
1208           minLocation.x = location.x;
1209         if (location.y < minLocation.y)
1210           minLocation.y = location.y;
1211       }
1212
1213       return minLocation;
1214     }
1215
1216     private Point getMaximumLocation(StyledText text, int offset, int length) {
1217       Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
1218
1219       for (int i = 0; i <= length; i++) {
1220         Point location = text.getLocationAtOffset(offset + i);
1221
1222         if (location.x > maxLocation.x)
1223           maxLocation.x = location.x;
1224         if (location.y > maxLocation.y)
1225           maxLocation.y = location.y;
1226       }
1227
1228       return maxLocation;
1229     }
1230   };
1231
1232   /**
1233    * This action dispatches into two behaviours: If there is no current text
1234    * hover, the javadoc is displayed using information presenter. If there is
1235    * a current text hover, it is converted into a information presenter in
1236    * order to make it sticky.
1237    */
1238   class InformationDispatchAction extends TextEditorAction {
1239
1240     /** The wrapped text operation action. */
1241     private final TextOperationAction fTextOperationAction;
1242
1243     /**
1244      * Creates a dispatch action.
1245      */
1246     public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) {
1247       super(resourceBundle, prefix, PHPEditor.this);
1248       if (textOperationAction == null)
1249         throw new IllegalArgumentException();
1250       fTextOperationAction = textOperationAction;
1251     }
1252
1253     /*
1254      * @see org.eclipse.jface.action.IAction#run()
1255      */
1256     public void run() {
1257
1258       ISourceViewer sourceViewer = getSourceViewer();
1259       if (sourceViewer == null) {
1260         fTextOperationAction.run();
1261         return;
1262       }
1263
1264       if (!(sourceViewer instanceof ITextViewerExtension2)) {
1265         fTextOperationAction.run();
1266         return;
1267       }
1268
1269       ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
1270
1271       // does a text hover exist?
1272       ITextHover textHover = textViewerExtension2.getCurrentTextHover();
1273       if (textHover == null) {
1274         fTextOperationAction.run();
1275         return;
1276       }
1277
1278       Point hoverEventLocation = textViewerExtension2.getHoverEventLocation();
1279       int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y);
1280       if (offset == -1) {
1281         fTextOperationAction.run();
1282         return;
1283       }
1284
1285       try {
1286         // get the text hover content
1287         IDocument document = sourceViewer.getDocument();
1288         String contentType = document.getContentType(offset);
1289
1290         final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset);
1291         if (hoverRegion == null)
1292           return;
1293
1294         final String hoverInfo = textHover.getHoverInfo(sourceViewer, hoverRegion);
1295
1296         // with information provider
1297         IInformationProvider informationProvider = new IInformationProvider() {
1298           /*
1299            * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int)
1300            */
1301           public IRegion getSubject(ITextViewer textViewer, int offset) {
1302             return hoverRegion;
1303           }
1304           /*
1305            * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
1306            */
1307           public String getInformation(ITextViewer textViewer, IRegion subject) {
1308             return hoverInfo;
1309           }
1310         };
1311
1312         fInformationPresenter.setOffset(offset);
1313         fInformationPresenter.setInformationProvider(informationProvider, contentType);
1314         fInformationPresenter.showInformation();
1315
1316       } catch (BadLocationException e) {
1317       }
1318     }
1319
1320     // modified version from TextViewer
1321     private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
1322
1323       StyledText styledText = textViewer.getTextWidget();
1324       IDocument document = textViewer.getDocument();
1325
1326       if (document == null)
1327         return -1;
1328
1329       try {
1330         int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y));
1331         if (textViewer instanceof ITextViewerExtension3) {
1332           ITextViewerExtension3 extension = (ITextViewerExtension3) textViewer;
1333           return extension.widgetOffset2ModelOffset(widgetLocation);
1334         } else {
1335           IRegion visibleRegion = textViewer.getVisibleRegion();
1336           return widgetLocation + visibleRegion.getOffset();
1337         }
1338       } catch (IllegalArgumentException e) {
1339         return -1;
1340       }
1341
1342     }
1343   };
1344
1345 //  static protected class AnnotationAccess implements IAnnotationAccess {
1346 //    /*
1347 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
1348 //     */
1349 //    public Object getType(Annotation annotation) {
1350 //      if (annotation instanceof IJavaAnnotation) {
1351 //        IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
1352 //   //     if (javaAnnotation.isRelevant())
1353 //   //       return javaAnnotation.getAnnotationType();
1354 //      }
1355 //      return null;
1356 //    }
1357 //
1358 //    /*
1359 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
1360 //     */
1361 //    public boolean isMultiLine(Annotation annotation) {
1362 //      return true;
1363 //    }
1364 //
1365 //    /*
1366 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
1367 //     */
1368 //    public boolean isTemporary(Annotation annotation) {
1369 //      if (annotation instanceof IJavaAnnotation) {
1370 //        IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
1371 //        if (javaAnnotation.isRelevant())
1372 //          return javaAnnotation.isTemporary();
1373 //      }
1374 //      return false;
1375 //    }
1376 //  };
1377
1378   private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
1379     /*
1380      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
1381      */
1382     public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
1383       handlePreferencePropertyChanged(event);
1384     }
1385   };
1386   
1387   /**
1388          * Finds and marks occurrence annotations.
1389          * 
1390          * @since 3.0
1391          */
1392         class OccurrencesFinderJob extends Job implements IDocumentListener {
1393                 
1394                 private IDocument fDocument;
1395                 private boolean fCancelled= false;
1396                 private IProgressMonitor fProgressMonitor;
1397                 private Position[] fPositions;
1398                 
1399                 public OccurrencesFinderJob(IDocument document, Position[] positions) {
1400                         super("Occurrences Marker"); //$NON-NLS-1$
1401                         fDocument= document;
1402                         fPositions= positions;
1403                         fDocument.addDocumentListener(this);
1404                 }
1405                 
1406                 private boolean isCancelled() {
1407                         return fCancelled || fProgressMonitor.isCanceled();
1408                 }
1409                 
1410                 /*
1411                  * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
1412                  */
1413                 public IStatus run(IProgressMonitor progressMonitor) {
1414                         
1415                         fProgressMonitor= progressMonitor;
1416                         
1417                         try {
1418                                 
1419                                 if (isCancelled())
1420                                         return Status.CANCEL_STATUS;
1421                                 
1422                                 ITextViewer textViewer= getViewer(); 
1423                                 if (textViewer == null)
1424                                         return Status.CANCEL_STATUS;
1425                                 
1426                                 IDocument document= textViewer.getDocument();
1427                                 if (document == null)
1428                                         return Status.CANCEL_STATUS;
1429                                 
1430                                 IDocumentProvider documentProvider= getDocumentProvider();
1431                                 if (documentProvider == null)
1432                                         return Status.CANCEL_STATUS;
1433                         
1434                                 IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
1435                                 if (annotationModel == null)
1436                                         return Status.CANCEL_STATUS;
1437                                 
1438                                 // Add occurrence annotations
1439                                 int length= fPositions.length;
1440                                 Map annotationMap= new HashMap(length);
1441                                 for (int i= 0; i < length; i++) {
1442                                         
1443                                         if (isCancelled())
1444                                                 return Status.CANCEL_STATUS; 
1445                                         
1446                                         String message;
1447                                         Position position= fPositions[i];
1448                                         
1449                                         // Create & add annotation
1450                                         try {
1451                                                 message= document.get(position.offset, position.length);
1452                                         } catch (BadLocationException ex) {
1453                                                 // Skip this match
1454                                                 continue;
1455                                         }
1456                                         annotationMap.put(
1457                                                         new Annotation("net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$
1458                                                         position);
1459                                 }
1460                                 
1461                                 if (isCancelled())
1462                                         return Status.CANCEL_STATUS;
1463                                 
1464                                 synchronized (annotationModel) {
1465                                         if (annotationModel instanceof IAnnotationModelExtension) {
1466                                                 ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
1467                                         } else {
1468                                                 removeOccurrenceAnnotations();
1469                                                 Iterator iter= annotationMap.entrySet().iterator();
1470                                                 while (iter.hasNext()) {
1471                                                         Map.Entry mapEntry= (Map.Entry)iter.next(); 
1472                                                         annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue());
1473                                                 }
1474                                         }
1475                                         fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
1476                                 }
1477                         } finally {
1478                                 fDocument.removeDocumentListener(this);
1479                         }
1480                         return Status.OK_STATUS;
1481                 }
1482
1483                 /*
1484                  * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1485                  */
1486                 public void documentAboutToBeChanged(DocumentEvent event) {
1487                         fCancelled= true;
1488                 }
1489
1490                 /*
1491                  * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1492                  */
1493                 public void documentChanged(DocumentEvent event) {
1494                 }
1495         }
1496         
1497         
1498         /**
1499          * Holds the current occurrence annotations.
1500          * @since 3.0
1501          */
1502   private Annotation[] fOccurrenceAnnotations= null;
1503   
1504   private Job fOccurrencesFinderJob;
1505         
1506   /** Preference key for showing the line number ruler */
1507 //  private final static String LINE_NUMBER_RULER = PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
1508   /** Preference key for the foreground color of the line numbers */
1509  // private final static String LINE_NUMBER_COLOR = PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
1510   /** Preference key for the link color */
1511   private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
1512   /** Preference key for compiler task tags */
1513   private final static String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
1514
1515   // protected PHPActionGroup fActionGroups;
1516   //  /** The outline page */
1517   //  private AbstractContentOutlinePage fOutlinePage;
1518   /** The outline page */
1519   protected JavaOutlinePage fOutlinePage;
1520   /** Outliner context menu Id */
1521   protected String fOutlinerContextMenuId;
1522         /**
1523          * The editor selection changed listener.
1524          * 
1525          * @since 3.0
1526          */
1527 //  private EditorSelectionChangedListener fEditorSelectionChangedListener;
1528   /** Indicates whether this editor should react on outline page selection changes */
1529   private int fIgnoreOutlinePageSelection;
1530   
1531         /** The outline page selection updater */
1532         private OutlinePageSelectionUpdater fUpdater;
1533   //  protected PHPSyntaxParserThread fValidationThread = null;
1534
1535   // private IPreferenceStore fPHPPrefStore;
1536   /** The selection changed listener */
1537   protected ISelectionChangedListener fSelectionChangedListener = new SelectionChangedListener();
1538
1539   /** The editor's bracket matcher */
1540   private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
1541
1542
1543   /** The line number ruler column */
1544 //  private LineNumberRulerColumn fLineNumberRulerColumn;
1545   /** This editor's encoding support */
1546   private DefaultEncodingSupport fEncodingSupport;
1547   /** The mouse listener */
1548   private MouseClickListener fMouseListener;
1549
1550   protected CompositeActionGroup fActionGroups;
1551   protected CompositeActionGroup fContextMenuGroup;
1552
1553   /** 
1554          * This editor's projection support 
1555          * @since 3.0
1556          */
1557         private ProjectionSupport fProjectionSupport;
1558         /** 
1559          * This editor's projection model updater 
1560          * @since 3.0
1561          */
1562         private IJavaFoldingStructureProvider fProjectionModelUpdater;
1563   /**
1564          * The action group for folding.
1565          *  
1566          * @since 3.0
1567          */
1568         private FoldingActionGroup fFoldingGroup;
1569         
1570   /** The information presenter. */
1571   private InformationPresenter fInformationPresenter;
1572   /** The annotation access */
1573 //  protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
1574   /** The overview ruler */
1575   protected OverviewRuler isOverviewRulerVisible;
1576   /** The source viewer decoration support */
1577   //protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
1578   /** The overview ruler */
1579   //protected OverviewRuler fOverviewRuler;
1580
1581   /** The preference property change listener for java core. */
1582   private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
1583   /**
1584    * Returns the most narrow java element including the given offset
1585    * 
1586    * @param offset the offset inside of the requested element
1587    */
1588   abstract protected IJavaElement getElementAt(int offset);
1589
1590   /**
1591    * Returns the java element of this editor's input corresponding to the given IJavaElement
1592    */
1593   abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
1594   /**
1595          * Sets the input of the editor's outline page.
1596          */
1597   abstract protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input);
1598
1599   /**
1600    * Default constructor.
1601    */
1602   public PHPEditor() {
1603     super();
1604   }
1605  
1606  
1607         /*
1608          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
1609          */
1610         protected void initializeKeyBindingScopes() {
1611                 setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" });  //$NON-NLS-1$
1612         }
1613         
1614         /*
1615          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
1616          */
1617         protected void initializeEditor() {
1618           //jsurfer old code
1619                 JavaTextTools textTools= PHPeclipsePlugin.getDefault().getJavaTextTools();
1620                 setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this)); //, IJavaPartitions.JAVA_PARTITIONING));
1621                 setRangeIndicator(new DefaultRangeIndicator());
1622 //              IPreferenceStore store= PHPeclipsePlugin.getDefault().getPreferenceStore();
1623 //              setPreferenceStore(store);
1624                 IPreferenceStore store= createCombinedPreferenceStore(null);
1625                 setPreferenceStore(store);
1626                 
1627                 // TODO changed in 3.x ?
1628             if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
1629               fUpdater= new OutlinePageSelectionUpdater();
1630             // jsurfer end
1631             
1632 //              IPreferenceStore store= createCombinedPreferenceStore(null);
1633 //              setPreferenceStore(store);
1634 //              JavaTextTools textTools= PHPeclipsePlugin.getDefault().getJavaTextTools();
1635 //              setSourceViewerConfiguration(new JavaSourceViewerConfiguration(textTools.getColorManager(), store, this, IJavaPartitions.JAVA_PARTITIONING));
1636 //              fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
1637 //              fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
1638 //              fMarkTypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
1639 //              fMarkMethodOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
1640 //              fMarkConstantOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
1641 //              fMarkFieldOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
1642 //              fMarkLocalVariableypeOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
1643 //              fMarkExceptionOccurrences= store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
1644 //              fMarkMethodExitPoints= store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
1645         }
1646   /*
1647    * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
1648    */
1649   protected void updatePropertyDependentActions() {
1650     super.updatePropertyDependentActions();
1651     if (fEncodingSupport != null)
1652       fEncodingSupport.reset();
1653   }
1654
1655   /*
1656    * Update the hovering behavior depending on the preferences.
1657    */
1658   private void updateHoverBehavior() {
1659     SourceViewerConfiguration configuration = getSourceViewerConfiguration();
1660     String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
1661
1662     for (int i = 0; i < types.length; i++) {
1663
1664       String t = types[i];
1665
1666       int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
1667
1668       ISourceViewer sourceViewer = getSourceViewer();
1669       if (sourceViewer instanceof ITextViewerExtension2) {
1670         if (stateMasks != null) {
1671           for (int j = 0; j < stateMasks.length; j++) {
1672             int stateMask = stateMasks[j];
1673             ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
1674             ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
1675           }
1676         } else {
1677           ITextHover textHover = configuration.getTextHover(sourceViewer, t);
1678           ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
1679         }
1680       } else
1681         sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
1682     }
1683   }
1684
1685   public void updatedTitleImage(Image image) {
1686     setTitleImage(image);
1687   }
1688   /*
1689    * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1690    */
1691   public Object getViewPartInput() {
1692     return getEditorInput().getAdapter(IResource.class);
1693   }
1694   /*
1695    * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
1696    */
1697   protected void doSetSelection(ISelection selection) {
1698     super.doSetSelection(selection);
1699     synchronizeOutlinePageSelection();
1700   }
1701         boolean isFoldingEnabled() {
1702                 return PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
1703         }
1704   /*
1705    * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
1706    * widgets.Composite)
1707    */
1708   public void createPartControl(Composite parent) {
1709     super.createPartControl(parent);
1710
1711     //fSourceViewerDecorationSupport.install(getPreferenceStore());
1712
1713     ProjectionViewer projectionViewer= (ProjectionViewer) getSourceViewer();
1714         
1715         fProjectionSupport= new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
1716         fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
1717         fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
1718         fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() {
1719                 public IInformationControl createInformationControl(Shell shell) {
1720                         return new CustomSourceInformationControl(shell, IDocument.DEFAULT_CONTENT_TYPE);
1721                 }
1722         });
1723     fProjectionSupport.install();
1724         
1725         fProjectionModelUpdater= PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
1726         if (fProjectionModelUpdater != null)
1727                 fProjectionModelUpdater.install(this, projectionViewer);
1728                         
1729         if (isFoldingEnabled())
1730                 projectionViewer.doOperation(ProjectionViewer.TOGGLE);
1731         Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1732     preferences.addPropertyChangeListener(fPropertyChangeListener);
1733     
1734     IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
1735       public IInformationControl createInformationControl(Shell parent) {
1736         boolean cutDown = false;
1737         int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
1738         return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown));
1739       }
1740     };
1741
1742     fInformationPresenter = new InformationPresenter(informationControlCreator);
1743     fInformationPresenter.setSizeConstraints(60, 10, true, true);
1744     fInformationPresenter.install(getSourceViewer());
1745
1746   }
1747
1748   /**
1749    * Returns this document's complete text.
1750    *
1751    * @return the document's complete text
1752    */
1753   public String get() {
1754     IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1755     return doc.get();
1756   }
1757
1758   /**
1759          * Sets the outliner's context menu ID.
1760          */
1761   protected void setOutlinerContextMenuId(String menuId) {
1762     fOutlinerContextMenuId = menuId;
1763   }
1764
1765   /**
1766    *  Returns the standard action group of this editor.
1767    */
1768   protected ActionGroup getActionGroup() {
1769     return fActionGroups;
1770   }
1771
1772   //  public JavaOutlinePage getfOutlinePage() {
1773   //    return fOutlinePage;
1774   //  }
1775
1776   /** The <code>PHPEditor</code> implementation of this 
1777    * <code>AbstractTextEditor</code> method extend the 
1778    * actions to add those specific to the receiver
1779    */
1780   protected void createActions() {
1781     super.createActions();
1782     
1783     fFoldingGroup= new FoldingActionGroup(this, getViewer());
1784     
1785         ResourceAction resAction= new TextOperationAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
1786         resAction= new InformationDispatchAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
1787         resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
1788         setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
1789 //      WorkbenchHelp.setHelp(resAction, IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
1790         
1791         Action action= new GotoMatchingBracketAction(this);
1792         action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);                               
1793         setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
1794                 
1795 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.", this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
1796 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
1797 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
1798 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
1799 //
1800 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.", this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
1801 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
1802 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE, action);
1803 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
1804 //      
1805 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.", this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
1806 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
1807 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY, action);
1808 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
1809         
1810         fEncodingSupport= new DefaultEncodingSupport();
1811         fEncodingSupport.initialize(this);
1812         
1813 //      fSelectionHistory= new SelectionHistory(this);
1814 //
1815 //      action= new StructureSelectEnclosingAction(this, fSelectionHistory);
1816 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);                            
1817 //      setAction(StructureSelectionAction.ENCLOSING, action);
1818 //
1819 //      action= new StructureSelectNextAction(this, fSelectionHistory);
1820 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
1821 //      setAction(StructureSelectionAction.NEXT, action);
1822 //
1823 //      action= new StructureSelectPreviousAction(this, fSelectionHistory);
1824 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
1825 //      setAction(StructureSelectionAction.PREVIOUS, action);
1826 //
1827 //      StructureSelectHistoryAction historyAction= new StructureSelectHistoryAction(this, fSelectionHistory);
1828 //      historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);          
1829 //      setAction(StructureSelectionAction.HISTORY, historyAction);
1830 //      fSelectionHistory.setHistoryAction(historyAction);
1831 //                      
1832 //      action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
1833 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);                            
1834 //      setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
1835 //
1836 //      action= GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
1837 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);                                
1838 //      setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
1839 //      
1840 //      action= new QuickFormatAction();
1841 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
1842 //      setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
1843 //
1844 //      action= new RemoveOccurrenceAnnotations(this);
1845 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
1846 //      setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
1847
1848         // add annotation actions
1849         action= new JavaSelectMarkerRulerAction2(PHPEditorMessages.getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
1850         setAction("AnnotationAction", action); //$NON-NLS-1$
1851   }
1852
1853         private void internalDoSetInput(IEditorInput input) throws CoreException {
1854                 super.doSetInput(input);
1855                 
1856                 if (fEncodingSupport != null)
1857                         fEncodingSupport.reset();
1858                 
1859                 setOutlinePageInput(fOutlinePage, input);
1860                                 
1861                 if (fProjectionModelUpdater != null)
1862                         fProjectionModelUpdater.initialize();
1863                 
1864 //              if (isShowingOverrideIndicators())
1865 //                      installOverrideIndicator(true);
1866         }
1867
1868         /*
1869          * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
1870          * @since 3.0
1871          */
1872         protected void setPreferenceStore(IPreferenceStore store) {
1873                 super.setPreferenceStore(store);
1874                 if (getSourceViewerConfiguration() instanceof PHPSourceViewerConfiguration) {
1875                         JavaTextTools textTools= PHPeclipsePlugin.getDefault().getJavaTextTools();
1876                         setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this, IPHPPartitions.PHP_PARTITIONING));
1877                 }
1878                 if (getSourceViewer() instanceof JavaSourceViewer)
1879                         ((JavaSourceViewer)getSourceViewer()).setPreferenceStore(store);
1880         }
1881   /** The <code>PHPEditor</code> implementation of this 
1882    * <code>AbstractTextEditor</code> method performs any extra 
1883    * disposal actions required by the php editor.
1884    */
1885   public void dispose() {
1886         if (fProjectionModelUpdater != null) {
1887                 fProjectionModelUpdater.uninstall();
1888                 fProjectionModelUpdater= null;
1889         }
1890         
1891         if (fProjectionSupport != null) {
1892                 fProjectionSupport.dispose();
1893                 fProjectionSupport= null;
1894         }
1895     //   PHPEditorEnvironment.disconnect(this);
1896     if (fOutlinePage != null)
1897       fOutlinePage.setInput(null);
1898
1899     if (fActionGroups != null)
1900       fActionGroups.dispose();
1901
1902     if (isBrowserLikeLinks())
1903       disableBrowserLikeLinks();
1904
1905     if (fEncodingSupport != null) {
1906       fEncodingSupport.dispose();
1907       fEncodingSupport = null;
1908     }
1909
1910     if (fPropertyChangeListener != null) {
1911       Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1912       preferences.removePropertyChangeListener(fPropertyChangeListener);
1913       fPropertyChangeListener = null;
1914     }
1915
1916 //    if (fSourceViewerDecorationSupport != null) {
1917 //      fSourceViewerDecorationSupport.dispose();
1918 //      fSourceViewerDecorationSupport = null;
1919 //    }
1920
1921     if (fBracketMatcher != null) {
1922       fBracketMatcher.dispose();
1923       fBracketMatcher = null;
1924     }
1925     super.dispose();
1926   }
1927
1928   /** The <code>PHPEditor</code> implementation of this 
1929    * <code>AbstractTextEditor</code> method performs any extra 
1930    * revert behavior required by the php editor.
1931    */
1932   //  public void doRevertToSaved() {
1933   //    super.doRevertToSaved();
1934   //    if (fOutlinePage != null)
1935   //      fOutlinePage.update();
1936   //  }
1937
1938   /** The <code>PHPEditor</code> implementation of this 
1939    * <code>AbstractTextEditor</code> method performs any extra 
1940    * save behavior required by the php editor.
1941    */
1942   //  public void doSave(IProgressMonitor monitor) {
1943   //    super.doSave(monitor);
1944   // compile or not, according to the user preferences
1945   // IPreferenceStore store = getPreferenceStore(); 
1946
1947   // the parse on save was changed to the eclipse "builders" concept
1948   //    if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
1949   //      IAction a = PHPParserAction.getInstance();
1950   //      if (a != null)
1951   //        a.run();
1952   //    }
1953
1954   //    if (SWT.getPlatform().equals("win32")) {
1955   //      IAction a = ShowExternalPreviewAction.getInstance();
1956   //      if (a != null)
1957   //        a.run();
1958   //    }
1959   //    if (fOutlinePage != null)
1960   //      fOutlinePage.update();
1961   //  }
1962
1963   /** The <code>PHPEditor</code> implementation of this 
1964    * <code>AbstractTextEditor</code> method performs any extra 
1965    * save as behavior required by the php editor.
1966    */
1967   //  public void doSaveAs() {
1968   //    super.doSaveAs();
1969   //    if (fOutlinePage != null)
1970   //      fOutlinePage.update();
1971   //  }
1972   /*
1973          * @see StatusTextEditor#getStatusHeader(IStatus)
1974          */
1975   protected String getStatusHeader(IStatus status) {
1976     if (fEncodingSupport != null) {
1977       String message = fEncodingSupport.getStatusHeader(status);
1978       if (message != null)
1979         return message;
1980     }
1981     return super.getStatusHeader(status);
1982   }
1983
1984   /*
1985    * @see StatusTextEditor#getStatusBanner(IStatus)
1986    */
1987   protected String getStatusBanner(IStatus status) {
1988     if (fEncodingSupport != null) {
1989       String message = fEncodingSupport.getStatusBanner(status);
1990       if (message != null)
1991         return message;
1992     }
1993     return super.getStatusBanner(status);
1994   }
1995
1996   /*
1997    * @see StatusTextEditor#getStatusMessage(IStatus)
1998    */
1999   protected String getStatusMessage(IStatus status) {
2000     if (fEncodingSupport != null) {
2001       String message = fEncodingSupport.getStatusMessage(status);
2002       if (message != null)
2003         return message;
2004     }
2005     return super.getStatusMessage(status);
2006   }
2007   /** The <code>PHPEditor</code> implementation of this 
2008    * <code>AbstractTextEditor</code> method performs sets the 
2009    * input of the outline page after AbstractTextEditor has set input.
2010    */
2011   //  protected void doSetInput(IEditorInput input) throws CoreException {
2012   //    super.doSetInput(input);
2013   //
2014   //    if (fEncodingSupport != null)
2015   //      fEncodingSupport.reset();
2016   //    if (fOutlinePage != null)
2017   //      fOutlinePage.setInput(input);
2018   //    //              setOutlinePageInput(fOutlinePage, input);
2019   //  } 
2020   protected void doSetInput(IEditorInput input) throws CoreException {
2021     super.doSetInput(input);
2022     if (fEncodingSupport != null)
2023       fEncodingSupport.reset();
2024     setOutlinePageInput(fOutlinePage, input);
2025   }
2026   /*
2027    * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
2028    */
2029   //  public Object getViewPartInput() {
2030   //    return getEditorInput().getAdapter(IFile.class);
2031   //  }
2032
2033   /** The <code>PHPEditor</code> implementation of this 
2034    * <code>AbstractTextEditor</code> method adds any 
2035    * PHPEditor specific entries.
2036    */
2037   public void editorContextMenuAboutToShow(MenuManager menu) {
2038     super.editorContextMenuAboutToShow(menu);
2039     menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
2040     menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
2041
2042     ActionContext context = new ActionContext(getSelectionProvider().getSelection());
2043     fContextMenuGroup.setContext(context);
2044     fContextMenuGroup.fillContextMenu(menu);
2045     fContextMenuGroup.setContext(null);
2046     //    addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
2047     //
2048     //    ActionContext context =
2049     //      new ActionContext(getSelectionProvider().getSelection());
2050     //    fContextMenuGroup.setContext(context);
2051     //    fContextMenuGroup.fillContextMenu(menu);
2052     //    fContextMenuGroup.setContext(null);
2053   }
2054
2055   /**
2056    * Creates the outline page used with this editor.
2057    */
2058   protected JavaOutlinePage createOutlinePage() {
2059
2060     //    AbstractContentOutlinePage page = new PHPContentOutlinePage(getDocumentProvider(), this);
2061     //
2062     //    page.addSelectionChangedListener(fSelectionChangedListener);
2063     //    //    setOutlinePageInput(page, getEditorInput());
2064     //    if (getEditorInput() != null)
2065     //      fOutlinePage.setInput(getEditorInput());
2066     //
2067     //    return page;
2068     JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
2069
2070     page.addSelectionChangedListener(fSelectionChangedListener);
2071     setOutlinePageInput(page, getEditorInput());
2072
2073     return page;
2074   }
2075
2076   /**
2077    * Informs the editor that its outliner has been closed.
2078    */
2079   public void outlinePageClosed() {
2080     if (fOutlinePage != null) {
2081       fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
2082       fOutlinePage = null;
2083       resetHighlightRange();
2084     }
2085   }
2086   /**
2087    * Synchronizes the outliner selection with the actual cursor
2088    * position in the editor.
2089    */
2090   public void synchronizeOutlinePageSelection() {
2091
2092     //          if (isEditingScriptRunning())
2093     //                  return;
2094
2095     ISourceViewer sourceViewer = getSourceViewer();
2096     if (sourceViewer == null || fOutlinePage == null)
2097       return;
2098
2099     StyledText styledText = sourceViewer.getTextWidget();
2100     if (styledText == null)
2101       return;
2102
2103     int caret = 0;
2104     if (sourceViewer instanceof ITextViewerExtension3) {
2105       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
2106       caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
2107     } else {
2108       int offset = sourceViewer.getVisibleRegion().getOffset();
2109       caret = offset + styledText.getCaretOffset();
2110     }
2111
2112     IJavaElement element = getElementAt(caret);
2113     if (element instanceof ISourceReference) {
2114       fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
2115       fOutlinePage.select((ISourceReference) element);
2116       fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
2117     }
2118   }
2119
2120   protected void setSelection(ISourceReference reference, boolean moveCursor) {
2121
2122     ISelection selection = getSelectionProvider().getSelection();
2123     if (selection instanceof TextSelection) {
2124       TextSelection textSelection = (TextSelection) selection;
2125       if (textSelection.getOffset() != 0 || textSelection.getLength() != 0)
2126         markInNavigationHistory();
2127     }
2128
2129     if (reference != null) {
2130
2131       StyledText textWidget = null;
2132
2133       ISourceViewer sourceViewer = getSourceViewer();
2134       if (sourceViewer != null)
2135         textWidget = sourceViewer.getTextWidget();
2136
2137       if (textWidget == null)
2138         return;
2139
2140       try {
2141
2142         ISourceRange range = reference.getSourceRange();
2143         if (range == null)
2144           return;
2145
2146         int offset = range.getOffset();
2147         int length = range.getLength();
2148
2149         if (offset < 0 || length < 0)
2150           return;
2151
2152         textWidget.setRedraw(false);
2153
2154         setHighlightRange(offset, length, moveCursor);
2155
2156         if (!moveCursor)
2157           return;
2158
2159         offset = -1;
2160         length = -1;
2161
2162         if (reference instanceof IMember) {
2163           range = ((IMember) reference).getNameRange();
2164           if (range != null) {
2165             offset = range.getOffset();
2166             length = range.getLength();
2167           }
2168         }
2169         //                                      else if (reference instanceof IImportDeclaration) {
2170         //                                              String name= ((IImportDeclaration) reference).getElementName();
2171         //                                              if (name != null && name.length() > 0) {
2172         //                                                      String content= reference.getSource();
2173         //                                                      if (content != null) {
2174         //                                                              offset= range.getOffset() + content.indexOf(name);
2175         //                                                              length= name.length();
2176         //                                                      }
2177         //                                              }
2178         //                                      } else if (reference instanceof IPackageDeclaration) {
2179         //                                              String name= ((IPackageDeclaration) reference).getElementName();
2180         //                                              if (name != null && name.length() > 0) {
2181         //                                                      String content= reference.getSource();
2182         //                                                      if (content != null) {
2183         //                                                              offset= range.getOffset() + content.indexOf(name);
2184         //                                                              length= name.length();
2185         //                                                      }
2186         //                                              }
2187         //                                      }
2188
2189         if (offset > -1 && length > 0) {
2190           sourceViewer.revealRange(offset, length);
2191           sourceViewer.setSelectedRange(offset, length);
2192         }
2193
2194       } catch (JavaModelException x) {
2195       } catch (IllegalArgumentException x) {
2196       } finally {
2197         if (textWidget != null)
2198           textWidget.setRedraw(true);
2199       }
2200
2201     } else if (moveCursor) {
2202       resetHighlightRange();
2203     }
2204
2205     markInNavigationHistory();
2206   }
2207
2208   public void setSelection(IJavaElement element) {
2209
2210     if (element == null || element instanceof ICompilationUnit) { // || element instanceof IClassFile) {
2211       /*
2212        * If the element is an ICompilationUnit this unit is either the input
2213        * of this editor or not being displayed. In both cases, nothing should
2214        * happened. (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
2215        */
2216       return;
2217     }
2218
2219     IJavaElement corresponding = getCorrespondingElement(element);
2220     if (corresponding instanceof ISourceReference) {
2221       ISourceReference reference = (ISourceReference) corresponding;
2222       // set hightlight range
2223       setSelection(reference, true);
2224       // set outliner selection
2225       if (fOutlinePage != null) {
2226         fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
2227         fOutlinePage.select(reference);
2228         fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
2229       }
2230     }
2231   }
2232
2233         public synchronized void editingScriptStarted() {
2234                 ++ fIgnoreOutlinePageSelection;
2235         }
2236         
2237         public synchronized void editingScriptEnded() {
2238                 -- fIgnoreOutlinePageSelection;
2239         }
2240         
2241         public synchronized boolean isEditingScriptRunning() {
2242                 return (fIgnoreOutlinePageSelection > 0);
2243         }
2244         
2245   /** The <code>PHPEditor</code> implementation of this 
2246    * <code>AbstractTextEditor</code> method performs gets
2247    * the java content outline page if request is for a an 
2248    * outline page.
2249    */
2250   public Object getAdapter(Class required) {
2251
2252     if (IContentOutlinePage.class.equals(required)) {
2253       if (fOutlinePage == null)
2254         fOutlinePage = createOutlinePage();
2255       return fOutlinePage;
2256     }
2257
2258     if (IEncodingSupport.class.equals(required))
2259       return fEncodingSupport;
2260
2261     if (required == IShowInTargetList.class) {
2262       return new IShowInTargetList() {
2263         public String[] getShowInTargetIds() {
2264           return new String[] { JavaUI.ID_PACKAGES, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
2265         }
2266
2267       };
2268     }
2269     if (fProjectionSupport != null) {
2270                 Object adapter= fProjectionSupport.getAdapter(getSourceViewer(), required);
2271                 if (adapter != null)
2272                         return adapter;
2273         }
2274                 
2275     return super.getAdapter(required);
2276   }
2277   //  public Object getAdapter(Class required) {
2278   //    if (IContentOutlinePage.class.equals(required)) {
2279   //      if (fOutlinePage == null) {
2280   //        fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
2281   //        if (getEditorInput() != null)
2282   //          fOutlinePage.setInput(getEditorInput());
2283   //      }
2284   //      return fOutlinePage;
2285   //    }
2286   //
2287   //    if (IEncodingSupport.class.equals(required))
2288   //      return fEncodingSupport;
2289   //
2290   //    return super.getAdapter(required);
2291   //  }
2292
2293   protected void doSelectionChanged(SelectionChangedEvent event) {
2294     ISourceReference reference = null;
2295
2296     ISelection selection = event.getSelection();
2297     Iterator iter = ((IStructuredSelection) selection).iterator();
2298     while (iter.hasNext()) {
2299       Object o = iter.next();
2300       if (o instanceof ISourceReference) {
2301         reference = (ISourceReference) o;
2302         break;
2303       }
2304     }
2305
2306     if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
2307       PHPeclipsePlugin.getActivePage().bringToTop(this);
2308
2309     try {
2310       editingScriptStarted();
2311       setSelection(reference, !isActivePart());
2312     } finally {
2313       editingScriptEnded();
2314     }
2315   }
2316   /*
2317          * @see AbstractTextEditor#adjustHighlightRange(int, int)
2318          */
2319   protected void adjustHighlightRange(int offset, int length) {
2320
2321     try {
2322
2323       IJavaElement element = getElementAt(offset);
2324       while (element instanceof ISourceReference) {
2325         ISourceRange range = ((ISourceReference) element).getSourceRange();
2326         if (offset < range.getOffset() + range.getLength() && range.getOffset() < offset + length) {
2327           setHighlightRange(range.getOffset(), range.getLength(), true);
2328           if (fOutlinePage != null) {
2329             fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
2330             fOutlinePage.select((ISourceReference) element);
2331             fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
2332           }
2333           return;
2334         }
2335         element = element.getParent();
2336       }
2337
2338     } catch (JavaModelException x) {
2339       PHPeclipsePlugin.log(x.getStatus());
2340     }
2341
2342     resetHighlightRange();
2343   }
2344   protected boolean isActivePart() {
2345     IWorkbenchWindow window = getSite().getWorkbenchWindow();
2346     IPartService service = window.getPartService();
2347     IWorkbenchPart part = service.getActivePart();
2348     return part != null && part.equals(this);
2349   }
2350
2351
2352   //  public void openContextHelp() {
2353   //    IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
2354   //    ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
2355   //    int pos = selection.getOffset();
2356   //    String word = getFunctionName(doc, pos);
2357   //    openContextHelp(word);
2358   //  }
2359   //
2360   //  private void openContextHelp(String word) {
2361   //    open(word);
2362   //  }
2363   //
2364   //  public static void open(String word) {
2365   //    IHelp help = WorkbenchHelp.getHelpSupport();
2366   //    if (help != null) {
2367   //      IHelpResource helpResource = new PHPFunctionHelpResource(word);
2368   //      WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
2369   //    } else {
2370   //      //   showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
2371   //    }
2372   //  }
2373
2374   //    private String getFunctionName(IDocument doc, int pos) {
2375   //            Point word = PHPWordExtractor.findWord(doc, pos);
2376   //            if (word != null) {
2377   //                    try {
2378   //                            return doc.get(word.x, word.y).replace('_', '-');
2379   //                    } catch (BadLocationException e) {
2380   //                    }
2381   //            }
2382   //            return "";
2383   //    }
2384
2385   /*
2386    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
2387    */
2388   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
2389
2390     try {
2391
2392       ISourceViewer sourceViewer = getSourceViewer();
2393       if (sourceViewer == null)
2394         return;
2395
2396       String property = event.getProperty();
2397
2398       if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
2399         Object value = event.getNewValue();
2400         if (value instanceof Integer) {
2401           sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
2402         } else if (value instanceof String) {
2403           sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
2404         }
2405         return;
2406       }
2407       
2408 //      if (OVERVIEW_RULER.equals(property)) {
2409 //        if (isOverviewRulerVisible())
2410 //          showOverviewRuler();
2411 //        else
2412 //          hideOverviewRuler();
2413 //        return;
2414 //      }
2415
2416 //      if (LINE_NUMBER_RULER.equals(property)) {
2417 //        if (isLineNumberRulerVisible())
2418 //          showLineNumberRuler();
2419 //        else
2420 //          hideLineNumberRuler();
2421 //        return;
2422 //      }
2423
2424 //      if (fLineNumberRulerColumn != null
2425 //        && (LINE_NUMBER_COLOR.equals(property) || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
2426 //
2427 //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2428 //      }
2429
2430       if (isJavaEditorHoverProperty(property))
2431         updateHoverBehavior();
2432
2433       if (BROWSER_LIKE_LINKS.equals(property)) {
2434         if (isBrowserLikeLinks())
2435           enableBrowserLikeLinks();
2436         else
2437           disableBrowserLikeLinks();
2438         return;
2439       }
2440
2441 //      if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) {
2442 //              if ((event.getNewValue() instanceof Boolean) && ((Boolean)event.getNewValue()).booleanValue())
2443 //                      fEditorSelectionChangedListener.selectionChanged();
2444 //              return;
2445 //      }
2446         
2447         if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) {
2448                 if (event.getNewValue() instanceof Boolean) {
2449                         Boolean disable= (Boolean) event.getNewValue();
2450                         enableOverwriteMode(!disable.booleanValue());
2451                 }
2452                 return;
2453         }
2454         
2455 //      if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
2456 //              if (event.getNewValue() instanceof Boolean) {
2457 //                      boolean markOccurrenceAnnotations= ((Boolean)event.getNewValue()).booleanValue();
2458 //                      if (markOccurrenceAnnotations != fMarkOccurrenceAnnotations) {
2459 //                              fMarkOccurrenceAnnotations= markOccurrenceAnnotations;
2460 //                              if (!fMarkOccurrenceAnnotations)
2461 //                                      uninstallOccurrencesFinder();
2462 //                              else
2463 //                                      installOccurrencesFinder();
2464 //                      }
2465 //              }
2466 //      }
2467 //      if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
2468 //              if (event.getNewValue() instanceof Boolean) {
2469 //                      boolean stickyOccurrenceAnnotations= ((Boolean)event.getNewValue()).booleanValue();
2470 //                      if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations) {
2471 //                              fStickyOccurrenceAnnotations= stickyOccurrenceAnnotations;
2472 ////                            if (!fMarkOccurrenceAnnotations)
2473 ////                                    uninstallOccurrencesFinder();
2474 ////                            else
2475 ////                                    installOccurrencesFinder();
2476 //                      }
2477 //              }
2478 //      }
2479         if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
2480                 if (sourceViewer instanceof ProjectionViewer) {
2481                         ProjectionViewer projectionViewer= (ProjectionViewer) sourceViewer;
2482                         if (fProjectionModelUpdater != null)
2483                                 fProjectionModelUpdater.uninstall();
2484                         // either freshly enabled or provider changed
2485                         fProjectionModelUpdater= PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
2486                         if (fProjectionModelUpdater != null) {
2487                                 fProjectionModelUpdater.install(this, projectionViewer);
2488                         }
2489                 }
2490                 return;
2491         }
2492     } finally {
2493       super.handlePreferenceStoreChanged(event);
2494     }
2495   }
2496
2497   //  /*
2498   //     * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
2499   //     */
2500   //  protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
2501   //
2502   //    try {
2503   //
2504   //      ISourceViewer sourceViewer = getSourceViewer();
2505   //      if (sourceViewer == null)
2506   //        return;
2507   //
2508   //      String property = event.getProperty();
2509   //
2510   //      //      if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
2511   //      //        Object value= event.getNewValue();
2512   //      //        if (value instanceof Integer) {
2513   //      //          sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
2514   //      //        } else if (value instanceof String) {
2515   //      //          sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
2516   //      //        }
2517   //      //        return;
2518   //      //      }
2519   //
2520   //      if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
2521   //        if (isLineNumberRulerVisible())
2522   //          showLineNumberRuler();
2523   //        else
2524   //          hideLineNumberRuler();
2525   //        return;
2526   //      }
2527   //
2528   //      if (fLineNumberRulerColumn != null
2529   //        && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
2530   //          || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
2531   //          || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
2532   //
2533   //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2534   //      }
2535   //
2536   //    } finally {
2537   //      super.handlePreferenceStoreChanged(event);
2538   //    }
2539   //  }
2540
2541   //  private boolean isJavaEditorHoverProperty(String property) {
2542   //    return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
2543   //      || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
2544   //      || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
2545   //      || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
2546   //      || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
2547   //      || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
2548   //      || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
2549   //      || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
2550   //  }
2551
2552   /**
2553    * Shows the line number ruler column.
2554    */
2555 //  private void showLineNumberRuler() {
2556 //    IVerticalRuler v = getVerticalRuler();
2557 //    if (v instanceof CompositeRuler) {
2558 //      CompositeRuler c = (CompositeRuler) v;
2559 //      c.addDecorator(1, createLineNumberRulerColumn());
2560 //    }
2561 //  }
2562   private boolean isJavaEditorHoverProperty(String property) {
2563     return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
2564   }
2565
2566   /**
2567          * Return whether the browser like links should be enabled
2568          * according to the preference store settings.
2569          * @return <code>true</code> if the browser like links should be enabled
2570          */
2571   private boolean isBrowserLikeLinks() {
2572     IPreferenceStore store = getPreferenceStore();
2573     return store.getBoolean(BROWSER_LIKE_LINKS);
2574   }
2575
2576   /**
2577    * Enables browser like links.
2578    */
2579   private void enableBrowserLikeLinks() {
2580     if (fMouseListener == null) {
2581       fMouseListener = new MouseClickListener();
2582       fMouseListener.install();
2583     }
2584   }
2585
2586   /**
2587    * Disables browser like links.
2588    */
2589   private void disableBrowserLikeLinks() {
2590     if (fMouseListener != null) {
2591       fMouseListener.uninstall();
2592       fMouseListener = null;
2593     }
2594   }
2595   /**
2596    * Handles a property change event describing a change
2597    * of the java core's preferences and updates the preference
2598    * related editor properties.
2599    * 
2600    * @param event the property change event
2601    */
2602   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
2603     if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
2604       ISourceViewer sourceViewer = getSourceViewer();
2605       if (sourceViewer != null
2606         && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())))
2607         sourceViewer.invalidateTextPresentation();
2608     }
2609   }
2610
2611   /**
2612    * Return whether the line number ruler column should be 
2613    * visible according to the preference store settings.
2614    * @return <code>true</code> if the line numbers should be visible
2615    */
2616 //  protected boolean isLineNumberRulerVisible() {
2617 //    IPreferenceStore store = getPreferenceStore();
2618 //    return store.getBoolean(LINE_NUMBER_RULER);
2619 //  }
2620   /**
2621    * Hides the line number ruler column.
2622    */
2623 //  private void hideLineNumberRuler() {
2624 //    IVerticalRuler v = getVerticalRuler();
2625 //    if (v instanceof CompositeRuler) {
2626 //      CompositeRuler c = (CompositeRuler) v;
2627 //      try {
2628 //        c.removeDecorator(1);
2629 //      } catch (Throwable e) {
2630 //      }
2631 //    }
2632 //  }
2633
2634         /*
2635          * @see AbstractTextEditor#handleCursorPositionChanged()
2636          */
2637         protected void handleCursorPositionChanged() {
2638                 super.handleCursorPositionChanged();
2639                 if (!isEditingScriptRunning() && fUpdater != null)
2640                         fUpdater.post();
2641         }
2642         /*
2643          * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced()
2644          */
2645         protected void handleElementContentReplaced() {
2646                 super.handleElementContentReplaced();
2647                 if (fProjectionModelUpdater != null)
2648                         fProjectionModelUpdater.initialize();
2649         }
2650   /**
2651    * Initializes the given line number ruler column from the preference store.
2652    * @param rulerColumn the ruler column to be initialized
2653    */
2654 //  protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
2655 //    JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
2656 //    IColorManager manager = textTools.getColorManager();
2657 //
2658 //    IPreferenceStore store = getPreferenceStore();
2659 //    if (store != null) {
2660 //
2661 //      RGB rgb = null;
2662 //      // foreground color
2663 //      if (store.contains(LINE_NUMBER_COLOR)) {
2664 //        if (store.isDefault(LINE_NUMBER_COLOR))
2665 //          rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
2666 //        else
2667 //          rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
2668 //      }
2669 //      rulerColumn.setForeground(manager.getColor(rgb));
2670 //
2671 //      rgb = null;
2672 //      // background color
2673 //      if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
2674 //        if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
2675 //          if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
2676 //            rgb = PreferenceConverter.getDefaultColor(store, PREFERENCE_COLOR_BACKGROUND);
2677 //          else
2678 //            rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
2679 //        }
2680 //      }
2681 //      rulerColumn.setBackground(manager.getColor(rgb));
2682 //    }
2683 //  }
2684
2685   /**
2686    * Creates a new line number ruler column that is appropriately initialized.
2687    */
2688 //  protected IVerticalRulerColumn createLineNumberRulerColumn() {
2689 //    fLineNumberRulerColumn = new LineNumberRulerColumn();
2690 //    initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2691 //    return fLineNumberRulerColumn;
2692 //  }
2693
2694   /*
2695    * @see AbstractTextEditor#createVerticalRuler()
2696    */
2697 //  protected IVerticalRuler createVerticalRuler() {
2698 //    CompositeRuler ruler = new CompositeRuler();
2699 //    ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
2700 //    if (isLineNumberRulerVisible())
2701 //      ruler.addDecorator(1, createLineNumberRulerColumn());
2702 //    return ruler;
2703 //  }
2704
2705   private static IRegion getSignedSelection(ITextViewer viewer) {
2706
2707     StyledText text = viewer.getTextWidget();
2708     int caretOffset = text.getCaretOffset();
2709     Point selection = text.getSelection();
2710
2711     // caret left
2712     int offset, length;
2713     if (caretOffset == selection.x) {
2714       offset = selection.y;
2715       length = selection.x - selection.y;
2716
2717       // caret right
2718     } else {
2719       offset = selection.x;
2720       length = selection.y - selection.x;
2721     }
2722
2723     return new Region(offset, length);
2724   }
2725
2726   /** Preference key for matching brackets */
2727   protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
2728   /** Preference key for matching brackets color */
2729   protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
2730   /** Preference key for highlighting current line */
2731   protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
2732   /** Preference key for highlight color of current line */
2733   protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
2734   /** Preference key for showing print marging ruler */
2735   protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
2736   /** Preference key for print margin ruler color */
2737   protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
2738   /** Preference key for print margin ruler column */
2739   protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
2740   /** Preference key for error indication */
2741 //  protected final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION;
2742   /** Preference key for error color */
2743 //  protected final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
2744   /** Preference key for warning indication */
2745 //  protected final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION;
2746   /** Preference key for warning color */
2747 //  protected final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
2748   /** Preference key for task indication */
2749   protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
2750   /** Preference key for task color */
2751   protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
2752   /** Preference key for bookmark indication */
2753   protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
2754   /** Preference key for bookmark color */
2755   protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
2756   /** Preference key for search result indication */
2757   protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
2758   /** Preference key for search result color */
2759   protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
2760   /** Preference key for unknown annotation indication */
2761   protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
2762   /** Preference key for unknown annotation color */
2763   protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
2764   /** Preference key for shwoing the overview ruler */
2765   protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
2766   /** Preference key for error indication in overview ruler */
2767   protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
2768   /** Preference key for warning indication in overview ruler */
2769   protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
2770   /** Preference key for task indication in overview ruler */
2771   protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
2772   /** Preference key for bookmark indication in overview ruler */
2773   protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
2774   /** Preference key for search result indication in overview ruler */
2775   protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
2776   /** Preference key for unknown annotation indication in overview ruler */
2777   protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
2778   //            /** Preference key for compiler task tags */
2779   //            private final static String COMPILER_TASK_TAGS= JavaCore.COMPILER_TASK_TAGS;
2780   /** Preference key for browser like links */
2781   private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
2782   /** Preference key for key modifier of browser like links */
2783   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
2784   /**
2785    * Preference key for key modifier mask of browser like links.
2786    * The value is only used if the value of <code>EDITOR_BROWSER_LIKE_LINKS</code>
2787    * cannot be resolved to valid SWT modifier bits.
2788    * 
2789    * @since 2.1.1
2790    */
2791   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
2792
2793   private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
2794
2795   private static boolean isBracket(char character) {
2796     for (int i = 0; i != BRACKETS.length; ++i)
2797       if (character == BRACKETS[i])
2798         return true;
2799     return false;
2800   }
2801
2802   private static boolean isSurroundedByBrackets(IDocument document, int offset) {
2803     if (offset == 0 || offset == document.getLength())
2804       return false;
2805
2806     try {
2807       return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
2808
2809     } catch (BadLocationException e) {
2810       return false;
2811     }
2812   }
2813
2814 //  protected void configureSourceViewerDecorationSupport() {
2815 //
2816 //    fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
2817 //
2818 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2819 //      AnnotationType.UNKNOWN,
2820 //      UNKNOWN_INDICATION_COLOR,
2821 //      UNKNOWN_INDICATION,
2822 //      UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
2823 //      0);
2824 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2825 //      AnnotationType.BOOKMARK,
2826 //      BOOKMARK_INDICATION_COLOR,
2827 //      BOOKMARK_INDICATION,
2828 //      BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
2829 //      1);
2830 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2831 //      AnnotationType.TASK,
2832 //      TASK_INDICATION_COLOR,
2833 //      TASK_INDICATION,
2834 //      TASK_INDICATION_IN_OVERVIEW_RULER, 
2835 //      2);
2836 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2837 //      AnnotationType.SEARCH,
2838 //      SEARCH_RESULT_INDICATION_COLOR,
2839 //      SEARCH_RESULT_INDICATION,
2840 //      SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
2841 //      3);
2842 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2843 //      AnnotationType.WARNING,
2844 //      WARNING_INDICATION_COLOR,
2845 //      WARNING_INDICATION,
2846 //      WARNING_INDICATION_IN_OVERVIEW_RULER,
2847 //      4);
2848 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2849 //      AnnotationType.ERROR,
2850 //      ERROR_INDICATION_COLOR,
2851 //      ERROR_INDICATION,
2852 //      ERROR_INDICATION_IN_OVERVIEW_RULER,
2853 //      5);
2854 //
2855 //    fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
2856 //    fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
2857 //    fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
2858 //
2859 //    fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
2860 //
2861 //  }
2862   /**
2863          * Returns the Java element wrapped by this editors input.
2864          * 
2865          * @return the Java element wrapped by this editors input.
2866          * @since 3.0
2867          */
2868         abstract protected IJavaElement getInputJavaElement();
2869
2870   /**
2871     * Jumps to the matching bracket.
2872     */
2873   public void gotoMatchingBracket() {
2874
2875     ISourceViewer sourceViewer = getSourceViewer();
2876     IDocument document = sourceViewer.getDocument();
2877     if (document == null)
2878       return;
2879
2880     IRegion selection = getSignedSelection(sourceViewer);
2881
2882     int selectionLength = Math.abs(selection.getLength());
2883     if (selectionLength > 1) {
2884       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$               
2885       sourceViewer.getTextWidget().getDisplay().beep();
2886       return;
2887     }
2888
2889     // #26314
2890     int sourceCaretOffset = selection.getOffset() + selection.getLength();
2891     if (isSurroundedByBrackets(document, sourceCaretOffset))
2892       sourceCaretOffset -= selection.getLength();
2893
2894     IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
2895     if (region == null) {
2896       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$              
2897       sourceViewer.getTextWidget().getDisplay().beep();
2898       return;
2899     }
2900
2901     int offset = region.getOffset();
2902     int length = region.getLength();
2903
2904     if (length < 1)
2905       return;
2906
2907     int anchor = fBracketMatcher.getAnchor();
2908     int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
2909
2910     boolean visible = false;
2911     if (sourceViewer instanceof ITextViewerExtension3) {
2912       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
2913       visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
2914     } else {
2915       IRegion visibleRegion = sourceViewer.getVisibleRegion();
2916       visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
2917     }
2918
2919     if (!visible) {
2920       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$          
2921       sourceViewer.getTextWidget().getDisplay().beep();
2922       return;
2923     }
2924
2925     if (selection.getLength() < 0)
2926       targetOffset -= selection.getLength();
2927
2928     sourceViewer.setSelectedRange(targetOffset, selection.getLength());
2929     sourceViewer.revealRange(targetOffset, selection.getLength());
2930   }
2931   /**
2932      * Ses the given message as error message to this editor's status line.
2933      * @param msg message to be set
2934      */
2935   protected void setStatusLineErrorMessage(String msg) {
2936     IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
2937     if (statusLine != null)
2938       statusLine.setMessage(true, msg, null);
2939   }
2940
2941   /**
2942      * Returns a segmentation of the line of the given document appropriate for bidi rendering.
2943      * The default implementation returns only the string literals of a php code line as segments.
2944      * 
2945      * @param document the document
2946      * @param lineOffset the offset of the line
2947      * @return the line's bidi segmentation
2948      * @throws BadLocationException in case lineOffset is not valid in document
2949      */
2950   public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException {
2951
2952     IRegion line = document.getLineInformationOfOffset(lineOffset);
2953     ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength());
2954
2955     List segmentation = new ArrayList();
2956     for (int i = 0; i < linePartitioning.length; i++) {
2957       if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i].getType()))
2958         segmentation.add(linePartitioning[i]);
2959     }
2960
2961     if (segmentation.size() == 0)
2962       return null;
2963
2964     int size = segmentation.size();
2965     int[] segments = new int[size * 2 + 1];
2966
2967     int j = 0;
2968     for (int i = 0; i < size; i++) {
2969       ITypedRegion segment = (ITypedRegion) segmentation.get(i);
2970
2971       if (i == 0)
2972         segments[j++] = 0;
2973
2974       int offset = segment.getOffset() - lineOffset;
2975       if (offset > segments[j - 1])
2976         segments[j++] = offset;
2977
2978       if (offset + segment.getLength() >= line.getLength())
2979         break;
2980
2981       segments[j++] = offset + segment.getLength();
2982     }
2983
2984     if (j < segments.length) {
2985       int[] result = new int[j];
2986       System.arraycopy(segments, 0, result, 0, j);
2987       segments = result;
2988     }
2989
2990     return segments;
2991   }
2992   /**
2993      * Returns a segmentation of the given line appropriate for bidi rendering. The default
2994      * implementation returns only the string literals of a php code line as segments.
2995      * 
2996      * @param lineOffset the offset of the line
2997      * @param line the content of the line
2998      * @return the line's bidi segmentation
2999      */
3000   protected int[] getBidiLineSegments(int lineOffset, String line) {
3001     IDocumentProvider provider = getDocumentProvider();
3002     if (provider != null && line != null && line.length() > 0) {
3003       IDocument document = provider.getDocument(getEditorInput());
3004       if (document != null)
3005         try {
3006           return getBidiLineSegments(document, lineOffset);
3007         } catch (BadLocationException x) {
3008           // ignore
3009         }
3010     }
3011     return null;
3012   }
3013
3014   /*
3015    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3016    */
3017   //  protected final ISourceViewer createSourceViewer(
3018   //    Composite parent,
3019   //    IVerticalRuler ruler,
3020   //    int styles) {
3021   //    ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
3022   //    StyledText text = viewer.getTextWidget();
3023   //    text.addBidiSegmentListener(new BidiSegmentListener() {
3024   //      public void lineGetSegments(BidiSegmentEvent event) {
3025   //        event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
3026   //      }
3027   //    });
3028   //    //   JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
3029   //    return viewer;
3030   //  }
3031   
3032   public final ISourceViewer getViewer() {
3033         return getSourceViewer();
3034   }
3035   
3036
3037 //  protected void showOverviewRuler() {
3038 //    if (fOverviewRuler != null) {
3039 //      if (getSourceViewer() instanceof ISourceViewerExtension) {
3040 //        ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(true);
3041 //        fSourceViewerDecorationSupport.updateOverviewDecorations();
3042 //      }
3043 //    }
3044 //  }
3045 //
3046 //  protected void hideOverviewRuler() {
3047 //    if (getSourceViewer() instanceof ISourceViewerExtension) {
3048 //      fSourceViewerDecorationSupport.hideAnnotationOverview();
3049 //      ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(false);
3050 //    }
3051 //  }
3052
3053 //  protected boolean isOverviewRulerVisible() {
3054 //    IPreferenceStore store = getPreferenceStore();
3055 //    return store.getBoolean(OVERVIEW_RULER);
3056 //  }
3057   /*
3058    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3059    */
3060 //  protected ISourceViewer createJavaSourceViewer(
3061 //    Composite parent,
3062 //    IVerticalRuler ruler,
3063 //    IOverviewRuler overviewRuler,
3064 //    boolean isOverviewRulerVisible,
3065 //    int styles) {
3066 //    return new SourceViewer(parent, ruler, overviewRuler, isOverviewRulerVisible(), styles);
3067 //  }
3068         /*
3069          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3070          */
3071         protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
3072                 return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, store);
3073         }
3074   /*
3075          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3076          */
3077         protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
3078                 
3079                 ISourceViewer viewer= createJavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, getPreferenceStore());
3080                 
3081                 StyledText text= viewer.getTextWidget();
3082                 text.addBidiSegmentListener(new  BidiSegmentListener() {
3083                         public void lineGetSegments(BidiSegmentEvent event) {
3084                                 event.segments= getBidiLineSegments(event.lineOffset, event.lineText);
3085                         }
3086                 });
3087                 
3088 //              JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
3089
3090                 // ensure source viewer decoration support has been created and configured
3091                 getSourceViewerDecorationSupport(viewer);                               
3092                 
3093                 return viewer;
3094         }
3095         /**
3096          * Creates and returns the preference store for this Java editor with the given input.
3097          *
3098          * @param input The editor input for which to create the preference store
3099          * @return the preference store for this editor
3100          *
3101          * @since 3.0
3102          */
3103         private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
3104                 List stores= new ArrayList(3);
3105
3106                 IJavaProject project= EditorUtility.getJavaProject(input);
3107                 if (project != null)
3108                         stores.add(new OptionsAdapter(project.getOptions(false), PHPeclipsePlugin.getDefault().getMockupPreferenceStore(), new OptionsAdapter.IPropertyChangeEventFilter() {
3109
3110                                 public boolean isFiltered(PropertyChangeEvent event) {
3111                                         IJavaElement inputJavaElement= getInputJavaElement();
3112                                         IJavaProject javaProject= inputJavaElement != null ? inputJavaElement.getJavaProject() : null;
3113                                         if (javaProject == null)
3114                                                 return true;
3115                                         
3116                                         return !javaProject.getProject().equals(event.getSource());
3117                                 }
3118                                 
3119                         }));
3120                 
3121                 stores.add(PHPeclipsePlugin.getDefault().getPreferenceStore());
3122                 stores.add(new PreferencesAdapter(JavaCore.getPlugin().getPluginPreferences()));
3123                 stores.add(EditorsUI.getPreferenceStore());
3124                 
3125                 return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()]));
3126         }
3127           /*
3128          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3129          */
3130 //      protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean isOverviewRulerVisible, int styles) {
3131 //              return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles);
3132 //      }
3133   /*
3134    * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
3135    */
3136   protected boolean affectsTextPresentation(PropertyChangeEvent event) {
3137     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
3138     return textTools.affectsBehavior(event);
3139   }
3140
3141   /**
3142    * Jumps to the error next according to the given direction.
3143    */
3144   public void gotoError(boolean forward) {
3145
3146     ISelectionProvider provider = getSelectionProvider();
3147
3148     ITextSelection s = (ITextSelection) provider.getSelection();
3149     Position errorPosition = new Position(0, 0);
3150     IJavaAnnotation nextError = getNextError(s.getOffset(), forward, errorPosition);
3151
3152     if (nextError != null) {
3153
3154       IMarker marker = null;
3155       if (nextError instanceof MarkerAnnotation)
3156         marker = ((MarkerAnnotation) nextError).getMarker();
3157       else {
3158         Iterator e = nextError.getOverlaidIterator();
3159         if (e != null) {
3160           while (e.hasNext()) {
3161             Object o = e.next();
3162             if (o instanceof MarkerAnnotation) {
3163               marker = ((MarkerAnnotation) o).getMarker();
3164               break;
3165             }
3166           }
3167         }
3168       }
3169
3170       if (marker != null) {
3171         IWorkbenchPage page = getSite().getPage();
3172         IViewPart view = view = page.findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
3173         if (view instanceof TaskList) {
3174           StructuredSelection ss = new StructuredSelection(marker);
3175           ((TaskList) view).setSelection(ss, true);
3176         }
3177       }
3178
3179       selectAndReveal(errorPosition.getOffset(), errorPosition.getLength());
3180 //      setStatusLineErrorMessage(nextError.getMessage());
3181
3182     } else {
3183
3184       setStatusLineErrorMessage(null);
3185
3186     }
3187   }
3188
3189   private IJavaAnnotation getNextError(int offset, boolean forward, Position errorPosition) {
3190
3191     IJavaAnnotation nextError = null;
3192     Position nextErrorPosition = null;
3193
3194     IDocument document = getDocumentProvider().getDocument(getEditorInput());
3195     int endOfDocument = document.getLength();
3196     int distance = 0;
3197
3198     IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
3199     Iterator e = new JavaAnnotationIterator(model, false);
3200     while (e.hasNext()) {
3201
3202       IJavaAnnotation a = (IJavaAnnotation) e.next();
3203       if (a.hasOverlay() || !a.isProblem())
3204         continue;
3205
3206       Position p = model.getPosition((Annotation) a);
3207       if (!p.includes(offset)) {
3208
3209         int currentDistance = 0;
3210
3211         if (forward) {
3212           currentDistance = p.getOffset() - offset;
3213           if (currentDistance < 0)
3214             currentDistance = endOfDocument - offset + p.getOffset();
3215         } else {
3216           currentDistance = offset - p.getOffset();
3217           if (currentDistance < 0)
3218             currentDistance = offset + endOfDocument - p.getOffset();
3219         }
3220
3221         if (nextError == null || currentDistance < distance) {
3222           distance = currentDistance;
3223           nextError = a;
3224           nextErrorPosition = p;
3225         }
3226       }
3227     }
3228
3229     if (nextErrorPosition != null) {
3230       errorPosition.setOffset(nextErrorPosition.getOffset());
3231       errorPosition.setLength(nextErrorPosition.getLength());
3232     }
3233
3234     return nextError;
3235   }
3236   void removeOccurrenceAnnotations() {
3237         IDocumentProvider documentProvider= getDocumentProvider();
3238         if (documentProvider == null)
3239                 return;
3240         
3241         IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
3242         if (annotationModel == null || fOccurrenceAnnotations == null)
3243                 return;
3244
3245         synchronized (annotationModel) {
3246                 if (annotationModel instanceof IAnnotationModelExtension) {
3247                         ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null);
3248                 } else {
3249                         for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++)
3250                                 annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
3251                 }
3252                 fOccurrenceAnnotations= null;
3253         }
3254 }
3255 //  protected void uninstallOverrideIndicator() {
3256 //      if (fOverrideIndicatorManager != null) {
3257 //              fOverrideIndicatorManager.removeAnnotations();
3258 //              fOverrideIndicatorManager= null;
3259 //      }
3260 //}
3261
3262 protected void installOverrideIndicator(boolean waitForReconcilation) {
3263 //      uninstallOverrideIndicator();
3264         IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
3265 //      IJavaElement inputElement= getInputJavaElement();
3266
3267 //      if (model == null || inputElement == null)
3268 //              return;
3269
3270 //      CompilationUnit ast= PHPeclipsePlugin.getDefault().getASTProvider().getAST(inputElement, true, null);
3271 //      fOverrideIndicatorManager= new OverrideIndicatorManager(model, inputElement, ast);              
3272 }
3273
3274 /**
3275  * Tells whether override indicators are shown.
3276  * 
3277  * @return <code>true</code> if the override indicators are shown
3278  * @since 3.0
3279  */
3280 //protected boolean isShowingOverrideIndicators() {
3281 //      AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
3282 //      IPreferenceStore store= getPreferenceStore();
3283 //      return getBoolean(store, preference.getHighlightPreferenceKey())
3284 //              || getBoolean(store, preference.getVerticalRulerPreferenceKey())
3285 //              || getBoolean(store, preference.getOverviewRulerPreferenceKey())
3286 //              || getBoolean(store, preference.getTextPreferenceKey());
3287 //}
3288
3289 /**
3290  * Returns the boolean preference for the given key.
3291  * 
3292  * @param store the preference store
3293  * @param key the preference key
3294  * @return <code>true</code> if the key exists in the store and its value is <code>true</code>
3295  * @since 3.0
3296  */
3297 private boolean getBoolean(IPreferenceStore store, String key) {
3298         return key != null && store.getBoolean(key);
3299 }
3300
3301   /**
3302          * Returns the folding action group, or <code>null</code> if there is none.
3303          * 
3304          * @return the folding action group, or <code>null</code> if there is none
3305          * @since 3.0
3306          */
3307         protected FoldingActionGroup getFoldingActionGroup() {
3308                 return fFoldingGroup;
3309         }
3310 }