Removing legacy build scripts. build.xml scripts are generated by pde-build, and...
[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  www.phpeclipse.de
13  **********************************************************************/
14 import java.lang.reflect.InvocationTargetException;
15 import java.lang.reflect.Method;
16 import java.text.BreakIterator;
17 import java.text.CharacterIterator;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.ResourceBundle;
24 import java.util.StringTokenizer;
25
26 import net.sourceforge.phpdt.core.ICompilationUnit;
27 import net.sourceforge.phpdt.core.IImportContainer;
28 import net.sourceforge.phpdt.core.IImportDeclaration;
29 import net.sourceforge.phpdt.core.IJavaElement;
30 import net.sourceforge.phpdt.core.IJavaProject;
31 import net.sourceforge.phpdt.core.IMember;
32 import net.sourceforge.phpdt.core.ISourceRange;
33 import net.sourceforge.phpdt.core.ISourceReference;
34 import net.sourceforge.phpdt.core.JavaCore;
35 import net.sourceforge.phpdt.core.JavaModelException;
36 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
37 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
38 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
39 import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
40 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
41 import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup;
42 import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter;
43 import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl;
44 import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator;
45 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
46 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
47 import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
48 import net.sourceforge.phpdt.internal.ui.text.JavaWordIterator;
49 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
50 import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
51 import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaExpandHover;
52 import net.sourceforge.phpdt.internal.ui.viewsupport.ISelectionListenerWithAST;
53 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
54 import net.sourceforge.phpdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
55 import net.sourceforge.phpdt.ui.IContextMenuConstants;
56 import net.sourceforge.phpdt.ui.JavaUI;
57 import net.sourceforge.phpdt.ui.PreferenceConstants;
58 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
59 import net.sourceforge.phpdt.ui.actions.OpenEditorActionGroup;
60 import net.sourceforge.phpdt.ui.text.JavaTextTools;
61 import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
62 import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
63 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
64 import net.sourceforge.phpeclipse.ui.editor.BrowserUtil;
65 import net.sourceforge.phpeclipse.webbrowser.views.BrowserView;
66
67 import org.eclipse.core.resources.IMarker;
68 import org.eclipse.core.resources.IResource;
69 import org.eclipse.core.runtime.CoreException;
70 import org.eclipse.core.runtime.IProgressMonitor;
71 import org.eclipse.core.runtime.IStatus;
72 import org.eclipse.core.runtime.NullProgressMonitor;
73 import org.eclipse.core.runtime.Preferences;
74 import org.eclipse.core.runtime.Status;
75 import org.eclipse.core.runtime.jobs.Job;
76 import org.eclipse.jface.action.Action;
77 import org.eclipse.jface.action.GroupMarker;
78 import org.eclipse.jface.action.IAction;
79 import org.eclipse.jface.action.MenuManager;
80 import org.eclipse.jface.action.Separator;
81 import org.eclipse.jface.preference.IPreferenceStore;
82 import org.eclipse.jface.preference.PreferenceConverter;
83 import org.eclipse.jface.text.BadLocationException;
84 import org.eclipse.jface.text.DefaultInformationControl;
85 import org.eclipse.jface.text.DocumentEvent;
86 import org.eclipse.jface.text.IDocument;
87 import org.eclipse.jface.text.IDocumentExtension4;
88 import org.eclipse.jface.text.IDocumentListener;
89 import org.eclipse.jface.text.IInformationControl;
90 import org.eclipse.jface.text.IInformationControlCreator;
91 import org.eclipse.jface.text.IRegion;
92 import org.eclipse.jface.text.ISelectionValidator;
93 import org.eclipse.jface.text.ISynchronizable;
94 import org.eclipse.jface.text.ITextHover;
95 import org.eclipse.jface.text.ITextInputListener;
96 import org.eclipse.jface.text.ITextPresentationListener;
97 import org.eclipse.jface.text.ITextSelection;
98 import org.eclipse.jface.text.ITextViewer;
99 import org.eclipse.jface.text.ITextViewerExtension2;
100 import org.eclipse.jface.text.ITextViewerExtension4;
101 import org.eclipse.jface.text.ITextViewerExtension5;
102 import org.eclipse.jface.text.ITypedRegion;
103 import org.eclipse.jface.text.Position;
104 import org.eclipse.jface.text.Region;
105 import org.eclipse.jface.text.TextPresentation;
106 import org.eclipse.jface.text.TextSelection;
107 import org.eclipse.jface.text.TextUtilities;
108 import org.eclipse.jface.text.information.IInformationProvider;
109 import org.eclipse.jface.text.information.InformationPresenter;
110 import org.eclipse.jface.text.link.LinkedModeModel;
111 import org.eclipse.jface.text.reconciler.IReconciler;
112 import org.eclipse.jface.text.source.Annotation;
113 import org.eclipse.jface.text.source.AnnotationRulerColumn;
114 import org.eclipse.jface.text.source.CompositeRuler;
115 import org.eclipse.jface.text.source.IAnnotationModel;
116 import org.eclipse.jface.text.source.IAnnotationModelExtension;
117 import org.eclipse.jface.text.source.IOverviewRuler;
118 import org.eclipse.jface.text.source.ISourceViewer;
119 import org.eclipse.jface.text.source.ISourceViewerExtension2;
120 import org.eclipse.jface.text.source.IVerticalRuler;
121 import org.eclipse.jface.text.source.IVerticalRulerColumn;
122 import org.eclipse.jface.text.source.OverviewRuler;
123 import org.eclipse.jface.text.source.SourceViewerConfiguration;
124 import org.eclipse.jface.text.source.projection.ProjectionSupport;
125 import org.eclipse.jface.text.source.projection.ProjectionViewer;
126 import org.eclipse.jface.util.IPropertyChangeListener;
127 import org.eclipse.jface.util.ListenerList;
128 import org.eclipse.jface.util.PropertyChangeEvent;
129 import org.eclipse.jface.viewers.DoubleClickEvent;
130 import org.eclipse.jface.viewers.IDoubleClickListener;
131 import org.eclipse.jface.viewers.IPostSelectionProvider;
132 import org.eclipse.jface.viewers.ISelection;
133 import org.eclipse.jface.viewers.ISelectionChangedListener;
134 import org.eclipse.jface.viewers.ISelectionProvider;
135 import org.eclipse.jface.viewers.IStructuredSelection;
136 import org.eclipse.jface.viewers.SelectionChangedEvent;
137 import org.eclipse.jface.viewers.StructuredSelection;
138 import org.eclipse.swt.SWT;
139 import org.eclipse.swt.custom.BidiSegmentEvent;
140 import org.eclipse.swt.custom.BidiSegmentListener;
141 import org.eclipse.swt.custom.ST;
142 import org.eclipse.swt.custom.StyleRange;
143 import org.eclipse.swt.custom.StyledText;
144 import org.eclipse.swt.events.FocusEvent;
145 import org.eclipse.swt.events.FocusListener;
146 import org.eclipse.swt.events.KeyEvent;
147 import org.eclipse.swt.events.KeyListener;
148 import org.eclipse.swt.events.MouseEvent;
149 import org.eclipse.swt.events.MouseListener;
150 import org.eclipse.swt.events.MouseMoveListener;
151 import org.eclipse.swt.events.PaintEvent;
152 import org.eclipse.swt.events.PaintListener;
153 import org.eclipse.swt.graphics.Color;
154 import org.eclipse.swt.graphics.Cursor;
155 import org.eclipse.swt.graphics.GC;
156 import org.eclipse.swt.graphics.Image;
157 import org.eclipse.swt.graphics.Point;
158 import org.eclipse.swt.graphics.RGB;
159 import org.eclipse.swt.widgets.Composite;
160 import org.eclipse.swt.widgets.Control;
161 import org.eclipse.swt.widgets.Display;
162 import org.eclipse.swt.widgets.Shell;
163 import org.eclipse.ui.IEditorInput;
164 import org.eclipse.ui.IEditorPart;
165 import org.eclipse.ui.IPageLayout;
166 import org.eclipse.ui.IPartService;
167 import org.eclipse.ui.ISelectionListener;
168 import org.eclipse.ui.IViewPart;
169 import org.eclipse.ui.IWindowListener;
170 import org.eclipse.ui.IWorkbenchPage;
171 import org.eclipse.ui.IWorkbenchPart;
172 import org.eclipse.ui.IWorkbenchWindow;
173 import org.eclipse.ui.PlatformUI;
174 import org.eclipse.ui.actions.ActionContext;
175 import org.eclipse.ui.actions.ActionGroup;
176 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
177 import org.eclipse.ui.editors.text.EditorsUI;
178 import org.eclipse.ui.editors.text.IEncodingSupport;
179 import org.eclipse.ui.part.FileEditorInput;
180 import org.eclipse.ui.part.IShowInSource;
181 import org.eclipse.ui.part.IShowInTargetList;
182 import org.eclipse.ui.part.ShowInContext;
183 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
184 import org.eclipse.ui.texteditor.AnnotationPreference;
185 import org.eclipse.ui.texteditor.ChainedPreferenceStore;
186 import org.eclipse.ui.texteditor.IDocumentProvider;
187 import org.eclipse.ui.texteditor.IEditorStatusLine;
188 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
189 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
190 import org.eclipse.ui.texteditor.IUpdate;
191 import org.eclipse.ui.texteditor.MarkerAnnotation;
192 import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
193 import org.eclipse.ui.texteditor.TextEditorAction;
194 import org.eclipse.ui.texteditor.TextNavigationAction;
195 import org.eclipse.ui.texteditor.TextOperationAction;
196 import org.eclipse.ui.views.contentoutline.ContentOutline;
197 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
198 import org.eclipse.ui.views.tasklist.TaskList;
199
200 /**
201  * PHP specific text editor.
202  */
203 public abstract class PHPEditor extends AbstractDecoratedTextEditor implements IViewPartInputProvider, IShowInTargetList,
204                 IShowInSource {
205         // extends StatusTextEditor implements IViewPartInputProvider { // extends
206         // TextEditor {
207
208         /**
209          * Internal implementation class for a change listener.
210          *
211          * @since 3.0
212          */
213         protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener {
214
215                 /**
216                  * Installs this selection changed listener with the given selection
217                  * provider. If the selection provider is a post selection provider, post
218                  * selection changed events are the preferred choice, otherwise normal
219                  * selection changed events are requested.
220                  *
221                  * @param selectionProvider
222                  */
223                 public void install(ISelectionProvider selectionProvider) {
224                         if (selectionProvider == null)
225                                 return;
226
227                         if (selectionProvider instanceof IPostSelectionProvider) {
228                                 IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
229                                 provider.addPostSelectionChangedListener(this);
230                         } else {
231                                 selectionProvider.addSelectionChangedListener(this);
232                         }
233                 }
234
235                 /**
236                  * Removes this selection changed listener from the given selection
237                  * provider.
238                  *
239                  * @param selectionProvider
240                  *          the selection provider
241                  */
242                 public void uninstall(ISelectionProvider selectionProvider) {
243                         if (selectionProvider == null)
244                                 return;
245
246                         if (selectionProvider instanceof IPostSelectionProvider) {
247                                 IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
248                                 provider.removePostSelectionChangedListener(this);
249                         } else {
250                                 selectionProvider.removeSelectionChangedListener(this);
251                         }
252                 }
253         }
254
255         /**
256          * Updates the Java outline page selection and this editor's range indicator.
257          *
258          * @since 3.0
259          */
260         private class EditorSelectionChangedListener extends AbstractSelectionChangedListener {
261
262                 /*
263                  * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
264                  */
265                 public void selectionChanged(SelectionChangedEvent event) {
266                         // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161
267                         PHPEditor.this.selectionChanged();
268                 }
269         }
270
271         /**
272          * "Smart" runnable for updating the outline page's selection.
273          */
274         // class OutlinePageSelectionUpdater implements Runnable {
275         //
276         // /** Has the runnable already been posted? */
277         // private boolean fPosted = false;
278         //
279         // public OutlinePageSelectionUpdater() {
280         // }
281         //
282         // /*
283         // * @see Runnable#run()
284         // */
285         // public void run() {
286         // synchronizeOutlinePageSelection();
287         // fPosted = false;
288         // }
289         //
290         // /**
291         // * Posts this runnable into the event queue.
292         // */
293         // public void post() {
294         // if (fPosted)
295         // return;
296         //
297         // Shell shell = getSite().getShell();
298         // if (shell != null & !shell.isDisposed()) {
299         // fPosted = true;
300         // shell.getDisplay().asyncExec(this);
301         // }
302         // }
303         // };
304         class SelectionChangedListener implements ISelectionChangedListener {
305                 public void selectionChanged(SelectionChangedEvent event) {
306                         doSelectionChanged(event);
307                 }
308         };
309
310         /**
311          * Adapts an options {@link java.util.Map}to
312          * {@link org.eclipse.jface.preference.IPreferenceStore}.
313          * <p>
314          * This preference store is read-only i.e. write access throws an
315          * {@link java.lang.UnsupportedOperationException}.
316          * </p>
317          *
318          * @since 3.0
319          */
320         private static class OptionsAdapter implements IPreferenceStore {
321
322                 /**
323                  * A property change event filter.
324                  */
325                 public interface IPropertyChangeEventFilter {
326
327                         /**
328                          * Should the given event be filtered?
329                          *
330                          * @param event
331                          *          The property change event.
332                          * @return <code>true</code> iff the given event should be filtered.
333                          */
334                         public boolean isFiltered(PropertyChangeEvent event);
335
336                 }
337
338                 /**
339                  * Property change listener. Listens for events in the options Map and fires
340                  * a {@link org.eclipse.jface.util.PropertyChangeEvent}on this adapter with
341                  * arguments from the received event.
342                  */
343                 private class PropertyChangeListener implements IPropertyChangeListener {
344
345                         /**
346                          * {@inheritDoc}
347                          */
348                         public void propertyChange(PropertyChangeEvent event) {
349                                 if (getFilter().isFiltered(event))
350                                         return;
351
352                                 if (event.getNewValue() == null)
353                                         fOptions.remove(event.getProperty());
354                                 else
355                                         fOptions.put(event.getProperty(), event.getNewValue());
356
357                                 firePropertyChangeEvent(event.getProperty(), event.getOldValue(), event.getNewValue());
358                         }
359                 }
360
361                 /** Listeners on this adapter */
362                 private ListenerList fListeners = new ListenerList();
363
364                 /** Listener on the adapted options Map */
365                 private IPropertyChangeListener fListener = new PropertyChangeListener();
366
367                 /** Adapted options Map */
368                 private Map fOptions;
369
370                 /** Preference store through which events are received. */
371                 private IPreferenceStore fMockupPreferenceStore;
372
373                 /** Property event filter. */
374                 private IPropertyChangeEventFilter fFilter;
375
376                 /**
377                  * Initialize with the given options.
378                  *
379                  * @param options
380                  *          The options to wrap
381                  * @param mockupPreferenceStore
382                  *          the mock-up preference store
383                  * @param filter
384                  *          the property change filter
385                  */
386                 public OptionsAdapter(Map options, IPreferenceStore mockupPreferenceStore, IPropertyChangeEventFilter filter) {
387                         fMockupPreferenceStore = mockupPreferenceStore;
388                         fOptions = options;
389                         setFilter(filter);
390                 }
391
392                 /**
393                  * {@inheritDoc}
394                  */
395                 public void addPropertyChangeListener(IPropertyChangeListener listener) {
396                         if (fListeners.size() == 0)
397                                 fMockupPreferenceStore.addPropertyChangeListener(fListener);
398                         fListeners.add(listener);
399                 }
400
401                 /**
402                  * {@inheritDoc}
403                  */
404                 public void removePropertyChangeListener(IPropertyChangeListener listener) {
405                         fListeners.remove(listener);
406                         if (fListeners.size() == 0)
407                                 fMockupPreferenceStore.removePropertyChangeListener(fListener);
408                 }
409
410                 /**
411                  * {@inheritDoc}
412                  */
413                 public boolean contains(String name) {
414                         return fOptions.containsKey(name);
415                 }
416
417                 /**
418                  * {@inheritDoc}
419                  */
420                 public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
421                         PropertyChangeEvent event = new PropertyChangeEvent(this, name, oldValue, newValue);
422                         Object[] listeners = fListeners.getListeners();
423                         for (int i = 0; i < listeners.length; i++)
424                                 ((IPropertyChangeListener) listeners[i]).propertyChange(event);
425                 }
426
427                 /**
428                  * {@inheritDoc}
429                  */
430                 public boolean getBoolean(String name) {
431                         boolean value = BOOLEAN_DEFAULT_DEFAULT;
432                         String s = (String) fOptions.get(name);
433                         if (s != null)
434                                 value = s.equals(TRUE);
435                         return value;
436                 }
437
438                 /**
439                  * {@inheritDoc}
440                  */
441                 public boolean getDefaultBoolean(String name) {
442                         return BOOLEAN_DEFAULT_DEFAULT;
443                 }
444
445                 /**
446                  * {@inheritDoc}
447                  */
448                 public double getDefaultDouble(String name) {
449                         return DOUBLE_DEFAULT_DEFAULT;
450                 }
451
452                 /**
453                  * {@inheritDoc}
454                  */
455                 public float getDefaultFloat(String name) {
456                         return FLOAT_DEFAULT_DEFAULT;
457                 }
458
459                 /**
460                  * {@inheritDoc}
461                  */
462                 public int getDefaultInt(String name) {
463                         return INT_DEFAULT_DEFAULT;
464                 }
465
466                 /**
467                  * {@inheritDoc}
468                  */
469                 public long getDefaultLong(String name) {
470                         return LONG_DEFAULT_DEFAULT;
471                 }
472
473                 /**
474                  * {@inheritDoc}
475                  */
476                 public String getDefaultString(String name) {
477                         return STRING_DEFAULT_DEFAULT;
478                 }
479
480                 /**
481                  * {@inheritDoc}
482                  */
483                 public double getDouble(String name) {
484                         double value = DOUBLE_DEFAULT_DEFAULT;
485                         String s = (String) fOptions.get(name);
486                         if (s != null) {
487                                 try {
488                                         value = new Double(s).doubleValue();
489                                 } catch (NumberFormatException e) {
490                                 }
491                         }
492                         return value;
493                 }
494
495                 /**
496                  * {@inheritDoc}
497                  */
498                 public float getFloat(String name) {
499                         float value = FLOAT_DEFAULT_DEFAULT;
500                         String s = (String) fOptions.get(name);
501                         if (s != null) {
502                                 try {
503                                         value = new Float(s).floatValue();
504                                 } catch (NumberFormatException e) {
505                                 }
506                         }
507                         return value;
508                 }
509
510                 /**
511                  * {@inheritDoc}
512                  */
513                 public int getInt(String name) {
514                         int value = INT_DEFAULT_DEFAULT;
515                         String s = (String) fOptions.get(name);
516                         if (s != null) {
517                                 try {
518                                         value = new Integer(s).intValue();
519                                 } catch (NumberFormatException e) {
520                                 }
521                         }
522                         return value;
523                 }
524
525                 /**
526                  * {@inheritDoc}
527                  */
528                 public long getLong(String name) {
529                         long value = LONG_DEFAULT_DEFAULT;
530                         String s = (String) fOptions.get(name);
531                         if (s != null) {
532                                 try {
533                                         value = new Long(s).longValue();
534                                 } catch (NumberFormatException e) {
535                                 }
536                         }
537                         return value;
538                 }
539
540                 /**
541                  * {@inheritDoc}
542                  */
543                 public String getString(String name) {
544                         String value = (String) fOptions.get(name);
545                         if (value == null)
546                                 value = STRING_DEFAULT_DEFAULT;
547                         return value;
548                 }
549
550                 /**
551                  * {@inheritDoc}
552                  */
553                 public boolean isDefault(String name) {
554                         return false;
555                 }
556
557                 /**
558                  * {@inheritDoc}
559                  */
560                 public boolean needsSaving() {
561                         return !fOptions.isEmpty();
562                 }
563
564                 /**
565                  * {@inheritDoc}
566                  */
567                 public void putValue(String name, String value) {
568                         throw new UnsupportedOperationException();
569                 }
570
571                 /**
572                  * {@inheritDoc}
573                  */
574                 public void setDefault(String name, double value) {
575                         throw new UnsupportedOperationException();
576                 }
577
578                 /**
579                  * {@inheritDoc}
580                  */
581                 public void setDefault(String name, float value) {
582                         throw new UnsupportedOperationException();
583                 }
584
585                 /**
586                  * {@inheritDoc}
587                  */
588                 public void setDefault(String name, int value) {
589                         throw new UnsupportedOperationException();
590                 }
591
592                 /**
593                  * {@inheritDoc}
594                  */
595                 public void setDefault(String name, long value) {
596                         throw new UnsupportedOperationException();
597                 }
598
599                 /**
600                  * {@inheritDoc}
601                  */
602                 public void setDefault(String name, String defaultObject) {
603                         throw new UnsupportedOperationException();
604                 }
605
606                 /**
607                  * {@inheritDoc}
608                  */
609                 public void setDefault(String name, boolean value) {
610                         throw new UnsupportedOperationException();
611                 }
612
613                 /**
614                  * {@inheritDoc}
615                  */
616                 public void setToDefault(String name) {
617                         throw new UnsupportedOperationException();
618                 }
619
620                 /**
621                  * {@inheritDoc}
622                  */
623                 public void setValue(String name, double value) {
624                         throw new UnsupportedOperationException();
625                 }
626
627                 /**
628                  * {@inheritDoc}
629                  */
630                 public void setValue(String name, float value) {
631                         throw new UnsupportedOperationException();
632                 }
633
634                 /**
635                  * {@inheritDoc}
636                  */
637                 public void setValue(String name, int value) {
638                         throw new UnsupportedOperationException();
639                 }
640
641                 /**
642                  * {@inheritDoc}
643                  */
644                 public void setValue(String name, long value) {
645                         throw new UnsupportedOperationException();
646                 }
647
648                 /**
649                  * {@inheritDoc}
650                  */
651                 public void setValue(String name, String value) {
652                         throw new UnsupportedOperationException();
653                 }
654
655                 /**
656                  * {@inheritDoc}
657                  */
658                 public void setValue(String name, boolean value) {
659                         throw new UnsupportedOperationException();
660                 }
661
662                 /**
663                  * Returns the adapted options Map.
664                  *
665                  * @return Returns the adapted options Map.
666                  */
667                 public Map getOptions() {
668                         return fOptions;
669                 }
670
671                 /**
672                  * Returns the mock-up preference store, events are received through this
673                  * preference store.
674                  *
675                  * @return Returns the mock-up preference store.
676                  */
677                 public IPreferenceStore getMockupPreferenceStore() {
678                         return fMockupPreferenceStore;
679                 }
680
681                 /**
682                  * Set the event filter to the given filter.
683                  *
684                  * @param filter
685                  *          The new filter.
686                  */
687                 public void setFilter(IPropertyChangeEventFilter filter) {
688                         fFilter = filter;
689                 }
690
691                 /**
692                  * Returns the event filter.
693                  *
694                  * @return The event filter.
695                  */
696                 public IPropertyChangeEventFilter getFilter() {
697                         return fFilter;
698                 }
699         }
700
701         /*
702          * Link mode.
703          */
704         // class MouseClickListener implements KeyListener, MouseListener,
705         // MouseMoveListener, FocusListener, PaintListener,
706         // IPropertyChangeListener, IDocumentListener, ITextInputListener {
707         //
708         // /** The session is active. */
709         // private boolean fActive;
710         //
711         // /** The currently active style range. */
712         // private IRegion fActiveRegion;
713         //
714         // /** The currently active style range as position. */
715         // private Position fRememberedPosition;
716         //
717         // /** The hand cursor. */
718         // private Cursor fCursor;
719         //
720         // /** The link color. */
721         // private Color fColor;
722         //
723         // /** The key modifier mask. */
724         // private int fKeyModifierMask;
725         //
726         // public void deactivate() {
727         // deactivate(false);
728         // }
729         //
730         // public void deactivate(boolean redrawAll) {
731         // if (!fActive)
732         // return;
733         //
734         // repairRepresentation(redrawAll);
735         // fActive = false;
736         // }
737         //
738         // public void install() {
739         //
740         // ISourceViewer sourceViewer = getSourceViewer();
741         // if (sourceViewer == null)
742         // return;
743         //
744         // StyledText text = sourceViewer.getTextWidget();
745         // if (text == null || text.isDisposed())
746         // return;
747         //
748         // updateColor(sourceViewer);
749         //
750         // sourceViewer.addTextInputListener(this);
751         //
752         // IDocument document = sourceViewer.getDocument();
753         // if (document != null)
754         // document.addDocumentListener(this);
755         //
756         // text.addKeyListener(this);
757         // text.addMouseListener(this);
758         // text.addMouseMoveListener(this);
759         // text.addFocusListener(this);
760         // text.addPaintListener(this);
761         //
762         // updateKeyModifierMask();
763         //
764         // IPreferenceStore preferenceStore = getPreferenceStore();
765         // preferenceStore.addPropertyChangeListener(this);
766         // }
767         //
768         // private void updateKeyModifierMask() {
769         // String modifiers =
770         // getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
771         // fKeyModifierMask = computeStateMask(modifiers);
772         // if (fKeyModifierMask == -1) {
773         // // Fallback to stored state mask
774         // fKeyModifierMask =
775         // getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
776         // }
777         // ;
778         // }
779         //
780         // private int computeStateMask(String modifiers) {
781         // if (modifiers == null)
782         // return -1;
783         //
784         // if (modifiers.length() == 0)
785         // return SWT.NONE;
786         //
787         // int stateMask = 0;
788         // StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-*
789         // "); //$NON-NLS-1$
790         // while (modifierTokenizer.hasMoreTokens()) {
791         // int modifier =
792         // EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
793         // if (modifier == 0 || (stateMask & modifier) == modifier)
794         // return -1;
795         // stateMask = stateMask | modifier;
796         // }
797         // return stateMask;
798         // }
799         //
800         // public void uninstall() {
801         //
802         // if (fColor != null) {
803         // fColor.dispose();
804         // fColor = null;
805         // }
806         //
807         // if (fCursor != null) {
808         // fCursor.dispose();
809         // fCursor = null;
810         // }
811         //
812         // ISourceViewer sourceViewer = getSourceViewer();
813         // if (sourceViewer == null)
814         // return;
815         //
816         // sourceViewer.removeTextInputListener(this);
817         //
818         // IDocument document = sourceViewer.getDocument();
819         // if (document != null)
820         // document.removeDocumentListener(this);
821         //
822         // IPreferenceStore preferenceStore = getPreferenceStore();
823         // if (preferenceStore != null)
824         // preferenceStore.removePropertyChangeListener(this);
825         //
826         // StyledText text = sourceViewer.getTextWidget();
827         // if (text == null || text.isDisposed())
828         // return;
829         //
830         // text.removeKeyListener(this);
831         // text.removeMouseListener(this);
832         // text.removeMouseMoveListener(this);
833         // text.removeFocusListener(this);
834         // text.removePaintListener(this);
835         // }
836         //
837         // /*
838         // * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
839         // */
840         // public void propertyChange(PropertyChangeEvent event) {
841         // if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
842         // ISourceViewer viewer = getSourceViewer();
843         // if (viewer != null)
844         // updateColor(viewer);
845         // } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
846         // updateKeyModifierMask();
847         // }
848         // }
849         //
850         // private void updateColor(ISourceViewer viewer) {
851         // if (fColor != null)
852         // fColor.dispose();
853         //
854         // StyledText text = viewer.getTextWidget();
855         // if (text == null || text.isDisposed())
856         // return;
857         //
858         // Display display = text.getDisplay();
859         // fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display);
860         // }
861         //
862         // /**
863         // * Creates a color from the information stored in the given preference
864         // store. Returns <code>null</code> if there is no such
865         // * information available.
866         // */
867         // private Color createColor(IPreferenceStore store, String key, Display
868         // display) {
869         //
870         // RGB rgb = null;
871         //
872         // if (store.contains(key)) {
873         //
874         // if (store.isDefault(key))
875         // rgb = PreferenceConverter.getDefaultColor(store, key);
876         // else
877         // rgb = PreferenceConverter.getColor(store, key);
878         //
879         // if (rgb != null)
880         // return new Color(display, rgb);
881         // }
882         //
883         // return null;
884         // }
885         //
886         // private void repairRepresentation() {
887         // repairRepresentation(false);
888         // }
889         //
890         // private void repairRepresentation(boolean redrawAll) {
891         //
892         // if (fActiveRegion == null)
893         // return;
894         //
895         // ISourceViewer viewer = getSourceViewer();
896         // if (viewer != null) {
897         // resetCursor(viewer);
898         //
899         // int offset = fActiveRegion.getOffset();
900         // int length = fActiveRegion.getLength();
901         //
902         // // remove style
903         // if (!redrawAll && viewer instanceof ITextViewerExtension2)
904         // ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset,
905         // length);
906         // else
907         // viewer.invalidateTextPresentation();
908         //
909         // // remove underline
910         // if (viewer instanceof ITextViewerExtension3) {
911         // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
912         // offset = extension.modelOffset2WidgetOffset(offset);
913         // } else {
914         // offset -= viewer.getVisibleRegion().getOffset();
915         // }
916         //
917         // StyledText text = viewer.getTextWidget();
918         // try {
919         // text.redrawRange(offset, length, true);
920         // } catch (IllegalArgumentException x) {
921         // PHPeclipsePlugin.log(x);
922         // }
923         // }
924         //
925         // fActiveRegion = null;
926         // }
927         //
928         // // will eventually be replaced by a method provided by jdt.core
929         // private IRegion selectWord(IDocument document, int anchor) {
930         //
931         // try {
932         // int offset = anchor;
933         // char c;
934         //
935         // while (offset >= 0) {
936         // c = document.getChar(offset);
937         // if (!Scanner.isPHPIdentifierPart(c))
938         // break;
939         // --offset;
940         // }
941         //
942         // int start = offset;
943         //
944         // offset = anchor;
945         // int length = document.getLength();
946         //
947         // while (offset < length) {
948         // c = document.getChar(offset);
949         // if (!Scanner.isPHPIdentifierPart(c))
950         // break;
951         // ++offset;
952         // }
953         //
954         // int end = offset;
955         //
956         // if (start == end)
957         // return new Region(start, 0);
958         // else
959         // return new Region(start + 1, end - start - 1);
960         //
961         // } catch (BadLocationException x) {
962         // return null;
963         // }
964         // }
965         //
966         // IRegion getCurrentTextRegion(ISourceViewer viewer) {
967         //
968         // int offset = getCurrentTextOffset(viewer);
969         // if (offset == -1)
970         // return null;
971         //
972         // return null;
973         // // IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
974         // // if (input == null)
975         // // return null;
976         // //
977         // // try {
978         // //
979         // // IJavaElement[] elements= null;
980         // // synchronized (input) {
981         // // elements= ((ICodeAssist) input).codeSelect(offset, 0);
982         // // }
983         // //
984         // // if (elements == null || elements.length == 0)
985         // // return null;
986         // //
987         // // return selectWord(viewer.getDocument(), offset);
988         // //
989         // // } catch (JavaModelException e) {
990         // // return null;
991         // // }
992         // }
993         //
994         // private int getCurrentTextOffset(ISourceViewer viewer) {
995         //
996         // try {
997         // StyledText text = viewer.getTextWidget();
998         // if (text == null || text.isDisposed())
999         // return -1;
1000         //
1001         // Display display = text.getDisplay();
1002         // Point absolutePosition = display.getCursorLocation();
1003         // Point relativePosition = text.toControl(absolutePosition);
1004         //
1005         // int widgetOffset = text.getOffsetAtLocation(relativePosition);
1006         // if (viewer instanceof ITextViewerExtension3) {
1007         // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
1008         // return extension.widgetOffset2ModelOffset(widgetOffset);
1009         // } else {
1010         // return widgetOffset + viewer.getVisibleRegion().getOffset();
1011         // }
1012         //
1013         // } catch (IllegalArgumentException e) {
1014         // return -1;
1015         // }
1016         // }
1017         //
1018         // private void highlightRegion(ISourceViewer viewer, IRegion region) {
1019         //
1020         // if (region.equals(fActiveRegion))
1021         // return;
1022         //
1023         // repairRepresentation();
1024         //
1025         // StyledText text = viewer.getTextWidget();
1026         // if (text == null || text.isDisposed())
1027         // return;
1028         //
1029         // // highlight region
1030         // int offset = 0;
1031         // int length = 0;
1032         //
1033         // if (viewer instanceof ITextViewerExtension3) {
1034         // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
1035         // IRegion widgetRange = extension.modelRange2WidgetRange(region);
1036         // if (widgetRange == null)
1037         // return;
1038         //
1039         // offset = widgetRange.getOffset();
1040         // length = widgetRange.getLength();
1041         //
1042         // } else {
1043         // offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
1044         // length = region.getLength();
1045         // }
1046         //
1047         // StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
1048         // Color foregroundColor = fColor;
1049         // Color backgroundColor = oldStyleRange == null ? text.getBackground() :
1050         // oldStyleRange.background;
1051         // StyleRange styleRange = new StyleRange(offset, length, foregroundColor,
1052         // backgroundColor);
1053         // text.setStyleRange(styleRange);
1054         //
1055         // // underline
1056         // text.redrawRange(offset, length, true);
1057         //
1058         // fActiveRegion = region;
1059         // }
1060         //
1061         // private void activateCursor(ISourceViewer viewer) {
1062         // StyledText text = viewer.getTextWidget();
1063         // if (text == null || text.isDisposed())
1064         // return;
1065         // Display display = text.getDisplay();
1066         // if (fCursor == null)
1067         // fCursor = new Cursor(display, SWT.CURSOR_HAND);
1068         // text.setCursor(fCursor);
1069         // }
1070         //
1071         // private void resetCursor(ISourceViewer viewer) {
1072         // StyledText text = viewer.getTextWidget();
1073         // if (text != null && !text.isDisposed())
1074         // text.setCursor(null);
1075         //
1076         // if (fCursor != null) {
1077         // fCursor.dispose();
1078         // fCursor = null;
1079         // }
1080         // }
1081         //
1082         // /*
1083         // * @see
1084         // org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
1085         // */
1086         // public void keyPressed(KeyEvent event) {
1087         //
1088         // if (fActive) {
1089         // deactivate();
1090         // return;
1091         // }
1092         //
1093         // if (event.keyCode != fKeyModifierMask) {
1094         // deactivate();
1095         // return;
1096         // }
1097         //
1098         // fActive = true;
1099         //
1100         // // removed for #25871
1101         // //
1102         // // ISourceViewer viewer= getSourceViewer();
1103         // // if (viewer == null)
1104         // // return;
1105         // //
1106         // // IRegion region= getCurrentTextRegion(viewer);
1107         // // if (region == null)
1108         // // return;
1109         // //
1110         // // highlightRegion(viewer, region);
1111         // // activateCursor(viewer);
1112         // }
1113         //
1114         // /*
1115         // * @see
1116         // org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
1117         // */
1118         // public void keyReleased(KeyEvent event) {
1119         //
1120         // if (!fActive)
1121         // return;
1122         //
1123         // deactivate();
1124         // }
1125         //
1126         // /*
1127         // * @see
1128         // org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
1129         // */
1130         // public void mouseDoubleClick(MouseEvent e) {
1131         // }
1132         //
1133         // /*
1134         // * @see
1135         // org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
1136         // */
1137         // public void mouseDown(MouseEvent event) {
1138         //
1139         // if (!fActive)
1140         // return;
1141         //
1142         // if (event.stateMask != fKeyModifierMask) {
1143         // deactivate();
1144         // return;
1145         // }
1146         //
1147         // if (event.button != 1) {
1148         // deactivate();
1149         // return;
1150         // }
1151         // }
1152         //
1153         // /*
1154         // * @see
1155         // org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
1156         // */
1157         // public void mouseUp(MouseEvent e) {
1158         //
1159         // if (!fActive)
1160         // return;
1161         //
1162         // if (e.button != 1) {
1163         // deactivate();
1164         // return;
1165         // }
1166         //
1167         // boolean wasActive = fCursor != null;
1168         //
1169         // deactivate();
1170         //
1171         // if (wasActive) {
1172         // IAction action = getAction("OpenEditor"); //$NON-NLS-1$
1173         // if (action != null)
1174         // action.run();
1175         // }
1176         // }
1177         //
1178         // /*
1179         // * @see
1180         // org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
1181         // */
1182         // public void mouseMove(MouseEvent event) {
1183         //
1184         // if (event.widget instanceof Control && !((Control)
1185         // event.widget).isFocusControl()) {
1186         // deactivate();
1187         // return;
1188         // }
1189         //
1190         // if (!fActive) {
1191         // if (event.stateMask != fKeyModifierMask)
1192         // return;
1193         // // modifier was already pressed
1194         // fActive = true;
1195         // }
1196         //
1197         // ISourceViewer viewer = getSourceViewer();
1198         // if (viewer == null) {
1199         // deactivate();
1200         // return;
1201         // }
1202         //
1203         // StyledText text = viewer.getTextWidget();
1204         // if (text == null || text.isDisposed()) {
1205         // deactivate();
1206         // return;
1207         // }
1208         //
1209         // if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0)
1210         // {
1211         // deactivate();
1212         // return;
1213         // }
1214         //
1215         // IRegion region = getCurrentTextRegion(viewer);
1216         // if (region == null || region.getLength() == 0) {
1217         // repairRepresentation();
1218         // return;
1219         // }
1220         //
1221         // highlightRegion(viewer, region);
1222         // activateCursor(viewer);
1223         // }
1224         //
1225         // /*
1226         // * @see
1227         // org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
1228         // */
1229         // public void focusGained(FocusEvent e) {
1230         // }
1231         //
1232         // /*
1233         // * @see
1234         // org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
1235         // */
1236         // public void focusLost(FocusEvent event) {
1237         // deactivate();
1238         // }
1239         //
1240         // /*
1241         // * @see
1242         // org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1243         // */
1244         // public void documentAboutToBeChanged(DocumentEvent event) {
1245         // if (fActive && fActiveRegion != null) {
1246         // fRememberedPosition = new Position(fActiveRegion.getOffset(),
1247         // fActiveRegion.getLength());
1248         // try {
1249         // event.getDocument().addPosition(fRememberedPosition);
1250         // } catch (BadLocationException x) {
1251         // fRememberedPosition = null;
1252         // }
1253         // }
1254         // }
1255         //
1256         // /*
1257         // * @see
1258         // org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1259         // */
1260         // public void documentChanged(DocumentEvent event) {
1261         // if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
1262         // event.getDocument().removePosition(fRememberedPosition);
1263         // fActiveRegion = new Region(fRememberedPosition.getOffset(),
1264         // fRememberedPosition.getLength());
1265         // }
1266         // fRememberedPosition = null;
1267         //
1268         // ISourceViewer viewer = getSourceViewer();
1269         // if (viewer != null) {
1270         // StyledText widget = viewer.getTextWidget();
1271         // if (widget != null && !widget.isDisposed()) {
1272         // widget.getDisplay().asyncExec(new Runnable() {
1273         // public void run() {
1274         // deactivate();
1275         // }
1276         // });
1277         // }
1278         // }
1279         // }
1280         //
1281         // /*
1282         // * @see
1283         // org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
1284         // * org.eclipse.jface.text.IDocument)
1285         // */
1286         // public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument
1287         // newInput) {
1288         // if (oldInput == null)
1289         // return;
1290         // deactivate();
1291         // oldInput.removeDocumentListener(this);
1292         // }
1293         //
1294         // /*
1295         // * @see
1296         // org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
1297         // * org.eclipse.jface.text.IDocument)
1298         // */
1299         // public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
1300         // if (newInput == null)
1301         // return;
1302         // newInput.addDocumentListener(this);
1303         // }
1304         //
1305         // /*
1306         // * @see PaintListener#paintControl(PaintEvent)
1307         // */
1308         // public void paintControl(PaintEvent event) {
1309         // if (fActiveRegion == null)
1310         // return;
1311         //
1312         // ISourceViewer viewer = getSourceViewer();
1313         // if (viewer == null)
1314         // return;
1315         //
1316         // StyledText text = viewer.getTextWidget();
1317         // if (text == null || text.isDisposed())
1318         // return;
1319         //
1320         // int offset = 0;
1321         // int length = 0;
1322         //
1323         // if (viewer instanceof ITextViewerExtension3) {
1324         //
1325         // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
1326         // IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset,
1327         // length));
1328         // if (widgetRange == null)
1329         // return;
1330         //
1331         // offset = widgetRange.getOffset();
1332         // length = widgetRange.getLength();
1333         //
1334         // } else {
1335         //
1336         // IRegion region = viewer.getVisibleRegion();
1337         // if (!includes(region, fActiveRegion))
1338         // return;
1339         //
1340         // offset = fActiveRegion.getOffset() - region.getOffset();
1341         // length = fActiveRegion.getLength();
1342         // }
1343         //
1344         // // support for bidi
1345         // Point minLocation = getMinimumLocation(text, offset, length);
1346         // Point maxLocation = getMaximumLocation(text, offset, length);
1347         //
1348         // int x1 = minLocation.x;
1349         // int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
1350         // int y = minLocation.y + text.getLineHeight() - 1;
1351         //
1352         // GC gc = event.gc;
1353         // if (fColor != null && !fColor.isDisposed())
1354         // gc.setForeground(fColor);
1355         // gc.drawLine(x1, y, x2, y);
1356         // }
1357         //
1358         // private boolean includes(IRegion region, IRegion position) {
1359         // return position.getOffset() >= region.getOffset()
1360         // && position.getOffset() + position.getLength() <= region.getOffset() +
1361         // region.getLength();
1362         // }
1363         //
1364         // private Point getMinimumLocation(StyledText text, int offset, int length) {
1365         // Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
1366         //
1367         // for (int i = 0; i <= length; i++) {
1368         // Point location = text.getLocationAtOffset(offset + i);
1369         //
1370         // if (location.x < minLocation.x)
1371         // minLocation.x = location.x;
1372         // if (location.y < minLocation.y)
1373         // minLocation.y = location.y;
1374         // }
1375         //
1376         // return minLocation;
1377         // }
1378         //
1379         // private Point getMaximumLocation(StyledText text, int offset, int length) {
1380         // Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
1381         //
1382         // for (int i = 0; i <= length; i++) {
1383         // Point location = text.getLocationAtOffset(offset + i);
1384         //
1385         // if (location.x > maxLocation.x)
1386         // maxLocation.x = location.x;
1387         // if (location.y > maxLocation.y)
1388         // maxLocation.y = location.y;
1389         // }
1390         //
1391         // return maxLocation;
1392         // }
1393         // };
1394         /*
1395          * Link mode.
1396          */
1397         class MouseClickListener implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener,
1398                         IPropertyChangeListener, IDocumentListener, ITextInputListener, ITextPresentationListener {
1399
1400                 /** The session is active. */
1401                 private boolean fActive;
1402
1403                 /** The currently active style range. */
1404                 private IRegion fActiveRegion;
1405
1406                 /** The currently active style range as position. */
1407                 private Position fRememberedPosition;
1408
1409                 /** The hand cursor. */
1410                 private Cursor fCursor;
1411
1412                 /** The link color. */
1413                 private Color fColor;
1414
1415                 /** The key modifier mask. */
1416                 private int fKeyModifierMask;
1417
1418                 public void deactivate() {
1419                         deactivate(false);
1420                 }
1421
1422                 public void deactivate(boolean redrawAll) {
1423                         if (!fActive)
1424                                 return;
1425
1426                         repairRepresentation(redrawAll);
1427                         fActive = false;
1428                 }
1429
1430                 public void install() {
1431                         ISourceViewer sourceViewer = getSourceViewer();
1432                         if (sourceViewer == null)
1433                                 return;
1434
1435                         StyledText text = sourceViewer.getTextWidget();
1436                         if (text == null || text.isDisposed())
1437                                 return;
1438
1439                         updateColor(sourceViewer);
1440
1441                         sourceViewer.addTextInputListener(this);
1442
1443                         IDocument document = sourceViewer.getDocument();
1444                         if (document != null)
1445                                 document.addDocumentListener(this);
1446
1447                         text.addKeyListener(this);
1448                         text.addMouseListener(this);
1449                         text.addMouseMoveListener(this);
1450                         text.addFocusListener(this);
1451                         text.addPaintListener(this);
1452
1453                         ((ITextViewerExtension4) sourceViewer).addTextPresentationListener(this);
1454
1455                         updateKeyModifierMask();
1456
1457                         IPreferenceStore preferenceStore = getPreferenceStore();
1458                         preferenceStore.addPropertyChangeListener(this);
1459                 }
1460
1461                 private void updateKeyModifierMask() {
1462                         String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
1463                         fKeyModifierMask = computeStateMask(modifiers);
1464                         if (fKeyModifierMask == -1) {
1465                                 // Fall back to stored state mask
1466                                 fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
1467                         }
1468                 }
1469
1470                 private int computeStateMask(String modifiers) {
1471                         if (modifiers == null)
1472                                 return -1;
1473
1474                         if (modifiers.length() == 0)
1475                                 return SWT.NONE;
1476
1477                         int stateMask = 0;
1478                         StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$
1479                         while (modifierTokenizer.hasMoreTokens()) {
1480                                 int modifier = EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
1481                                 if (modifier == 0 || (stateMask & modifier) == modifier)
1482                                         return -1;
1483                                 stateMask = stateMask | modifier;
1484                         }
1485                         return stateMask;
1486                 }
1487
1488                 public void uninstall() {
1489
1490                         if (fColor != null) {
1491                                 fColor.dispose();
1492                                 fColor = null;
1493                         }
1494
1495                         if (fCursor != null) {
1496                                 fCursor.dispose();
1497                                 fCursor = null;
1498                         }
1499
1500                         ISourceViewer sourceViewer = getSourceViewer();
1501                         if (sourceViewer != null)
1502                                 sourceViewer.removeTextInputListener(this);
1503
1504                         IDocumentProvider documentProvider = getDocumentProvider();
1505                         if (documentProvider != null) {
1506                                 IDocument document = documentProvider.getDocument(getEditorInput());
1507                                 if (document != null)
1508                                         document.removeDocumentListener(this);
1509                         }
1510
1511                         IPreferenceStore preferenceStore = getPreferenceStore();
1512                         if (preferenceStore != null)
1513                                 preferenceStore.removePropertyChangeListener(this);
1514
1515                         if (sourceViewer == null)
1516                                 return;
1517
1518                         StyledText text = sourceViewer.getTextWidget();
1519                         if (text == null || text.isDisposed())
1520                                 return;
1521
1522                         text.removeKeyListener(this);
1523                         text.removeMouseListener(this);
1524                         text.removeMouseMoveListener(this);
1525                         text.removeFocusListener(this);
1526                         text.removePaintListener(this);
1527
1528                         ((ITextViewerExtension4) sourceViewer).removeTextPresentationListener(this);
1529                 }
1530
1531                 /*
1532                  * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
1533                  */
1534                 public void propertyChange(PropertyChangeEvent event) {
1535                         if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
1536                                 ISourceViewer viewer = getSourceViewer();
1537                                 if (viewer != null)
1538                                         updateColor(viewer);
1539                         } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
1540                                 updateKeyModifierMask();
1541                         }
1542                 }
1543
1544                 private void updateColor(ISourceViewer viewer) {
1545                         if (fColor != null)
1546                                 fColor.dispose();
1547
1548                         StyledText text = viewer.getTextWidget();
1549                         if (text == null || text.isDisposed())
1550                                 return;
1551
1552                         Display display = text.getDisplay();
1553                         fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display);
1554                 }
1555
1556                 /**
1557                  * Creates a color from the information stored in the given preference
1558                  * store.
1559                  *
1560                  * @param store
1561                  *          the preference store
1562                  * @param key
1563                  *          the key
1564                  * @param display
1565                  *          the display
1566                  * @return the color or <code>null</code> if there is no such information
1567                  *         available
1568                  */
1569                 private Color createColor(IPreferenceStore store, String key, Display display) {
1570
1571                         RGB rgb = null;
1572
1573                         if (store.contains(key)) {
1574
1575                                 if (store.isDefault(key))
1576                                         rgb = PreferenceConverter.getDefaultColor(store, key);
1577                                 else
1578                                         rgb = PreferenceConverter.getColor(store, key);
1579
1580                                 if (rgb != null)
1581                                         return new Color(display, rgb);
1582                         }
1583
1584                         return null;
1585                 }
1586
1587                 private void repairRepresentation() {
1588                         repairRepresentation(false);
1589                 }
1590
1591                 private void repairRepresentation(boolean redrawAll) {
1592
1593                         if (fActiveRegion == null)
1594                                 return;
1595
1596                         int offset = fActiveRegion.getOffset();
1597                         int length = fActiveRegion.getLength();
1598                         fActiveRegion = null;
1599
1600                         ISourceViewer viewer = getSourceViewer();
1601                         if (viewer != null) {
1602
1603                                 resetCursor(viewer);
1604
1605                                 // Invalidate ==> remove applied text presentation
1606                                 if (!redrawAll && viewer instanceof ITextViewerExtension2)
1607                                         ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length);
1608                                 else
1609                                         viewer.invalidateTextPresentation();
1610
1611                                 // Remove underline
1612                                 if (viewer instanceof ITextViewerExtension5) {
1613                                         ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
1614                                         offset = extension.modelOffset2WidgetOffset(offset);
1615                                 } else {
1616                                         offset -= viewer.getVisibleRegion().getOffset();
1617                                 }
1618                                 try {
1619                                         StyledText text = viewer.getTextWidget();
1620
1621                                         text.redrawRange(offset, length, false);
1622                                 } catch (IllegalArgumentException x) {
1623                                         // JavaPlugin.log(x);
1624                                 }
1625                         }
1626                 }
1627
1628                 // will eventually be replaced by a method provided by jdt.core
1629                 private IRegion selectWord(IDocument document, int anchor) {
1630
1631                         try {
1632                                 int offset = anchor;
1633                                 char c;
1634
1635                                 while (offset >= 0) {
1636                                         c = document.getChar(offset);
1637                                         if (!Scanner.isPHPIdentifierPart(c) && c != '$')
1638                                                 break;
1639                                         --offset;
1640                                 }
1641
1642                                 int start = offset;
1643
1644                                 offset = anchor;
1645                                 int length = document.getLength();
1646
1647                                 while (offset < length) {
1648                                         c = document.getChar(offset);
1649                                         if (!Scanner.isPHPIdentifierPart(c) && c != '$')
1650                                                 break;
1651                                         ++offset;
1652                                 }
1653
1654                                 int end = offset;
1655
1656                                 if (start == end)
1657                                         return new Region(start, 0);
1658                                 else
1659                                         return new Region(start + 1, end - start - 1);
1660
1661                         } catch (BadLocationException x) {
1662                                 return null;
1663                         }
1664                 }
1665
1666                 IRegion getCurrentTextRegion(ISourceViewer viewer) {
1667
1668                         int offset = getCurrentTextOffset(viewer);
1669                         if (offset == -1)
1670                                 return null;
1671
1672                         IJavaElement input = SelectionConverter.getInput(PHPEditor.this);
1673                         if (input == null)
1674                                 return null;
1675
1676                         // try {
1677
1678                         // IJavaElement[] elements= null;
1679                         // synchronized (input) {
1680                         // elements= ((ICodeAssist) input).codeSelect(offset, 0);
1681                         // }
1682                         //
1683                         // if (elements == null || elements.length == 0)
1684                         // return null;
1685
1686                         return selectWord(viewer.getDocument(), offset);
1687
1688                         // } catch (JavaModelException e) {
1689                         // return null;
1690                         // }
1691                 }
1692
1693                 private int getCurrentTextOffset(ISourceViewer viewer) {
1694
1695                         try {
1696                                 StyledText text = viewer.getTextWidget();
1697                                 if (text == null || text.isDisposed())
1698                                         return -1;
1699
1700                                 Display display = text.getDisplay();
1701                                 Point absolutePosition = display.getCursorLocation();
1702                                 Point relativePosition = text.toControl(absolutePosition);
1703
1704                                 int widgetOffset = text.getOffsetAtLocation(relativePosition);
1705                                 if (viewer instanceof ITextViewerExtension5) {
1706                                         ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
1707                                         return extension.widgetOffset2ModelOffset(widgetOffset);
1708                                 } else {
1709                                         return widgetOffset + viewer.getVisibleRegion().getOffset();
1710                                 }
1711
1712                         } catch (IllegalArgumentException e) {
1713                                 return -1;
1714                         }
1715                 }
1716
1717                 public void applyTextPresentation(TextPresentation textPresentation) {
1718                         if (fActiveRegion == null)
1719                                 return;
1720                         IRegion region = textPresentation.getExtent();
1721                         if (fActiveRegion.getOffset() + fActiveRegion.getLength() >= region.getOffset()
1722                                         && region.getOffset() + region.getLength() > fActiveRegion.getOffset())
1723                                 textPresentation.mergeStyleRange(new StyleRange(fActiveRegion.getOffset(), fActiveRegion.getLength(), fColor, null));
1724                 }
1725
1726                 private void highlightRegion(ISourceViewer viewer, IRegion region) {
1727
1728                         if (region.equals(fActiveRegion))
1729                                 return;
1730
1731                         repairRepresentation();
1732
1733                         StyledText text = viewer.getTextWidget();
1734                         if (text == null || text.isDisposed())
1735                                 return;
1736
1737                         // Underline
1738                         int offset = 0;
1739                         int length = 0;
1740                         if (viewer instanceof ITextViewerExtension5) {
1741                                 ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
1742                                 IRegion widgetRange = extension.modelRange2WidgetRange(region);
1743                                 if (widgetRange == null)
1744                                         return;
1745
1746                                 offset = widgetRange.getOffset();
1747                                 length = widgetRange.getLength();
1748
1749                         } else {
1750                                 offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
1751                                 length = region.getLength();
1752                         }
1753                         text.redrawRange(offset, length, false);
1754
1755                         // Invalidate region ==> apply text presentation
1756                         fActiveRegion = region;
1757                         if (viewer instanceof ITextViewerExtension2)
1758                                 ((ITextViewerExtension2) viewer).invalidateTextPresentation(region.getOffset(), region.getLength());
1759                         else
1760                                 viewer.invalidateTextPresentation();
1761                 }
1762
1763                 private void activateCursor(ISourceViewer viewer) {
1764                         StyledText text = viewer.getTextWidget();
1765                         if (text == null || text.isDisposed())
1766                                 return;
1767                         Display display = text.getDisplay();
1768                         if (fCursor == null)
1769                                 fCursor = new Cursor(display, SWT.CURSOR_HAND);
1770                         text.setCursor(fCursor);
1771                 }
1772
1773                 private void resetCursor(ISourceViewer viewer) {
1774                         StyledText text = viewer.getTextWidget();
1775                         if (text != null && !text.isDisposed())
1776                                 text.setCursor(null);
1777
1778                         if (fCursor != null) {
1779                                 fCursor.dispose();
1780                                 fCursor = null;
1781                         }
1782                 }
1783
1784                 /*
1785                  * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
1786                  */
1787                 public void keyPressed(KeyEvent event) {
1788
1789                         if (fActive) {
1790                                 deactivate();
1791                                 return;
1792                         }
1793
1794                         if (event.keyCode != fKeyModifierMask) {
1795                                 deactivate();
1796                                 return;
1797                         }
1798
1799                         fActive = true;
1800
1801                         // removed for #25871
1802                         //
1803                         // ISourceViewer viewer= getSourceViewer();
1804                         // if (viewer == null)
1805                         // return;
1806                         //
1807                         // IRegion region= getCurrentTextRegion(viewer);
1808                         // if (region == null)
1809                         // return;
1810                         //
1811                         // highlightRegion(viewer, region);
1812                         // activateCursor(viewer);
1813                 }
1814
1815                 /*
1816                  * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
1817                  */
1818                 public void keyReleased(KeyEvent event) {
1819
1820                         if (!fActive)
1821                                 return;
1822
1823                         deactivate();
1824                 }
1825
1826                 /*
1827                  * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
1828                  */
1829                 public void mouseDoubleClick(MouseEvent e) {
1830                 }
1831
1832                 /*
1833                  * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
1834                  */
1835                 public void mouseDown(MouseEvent event) {
1836
1837                         if (!fActive)
1838                                 return;
1839
1840                         if (event.stateMask != fKeyModifierMask) {
1841                                 deactivate();
1842                                 return;
1843                         }
1844
1845                         if (event.button != 1) {
1846                                 deactivate();
1847                                 return;
1848                         }
1849                 }
1850
1851                 /*
1852                  * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
1853                  */
1854                 public void mouseUp(MouseEvent e) {
1855
1856                         if (!fActive)
1857                                 return;
1858
1859                         if (e.button != 1) {
1860                                 deactivate();
1861                                 return;
1862                         }
1863
1864                         boolean wasActive = fCursor != null;
1865
1866                         deactivate();
1867
1868                         if (wasActive) {
1869                                 IAction action = getAction("OpenEditor"); //$NON-NLS-1$
1870                                 if (action != null)
1871                                         action.run();
1872                         }
1873                 }
1874
1875                 /*
1876                  * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
1877                  */
1878                 public void mouseMove(MouseEvent event) {
1879
1880                         if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) {
1881                                 deactivate();
1882                                 return;
1883                         }
1884
1885                         if (!fActive) {
1886                                 if (event.stateMask != fKeyModifierMask)
1887                                         return;
1888                                 // modifier was already pressed
1889                                 fActive = true;
1890                         }
1891
1892                         ISourceViewer viewer = getSourceViewer();
1893                         if (viewer == null) {
1894                                 deactivate();
1895                                 return;
1896                         }
1897
1898                         StyledText text = viewer.getTextWidget();
1899                         if (text == null || text.isDisposed()) {
1900                                 deactivate();
1901                                 return;
1902                         }
1903
1904                         if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0) {
1905                                 deactivate();
1906                                 return;
1907                         }
1908
1909                         IRegion region = getCurrentTextRegion(viewer);
1910                         if (region == null || region.getLength() == 0) {
1911                                 repairRepresentation();
1912                                 return;
1913                         }
1914
1915                         highlightRegion(viewer, region);
1916                         activateCursor(viewer);
1917                 }
1918
1919                 /*
1920                  * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
1921                  */
1922                 public void focusGained(FocusEvent e) {
1923                 }
1924
1925                 /*
1926                  * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
1927                  */
1928                 public void focusLost(FocusEvent event) {
1929                         deactivate();
1930                 }
1931
1932                 /*
1933                  * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1934                  */
1935                 public void documentAboutToBeChanged(DocumentEvent event) {
1936                         if (fActive && fActiveRegion != null) {
1937                                 fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength());
1938                                 try {
1939                                         event.getDocument().addPosition(fRememberedPosition);
1940                                 } catch (BadLocationException x) {
1941                                         fRememberedPosition = null;
1942                                 }
1943                         }
1944                 }
1945
1946                 /*
1947                  * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1948                  */
1949                 public void documentChanged(DocumentEvent event) {
1950                         if (fRememberedPosition != null) {
1951                                 if (!fRememberedPosition.isDeleted()) {
1952
1953                                         event.getDocument().removePosition(fRememberedPosition);
1954                                         fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength());
1955                                         fRememberedPosition = null;
1956
1957                                         ISourceViewer viewer = getSourceViewer();
1958                                         if (viewer != null) {
1959                                                 StyledText widget = viewer.getTextWidget();
1960                                                 if (widget != null && !widget.isDisposed()) {
1961                                                         widget.getDisplay().asyncExec(new Runnable() {
1962                                                                 public void run() {
1963                                                                         deactivate();
1964                                                                 }
1965                                                         });
1966                                                 }
1967                                         }
1968
1969                                 } else {
1970                                         fActiveRegion = null;
1971                                         fRememberedPosition = null;
1972                                         deactivate();
1973                                 }
1974                         }
1975                 }
1976
1977                 /*
1978                  * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
1979                  *      org.eclipse.jface.text.IDocument)
1980                  */
1981                 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
1982                         if (oldInput == null)
1983                                 return;
1984                         deactivate();
1985                         oldInput.removeDocumentListener(this);
1986                 }
1987
1988                 /*
1989                  * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
1990                  *      org.eclipse.jface.text.IDocument)
1991                  */
1992                 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
1993                         if (newInput == null)
1994                                 return;
1995                         newInput.addDocumentListener(this);
1996                 }
1997
1998                 /*
1999                  * @see PaintListener#paintControl(PaintEvent)
2000                  */
2001                 public void paintControl(PaintEvent event) {
2002                         if (fActiveRegion == null)
2003                                 return;
2004
2005                         ISourceViewer viewer = getSourceViewer();
2006                         if (viewer == null)
2007                                 return;
2008
2009                         StyledText text = viewer.getTextWidget();
2010                         if (text == null || text.isDisposed())
2011                                 return;
2012
2013                         int offset = 0;
2014                         int length = 0;
2015
2016                         if (viewer instanceof ITextViewerExtension5) {
2017
2018                                 ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
2019                                 IRegion widgetRange = extension.modelRange2WidgetRange(fActiveRegion);
2020                                 if (widgetRange == null)
2021                                         return;
2022
2023                                 offset = widgetRange.getOffset();
2024                                 length = widgetRange.getLength();
2025
2026                         } else {
2027
2028                                 IRegion region = viewer.getVisibleRegion();
2029                                 if (!includes(region, fActiveRegion))
2030                                         return;
2031
2032                                 offset = fActiveRegion.getOffset() - region.getOffset();
2033                                 length = fActiveRegion.getLength();
2034                         }
2035
2036                         // support for bidi
2037                         Point minLocation = getMinimumLocation(text, offset, length);
2038                         Point maxLocation = getMaximumLocation(text, offset, length);
2039
2040                         int x1 = minLocation.x;
2041                         int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
2042                         int y = minLocation.y + text.getLineHeight() - 1;
2043
2044                         GC gc = event.gc;
2045                         if (fColor != null && !fColor.isDisposed())
2046                                 gc.setForeground(fColor);
2047                         gc.drawLine(x1, y, x2, y);
2048                 }
2049
2050                 private boolean includes(IRegion region, IRegion position) {
2051                         return position.getOffset() >= region.getOffset()
2052                                         && position.getOffset() + position.getLength() <= region.getOffset() + region.getLength();
2053                 }
2054
2055                 private Point getMinimumLocation(StyledText text, int offset, int length) {
2056                         Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
2057
2058                         for (int i = 0; i <= length; i++) {
2059                                 Point location = text.getLocationAtOffset(offset + i);
2060
2061                                 if (location.x < minLocation.x)
2062                                         minLocation.x = location.x;
2063                                 if (location.y < minLocation.y)
2064                                         minLocation.y = location.y;
2065                         }
2066
2067                         return minLocation;
2068                 }
2069
2070                 private Point getMaximumLocation(StyledText text, int offset, int length) {
2071                         Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
2072
2073                         for (int i = 0; i <= length; i++) {
2074                                 Point location = text.getLocationAtOffset(offset + i);
2075
2076                                 if (location.x > maxLocation.x)
2077                                         maxLocation.x = location.x;
2078                                 if (location.y > maxLocation.y)
2079                                         maxLocation.y = location.y;
2080                         }
2081
2082                         return maxLocation;
2083                 }
2084         }
2085
2086         /**
2087          * This action dispatches into two behaviours: If there is no current text
2088          * hover, the javadoc is displayed using information presenter. If there is a
2089          * current text hover, it is converted into a information presenter in order
2090          * to make it sticky.
2091          */
2092         class InformationDispatchAction extends TextEditorAction {
2093
2094                 /** The wrapped text operation action. */
2095                 private final TextOperationAction fTextOperationAction;
2096
2097                 /**
2098                  * Creates a dispatch action.
2099                  */
2100                 public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) {
2101                         super(resourceBundle, prefix, PHPEditor.this);
2102                         if (textOperationAction == null)
2103                                 throw new IllegalArgumentException();
2104                         fTextOperationAction = textOperationAction;
2105                 }
2106
2107                 /*
2108                  * @see org.eclipse.jface.action.IAction#run()
2109                  */
2110                 public void run() {
2111
2112                         ISourceViewer sourceViewer = getSourceViewer();
2113                         if (sourceViewer == null) {
2114                                 fTextOperationAction.run();
2115                                 return;
2116                         }
2117
2118                         if (!(sourceViewer instanceof ITextViewerExtension2)) {
2119                                 fTextOperationAction.run();
2120                                 return;
2121                         }
2122
2123                         ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
2124
2125                         // does a text hover exist?
2126                         ITextHover textHover = textViewerExtension2.getCurrentTextHover();
2127                         if (textHover == null) {
2128                                 fTextOperationAction.run();
2129                                 return;
2130                         }
2131
2132                         Point hoverEventLocation = textViewerExtension2.getHoverEventLocation();
2133                         int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y);
2134                         if (offset == -1) {
2135                                 fTextOperationAction.run();
2136                                 return;
2137                         }
2138
2139                         try {
2140                                 // get the text hover content
2141                                 IDocument document = sourceViewer.getDocument();
2142                                 String contentType = document.getContentType(offset);
2143
2144                                 final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset);
2145                                 if (hoverRegion == null)
2146                                         return;
2147
2148                                 final String hoverInfo = textHover.getHoverInfo(sourceViewer, hoverRegion);
2149
2150                                 // with information provider
2151                                 IInformationProvider informationProvider = new IInformationProvider() {
2152                                         /*
2153                                          * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
2154                                          *      int)
2155                                          */
2156                                         public IRegion getSubject(ITextViewer textViewer, int offset) {
2157                                                 return hoverRegion;
2158                                         }
2159
2160                                         /*
2161                                          * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
2162                                          *      org.eclipse.jface.text.IRegion)
2163                                          */
2164                                         public String getInformation(ITextViewer textViewer, IRegion subject) {
2165                                                 return hoverInfo;
2166                                         }
2167                                 };
2168
2169                                 fInformationPresenter.setOffset(offset);
2170                                 fInformationPresenter.setInformationProvider(informationProvider, contentType);
2171                                 fInformationPresenter.showInformation();
2172
2173                         } catch (BadLocationException e) {
2174                         }
2175                 }
2176
2177                 // modified version from TextViewer
2178                 private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
2179
2180                         StyledText styledText = textViewer.getTextWidget();
2181                         IDocument document = textViewer.getDocument();
2182
2183                         if (document == null)
2184                                 return -1;
2185
2186                         try {
2187                                 int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y));
2188                                 if (textViewer instanceof ITextViewerExtension5) {
2189                                         ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer;
2190                                         return extension.widgetOffset2ModelOffset(widgetLocation);
2191                                 } else {
2192                                         IRegion visibleRegion = textViewer.getVisibleRegion();
2193                                         return widgetLocation + visibleRegion.getOffset();
2194                                 }
2195                         } catch (IllegalArgumentException e) {
2196                                 return -1;
2197                         }
2198
2199                 }
2200         };
2201
2202         /**
2203          * This action implements smart home.
2204          *
2205          * Instead of going to the start of a line it does the following: - if smart
2206          * home/end is enabled and the caret is after the line's first non-whitespace
2207          * then the caret is moved directly before it, taking JavaDoc and multi-line
2208          * comments into account. - if the caret is before the line's first
2209          * non-whitespace the caret is moved to the beginning of the line - if the
2210          * caret is at the beginning of the line see first case.
2211          *
2212          * @since 3.0
2213          */
2214         protected class SmartLineStartAction extends LineStartAction {
2215
2216                 /**
2217                  * Creates a new smart line start action
2218                  *
2219                  * @param textWidget
2220                  *          the styled text widget
2221                  * @param doSelect
2222                  *          a boolean flag which tells if the text up to the beginning of
2223                  *          the line should be selected
2224                  */
2225                 public SmartLineStartAction(final StyledText textWidget, final boolean doSelect) {
2226                         super(textWidget, doSelect);
2227                 }
2228
2229                 /*
2230                  * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#getLineStartPosition(java.lang.String,
2231                  *      int, java.lang.String)
2232                  */
2233                 protected int getLineStartPosition(final IDocument document, final String line, final int length, final int offset) {
2234
2235                         String type = IDocument.DEFAULT_CONTENT_TYPE;
2236                         try {
2237                                 type = TextUtilities.getContentType(document, IPHPPartitions.PHP_PARTITIONING, offset, true);
2238                         } catch (BadLocationException exception) {
2239                                 // Should not happen
2240                         }
2241
2242                         int index = super.getLineStartPosition(document, line, length, offset);
2243                         if (type.equals(IPHPPartitions.PHP_PHPDOC_COMMENT) || type.equals(IPHPPartitions.PHP_MULTILINE_COMMENT)) {
2244                                 if (index < length - 1 && line.charAt(index) == '*' && line.charAt(index + 1) != '/') {
2245                                         do {
2246                                                 ++index;
2247                                         } while (index < length && Character.isWhitespace(line.charAt(index)));
2248                                 }
2249                         } else {
2250                                 if (index < length - 1 && line.charAt(index) == '/' && line.charAt(index + 1) == '/') {
2251                                         index++;
2252                                         do {
2253                                                 ++index;
2254                                         } while (index < length && Character.isWhitespace(line.charAt(index)));
2255                                 }
2256                         }
2257                         return index;
2258                 }
2259         }
2260
2261         /**
2262          * Text navigation action to navigate to the next sub-word.
2263          *
2264          * @since 3.0
2265          */
2266         protected abstract class NextSubWordAction extends TextNavigationAction {
2267
2268                 protected JavaWordIterator fIterator = new JavaWordIterator();
2269
2270                 /**
2271                  * Creates a new next sub-word action.
2272                  *
2273                  * @param code
2274                  *          Action code for the default operation. Must be an action code
2275                  *          from
2276                  * @see org.eclipse.swt.custom.ST.
2277                  */
2278                 protected NextSubWordAction(int code) {
2279                         super(getSourceViewer().getTextWidget(), code);
2280                 }
2281
2282                 /*
2283                  * @see org.eclipse.jface.action.IAction#run()
2284                  */
2285                 public void run() {
2286                         // Check whether we are in a java code partition and the preference is
2287                         // enabled
2288                         final IPreferenceStore store = getPreferenceStore();
2289                         if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
2290                                 super.run();
2291                                 return;
2292                         }
2293
2294                         final ISourceViewer viewer = getSourceViewer();
2295                         final IDocument document = viewer.getDocument();
2296                         fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document));
2297                         int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
2298                         if (position == -1)
2299                                 return;
2300
2301                         int next = findNextPosition(position);
2302                         if (next != BreakIterator.DONE) {
2303                                 setCaretPosition(next);
2304                                 getTextWidget().showSelection();
2305                                 fireSelectionChanged();
2306                         }
2307
2308                 }
2309
2310                 /**
2311                  * Finds the next position after the given position.
2312                  *
2313                  * @param position
2314                  *          the current position
2315                  * @return the next position
2316                  */
2317                 protected int findNextPosition(int position) {
2318                         ISourceViewer viewer = getSourceViewer();
2319                         int widget = -1;
2320                         while (position != BreakIterator.DONE && widget == -1) { // TODO:
2321                                 // optimize
2322                                 position = fIterator.following(position);
2323                                 if (position != BreakIterator.DONE)
2324                                         widget = modelOffset2WidgetOffset(viewer, position);
2325                         }
2326                         return position;
2327                 }
2328
2329                 /**
2330                  * Sets the caret position to the sub-word boundary given with
2331                  * <code>position</code>.
2332                  *
2333                  * @param position
2334                  *          Position where the action should move the caret
2335                  */
2336                 protected abstract void setCaretPosition(int position);
2337         }
2338
2339         /**
2340          * Text navigation action to navigate to the next sub-word.
2341          *
2342          * @since 3.0
2343          */
2344         protected class NavigateNextSubWordAction extends NextSubWordAction {
2345
2346                 /**
2347                  * Creates a new navigate next sub-word action.
2348                  */
2349                 public NavigateNextSubWordAction() {
2350                         super(ST.WORD_NEXT);
2351                 }
2352
2353                 /*
2354                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
2355                  */
2356                 protected void setCaretPosition(final int position) {
2357                         getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
2358                 }
2359         }
2360
2361         /**
2362          * Text operation action to delete the next sub-word.
2363          *
2364          * @since 3.0
2365          */
2366         protected class DeleteNextSubWordAction extends NextSubWordAction implements IUpdate {
2367
2368                 /**
2369                  * Creates a new delete next sub-word action.
2370                  */
2371                 public DeleteNextSubWordAction() {
2372                         super(ST.DELETE_WORD_NEXT);
2373                 }
2374
2375                 /*
2376                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
2377                  */
2378                 protected void setCaretPosition(final int position) {
2379                         if (!validateEditorInputState())
2380                                 return;
2381
2382                         final ISourceViewer viewer = getSourceViewer();
2383                         final int caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
2384
2385                         try {
2386                                 viewer.getDocument().replace(caret, position - caret, ""); //$NON-NLS-1$
2387                         } catch (BadLocationException exception) {
2388                                 // Should not happen
2389                         }
2390                 }
2391
2392                 /*
2393                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int)
2394                  */
2395                 protected int findNextPosition(int position) {
2396                         return fIterator.following(position);
2397                 }
2398
2399                 /*
2400                  * @see org.eclipse.ui.texteditor.IUpdate#update()
2401                  */
2402                 public void update() {
2403                         setEnabled(isEditorInputModifiable());
2404                 }
2405         }
2406
2407         /**
2408          * Text operation action to select the next sub-word.
2409          *
2410          * @since 3.0
2411          */
2412         protected class SelectNextSubWordAction extends NextSubWordAction {
2413
2414                 /**
2415                  * Creates a new select next sub-word action.
2416                  */
2417                 public SelectNextSubWordAction() {
2418                         super(ST.SELECT_WORD_NEXT);
2419                 }
2420
2421                 /*
2422                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
2423                  */
2424                 protected void setCaretPosition(final int position) {
2425                         final ISourceViewer viewer = getSourceViewer();
2426
2427                         final StyledText text = viewer.getTextWidget();
2428                         if (text != null && !text.isDisposed()) {
2429
2430                                 final Point selection = text.getSelection();
2431                                 final int caret = text.getCaretOffset();
2432                                 final int offset = modelOffset2WidgetOffset(viewer, position);
2433
2434                                 if (caret == selection.x)
2435                                         text.setSelectionRange(selection.y, offset - selection.y);
2436                                 else
2437                                         text.setSelectionRange(selection.x, offset - selection.x);
2438                         }
2439                 }
2440         }
2441
2442         /**
2443          * Text navigation action to navigate to the previous sub-word.
2444          *
2445          * @since 3.0
2446          */
2447         protected abstract class PreviousSubWordAction extends TextNavigationAction {
2448
2449                 protected JavaWordIterator fIterator = new JavaWordIterator();
2450
2451                 /**
2452                  * Creates a new previous sub-word action.
2453                  *
2454                  * @param code
2455                  *          Action code for the default operation. Must be an action code
2456                  *          from
2457                  * @see org.eclipse.swt.custom.ST.
2458                  */
2459                 protected PreviousSubWordAction(final int code) {
2460                         super(getSourceViewer().getTextWidget(), code);
2461                 }
2462
2463                 /*
2464                  * @see org.eclipse.jface.action.IAction#run()
2465                  */
2466                 public void run() {
2467                         // Check whether we are in a java code partition and the preference is
2468                         // enabled
2469                         final IPreferenceStore store = getPreferenceStore();
2470                         if (!store.getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
2471                                 super.run();
2472                                 return;
2473                         }
2474
2475                         final ISourceViewer viewer = getSourceViewer();
2476                         final IDocument document = viewer.getDocument();
2477                         fIterator.setText((CharacterIterator) new DocumentCharacterIterator(document));
2478                         int position = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
2479                         if (position == -1)
2480                                 return;
2481
2482                         int previous = findPreviousPosition(position);
2483                         if (previous != BreakIterator.DONE) {
2484                                 setCaretPosition(previous);
2485                                 getTextWidget().showSelection();
2486                                 fireSelectionChanged();
2487                         }
2488
2489                 }
2490
2491                 /**
2492                  * Finds the previous position before the given position.
2493                  *
2494                  * @param position
2495                  *          the current position
2496                  * @return the previous position
2497                  */
2498                 protected int findPreviousPosition(int position) {
2499                         ISourceViewer viewer = getSourceViewer();
2500                         int widget = -1;
2501                         while (position != BreakIterator.DONE && widget == -1) { // TODO:
2502                                 // optimize
2503                                 position = fIterator.preceding(position);
2504                                 if (position != BreakIterator.DONE)
2505                                         widget = modelOffset2WidgetOffset(viewer, position);
2506                         }
2507                         return position;
2508                 }
2509
2510                 /**
2511                  * Sets the caret position to the sub-word boundary given with
2512                  * <code>position</code>.
2513                  *
2514                  * @param position
2515                  *          Position where the action should move the caret
2516                  */
2517                 protected abstract void setCaretPosition(int position);
2518         }
2519
2520         /**
2521          * Text navigation action to navigate to the previous sub-word.
2522          *
2523          * @since 3.0
2524          */
2525         protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
2526
2527                 /**
2528                  * Creates a new navigate previous sub-word action.
2529                  */
2530                 public NavigatePreviousSubWordAction() {
2531                         super(ST.WORD_PREVIOUS);
2532                 }
2533
2534                 /*
2535                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
2536                  */
2537                 protected void setCaretPosition(final int position) {
2538                         getTextWidget().setCaretOffset(modelOffset2WidgetOffset(getSourceViewer(), position));
2539                 }
2540         }
2541
2542         /**
2543          * Text operation action to delete the previous sub-word.
2544          *
2545          * @since 3.0
2546          */
2547         protected class DeletePreviousSubWordAction extends PreviousSubWordAction implements IUpdate {
2548
2549                 /**
2550                  * Creates a new delete previous sub-word action.
2551                  */
2552                 public DeletePreviousSubWordAction() {
2553                         super(ST.DELETE_WORD_PREVIOUS);
2554                 }
2555
2556                 /*
2557                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
2558                  */
2559                 protected void setCaretPosition(final int position) {
2560                         if (!validateEditorInputState())
2561                                 return;
2562
2563                         final ISourceViewer viewer = getSourceViewer();
2564                         final int caret = widgetOffset2ModelOffset(viewer, viewer.getTextWidget().getCaretOffset());
2565
2566                         try {
2567                                 viewer.getDocument().replace(position, caret - position, ""); //$NON-NLS-1$
2568                         } catch (BadLocationException exception) {
2569                                 // Should not happen
2570                         }
2571                 }
2572
2573                 /*
2574                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int)
2575                  */
2576                 protected int findPreviousPosition(int position) {
2577                         return fIterator.preceding(position);
2578                 }
2579
2580                 /*
2581                  * @see org.eclipse.ui.texteditor.IUpdate#update()
2582                  */
2583                 public void update() {
2584                         setEnabled(isEditorInputModifiable());
2585                 }
2586         }
2587
2588         /**
2589          * Text operation action to select the previous sub-word.
2590          *
2591          * @since 3.0
2592          */
2593         protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
2594
2595                 /**
2596                  * Creates a new select previous sub-word action.
2597                  */
2598                 public SelectPreviousSubWordAction() {
2599                         super(ST.SELECT_WORD_PREVIOUS);
2600                 }
2601
2602                 /*
2603                  * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
2604                  */
2605                 protected void setCaretPosition(final int position) {
2606                         final ISourceViewer viewer = getSourceViewer();
2607
2608                         final StyledText text = viewer.getTextWidget();
2609                         if (text != null && !text.isDisposed()) {
2610
2611                                 final Point selection = text.getSelection();
2612                                 final int caret = text.getCaretOffset();
2613                                 final int offset = modelOffset2WidgetOffset(viewer, position);
2614
2615                                 if (caret == selection.x)
2616                                         text.setSelectionRange(selection.y, offset - selection.y);
2617                                 else
2618                                         text.setSelectionRange(selection.x, offset - selection.x);
2619                         }
2620                 }
2621         }
2622
2623         // static protected class AnnotationAccess implements IAnnotationAccess {
2624         // /*
2625         // * @see
2626         // org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
2627         // */
2628         // public Object getType(Annotation annotation) {
2629         // if (annotation instanceof IJavaAnnotation) {
2630         // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
2631         // // if (javaAnnotation.isRelevant())
2632         // // return javaAnnotation.getAnnotationType();
2633         // }
2634         // return null;
2635         // }
2636         //
2637         // /*
2638         // * @see
2639         // org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
2640         // */
2641         // public boolean isMultiLine(Annotation annotation) {
2642         // return true;
2643         // }
2644         //
2645         // /*
2646         // * @see
2647         // org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
2648         // */
2649         // public boolean isTemporary(Annotation annotation) {
2650         // if (annotation instanceof IJavaAnnotation) {
2651         // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
2652         // if (javaAnnotation.isRelevant())
2653         // return javaAnnotation.isTemporary();
2654         // }
2655         // return false;
2656         // }
2657         // };
2658
2659         private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
2660                 /*
2661                  * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
2662                  */
2663                 public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
2664                         handlePreferencePropertyChanged(event);
2665                 }
2666         };
2667
2668         /**
2669          * Finds and marks occurrence annotations.
2670          *
2671          * @since 3.0
2672          */
2673         class OccurrencesFinderJob extends Job {
2674
2675                 private IDocument fDocument;
2676
2677                 private ISelection fSelection;
2678
2679                 private ISelectionValidator fPostSelectionValidator;
2680
2681                 private boolean fCanceled = false;
2682
2683                 private IProgressMonitor fProgressMonitor;
2684
2685                 private Position[] fPositions;
2686
2687                 public OccurrencesFinderJob(IDocument document, Position[] positions, ISelection selection) {
2688                         super(PHPEditorMessages.JavaEditor_markOccurrences_job_name);
2689                         fDocument = document;
2690                         fSelection = selection;
2691                         fPositions = positions;
2692
2693                         if (getSelectionProvider() instanceof ISelectionValidator)
2694                                 fPostSelectionValidator = (ISelectionValidator) getSelectionProvider();
2695                 }
2696
2697                 // cannot use cancel() because it is declared final
2698                 void doCancel() {
2699                         fCanceled = true;
2700                         cancel();
2701                 }
2702
2703                 private boolean isCanceled() {
2704                         return fCanceled || fProgressMonitor.isCanceled() || fPostSelectionValidator != null
2705                                         && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
2706                                         || LinkedModeModel.hasInstalledModel(fDocument);
2707                 }
2708
2709                 /*
2710                  * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
2711                  */
2712                 public IStatus run(IProgressMonitor progressMonitor) {
2713
2714                         fProgressMonitor = progressMonitor;
2715
2716                         if (isCanceled())
2717                                 return Status.CANCEL_STATUS;
2718
2719                         ITextViewer textViewer = getViewer();
2720                         if (textViewer == null)
2721                                 return Status.CANCEL_STATUS;
2722
2723                         IDocument document = textViewer.getDocument();
2724                         if (document == null)
2725                                 return Status.CANCEL_STATUS;
2726
2727                         IDocumentProvider documentProvider = getDocumentProvider();
2728                         if (documentProvider == null)
2729                                 return Status.CANCEL_STATUS;
2730
2731                         IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput());
2732                         if (annotationModel == null)
2733                                 return Status.CANCEL_STATUS;
2734
2735                         // Add occurrence annotations
2736                         int length = fPositions.length;
2737                         Map annotationMap = new HashMap(length);
2738                         for (int i = 0; i < length; i++) {
2739
2740                                 if (isCanceled())
2741                                         return Status.CANCEL_STATUS;
2742
2743                                 String message;
2744                                 Position position = fPositions[i];
2745
2746                                 // Create & add annotation
2747                                 try {
2748                                         message = document.get(position.offset, position.length);
2749                                 } catch (BadLocationException ex) {
2750                                         // Skip this match
2751                                         continue;
2752                                 }
2753                                 annotationMap.put(new Annotation("net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$
2754                                                 position);
2755                         }
2756
2757                         if (isCanceled())
2758                                 return Status.CANCEL_STATUS;
2759
2760                         synchronized (getLockObject(annotationModel)) {
2761                                 if (annotationModel instanceof IAnnotationModelExtension) {
2762                                         ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
2763                                 } else {
2764                                         removeOccurrenceAnnotations();
2765                                         Iterator iter = annotationMap.entrySet().iterator();
2766                                         while (iter.hasNext()) {
2767                                                 Map.Entry mapEntry = (Map.Entry) iter.next();
2768                                                 annotationModel.addAnnotation((Annotation) mapEntry.getKey(), (Position) mapEntry.getValue());
2769                                         }
2770                                 }
2771                                 fOccurrenceAnnotations = (Annotation[]) annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
2772                         }
2773
2774                         return Status.OK_STATUS;
2775                 }
2776         }
2777
2778         /**
2779          * Cancels the occurrences finder job upon document changes.
2780          *
2781          * @since 3.0
2782          */
2783         class OccurrencesFinderJobCanceler implements IDocumentListener, ITextInputListener {
2784
2785                 public void install() {
2786                         ISourceViewer sourceViewer = getSourceViewer();
2787                         if (sourceViewer == null)
2788                                 return;
2789
2790                         StyledText text = sourceViewer.getTextWidget();
2791                         if (text == null || text.isDisposed())
2792                                 return;
2793
2794                         sourceViewer.addTextInputListener(this);
2795
2796                         IDocument document = sourceViewer.getDocument();
2797                         if (document != null)
2798                                 document.addDocumentListener(this);
2799                 }
2800
2801                 public void uninstall() {
2802                         ISourceViewer sourceViewer = getSourceViewer();
2803                         if (sourceViewer != null)
2804                                 sourceViewer.removeTextInputListener(this);
2805
2806                         IDocumentProvider documentProvider = getDocumentProvider();
2807                         if (documentProvider != null) {
2808                                 IDocument document = documentProvider.getDocument(getEditorInput());
2809                                 if (document != null)
2810                                         document.removeDocumentListener(this);
2811                         }
2812                 }
2813
2814                 /*
2815                  * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
2816                  */
2817                 public void documentAboutToBeChanged(DocumentEvent event) {
2818                         if (fOccurrencesFinderJob != null)
2819                                 fOccurrencesFinderJob.doCancel();
2820                 }
2821
2822                 /*
2823                  * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
2824                  */
2825                 public void documentChanged(DocumentEvent event) {
2826                 }
2827
2828                 /*
2829                  * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
2830                  *      org.eclipse.jface.text.IDocument)
2831                  */
2832                 public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
2833                         if (oldInput == null)
2834                                 return;
2835
2836                         oldInput.removeDocumentListener(this);
2837                 }
2838
2839                 /*
2840                  * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
2841                  *      org.eclipse.jface.text.IDocument)
2842                  */
2843                 public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
2844                         if (newInput == null)
2845                                 return;
2846                         newInput.addDocumentListener(this);
2847                 }
2848         }
2849
2850         /**
2851          * Internal activation listener.
2852          *
2853          * @since 3.0
2854          */
2855         private class ActivationListener implements IWindowListener {
2856
2857                 /*
2858                  * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
2859                  * @since 3.1
2860                  */
2861                 public void windowActivated(IWorkbenchWindow window) {
2862                         if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart()) {
2863                                 fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection();
2864                                 SelectionListenerWithASTManager.getDefault().forceSelectionChange(PHPEditor.this,
2865                                                 (ITextSelection) fForcedMarkOccurrencesSelection);
2866                         }
2867                 }
2868
2869                 /*
2870                  * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
2871                  * @since 3.1
2872                  */
2873                 public void windowDeactivated(IWorkbenchWindow window) {
2874                         if (window == getEditorSite().getWorkbenchWindow() && fMarkOccurrenceAnnotations && isActivePart())
2875                                 removeOccurrenceAnnotations();
2876                 }
2877
2878                 /*
2879                  * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
2880                  * @since 3.1
2881                  */
2882                 public void windowClosed(IWorkbenchWindow window) {
2883                 }
2884
2885                 /*
2886                  * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
2887                  * @since 3.1
2888                  */
2889                 public void windowOpened(IWorkbenchWindow window) {
2890                 }
2891         }
2892
2893         /**
2894          * Updates the selection in the editor's widget with the selection of the
2895          * outline page.
2896          */
2897         class OutlineSelectionChangedListener extends AbstractSelectionChangedListener {
2898                 public void selectionChanged(SelectionChangedEvent event) {
2899                         doSelectionChanged(event);
2900                 }
2901         }
2902
2903         /**
2904          * The internal shell activation listener for updating occurrences.
2905          *
2906          * @since 3.0
2907          */
2908         private ActivationListener fActivationListener = new ActivationListener();
2909
2910         private ISelectionListenerWithAST fPostSelectionListenerWithAST;
2911
2912         private OccurrencesFinderJob fOccurrencesFinderJob;
2913
2914         /** The occurrences finder job canceler */
2915         private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler;
2916
2917         /**
2918          * Holds the current occurrence annotations.
2919          *
2920          * @since 3.0
2921          */
2922         private Annotation[] fOccurrenceAnnotations = null;
2923
2924         /**
2925          * Tells whether all occurrences of the element at the current caret location
2926          * are automatically marked in this editor.
2927          *
2928          * @since 3.0
2929          */
2930         private boolean fMarkOccurrenceAnnotations;
2931
2932         /**
2933          * The selection used when forcing occurrence marking through code.
2934          *
2935          * @since 3.0
2936          */
2937         private ISelection fForcedMarkOccurrencesSelection;
2938
2939         /**
2940          * The document modification stamp at the time when the last occurrence
2941          * marking took place.
2942          *
2943          * @since 3.1
2944          */
2945         private long fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
2946
2947         /**
2948          * The region of the word under the caret used to when computing the current
2949          * occurrence markings.
2950          *
2951          * @since 3.1
2952          */
2953         private IRegion fMarkOccurrenceTargetRegion;
2954
2955         /**
2956          * Tells whether the occurrence annotations are sticky i.e. whether they stay
2957          * even if there's no valid Java element at the current caret position. Only
2958          * valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
2959          *
2960          * @since 3.0
2961          */
2962         private boolean fStickyOccurrenceAnnotations;
2963
2964         /** Preference key for showing the line number ruler */
2965         // private final static String LINE_NUMBER_RULER =
2966         // PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
2967         /** Preference key for the foreground color of the line numbers */
2968         // private final static String LINE_NUMBER_COLOR =
2969         // PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
2970         /** Preference key for the link color */
2971         private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
2972
2973         /** Preference key for compiler task tags */
2974         private final static String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
2975
2976         // protected PHPActionGroup fActionGroups;
2977         // /** The outline page */
2978         // private AbstractContentOutlinePage fOutlinePage;
2979         /** The outline page */
2980         protected JavaOutlinePage fOutlinePage;
2981
2982         /** Outliner context menu Id */
2983         protected String fOutlinerContextMenuId;
2984
2985         /**
2986          * Indicates whether this editor should react on outline page selection
2987          * changes
2988          */
2989         private int fIgnoreOutlinePageSelection;
2990
2991         /** The outline page selection updater */
2992         // private OutlinePageSelectionUpdater fUpdater;
2993         // protected PHPSyntaxParserThread fValidationThread = null;
2994         // private IPreferenceStore fPHPPrefStore;
2995         /** The selection changed listener */
2996         // protected ISelectionChangedListener fSelectionChangedListener = new
2997         // SelectionChangedListener();
2998         /**
2999          * The editor selection changed listener.
3000          *
3001          * @since 3.0
3002          */
3003         private EditorSelectionChangedListener fEditorSelectionChangedListener;
3004
3005         /** The selection changed listener */
3006         protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener();
3007
3008         /** The editor's bracket matcher */
3009         private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
3010
3011         /** The line number ruler column */
3012         // private LineNumberRulerColumn fLineNumberRulerColumn;
3013         /** This editor's encoding support */
3014         private DefaultEncodingSupport fEncodingSupport;
3015
3016         /** The mouse listener */
3017         private MouseClickListener fMouseListener;
3018
3019         /**
3020          * Indicates whether this editor is about to update any annotation views.
3021          *
3022          * @since 3.0
3023          */
3024         private boolean fIsUpdatingAnnotationViews = false;
3025
3026         /**
3027          * The marker that served as last target for a goto marker request.
3028          *
3029          * @since 3.0
3030          */
3031         private IMarker fLastMarkerTarget = null;
3032
3033         protected CompositeActionGroup fActionGroups;
3034
3035         protected CompositeActionGroup fContextMenuGroup;
3036
3037         /**
3038          * This editor's projection support
3039          *
3040          * @since 3.0
3041          */
3042         private ProjectionSupport fProjectionSupport;
3043
3044         /**
3045          * This editor's projection model updater
3046          *
3047          * @since 3.0
3048          */
3049         private IJavaFoldingStructureProvider fProjectionModelUpdater;
3050
3051         /**
3052          * The override and implements indicator manager for this editor.
3053          *
3054          * @since 3.0
3055          */
3056         // protected OverrideIndicatorManager fOverrideIndicatorManager;
3057         /**
3058          * The action group for folding.
3059          *
3060          * @since 3.0
3061          */
3062         private FoldingActionGroup fFoldingGroup;
3063
3064         /** The information presenter. */
3065         private InformationPresenter fInformationPresenter;
3066
3067         /** The annotation access */
3068         // protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
3069         /** The overview ruler */
3070         protected OverviewRuler isOverviewRulerVisible;
3071
3072         /** The source viewer decoration support */
3073         // protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
3074         /** The overview ruler */
3075         // protected OverviewRuler fOverviewRuler;
3076         /** The preference property change listener for java core. */
3077         private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
3078
3079         /**
3080          * Returns the most narrow java element including the given offset
3081          *
3082          * @param offset
3083          *          the offset inside of the requested element
3084          */
3085         abstract protected IJavaElement getElementAt(int offset);
3086
3087         /**
3088          * Returns the java element of this editor's input corresponding to the given
3089          * IJavaElement
3090          */
3091         abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
3092
3093         /**
3094          * Sets the input of the editor's outline page.
3095          */
3096         abstract protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input);
3097
3098         /**
3099          * Default constructor.
3100          */
3101         public PHPEditor() {
3102                 super();
3103         }
3104
3105         /*
3106          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
3107          */
3108         protected void initializeKeyBindingScopes() {
3109                 setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$
3110         }
3111
3112         /*
3113          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
3114          */
3115         protected void initializeEditor() {
3116                 // jsurfer old code
3117                 // JavaTextTools textTools =
3118                 // PHPeclipsePlugin.getDefault().getJavaTextTools();
3119                 // setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools,
3120                 // this, IPHPPartitions.PHP_PARTITIONING)); //,
3121                 // IJavaPartitions.JAVA_PARTITIONING));
3122                 IPreferenceStore store = createCombinedPreferenceStore(null);
3123                 setPreferenceStore(store);
3124                 JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
3125                 setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this,
3126                                 IPHPPartitions.PHP_PARTITIONING));
3127
3128                 // TODO changed in 3.x ?
3129                 // setRangeIndicator(new DefaultRangeIndicator());
3130                 // if
3131                 // (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
3132                 // fUpdater = new OutlinePageSelectionUpdater();
3133                 // jsurfer end
3134
3135                 // IPreferenceStore store= createCombinedPreferenceStore(null);
3136                 // setPreferenceStore(store);
3137                 // JavaTextTools textTools=
3138                 // PHPeclipsePlugin.getDefault().getJavaTextTools();
3139                 // setSourceViewerConfiguration(new
3140                 // JavaSourceViewerConfiguration(textTools.getColorManager(), store,
3141                 // this, IJavaPartitions.JAVA_PARTITIONING));
3142                 fMarkOccurrenceAnnotations = store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
3143                 fStickyOccurrenceAnnotations = store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
3144                 // fMarkTypeOccurrences=
3145                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
3146                 // fMarkMethodOccurrences=
3147                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
3148                 // fMarkConstantOccurrences=
3149                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
3150                 // fMarkFieldOccurrences=
3151                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
3152                 // fMarkLocalVariableypeOccurrences=
3153                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
3154                 // fMarkExceptions=
3155                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
3156                 // fMarkImplementors=
3157                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS);
3158                 // fMarkMethodExitPoints=
3159                 // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
3160
3161         }
3162
3163         /*
3164          * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
3165          */
3166         protected void updatePropertyDependentActions() {
3167                 super.updatePropertyDependentActions();
3168                 if (fEncodingSupport != null)
3169                         fEncodingSupport.reset();
3170         }
3171
3172         /*
3173          * Update the hovering behavior depending on the preferences.
3174          */
3175         private void updateHoverBehavior() {
3176                 SourceViewerConfiguration configuration = getSourceViewerConfiguration();
3177                 String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
3178
3179                 for (int i = 0; i < types.length; i++) {
3180
3181                         String t = types[i];
3182
3183                         int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
3184
3185                         ISourceViewer sourceViewer = getSourceViewer();
3186                         if (sourceViewer instanceof ITextViewerExtension2) {
3187                                 if (stateMasks != null) {
3188                                         for (int j = 0; j < stateMasks.length; j++) {
3189                                                 int stateMask = stateMasks[j];
3190                                                 ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
3191                                                 ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
3192                                         }
3193                                 } else {
3194                                         ITextHover textHover = configuration.getTextHover(sourceViewer, t);
3195                                         ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
3196                                 }
3197                         } else
3198                                 sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
3199                 }
3200         }
3201
3202         public void updatedTitleImage(Image image) {
3203                 setTitleImage(image);
3204         }
3205
3206         /*
3207          * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
3208          */
3209         public Object getViewPartInput() {
3210                 return getEditorInput().getAdapter(IResource.class);
3211         }
3212
3213         /*
3214          * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
3215          */
3216         protected void doSetSelection(ISelection selection) {
3217                 super.doSetSelection(selection);
3218                 synchronizeOutlinePageSelection();
3219         }
3220
3221         boolean isFoldingEnabled() {
3222                 return PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
3223         }
3224
3225         /*
3226          * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
3227          *      widgets.Composite)
3228          */
3229         public void createPartControl(Composite parent) {
3230                 super.createPartControl(parent);
3231
3232                 // fSourceViewerDecorationSupport.install(getPreferenceStore());
3233
3234                 ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
3235
3236                 fProjectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors());
3237                 fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
3238                 fProjectionSupport.addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
3239                 fProjectionSupport.setHoverControlCreator(new IInformationControlCreator() {
3240                         public IInformationControl createInformationControl(Shell shell) {
3241                                 return new CustomSourceInformationControl(shell, IDocument.DEFAULT_CONTENT_TYPE);
3242                         }
3243                 });
3244                 fProjectionSupport.install();
3245
3246                 fProjectionModelUpdater = PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
3247                 if (fProjectionModelUpdater != null)
3248                         fProjectionModelUpdater.install(this, projectionViewer);
3249
3250                 if (isFoldingEnabled())
3251                         projectionViewer.doOperation(ProjectionViewer.TOGGLE);
3252                 Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
3253                 preferences.addPropertyChangeListener(fPropertyChangeListener);
3254
3255                 IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
3256                         public IInformationControl createInformationControl(Shell parent) {
3257                                 boolean cutDown = false;
3258                                 int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
3259                                 return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown));
3260                         }
3261                 };
3262
3263                 fInformationPresenter = new InformationPresenter(informationControlCreator);
3264                 fInformationPresenter.setSizeConstraints(60, 10, true, true);
3265                 fInformationPresenter.install(getSourceViewer());
3266
3267                 fEditorSelectionChangedListener = new EditorSelectionChangedListener();
3268                 fEditorSelectionChangedListener.install(getSelectionProvider());
3269
3270                 if (isBrowserLikeLinks())
3271                         enableBrowserLikeLinks();
3272
3273                 if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE))
3274                         enableOverwriteMode(false);
3275
3276                 if (fMarkOccurrenceAnnotations)
3277                         installOccurrencesFinder();
3278
3279                 PlatformUI.getWorkbench().addWindowListener(fActivationListener);
3280
3281                 setWordWrap();
3282         }
3283
3284         private void setWordWrap() {
3285                 if (getSourceViewer() != null) {
3286                         getSourceViewer().getTextWidget().setWordWrap(
3287                                         PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_WRAP_WORDS));
3288                 }
3289         }
3290
3291         protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) {
3292
3293                 support.setCharacterPairMatcher(fBracketMatcher);
3294                 support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
3295
3296                 super.configureSourceViewerDecorationSupport(support);
3297         }
3298
3299         /*
3300          * @see org.eclipse.ui.texteditor.AbstractTextEditor#gotoMarker(org.eclipse.core.resources.IMarker)
3301          */
3302         public void gotoMarker(IMarker marker) {
3303                 fLastMarkerTarget = marker;
3304                 if (!fIsUpdatingAnnotationViews) {
3305                         super.gotoMarker(marker);
3306                 }
3307         }
3308
3309         /**
3310          * Jumps to the next enabled annotation according to the given direction. An
3311          * annotation type is enabled if it is configured to be in the Next/Previous
3312          * tool bar drop down menu and if it is checked.
3313          *
3314          * @param forward
3315          *          <code>true</code> if search direction is forward,
3316          *          <code>false</code> if backward
3317          */
3318         public Annotation gotoAnnotation(boolean forward) {
3319                 ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection();
3320                 Position position = new Position(0, 0);
3321                 Annotation annotation=null;
3322                 if (false /* delayed - see bug 18316 */) {
3323                         annotation=getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
3324                         selectAndReveal(position.getOffset(), position.getLength());
3325                 } else /* no delay - see bug 18316 */{
3326                         annotation = getNextAnnotation(selection.getOffset(), selection.getLength(), forward, position);
3327                         setStatusLineErrorMessage(null);
3328                         setStatusLineMessage(null);
3329                         if (annotation != null) {
3330                                 updateAnnotationViews(annotation);
3331                                 selectAndReveal(position.getOffset(), position.getLength());
3332                                 setStatusLineMessage(annotation.getText());
3333                         }
3334                 }
3335                 return annotation;
3336         }
3337
3338         /**
3339          * Returns the lock object for the given annotation model.
3340          *
3341          * @param annotationModel
3342          *          the annotation model
3343          * @return the annotation model's lock object
3344          * @since 3.0
3345          */
3346         private Object getLockObject(IAnnotationModel annotationModel) {
3347                 if (annotationModel instanceof ISynchronizable)
3348                         return ((ISynchronizable) annotationModel).getLockObject();
3349                 else
3350                         return annotationModel;
3351         }
3352
3353         /**
3354          * Updates the annotation views that show the given annotation.
3355          *
3356          * @param annotation
3357          *          the annotation
3358          */
3359         private void updateAnnotationViews(Annotation annotation) {
3360                 IMarker marker = null;
3361                 if (annotation instanceof MarkerAnnotation)
3362                         marker = ((MarkerAnnotation) annotation).getMarker();
3363                 else if (annotation instanceof IJavaAnnotation) {
3364                         Iterator e = ((IJavaAnnotation) annotation).getOverlaidIterator();
3365                         if (e != null) {
3366                                 while (e.hasNext()) {
3367                                         Object o = e.next();
3368                                         if (o instanceof MarkerAnnotation) {
3369                                                 marker = ((MarkerAnnotation) o).getMarker();
3370                                                 break;
3371                                         }
3372                                 }
3373                         }
3374                 }
3375
3376                 if (marker != null && !marker.equals(fLastMarkerTarget)) {
3377                         try {
3378                                 boolean isProblem = marker.isSubtypeOf(IMarker.PROBLEM);
3379                                 IWorkbenchPage page = getSite().getPage();
3380                                 IViewPart view = page.findView(isProblem ? IPageLayout.ID_PROBLEM_VIEW : IPageLayout.ID_TASK_LIST); //$NON-NLS-1$  //$NON-NLS-2$
3381                                 if (view != null) {
3382                                         Method method = view.getClass().getMethod("setSelection", new Class[] { IStructuredSelection.class, boolean.class }); //$NON-NLS-1$
3383                                         method.invoke(view, new Object[] { new StructuredSelection(marker), Boolean.TRUE });
3384                                 }
3385                         } catch (CoreException x) {
3386                         } catch (NoSuchMethodException x) {
3387                         } catch (IllegalAccessException x) {
3388                         } catch (InvocationTargetException x) {
3389                         }
3390                         // ignore exceptions, don't update any of the lists, just set status line
3391                 }
3392         }
3393
3394         /**
3395          * Returns this document's complete text.
3396          *
3397          * @return the document's complete text
3398          */
3399         public String get() {
3400                 IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
3401                 return doc.get();
3402         }
3403
3404         /**
3405          * Sets the outliner's context menu ID.
3406          */
3407         protected void setOutlinerContextMenuId(String menuId) {
3408                 fOutlinerContextMenuId = menuId;
3409         }
3410
3411         /**
3412          * Returns the standard action group of this editor.
3413          */
3414         protected ActionGroup getActionGroup() {
3415                 return fActionGroups;
3416         }
3417
3418         // public JavaOutlinePage getfOutlinePage() {
3419         // return fOutlinePage;
3420         // }
3421
3422         /**
3423          * The <code>PHPEditor</code> implementation of this
3424          * <code>AbstractTextEditor</code> method extend the actions to add those
3425          * specific to the receiver
3426          */
3427         protected void createActions() {
3428                 super.createActions();
3429
3430                 ActionGroup oeg, ovg, jsg, sg;
3431                 fActionGroups = new CompositeActionGroup(new ActionGroup[] { oeg = new OpenEditorActionGroup(this),
3432                 // sg= new ShowActionGroup(this),
3433                                 // ovg= new OpenViewActionGroup(this),
3434                                 // jsg= new JavaSearchActionGroup(this)
3435                                 });
3436                 fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] { oeg });
3437                 // , ovg, sg, jsg});
3438
3439                 fFoldingGroup = new FoldingActionGroup(this, getViewer());
3440
3441                 // ResourceAction resAction = new
3442                 // TextOperationAction(PHPEditorMessages.getResourceBundle(),
3443                 // "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
3444                 // resAction = new
3445                 // InformationDispatchAction(PHPEditorMessages.getResourceBundle(),
3446                 // "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
3447                 // resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
3448                 // setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
3449
3450                 // WorkbenchHelp.setHelp(resAction,
3451                 // IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
3452
3453                 Action action = new GotoMatchingBracketAction(this);
3454                 action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
3455                 setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
3456
3457                 // action= new
3458                 // TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.",
3459                 // this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
3460                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
3461                 // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
3462                 // // WorkbenchHelp.setHelp(action,
3463                 // IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
3464                 //
3465                 // action= new
3466                 // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.",
3467                 // this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
3468                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
3469                 // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE,
3470                 // action);
3471                 // // WorkbenchHelp.setHelp(action,
3472                 // IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
3473                 //
3474                 // action= new
3475                 // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.",
3476                 // this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
3477                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
3478                 // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY,
3479                 // action);
3480                 // // WorkbenchHelp.setHelp(action,
3481                 // IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
3482
3483                 fEncodingSupport = new DefaultEncodingSupport();
3484                 fEncodingSupport.initialize(this);
3485
3486                 // fSelectionHistory= new SelectionHistory(this);
3487                 //
3488                 // action= new StructureSelectEnclosingAction(this, fSelectionHistory);
3489                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);
3490                 // setAction(StructureSelectionAction.ENCLOSING, action);
3491                 //
3492                 // action= new StructureSelectNextAction(this, fSelectionHistory);
3493                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
3494                 // setAction(StructureSelectionAction.NEXT, action);
3495                 //
3496                 // action= new StructureSelectPreviousAction(this, fSelectionHistory);
3497                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
3498                 // setAction(StructureSelectionAction.PREVIOUS, action);
3499                 //
3500                 // StructureSelectHistoryAction historyAction= new
3501                 // StructureSelectHistoryAction(this, fSelectionHistory);
3502                 // historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);
3503                 // setAction(StructureSelectionAction.HISTORY, historyAction);
3504                 // fSelectionHistory.setHistoryAction(historyAction);
3505                 //
3506                 // action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
3507                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
3508                 // setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
3509                 //
3510                 // action=
3511                 // GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
3512                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
3513                 // setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
3514                 //
3515                 // action= new QuickFormatAction();
3516                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
3517                 // setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
3518                 //
3519                 // action= new RemoveOccurrenceAnnotations(this);
3520                 // action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
3521                 // setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
3522
3523                 // add annotation actions
3524                 action = new JavaSelectMarkerRulerAction2(PHPEditorMessages.getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
3525                 setAction("AnnotationAction", action); //$NON-NLS-1$
3526         }
3527
3528         private void internalDoSetInput(IEditorInput input) throws CoreException {
3529                 super.doSetInput(input);
3530
3531                 if (getSourceViewer() instanceof JavaSourceViewer) {
3532                         JavaSourceViewer viewer = (JavaSourceViewer) getSourceViewer();
3533                         if (viewer.getReconciler() == null) {
3534                                 IReconciler reconciler = getSourceViewerConfiguration().getReconciler(viewer);
3535                                 if (reconciler != null) {
3536                                         reconciler.install(viewer);
3537                                         viewer.setReconciler(reconciler);
3538                                 }
3539                         }
3540                 }
3541
3542                 if (fEncodingSupport != null)
3543                         fEncodingSupport.reset();
3544
3545                 setOutlinePageInput(fOutlinePage, input);
3546
3547                 if (fProjectionModelUpdater != null)
3548                         fProjectionModelUpdater.initialize();
3549
3550                 // if (isShowingOverrideIndicators())
3551                 // installOverrideIndicator(false);
3552         }
3553
3554         /*
3555          * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
3556          * @since 3.0
3557          */
3558         protected void setPreferenceStore(IPreferenceStore store) {
3559                 super.setPreferenceStore(store);
3560                 if (getSourceViewerConfiguration() instanceof PHPSourceViewerConfiguration) {
3561                         JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
3562                         setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools.getColorManager(), store, this,
3563                                         IPHPPartitions.PHP_PARTITIONING));
3564                 }
3565                 if (getSourceViewer() instanceof JavaSourceViewer)
3566                         ((JavaSourceViewer) getSourceViewer()).setPreferenceStore(store);
3567         }
3568
3569         /**
3570          * The <code>PHPEditor</code> implementation of this
3571          * <code>AbstractTextEditor</code> method performs any extra disposal
3572          * actions required by the php editor.
3573          */
3574         public void dispose() {
3575                 if (fProjectionModelUpdater != null) {
3576                         fProjectionModelUpdater.uninstall();
3577                         fProjectionModelUpdater = null;
3578                 }
3579
3580                 if (fProjectionSupport != null) {
3581                         fProjectionSupport.dispose();
3582                         fProjectionSupport = null;
3583                 }
3584                 // PHPEditorEnvironment.disconnect(this);
3585                 if (fOutlinePage != null)
3586                         fOutlinePage.setInput(null);
3587
3588                 if (fActionGroups != null)
3589                         fActionGroups.dispose();
3590
3591                 if (isBrowserLikeLinks())
3592                         disableBrowserLikeLinks();
3593
3594                 // cancel possible running computation
3595                 fMarkOccurrenceAnnotations = false;
3596                 uninstallOccurrencesFinder();
3597
3598                 uninstallOverrideIndicator();
3599
3600                 if (fActivationListener != null) {
3601                         PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
3602                         fActivationListener = null;
3603                 }
3604
3605                 if (fEncodingSupport != null) {
3606                         fEncodingSupport.dispose();
3607                         fEncodingSupport = null;
3608                 }
3609
3610                 if (fPropertyChangeListener != null) {
3611                         Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
3612                         preferences.removePropertyChangeListener(fPropertyChangeListener);
3613                         fPropertyChangeListener = null;
3614                 }
3615
3616                 // if (fSourceViewerDecorationSupport != null) {
3617                 // fSourceViewerDecorationSupport.dispose();
3618                 // fSourceViewerDecorationSupport = null;
3619                 // }
3620
3621                 if (fBracketMatcher != null) {
3622                         fBracketMatcher.dispose();
3623                         fBracketMatcher = null;
3624                 }
3625
3626                 if (fEditorSelectionChangedListener != null) {
3627                         fEditorSelectionChangedListener.uninstall(getSelectionProvider());
3628                         fEditorSelectionChangedListener = null;
3629                 }
3630
3631                 super.dispose();
3632         }
3633
3634         /**
3635          * The <code>PHPEditor</code> implementation of this
3636          * <code>AbstractTextEditor</code> method performs any extra revert behavior
3637          * required by the php editor.
3638          */
3639         // public void doRevertToSaved() {
3640         // super.doRevertToSaved();
3641         // if (fOutlinePage != null)
3642         // fOutlinePage.update();
3643         // }
3644         /**
3645          * The <code>PHPEditor</code> implementation of this
3646          * <code>AbstractTextEditor</code> method performs any extra save behavior
3647          * required by the php editor.
3648          */
3649         // public void doSave(IProgressMonitor monitor) {
3650         // super.doSave(monitor);
3651         // compile or not, according to the user preferences
3652         // IPreferenceStore store = getPreferenceStore();
3653         // the parse on save was changed to the eclipse "builders" concept
3654         // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
3655         // IAction a = PHPParserAction.getInstance();
3656         // if (a != null)
3657         // a.run();
3658         // }
3659         // if (SWT.getPlatform().equals("win32")) {
3660         // IAction a = ShowExternalPreviewAction.getInstance();
3661         // if (a != null)
3662         // a.run();
3663         // }
3664         // if (fOutlinePage != null)
3665         // fOutlinePage.update();
3666         // }
3667         /**
3668          * The <code>PHPEditor</code> implementation of this
3669          * <code>AbstractTextEditor</code> method performs any extra save as
3670          * behavior required by the php editor.
3671          */
3672         // public void doSaveAs() {
3673         // super.doSaveAs();
3674         // if (fOutlinePage != null)
3675         // fOutlinePage.update();
3676         // }
3677         /*
3678          * @see StatusTextEditor#getStatusHeader(IStatus)
3679          */
3680         protected String getStatusHeader(IStatus status) {
3681                 if (fEncodingSupport != null) {
3682                         String message = fEncodingSupport.getStatusHeader(status);
3683                         if (message != null)
3684                                 return message;
3685                 }
3686                 return super.getStatusHeader(status);
3687         }
3688
3689         /*
3690          * @see StatusTextEditor#getStatusBanner(IStatus)
3691          */
3692         protected String getStatusBanner(IStatus status) {
3693                 if (fEncodingSupport != null) {
3694                         String message = fEncodingSupport.getStatusBanner(status);
3695                         if (message != null)
3696                                 return message;
3697                 }
3698                 return super.getStatusBanner(status);
3699         }
3700
3701         /*
3702          * @see StatusTextEditor#getStatusMessage(IStatus)
3703          */
3704         protected String getStatusMessage(IStatus status) {
3705                 if (fEncodingSupport != null) {
3706                         String message = fEncodingSupport.getStatusMessage(status);
3707                         if (message != null)
3708                                 return message;
3709                 }
3710                 return super.getStatusMessage(status);
3711         }
3712
3713         /**
3714          * The <code>PHPEditor</code> implementation of this
3715          * <code>AbstractTextEditor</code> method performs sets the input of the
3716          * outline page after AbstractTextEditor has set input.
3717          */
3718         // protected void doSetInput(IEditorInput input) throws CoreException {
3719         // super.doSetInput(input);
3720         // if (fEncodingSupport != null)
3721         // fEncodingSupport.reset();
3722         // setOutlinePageInput(fOutlinePage, input);
3723         // }
3724         /*
3725          * @see AbstractTextEditor#doSetInput
3726          */
3727         protected void doSetInput(IEditorInput input) throws CoreException {
3728                 ISourceViewer sourceViewer = getSourceViewer();
3729                 if (!(sourceViewer instanceof ISourceViewerExtension2)) {
3730                         setPreferenceStore(createCombinedPreferenceStore(input));
3731                         internalDoSetInput(input);
3732                         return;
3733                 }
3734
3735                 // uninstall & unregister preference store listener
3736                 if (isBrowserLikeLinks())
3737                         disableBrowserLikeLinks();
3738                 getSourceViewerDecorationSupport(sourceViewer).uninstall();
3739                 ((ISourceViewerExtension2) sourceViewer).unconfigure();
3740
3741                 setPreferenceStore(createCombinedPreferenceStore(input));
3742
3743                 // install & register preference store listener
3744                 sourceViewer.configure(getSourceViewerConfiguration());
3745                 getSourceViewerDecorationSupport(sourceViewer).install(getPreferenceStore());
3746                 if (isBrowserLikeLinks())
3747                         enableBrowserLikeLinks();
3748
3749                 internalDoSetInput(input);
3750         }
3751
3752         /*
3753          * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
3754          */
3755         // public Object getViewPartInput() {
3756         // return getEditorInput().getAdapter(IFile.class);
3757         // }
3758         /**
3759          * The <code>PHPEditor</code> implementation of this
3760          * <code>AbstractTextEditor</code> method adds any PHPEditor specific
3761          * entries.
3762          */
3763         public void editorContextMenuAboutToShow(MenuManager menu) {
3764                 super.editorContextMenuAboutToShow(menu);
3765                 menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
3766                 menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
3767
3768                 ActionContext context = new ActionContext(getSelectionProvider().getSelection());
3769                 fContextMenuGroup.setContext(context);
3770                 fContextMenuGroup.fillContextMenu(menu);
3771                 fContextMenuGroup.setContext(null);
3772                 // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format");
3773                 // //$NON-NLS-1$
3774                 //
3775                 // ActionContext context =
3776                 // new ActionContext(getSelectionProvider().getSelection());
3777                 // fContextMenuGroup.setContext(context);
3778                 // fContextMenuGroup.fillContextMenu(menu);
3779                 // fContextMenuGroup.setContext(null);
3780         }
3781
3782         /**
3783          * Creates the outline page used with this editor.
3784          */
3785         protected JavaOutlinePage createOutlinePage() {
3786                 JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
3787                 fOutlineSelectionChangedListener.install(page);
3788                 setOutlinePageInput(page, getEditorInput());
3789                 return page;
3790         }
3791
3792         /**
3793          * Informs the editor that its outliner has been closed.
3794          */
3795         public void outlinePageClosed() {
3796                 if (fOutlinePage != null) {
3797                         fOutlineSelectionChangedListener.uninstall(fOutlinePage);
3798                         fOutlinePage = null;
3799                         resetHighlightRange();
3800                 }
3801         }
3802
3803         /**
3804          * Synchronizes the outliner selection with the given element position in the
3805          * editor.
3806          *
3807          * @param element
3808          *          the java element to select
3809          */
3810         protected void synchronizeOutlinePage(ISourceReference element) {
3811                 synchronizeOutlinePage(element, true);
3812         }
3813
3814         /**
3815          * Synchronizes the outliner selection with the given element position in the
3816          * editor.
3817          *
3818          * @param element
3819          *          the java element to select
3820          * @param checkIfOutlinePageActive
3821          *          <code>true</code> if check for active outline page needs to be
3822          *          done
3823          */
3824         protected void synchronizeOutlinePage(ISourceReference element, boolean checkIfOutlinePageActive) {
3825                 if (fOutlinePage != null && element != null && !(checkIfOutlinePageActive && isJavaOutlinePageActive())) {
3826                         fOutlineSelectionChangedListener.uninstall(fOutlinePage);
3827                         fOutlinePage.select(element);
3828                         fOutlineSelectionChangedListener.install(fOutlinePage);
3829                 }
3830         }
3831
3832         /**
3833          * Synchronizes the outliner selection with the actual cursor position in the
3834          * editor.
3835          */
3836         public void synchronizeOutlinePageSelection() {
3837                 synchronizeOutlinePage(computeHighlightRangeSourceReference());
3838
3839                 // ISourceViewer sourceViewer = getSourceViewer();
3840                 // if (sourceViewer == null || fOutlinePage == null)
3841                 // return;
3842                 //
3843                 // StyledText styledText = sourceViewer.getTextWidget();
3844                 // if (styledText == null)
3845                 // return;
3846                 //
3847                 // int caret = 0;
3848                 // if (sourceViewer instanceof ITextViewerExtension3) {
3849                 // ITextViewerExtension3 extension = (ITextViewerExtension3)
3850                 // sourceViewer;
3851                 // caret =
3852                 // extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
3853                 // } else {
3854                 // int offset = sourceViewer.getVisibleRegion().getOffset();
3855                 // caret = offset + styledText.getCaretOffset();
3856                 // }
3857                 //
3858                 // IJavaElement element = getElementAt(caret);
3859                 // if (element instanceof ISourceReference) {
3860                 // fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
3861                 // fOutlinePage.select((ISourceReference) element);
3862                 // fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
3863                 // }
3864         }
3865
3866         protected void setSelection(ISourceReference reference, boolean moveCursor) {
3867
3868                 ISelection selection = getSelectionProvider().getSelection();
3869                 if (selection instanceof TextSelection) {
3870                         TextSelection textSelection = (TextSelection) selection;
3871                         if (textSelection.getOffset() != 0 || textSelection.getLength() != 0)
3872                                 markInNavigationHistory();
3873                 }
3874
3875                 if (reference != null) {
3876
3877                         StyledText textWidget = null;
3878
3879                         ISourceViewer sourceViewer = getSourceViewer();
3880                         if (sourceViewer != null)
3881                                 textWidget = sourceViewer.getTextWidget();
3882
3883                         if (textWidget == null)
3884                                 return;
3885
3886                         try {
3887
3888                                 ISourceRange range = reference.getSourceRange();
3889                                 if (range == null)
3890                                         return;
3891
3892                                 int offset = range.getOffset();
3893                                 int length = range.getLength();
3894
3895                                 if (offset < 0 || length < 0)
3896                                         return;
3897
3898                                 textWidget.setRedraw(false);
3899
3900                                 setHighlightRange(offset, length, moveCursor);
3901
3902                                 if (!moveCursor)
3903                                         return;
3904
3905                                 offset = -1;
3906                                 length = -1;
3907
3908                                 if (reference instanceof IMember) {
3909                                         range = ((IMember) reference).getNameRange();
3910                                         if (range != null) {
3911                                                 offset = range.getOffset();
3912                                                 length = range.getLength();
3913                                         }
3914                                 }
3915                                 // else if (reference instanceof IImportDeclaration) {
3916                                 // String name= ((IImportDeclaration)
3917                                 // reference).getElementName();
3918                                 // if (name != null && name.length() > 0) {
3919                                 // String content= reference.getSource();
3920                                 // if (content != null) {
3921                                 // offset= range.getOffset() + content.indexOf(name);
3922                                 // length= name.length();
3923                                 // }
3924                                 // }
3925                                 // } else if (reference instanceof IPackageDeclaration) {
3926                                 // String name= ((IPackageDeclaration)
3927                                 // reference).getElementName();
3928                                 // if (name != null && name.length() > 0) {
3929                                 // String content= reference.getSource();
3930                                 // if (content != null) {
3931                                 // offset= range.getOffset() + content.indexOf(name);
3932                                 // length= name.length();
3933                                 // }
3934                                 // }
3935                                 // }
3936
3937                                 if (offset > -1 && length > 0) {
3938                                         sourceViewer.revealRange(offset, length);
3939                                         sourceViewer.setSelectedRange(offset, length);
3940                                 }
3941
3942                         } catch (JavaModelException x) {
3943                         } catch (IllegalArgumentException x) {
3944                         } finally {
3945                                 if (textWidget != null)
3946                                         textWidget.setRedraw(true);
3947                         }
3948
3949                 } else if (moveCursor) {
3950                         resetHighlightRange();
3951                 }
3952
3953                 markInNavigationHistory();
3954         }
3955
3956         public void setSelection(IJavaElement element) {
3957                 if (element == null || element instanceof ICompilationUnit) { // ||
3958                         // element
3959                         // instanceof
3960                         // IClassFile)
3961                         // {
3962                         /*
3963                          * If the element is an ICompilationUnit this unit is either the input of
3964                          * this editor or not being displayed. In both cases, nothing should
3965                          * happened. (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
3966                          */
3967                         return;
3968                 }
3969
3970                 IJavaElement corresponding = getCorrespondingElement(element);
3971                 if (corresponding instanceof ISourceReference) {
3972                         ISourceReference reference = (ISourceReference) corresponding;
3973                         // set highlight range
3974                         setSelection(reference, true);
3975                         // set outliner selection
3976                         if (fOutlinePage != null) {
3977                                 fOutlineSelectionChangedListener.uninstall(fOutlinePage);
3978                                 fOutlinePage.select(reference);
3979                                 fOutlineSelectionChangedListener.install(fOutlinePage);
3980                         }
3981                 }
3982         }
3983
3984         public synchronized void editingScriptStarted() {
3985                 ++fIgnoreOutlinePageSelection;
3986         }
3987
3988         public synchronized void editingScriptEnded() {
3989                 --fIgnoreOutlinePageSelection;
3990         }
3991
3992         public synchronized boolean isEditingScriptRunning() {
3993                 return (fIgnoreOutlinePageSelection > 0);
3994         }
3995
3996         /**
3997          * The <code>PHPEditor</code> implementation of this
3998          * <code>AbstractTextEditor</code> method performs gets the java content
3999          * outline page if request is for a an outline page.
4000          */
4001         public Object getAdapter(Class required) {
4002
4003                 if (IContentOutlinePage.class.equals(required)) {
4004                         if (fOutlinePage == null)
4005                                 fOutlinePage = createOutlinePage();
4006                         return fOutlinePage;
4007                 }
4008
4009                 if (IEncodingSupport.class.equals(required))
4010                         return fEncodingSupport;
4011
4012                 if (required == IShowInTargetList.class) {
4013                         return new IShowInTargetList() {
4014                                 public String[] getShowInTargetIds() {
4015                                         return new String[] { JavaUI.ID_PACKAGES, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
4016                                 }
4017
4018                         };
4019                 }
4020                 if (fProjectionSupport != null) {
4021                         Object adapter = fProjectionSupport.getAdapter(getSourceViewer(), required);
4022                         if (adapter != null)
4023                                 return adapter;
4024                 }
4025
4026                 return super.getAdapter(required);
4027         }
4028
4029         // public Object getAdapter(Class required) {
4030         // if (IContentOutlinePage.class.equals(required)) {
4031         // if (fOutlinePage == null) {
4032         // fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
4033         // if (getEditorInput() != null)
4034         // fOutlinePage.setInput(getEditorInput());
4035         // }
4036         // return fOutlinePage;
4037         // }
4038         //
4039         // if (IEncodingSupport.class.equals(required))
4040         // return fEncodingSupport;
4041         //
4042         // return super.getAdapter(required);
4043         // }
4044
4045         protected void doSelectionChanged(SelectionChangedEvent event) {
4046                 ISourceReference reference = null;
4047
4048                 ISelection selection = event.getSelection();
4049                 Iterator iter = ((IStructuredSelection) selection).iterator();
4050                 while (iter.hasNext()) {
4051                         Object o = iter.next();
4052                         if (o instanceof ISourceReference) {
4053                                 reference = (ISourceReference) o;
4054                                 break;
4055                         }
4056                 }
4057
4058                 if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
4059                         PHPeclipsePlugin.getActivePage().bringToTop(this);
4060
4061                 try {
4062                         editingScriptStarted();
4063                         setSelection(reference, !isActivePart());
4064                 } finally {
4065                         editingScriptEnded();
4066                 }
4067         }
4068
4069         /*
4070          * @see AbstractTextEditor#adjustHighlightRange(int, int)
4071          */
4072         protected void adjustHighlightRange(int offset, int length) {
4073
4074                 try {
4075
4076                         IJavaElement element = getElementAt(offset);
4077                         while (element instanceof ISourceReference) {
4078                                 ISourceRange range = ((ISourceReference) element).getSourceRange();
4079                                 if (offset < range.getOffset() + range.getLength() && range.getOffset() < offset + length) {
4080
4081                                         ISourceViewer viewer = getSourceViewer();
4082                                         if (viewer instanceof ITextViewerExtension5) {
4083                                                 ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
4084                                                 extension.exposeModelRange(new Region(range.getOffset(), range.getLength()));
4085                                         }
4086
4087                                         setHighlightRange(range.getOffset(), range.getLength(), true);
4088                                         if (fOutlinePage != null) {
4089                                                 fOutlineSelectionChangedListener.uninstall(fOutlinePage);
4090                                                 fOutlinePage.select((ISourceReference) element);
4091                                                 fOutlineSelectionChangedListener.install(fOutlinePage);
4092                                         }
4093
4094                                         return;
4095                                 }
4096                                 element = element.getParent();
4097                         }
4098
4099                 } catch (JavaModelException x) {
4100                         PHPeclipsePlugin.log(x.getStatus());
4101                 }
4102
4103                 ISourceViewer viewer = getSourceViewer();
4104                 if (viewer instanceof ITextViewerExtension5) {
4105                         ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
4106                         extension.exposeModelRange(new Region(offset, length));
4107                 } else {
4108                         resetHighlightRange();
4109                 }
4110
4111         }
4112
4113         protected boolean isActivePart() {
4114                 IWorkbenchWindow window = getSite().getWorkbenchWindow();
4115                 IPartService service = window.getPartService();
4116                 IWorkbenchPart part = service.getActivePart();
4117                 return part != null && part.equals(this);
4118         }
4119
4120         // public void openContextHelp() {
4121         // IDocument doc =
4122         // this.getDocumentProvider().getDocument(this.getEditorInput());
4123         // ITextSelection selection = (ITextSelection)
4124         // this.getSelectionProvider().getSelection();
4125         // int pos = selection.getOffset();
4126         // String word = getFunctionName(doc, pos);
4127         // openContextHelp(word);
4128         // }
4129         //
4130         // private void openContextHelp(String word) {
4131         // open(word);
4132         // }
4133         //
4134         // public static void open(String word) {
4135         // IHelp help = WorkbenchHelp.getHelpSupport();
4136         // if (help != null) {
4137         // IHelpResource helpResource = new PHPFunctionHelpResource(word);
4138         // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
4139         // } else {
4140         // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help
4141         // not available"), false); //$NON-NLS-1$
4142         // }
4143         // }
4144
4145         // private String getFunctionName(IDocument doc, int pos) {
4146         // Point word = PHPWordExtractor.findWord(doc, pos);
4147         // if (word != null) {
4148         // try {
4149         // return doc.get(word.x, word.y).replace('_', '-');
4150         // } catch (BadLocationException e) {
4151         // }
4152         // }
4153         // return "";
4154         // }
4155
4156         /*
4157          * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
4158          */
4159         protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
4160
4161                 try {
4162
4163                         ISourceViewer sourceViewer = getSourceViewer();
4164                         if (sourceViewer == null)
4165                                 return;
4166
4167                         String property = event.getProperty();
4168
4169                         if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
4170                                 Object value = event.getNewValue();
4171                                 if (value instanceof Integer) {
4172                                         sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
4173                                 } else if (value instanceof String) {
4174                                         try {
4175                                                 sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
4176                                         } catch (NumberFormatException e) {
4177                                                 // bug #1038071 - set default tab:
4178                                                 sourceViewer.getTextWidget().setTabs(80);
4179                                         }
4180                                 }
4181                                 return;
4182                         }
4183
4184                         // if (OVERVIEW_RULER.equals(property)) {
4185                         // if (isOverviewRulerVisible())
4186                         // showOverviewRuler();
4187                         // else
4188                         // hideOverviewRuler();
4189                         // return;
4190                         // }
4191
4192                         // if (LINE_NUMBER_RULER.equals(property)) {
4193                         // if (isLineNumberRulerVisible())
4194                         // showLineNumberRuler();
4195                         // else
4196                         // hideLineNumberRuler();
4197                         // return;
4198                         // }
4199
4200                         // if (fLineNumberRulerColumn != null
4201                         // && (LINE_NUMBER_COLOR.equals(property) ||
4202                         // PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) ||
4203                         // PREFERENCE_COLOR_BACKGROUND.equals(property))) {
4204                         //
4205                         // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
4206                         // }
4207
4208                         if (isJavaEditorHoverProperty(property))
4209                                 updateHoverBehavior();
4210
4211                         if (BROWSER_LIKE_LINKS.equals(property)) {
4212                                 if (isBrowserLikeLinks())
4213                                         enableBrowserLikeLinks();
4214                                 else
4215                                         disableBrowserLikeLinks();
4216                                 return;
4217                         }
4218
4219                         if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) {
4220                                 if (event.getNewValue() instanceof Boolean) {
4221                                         Boolean disable = (Boolean) event.getNewValue();
4222                                         enableOverwriteMode(!disable.booleanValue());
4223                                 }
4224                                 return;
4225                         }
4226
4227                         boolean newBooleanValue = false;
4228                         Object newValue = event.getNewValue();
4229                         if (newValue != null)
4230                                 newBooleanValue = Boolean.valueOf(newValue.toString()).booleanValue();
4231
4232                         if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) {
4233                                 if (newBooleanValue)
4234                                         selectionChanged();
4235                                 return;
4236                         }
4237
4238                         if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
4239                                 if (newBooleanValue != fMarkOccurrenceAnnotations) {
4240                                         fMarkOccurrenceAnnotations = newBooleanValue;
4241                                         if (!fMarkOccurrenceAnnotations)
4242                                                 uninstallOccurrencesFinder();
4243                                         else
4244                                                 installOccurrencesFinder();
4245                                 }
4246                                 return;
4247                         }
4248
4249                         if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
4250                                 fStickyOccurrenceAnnotations = newBooleanValue;
4251                                 return;
4252                         }
4253                         // }
4254                         // }
4255                         // if
4256                         // (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property))
4257                         // {
4258                         // if (event.getNewValue() instanceof Boolean) {
4259                         // boolean stickyOccurrenceAnnotations=
4260                         // ((Boolean)event.getNewValue()).booleanValue();
4261                         // if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations)
4262                         // {
4263
4264                         ((PHPSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event);
4265
4266                         // if (affectsOverrideIndicatorAnnotations(event)) {
4267                         // if (isShowingOverrideIndicators()) {
4268                         // if (fOverrideIndicatorManager == null)
4269                         // installOverrideIndicator(true);
4270                         // } else {
4271                         // if (fOverrideIndicatorManager != null)
4272                         // uninstallOverrideIndicator();
4273                         // }
4274                         // return;
4275                         // }
4276
4277                         if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
4278                                 if (sourceViewer instanceof ProjectionViewer) {
4279                                         ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer;
4280                                         if (fProjectionModelUpdater != null)
4281                                                 fProjectionModelUpdater.uninstall();
4282                                         // either freshly enabled or provider changed
4283                                         fProjectionModelUpdater = PHPeclipsePlugin.getDefault().getFoldingStructureProviderRegistry().getCurrentFoldingProvider();
4284                                         if (fProjectionModelUpdater != null) {
4285                                                 fProjectionModelUpdater.install(this, projectionViewer);
4286                                         }
4287                                 }
4288                                 return;
4289                         }
4290                 } finally {
4291                         super.handlePreferenceStoreChanged(event);
4292                 }
4293         }
4294
4295         // /*
4296         // * @see
4297         // AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
4298         // */
4299         // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
4300         //
4301         // try {
4302         //
4303         // ISourceViewer sourceViewer = getSourceViewer();
4304         // if (sourceViewer == null)
4305         // return;
4306         //
4307         // String property = event.getProperty();
4308         //
4309         // // if
4310         // (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
4311         // // Object value= event.getNewValue();
4312         // // if (value instanceof Integer) {
4313         // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
4314         // // } else if (value instanceof String) {
4315         // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String)
4316         // value));
4317         // // }
4318         // // return;
4319         // // }
4320         //
4321         // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
4322         // if (isLineNumberRulerVisible())
4323         // showLineNumberRuler();
4324         // else
4325         // hideLineNumberRuler();
4326         // return;
4327         // }
4328         //
4329         // if (fLineNumberRulerColumn != null
4330         // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
4331         // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
4332         // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
4333         //
4334         // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
4335         // }
4336         //
4337         // } finally {
4338         // super.handlePreferenceStoreChanged(event);
4339         // }
4340         // }
4341
4342         // private boolean isJavaEditorHoverProperty(String property) {
4343         // return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
4344         // || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
4345         // || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
4346         // || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
4347         // || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
4348         // || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
4349         // || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
4350         // || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
4351         // }
4352
4353         /**
4354          * Shows the line number ruler column.
4355          */
4356         // private void showLineNumberRuler() {
4357         // IVerticalRuler v = getVerticalRuler();
4358         // if (v instanceof CompositeRuler) {
4359         // CompositeRuler c = (CompositeRuler) v;
4360         // c.addDecorator(1, createLineNumberRulerColumn());
4361         // }
4362         // }
4363         private boolean isJavaEditorHoverProperty(String property) {
4364                 return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
4365         }
4366
4367         /**
4368          * Return whether the browser like links should be enabled according to the
4369          * preference store settings.
4370          *
4371          * @return <code>true</code> if the browser like links should be enabled
4372          */
4373         private boolean isBrowserLikeLinks() {
4374                 IPreferenceStore store = getPreferenceStore();
4375                 return store.getBoolean(BROWSER_LIKE_LINKS);
4376         }
4377
4378         /**
4379          * Enables browser like links.
4380          */
4381         private void enableBrowserLikeLinks() {
4382                 if (fMouseListener == null) {
4383                         fMouseListener = new MouseClickListener();
4384                         fMouseListener.install();
4385                 }
4386         }
4387
4388         /**
4389          * Disables browser like links.
4390          */
4391         private void disableBrowserLikeLinks() {
4392                 if (fMouseListener != null) {
4393                         fMouseListener.uninstall();
4394                         fMouseListener = null;
4395                 }
4396         }
4397
4398         /**
4399          * Handles a property change event describing a change of the java core's
4400          * preferences and updates the preference related editor properties.
4401          *
4402          * @param event
4403          *          the property change event
4404          */
4405         protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
4406                 if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
4407                         ISourceViewer sourceViewer = getSourceViewer();
4408                         if (sourceViewer != null
4409                                         && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event
4410                                                         .getNewValue())))
4411                                 sourceViewer.invalidateTextPresentation();
4412                 }
4413                 if (PreferenceConstants.EDITOR_WRAP_WORDS.equals(event.getProperty())) {
4414                         setWordWrap();
4415                 }
4416         }
4417
4418         /**
4419          * Return whether the line number ruler column should be visible according to
4420          * the preference store settings.
4421          *
4422          * @return <code>true</code> if the line numbers should be visible
4423          */
4424         // protected boolean isLineNumberRulerVisible() {
4425         // IPreferenceStore store = getPreferenceStore();
4426         // return store.getBoolean(LINE_NUMBER_RULER);
4427         // }
4428         /**
4429          * Hides the line number ruler column.
4430          */
4431         // private void hideLineNumberRuler() {
4432         // IVerticalRuler v = getVerticalRuler();
4433         // if (v instanceof CompositeRuler) {
4434         // CompositeRuler c = (CompositeRuler) v;
4435         // try {
4436         // c.removeDecorator(1);
4437         // } catch (Throwable e) {
4438         // }
4439         // }
4440         // }
4441         /*
4442          * @see AbstractTextEditor#handleCursorPositionChanged()
4443          */
4444         // protected void handleCursorPositionChanged() {
4445         // super.handleCursorPositionChanged();
4446         // if (!isEditingScriptRunning() && fUpdater != null)
4447         // fUpdater.post();
4448         // }
4449         /*
4450          * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced()
4451          */
4452         protected void handleElementContentReplaced() {
4453                 super.handleElementContentReplaced();
4454                 if (fProjectionModelUpdater != null)
4455                         fProjectionModelUpdater.initialize();
4456         }
4457
4458         /**
4459          * Initializes the given line number ruler column from the preference store.
4460          *
4461          * @param rulerColumn
4462          *          the ruler column to be initialized
4463          */
4464         // protected void initializeLineNumberRulerColumn(LineNumberRulerColumn
4465         // rulerColumn) {
4466         // JavaTextTools textTools =
4467         // PHPeclipsePlugin.getDefault().getJavaTextTools();
4468         // IColorManager manager = textTools.getColorManager();
4469         //
4470         // IPreferenceStore store = getPreferenceStore();
4471         // if (store != null) {
4472         //
4473         // RGB rgb = null;
4474         // // foreground color
4475         // if (store.contains(LINE_NUMBER_COLOR)) {
4476         // if (store.isDefault(LINE_NUMBER_COLOR))
4477         // rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
4478         // else
4479         // rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
4480         // }
4481         // rulerColumn.setForeground(manager.getColor(rgb));
4482         //
4483         // rgb = null;
4484         // // background color
4485         // if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
4486         // if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
4487         // if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
4488         // rgb = PreferenceConverter.getDefaultColor(store,
4489         // PREFERENCE_COLOR_BACKGROUND);
4490         // else
4491         // rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
4492         // }
4493         // }
4494         // rulerColumn.setBackground(manager.getColor(rgb));
4495         // }
4496         // }
4497         /**
4498          * Creates a new line number ruler column that is appropriately initialized.
4499          */
4500         // protected IVerticalRulerColumn createLineNumberRulerColumn() {
4501         // fLineNumberRulerColumn = new LineNumberRulerColumn();
4502         // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
4503         // return fLineNumberRulerColumn;
4504         // }
4505         /*
4506          * @see AbstractTextEditor#createVerticalRuler()
4507          */
4508         // protected IVerticalRuler createVerticalRuler() {
4509         // CompositeRuler ruler = new CompositeRuler();
4510         // ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
4511         // if (isLineNumberRulerVisible())
4512         // ruler.addDecorator(1, createLineNumberRulerColumn());
4513         // return ruler;
4514         // }
4515         // private static IRegion getSignedSelection(ITextViewer viewer) {
4516         //
4517         // StyledText text = viewer.getTextWidget();
4518         // int caretOffset = text.getCaretOffset();
4519         // Point selection = text.getSelection();
4520         //
4521         // // caret left
4522         // int offset, length;
4523         // if (caretOffset == selection.x) {
4524         // offset = selection.y;
4525         // length = selection.x - selection.y;
4526         //
4527         // // caret right
4528         // } else {
4529         // offset = selection.x;
4530         // length = selection.y - selection.x;
4531         // }
4532         //
4533         // return new Region(offset, length);
4534         // }
4535         protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
4536                 StyledText text = sourceViewer.getTextWidget();
4537                 Point selection = text.getSelectionRange();
4538
4539                 if (text.getCaretOffset() == selection.x) {
4540                         selection.x = selection.x + selection.y;
4541                         selection.y = -selection.y;
4542                 }
4543
4544                 selection.x = widgetOffset2ModelOffset(sourceViewer, selection.x);
4545
4546                 return new Region(selection.x, selection.y);
4547         }
4548
4549         /** Preference key for matching brackets */
4550         protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
4551
4552         /** Preference key for matching brackets color */
4553         protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
4554
4555         /** Preference key for highlighting current line */
4556         // protected final static String CURRENT_LINE =
4557         // PreferenceConstants.EDITOR_CURRENT_LINE;
4558         /** Preference key for highlight color of current line */
4559         // protected final static String CURRENT_LINE_COLOR =
4560         // PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
4561         /** Preference key for showing print marging ruler */
4562         // protected final static String PRINT_MARGIN =
4563         // PreferenceConstants.EDITOR_PRINT_MARGIN;
4564         /** Preference key for print margin ruler color */
4565         // protected final static String PRINT_MARGIN_COLOR =
4566         // PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
4567         /** Preference key for print margin ruler column */
4568         // protected final static String PRINT_MARGIN_COLUMN =
4569         // PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
4570         /** Preference key for error indication */
4571         // protected final static String ERROR_INDICATION =
4572         // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
4573         /** Preference key for error color */
4574         // protected final static String ERROR_INDICATION_COLOR =
4575         // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
4576         /** Preference key for warning indication */
4577         // protected final static String WARNING_INDICATION =
4578         // PreferenceConstants.EDITOR_WARNING_INDICATION;
4579         /** Preference key for warning color */
4580         // protected final static String WARNING_INDICATION_COLOR =
4581         // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
4582         /** Preference key for task indication */
4583         protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
4584
4585         /** Preference key for task color */
4586         protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
4587
4588         /** Preference key for bookmark indication */
4589         protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
4590
4591         /** Preference key for bookmark color */
4592         protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
4593
4594         /** Preference key for search result indication */
4595         protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
4596
4597         /** Preference key for search result color */
4598         protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
4599
4600         /** Preference key for unknown annotation indication */
4601         protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
4602
4603         /** Preference key for unknown annotation color */
4604         protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
4605
4606         /** Preference key for shwoing the overview ruler */
4607         protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
4608
4609         /** Preference key for error indication in overview ruler */
4610         protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
4611
4612         /** Preference key for warning indication in overview ruler */
4613         protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
4614
4615         /** Preference key for task indication in overview ruler */
4616         protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
4617
4618         /** Preference key for bookmark indication in overview ruler */
4619         protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
4620
4621         /** Preference key for search result indication in overview ruler */
4622         protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
4623
4624         /** Preference key for unknown annotation indication in overview ruler */
4625         protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
4626
4627         // /** Preference key for compiler task tags */
4628         // private final static String COMPILER_TASK_TAGS=
4629         // JavaCore.COMPILER_TASK_TAGS;
4630         /** Preference key for browser like links */
4631         private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
4632
4633         /** Preference key for key modifier of browser like links */
4634         private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
4635
4636         /**
4637          * Preference key for key modifier mask of browser like links. The value is
4638          * only used if the value of <code>EDITOR_BROWSER_LIKE_LINKS</code> cannot
4639          * be resolved to valid SWT modifier bits.
4640          *
4641          * @since 2.1.1
4642          */
4643         private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
4644
4645         private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
4646
4647         private static boolean isBracket(char character) {
4648                 for (int i = 0; i != BRACKETS.length; ++i)
4649                         if (character == BRACKETS[i])
4650                                 return true;
4651                 return false;
4652         }
4653
4654         private static boolean isSurroundedByBrackets(IDocument document, int offset) {
4655                 if (offset == 0 || offset == document.getLength())
4656                         return false;
4657
4658                 try {
4659                         return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
4660
4661                 } catch (BadLocationException e) {
4662                         return false;
4663                 }
4664         }
4665
4666         // protected void configureSourceViewerDecorationSupport() {
4667         //
4668         // fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
4669         //
4670         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4671         // AnnotationType.UNKNOWN,
4672         // UNKNOWN_INDICATION_COLOR,
4673         // UNKNOWN_INDICATION,
4674         // UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
4675         // 0);
4676         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4677         // AnnotationType.BOOKMARK,
4678         // BOOKMARK_INDICATION_COLOR,
4679         // BOOKMARK_INDICATION,
4680         // BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
4681         // 1);
4682         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4683         // AnnotationType.TASK,
4684         // TASK_INDICATION_COLOR,
4685         // TASK_INDICATION,
4686         // TASK_INDICATION_IN_OVERVIEW_RULER,
4687         // 2);
4688         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4689         // AnnotationType.SEARCH,
4690         // SEARCH_RESULT_INDICATION_COLOR,
4691         // SEARCH_RESULT_INDICATION,
4692         // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
4693         // 3);
4694         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4695         // AnnotationType.WARNING,
4696         // WARNING_INDICATION_COLOR,
4697         // WARNING_INDICATION,
4698         // WARNING_INDICATION_IN_OVERVIEW_RULER,
4699         // 4);
4700         // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
4701         // AnnotationType.ERROR,
4702         // ERROR_INDICATION_COLOR,
4703         // ERROR_INDICATION,
4704         // ERROR_INDICATION_IN_OVERVIEW_RULER,
4705         // 5);
4706         //
4707         // fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE,
4708         // CURRENT_LINE_COLOR);
4709         // fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN,
4710         // PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
4711         // fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
4712         // MATCHING_BRACKETS_COLOR);
4713         //
4714         // fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
4715         //
4716         // }
4717         /**
4718          * Returns the Java element wrapped by this editors input.
4719          *
4720          * @return the Java element wrapped by this editors input.
4721          * @since 3.0
4722          */
4723         abstract protected IJavaElement getInputJavaElement();
4724
4725         protected void updateStatusLine() {
4726                 ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection();
4727                 Annotation annotation = getAnnotation(selection.getOffset(), selection.getLength());
4728                 setStatusLineErrorMessage(null);
4729                 setStatusLineMessage(null);
4730                 if (annotation != null) {
4731                         try {
4732                                 fIsUpdatingAnnotationViews = true;
4733                                 updateAnnotationViews(annotation);
4734                         } finally {
4735                                 fIsUpdatingAnnotationViews = false;
4736                         }
4737                         if (annotation instanceof IJavaAnnotation && ((IJavaAnnotation) annotation).isProblem())
4738                                 setStatusLineMessage(annotation.getText());
4739                 }
4740         }
4741
4742         /**
4743          * Jumps to the matching bracket.
4744          */
4745         public void gotoMatchingBracket() {
4746
4747                 ISourceViewer sourceViewer = getSourceViewer();
4748                 IDocument document = sourceViewer.getDocument();
4749                 if (document == null)
4750                         return;
4751
4752                 IRegion selection = getSignedSelection(sourceViewer);
4753
4754                 int selectionLength = Math.abs(selection.getLength());
4755                 if (selectionLength > 1) {
4756                         setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
4757                         sourceViewer.getTextWidget().getDisplay().beep();
4758                         return;
4759                 }
4760
4761                 // #26314
4762                 int sourceCaretOffset = selection.getOffset() + selection.getLength();
4763                 if (isSurroundedByBrackets(document, sourceCaretOffset))
4764                         sourceCaretOffset -= selection.getLength();
4765
4766                 IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
4767                 if (region == null) {
4768                         setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
4769                         sourceViewer.getTextWidget().getDisplay().beep();
4770                         return;
4771                 }
4772
4773                 int offset = region.getOffset();
4774                 int length = region.getLength();
4775
4776                 if (length < 1)
4777                         return;
4778
4779                 int anchor = fBracketMatcher.getAnchor();
4780                 int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
4781
4782                 boolean visible = false;
4783                 if (sourceViewer instanceof ITextViewerExtension5) {
4784                         ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
4785                         visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
4786                 } else {
4787                         IRegion visibleRegion = sourceViewer.getVisibleRegion();
4788                         visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
4789                 }
4790
4791                 if (!visible) {
4792                         setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
4793                         sourceViewer.getTextWidget().getDisplay().beep();
4794                         return;
4795                 }
4796
4797                 if (selection.getLength() < 0)
4798                         targetOffset -= selection.getLength();
4799
4800                 sourceViewer.setSelectedRange(targetOffset, selection.getLength());
4801                 sourceViewer.revealRange(targetOffset, selection.getLength());
4802         }
4803
4804         /**
4805          * Ses the given message as error message to this editor's status line.
4806          *
4807          * @param msg
4808          *          message to be set
4809          */
4810         protected void setStatusLineErrorMessage(String msg) {
4811                 IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
4812                 if (statusLine != null)
4813                         statusLine.setMessage(true, msg, null);
4814         }
4815
4816         /**
4817          * Sets the given message as message to this editor's status line.
4818          *
4819          * @param msg
4820          *          message to be set
4821          * @since 3.0
4822          */
4823         protected void setStatusLineMessage(String msg) {
4824                 IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
4825                 if (statusLine != null)
4826                         statusLine.setMessage(false, msg, null);
4827         }
4828
4829         /**
4830          * Returns the annotation closest to the given range respecting the given
4831          * direction. If an annotation is found, the annotations current position is
4832          * copied into the provided annotation position.
4833          *
4834          * @param offset
4835          *          the region offset
4836          * @param length
4837          *          the region length
4838          * @param forward
4839          *          <code>true</code> for forwards, <code>false</code> for
4840          *          backward
4841          * @param annotationPosition
4842          *          the position of the found annotation
4843          * @return the found annotation
4844          */
4845         private Annotation getNextAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) {
4846
4847                 Annotation nextAnnotation = null;
4848                 Position nextAnnotationPosition = null;
4849                 Annotation containingAnnotation = null;
4850                 Position containingAnnotationPosition = null;
4851                 boolean currentAnnotation = false;
4852
4853                 IDocument document = getDocumentProvider().getDocument(getEditorInput());
4854                 int endOfDocument = document.getLength();
4855                 int distance = Integer.MAX_VALUE;
4856
4857                 IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
4858                 Iterator e = new JavaAnnotationIterator(model, true, true);
4859                 while (e.hasNext()) {
4860                         Annotation a = (Annotation) e.next();
4861                         if ((a instanceof IJavaAnnotation) && ((IJavaAnnotation) a).hasOverlay() || !isNavigationTarget(a))
4862                                 continue;
4863
4864                         Position p = model.getPosition(a);
4865                         if (p == null)
4866                                 continue;
4867
4868                         if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// ||
4869                                 // p.includes(offset))
4870                                 // {
4871                                 if (containingAnnotation == null
4872                                                 || (forward && p.length >= containingAnnotationPosition.length || !forward
4873                                                                 && p.length >= containingAnnotationPosition.length)) {
4874                                         containingAnnotation = a;
4875                                         containingAnnotationPosition = p;
4876                                         currentAnnotation = p.length == length;
4877                                 }
4878                         } else {
4879                                 int currentDistance = 0;
4880
4881                                 if (forward) {
4882                                         currentDistance = p.getOffset() - offset;
4883                                         if (currentDistance < 0)
4884                                                 currentDistance = endOfDocument + currentDistance;
4885
4886                                         if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
4887                                                 distance = currentDistance;
4888                                                 nextAnnotation = a;
4889                                                 nextAnnotationPosition = p;
4890                                         }
4891                                 } else {
4892                                         currentDistance = offset + length - (p.getOffset() + p.length);
4893                                         if (currentDistance < 0)
4894                                                 currentDistance = endOfDocument + currentDistance;
4895
4896                                         if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) {
4897                                                 distance = currentDistance;
4898                                                 nextAnnotation = a;
4899                                                 nextAnnotationPosition = p;
4900                                         }
4901                                 }
4902                         }
4903                 }
4904                 if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) {
4905                         annotationPosition.setOffset(containingAnnotationPosition.getOffset());
4906                         annotationPosition.setLength(containingAnnotationPosition.getLength());
4907                         return containingAnnotation;
4908                 }
4909                 if (nextAnnotationPosition != null) {
4910                         annotationPosition.setOffset(nextAnnotationPosition.getOffset());
4911                         annotationPosition.setLength(nextAnnotationPosition.getLength());
4912                 }
4913
4914                 return nextAnnotation;
4915         }
4916
4917         /**
4918          * Returns the annotation overlapping with the given range or
4919          * <code>null</code>.
4920          *
4921          * @param offset
4922          *          the region offset
4923          * @param length
4924          *          the region length
4925          * @return the found annotation or <code>null</code>
4926          * @since 3.0
4927          */
4928         private Annotation getAnnotation(int offset, int length) {
4929                 IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
4930                 Iterator e = new JavaAnnotationIterator(model, true, true);
4931                 while (e.hasNext()) {
4932                         Annotation a = (Annotation) e.next();
4933                         if (!isNavigationTarget(a))
4934                                 continue;
4935
4936                         Position p = model.getPosition(a);
4937                         if (p != null && p.overlapsWith(offset, length))
4938                                 return a;
4939                 }
4940
4941                 return null;
4942         }
4943
4944         /**
4945          * Returns whether the given annotation is configured as a target for the "Go
4946          * to Next/Previous Annotation" actions
4947          *
4948          * @param annotation
4949          *          the annotation
4950          * @return <code>true</code> if this is a target, <code>false</code>
4951          *         otherwise
4952          * @since 3.0
4953          */
4954         protected boolean isNavigationTarget(Annotation annotation) {
4955                 Preferences preferences = EditorsUI.getPluginPreferences();
4956                 AnnotationPreference preference = getAnnotationPreferenceLookup().getAnnotationPreference(annotation);
4957                 // See bug 41689
4958                 // String key= forward ? preference.getIsGoToNextNavigationTargetKey() :
4959                 // preference.getIsGoToPreviousNavigationTargetKey();
4960                 String key = preference == null ? null : preference.getIsGoToNextNavigationTargetKey();
4961                 return (key != null && preferences.getBoolean(key));
4962         }
4963
4964         /**
4965          * Returns a segmentation of the line of the given document appropriate for
4966          * bidi rendering. The default implementation returns only the string literals
4967          * of a php code line as segments.
4968          *
4969          * @param document
4970          *          the document
4971          * @param lineOffset
4972          *          the offset of the line
4973          * @return the line's bidi segmentation
4974          * @throws BadLocationException
4975          *           in case lineOffset is not valid in document
4976          */
4977         public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException {
4978
4979                 IRegion line = document.getLineInformationOfOffset(lineOffset);
4980                 ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength());
4981
4982                 List segmentation = new ArrayList();
4983                 for (int i = 0; i < linePartitioning.length; i++) {
4984                         if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i].getType())) {
4985                                 segmentation.add(linePartitioning[i]);
4986                         } else if (IPHPPartitions.PHP_STRING_HEREDOC.equals(linePartitioning[i].getType())) {
4987                                 segmentation.add(linePartitioning[i]);
4988                         }
4989                 }
4990
4991                 if (segmentation.size() == 0)
4992                         return null;
4993
4994                 int size = segmentation.size();
4995                 int[] segments = new int[size * 2 + 1];
4996
4997                 int j = 0;
4998                 for (int i = 0; i < size; i++) {
4999                         ITypedRegion segment = (ITypedRegion) segmentation.get(i);
5000
5001                         if (i == 0)
5002                                 segments[j++] = 0;
5003
5004                         int offset = segment.getOffset() - lineOffset;
5005                         if (offset > segments[j - 1])
5006                                 segments[j++] = offset;
5007
5008                         if (offset + segment.getLength() >= line.getLength())
5009                                 break;
5010
5011                         segments[j++] = offset + segment.getLength();
5012                 }
5013
5014                 if (j < segments.length) {
5015                         int[] result = new int[j];
5016                         System.arraycopy(segments, 0, result, 0, j);
5017                         segments = result;
5018                 }
5019
5020                 return segments;
5021         }
5022
5023         /**
5024          * Returns a segmentation of the given line appropriate for bidi rendering.
5025          * The default implementation returns only the string literals of a php code
5026          * line as segments.
5027          *
5028          * @param lineOffset
5029          *          the offset of the line
5030          * @param line
5031          *          the content of the line
5032          * @return the line's bidi segmentation
5033          */
5034         protected int[] getBidiLineSegments(int lineOffset, String line) {
5035                 IDocumentProvider provider = getDocumentProvider();
5036                 if (provider != null && line != null && line.length() > 0) {
5037                         IDocument document = provider.getDocument(getEditorInput());
5038                         if (document != null)
5039                                 try {
5040                                         return getBidiLineSegments(document, lineOffset);
5041                                 } catch (BadLocationException x) {
5042                                         // ignore
5043                                 }
5044                 }
5045                 return null;
5046         }
5047
5048         /*
5049          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
5050          */
5051         // protected final ISourceViewer createSourceViewer(
5052         // Composite parent,
5053         // IVerticalRuler ruler,
5054         // int styles) {
5055         // ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
5056         // StyledText text = viewer.getTextWidget();
5057         // text.addBidiSegmentListener(new BidiSegmentListener() {
5058         // public void lineGetSegments(BidiSegmentEvent event) {
5059         // event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
5060         // }
5061         // });
5062         // // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
5063         // return viewer;
5064         // }
5065         public final ISourceViewer getViewer() {
5066                 return getSourceViewer();
5067         }
5068
5069         // protected void showOverviewRuler() {
5070         // if (fOverviewRuler != null) {
5071         // if (getSourceViewer() instanceof ISourceViewerExtension) {
5072         // ((ISourceViewerExtension)
5073         // getSourceViewer()).showAnnotationsOverview(true);
5074         // fSourceViewerDecorationSupport.updateOverviewDecorations();
5075         // }
5076         // }
5077         // }
5078         //
5079         // protected void hideOverviewRuler() {
5080         // if (getSourceViewer() instanceof ISourceViewerExtension) {
5081         // fSourceViewerDecorationSupport.hideAnnotationOverview();
5082         // ((ISourceViewerExtension)
5083         // getSourceViewer()).showAnnotationsOverview(false);
5084         // }
5085         // }
5086
5087         // protected boolean isOverviewRulerVisible() {
5088         // IPreferenceStore store = getPreferenceStore();
5089         // return store.getBoolean(OVERVIEW_RULER);
5090         // }
5091         /*
5092          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
5093          */
5094         // protected ISourceViewer createJavaSourceViewer(
5095         // Composite parent,
5096         // IVerticalRuler ruler,
5097         // IOverviewRuler overviewRuler,
5098         // boolean isOverviewRulerVisible,
5099         // int styles) {
5100         // return new SourceViewer(parent, ruler, overviewRuler,
5101         // isOverviewRulerVisible(), styles);
5102         // }
5103         /*
5104          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
5105          */
5106         protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
5107                         boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
5108                 return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles, store);
5109         }
5110
5111         /*
5112          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
5113          */
5114         protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
5115
5116                 ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles,
5117                                 getPreferenceStore());
5118
5119                 StyledText text = viewer.getTextWidget();
5120                 text.addBidiSegmentListener(new BidiSegmentListener() {
5121                         public void lineGetSegments(BidiSegmentEvent event) {
5122                                 event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
5123                         }
5124                 });
5125
5126                 // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
5127
5128                 // ensure source viewer decoration support has been created and
5129                 // configured
5130                 getSourceViewerDecorationSupport(viewer);
5131
5132                 return viewer;
5133         }
5134
5135         /*
5136          * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
5137          */
5138         protected boolean affectsTextPresentation(PropertyChangeEvent event) {
5139                 return ((PHPSourceViewerConfiguration) getSourceViewerConfiguration()).affectsTextPresentation(event)
5140                                 || super.affectsTextPresentation(event);
5141         }
5142
5143         //
5144         // protected boolean affectsTextPresentation(PropertyChangeEvent event) {
5145         // JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
5146         // return textTools.affectsBehavior(event);
5147         // }
5148         /**
5149          * Creates and returns the preference store for this Java editor with the
5150          * given input.
5151          *
5152          * @param input
5153          *          The editor input for which to create the preference store
5154          * @return the preference store for this editor
5155          *
5156          * @since 3.0
5157          */
5158         private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
5159                 List stores = new ArrayList(3);
5160
5161                 IJavaProject project = EditorUtility.getJavaProject(input);
5162                 if (project != null)
5163                         stores.add(new OptionsAdapter(project.getOptions(false), PHPeclipsePlugin.getDefault().getMockupPreferenceStore(),
5164                                         new OptionsAdapter.IPropertyChangeEventFilter() {
5165
5166                                                 public boolean isFiltered(PropertyChangeEvent event) {
5167                                                         IJavaElement inputJavaElement = getInputJavaElement();
5168                                                         IJavaProject javaProject = inputJavaElement != null ? inputJavaElement.getJavaProject() : null;
5169                                                         if (javaProject == null)
5170                                                                 return true;
5171
5172                                                         return !javaProject.getProject().equals(event.getSource());
5173                                                 }
5174
5175                                         }));
5176
5177                 stores.add(PHPeclipsePlugin.getDefault().getPreferenceStore());
5178                 stores.add(new PreferencesAdapter(JavaCore.getPlugin().getPluginPreferences()));
5179                 stores.add(EditorsUI.getPreferenceStore());
5180
5181                 return new ChainedPreferenceStore((IPreferenceStore[]) stores.toArray(new IPreferenceStore[stores.size()]));
5182         }
5183
5184         /**
5185          * Jumps to the error next according to the given direction.
5186          */
5187         public void gotoError(boolean forward) {
5188
5189                 ISelectionProvider provider = getSelectionProvider();
5190
5191                 ITextSelection s = (ITextSelection) provider.getSelection();
5192                 Position errorPosition = new Position(0, 0);
5193                 IJavaAnnotation nextError = getNextError(s.getOffset(), forward, errorPosition);
5194
5195                 if (nextError != null) {
5196
5197                         IMarker marker = null;
5198                         if (nextError instanceof MarkerAnnotation)
5199                                 marker = ((MarkerAnnotation) nextError).getMarker();
5200                         else {
5201                                 Iterator e = nextError.getOverlaidIterator();
5202                                 if (e != null) {
5203                                         while (e.hasNext()) {
5204                                                 Object o = e.next();
5205                                                 if (o instanceof MarkerAnnotation) {
5206                                                         marker = ((MarkerAnnotation) o).getMarker();
5207                                                         break;
5208                                                 }
5209                                         }
5210                                 }
5211                         }
5212
5213                         if (marker != null) {
5214                                 IWorkbenchPage page = getSite().getPage();
5215                                 IViewPart view = view = page.findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
5216                                 if (view instanceof TaskList) {
5217                                         StructuredSelection ss = new StructuredSelection(marker);
5218                                         ((TaskList) view).setSelection(ss, true);
5219                                 }
5220                         }
5221
5222                         selectAndReveal(errorPosition.getOffset(), errorPosition.getLength());
5223                         // setStatusLineErrorMessage(nextError.getMessage());
5224
5225                 } else {
5226
5227                         setStatusLineErrorMessage(null);
5228
5229                 }
5230         }
5231
5232         private IJavaAnnotation getNextError(int offset, boolean forward, Position errorPosition) {
5233
5234                 IJavaAnnotation nextError = null;
5235                 Position nextErrorPosition = null;
5236
5237                 IDocument document = getDocumentProvider().getDocument(getEditorInput());
5238                 int endOfDocument = document.getLength();
5239                 int distance = 0;
5240
5241                 IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
5242                 Iterator e = new JavaAnnotationIterator(model, false);
5243                 while (e.hasNext()) {
5244
5245                         IJavaAnnotation a = (IJavaAnnotation) e.next();
5246                         if (a.hasOverlay() || !a.isProblem())
5247                                 continue;
5248
5249                         Position p = model.getPosition((Annotation) a);
5250                         if (!p.includes(offset)) {
5251
5252                                 int currentDistance = 0;
5253
5254                                 if (forward) {
5255                                         currentDistance = p.getOffset() - offset;
5256                                         if (currentDistance < 0)
5257                                                 currentDistance = endOfDocument - offset + p.getOffset();
5258                                 } else {
5259                                         currentDistance = offset - p.getOffset();
5260                                         if (currentDistance < 0)
5261                                                 currentDistance = offset + endOfDocument - p.getOffset();
5262                                 }
5263
5264                                 if (nextError == null || currentDistance < distance) {
5265                                         distance = currentDistance;
5266                                         nextError = a;
5267                                         nextErrorPosition = p;
5268                                 }
5269                         }
5270                 }
5271
5272                 if (nextErrorPosition != null) {
5273                         errorPosition.setOffset(nextErrorPosition.getOffset());
5274                         errorPosition.setLength(nextErrorPosition.getLength());
5275                 }
5276
5277                 return nextError;
5278         }
5279
5280         protected void uninstallOverrideIndicator() {
5281                 // if (fOverrideIndicatorManager != null) {
5282                 // fOverrideIndicatorManager.removeAnnotations();
5283                 // fOverrideIndicatorManager= null;
5284                 // }
5285         }
5286
5287         protected void installOverrideIndicator(boolean waitForReconcilation) {
5288                 uninstallOverrideIndicator();
5289                 IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
5290                 final IJavaElement inputElement = getInputJavaElement();
5291
5292                 if (model == null || inputElement == null)
5293                         return;
5294
5295                 // fOverrideIndicatorManager= new OverrideIndicatorManager(model,
5296                 // inputElement, null);
5297                 //
5298                 // if (provideAST) {
5299                 // Job job= new
5300                 // Job(JavaEditorMessages.getString("OverrideIndicatorManager.intallJob")) {
5301                 // //$NON-NLS-1$
5302                 // /*
5303                 // * @see
5304                 // org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
5305                 // * @since 3.0
5306                 // */
5307                 // protected IStatus run(IProgressMonitor monitor) {
5308                 // CompilationUnit ast=
5309                 // JavaPlugin.getDefault().getASTProvider().getAST(inputElement, true,
5310                 // null);
5311                 // if (fOverrideIndicatorManager != null) // editor might have been closed
5312                 // in the meanwhile
5313                 // fOverrideIndicatorManager.reconciled(ast, true, monitor);
5314                 // return Status.OK_STATUS;
5315                 // }
5316                 // };
5317                 // job.setPriority(Job.DECORATE);
5318                 // job.setSystem(true);
5319                 // job.schedule();
5320                 // }
5321         }
5322
5323         /**
5324          * Tells whether override indicators are shown.
5325          *
5326          * @return <code>true</code> if the override indicators are shown
5327          * @since 3.0
5328          */
5329         // protected boolean isShowingOverrideIndicators() {
5330         // AnnotationPreference preference=
5331         // getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
5332         // IPreferenceStore store= getPreferenceStore();
5333         // return getBoolean(store, preference.getHighlightPreferenceKey())
5334         // || getBoolean(store, preference.getVerticalRulerPreferenceKey())
5335         // || getBoolean(store, preference.getOverviewRulerPreferenceKey())
5336         // || getBoolean(store, preference.getTextPreferenceKey());
5337         // }
5338         /**
5339          * Returns the boolean preference for the given key.
5340          *
5341          * @param store
5342          *          the preference store
5343          * @param key
5344          *          the preference key
5345          * @return <code>true</code> if the key exists in the store and its value is
5346          *         <code>true</code>
5347          * @since 3.0
5348          */
5349         private boolean getBoolean(IPreferenceStore store, String key) {
5350                 return key != null && store.getBoolean(key);
5351         }
5352
5353         protected boolean isPrefQuickDiffAlwaysOn() {
5354                 return false; // never show change ruler for the non-editable java editor.
5355                 // Overridden in subclasses like PHPUnitEditor
5356         }
5357
5358         /*
5359          * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions()
5360          */
5361         protected void createNavigationActions() {
5362                 super.createNavigationActions();
5363
5364                 final StyledText textWidget = getSourceViewer().getTextWidget();
5365
5366                 IAction action = new SmartLineStartAction(textWidget, false);
5367                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
5368                 setAction(ITextEditorActionDefinitionIds.LINE_START, action);
5369
5370                 action = new SmartLineStartAction(textWidget, true);
5371                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
5372                 setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action);
5373
5374                 action = new NavigatePreviousSubWordAction();
5375                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS);
5376                 setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action);
5377                 textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL);
5378
5379                 action = new NavigateNextSubWordAction();
5380                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT);
5381                 setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action);
5382                 textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL);
5383
5384                 action = new SelectPreviousSubWordAction();
5385                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS);
5386                 setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action);
5387                 textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT, SWT.NULL);
5388
5389                 action = new SelectNextSubWordAction();
5390                 action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT);
5391                 setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action);
5392                 textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT, SWT.NULL);
5393         }
5394
5395         /*
5396          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createCompositeRuler()
5397          */
5398 //      protected CompositeRuler createCompositeRuler() {
5399 //              if (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
5400 //                      return super.createCompositeRuler();
5401 //
5402 //              CompositeRuler ruler = new CompositeRuler();
5403 //              AnnotationRulerColumn column = new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
5404 //              column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new IDoubleClickListener() {
5405 //
5406 //                      public void doubleClick(DoubleClickEvent event) {
5407 //                              // for now: just invoke ruler double click action
5408 //                              triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
5409 //                      }
5410 //
5411 //                      private void triggerAction(String actionID) {
5412 //                              IAction action = getAction(actionID);
5413 //                              if (action != null) {
5414 //                                      if (action instanceof IUpdate)
5415 //                                              ((IUpdate) action).update();
5416 //                                      // hack to propagate line change
5417 //                                      if (action instanceof ISelectionListener) {
5418 //                                              ((ISelectionListener) action).selectionChanged(null, null);
5419 //                                      }
5420 //                                      if (action.isEnabled())
5421 //                                              action.run();
5422 //                              }
5423 //                      }
5424 //
5425 //              }));
5426 //              ruler.addDecorator(0, column);
5427 //
5428 //              if (isLineNumberRulerVisible())
5429 //                      ruler.addDecorator(1, createLineNumberRulerColumn());
5430 //              else if (isPrefQuickDiffAlwaysOn())
5431 //                      ruler.addDecorator(1, createChangeRulerColumn());
5432 //
5433 //              return ruler;
5434 //      }
5435
5436         /*
5437          * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createAnnotationRulerColumn(org.eclipse.jface.text.source.CompositeRuler)
5438          * @since 3.2
5439          */
5440         protected IVerticalRulerColumn createAnnotationRulerColumn(CompositeRuler ruler) {
5441                 if (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
5442                         return super.createAnnotationRulerColumn(ruler);
5443
5444                 AnnotationRulerColumn column= new AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
5445                 column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new IDoubleClickListener() {
5446
5447                         public void doubleClick(DoubleClickEvent event) {
5448                                 // for now: just invoke ruler double click action
5449                                 triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
5450                         }
5451
5452                         private void triggerAction(String actionID) {
5453                                 IAction action= getAction(actionID);
5454                                 if (action != null) {
5455                                         if (action instanceof IUpdate)
5456                                                 ((IUpdate) action).update();
5457                                         // hack to propagate line change
5458                                         if (action instanceof ISelectionListener) {
5459                                                 ((ISelectionListener)action).selectionChanged(null, null);
5460                                         }
5461                                         if (action.isEnabled())
5462                                                 action.run();
5463                                 }
5464                         }
5465
5466                 }));
5467                 
5468                 return column;
5469         }
5470         /**
5471          * Returns the folding action group, or <code>null</code> if there is none.
5472          *
5473          * @return the folding action group, or <code>null</code> if there is none
5474          * @since 3.0
5475          */
5476         protected FoldingActionGroup getFoldingActionGroup() {
5477                 return fFoldingGroup;
5478         }
5479
5480         /*
5481          * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert()
5482          */
5483         protected void performRevert() {
5484                 ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
5485                 projectionViewer.setRedraw(false);
5486                 try {
5487
5488                         boolean projectionMode = projectionViewer.isProjectionMode();
5489                         if (projectionMode) {
5490                                 projectionViewer.disableProjection();
5491                                 if (fProjectionModelUpdater != null)
5492                                         fProjectionModelUpdater.uninstall();
5493                         }
5494
5495                         super.performRevert();
5496
5497                         if (projectionMode) {
5498                                 if (fProjectionModelUpdater != null)
5499                                         fProjectionModelUpdater.install(this, projectionViewer);
5500                                 projectionViewer.enableProjection();
5501                         }
5502
5503                 } finally {
5504                         projectionViewer.setRedraw(true);
5505                 }
5506         }
5507
5508         /**
5509          * React to changed selection.
5510          *
5511          * @since 3.0
5512          */
5513         protected void selectionChanged() {
5514                 if (getSelectionProvider() == null)
5515                         return;
5516                 ISourceReference element = computeHighlightRangeSourceReference();
5517                 if (getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
5518                         synchronizeOutlinePage(element);
5519                 setSelection(element, false);
5520                 updateStatusLine();
5521         }
5522
5523         private boolean isJavaOutlinePageActive() {
5524                 IWorkbenchPart part = getActivePart();
5525                 return part instanceof ContentOutline && ((ContentOutline) part).getCurrentPage() == fOutlinePage;
5526         }
5527
5528         private IWorkbenchPart getActivePart() {
5529                 IWorkbenchWindow window = getSite().getWorkbenchWindow();
5530                 IPartService service = window.getPartService();
5531                 IWorkbenchPart part = service.getActivePart();
5532                 return part;
5533         }
5534
5535         /**
5536          * Computes and returns the source reference that includes the caret and
5537          * serves as provider for the outline page selection and the editor range
5538          * indication.
5539          *
5540          * @return the computed source reference
5541          * @since 3.0
5542          */
5543         protected ISourceReference computeHighlightRangeSourceReference() {
5544                 ISourceViewer sourceViewer = getSourceViewer();
5545                 if (sourceViewer == null)
5546                         return null;
5547
5548                 StyledText styledText = sourceViewer.getTextWidget();
5549                 if (styledText == null)
5550                         return null;
5551
5552                 int caret = 0;
5553                 if (sourceViewer instanceof ITextViewerExtension5) {
5554                         ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
5555                         caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
5556                 } else {
5557                         int offset = sourceViewer.getVisibleRegion().getOffset();
5558                         caret = offset + styledText.getCaretOffset();
5559                 }
5560
5561                 IJavaElement element = getElementAt(caret, false);
5562
5563                 if (!(element instanceof ISourceReference))
5564                         return null;
5565
5566                 if (element.getElementType() == IJavaElement.IMPORT_DECLARATION) {
5567
5568                         IImportDeclaration declaration = (IImportDeclaration) element;
5569                         IImportContainer container = (IImportContainer) declaration.getParent();
5570                         ISourceRange srcRange = null;
5571
5572                         try {
5573                                 srcRange = container.getSourceRange();
5574                         } catch (JavaModelException e) {
5575                         }
5576
5577                         if (srcRange != null && srcRange.getOffset() == caret)
5578                                 return container;
5579                 }
5580
5581                 return (ISourceReference) element;
5582         }
5583
5584         /**
5585          * Returns the most narrow java element including the given offset.
5586          *
5587          * @param offset
5588          *          the offset inside of the requested element
5589          * @param reconcile
5590          *          <code>true</code> if editor input should be reconciled in
5591          *          advance
5592          * @return the most narrow java element
5593          * @since 3.0
5594          */
5595         protected IJavaElement getElementAt(int offset, boolean reconcile) {
5596                 return getElementAt(offset);
5597         }
5598
5599         public ShowInContext getShowInContext() {
5600                 FileEditorInput fei = (FileEditorInput) getEditorInput();
5601                 ShowInContext context = BrowserUtil.getShowInContext(fei.getFile(), false, "");
5602                 if (context != null) {
5603                         return context;
5604                 }
5605                 return new ShowInContext(fei.getFile(), null);
5606         }
5607
5608         public String[] getShowInTargetIds() {
5609                 return new String[] { BrowserView.ID_BROWSER };
5610         }
5611
5612         /**
5613          * Updates the occurrences annotations based on the current selection.
5614          *
5615          * @param selection
5616          *          the text selection
5617          * @param astRoot
5618          *          the compilation unit AST
5619          * @since 3.0
5620          */
5621         protected void updateOccurrenceAnnotations(ITextSelection selection) {// ,
5622                 // CompilationUnit
5623                 // astRoot)
5624                 // {
5625
5626                 if (fOccurrencesFinderJob != null)
5627                         fOccurrencesFinderJob.cancel();
5628
5629                 if (!fMarkOccurrenceAnnotations)
5630                         return;
5631
5632                 // if (astRoot == null || selection == null)
5633                 if (selection == null)
5634                         return;
5635
5636                 IDocument document = getSourceViewer().getDocument();
5637                 if (document == null)
5638                         return;
5639
5640                 fMarkOccurrenceTargetRegion = null;
5641                 if (document instanceof IDocumentExtension4) {
5642                         int offset = selection.getOffset();
5643                         long currentModificationStamp = ((IDocumentExtension4) document).getModificationStamp();
5644                         if (fMarkOccurrenceTargetRegion != null && currentModificationStamp == fMarkOccurrenceModificationStamp) {
5645                                 if (fMarkOccurrenceTargetRegion.getOffset() <= offset
5646                                                 && offset <= fMarkOccurrenceTargetRegion.getOffset() + fMarkOccurrenceTargetRegion.getLength())
5647                                         return;
5648                         }
5649                         fMarkOccurrenceTargetRegion = JavaWordFinder.findWord(document, offset);
5650                         fMarkOccurrenceModificationStamp = currentModificationStamp;
5651                 }
5652
5653                 if (fMarkOccurrenceTargetRegion == null || fMarkOccurrenceTargetRegion.getLength() == 0) {
5654                         return;
5655                 }
5656
5657                 List matches = null;
5658
5659                 if (matches == null) {
5660                         try {
5661                                 matches = new ArrayList();
5662
5663                                 Scanner fScanner = new Scanner();
5664                                 fScanner.setSource(document.get().toCharArray());
5665                                 fScanner.setPHPMode(false);
5666                                 String wordStr;
5667                                 char[] word;
5668
5669                                 wordStr = document.get(fMarkOccurrenceTargetRegion.getOffset(), fMarkOccurrenceTargetRegion.getLength());
5670                                 if (wordStr != null) {
5671                                         word = wordStr.toCharArray();
5672                                         int fToken = ITerminalSymbols.TokenNameEOF;
5673                                         try {
5674                                                 fToken = fScanner.getNextToken();
5675                                                 while (fToken != ITerminalSymbols.TokenNameEOF) { // && fToken !=
5676                                                         // TokenNameERROR) {
5677                                                         if (fToken == ITerminalSymbols.TokenNameVariable || fToken == ITerminalSymbols.TokenNameIdentifier) {
5678                                                                 // global variable
5679                                                                 if (fScanner.equalsCurrentTokenSource(word)) {
5680                                                                         matches.add(new Region(fScanner.getCurrentTokenStartPosition(), fScanner.getCurrentTokenEndPosition()
5681                                                                                         - fScanner.getCurrentTokenStartPosition() + 1));
5682                                                                 }
5683                                                         }
5684                                                         fToken = fScanner.getNextToken();
5685                                                 }
5686                                         } catch (InvalidInputException e) {
5687                                                 // ignore errors
5688                                         } catch (SyntaxError e) {
5689                                                 // ignore errors
5690                                         }
5691                                 }
5692                         } catch (BadLocationException e1) {
5693                                 // ignore errors
5694                         } catch (Exception e) {
5695                                 e.printStackTrace();
5696                                 // ignore errors
5697                         }
5698
5699                 }
5700
5701                 if (matches == null || matches.size() == 0) {
5702                         if (!fStickyOccurrenceAnnotations)
5703                                 removeOccurrenceAnnotations();
5704                         return;
5705                 }
5706
5707                 Position[] positions = new Position[matches.size()];
5708                 int i = 0;
5709                 for (Iterator each = matches.iterator(); each.hasNext();) {
5710                         IRegion currentNode = (IRegion) each.next();
5711                         positions[i++] = new Position(currentNode.getOffset(), currentNode.getLength());
5712                 }
5713
5714                 fOccurrencesFinderJob = new OccurrencesFinderJob(document, positions, selection);
5715                 // fOccurrencesFinderJob.setPriority(Job.DECORATE);
5716                 // fOccurrencesFinderJob.setSystem(true);
5717                 // fOccurrencesFinderJob.schedule();
5718                 fOccurrencesFinderJob.run(new NullProgressMonitor());
5719         }
5720
5721         protected void installOccurrencesFinder() {
5722                 fMarkOccurrenceAnnotations = true;
5723
5724                 fPostSelectionListenerWithAST = new ISelectionListenerWithAST() {
5725                         public void selectionChanged(IEditorPart part, ITextSelection selection) { // ,
5726                                 // CompilationUnit
5727                                 // astRoot)
5728                                 // {
5729                                 updateOccurrenceAnnotations(selection);// , astRoot);
5730                         }
5731                 };
5732                 SelectionListenerWithASTManager.getDefault().addListener(this, fPostSelectionListenerWithAST);
5733                 if (getSelectionProvider() != null) {
5734                         fForcedMarkOccurrencesSelection = getSelectionProvider().getSelection();
5735                         SelectionListenerWithASTManager.getDefault().forceSelectionChange(this, (ITextSelection) fForcedMarkOccurrencesSelection);
5736                 }
5737
5738                 if (fOccurrencesFinderJobCanceler == null) {
5739                         fOccurrencesFinderJobCanceler = new OccurrencesFinderJobCanceler();
5740                         fOccurrencesFinderJobCanceler.install();
5741                 }
5742         }
5743
5744         protected void uninstallOccurrencesFinder() {
5745                 fMarkOccurrenceAnnotations = false;
5746
5747                 if (fOccurrencesFinderJob != null) {
5748                         fOccurrencesFinderJob.cancel();
5749                         fOccurrencesFinderJob = null;
5750                 }
5751
5752                 if (fOccurrencesFinderJobCanceler != null) {
5753                         fOccurrencesFinderJobCanceler.uninstall();
5754                         fOccurrencesFinderJobCanceler = null;
5755                 }
5756
5757                 if (fPostSelectionListenerWithAST != null) {
5758                         SelectionListenerWithASTManager.getDefault().removeListener(this, fPostSelectionListenerWithAST);
5759                         fPostSelectionListenerWithAST = null;
5760                 }
5761
5762                 removeOccurrenceAnnotations();
5763         }
5764
5765         protected boolean isMarkingOccurrences() {
5766                 return fMarkOccurrenceAnnotations;
5767         }
5768
5769         void removeOccurrenceAnnotations() {
5770                 fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
5771                 fMarkOccurrenceTargetRegion = null;
5772
5773                 IDocumentProvider documentProvider = getDocumentProvider();
5774                 if (documentProvider == null)
5775                         return;
5776
5777                 IAnnotationModel annotationModel = documentProvider.getAnnotationModel(getEditorInput());
5778                 if (annotationModel == null || fOccurrenceAnnotations == null)
5779                         return;
5780
5781                 synchronized (getLockObject(annotationModel)) {
5782                         if (annotationModel instanceof IAnnotationModelExtension) {
5783                                 ((IAnnotationModelExtension) annotationModel).replaceAnnotations(fOccurrenceAnnotations, null);
5784                         } else {
5785                                 for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++)
5786                                         annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
5787                         }
5788                         fOccurrenceAnnotations = null;
5789                 }
5790         }
5791 }