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