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