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