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