Syntax highlighting is changeable.
[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          * The override and implements indicator manager for this editor.
1686          * @since 3.0
1687          */
1688 //      protected OverrideIndicatorManager fOverrideIndicatorManager;
1689   /**
1690    * The action group for folding.
1691    * 
1692    * @since 3.0
1693    */
1694   private FoldingActionGroup fFoldingGroup;
1695
1696   /** The information presenter. */
1697   private InformationPresenter fInformationPresenter;
1698
1699   /** The annotation access */
1700   //  protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
1701   /** The overview ruler */
1702   protected OverviewRuler isOverviewRulerVisible;
1703
1704   /** The source viewer decoration support */
1705   //protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
1706   /** The overview ruler */
1707   //protected OverviewRuler fOverviewRuler;
1708   /** The preference property change listener for java core. */
1709   private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
1710
1711   /**
1712    * Returns the most narrow java element including the given offset
1713    * 
1714    * @param offset
1715    *          the offset inside of the requested element
1716    */
1717   abstract protected IJavaElement getElementAt(int offset);
1718
1719   /**
1720    * Returns the java element of this editor's input corresponding to the given IJavaElement
1721    */
1722   abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
1723
1724   /**
1725    * Sets the input of the editor's outline page.
1726    */
1727   abstract protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input);
1728
1729   /**
1730    * Default constructor.
1731    */
1732   public PHPEditor() {
1733     super();
1734   }
1735
1736   /*
1737    * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
1738    */
1739   protected void initializeKeyBindingScopes() {
1740     setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$
1741   }
1742
1743   /*
1744    * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
1745    */
1746   protected void initializeEditor() {
1747     //jsurfer old code
1748 //    JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
1749 //    setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this, IPHPPartitions.PHP_PARTITIONING)); //, IJavaPartitions.JAVA_PARTITIONING));
1750     IPreferenceStore store= createCombinedPreferenceStore(null);
1751         setPreferenceStore(store);
1752     JavaTextTools textTools= PHPeclipsePlugin.getDefault().getJavaTextTools();
1753         setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this, IPHPPartitions.PHP_PARTITIONING));
1754     // TODO changed in 3.x ?
1755 //    setRangeIndicator(new DefaultRangeIndicator());
1756 //    if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
1757 //      fUpdater = new OutlinePageSelectionUpdater();
1758     // jsurfer end
1759
1760     //          IPreferenceStore store= createCombinedPreferenceStore(null);
1761     //          setPreferenceStore(store);
1762     //          JavaTextTools textTools=
1763     // PHPeclipsePlugin.getDefault().getJavaTextTools();
1764     //          setSourceViewerConfiguration(new
1765     // JavaSourceViewerConfiguration(textTools.getColorManager(), store,
1766     // this, IJavaPartitions.JAVA_PARTITIONING));
1767     //          fMarkOccurrenceAnnotations=
1768     // store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
1769     //          fStickyOccurrenceAnnotations=
1770     // store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
1771     //          fMarkTypeOccurrences=
1772     // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
1773     //          fMarkMethodOccurrences=
1774     // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
1775     //          fMarkConstantOccurrences=
1776     // store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
1777     //          fMarkFieldOccurrences=
1778     // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
1779     //          fMarkLocalVariableypeOccurrences=
1780     // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
1781     //          fMarkExceptionOccurrences=
1782     // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
1783     //          fMarkMethodExitPoints=
1784     // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
1785   }
1786
1787   /*
1788    * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
1789    */
1790   protected void updatePropertyDependentActions() {
1791     super.updatePropertyDependentActions();
1792     if (fEncodingSupport != null)
1793       fEncodingSupport.reset();
1794   }
1795
1796   /*
1797    * Update the hovering behavior depending on the preferences.
1798    */
1799   private void updateHoverBehavior() {
1800     SourceViewerConfiguration configuration = getSourceViewerConfiguration();
1801     String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
1802
1803     for (int i = 0; i < types.length; i++) {
1804
1805       String t = types[i];
1806
1807       int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
1808
1809       ISourceViewer sourceViewer = getSourceViewer();
1810       if (sourceViewer instanceof ITextViewerExtension2) {
1811         if (stateMasks != null) {
1812           for (int j = 0; j < stateMasks.length; j++) {
1813             int stateMask = stateMasks[j];
1814             ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
1815             ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
1816           }
1817         } else {
1818           ITextHover textHover = configuration.getTextHover(sourceViewer, t);
1819           ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
1820         }
1821       } else
1822         sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
1823     }
1824   }
1825
1826   public void updatedTitleImage(Image image) {
1827     setTitleImage(image);
1828   }
1829
1830   /*
1831    * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1832    */
1833   public Object getViewPartInput() {
1834     return getEditorInput().getAdapter(IResource.class);
1835   }
1836
1837   /*
1838    * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
1839    */
1840   protected void doSetSelection(ISelection selection) {
1841     super.doSetSelection(selection);
1842     synchronizeOutlinePageSelection();
1843   }
1844
1845   boolean isFoldingEnabled() {
1846     return PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
1847   }
1848
1849   /*
1850    * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt. widgets.Composite)
1851    */
1852   public void createPartControl(Composite parent) {
1853     super.createPartControl(parent);
1854
1855     //fSourceViewerDecorationSupport.install(getPreferenceStore());
1856
1857     ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
1858
1859     fProjectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
1860     fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
1861     fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
1862     fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() {
1863       public IInformationControl createInformationControl(Shell shell) {
1864         return new CustomSourceInformationControl(shell, IDocument.DEFAULT_CONTENT_TYPE);
1865       }
1866     });
1867     fProjectionSupport.install();
1868
1869     fProjectionModelUpdater = PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
1870     if (fProjectionModelUpdater != null)
1871       fProjectionModelUpdater.install(this, projectionViewer);
1872
1873     if (isFoldingEnabled())
1874       projectionViewer.doOperation(ProjectionViewer.TOGGLE);
1875     Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1876     preferences.addPropertyChangeListener(fPropertyChangeListener);
1877
1878     IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
1879       public IInformationControl createInformationControl(Shell parent) {
1880         boolean cutDown = false;
1881         int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
1882         return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown));
1883       }
1884     };
1885
1886     fInformationPresenter = new InformationPresenter(informationControlCreator);
1887     fInformationPresenter.setSizeConstraints(60, 10, true, true);
1888     fInformationPresenter.install(getSourceViewer());
1889
1890     fEditorSelectionChangedListener = new EditorSelectionChangedListener();
1891     fEditorSelectionChangedListener.install(getSelectionProvider());
1892
1893     if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE))
1894       enableOverwriteMode(false);
1895
1896     //  getEditorSite().getShell().addShellListener(fActivationListener);
1897   }
1898
1899   protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
1900         
1901         support.setCharacterPairMatcher(fBracketMatcher);
1902         support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
1903         
1904         super.configureSourceViewerDecorationSupport(support);
1905   }
1906         
1907   /**
1908    * Returns this document's complete text.
1909    * 
1910    * @return the document's complete text
1911    */
1912   public String get() {
1913     IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1914     return doc.get();
1915   }
1916
1917   /**
1918    * Sets the outliner's context menu ID.
1919    */
1920   protected void setOutlinerContextMenuId(String menuId) {
1921     fOutlinerContextMenuId = menuId;
1922   }
1923
1924   /**
1925    * Returns the standard action group of this editor.
1926    */
1927   protected ActionGroup getActionGroup() {
1928     return fActionGroups;
1929   }
1930
1931   //  public JavaOutlinePage getfOutlinePage() {
1932   //    return fOutlinePage;
1933   //  }
1934
1935   /**
1936    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method extend the actions to add those
1937    * specific to the receiver
1938    */
1939   protected void createActions() {
1940     super.createActions();
1941
1942     fFoldingGroup = new FoldingActionGroup(this, getViewer());
1943
1944     ResourceAction resAction = new TextOperationAction(PHPEditorMessages.getResourceBundle(),
1945         "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
1946     resAction = new InformationDispatchAction(PHPEditorMessages.getResourceBundle(),
1947         "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
1948     resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
1949     setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
1950     //  WorkbenchHelp.setHelp(resAction,
1951     // IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
1952
1953     Action action = new GotoMatchingBracketAction(this);
1954     action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
1955     setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
1956
1957     //  action= new
1958     // TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.",
1959     // this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
1960     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
1961     //  setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
1962     //// WorkbenchHelp.setHelp(action,
1963     // IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
1964     //
1965     //  action= new
1966     // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.",
1967     // this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
1968     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
1969     //  setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE,
1970     // action);
1971     //// WorkbenchHelp.setHelp(action,
1972     // IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
1973     //  
1974     //  action= new
1975     // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.",
1976     // this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
1977     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
1978     //  setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY,
1979     // action);
1980     //// WorkbenchHelp.setHelp(action,
1981     // IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
1982
1983     fEncodingSupport = new DefaultEncodingSupport();
1984     fEncodingSupport.initialize(this);
1985
1986     //  fSelectionHistory= new SelectionHistory(this);
1987     //
1988     //  action= new StructureSelectEnclosingAction(this, fSelectionHistory);
1989     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);
1990     //  setAction(StructureSelectionAction.ENCLOSING, action);
1991     //
1992     //  action= new StructureSelectNextAction(this, fSelectionHistory);
1993     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
1994     //  setAction(StructureSelectionAction.NEXT, action);
1995     //
1996     //  action= new StructureSelectPreviousAction(this, fSelectionHistory);
1997     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
1998     //  setAction(StructureSelectionAction.PREVIOUS, action);
1999     //
2000     //  StructureSelectHistoryAction historyAction= new
2001     // StructureSelectHistoryAction(this, fSelectionHistory);
2002     //  historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);
2003     //  setAction(StructureSelectionAction.HISTORY, historyAction);
2004     //  fSelectionHistory.setHistoryAction(historyAction);
2005     //                  
2006     //  action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
2007     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
2008     //  setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
2009     //
2010     //  action=
2011     // GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
2012     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
2013     //  setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
2014     //  
2015     //  action= new QuickFormatAction();
2016     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
2017     //  setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
2018     //
2019     //  action= new RemoveOccurrenceAnnotations(this);
2020     //  action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
2021     //  setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
2022
2023     // add annotation actions
2024     action = new JavaSelectMarkerRulerAction2(PHPEditorMessages.getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
2025     setAction("AnnotationAction", action); //$NON-NLS-1$
2026   }
2027
2028   private void internalDoSetInput(IEditorInput input) throws CoreException {
2029     super.doSetInput(input);
2030
2031     if (getSourceViewer() instanceof JavaSourceViewer) {
2032                 JavaSourceViewer viewer= (JavaSourceViewer)getSourceViewer();
2033                 if (viewer.getReconciler() == null) {
2034                         IReconciler reconciler= getSourceViewerConfiguration().getReconciler(viewer);
2035                         if (reconciler != null) {
2036                                 reconciler.install(viewer);
2037                                 viewer.setReconciler(reconciler);
2038                         }
2039                 }
2040         }
2041         
2042     if (fEncodingSupport != null)
2043       fEncodingSupport.reset();
2044
2045     setOutlinePageInput(fOutlinePage, input);
2046
2047     if (fProjectionModelUpdater != null)
2048       fProjectionModelUpdater.initialize();
2049
2050 //    if (isShowingOverrideIndicators())
2051 //              installOverrideIndicator(false);
2052   }
2053
2054   /*
2055    * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
2056    * @since 3.0
2057    */
2058   protected void setPreferenceStore(IPreferenceStore store) {
2059     super.setPreferenceStore(store);
2060     if (getSourceViewerConfiguration() instanceof PHPSourceViewerConfiguration) {
2061       JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
2062       setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this,
2063           IPHPPartitions.PHP_PARTITIONING));
2064     }
2065     if (getSourceViewer() instanceof JavaSourceViewer)
2066       ((JavaSourceViewer) getSourceViewer()).setPreferenceStore(store);
2067   }
2068
2069   /**
2070    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs any extra disposal
2071    * actions required by the php editor.
2072    */
2073   public void dispose() {
2074     if (fProjectionModelUpdater != null) {
2075       fProjectionModelUpdater.uninstall();
2076       fProjectionModelUpdater = null;
2077     }
2078
2079     if (fProjectionSupport != null) {
2080       fProjectionSupport.dispose();
2081       fProjectionSupport = null;
2082     }
2083     //   PHPEditorEnvironment.disconnect(this);
2084     if (fOutlinePage != null)
2085       fOutlinePage.setInput(null);
2086
2087     if (fActionGroups != null)
2088       fActionGroups.dispose();
2089
2090     if (isBrowserLikeLinks())
2091       disableBrowserLikeLinks();
2092
2093     if (fEncodingSupport != null) {
2094       fEncodingSupport.dispose();
2095       fEncodingSupport = null;
2096     }
2097
2098     if (fPropertyChangeListener != null) {
2099       Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
2100       preferences.removePropertyChangeListener(fPropertyChangeListener);
2101       fPropertyChangeListener = null;
2102     }
2103
2104     //    if (fSourceViewerDecorationSupport != null) {
2105     //      fSourceViewerDecorationSupport.dispose();
2106     //      fSourceViewerDecorationSupport = null;
2107     //    }
2108
2109     if (fBracketMatcher != null) {
2110       fBracketMatcher.dispose();
2111       fBracketMatcher = null;
2112     }
2113
2114     if (fEditorSelectionChangedListener != null) {
2115       fEditorSelectionChangedListener.uninstall(getSelectionProvider());
2116       fEditorSelectionChangedListener = null;
2117     }
2118
2119     super.dispose();
2120   }
2121
2122   /**
2123    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs any extra revert behavior
2124    * required by the php editor.
2125    */
2126   //  public void doRevertToSaved() {
2127   //    super.doRevertToSaved();
2128   //    if (fOutlinePage != null)
2129   //      fOutlinePage.update();
2130   //  }
2131   /**
2132    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs any extra save behavior
2133    * required by the php editor.
2134    */
2135   //  public void doSave(IProgressMonitor monitor) {
2136   //    super.doSave(monitor);
2137   // compile or not, according to the user preferences
2138   // IPreferenceStore store = getPreferenceStore();
2139   // the parse on save was changed to the eclipse "builders" concept
2140   //    if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
2141   //      IAction a = PHPParserAction.getInstance();
2142   //      if (a != null)
2143   //        a.run();
2144   //    }
2145   //    if (SWT.getPlatform().equals("win32")) {
2146   //      IAction a = ShowExternalPreviewAction.getInstance();
2147   //      if (a != null)
2148   //        a.run();
2149   //    }
2150   //    if (fOutlinePage != null)
2151   //      fOutlinePage.update();
2152   //  }
2153   /**
2154    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs any extra save as
2155    * behavior required by the php editor.
2156    */
2157   //  public void doSaveAs() {
2158   //    super.doSaveAs();
2159   //    if (fOutlinePage != null)
2160   //      fOutlinePage.update();
2161   //  }
2162   /*
2163    * @see StatusTextEditor#getStatusHeader(IStatus)
2164    */
2165   protected String getStatusHeader(IStatus status) {
2166     if (fEncodingSupport != null) {
2167       String message = fEncodingSupport.getStatusHeader(status);
2168       if (message != null)
2169         return message;
2170     }
2171     return super.getStatusHeader(status);
2172   }
2173
2174   /*
2175    * @see StatusTextEditor#getStatusBanner(IStatus)
2176    */
2177   protected String getStatusBanner(IStatus status) {
2178     if (fEncodingSupport != null) {
2179       String message = fEncodingSupport.getStatusBanner(status);
2180       if (message != null)
2181         return message;
2182     }
2183     return super.getStatusBanner(status);
2184   }
2185
2186   /*
2187    * @see StatusTextEditor#getStatusMessage(IStatus)
2188    */
2189   protected String getStatusMessage(IStatus status) {
2190     if (fEncodingSupport != null) {
2191       String message = fEncodingSupport.getStatusMessage(status);
2192       if (message != null)
2193         return message;
2194     }
2195     return super.getStatusMessage(status);
2196   }
2197
2198   /**
2199    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs sets the input of the
2200    * outline page after AbstractTextEditor has set input.
2201    */
2202   //  protected void doSetInput(IEditorInput input) throws CoreException {
2203   //    super.doSetInput(input);
2204   //
2205   //    if (fEncodingSupport != null)
2206   //      fEncodingSupport.reset();
2207   //    if (fOutlinePage != null)
2208   //      fOutlinePage.setInput(input);
2209   //    // setOutlinePageInput(fOutlinePage, input);
2210   //  }
2211   protected void doSetInput(IEditorInput input) throws CoreException {
2212     super.doSetInput(input);
2213     if (fEncodingSupport != null)
2214       fEncodingSupport.reset();
2215     setOutlinePageInput(fOutlinePage, input);
2216   }
2217
2218   /*
2219    * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
2220    */
2221   //  public Object getViewPartInput() {
2222   //    return getEditorInput().getAdapter(IFile.class);
2223   //  }
2224   /**
2225    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method adds any PHPEditor specific
2226    * entries.
2227    */
2228   public void editorContextMenuAboutToShow(MenuManager menu) {
2229     super.editorContextMenuAboutToShow(menu);
2230     menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
2231     menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
2232
2233     ActionContext context = new ActionContext(getSelectionProvider().getSelection());
2234     fContextMenuGroup.setContext(context);
2235     fContextMenuGroup.fillContextMenu(menu);
2236     fContextMenuGroup.setContext(null);
2237     //    addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format");
2238     // //$NON-NLS-1$
2239     //
2240     //    ActionContext context =
2241     //      new ActionContext(getSelectionProvider().getSelection());
2242     //    fContextMenuGroup.setContext(context);
2243     //    fContextMenuGroup.fillContextMenu(menu);
2244     //    fContextMenuGroup.setContext(null);
2245   }
2246
2247   /**
2248    * Creates the outline page used with this editor.
2249    */
2250   protected JavaOutlinePage createOutlinePage() {
2251     JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
2252     fOutlineSelectionChangedListener.install(page);
2253     setOutlinePageInput(page, getEditorInput());
2254     return page;
2255   }
2256
2257   /**
2258    * Informs the editor that its outliner has been closed.
2259    */
2260   public void outlinePageClosed() {
2261     if (fOutlinePage != null) {
2262       fOutlineSelectionChangedListener.uninstall(fOutlinePage);
2263       fOutlinePage = null;
2264       resetHighlightRange();
2265     }
2266   }
2267
2268   /**
2269    * Synchronizes the outliner selection with the given element position in the editor.
2270    * 
2271    * @param element
2272    *          the java element to select
2273    */
2274   protected void synchronizeOutlinePage(ISourceReference element) {
2275     synchronizeOutlinePage(element, true);
2276   }
2277
2278   /**
2279    * Synchronizes the outliner selection with the given element position in the editor.
2280    * 
2281    * @param element
2282    *          the java element to select
2283    * @param checkIfOutlinePageActive
2284    *          <code>true</code> if check for active outline page needs to be done
2285    */
2286   protected void synchronizeOutlinePage(ISourceReference element, boolean checkIfOutlinePageActive) {
2287     if (fOutlinePage != null && element != null && !(checkIfOutlinePageActive && isJavaOutlinePageActive())) {
2288       fOutlineSelectionChangedListener.uninstall(fOutlinePage);
2289       fOutlinePage.select(element);
2290       fOutlineSelectionChangedListener.install(fOutlinePage);
2291     }
2292   }
2293
2294   /**
2295    * Synchronizes the outliner selection with the actual cursor position in the editor.
2296    */
2297   public void synchronizeOutlinePageSelection() {
2298     synchronizeOutlinePage(computeHighlightRangeSourceReference());
2299
2300     //    ISourceViewer sourceViewer = getSourceViewer();
2301     //    if (sourceViewer == null || fOutlinePage == null)
2302     //      return;
2303     //
2304     //    StyledText styledText = sourceViewer.getTextWidget();
2305     //    if (styledText == null)
2306     //      return;
2307     //
2308     //    int caret = 0;
2309     //    if (sourceViewer instanceof ITextViewerExtension3) {
2310     //      ITextViewerExtension3 extension = (ITextViewerExtension3)
2311     // sourceViewer;
2312     //      caret =
2313     // extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
2314     //    } else {
2315     //      int offset = sourceViewer.getVisibleRegion().getOffset();
2316     //      caret = offset + styledText.getCaretOffset();
2317     //    }
2318     //
2319     //    IJavaElement element = getElementAt(caret);
2320     //    if (element instanceof ISourceReference) {
2321     //      fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
2322     //      fOutlinePage.select((ISourceReference) element);
2323     //      fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
2324     //    }
2325   }
2326
2327   protected void setSelection(ISourceReference reference, boolean moveCursor) {
2328
2329     ISelection selection = getSelectionProvider().getSelection();
2330     if (selection instanceof TextSelection) {
2331       TextSelection textSelection = (TextSelection) selection;
2332       if (textSelection.getOffset() != 0 || textSelection.getLength() != 0)
2333         markInNavigationHistory();
2334     }
2335
2336     if (reference != null) {
2337
2338       StyledText textWidget = null;
2339
2340       ISourceViewer sourceViewer = getSourceViewer();
2341       if (sourceViewer != null)
2342         textWidget = sourceViewer.getTextWidget();
2343
2344       if (textWidget == null)
2345         return;
2346
2347       try {
2348
2349         ISourceRange range = reference.getSourceRange();
2350         if (range == null)
2351           return;
2352
2353         int offset = range.getOffset();
2354         int length = range.getLength();
2355
2356         if (offset < 0 || length < 0)
2357           return;
2358
2359         textWidget.setRedraw(false);
2360
2361         setHighlightRange(offset, length, moveCursor);
2362
2363         if (!moveCursor)
2364           return;
2365
2366         offset = -1;
2367         length = -1;
2368
2369         if (reference instanceof IMember) {
2370           range = ((IMember) reference).getNameRange();
2371           if (range != null) {
2372             offset = range.getOffset();
2373             length = range.getLength();
2374           }
2375         }
2376         //                                      else if (reference instanceof IImportDeclaration) {
2377         //                                              String name= ((IImportDeclaration)
2378         // reference).getElementName();
2379         //                                              if (name != null && name.length() > 0) {
2380         //                                                      String content= reference.getSource();
2381         //                                                      if (content != null) {
2382         //                                                              offset= range.getOffset() + content.indexOf(name);
2383         //                                                              length= name.length();
2384         //                                                      }
2385         //                                              }
2386         //                                      } else if (reference instanceof IPackageDeclaration) {
2387         //                                              String name= ((IPackageDeclaration)
2388         // reference).getElementName();
2389         //                                              if (name != null && name.length() > 0) {
2390         //                                                      String content= reference.getSource();
2391         //                                                      if (content != null) {
2392         //                                                              offset= range.getOffset() + content.indexOf(name);
2393         //                                                              length= name.length();
2394         //                                                      }
2395         //                                              }
2396         //                                      }
2397
2398         if (offset > -1 && length > 0) {
2399           sourceViewer.revealRange(offset, length);
2400           sourceViewer.setSelectedRange(offset, length);
2401         }
2402
2403       } catch (JavaModelException x) {
2404       } catch (IllegalArgumentException x) {
2405       } finally {
2406         if (textWidget != null)
2407           textWidget.setRedraw(true);
2408       }
2409
2410     } else if (moveCursor) {
2411       resetHighlightRange();
2412     }
2413
2414     markInNavigationHistory();
2415   }
2416
2417   public void setSelection(IJavaElement element) {
2418     if (element == null || element instanceof ICompilationUnit) { // ||
2419       // element
2420       // instanceof
2421       // IClassFile)
2422       // {
2423       /*
2424        * If the element is an ICompilationUnit this unit is either the input of this editor or not being displayed. In both cases,
2425        * nothing should happened. (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
2426        */
2427       return;
2428     }
2429
2430     IJavaElement corresponding = getCorrespondingElement(element);
2431     if (corresponding instanceof ISourceReference) {
2432       ISourceReference reference = (ISourceReference) corresponding;
2433       // set highlight range
2434       setSelection(reference, true);
2435       // set outliner selection
2436       if (fOutlinePage != null) {
2437         fOutlineSelectionChangedListener.uninstall(fOutlinePage);
2438         fOutlinePage.select(reference);
2439         fOutlineSelectionChangedListener.install(fOutlinePage);
2440       }
2441     }
2442   }
2443
2444   public synchronized void editingScriptStarted() {
2445     ++fIgnoreOutlinePageSelection;
2446   }
2447
2448   public synchronized void editingScriptEnded() {
2449     --fIgnoreOutlinePageSelection;
2450   }
2451
2452   public synchronized boolean isEditingScriptRunning() {
2453     return (fIgnoreOutlinePageSelection > 0);
2454   }
2455
2456   /**
2457    * The <code>PHPEditor</code> implementation of this <code>AbstractTextEditor</code> method performs gets the java content
2458    * outline page if request is for a an outline page.
2459    */
2460   public Object getAdapter(Class required) {
2461
2462     if (IContentOutlinePage.class.equals(required)) {
2463       if (fOutlinePage == null)
2464         fOutlinePage = createOutlinePage();
2465       return fOutlinePage;
2466     }
2467
2468     if (IEncodingSupport.class.equals(required))
2469       return fEncodingSupport;
2470
2471     if (required == IShowInTargetList.class) {
2472       return new IShowInTargetList() {
2473         public String[] getShowInTargetIds() {
2474           return new String[] { JavaUI.ID_PACKAGES, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
2475         }
2476
2477       };
2478     }
2479     if (fProjectionSupport != null) {
2480       Object adapter = fProjectionSupport.getAdapter(getSourceViewer(), required);
2481       if (adapter != null)
2482         return adapter;
2483     }
2484
2485     return super.getAdapter(required);
2486   }
2487
2488   //  public Object getAdapter(Class required) {
2489   //    if (IContentOutlinePage.class.equals(required)) {
2490   //      if (fOutlinePage == null) {
2491   //        fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
2492   //        if (getEditorInput() != null)
2493   //          fOutlinePage.setInput(getEditorInput());
2494   //      }
2495   //      return fOutlinePage;
2496   //    }
2497   //
2498   //    if (IEncodingSupport.class.equals(required))
2499   //      return fEncodingSupport;
2500   //
2501   //    return super.getAdapter(required);
2502   //  }
2503
2504   protected void doSelectionChanged(SelectionChangedEvent event) {
2505     ISourceReference reference = null;
2506
2507     ISelection selection = event.getSelection();
2508     Iterator iter = ((IStructuredSelection) selection).iterator();
2509     while (iter.hasNext()) {
2510       Object o = iter.next();
2511       if (o instanceof ISourceReference) {
2512         reference = (ISourceReference) o;
2513         break;
2514       }
2515     }
2516
2517     if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
2518       PHPeclipsePlugin.getActivePage().bringToTop(this);
2519
2520     try {
2521       editingScriptStarted();
2522       setSelection(reference, !isActivePart());
2523     } finally {
2524       editingScriptEnded();
2525     }
2526   }
2527
2528   /*
2529    * @see AbstractTextEditor#adjustHighlightRange(int, int)
2530    */
2531   protected void adjustHighlightRange(int offset, int length) {
2532
2533     try {
2534
2535       IJavaElement element = getElementAt(offset);
2536       while (element instanceof ISourceReference) {
2537         ISourceRange range = ((ISourceReference) element).getSourceRange();
2538         if (offset < range.getOffset() + range.getLength() && range.getOffset() < offset + length) {
2539
2540           ISourceViewer viewer = getSourceViewer();
2541           if (viewer instanceof ITextViewerExtension5) {
2542             ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
2543             extension.exposeModelRange(new Region(range.getOffset(), range.getLength()));
2544           }
2545
2546           setHighlightRange(range.getOffset(), range.getLength(), true);
2547           if (fOutlinePage != null) {
2548             fOutlineSelectionChangedListener.uninstall(fOutlinePage);
2549             fOutlinePage.select((ISourceReference) element);
2550             fOutlineSelectionChangedListener.install(fOutlinePage);
2551           }
2552
2553           return;
2554         }
2555         element = element.getParent();
2556       }
2557
2558     } catch (JavaModelException x) {
2559       PHPeclipsePlugin.log(x.getStatus());
2560     }
2561
2562     ISourceViewer viewer = getSourceViewer();
2563     if (viewer instanceof ITextViewerExtension5) {
2564       ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
2565       extension.exposeModelRange(new Region(offset, length));
2566     } else {
2567       resetHighlightRange();
2568     }
2569
2570   }
2571
2572   protected boolean isActivePart() {
2573     IWorkbenchWindow window = getSite().getWorkbenchWindow();
2574     IPartService service = window.getPartService();
2575     IWorkbenchPart part = service.getActivePart();
2576     return part != null && part.equals(this);
2577   }
2578
2579   //  public void openContextHelp() {
2580   //    IDocument doc =
2581   // this.getDocumentProvider().getDocument(this.getEditorInput());
2582   //    ITextSelection selection = (ITextSelection)
2583   // this.getSelectionProvider().getSelection();
2584   //    int pos = selection.getOffset();
2585   //    String word = getFunctionName(doc, pos);
2586   //    openContextHelp(word);
2587   //  }
2588   //
2589   //  private void openContextHelp(String word) {
2590   //    open(word);
2591   //  }
2592   //
2593   //  public static void open(String word) {
2594   //    IHelp help = WorkbenchHelp.getHelpSupport();
2595   //    if (help != null) {
2596   //      IHelpResource helpResource = new PHPFunctionHelpResource(word);
2597   //      WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
2598   //    } else {
2599   //      // showMessage(shell, dialogTitle, ActionMessages.getString("Open help
2600   // not available"), false); //$NON-NLS-1$
2601   //    }
2602   //  }
2603
2604   //    private String getFunctionName(IDocument doc, int pos) {
2605   //            Point word = PHPWordExtractor.findWord(doc, pos);
2606   //            if (word != null) {
2607   //                    try {
2608   //                            return doc.get(word.x, word.y).replace('_', '-');
2609   //                    } catch (BadLocationException e) {
2610   //                    }
2611   //            }
2612   //            return "";
2613   //    }
2614
2615   /*
2616    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
2617    */
2618   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
2619
2620     try {
2621
2622       ISourceViewer sourceViewer = getSourceViewer();
2623       if (sourceViewer == null)
2624         return;
2625
2626       String property = event.getProperty();
2627
2628       if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
2629         Object value = event.getNewValue();
2630         if (value instanceof Integer) {
2631           sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
2632         } else if (value instanceof String) {
2633           sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
2634         }
2635         return;
2636       }
2637
2638       //      if (OVERVIEW_RULER.equals(property)) {
2639       //        if (isOverviewRulerVisible())
2640       //          showOverviewRuler();
2641       //        else
2642       //          hideOverviewRuler();
2643       //        return;
2644       //      }
2645
2646       //      if (LINE_NUMBER_RULER.equals(property)) {
2647       //        if (isLineNumberRulerVisible())
2648       //          showLineNumberRuler();
2649       //        else
2650       //          hideLineNumberRuler();
2651       //        return;
2652       //      }
2653
2654       //      if (fLineNumberRulerColumn != null
2655       //        && (LINE_NUMBER_COLOR.equals(property) ||
2656       // PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) ||
2657       // PREFERENCE_COLOR_BACKGROUND.equals(property))) {
2658       //
2659       //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2660       //      }
2661
2662       if (isJavaEditorHoverProperty(property))
2663         updateHoverBehavior();
2664
2665       if (BROWSER_LIKE_LINKS.equals(property)) {
2666         if (isBrowserLikeLinks())
2667           enableBrowserLikeLinks();
2668         else
2669           disableBrowserLikeLinks();
2670         return;
2671       }
2672
2673       if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) {
2674                 if ((event.getNewValue() instanceof Boolean) && ((Boolean)event.getNewValue()).booleanValue())
2675                         selectionChanged();
2676                 return;
2677           } 
2678
2679       if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) {
2680         if (event.getNewValue() instanceof Boolean) {
2681           Boolean disable = (Boolean) event.getNewValue();
2682           enableOverwriteMode(!disable.booleanValue());
2683         }
2684         return;
2685       }
2686
2687       //        if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property))
2688       // {
2689       //                if (event.getNewValue() instanceof Boolean) {
2690       //                        boolean markOccurrenceAnnotations=
2691       // ((Boolean)event.getNewValue()).booleanValue();
2692       //                        if (markOccurrenceAnnotations != fMarkOccurrenceAnnotations) {
2693       //                                fMarkOccurrenceAnnotations= markOccurrenceAnnotations;
2694       //                                if (!fMarkOccurrenceAnnotations)
2695       //                                        uninstallOccurrencesFinder();
2696       //                                else
2697       //                                        installOccurrencesFinder();
2698       //                        }
2699       //                }
2700       //        }
2701       //        if
2702       // (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property))
2703       // {
2704       //                if (event.getNewValue() instanceof Boolean) {
2705       //                        boolean stickyOccurrenceAnnotations=
2706       // ((Boolean)event.getNewValue()).booleanValue();
2707       //                        if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations)
2708       // {
2709       //                                fStickyOccurrenceAnnotations= stickyOccurrenceAnnotations;
2710       //// if (!fMarkOccurrenceAnnotations)
2711       //// uninstallOccurrencesFinder();
2712       //// else
2713       //// installOccurrencesFinder();
2714       //                        }
2715       //                }
2716       //        }
2717       
2718       ((PHPSourceViewerConfiguration)getSourceViewerConfiguration()).handlePropertyChangeEvent(event);
2719                 
2720 //              if (affectsOverrideIndicatorAnnotations(event)) {
2721 //                      if (isShowingOverrideIndicators()) {
2722 //                              if (fOverrideIndicatorManager == null)
2723 //                                      installOverrideIndicator(true);
2724 //                      } else {
2725 //                              if (fOverrideIndicatorManager != null)
2726 //                                      uninstallOverrideIndicator();
2727 //                      }
2728 //                      return;
2729 //              }
2730                 
2731       if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
2732         if (sourceViewer instanceof ProjectionViewer) {
2733           ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer;
2734           if (fProjectionModelUpdater != null)
2735             fProjectionModelUpdater.uninstall();
2736           // either freshly enabled or provider changed
2737           fProjectionModelUpdater = PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
2738           if (fProjectionModelUpdater != null) {
2739             fProjectionModelUpdater.install(this, projectionViewer);
2740           }
2741         }
2742         return;
2743       }
2744     } finally {
2745       super.handlePreferenceStoreChanged(event);
2746     }
2747   }
2748
2749   //  /*
2750   //     * @see
2751   // AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
2752   //     */
2753   //  protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
2754   //
2755   //    try {
2756   //
2757   //      ISourceViewer sourceViewer = getSourceViewer();
2758   //      if (sourceViewer == null)
2759   //        return;
2760   //
2761   //      String property = event.getProperty();
2762   //
2763   //      // if
2764   // (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
2765   //      // Object value= event.getNewValue();
2766   //      // if (value instanceof Integer) {
2767   //      // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
2768   //      // } else if (value instanceof String) {
2769   //      // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String)
2770   // value));
2771   //      // }
2772   //      // return;
2773   //      // }
2774   //
2775   //      if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
2776   //        if (isLineNumberRulerVisible())
2777   //          showLineNumberRuler();
2778   //        else
2779   //          hideLineNumberRuler();
2780   //        return;
2781   //      }
2782   //
2783   //      if (fLineNumberRulerColumn != null
2784   //        && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
2785   //          || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
2786   //          || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
2787   //
2788   //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2789   //      }
2790   //
2791   //    } finally {
2792   //      super.handlePreferenceStoreChanged(event);
2793   //    }
2794   //  }
2795
2796   //  private boolean isJavaEditorHoverProperty(String property) {
2797   //    return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
2798   //      || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
2799   //      || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
2800   //      || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
2801   //      || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
2802   //      || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
2803   //      || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
2804   //      || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
2805   //  }
2806
2807   /**
2808    * Shows the line number ruler column.
2809    */
2810   //  private void showLineNumberRuler() {
2811   //    IVerticalRuler v = getVerticalRuler();
2812   //    if (v instanceof CompositeRuler) {
2813   //      CompositeRuler c = (CompositeRuler) v;
2814   //      c.addDecorator(1, createLineNumberRulerColumn());
2815   //    }
2816   //  }
2817   private boolean isJavaEditorHoverProperty(String property) {
2818     return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
2819   }
2820
2821   /**
2822    * Return whether the browser like links should be enabled according to the preference store settings.
2823    * 
2824    * @return <code>true</code> if the browser like links should be enabled
2825    */
2826   private boolean isBrowserLikeLinks() {
2827     IPreferenceStore store = getPreferenceStore();
2828     return store.getBoolean(BROWSER_LIKE_LINKS);
2829   }
2830
2831   /**
2832    * Enables browser like links.
2833    */
2834   private void enableBrowserLikeLinks() {
2835     if (fMouseListener == null) {
2836       fMouseListener = new MouseClickListener();
2837       fMouseListener.install();
2838     }
2839   }
2840
2841   /**
2842    * Disables browser like links.
2843    */
2844   private void disableBrowserLikeLinks() {
2845     if (fMouseListener != null) {
2846       fMouseListener.uninstall();
2847       fMouseListener = null;
2848     }
2849   }
2850
2851   /**
2852    * Handles a property change event describing a change of the java core's preferences and updates the preference related editor
2853    * properties.
2854    * 
2855    * @param event
2856    *          the property change event
2857    */
2858   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
2859     if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
2860       ISourceViewer sourceViewer = getSourceViewer();
2861       if (sourceViewer != null
2862           && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event
2863               .getNewValue())))
2864         sourceViewer.invalidateTextPresentation();
2865     }
2866   }
2867
2868   /**
2869    * Return whether the line number ruler column should be visible according to the preference store settings.
2870    * 
2871    * @return <code>true</code> if the line numbers should be visible
2872    */
2873   //  protected boolean isLineNumberRulerVisible() {
2874   //    IPreferenceStore store = getPreferenceStore();
2875   //    return store.getBoolean(LINE_NUMBER_RULER);
2876   //  }
2877   /**
2878    * Hides the line number ruler column.
2879    */
2880   //  private void hideLineNumberRuler() {
2881   //    IVerticalRuler v = getVerticalRuler();
2882   //    if (v instanceof CompositeRuler) {
2883   //      CompositeRuler c = (CompositeRuler) v;
2884   //      try {
2885   //        c.removeDecorator(1);
2886   //      } catch (Throwable e) {
2887   //      }
2888   //    }
2889   //  }
2890   /*
2891    * @see AbstractTextEditor#handleCursorPositionChanged()
2892    */
2893   protected void handleCursorPositionChanged() {
2894     super.handleCursorPositionChanged();
2895     if (!isEditingScriptRunning() && fUpdater != null)
2896       fUpdater.post();
2897   }
2898
2899   /*
2900    * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced()
2901    */
2902   protected void handleElementContentReplaced() {
2903     super.handleElementContentReplaced();
2904     if (fProjectionModelUpdater != null)
2905       fProjectionModelUpdater.initialize();
2906   }
2907
2908   /**
2909    * Initializes the given line number ruler column from the preference store.
2910    * 
2911    * @param rulerColumn
2912    *          the ruler column to be initialized
2913    */
2914   //  protected void initializeLineNumberRulerColumn(LineNumberRulerColumn
2915   // rulerColumn) {
2916   //    JavaTextTools textTools =
2917   // PHPeclipsePlugin.getDefault().getJavaTextTools();
2918   //    IColorManager manager = textTools.getColorManager();
2919   //
2920   //    IPreferenceStore store = getPreferenceStore();
2921   //    if (store != null) {
2922   //
2923   //      RGB rgb = null;
2924   //      // foreground color
2925   //      if (store.contains(LINE_NUMBER_COLOR)) {
2926   //        if (store.isDefault(LINE_NUMBER_COLOR))
2927   //          rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
2928   //        else
2929   //          rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
2930   //      }
2931   //      rulerColumn.setForeground(manager.getColor(rgb));
2932   //
2933   //      rgb = null;
2934   //      // background color
2935   //      if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
2936   //        if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
2937   //          if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
2938   //            rgb = PreferenceConverter.getDefaultColor(store,
2939   // PREFERENCE_COLOR_BACKGROUND);
2940   //          else
2941   //            rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
2942   //        }
2943   //      }
2944   //      rulerColumn.setBackground(manager.getColor(rgb));
2945   //    }
2946   //  }
2947   /**
2948    * Creates a new line number ruler column that is appropriately initialized.
2949    */
2950   //  protected IVerticalRulerColumn createLineNumberRulerColumn() {
2951   //    fLineNumberRulerColumn = new LineNumberRulerColumn();
2952   //    initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2953   //    return fLineNumberRulerColumn;
2954   //  }
2955   /*
2956    * @see AbstractTextEditor#createVerticalRuler()
2957    */
2958   //  protected IVerticalRuler createVerticalRuler() {
2959   //    CompositeRuler ruler = new CompositeRuler();
2960   //    ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
2961   //    if (isLineNumberRulerVisible())
2962   //      ruler.addDecorator(1, createLineNumberRulerColumn());
2963   //    return ruler;
2964   //  }
2965 //  private static IRegion getSignedSelection(ITextViewer viewer) {
2966 //
2967 //    StyledText text = viewer.getTextWidget();
2968 //    int caretOffset = text.getCaretOffset();
2969 //    Point selection = text.getSelection();
2970 //
2971 //    // caret left
2972 //    int offset, length;
2973 //    if (caretOffset == selection.x) {
2974 //      offset = selection.y;
2975 //      length = selection.x - selection.y;
2976 //
2977 //      // caret right
2978 //    } else {
2979 //      offset = selection.x;
2980 //      length = selection.y - selection.x;
2981 //    }
2982 //
2983 //    return new Region(offset, length);
2984 //  }
2985         protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
2986                 StyledText text= sourceViewer.getTextWidget();
2987                 Point selection= text.getSelectionRange();
2988                 
2989                 if (text.getCaretOffset() == selection.x) {
2990                         selection.x= selection.x + selection.y;
2991                         selection.y= -selection.y;
2992                 }
2993                 
2994                 selection.x= widgetOffset2ModelOffset(sourceViewer, selection.x);
2995                 
2996                 return new Region(selection.x, selection.y);
2997         }
2998   /** Preference key for matching brackets */
2999   protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
3000
3001   /** Preference key for matching brackets color */
3002   protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
3003
3004   /** Preference key for highlighting current line */
3005 //  protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
3006
3007   /** Preference key for highlight color of current line */
3008 //  protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
3009
3010   /** Preference key for showing print marging ruler */
3011 //  protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
3012
3013   /** Preference key for print margin ruler color */
3014 //  protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
3015
3016   /** Preference key for print margin ruler column */
3017 //  protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
3018
3019   /** Preference key for error indication */
3020   //  protected final static String ERROR_INDICATION =
3021   // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
3022   /** Preference key for error color */
3023   //  protected final static String ERROR_INDICATION_COLOR =
3024   // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
3025   /** Preference key for warning indication */
3026   //  protected final static String WARNING_INDICATION =
3027   // PreferenceConstants.EDITOR_WARNING_INDICATION;
3028   /** Preference key for warning color */
3029   //  protected final static String WARNING_INDICATION_COLOR =
3030   // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
3031   /** Preference key for task indication */
3032   protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
3033
3034   /** Preference key for task color */
3035   protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
3036
3037   /** Preference key for bookmark indication */
3038   protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
3039
3040   /** Preference key for bookmark color */
3041   protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
3042
3043   /** Preference key for search result indication */
3044   protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
3045
3046   /** Preference key for search result color */
3047   protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
3048
3049   /** Preference key for unknown annotation indication */
3050   protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
3051
3052   /** Preference key for unknown annotation color */
3053   protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
3054
3055   /** Preference key for shwoing the overview ruler */
3056   protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
3057
3058   /** Preference key for error indication in overview ruler */
3059   protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
3060
3061   /** Preference key for warning indication in overview ruler */
3062   protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
3063
3064   /** Preference key for task indication in overview ruler */
3065   protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
3066
3067   /** Preference key for bookmark indication in overview ruler */
3068   protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
3069
3070   /** Preference key for search result indication in overview ruler */
3071   protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
3072
3073   /** Preference key for unknown annotation indication in overview ruler */
3074   protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
3075
3076   //            /** Preference key for compiler task tags */
3077   //            private final static String COMPILER_TASK_TAGS=
3078   // JavaCore.COMPILER_TASK_TAGS;
3079   /** Preference key for browser like links */
3080   private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
3081
3082   /** Preference key for key modifier of browser like links */
3083   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
3084
3085   /**
3086    * Preference key for key modifier mask of browser like links. The value is only used if the value of
3087    * <code>EDITOR_BROWSER_LIKE_LINKS</code> cannot be resolved to valid SWT modifier bits.
3088    * 
3089    * @since 2.1.1
3090    */
3091   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
3092
3093   private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
3094
3095   private static boolean isBracket(char character) {
3096     for (int i = 0; i != BRACKETS.length; ++i)
3097       if (character == BRACKETS[i])
3098         return true;
3099     return false;
3100   }
3101
3102   private static boolean isSurroundedByBrackets(IDocument document, int offset) {
3103     if (offset == 0 || offset == document.getLength())
3104       return false;
3105
3106     try {
3107       return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
3108
3109     } catch (BadLocationException e) {
3110       return false;
3111     }
3112   }
3113
3114   //  protected void configureSourceViewerDecorationSupport() {
3115   //
3116   //    fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
3117   //
3118   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3119   //      AnnotationType.UNKNOWN,
3120   //      UNKNOWN_INDICATION_COLOR,
3121   //      UNKNOWN_INDICATION,
3122   //      UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
3123   //      0);
3124   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3125   //      AnnotationType.BOOKMARK,
3126   //      BOOKMARK_INDICATION_COLOR,
3127   //      BOOKMARK_INDICATION,
3128   //      BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
3129   //      1);
3130   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3131   //      AnnotationType.TASK,
3132   //      TASK_INDICATION_COLOR,
3133   //      TASK_INDICATION,
3134   //      TASK_INDICATION_IN_OVERVIEW_RULER,
3135   //      2);
3136   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3137   //      AnnotationType.SEARCH,
3138   //      SEARCH_RESULT_INDICATION_COLOR,
3139   //      SEARCH_RESULT_INDICATION,
3140   //      SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
3141   //      3);
3142   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3143   //      AnnotationType.WARNING,
3144   //      WARNING_INDICATION_COLOR,
3145   //      WARNING_INDICATION,
3146   //      WARNING_INDICATION_IN_OVERVIEW_RULER,
3147   //      4);
3148   //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
3149   //      AnnotationType.ERROR,
3150   //      ERROR_INDICATION_COLOR,
3151   //      ERROR_INDICATION,
3152   //      ERROR_INDICATION_IN_OVERVIEW_RULER,
3153   //      5);
3154   //
3155   //    fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE,
3156   // CURRENT_LINE_COLOR);
3157   //    fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN,
3158   // PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
3159   //    fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
3160   // MATCHING_BRACKETS_COLOR);
3161   //
3162   //    fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
3163   //
3164   //  }
3165   /**
3166    * Returns the Java element wrapped by this editors input.
3167    * 
3168    * @return the Java element wrapped by this editors input.
3169    * @since 3.0
3170    */
3171   abstract protected IJavaElement getInputJavaElement();
3172
3173   /**
3174    * Jumps to the matching bracket.
3175    */
3176   public void gotoMatchingBracket() {
3177
3178     ISourceViewer sourceViewer = getSourceViewer();
3179     IDocument document = sourceViewer.getDocument();
3180     if (document == null)
3181       return;
3182
3183     IRegion selection = getSignedSelection(sourceViewer);
3184
3185     int selectionLength = Math.abs(selection.getLength());
3186     if (selectionLength > 1) {
3187       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$               
3188       sourceViewer.getTextWidget().getDisplay().beep();
3189       return;
3190     }
3191
3192     // #26314
3193     int sourceCaretOffset = selection.getOffset() + selection.getLength();
3194     if (isSurroundedByBrackets(document, sourceCaretOffset))
3195       sourceCaretOffset -= selection.getLength();
3196
3197     IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
3198     if (region == null) {
3199       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$              
3200       sourceViewer.getTextWidget().getDisplay().beep();
3201       return;
3202     }
3203
3204     int offset = region.getOffset();
3205     int length = region.getLength();
3206
3207     if (length < 1)
3208       return;
3209
3210     int anchor = fBracketMatcher.getAnchor();
3211     int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
3212
3213     boolean visible = false;
3214     if (sourceViewer instanceof ITextViewerExtension3) {
3215       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
3216       visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
3217     } else {
3218       IRegion visibleRegion = sourceViewer.getVisibleRegion();
3219       visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
3220     }
3221
3222     if (!visible) {
3223       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$          
3224       sourceViewer.getTextWidget().getDisplay().beep();
3225       return;
3226     }
3227
3228     if (selection.getLength() < 0)
3229       targetOffset -= selection.getLength();
3230
3231     sourceViewer.setSelectedRange(targetOffset, selection.getLength());
3232     sourceViewer.revealRange(targetOffset, selection.getLength());
3233   }
3234
3235   /**
3236    * Ses the given message as error message to this editor's status line.
3237    * 
3238    * @param msg
3239    *          message to be set
3240    */
3241   protected void setStatusLineErrorMessage(String msg) {
3242     IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
3243     if (statusLine != null)
3244       statusLine.setMessage(true, msg, null);
3245   }
3246
3247   /**
3248    * Returns a segmentation of the line of the given document appropriate for bidi rendering. The default implementation returns
3249    * only the string literals of a php code line as segments.
3250    * 
3251    * @param document
3252    *          the document
3253    * @param lineOffset
3254    *          the offset of the line
3255    * @return the line's bidi segmentation
3256    * @throws BadLocationException
3257    *           in case lineOffset is not valid in document
3258    */
3259   public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException {
3260
3261     IRegion line = document.getLineInformationOfOffset(lineOffset);
3262     ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength());
3263
3264     List segmentation = new ArrayList();
3265     for (int i = 0; i < linePartitioning.length; i++) {
3266       if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i].getType()))
3267         segmentation.add(linePartitioning[i]);
3268     }
3269
3270     if (segmentation.size() == 0)
3271       return null;
3272
3273     int size = segmentation.size();
3274     int[] segments = new int[size * 2 + 1];
3275
3276     int j = 0;
3277     for (int i = 0; i < size; i++) {
3278       ITypedRegion segment = (ITypedRegion) segmentation.get(i);
3279
3280       if (i == 0)
3281         segments[j++] = 0;
3282
3283       int offset = segment.getOffset() - lineOffset;
3284       if (offset > segments[j - 1])
3285         segments[j++] = offset;
3286
3287       if (offset + segment.getLength() >= line.getLength())
3288         break;
3289
3290       segments[j++] = offset + segment.getLength();
3291     }
3292
3293     if (j < segments.length) {
3294       int[] result = new int[j];
3295       System.arraycopy(segments, 0, result, 0, j);
3296       segments = result;
3297     }
3298
3299     return segments;
3300   }
3301
3302   /**
3303    * Returns a segmentation of the given line appropriate for bidi rendering. The default implementation returns only the string
3304    * literals of a php code line as segments.
3305    * 
3306    * @param lineOffset
3307    *          the offset of the line
3308    * @param line
3309    *          the content of the line
3310    * @return the line's bidi segmentation
3311    */
3312   protected int[] getBidiLineSegments(int lineOffset, String line) {
3313     IDocumentProvider provider = getDocumentProvider();
3314     if (provider != null && line != null && line.length() > 0) {
3315       IDocument document = provider.getDocument(getEditorInput());
3316       if (document != null)
3317         try {
3318           return getBidiLineSegments(document, lineOffset);
3319         } catch (BadLocationException x) {
3320           // ignore
3321         }
3322     }
3323     return null;
3324   }
3325
3326   /*
3327    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3328    */
3329   //  protected final ISourceViewer createSourceViewer(
3330   //    Composite parent,
3331   //    IVerticalRuler ruler,
3332   //    int styles) {
3333   //    ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
3334   //    StyledText text = viewer.getTextWidget();
3335   //    text.addBidiSegmentListener(new BidiSegmentListener() {
3336   //      public void lineGetSegments(BidiSegmentEvent event) {
3337   //        event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
3338   //      }
3339   //    });
3340   //    // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
3341   //    return viewer;
3342   //  }
3343   public final ISourceViewer getViewer() {
3344     return getSourceViewer();
3345   }
3346
3347   //  protected void showOverviewRuler() {
3348   //    if (fOverviewRuler != null) {
3349   //      if (getSourceViewer() instanceof ISourceViewerExtension) {
3350   //        ((ISourceViewerExtension)
3351   // getSourceViewer()).showAnnotationsOverview(true);
3352   //        fSourceViewerDecorationSupport.updateOverviewDecorations();
3353   //      }
3354   //    }
3355   //  }
3356   //
3357   //  protected void hideOverviewRuler() {
3358   //    if (getSourceViewer() instanceof ISourceViewerExtension) {
3359   //      fSourceViewerDecorationSupport.hideAnnotationOverview();
3360   //      ((ISourceViewerExtension)
3361   // getSourceViewer()).showAnnotationsOverview(false);
3362   //    }
3363   //  }
3364
3365   //  protected boolean isOverviewRulerVisible() {
3366   //    IPreferenceStore store = getPreferenceStore();
3367   //    return store.getBoolean(OVERVIEW_RULER);
3368   //  }
3369   /*
3370    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3371    */
3372   //  protected ISourceViewer createJavaSourceViewer(
3373   //    Composite parent,
3374   //    IVerticalRuler ruler,
3375   //    IOverviewRuler overviewRuler,
3376   //    boolean isOverviewRulerVisible,
3377   //    int styles) {
3378   //    return new SourceViewer(parent, ruler, overviewRuler,
3379   // isOverviewRulerVisible(), styles);
3380   //  }
3381   /*
3382    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3383    */
3384   protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
3385       boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
3386     return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, store);
3387   }
3388
3389   /*
3390    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
3391    */
3392   protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
3393
3394     ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles,
3395         getPreferenceStore());
3396
3397     StyledText text = viewer.getTextWidget();
3398     text.addBidiSegmentListener(new BidiSegmentListener() {
3399       public void lineGetSegments(BidiSegmentEvent event) {
3400         event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
3401       }
3402     });
3403
3404     //          JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
3405
3406     // ensure source viewer decoration support has been created and
3407     // configured
3408     getSourceViewerDecorationSupport(viewer);
3409
3410     return viewer;
3411   }
3412   /*
3413          * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
3414          */
3415         protected boolean affectsTextPresentation(PropertyChangeEvent event) {
3416                 return ((PHPSourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event) || super.affectsTextPresentation(event);
3417         }
3418 //
3419 //        protected boolean affectsTextPresentation(PropertyChangeEvent event) {
3420 //          JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
3421 //          return textTools.affectsBehavior(event);
3422 //        }
3423   /**
3424    * Creates and returns the preference store for this Java editor with the given input.
3425    * 
3426    * @param input
3427    *          The editor input for which to create the preference store
3428    * @return the preference store for this editor
3429    * 
3430    * @since 3.0
3431    */
3432   private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
3433     List stores = new ArrayList(3);
3434
3435     IJavaProject project = EditorUtility.getJavaProject(input);
3436     if (project != null)
3437       stores.add(new OptionsAdapter(project.getOptions(false), PHPeclipsePlugin.getDefault().getMockupPreferenceStore(),
3438           new OptionsAdapter.IPropertyChangeEventFilter() {
3439
3440             public boolean isFiltered(PropertyChangeEvent event) {
3441               IJavaElement inputJavaElement = getInputJavaElement();
3442               IJavaProject javaProject = inputJavaElement != null ? inputJavaElement.getJavaProject() : null;
3443               if (javaProject == null)
3444                 return true;
3445
3446               return !javaProject.getProject().equals(event.getSource());
3447             }
3448
3449           }));
3450
3451     stores.add(PHPeclipsePlugin.getDefault().getPreferenceStore());
3452     stores.add(new PreferencesAdapter(JavaCore.getPlugin().getPluginPreferences()));
3453     stores.add(EditorsUI.getPreferenceStore());
3454
3455     return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()]));
3456   }
3457
3458   /**
3459    * Jumps to the error next according to the given direction.
3460    */
3461   public void gotoError(boolean forward) {
3462
3463     ISelectionProvider provider = getSelectionProvider();
3464
3465     ITextSelection s = (ITextSelection) provider.getSelection();
3466     Position errorPosition = new Position(0, 0);
3467     IJavaAnnotation nextError = getNextError(s.getOffset(), forward, errorPosition);
3468
3469     if (nextError != null) {
3470
3471       IMarker marker = null;
3472       if (nextError instanceof MarkerAnnotation)
3473         marker = ((MarkerAnnotation) nextError).getMarker();
3474       else {
3475         Iterator e = nextError.getOverlaidIterator();
3476         if (e != null) {
3477           while (e.hasNext()) {
3478             Object o = e.next();
3479             if (o instanceof MarkerAnnotation) {
3480               marker = ((MarkerAnnotation) o).getMarker();
3481               break;
3482             }
3483           }
3484         }
3485       }
3486
3487       if (marker != null) {
3488         IWorkbenchPage page = getSite().getPage();
3489         IViewPart view = view = page.findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
3490         if (view instanceof TaskList) {
3491           StructuredSelection ss = new StructuredSelection(marker);
3492           ((TaskList) view).setSelection(ss, true);
3493         }
3494       }
3495
3496       selectAndReveal(errorPosition.getOffset(), errorPosition.getLength());
3497       //      setStatusLineErrorMessage(nextError.getMessage());
3498
3499     } else {
3500
3501       setStatusLineErrorMessage(null);
3502
3503     }
3504   }
3505
3506   private IJavaAnnotation getNextError(int offset, boolean forward, Position errorPosition) {
3507
3508     IJavaAnnotation nextError = null;
3509     Position nextErrorPosition = null;
3510
3511     IDocument document = getDocumentProvider().getDocument(getEditorInput());
3512     int endOfDocument = document.getLength();
3513     int distance = 0;
3514
3515     IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
3516     Iterator e = new JavaAnnotationIterator(model, false);
3517     while (e.hasNext()) {
3518
3519       IJavaAnnotation a = (IJavaAnnotation) e.next();
3520       if (a.hasOverlay() || !a.isProblem())
3521         continue;
3522
3523       Position p = model.getPosition((Annotation) a);
3524       if (!p.includes(offset)) {
3525
3526         int currentDistance = 0;
3527
3528         if (forward) {
3529           currentDistance = p.getOffset() - offset;
3530           if (currentDistance < 0)
3531             currentDistance = endOfDocument - offset + p.getOffset();
3532         } else {
3533           currentDistance = offset - p.getOffset();
3534           if (currentDistance < 0)
3535             currentDistance = offset + endOfDocument - p.getOffset();
3536         }
3537
3538         if (nextError == null || currentDistance < distance) {
3539           distance = currentDistance;
3540           nextError = a;
3541           nextErrorPosition = p;
3542         }
3543       }
3544     }
3545
3546     if (nextErrorPosition != null) {
3547       errorPosition.setOffset(nextErrorPosition.getOffset());
3548       errorPosition.setLength(nextErrorPosition.getLength());
3549     }
3550
3551     return nextError;
3552   }
3553
3554   void removeOccurrenceAnnotations() {
3555     IDocumentProvider documentProvider = getDocumentProvider();
3556     if (documentProvider == null)
3557       return;
3558
3559     IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput());
3560     if (annotationModel == null || fOccurrenceAnnotations == null)
3561       return;
3562
3563     synchronized (annotationModel) {
3564       if (annotationModel instanceof IAnnotationModelExtension) {
3565         ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, null);
3566       } else {
3567         for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++)
3568           annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
3569       }
3570       fOccurrenceAnnotations = null;
3571     }
3572   }
3573
3574   //  protected void uninstallOverrideIndicator() {
3575   //    if (fOverrideIndicatorManager != null) {
3576   //            fOverrideIndicatorManager.removeAnnotations();
3577   //            fOverrideIndicatorManager= null;
3578   //    }
3579   //}
3580
3581   protected void installOverrideIndicator(boolean waitForReconcilation) {
3582     //  uninstallOverrideIndicator();
3583     IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
3584     //  IJavaElement inputElement= getInputJavaElement();
3585
3586     //  if (model == null || inputElement == null)
3587     //          return;
3588
3589     //  CompilationUnit ast=
3590     // PHPeclipsePlugin.getDefault().getASTProvider().getAST(inputElement,
3591     // true, null);
3592     //  fOverrideIndicatorManager= new OverrideIndicatorManager(model,
3593     // inputElement, ast);
3594   }
3595
3596   /**
3597          * Tells whether override indicators are shown.
3598          * 
3599          * @return <code>true</code> if the override indicators are shown
3600          * @since 3.0
3601          */
3602 //      protected boolean isShowingOverrideIndicators() {
3603 //              AnnotationPreference preference= getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
3604 //              IPreferenceStore store= getPreferenceStore();
3605 //              return getBoolean(store, preference.getHighlightPreferenceKey())
3606 //                      || getBoolean(store, preference.getVerticalRulerPreferenceKey())
3607 //                      || getBoolean(store, preference.getOverviewRulerPreferenceKey())
3608 //                      || getBoolean(store, preference.getTextPreferenceKey());
3609 //      }
3610   /**
3611    * Returns the boolean preference for the given key.
3612    * 
3613    * @param store
3614    *          the preference store
3615    * @param key
3616    *          the preference key
3617    * @return <code>true</code> if the key exists in the store and its value is <code>true</code>
3618    * @since 3.0
3619    */
3620   private boolean getBoolean(IPreferenceStore store, String key) {
3621     return key != null && store.getBoolean(key);
3622   }
3623
3624   /**
3625    * Returns the folding action group, or <code>null</code> if there is none.
3626    * 
3627    * @return the folding action group, or <code>null</code> if there is none
3628    * @since 3.0
3629    */
3630   protected FoldingActionGroup getFoldingActionGroup() {
3631     return fFoldingGroup;
3632   }
3633
3634   /**
3635    * React to changed selection.
3636    * 
3637    * @since 3.0
3638    */
3639   protected void selectionChanged() {
3640     if (getSelectionProvider() == null)
3641       return;
3642     ISourceReference element = computeHighlightRangeSourceReference();
3643     if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
3644       synchronizeOutlinePage(element);
3645     setSelection(element, false);
3646     //          updateStatusLine();
3647   }
3648
3649   private boolean isJavaOutlinePageActive() {
3650     IWorkbenchPart part = getActivePart();
3651     return part instanceof ContentOutline && ((ContentOutline) part).getCurrentPage() == fOutlinePage;
3652   }
3653
3654   private IWorkbenchPart getActivePart() {
3655     IWorkbenchWindow window = getSite().getWorkbenchWindow();
3656     IPartService service = window.getPartService();
3657     IWorkbenchPart part = service.getActivePart();
3658     return part;
3659   }
3660
3661   /**
3662    * Computes and returns the source reference that includes the caret and serves as provider for the outline page selection and the
3663    * editor range indication.
3664    * 
3665    * @return the computed source reference
3666    * @since 3.0
3667    */
3668   protected ISourceReference computeHighlightRangeSourceReference() {
3669     ISourceViewer sourceViewer = getSourceViewer();
3670     if (sourceViewer == null)
3671       return null;
3672
3673     StyledText styledText = sourceViewer.getTextWidget();
3674     if (styledText == null)
3675       return null;
3676
3677     int caret = 0;
3678     if (sourceViewer instanceof ITextViewerExtension5) {
3679       ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
3680       caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
3681     } else {
3682       int offset = sourceViewer.getVisibleRegion().getOffset();
3683       caret = offset + styledText.getCaretOffset();
3684     }
3685
3686     IJavaElement element = getElementAt(caret, false);
3687
3688     if (!(element instanceof ISourceReference))
3689       return null;
3690
3691     if (element.getElementType() == IJavaElement.IMPORT_DECLARATION) {
3692
3693       IImportDeclaration declaration = (IImportDeclaration) element;
3694       IImportContainer container = (IImportContainer) declaration.getParent();
3695       ISourceRange srcRange = null;
3696
3697       try {
3698         srcRange = container.getSourceRange();
3699       } catch (JavaModelException e) {
3700       }
3701
3702       if (srcRange != null && srcRange.getOffset() == caret)
3703         return container;
3704     }
3705
3706     return (ISourceReference) element;
3707   }
3708
3709   /**
3710    * Returns the most narrow java element including the given offset.
3711    * 
3712    * @param offset
3713    *          the offset inside of the requested element
3714    * @param reconcile
3715    *          <code>true</code> if editor input should be reconciled in advance
3716    * @return the most narrow java element
3717    * @since 3.0
3718    */
3719   protected IJavaElement getElementAt(int offset, boolean reconcile) {
3720     return getElementAt(offset);
3721   }
3722 }