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