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