misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPEditor.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 /**********************************************************************
4 Copyright (c) 2000, 2002 IBM Corp. and others.
5 All rights reserved. This program and the accompanying materials
6 are made available under the terms of the Common Public License v1.0
7 which accompanies this distribution, and is available at
8 http://www.eclipse.org/legal/cpl-v10.html
9
10 Contributors:
11     IBM Corporation - Initial implementation
12     Klaus Hartlage - www.eclipseproject.de
13 **********************************************************************/
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.ResourceBundle;
20 import java.util.StringTokenizer;
21
22 import net.sourceforge.phpdt.core.ICompilationUnit;
23 import net.sourceforge.phpdt.core.IJavaElement;
24 import net.sourceforge.phpdt.core.IMember;
25 import net.sourceforge.phpdt.core.ISourceRange;
26 import net.sourceforge.phpdt.core.ISourceReference;
27 import net.sourceforge.phpdt.core.JavaCore;
28 import net.sourceforge.phpdt.core.JavaModelException;
29 import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
30 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
31 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
32 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
33 import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
34 import net.sourceforge.phpdt.ui.IContextMenuConstants;
35 import net.sourceforge.phpdt.ui.JavaUI;
36 import net.sourceforge.phpdt.ui.PreferenceConstants;
37 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
38 import net.sourceforge.phpdt.ui.text.JavaTextTools;
39 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
40
41 import org.eclipse.core.resources.IMarker;
42 import org.eclipse.core.resources.IResource;
43 import org.eclipse.core.runtime.CoreException;
44 import org.eclipse.core.runtime.IProgressMonitor;
45 import org.eclipse.core.runtime.IStatus;
46 import org.eclipse.core.runtime.Preferences;
47 import org.eclipse.core.runtime.Status;
48 import org.eclipse.core.runtime.jobs.Job;
49 import org.eclipse.jface.action.Action;
50 import org.eclipse.jface.action.GroupMarker;
51 import org.eclipse.jface.action.IAction;
52 import org.eclipse.jface.action.MenuManager;
53 import org.eclipse.jface.action.Separator;
54 import org.eclipse.jface.preference.IPreferenceStore;
55 import org.eclipse.jface.preference.PreferenceConverter;
56 import org.eclipse.jface.text.BadLocationException;
57 import org.eclipse.jface.text.DefaultInformationControl;
58 import org.eclipse.jface.text.DocumentEvent;
59 import org.eclipse.jface.text.IDocument;
60 import org.eclipse.jface.text.IDocumentListener;
61 import org.eclipse.jface.text.IInformationControl;
62 import org.eclipse.jface.text.IInformationControlCreator;
63 import org.eclipse.jface.text.IRegion;
64 import org.eclipse.jface.text.ITextHover;
65 import org.eclipse.jface.text.ITextInputListener;
66 import org.eclipse.jface.text.ITextSelection;
67 import org.eclipse.jface.text.ITextViewer;
68 import org.eclipse.jface.text.ITextViewerExtension2;
69 import org.eclipse.jface.text.ITextViewerExtension3;
70 import org.eclipse.jface.text.ITypedRegion;
71 import org.eclipse.jface.text.Position;
72 import org.eclipse.jface.text.Region;
73 import org.eclipse.jface.text.TextSelection;
74 import org.eclipse.jface.text.information.IInformationProvider;
75 import org.eclipse.jface.text.information.InformationPresenter;
76 import org.eclipse.jface.text.source.Annotation;
77 import org.eclipse.jface.text.source.IAnnotationModel;
78 import org.eclipse.jface.text.source.IAnnotationModelExtension;
79 import org.eclipse.jface.text.source.IOverviewRuler;
80 import org.eclipse.jface.text.source.ISourceViewer;
81 import org.eclipse.jface.text.source.IVerticalRuler;
82 import org.eclipse.jface.text.source.OverviewRuler;
83 import org.eclipse.jface.text.source.SourceViewerConfiguration;
84 import org.eclipse.jface.util.IPropertyChangeListener;
85 import org.eclipse.jface.util.PropertyChangeEvent;
86 import org.eclipse.jface.viewers.ISelection;
87 import org.eclipse.jface.viewers.ISelectionChangedListener;
88 import org.eclipse.jface.viewers.ISelectionProvider;
89 import org.eclipse.jface.viewers.IStructuredSelection;
90 import org.eclipse.jface.viewers.SelectionChangedEvent;
91 import org.eclipse.jface.viewers.StructuredSelection;
92 import org.eclipse.swt.SWT;
93 import org.eclipse.swt.custom.BidiSegmentEvent;
94 import org.eclipse.swt.custom.BidiSegmentListener;
95 import org.eclipse.swt.custom.StyleRange;
96 import org.eclipse.swt.custom.StyledText;
97 import org.eclipse.swt.events.FocusEvent;
98 import org.eclipse.swt.events.FocusListener;
99 import org.eclipse.swt.events.KeyEvent;
100 import org.eclipse.swt.events.KeyListener;
101 import org.eclipse.swt.events.MouseEvent;
102 import org.eclipse.swt.events.MouseListener;
103 import org.eclipse.swt.events.MouseMoveListener;
104 import org.eclipse.swt.events.PaintEvent;
105 import org.eclipse.swt.events.PaintListener;
106 import org.eclipse.swt.graphics.Color;
107 import org.eclipse.swt.graphics.Cursor;
108 import org.eclipse.swt.graphics.GC;
109 import org.eclipse.swt.graphics.Image;
110 import org.eclipse.swt.graphics.Point;
111 import org.eclipse.swt.graphics.RGB;
112 import org.eclipse.swt.widgets.Composite;
113 import org.eclipse.swt.widgets.Control;
114 import org.eclipse.swt.widgets.Display;
115 import org.eclipse.swt.widgets.Shell;
116 import org.eclipse.ui.IEditorInput;
117 import org.eclipse.ui.IPageLayout;
118 import org.eclipse.ui.IPartService;
119 import org.eclipse.ui.IViewPart;
120 import org.eclipse.ui.IWorkbenchPage;
121 import org.eclipse.ui.IWorkbenchPart;
122 import org.eclipse.ui.IWorkbenchWindow;
123 import org.eclipse.ui.actions.ActionContext;
124 import org.eclipse.ui.actions.ActionGroup;
125 import org.eclipse.ui.editors.text.DefaultEncodingSupport;
126 import org.eclipse.ui.editors.text.IEncodingSupport;
127 import org.eclipse.ui.part.IShowInTargetList;
128 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
129 import org.eclipse.ui.texteditor.ExtendedTextEditor;
130 import org.eclipse.ui.texteditor.IDocumentProvider;
131 import org.eclipse.ui.texteditor.IEditorStatusLine;
132 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
133 import org.eclipse.ui.texteditor.MarkerAnnotation;
134 import org.eclipse.ui.texteditor.ResourceAction;
135 import org.eclipse.ui.texteditor.TextEditorAction;
136 import org.eclipse.ui.texteditor.TextOperationAction;
137 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
138 import org.eclipse.ui.views.tasklist.TaskList;
139
140 /**
141  * PHP specific text editor.
142  */
143 public abstract class PHPEditor  extends ExtendedTextEditor implements IViewPartInputProvider {
144 //extends StatusTextEditor implements IViewPartInputProvider { // extends TextEditor {
145   /**
146          * "Smart" runnable for updating the outline page's selection.
147          */
148   class OutlinePageSelectionUpdater implements Runnable {
149
150     /** Has the runnable already been posted? */
151     private boolean fPosted = false;
152
153     public OutlinePageSelectionUpdater() {
154     }
155
156     /*
157      * @see Runnable#run()
158      */
159     public void run() {
160       synchronizeOutlinePageSelection();
161       fPosted = false;
162     }
163
164     /**
165      * Posts this runnable into the event queue.
166      */
167     public void post() {
168       if (fPosted)
169         return;
170
171       Shell shell = getSite().getShell();
172       if (shell != null & !shell.isDisposed()) {
173         fPosted = true;
174         shell.getDisplay().asyncExec(this);
175       }
176     }
177   };
178   class SelectionChangedListener implements ISelectionChangedListener {
179     public void selectionChanged(SelectionChangedEvent event) {
180       doSelectionChanged(event);
181     }
182   };
183
184   /*
185   * Link mode.  
186   */
187   class MouseClickListener
188     implements KeyListener, MouseListener, MouseMoveListener, FocusListener, PaintListener, IPropertyChangeListener, IDocumentListener, ITextInputListener {
189
190     /** The session is active. */
191     private boolean fActive;
192
193     /** The currently active style range. */
194     private IRegion fActiveRegion;
195     /** The currently active style range as position. */
196     private Position fRememberedPosition;
197     /** The hand cursor. */
198     private Cursor fCursor;
199
200     /** The link color. */
201     private Color fColor;
202     /** The key modifier mask. */
203     private int fKeyModifierMask;
204
205     public void deactivate() {
206       deactivate(false);
207     }
208
209     public void deactivate(boolean redrawAll) {
210       if (!fActive)
211         return;
212
213       repairRepresentation(redrawAll);
214       fActive = false;
215     }
216
217     public void install() {
218
219       ISourceViewer sourceViewer = getSourceViewer();
220       if (sourceViewer == null)
221         return;
222
223       StyledText text = sourceViewer.getTextWidget();
224       if (text == null || text.isDisposed())
225         return;
226
227       updateColor(sourceViewer);
228
229       sourceViewer.addTextInputListener(this);
230
231       IDocument document = sourceViewer.getDocument();
232       if (document != null)
233         document.addDocumentListener(this);
234
235       text.addKeyListener(this);
236       text.addMouseListener(this);
237       text.addMouseMoveListener(this);
238       text.addFocusListener(this);
239       text.addPaintListener(this);
240
241       updateKeyModifierMask();
242
243       IPreferenceStore preferenceStore = getPreferenceStore();
244       preferenceStore.addPropertyChangeListener(this);
245     }
246
247     private void updateKeyModifierMask() {
248       String modifiers = getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
249       fKeyModifierMask = computeStateMask(modifiers);
250       if (fKeyModifierMask == -1) {
251         // Fallback to stored state mask
252         fKeyModifierMask = getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
253       };
254     }
255
256     private int computeStateMask(String modifiers) {
257       if (modifiers == null)
258         return -1;
259
260       if (modifiers.length() == 0)
261         return SWT.NONE;
262
263       int stateMask = 0;
264       StringTokenizer modifierTokenizer = new StringTokenizer(modifiers, ",;.:+-* "); //$NON-NLS-1$
265       while (modifierTokenizer.hasMoreTokens()) {
266         int modifier = EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
267         if (modifier == 0 || (stateMask & modifier) == modifier)
268           return -1;
269         stateMask = stateMask | modifier;
270       }
271       return stateMask;
272     }
273
274     public void uninstall() {
275
276       if (fColor != null) {
277         fColor.dispose();
278         fColor = null;
279       }
280
281       if (fCursor != null) {
282         fCursor.dispose();
283         fCursor = null;
284       }
285
286       ISourceViewer sourceViewer = getSourceViewer();
287       if (sourceViewer == null)
288         return;
289
290       sourceViewer.removeTextInputListener(this);
291
292       IDocument document = sourceViewer.getDocument();
293       if (document != null)
294         document.removeDocumentListener(this);
295
296       IPreferenceStore preferenceStore = getPreferenceStore();
297       if (preferenceStore != null)
298         preferenceStore.removePropertyChangeListener(this);
299
300       StyledText text = sourceViewer.getTextWidget();
301       if (text == null || text.isDisposed())
302         return;
303
304       text.removeKeyListener(this);
305       text.removeMouseListener(this);
306       text.removeMouseMoveListener(this);
307       text.removeFocusListener(this);
308       text.removePaintListener(this);
309     }
310
311     /*
312      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
313      */
314     public void propertyChange(PropertyChangeEvent event) {
315       if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
316         ISourceViewer viewer = getSourceViewer();
317         if (viewer != null)
318           updateColor(viewer);
319       } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
320         updateKeyModifierMask();
321       }
322     }
323
324     private void updateColor(ISourceViewer viewer) {
325       if (fColor != null)
326         fColor.dispose();
327
328       StyledText text = viewer.getTextWidget();
329       if (text == null || text.isDisposed())
330         return;
331
332       Display display = text.getDisplay();
333       fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR, display);
334     }
335
336     /**
337      * Creates a color from the information stored in the given preference store.
338      * Returns <code>null</code> if there is no such information available.
339      */
340     private Color createColor(IPreferenceStore store, String key, Display display) {
341
342       RGB rgb = null;
343
344       if (store.contains(key)) {
345
346         if (store.isDefault(key))
347           rgb = PreferenceConverter.getDefaultColor(store, key);
348         else
349           rgb = PreferenceConverter.getColor(store, key);
350
351         if (rgb != null)
352           return new Color(display, rgb);
353       }
354
355       return null;
356     }
357
358     private void repairRepresentation() {
359       repairRepresentation(false);
360     }
361
362     private void repairRepresentation(boolean redrawAll) {
363
364       if (fActiveRegion == null)
365         return;
366
367       ISourceViewer viewer = getSourceViewer();
368       if (viewer != null) {
369         resetCursor(viewer);
370
371         int offset = fActiveRegion.getOffset();
372         int length = fActiveRegion.getLength();
373
374         // remove style
375         if (!redrawAll && viewer instanceof ITextViewerExtension2)
376            ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset, length);
377         else
378           viewer.invalidateTextPresentation();
379
380         // remove underline                             
381         if (viewer instanceof ITextViewerExtension3) {
382           ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
383           offset = extension.modelOffset2WidgetOffset(offset);
384         } else {
385           offset -= viewer.getVisibleRegion().getOffset();
386         }
387
388         StyledText text = viewer.getTextWidget();
389         try {
390           text.redrawRange(offset, length, true);
391         } catch (IllegalArgumentException x) {
392           PHPeclipsePlugin.log(x);
393         }
394       }
395
396       fActiveRegion = null;
397     }
398
399     // will eventually be replaced by a method provided by jdt.core             
400     private IRegion selectWord(IDocument document, int anchor) {
401
402       try {
403         int offset = anchor;
404         char c;
405
406         while (offset >= 0) {
407           c = document.getChar(offset);
408           if (!Character.isJavaIdentifierPart(c))
409             break;
410           --offset;
411         }
412
413         int start = offset;
414
415         offset = anchor;
416         int length = document.getLength();
417
418         while (offset < length) {
419           c = document.getChar(offset);
420           if (!Character.isJavaIdentifierPart(c))
421             break;
422           ++offset;
423         }
424
425         int end = offset;
426
427         if (start == end)
428           return new Region(start, 0);
429         else
430           return new Region(start + 1, end - start - 1);
431
432       } catch (BadLocationException x) {
433         return null;
434       }
435     }
436
437     IRegion getCurrentTextRegion(ISourceViewer viewer) {
438
439       int offset = getCurrentTextOffset(viewer);
440       if (offset == -1)
441         return null;
442
443       return null;
444       //                                IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
445       //                                if (input == null)
446       //                                        return null;
447       //      
448       //                                try {
449       //                                
450       //                                        IJavaElement[] elements= null;
451       //                                        synchronized (input) {
452       //                                                elements= ((ICodeAssist) input).codeSelect(offset, 0);
453       //                                        }
454       //                                
455       //                                        if (elements == null || elements.length == 0)
456       //                                                return null;
457       //                                        
458       //                                        return selectWord(viewer.getDocument(), offset);
459       //                                        
460       //                                } catch (JavaModelException e) {
461       //                                        return null;    
462       //                                }
463     }
464
465     private int getCurrentTextOffset(ISourceViewer viewer) {
466
467       try {
468         StyledText text = viewer.getTextWidget();
469         if (text == null || text.isDisposed())
470           return -1;
471
472         Display display = text.getDisplay();
473         Point absolutePosition = display.getCursorLocation();
474         Point relativePosition = text.toControl(absolutePosition);
475
476         int widgetOffset = text.getOffsetAtLocation(relativePosition);
477         if (viewer instanceof ITextViewerExtension3) {
478           ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
479           return extension.widgetOffset2ModelOffset(widgetOffset);
480         } else {
481           return widgetOffset + viewer.getVisibleRegion().getOffset();
482         }
483
484       } catch (IllegalArgumentException e) {
485         return -1;
486       }
487     }
488
489     private void highlightRegion(ISourceViewer viewer, IRegion region) {
490
491       if (region.equals(fActiveRegion))
492         return;
493
494       repairRepresentation();
495
496       StyledText text = viewer.getTextWidget();
497       if (text == null || text.isDisposed())
498         return;
499
500       // highlight region
501       int offset = 0;
502       int length = 0;
503
504       if (viewer instanceof ITextViewerExtension3) {
505         ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
506         IRegion widgetRange = extension.modelRange2WidgetRange(region);
507         if (widgetRange == null)
508           return;
509
510         offset = widgetRange.getOffset();
511         length = widgetRange.getLength();
512
513       } else {
514         offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
515         length = region.getLength();
516       }
517
518       StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
519       Color foregroundColor = fColor;
520       Color backgroundColor = oldStyleRange == null ? text.getBackground() : oldStyleRange.background;
521       StyleRange styleRange = new StyleRange(offset, length, foregroundColor, backgroundColor);
522       text.setStyleRange(styleRange);
523
524       // underline
525       text.redrawRange(offset, length, true);
526
527       fActiveRegion = region;
528     }
529
530     private void activateCursor(ISourceViewer viewer) {
531       StyledText text = viewer.getTextWidget();
532       if (text == null || text.isDisposed())
533         return;
534       Display display = text.getDisplay();
535       if (fCursor == null)
536         fCursor = new Cursor(display, SWT.CURSOR_HAND);
537       text.setCursor(fCursor);
538     }
539
540     private void resetCursor(ISourceViewer viewer) {
541       StyledText text = viewer.getTextWidget();
542       if (text != null && !text.isDisposed())
543         text.setCursor(null);
544
545       if (fCursor != null) {
546         fCursor.dispose();
547         fCursor = null;
548       }
549     }
550
551     /*
552      * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
553      */
554     public void keyPressed(KeyEvent event) {
555
556       if (fActive) {
557         deactivate();
558         return;
559       }
560
561       if (event.keyCode != fKeyModifierMask) {
562         deactivate();
563         return;
564       }
565
566       fActive = true;
567
568       //                                removed for #25871                      
569       //
570       //                                ISourceViewer viewer= getSourceViewer();
571       //                                if (viewer == null)
572       //                                        return;
573       //                        
574       //                                IRegion region= getCurrentTextRegion(viewer);
575       //                                if (region == null)
576       //                                        return;
577       //                        
578       //                                highlightRegion(viewer, region);
579       //                                activateCursor(viewer);                                                                                         
580     }
581
582     /*
583      * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
584      */
585     public void keyReleased(KeyEvent event) {
586
587       if (!fActive)
588         return;
589
590       deactivate();
591     }
592
593     /*
594      * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
595      */
596     public void mouseDoubleClick(MouseEvent e) {
597     }
598     /*
599      * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
600      */
601     public void mouseDown(MouseEvent event) {
602
603       if (!fActive)
604         return;
605
606       if (event.stateMask != fKeyModifierMask) {
607         deactivate();
608         return;
609       }
610
611       if (event.button != 1) {
612         deactivate();
613         return;
614       }
615     }
616
617     /*
618      * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
619      */
620     public void mouseUp(MouseEvent e) {
621
622       if (!fActive)
623         return;
624
625       if (e.button != 1) {
626         deactivate();
627         return;
628       }
629
630       boolean wasActive = fCursor != null;
631
632       deactivate();
633
634       if (wasActive) {
635         IAction action = getAction("OpenEditor"); //$NON-NLS-1$
636         if (action != null)
637           action.run();
638       }
639     }
640
641     /*
642      * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
643      */
644     public void mouseMove(MouseEvent event) {
645
646       if (event.widget instanceof Control && !((Control) event.widget).isFocusControl()) {
647         deactivate();
648         return;
649       }
650
651       if (!fActive) {
652         if (event.stateMask != fKeyModifierMask)
653           return;
654         // modifier was already pressed
655         fActive = true;
656       }
657
658       ISourceViewer viewer = getSourceViewer();
659       if (viewer == null) {
660         deactivate();
661         return;
662       }
663
664       StyledText text = viewer.getTextWidget();
665       if (text == null || text.isDisposed()) {
666         deactivate();
667         return;
668       }
669
670       if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() != 0) {
671         deactivate();
672         return;
673       }
674
675       IRegion region = getCurrentTextRegion(viewer);
676       if (region == null || region.getLength() == 0) {
677         repairRepresentation();
678         return;
679       }
680
681       highlightRegion(viewer, region);
682       activateCursor(viewer);
683     }
684
685     /*
686      * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
687      */
688     public void focusGained(FocusEvent e) {
689     }
690
691     /*
692      * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
693      */
694     public void focusLost(FocusEvent event) {
695       deactivate();
696     }
697
698     /*
699      * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
700      */
701     public void documentAboutToBeChanged(DocumentEvent event) {
702       if (fActive && fActiveRegion != null) {
703         fRememberedPosition = new Position(fActiveRegion.getOffset(), fActiveRegion.getLength());
704         try {
705           event.getDocument().addPosition(fRememberedPosition);
706         } catch (BadLocationException x) {
707           fRememberedPosition = null;
708         }
709       }
710     }
711
712     /*
713      * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
714      */
715     public void documentChanged(DocumentEvent event) {
716       if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
717         event.getDocument().removePosition(fRememberedPosition);
718         fActiveRegion = new Region(fRememberedPosition.getOffset(), fRememberedPosition.getLength());
719       }
720       fRememberedPosition = null;
721
722       ISourceViewer viewer = getSourceViewer();
723       if (viewer != null) {
724         StyledText widget = viewer.getTextWidget();
725         if (widget != null && !widget.isDisposed()) {
726           widget.getDisplay().asyncExec(new Runnable() {
727             public void run() {
728               deactivate();
729             }
730           });
731         }
732       }
733     }
734
735     /*
736      * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
737      */
738     public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
739       if (oldInput == null)
740         return;
741       deactivate();
742       oldInput.removeDocumentListener(this);
743     }
744
745     /*
746      * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
747      */
748     public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
749       if (newInput == null)
750         return;
751       newInput.addDocumentListener(this);
752     }
753
754     /*
755      * @see PaintListener#paintControl(PaintEvent)
756      */
757     public void paintControl(PaintEvent event) {
758       if (fActiveRegion == null)
759         return;
760
761       ISourceViewer viewer = getSourceViewer();
762       if (viewer == null)
763         return;
764
765       StyledText text = viewer.getTextWidget();
766       if (text == null || text.isDisposed())
767         return;
768
769       int offset = 0;
770       int length = 0;
771
772       if (viewer instanceof ITextViewerExtension3) {
773
774         ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
775         IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset, length));
776         if (widgetRange == null)
777           return;
778
779         offset = widgetRange.getOffset();
780         length = widgetRange.getLength();
781
782       } else {
783
784         IRegion region = viewer.getVisibleRegion();
785         if (!includes(region, fActiveRegion))
786           return;
787
788         offset = fActiveRegion.getOffset() - region.getOffset();
789         length = fActiveRegion.getLength();
790       }
791
792       // support for bidi
793       Point minLocation = getMinimumLocation(text, offset, length);
794       Point maxLocation = getMaximumLocation(text, offset, length);
795
796       int x1 = minLocation.x;
797       int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
798       int y = minLocation.y + text.getLineHeight() - 1;
799
800       GC gc = event.gc;
801       if (fColor != null && !fColor.isDisposed())
802         gc.setForeground(fColor);
803       gc.drawLine(x1, y, x2, y);
804     }
805
806     private boolean includes(IRegion region, IRegion position) {
807       return position.getOffset() >= region.getOffset() && position.getOffset() + position.getLength() <= region.getOffset() + region.getLength();
808     }
809
810     private Point getMinimumLocation(StyledText text, int offset, int length) {
811       Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
812
813       for (int i = 0; i <= length; i++) {
814         Point location = text.getLocationAtOffset(offset + i);
815
816         if (location.x < minLocation.x)
817           minLocation.x = location.x;
818         if (location.y < minLocation.y)
819           minLocation.y = location.y;
820       }
821
822       return minLocation;
823     }
824
825     private Point getMaximumLocation(StyledText text, int offset, int length) {
826       Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
827
828       for (int i = 0; i <= length; i++) {
829         Point location = text.getLocationAtOffset(offset + i);
830
831         if (location.x > maxLocation.x)
832           maxLocation.x = location.x;
833         if (location.y > maxLocation.y)
834           maxLocation.y = location.y;
835       }
836
837       return maxLocation;
838     }
839   };
840
841   /**
842    * This action dispatches into two behaviours: If there is no current text
843    * hover, the javadoc is displayed using information presenter. If there is
844    * a current text hover, it is converted into a information presenter in
845    * order to make it sticky.
846    */
847   class InformationDispatchAction extends TextEditorAction {
848
849     /** The wrapped text operation action. */
850     private final TextOperationAction fTextOperationAction;
851
852     /**
853      * Creates a dispatch action.
854      */
855     public InformationDispatchAction(ResourceBundle resourceBundle, String prefix, final TextOperationAction textOperationAction) {
856       super(resourceBundle, prefix, PHPEditor.this);
857       if (textOperationAction == null)
858         throw new IllegalArgumentException();
859       fTextOperationAction = textOperationAction;
860     }
861
862     /*
863      * @see org.eclipse.jface.action.IAction#run()
864      */
865     public void run() {
866
867       ISourceViewer sourceViewer = getSourceViewer();
868       if (sourceViewer == null) {
869         fTextOperationAction.run();
870         return;
871       }
872
873       if (!(sourceViewer instanceof ITextViewerExtension2)) {
874         fTextOperationAction.run();
875         return;
876       }
877
878       ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
879
880       // does a text hover exist?
881       ITextHover textHover = textViewerExtension2.getCurrentTextHover();
882       if (textHover == null) {
883         fTextOperationAction.run();
884         return;
885       }
886
887       Point hoverEventLocation = textViewerExtension2.getHoverEventLocation();
888       int offset = computeOffsetAtLocation(sourceViewer, hoverEventLocation.x, hoverEventLocation.y);
889       if (offset == -1) {
890         fTextOperationAction.run();
891         return;
892       }
893
894       try {
895         // get the text hover content
896         IDocument document = sourceViewer.getDocument();
897         String contentType = document.getContentType(offset);
898
899         final IRegion hoverRegion = textHover.getHoverRegion(sourceViewer, offset);
900         if (hoverRegion == null)
901           return;
902
903         final String hoverInfo = textHover.getHoverInfo(sourceViewer, hoverRegion);
904
905         // with information provider
906         IInformationProvider informationProvider = new IInformationProvider() {
907           /*
908            * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int)
909            */
910           public IRegion getSubject(ITextViewer textViewer, int offset) {
911             return hoverRegion;
912           }
913           /*
914            * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
915            */
916           public String getInformation(ITextViewer textViewer, IRegion subject) {
917             return hoverInfo;
918           }
919         };
920
921         fInformationPresenter.setOffset(offset);
922         fInformationPresenter.setInformationProvider(informationProvider, contentType);
923         fInformationPresenter.showInformation();
924
925       } catch (BadLocationException e) {
926       }
927     }
928
929     // modified version from TextViewer
930     private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
931
932       StyledText styledText = textViewer.getTextWidget();
933       IDocument document = textViewer.getDocument();
934
935       if (document == null)
936         return -1;
937
938       try {
939         int widgetLocation = styledText.getOffsetAtLocation(new Point(x, y));
940         if (textViewer instanceof ITextViewerExtension3) {
941           ITextViewerExtension3 extension = (ITextViewerExtension3) textViewer;
942           return extension.widgetOffset2ModelOffset(widgetLocation);
943         } else {
944           IRegion visibleRegion = textViewer.getVisibleRegion();
945           return widgetLocation + visibleRegion.getOffset();
946         }
947       } catch (IllegalArgumentException e) {
948         return -1;
949       }
950
951     }
952   };
953
954 //  static protected class AnnotationAccess implements IAnnotationAccess {
955 //    /*
956 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
957 //     */
958 //    public Object getType(Annotation annotation) {
959 //      if (annotation instanceof IJavaAnnotation) {
960 //        IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
961 //   //     if (javaAnnotation.isRelevant())
962 //   //       return javaAnnotation.getAnnotationType();
963 //      }
964 //      return null;
965 //    }
966 //
967 //    /*
968 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
969 //     */
970 //    public boolean isMultiLine(Annotation annotation) {
971 //      return true;
972 //    }
973 //
974 //    /*
975 //     * @see org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
976 //     */
977 //    public boolean isTemporary(Annotation annotation) {
978 //      if (annotation instanceof IJavaAnnotation) {
979 //        IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
980 //        if (javaAnnotation.isRelevant())
981 //          return javaAnnotation.isTemporary();
982 //      }
983 //      return false;
984 //    }
985 //  };
986
987   private class PropertyChangeListener implements org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
988     /*
989      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
990      */
991     public void propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
992       handlePreferencePropertyChanged(event);
993     }
994   };
995   
996   /**
997          * Finds and marks occurrence annotations.
998          * 
999          * @since 3.0
1000          */
1001         class OccurrencesFinderJob extends Job implements IDocumentListener {
1002                 
1003                 private IDocument fDocument;
1004                 private boolean fCancelled= false;
1005                 private IProgressMonitor fProgressMonitor;
1006                 private Position[] fPositions;
1007                 
1008                 public OccurrencesFinderJob(IDocument document, Position[] positions) {
1009                         super("Occurrences Marker"); //$NON-NLS-1$
1010                         fDocument= document;
1011                         fPositions= positions;
1012                         fDocument.addDocumentListener(this);
1013                 }
1014                 
1015                 private boolean isCancelled() {
1016                         return fCancelled || fProgressMonitor.isCanceled();
1017                 }
1018                 
1019                 /*
1020                  * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
1021                  */
1022                 public IStatus run(IProgressMonitor progressMonitor) {
1023                         
1024                         fProgressMonitor= progressMonitor;
1025                         
1026                         try {
1027                                 
1028                                 if (isCancelled())
1029                                         return Status.CANCEL_STATUS;
1030                                 
1031                                 ITextViewer textViewer= getViewer(); 
1032                                 if (textViewer == null)
1033                                         return Status.CANCEL_STATUS;
1034                                 
1035                                 IDocument document= textViewer.getDocument();
1036                                 if (document == null)
1037                                         return Status.CANCEL_STATUS;
1038                                 
1039                                 IDocumentProvider documentProvider= getDocumentProvider();
1040                                 if (documentProvider == null)
1041                                         return Status.CANCEL_STATUS;
1042                         
1043                                 IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
1044                                 if (annotationModel == null)
1045                                         return Status.CANCEL_STATUS;
1046                                 
1047                                 // Add occurrence annotations
1048                                 int length= fPositions.length;
1049                                 Map annotationMap= new HashMap(length);
1050                                 for (int i= 0; i < length; i++) {
1051                                         
1052                                         if (isCancelled())
1053                                                 return Status.CANCEL_STATUS; 
1054                                         
1055                                         String message;
1056                                         Position position= fPositions[i];
1057                                         
1058                                         // Create & add annotation
1059                                         try {
1060                                                 message= document.get(position.offset, position.length);
1061                                         } catch (BadLocationException ex) {
1062                                                 // Skip this match
1063                                                 continue;
1064                                         }
1065                                         annotationMap.put(
1066                                                         new Annotation("net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$
1067                                                         position);
1068                                 }
1069                                 
1070                                 if (isCancelled())
1071                                         return Status.CANCEL_STATUS;
1072                                 
1073                                 synchronized (annotationModel) {
1074                                         if (annotationModel instanceof IAnnotationModelExtension) {
1075                                                 ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, annotationMap);
1076                                         } else {
1077                                                 removeOccurrenceAnnotations();
1078                                                 Iterator iter= annotationMap.entrySet().iterator();
1079                                                 while (iter.hasNext()) {
1080                                                         Map.Entry mapEntry= (Map.Entry)iter.next(); 
1081                                                         annotationModel.addAnnotation((Annotation)mapEntry.getKey(), (Position)mapEntry.getValue());
1082                                                 }
1083                                         }
1084                                         fOccurrenceAnnotations= (Annotation[])annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
1085                                 }
1086                         } finally {
1087                                 fDocument.removeDocumentListener(this);
1088                         }
1089                         return Status.OK_STATUS;
1090                 }
1091
1092                 /*
1093                  * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
1094                  */
1095                 public void documentAboutToBeChanged(DocumentEvent event) {
1096                         fCancelled= true;
1097                 }
1098
1099                 /*
1100                  * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
1101                  */
1102                 public void documentChanged(DocumentEvent event) {
1103                 }
1104         }
1105         
1106         
1107         /**
1108          * Holds the current occurrence annotations.
1109          * @since 3.0
1110          */
1111   private Annotation[] fOccurrenceAnnotations= null;
1112   
1113   private Job fOccurrencesFinderJob;
1114         
1115   /** Preference key for showing the line number ruler */
1116 //  private final static String LINE_NUMBER_RULER = PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
1117   /** Preference key for the foreground color of the line numbers */
1118  // private final static String LINE_NUMBER_COLOR = PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
1119   /** Preference key for the link color */
1120   private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
1121   /** Preference key for compiler task tags */
1122   private final static String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
1123
1124   // protected PHPActionGroup fActionGroups;
1125   //  /** The outline page */
1126   //  private AbstractContentOutlinePage fOutlinePage;
1127   /** The outline page */
1128   protected JavaOutlinePage fOutlinePage;
1129   /** Outliner context menu Id */
1130   protected String fOutlinerContextMenuId;
1131         /**
1132          * The editor selection changed listener.
1133          * 
1134          * @since 3.0
1135          */
1136 //  private EditorSelectionChangedListener fEditorSelectionChangedListener;
1137   /** Indicates whether this editor should react on outline page selection changes */
1138   private int fIgnoreOutlinePageSelection;
1139   
1140         /** The outline page selection updater */
1141         private OutlinePageSelectionUpdater fUpdater;
1142   //  protected PHPSyntaxParserThread fValidationThread = null;
1143
1144   // private IPreferenceStore fPHPPrefStore;
1145   /** The selection changed listener */
1146   protected ISelectionChangedListener fSelectionChangedListener = new SelectionChangedListener();
1147
1148   /** The editor's bracket matcher */
1149   private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
1150
1151
1152   /** The line number ruler column */
1153 //  private LineNumberRulerColumn fLineNumberRulerColumn;
1154   /** This editor's encoding support */
1155   private DefaultEncodingSupport fEncodingSupport;
1156   /** The mouse listener */
1157   private MouseClickListener fMouseListener;
1158
1159   protected CompositeActionGroup fActionGroups;
1160   protected CompositeActionGroup fContextMenuGroup;
1161
1162   /** The information presenter. */
1163   private InformationPresenter fInformationPresenter;
1164   /** The annotation access */
1165 //  protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
1166   /** The overview ruler */
1167   protected OverviewRuler isOverviewRulerVisible;
1168   /** The source viewer decoration support */
1169   //protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
1170   /** The overview ruler */
1171   //protected OverviewRuler fOverviewRuler;
1172
1173   /** The preference property change listener for java core. */
1174   private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
1175   /**
1176    * Returns the most narrow java element including the given offset
1177    * 
1178    * @param offset the offset inside of the requested element
1179    */
1180   abstract protected IJavaElement getElementAt(int offset);
1181
1182   /**
1183    * Returns the java element of this editor's input corresponding to the given IJavaElement
1184    */
1185   abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
1186   /**
1187          * Sets the input of the editor's outline page.
1188          */
1189   abstract protected void setOutlinePageInput(JavaOutlinePage page, IEditorInput input);
1190
1191   /**
1192    * Default constructor.
1193    */
1194   public PHPEditor() {
1195     super();
1196         JavaTextTools textTools= PHPeclipsePlugin.getDefault().getJavaTextTools();
1197         setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools, this)); //, IJavaPartitions.JAVA_PARTITIONING));
1198         setRangeIndicator(new DefaultRangeIndicator());
1199         IPreferenceStore store= PHPeclipsePlugin.getDefault().getPreferenceStore();
1200         setPreferenceStore(store);
1201         setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" });  //$NON-NLS-1$
1202 //      fMarkOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
1203 //      fStickyOccurrenceAnnotations= store.getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
1204     
1205         // TODO changed in 3.x ?
1206     if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
1207       fUpdater= new OutlinePageSelectionUpdater();
1208   }
1209  
1210   /*
1211    * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
1212    */
1213   protected void updatePropertyDependentActions() {
1214     super.updatePropertyDependentActions();
1215     if (fEncodingSupport != null)
1216       fEncodingSupport.reset();
1217   }
1218
1219   /*
1220    * Update the hovering behavior depending on the preferences.
1221    */
1222   private void updateHoverBehavior() {
1223     SourceViewerConfiguration configuration = getSourceViewerConfiguration();
1224     String[] types = configuration.getConfiguredContentTypes(getSourceViewer());
1225
1226     for (int i = 0; i < types.length; i++) {
1227
1228       String t = types[i];
1229
1230       int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(getSourceViewer(), t);
1231
1232       ISourceViewer sourceViewer = getSourceViewer();
1233       if (sourceViewer instanceof ITextViewerExtension2) {
1234         if (stateMasks != null) {
1235           for (int j = 0; j < stateMasks.length; j++) {
1236             int stateMask = stateMasks[j];
1237             ITextHover textHover = configuration.getTextHover(sourceViewer, t, stateMask);
1238             ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, stateMask);
1239           }
1240         } else {
1241           ITextHover textHover = configuration.getTextHover(sourceViewer, t);
1242           ((ITextViewerExtension2) sourceViewer).setTextHover(textHover, t, ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
1243         }
1244       } else
1245         sourceViewer.setTextHover(configuration.getTextHover(sourceViewer, t), t);
1246     }
1247   }
1248
1249   public void updatedTitleImage(Image image) {
1250     setTitleImage(image);
1251   }
1252   /*
1253    * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1254    */
1255   public Object getViewPartInput() {
1256     return getEditorInput().getAdapter(IResource.class);
1257   }
1258   /*
1259    * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
1260    */
1261   protected void doSetSelection(ISelection selection) {
1262     super.doSetSelection(selection);
1263     synchronizeOutlinePageSelection();
1264   }
1265   /*
1266    * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
1267    * widgets.Composite)
1268    */
1269   public void createPartControl(Composite parent) {
1270     super.createPartControl(parent);
1271
1272     //fSourceViewerDecorationSupport.install(getPreferenceStore());
1273
1274     Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1275     preferences.addPropertyChangeListener(fPropertyChangeListener);
1276
1277     IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
1278       public IInformationControl createInformationControl(Shell parent) {
1279         boolean cutDown = false;
1280         int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
1281         return new DefaultInformationControl(parent, SWT.RESIZE, style, new HTMLTextPresenter(cutDown));
1282       }
1283     };
1284
1285     fInformationPresenter = new InformationPresenter(informationControlCreator);
1286     fInformationPresenter.setSizeConstraints(60, 10, true, true);
1287     fInformationPresenter.install(getSourceViewer());
1288
1289   }
1290
1291   /**
1292    * Returns this document's complete text.
1293    *
1294    * @return the document's complete text
1295    */
1296   public String get() {
1297     IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1298     return doc.get();
1299   }
1300
1301   /**
1302          * Sets the outliner's context menu ID.
1303          */
1304   protected void setOutlinerContextMenuId(String menuId) {
1305     fOutlinerContextMenuId = menuId;
1306   }
1307
1308   /**
1309    *  Returns the standard action group of this editor.
1310    */
1311   protected ActionGroup getActionGroup() {
1312     return fActionGroups;
1313   }
1314
1315   //  public JavaOutlinePage getfOutlinePage() {
1316   //    return fOutlinePage;
1317   //  }
1318
1319   /** The <code>PHPEditor</code> implementation of this 
1320    * <code>AbstractTextEditor</code> method extend the 
1321    * actions to add those specific to the receiver
1322    */
1323   protected void createActions() {
1324     super.createActions();
1325     
1326         ResourceAction resAction= new TextOperationAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
1327         resAction= new InformationDispatchAction(PHPEditorMessages.getResourceBundle(), "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
1328         resAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_JAVADOC);
1329         setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
1330 //      WorkbenchHelp.setHelp(resAction, IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
1331         
1332         Action action= new GotoMatchingBracketAction(this);
1333         action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);                               
1334         setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
1335                 
1336 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.", this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
1337 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
1338 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
1339 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
1340 //
1341 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.", this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
1342 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
1343 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE, action);
1344 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
1345 //      
1346 //      action= new TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.", this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
1347 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
1348 //      setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY, action);
1349 ////    WorkbenchHelp.setHelp(action, IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
1350         
1351         fEncodingSupport= new DefaultEncodingSupport();
1352         fEncodingSupport.initialize(this);
1353         
1354 //      fSelectionHistory= new SelectionHistory(this);
1355 //
1356 //      action= new StructureSelectEnclosingAction(this, fSelectionHistory);
1357 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);                            
1358 //      setAction(StructureSelectionAction.ENCLOSING, action);
1359 //
1360 //      action= new StructureSelectNextAction(this, fSelectionHistory);
1361 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
1362 //      setAction(StructureSelectionAction.NEXT, action);
1363 //
1364 //      action= new StructureSelectPreviousAction(this, fSelectionHistory);
1365 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
1366 //      setAction(StructureSelectionAction.PREVIOUS, action);
1367 //
1368 //      StructureSelectHistoryAction historyAction= new StructureSelectHistoryAction(this, fSelectionHistory);
1369 //      historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);          
1370 //      setAction(StructureSelectionAction.HISTORY, historyAction);
1371 //      fSelectionHistory.setHistoryAction(historyAction);
1372 //                      
1373 //      action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
1374 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);                            
1375 //      setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
1376 //
1377 //      action= GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
1378 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);                                
1379 //      setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
1380 //      
1381 //      action= new QuickFormatAction();
1382 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
1383 //      setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
1384 //
1385 //      action= new RemoveOccurrenceAnnotations(this);
1386 //      action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
1387 //      setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
1388
1389         // add annotation actions
1390         action= new JavaSelectMarkerRulerAction2(PHPEditorMessages.getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
1391         setAction("AnnotationAction", action); //$NON-NLS-1$
1392     
1393         // add annotation actions
1394         action= new JavaSelectMarkerRulerAction2(PHPEditorMessages.getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
1395         setAction("AnnotationAction", action); //$NON-NLS-1$
1396   }
1397
1398   /** The <code>PHPEditor</code> implementation of this 
1399    * <code>AbstractTextEditor</code> method performs any extra 
1400    * disposal actions required by the php editor.
1401    */
1402   public void dispose() {
1403     //   PHPEditorEnvironment.disconnect(this);
1404     if (fOutlinePage != null)
1405       fOutlinePage.setInput(null);
1406
1407     if (fActionGroups != null)
1408       fActionGroups.dispose();
1409
1410     if (isBrowserLikeLinks())
1411       disableBrowserLikeLinks();
1412
1413     if (fEncodingSupport != null) {
1414       fEncodingSupport.dispose();
1415       fEncodingSupport = null;
1416     }
1417
1418     if (fPropertyChangeListener != null) {
1419       Preferences preferences = PHPeclipsePlugin.getDefault().getPluginPreferences();
1420       preferences.removePropertyChangeListener(fPropertyChangeListener);
1421       fPropertyChangeListener = null;
1422     }
1423
1424 //    if (fSourceViewerDecorationSupport != null) {
1425 //      fSourceViewerDecorationSupport.dispose();
1426 //      fSourceViewerDecorationSupport = null;
1427 //    }
1428
1429     if (fBracketMatcher != null) {
1430       fBracketMatcher.dispose();
1431       fBracketMatcher = null;
1432     }
1433     super.dispose();
1434   }
1435
1436   /** The <code>PHPEditor</code> implementation of this 
1437    * <code>AbstractTextEditor</code> method performs any extra 
1438    * revert behavior required by the php editor.
1439    */
1440   //  public void doRevertToSaved() {
1441   //    super.doRevertToSaved();
1442   //    if (fOutlinePage != null)
1443   //      fOutlinePage.update();
1444   //  }
1445
1446   /** The <code>PHPEditor</code> implementation of this 
1447    * <code>AbstractTextEditor</code> method performs any extra 
1448    * save behavior required by the php editor.
1449    */
1450   //  public void doSave(IProgressMonitor monitor) {
1451   //    super.doSave(monitor);
1452   // compile or not, according to the user preferences
1453   // IPreferenceStore store = getPreferenceStore(); 
1454
1455   // the parse on save was changed to the eclipse "builders" concept
1456   //    if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
1457   //      IAction a = PHPParserAction.getInstance();
1458   //      if (a != null)
1459   //        a.run();
1460   //    }
1461
1462   //    if (SWT.getPlatform().equals("win32")) {
1463   //      IAction a = ShowExternalPreviewAction.getInstance();
1464   //      if (a != null)
1465   //        a.run();
1466   //    }
1467   //    if (fOutlinePage != null)
1468   //      fOutlinePage.update();
1469   //  }
1470
1471   /** The <code>PHPEditor</code> implementation of this 
1472    * <code>AbstractTextEditor</code> method performs any extra 
1473    * save as behavior required by the php editor.
1474    */
1475   //  public void doSaveAs() {
1476   //    super.doSaveAs();
1477   //    if (fOutlinePage != null)
1478   //      fOutlinePage.update();
1479   //  }
1480   /*
1481          * @see StatusTextEditor#getStatusHeader(IStatus)
1482          */
1483   protected String getStatusHeader(IStatus status) {
1484     if (fEncodingSupport != null) {
1485       String message = fEncodingSupport.getStatusHeader(status);
1486       if (message != null)
1487         return message;
1488     }
1489     return super.getStatusHeader(status);
1490   }
1491
1492   /*
1493    * @see StatusTextEditor#getStatusBanner(IStatus)
1494    */
1495   protected String getStatusBanner(IStatus status) {
1496     if (fEncodingSupport != null) {
1497       String message = fEncodingSupport.getStatusBanner(status);
1498       if (message != null)
1499         return message;
1500     }
1501     return super.getStatusBanner(status);
1502   }
1503
1504   /*
1505    * @see StatusTextEditor#getStatusMessage(IStatus)
1506    */
1507   protected String getStatusMessage(IStatus status) {
1508     if (fEncodingSupport != null) {
1509       String message = fEncodingSupport.getStatusMessage(status);
1510       if (message != null)
1511         return message;
1512     }
1513     return super.getStatusMessage(status);
1514   }
1515   /** The <code>PHPEditor</code> implementation of this 
1516    * <code>AbstractTextEditor</code> method performs sets the 
1517    * input of the outline page after AbstractTextEditor has set input.
1518    */
1519   //  protected void doSetInput(IEditorInput input) throws CoreException {
1520   //    super.doSetInput(input);
1521   //
1522   //    if (fEncodingSupport != null)
1523   //      fEncodingSupport.reset();
1524   //    if (fOutlinePage != null)
1525   //      fOutlinePage.setInput(input);
1526   //    //              setOutlinePageInput(fOutlinePage, input);
1527   //  } 
1528   protected void doSetInput(IEditorInput input) throws CoreException {
1529     super.doSetInput(input);
1530     if (fEncodingSupport != null)
1531       fEncodingSupport.reset();
1532     setOutlinePageInput(fOutlinePage, input);
1533   }
1534   /*
1535    * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
1536    */
1537   //  public Object getViewPartInput() {
1538   //    return getEditorInput().getAdapter(IFile.class);
1539   //  }
1540
1541   /** The <code>PHPEditor</code> implementation of this 
1542    * <code>AbstractTextEditor</code> method adds any 
1543    * PHPEditor specific entries.
1544    */
1545   public void editorContextMenuAboutToShow(MenuManager menu) {
1546     super.editorContextMenuAboutToShow(menu);
1547     menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO, new Separator(IContextMenuConstants.GROUP_OPEN));
1548     menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(IContextMenuConstants.GROUP_SHOW));
1549
1550     ActionContext context = new ActionContext(getSelectionProvider().getSelection());
1551     fContextMenuGroup.setContext(context);
1552     fContextMenuGroup.fillContextMenu(menu);
1553     fContextMenuGroup.setContext(null);
1554     //    addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
1555     //
1556     //    ActionContext context =
1557     //      new ActionContext(getSelectionProvider().getSelection());
1558     //    fContextMenuGroup.setContext(context);
1559     //    fContextMenuGroup.fillContextMenu(menu);
1560     //    fContextMenuGroup.setContext(null);
1561   }
1562
1563   /**
1564    * Creates the outline page used with this editor.
1565    */
1566   protected JavaOutlinePage createOutlinePage() {
1567
1568     //    AbstractContentOutlinePage page = new PHPContentOutlinePage(getDocumentProvider(), this);
1569     //
1570     //    page.addSelectionChangedListener(fSelectionChangedListener);
1571     //    //    setOutlinePageInput(page, getEditorInput());
1572     //    if (getEditorInput() != null)
1573     //      fOutlinePage.setInput(getEditorInput());
1574     //
1575     //    return page;
1576     JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
1577
1578     page.addSelectionChangedListener(fSelectionChangedListener);
1579     setOutlinePageInput(page, getEditorInput());
1580
1581     return page;
1582   }
1583
1584   /**
1585    * Informs the editor that its outliner has been closed.
1586    */
1587   public void outlinePageClosed() {
1588     if (fOutlinePage != null) {
1589       fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
1590       fOutlinePage = null;
1591       resetHighlightRange();
1592     }
1593   }
1594   /**
1595    * Synchronizes the outliner selection with the actual cursor
1596    * position in the editor.
1597    */
1598   public void synchronizeOutlinePageSelection() {
1599
1600     //          if (isEditingScriptRunning())
1601     //                  return;
1602
1603     ISourceViewer sourceViewer = getSourceViewer();
1604     if (sourceViewer == null || fOutlinePage == null)
1605       return;
1606
1607     StyledText styledText = sourceViewer.getTextWidget();
1608     if (styledText == null)
1609       return;
1610
1611     int caret = 0;
1612     if (sourceViewer instanceof ITextViewerExtension3) {
1613       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
1614       caret = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
1615     } else {
1616       int offset = sourceViewer.getVisibleRegion().getOffset();
1617       caret = offset + styledText.getCaretOffset();
1618     }
1619
1620     IJavaElement element = getElementAt(caret);
1621     if (element instanceof ISourceReference) {
1622       fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
1623       fOutlinePage.select((ISourceReference) element);
1624       fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
1625     }
1626   }
1627
1628   protected void setSelection(ISourceReference reference, boolean moveCursor) {
1629
1630     ISelection selection = getSelectionProvider().getSelection();
1631     if (selection instanceof TextSelection) {
1632       TextSelection textSelection = (TextSelection) selection;
1633       if (textSelection.getOffset() != 0 || textSelection.getLength() != 0)
1634         markInNavigationHistory();
1635     }
1636
1637     if (reference != null) {
1638
1639       StyledText textWidget = null;
1640
1641       ISourceViewer sourceViewer = getSourceViewer();
1642       if (sourceViewer != null)
1643         textWidget = sourceViewer.getTextWidget();
1644
1645       if (textWidget == null)
1646         return;
1647
1648       try {
1649
1650         ISourceRange range = reference.getSourceRange();
1651         if (range == null)
1652           return;
1653
1654         int offset = range.getOffset();
1655         int length = range.getLength();
1656
1657         if (offset < 0 || length < 0)
1658           return;
1659
1660         textWidget.setRedraw(false);
1661
1662         setHighlightRange(offset, length, moveCursor);
1663
1664         if (!moveCursor)
1665           return;
1666
1667         offset = -1;
1668         length = -1;
1669
1670         if (reference instanceof IMember) {
1671           range = ((IMember) reference).getNameRange();
1672           if (range != null) {
1673             offset = range.getOffset();
1674             length = range.getLength();
1675           }
1676         }
1677         //                                      else if (reference instanceof IImportDeclaration) {
1678         //                                              String name= ((IImportDeclaration) reference).getElementName();
1679         //                                              if (name != null && name.length() > 0) {
1680         //                                                      String content= reference.getSource();
1681         //                                                      if (content != null) {
1682         //                                                              offset= range.getOffset() + content.indexOf(name);
1683         //                                                              length= name.length();
1684         //                                                      }
1685         //                                              }
1686         //                                      } else if (reference instanceof IPackageDeclaration) {
1687         //                                              String name= ((IPackageDeclaration) reference).getElementName();
1688         //                                              if (name != null && name.length() > 0) {
1689         //                                                      String content= reference.getSource();
1690         //                                                      if (content != null) {
1691         //                                                              offset= range.getOffset() + content.indexOf(name);
1692         //                                                              length= name.length();
1693         //                                                      }
1694         //                                              }
1695         //                                      }
1696
1697         if (offset > -1 && length > 0) {
1698           sourceViewer.revealRange(offset, length);
1699           sourceViewer.setSelectedRange(offset, length);
1700         }
1701
1702       } catch (JavaModelException x) {
1703       } catch (IllegalArgumentException x) {
1704       } finally {
1705         if (textWidget != null)
1706           textWidget.setRedraw(true);
1707       }
1708
1709     } else if (moveCursor) {
1710       resetHighlightRange();
1711     }
1712
1713     markInNavigationHistory();
1714   }
1715
1716   public void setSelection(IJavaElement element) {
1717
1718     if (element == null || element instanceof ICompilationUnit) { // || element instanceof IClassFile) {
1719       /*
1720        * If the element is an ICompilationUnit this unit is either the input
1721        * of this editor or not being displayed. In both cases, nothing should
1722        * happened. (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
1723        */
1724       return;
1725     }
1726
1727     IJavaElement corresponding = getCorrespondingElement(element);
1728     if (corresponding instanceof ISourceReference) {
1729       ISourceReference reference = (ISourceReference) corresponding;
1730       // set hightlight range
1731       setSelection(reference, true);
1732       // set outliner selection
1733       if (fOutlinePage != null) {
1734         fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
1735         fOutlinePage.select(reference);
1736         fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
1737       }
1738     }
1739   }
1740
1741         public synchronized void editingScriptStarted() {
1742                 ++ fIgnoreOutlinePageSelection;
1743         }
1744         
1745         public synchronized void editingScriptEnded() {
1746                 -- fIgnoreOutlinePageSelection;
1747         }
1748         
1749         public synchronized boolean isEditingScriptRunning() {
1750                 return (fIgnoreOutlinePageSelection > 0);
1751         }
1752         
1753   /** The <code>PHPEditor</code> implementation of this 
1754    * <code>AbstractTextEditor</code> method performs gets
1755    * the java content outline page if request is for a an 
1756    * outline page.
1757    */
1758   public Object getAdapter(Class required) {
1759
1760     if (IContentOutlinePage.class.equals(required)) {
1761       if (fOutlinePage == null)
1762         fOutlinePage = createOutlinePage();
1763       return fOutlinePage;
1764     }
1765
1766     if (IEncodingSupport.class.equals(required))
1767       return fEncodingSupport;
1768
1769     if (required == IShowInTargetList.class) {
1770       return new IShowInTargetList() {
1771         public String[] getShowInTargetIds() {
1772           return new String[] { JavaUI.ID_PACKAGES, IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
1773         }
1774
1775       };
1776     }
1777
1778     return super.getAdapter(required);
1779   }
1780   //  public Object getAdapter(Class required) {
1781   //    if (IContentOutlinePage.class.equals(required)) {
1782   //      if (fOutlinePage == null) {
1783   //        fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
1784   //        if (getEditorInput() != null)
1785   //          fOutlinePage.setInput(getEditorInput());
1786   //      }
1787   //      return fOutlinePage;
1788   //    }
1789   //
1790   //    if (IEncodingSupport.class.equals(required))
1791   //      return fEncodingSupport;
1792   //
1793   //    return super.getAdapter(required);
1794   //  }
1795
1796   protected void doSelectionChanged(SelectionChangedEvent event) {
1797     ISourceReference reference = null;
1798
1799     ISelection selection = event.getSelection();
1800     Iterator iter = ((IStructuredSelection) selection).iterator();
1801     while (iter.hasNext()) {
1802       Object o = iter.next();
1803       if (o instanceof ISourceReference) {
1804         reference = (ISourceReference) o;
1805         break;
1806       }
1807     }
1808
1809     if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
1810       PHPeclipsePlugin.getActivePage().bringToTop(this);
1811
1812     try {
1813       editingScriptStarted();
1814       setSelection(reference, !isActivePart());
1815     } finally {
1816       editingScriptEnded();
1817     }
1818   }
1819   /*
1820          * @see AbstractTextEditor#adjustHighlightRange(int, int)
1821          */
1822   protected void adjustHighlightRange(int offset, int length) {
1823
1824     try {
1825
1826       IJavaElement element = getElementAt(offset);
1827       while (element instanceof ISourceReference) {
1828         ISourceRange range = ((ISourceReference) element).getSourceRange();
1829         if (offset < range.getOffset() + range.getLength() && range.getOffset() < offset + length) {
1830           setHighlightRange(range.getOffset(), range.getLength(), true);
1831           if (fOutlinePage != null) {
1832             fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
1833             fOutlinePage.select((ISourceReference) element);
1834             fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
1835           }
1836           return;
1837         }
1838         element = element.getParent();
1839       }
1840
1841     } catch (JavaModelException x) {
1842       PHPeclipsePlugin.log(x.getStatus());
1843     }
1844
1845     resetHighlightRange();
1846   }
1847   protected boolean isActivePart() {
1848     IWorkbenchWindow window = getSite().getWorkbenchWindow();
1849     IPartService service = window.getPartService();
1850     IWorkbenchPart part = service.getActivePart();
1851     return part != null && part.equals(this);
1852   }
1853
1854
1855   //  public void openContextHelp() {
1856   //    IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
1857   //    ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
1858   //    int pos = selection.getOffset();
1859   //    String word = getFunctionName(doc, pos);
1860   //    openContextHelp(word);
1861   //  }
1862   //
1863   //  private void openContextHelp(String word) {
1864   //    open(word);
1865   //  }
1866   //
1867   //  public static void open(String word) {
1868   //    IHelp help = WorkbenchHelp.getHelpSupport();
1869   //    if (help != null) {
1870   //      IHelpResource helpResource = new PHPFunctionHelpResource(word);
1871   //      WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
1872   //    } else {
1873   //      //   showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
1874   //    }
1875   //  }
1876
1877   //    private String getFunctionName(IDocument doc, int pos) {
1878   //            Point word = PHPWordExtractor.findWord(doc, pos);
1879   //            if (word != null) {
1880   //                    try {
1881   //                            return doc.get(word.x, word.y).replace('_', '-');
1882   //                    } catch (BadLocationException e) {
1883   //                    }
1884   //            }
1885   //            return "";
1886   //    }
1887
1888   /*
1889    * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1890    */
1891   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1892
1893     try {
1894
1895       ISourceViewer sourceViewer = getSourceViewer();
1896       if (sourceViewer == null)
1897         return;
1898
1899       String property = event.getProperty();
1900
1901       if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
1902         Object value = event.getNewValue();
1903         if (value instanceof Integer) {
1904           sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
1905         } else if (value instanceof String) {
1906           sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
1907         }
1908         return;
1909       }
1910       
1911 //      if (OVERVIEW_RULER.equals(property)) {
1912 //        if (isOverviewRulerVisible())
1913 //          showOverviewRuler();
1914 //        else
1915 //          hideOverviewRuler();
1916 //        return;
1917 //      }
1918
1919 //      if (LINE_NUMBER_RULER.equals(property)) {
1920 //        if (isLineNumberRulerVisible())
1921 //          showLineNumberRuler();
1922 //        else
1923 //          hideLineNumberRuler();
1924 //        return;
1925 //      }
1926
1927 //      if (fLineNumberRulerColumn != null
1928 //        && (LINE_NUMBER_COLOR.equals(property) || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
1929 //
1930 //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
1931 //      }
1932
1933       if (isJavaEditorHoverProperty(property))
1934         updateHoverBehavior();
1935
1936       if (BROWSER_LIKE_LINKS.equals(property)) {
1937         if (isBrowserLikeLinks())
1938           enableBrowserLikeLinks();
1939         else
1940           disableBrowserLikeLinks();
1941         return;
1942       }
1943
1944 //      if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE.equals(property)) {
1945 //              if ((event.getNewValue() instanceof Boolean) && ((Boolean)event.getNewValue()).booleanValue())
1946 //                      fEditorSelectionChangedListener.selectionChanged();
1947 //              return;
1948 //      }
1949         
1950         if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE.equals(property)) {
1951                 if (event.getNewValue() instanceof Boolean) {
1952                         Boolean disable= (Boolean) event.getNewValue();
1953                         configureInsertMode(OVERWRITE, !disable.booleanValue());
1954                 }
1955         }
1956         
1957 //      if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
1958 //              if (event.getNewValue() instanceof Boolean) {
1959 //                      boolean markOccurrenceAnnotations= ((Boolean)event.getNewValue()).booleanValue();
1960 //                      if (markOccurrenceAnnotations != fMarkOccurrenceAnnotations) {
1961 //                              fMarkOccurrenceAnnotations= markOccurrenceAnnotations;
1962 //                              if (!fMarkOccurrenceAnnotations)
1963 //                                      uninstallOccurrencesFinder();
1964 //                              else
1965 //                                      installOccurrencesFinder();
1966 //                      }
1967 //              }
1968 //      }
1969 //      if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
1970 //              if (event.getNewValue() instanceof Boolean) {
1971 //                      boolean stickyOccurrenceAnnotations= ((Boolean)event.getNewValue()).booleanValue();
1972 //                      if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations) {
1973 //                              fStickyOccurrenceAnnotations= stickyOccurrenceAnnotations;
1974 ////                            if (!fMarkOccurrenceAnnotations)
1975 ////                                    uninstallOccurrencesFinder();
1976 ////                            else
1977 ////                                    installOccurrencesFinder();
1978 //                      }
1979 //              }
1980 //      }
1981         
1982     } finally {
1983       super.handlePreferenceStoreChanged(event);
1984     }
1985   }
1986
1987   //  /*
1988   //     * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
1989   //     */
1990   //  protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
1991   //
1992   //    try {
1993   //
1994   //      ISourceViewer sourceViewer = getSourceViewer();
1995   //      if (sourceViewer == null)
1996   //        return;
1997   //
1998   //      String property = event.getProperty();
1999   //
2000   //      //      if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
2001   //      //        Object value= event.getNewValue();
2002   //      //        if (value instanceof Integer) {
2003   //      //          sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
2004   //      //        } else if (value instanceof String) {
2005   //      //          sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
2006   //      //        }
2007   //      //        return;
2008   //      //      }
2009   //
2010   //      if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
2011   //        if (isLineNumberRulerVisible())
2012   //          showLineNumberRuler();
2013   //        else
2014   //          hideLineNumberRuler();
2015   //        return;
2016   //      }
2017   //
2018   //      if (fLineNumberRulerColumn != null
2019   //        && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
2020   //          || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
2021   //          || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
2022   //
2023   //        initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2024   //      }
2025   //
2026   //    } finally {
2027   //      super.handlePreferenceStoreChanged(event);
2028   //    }
2029   //  }
2030
2031   //  private boolean isJavaEditorHoverProperty(String property) {
2032   //    return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
2033   //      || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
2034   //      || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
2035   //      || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
2036   //      || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
2037   //      || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
2038   //      || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
2039   //      || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
2040   //  }
2041
2042   /**
2043    * Shows the line number ruler column.
2044    */
2045 //  private void showLineNumberRuler() {
2046 //    IVerticalRuler v = getVerticalRuler();
2047 //    if (v instanceof CompositeRuler) {
2048 //      CompositeRuler c = (CompositeRuler) v;
2049 //      c.addDecorator(1, createLineNumberRulerColumn());
2050 //    }
2051 //  }
2052   private boolean isJavaEditorHoverProperty(String property) {
2053     return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
2054   }
2055
2056   /**
2057          * Return whether the browser like links should be enabled
2058          * according to the preference store settings.
2059          * @return <code>true</code> if the browser like links should be enabled
2060          */
2061   private boolean isBrowserLikeLinks() {
2062     IPreferenceStore store = getPreferenceStore();
2063     return store.getBoolean(BROWSER_LIKE_LINKS);
2064   }
2065
2066   /**
2067    * Enables browser like links.
2068    */
2069   private void enableBrowserLikeLinks() {
2070     if (fMouseListener == null) {
2071       fMouseListener = new MouseClickListener();
2072       fMouseListener.install();
2073     }
2074   }
2075
2076   /**
2077    * Disables browser like links.
2078    */
2079   private void disableBrowserLikeLinks() {
2080     if (fMouseListener != null) {
2081       fMouseListener.uninstall();
2082       fMouseListener = null;
2083     }
2084   }
2085   /**
2086    * Handles a property change event describing a change
2087    * of the java core's preferences and updates the preference
2088    * related editor properties.
2089    * 
2090    * @param event the property change event
2091    */
2092   protected void handlePreferencePropertyChanged(org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
2093     if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
2094       ISourceViewer sourceViewer = getSourceViewer();
2095       if (sourceViewer != null
2096         && affectsTextPresentation(new PropertyChangeEvent(event.getSource(), event.getProperty(), event.getOldValue(), event.getNewValue())))
2097         sourceViewer.invalidateTextPresentation();
2098     }
2099   }
2100
2101   /**
2102    * Return whether the line number ruler column should be 
2103    * visible according to the preference store settings.
2104    * @return <code>true</code> if the line numbers should be visible
2105    */
2106 //  protected boolean isLineNumberRulerVisible() {
2107 //    IPreferenceStore store = getPreferenceStore();
2108 //    return store.getBoolean(LINE_NUMBER_RULER);
2109 //  }
2110   /**
2111    * Hides the line number ruler column.
2112    */
2113 //  private void hideLineNumberRuler() {
2114 //    IVerticalRuler v = getVerticalRuler();
2115 //    if (v instanceof CompositeRuler) {
2116 //      CompositeRuler c = (CompositeRuler) v;
2117 //      try {
2118 //        c.removeDecorator(1);
2119 //      } catch (Throwable e) {
2120 //      }
2121 //    }
2122 //  }
2123
2124         /*
2125          * @see AbstractTextEditor#handleCursorPositionChanged()
2126          */
2127         protected void handleCursorPositionChanged() {
2128                 super.handleCursorPositionChanged();
2129                 if (!isEditingScriptRunning() && fUpdater != null)
2130                         fUpdater.post();
2131         }
2132         
2133   /**
2134    * Initializes the given line number ruler column from the preference store.
2135    * @param rulerColumn the ruler column to be initialized
2136    */
2137 //  protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
2138 //    JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
2139 //    IColorManager manager = textTools.getColorManager();
2140 //
2141 //    IPreferenceStore store = getPreferenceStore();
2142 //    if (store != null) {
2143 //
2144 //      RGB rgb = null;
2145 //      // foreground color
2146 //      if (store.contains(LINE_NUMBER_COLOR)) {
2147 //        if (store.isDefault(LINE_NUMBER_COLOR))
2148 //          rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
2149 //        else
2150 //          rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
2151 //      }
2152 //      rulerColumn.setForeground(manager.getColor(rgb));
2153 //
2154 //      rgb = null;
2155 //      // background color
2156 //      if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
2157 //        if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
2158 //          if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
2159 //            rgb = PreferenceConverter.getDefaultColor(store, PREFERENCE_COLOR_BACKGROUND);
2160 //          else
2161 //            rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
2162 //        }
2163 //      }
2164 //      rulerColumn.setBackground(manager.getColor(rgb));
2165 //    }
2166 //  }
2167
2168   /**
2169    * Creates a new line number ruler column that is appropriately initialized.
2170    */
2171 //  protected IVerticalRulerColumn createLineNumberRulerColumn() {
2172 //    fLineNumberRulerColumn = new LineNumberRulerColumn();
2173 //    initializeLineNumberRulerColumn(fLineNumberRulerColumn);
2174 //    return fLineNumberRulerColumn;
2175 //  }
2176
2177   /*
2178    * @see AbstractTextEditor#createVerticalRuler()
2179    */
2180 //  protected IVerticalRuler createVerticalRuler() {
2181 //    CompositeRuler ruler = new CompositeRuler();
2182 //    ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
2183 //    if (isLineNumberRulerVisible())
2184 //      ruler.addDecorator(1, createLineNumberRulerColumn());
2185 //    return ruler;
2186 //  }
2187
2188   private static IRegion getSignedSelection(ITextViewer viewer) {
2189
2190     StyledText text = viewer.getTextWidget();
2191     int caretOffset = text.getCaretOffset();
2192     Point selection = text.getSelection();
2193
2194     // caret left
2195     int offset, length;
2196     if (caretOffset == selection.x) {
2197       offset = selection.y;
2198       length = selection.x - selection.y;
2199
2200       // caret right
2201     } else {
2202       offset = selection.x;
2203       length = selection.y - selection.x;
2204     }
2205
2206     return new Region(offset, length);
2207   }
2208
2209   /** Preference key for matching brackets */
2210   protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
2211   /** Preference key for matching brackets color */
2212   protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
2213   /** Preference key for highlighting current line */
2214   protected final static String CURRENT_LINE = PreferenceConstants.EDITOR_CURRENT_LINE;
2215   /** Preference key for highlight color of current line */
2216   protected final static String CURRENT_LINE_COLOR = PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
2217   /** Preference key for showing print marging ruler */
2218   protected final static String PRINT_MARGIN = PreferenceConstants.EDITOR_PRINT_MARGIN;
2219   /** Preference key for print margin ruler color */
2220   protected final static String PRINT_MARGIN_COLOR = PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
2221   /** Preference key for print margin ruler column */
2222   protected final static String PRINT_MARGIN_COLUMN = PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
2223   /** Preference key for error indication */
2224 //  protected final static String ERROR_INDICATION = PreferenceConstants.EDITOR_PROBLEM_INDICATION;
2225   /** Preference key for error color */
2226 //  protected final static String ERROR_INDICATION_COLOR = PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
2227   /** Preference key for warning indication */
2228 //  protected final static String WARNING_INDICATION = PreferenceConstants.EDITOR_WARNING_INDICATION;
2229   /** Preference key for warning color */
2230 //  protected final static String WARNING_INDICATION_COLOR = PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
2231   /** Preference key for task indication */
2232   protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
2233   /** Preference key for task color */
2234   protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
2235   /** Preference key for bookmark indication */
2236   protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
2237   /** Preference key for bookmark color */
2238   protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
2239   /** Preference key for search result indication */
2240   protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
2241   /** Preference key for search result color */
2242   protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
2243   /** Preference key for unknown annotation indication */
2244   protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
2245   /** Preference key for unknown annotation color */
2246   protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
2247   /** Preference key for shwoing the overview ruler */
2248   protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
2249   /** Preference key for error indication in overview ruler */
2250   protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
2251   /** Preference key for warning indication in overview ruler */
2252   protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
2253   /** Preference key for task indication in overview ruler */
2254   protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
2255   /** Preference key for bookmark indication in overview ruler */
2256   protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
2257   /** Preference key for search result indication in overview ruler */
2258   protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
2259   /** Preference key for unknown annotation indication in overview ruler */
2260   protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
2261   //            /** Preference key for compiler task tags */
2262   //            private final static String COMPILER_TASK_TAGS= JavaCore.COMPILER_TASK_TAGS;
2263   /** Preference key for browser like links */
2264   private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
2265   /** Preference key for key modifier of browser like links */
2266   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
2267   /**
2268    * Preference key for key modifier mask of browser like links.
2269    * The value is only used if the value of <code>EDITOR_BROWSER_LIKE_LINKS</code>
2270    * cannot be resolved to valid SWT modifier bits.
2271    * 
2272    * @since 2.1.1
2273    */
2274   private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
2275
2276   private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
2277
2278   private static boolean isBracket(char character) {
2279     for (int i = 0; i != BRACKETS.length; ++i)
2280       if (character == BRACKETS[i])
2281         return true;
2282     return false;
2283   }
2284
2285   private static boolean isSurroundedByBrackets(IDocument document, int offset) {
2286     if (offset == 0 || offset == document.getLength())
2287       return false;
2288
2289     try {
2290       return isBracket(document.getChar(offset - 1)) && isBracket(document.getChar(offset));
2291
2292     } catch (BadLocationException e) {
2293       return false;
2294     }
2295   }
2296
2297 //  protected void configureSourceViewerDecorationSupport() {
2298 //
2299 //    fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
2300 //
2301 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2302 //      AnnotationType.UNKNOWN,
2303 //      UNKNOWN_INDICATION_COLOR,
2304 //      UNKNOWN_INDICATION,
2305 //      UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
2306 //      0);
2307 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2308 //      AnnotationType.BOOKMARK,
2309 //      BOOKMARK_INDICATION_COLOR,
2310 //      BOOKMARK_INDICATION,
2311 //      BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
2312 //      1);
2313 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2314 //      AnnotationType.TASK,
2315 //      TASK_INDICATION_COLOR,
2316 //      TASK_INDICATION,
2317 //      TASK_INDICATION_IN_OVERVIEW_RULER, 
2318 //      2);
2319 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2320 //      AnnotationType.SEARCH,
2321 //      SEARCH_RESULT_INDICATION_COLOR,
2322 //      SEARCH_RESULT_INDICATION,
2323 //      SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
2324 //      3);
2325 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2326 //      AnnotationType.WARNING,
2327 //      WARNING_INDICATION_COLOR,
2328 //      WARNING_INDICATION,
2329 //      WARNING_INDICATION_IN_OVERVIEW_RULER,
2330 //      4);
2331 //    fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
2332 //      AnnotationType.ERROR,
2333 //      ERROR_INDICATION_COLOR,
2334 //      ERROR_INDICATION,
2335 //      ERROR_INDICATION_IN_OVERVIEW_RULER,
2336 //      5);
2337 //
2338 //    fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE, CURRENT_LINE_COLOR);
2339 //    fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN, PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
2340 //    fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS, MATCHING_BRACKETS_COLOR);
2341 //
2342 //    fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
2343 //
2344 //  }
2345   /**
2346     * Jumps to the matching bracket.
2347     */
2348   public void gotoMatchingBracket() {
2349
2350     ISourceViewer sourceViewer = getSourceViewer();
2351     IDocument document = sourceViewer.getDocument();
2352     if (document == null)
2353       return;
2354
2355     IRegion selection = getSignedSelection(sourceViewer);
2356
2357     int selectionLength = Math.abs(selection.getLength());
2358     if (selectionLength > 1) {
2359       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$               
2360       sourceViewer.getTextWidget().getDisplay().beep();
2361       return;
2362     }
2363
2364     // #26314
2365     int sourceCaretOffset = selection.getOffset() + selection.getLength();
2366     if (isSurroundedByBrackets(document, sourceCaretOffset))
2367       sourceCaretOffset -= selection.getLength();
2368
2369     IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
2370     if (region == null) {
2371       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$              
2372       sourceViewer.getTextWidget().getDisplay().beep();
2373       return;
2374     }
2375
2376     int offset = region.getOffset();
2377     int length = region.getLength();
2378
2379     if (length < 1)
2380       return;
2381
2382     int anchor = fBracketMatcher.getAnchor();
2383     int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
2384
2385     boolean visible = false;
2386     if (sourceViewer instanceof ITextViewerExtension3) {
2387       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
2388       visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
2389     } else {
2390       IRegion visibleRegion = sourceViewer.getVisibleRegion();
2391       visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
2392     }
2393
2394     if (!visible) {
2395       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$          
2396       sourceViewer.getTextWidget().getDisplay().beep();
2397       return;
2398     }
2399
2400     if (selection.getLength() < 0)
2401       targetOffset -= selection.getLength();
2402
2403     sourceViewer.setSelectedRange(targetOffset, selection.getLength());
2404     sourceViewer.revealRange(targetOffset, selection.getLength());
2405   }
2406   /**
2407      * Ses the given message as error message to this editor's status line.
2408      * @param msg message to be set
2409      */
2410   protected void setStatusLineErrorMessage(String msg) {
2411     IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
2412     if (statusLine != null)
2413       statusLine.setMessage(true, msg, null);
2414   }
2415
2416   /**
2417      * Returns a segmentation of the line of the given document appropriate for bidi rendering.
2418      * The default implementation returns only the string literals of a php code line as segments.
2419      * 
2420      * @param document the document
2421      * @param lineOffset the offset of the line
2422      * @return the line's bidi segmentation
2423      * @throws BadLocationException in case lineOffset is not valid in document
2424      */
2425   public static int[] getBidiLineSegments(IDocument document, int lineOffset) throws BadLocationException {
2426
2427     IRegion line = document.getLineInformationOfOffset(lineOffset);
2428     ITypedRegion[] linePartitioning = document.computePartitioning(lineOffset, line.getLength());
2429
2430     List segmentation = new ArrayList();
2431     for (int i = 0; i < linePartitioning.length; i++) {
2432       if (IPHPPartitions.PHP_STRING.equals(linePartitioning[i].getType()))
2433         segmentation.add(linePartitioning[i]);
2434     }
2435
2436     if (segmentation.size() == 0)
2437       return null;
2438
2439     int size = segmentation.size();
2440     int[] segments = new int[size * 2 + 1];
2441
2442     int j = 0;
2443     for (int i = 0; i < size; i++) {
2444       ITypedRegion segment = (ITypedRegion) segmentation.get(i);
2445
2446       if (i == 0)
2447         segments[j++] = 0;
2448
2449       int offset = segment.getOffset() - lineOffset;
2450       if (offset > segments[j - 1])
2451         segments[j++] = offset;
2452
2453       if (offset + segment.getLength() >= line.getLength())
2454         break;
2455
2456       segments[j++] = offset + segment.getLength();
2457     }
2458
2459     if (j < segments.length) {
2460       int[] result = new int[j];
2461       System.arraycopy(segments, 0, result, 0, j);
2462       segments = result;
2463     }
2464
2465     return segments;
2466   }
2467   /**
2468      * Returns a segmentation of the given line appropriate for bidi rendering. The default
2469      * implementation returns only the string literals of a php code line as segments.
2470      * 
2471      * @param lineOffset the offset of the line
2472      * @param line the content of the line
2473      * @return the line's bidi segmentation
2474      */
2475   protected int[] getBidiLineSegments(int lineOffset, String line) {
2476     IDocumentProvider provider = getDocumentProvider();
2477     if (provider != null && line != null && line.length() > 0) {
2478       IDocument document = provider.getDocument(getEditorInput());
2479       if (document != null)
2480         try {
2481           return getBidiLineSegments(document, lineOffset);
2482         } catch (BadLocationException x) {
2483           // ignore
2484         }
2485     }
2486     return null;
2487   }
2488
2489   /*
2490    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
2491    */
2492   //  protected final ISourceViewer createSourceViewer(
2493   //    Composite parent,
2494   //    IVerticalRuler ruler,
2495   //    int styles) {
2496   //    ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
2497   //    StyledText text = viewer.getTextWidget();
2498   //    text.addBidiSegmentListener(new BidiSegmentListener() {
2499   //      public void lineGetSegments(BidiSegmentEvent event) {
2500   //        event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
2501   //      }
2502   //    });
2503   //    //   JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
2504   //    return viewer;
2505   //  }
2506   
2507   public final ISourceViewer getViewer() {
2508         return getSourceViewer();
2509   }
2510   
2511   protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler verticalRuler, int styles) {
2512         ISourceViewer viewer= createJavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles);
2513         
2514         StyledText text= viewer.getTextWidget();
2515         text.addBidiSegmentListener(new  BidiSegmentListener() {
2516                 public void lineGetSegments(BidiSegmentEvent event) {
2517                         event.segments= getBidiLineSegments(event.lineOffset, event.lineText);
2518                 }
2519         });
2520         
2521 //      JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
2522
2523         // ensure source viewer decoration support has been created and configured
2524         getSourceViewerDecorationSupport(viewer);                               
2525         
2526         return viewer;
2527         
2528 //    ISharedTextColors sharedColors = PHPeclipsePlugin.getDefault().getJavaTextTools().getColorManager();
2529 //
2530 //    fOverviewRuler = new OverviewRuler(fAnnotationAccess, VERTICAL_RULER_WIDTH, sharedColors);
2531 //    fOverviewRuler.addHeaderAnnotationType(AnnotationType.WARNING);
2532 //    fOverviewRuler.addHeaderAnnotationType(AnnotationType.ERROR);
2533 //
2534 //    ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler, fOverviewRuler, isOverviewRulerVisible(), styles);
2535 //
2536 //    StyledText text = viewer.getTextWidget();
2537 //    text.addBidiSegmentListener(new BidiSegmentListener() {
2538 //      public void lineGetSegments(BidiSegmentEvent event) {
2539 //        event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
2540 //      }
2541 //    });
2542 //
2543 //    //                JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
2544 //
2545 //    fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(viewer, fOverviewRuler, fAnnotationAccess, sharedColors);
2546 //    configureSourceViewerDecorationSupport();
2547 //
2548 //    return viewer;
2549   }
2550
2551 //  protected void showOverviewRuler() {
2552 //    if (fOverviewRuler != null) {
2553 //      if (getSourceViewer() instanceof ISourceViewerExtension) {
2554 //        ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(true);
2555 //        fSourceViewerDecorationSupport.updateOverviewDecorations();
2556 //      }
2557 //    }
2558 //  }
2559 //
2560 //  protected void hideOverviewRuler() {
2561 //    if (getSourceViewer() instanceof ISourceViewerExtension) {
2562 //      fSourceViewerDecorationSupport.hideAnnotationOverview();
2563 //      ((ISourceViewerExtension) getSourceViewer()).showAnnotationsOverview(false);
2564 //    }
2565 //  }
2566
2567 //  protected boolean isOverviewRulerVisible() {
2568 //    IPreferenceStore store = getPreferenceStore();
2569 //    return store.getBoolean(OVERVIEW_RULER);
2570 //  }
2571   /*
2572    * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
2573    */
2574 //  protected ISourceViewer createJavaSourceViewer(
2575 //    Composite parent,
2576 //    IVerticalRuler ruler,
2577 //    IOverviewRuler overviewRuler,
2578 //    boolean isOverviewRulerVisible,
2579 //    int styles) {
2580 //    return new SourceViewer(parent, ruler, overviewRuler, isOverviewRulerVisible(), styles);
2581 //  }
2582   
2583   /*
2584          * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler, int)
2585          */
2586         protected ISourceViewer createJavaSourceViewer(Composite parent, IVerticalRuler verticalRuler, IOverviewRuler overviewRuler, boolean isOverviewRulerVisible, int styles) {
2587                 return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(), isOverviewRulerVisible(), styles);
2588         }
2589   /*
2590    * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
2591    */
2592   protected boolean affectsTextPresentation(PropertyChangeEvent event) {
2593     JavaTextTools textTools = PHPeclipsePlugin.getDefault().getJavaTextTools();
2594     return textTools.affectsBehavior(event);
2595   }
2596
2597   /**
2598    * Jumps to the error next according to the given direction.
2599    */
2600   public void gotoError(boolean forward) {
2601
2602     ISelectionProvider provider = getSelectionProvider();
2603
2604     ITextSelection s = (ITextSelection) provider.getSelection();
2605     Position errorPosition = new Position(0, 0);
2606     IJavaAnnotation nextError = getNextError(s.getOffset(), forward, errorPosition);
2607
2608     if (nextError != null) {
2609
2610       IMarker marker = null;
2611       if (nextError instanceof MarkerAnnotation)
2612         marker = ((MarkerAnnotation) nextError).getMarker();
2613       else {
2614         Iterator e = nextError.getOverlaidIterator();
2615         if (e != null) {
2616           while (e.hasNext()) {
2617             Object o = e.next();
2618             if (o instanceof MarkerAnnotation) {
2619               marker = ((MarkerAnnotation) o).getMarker();
2620               break;
2621             }
2622           }
2623         }
2624       }
2625
2626       if (marker != null) {
2627         IWorkbenchPage page = getSite().getPage();
2628         IViewPart view = view = page.findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
2629         if (view instanceof TaskList) {
2630           StructuredSelection ss = new StructuredSelection(marker);
2631           ((TaskList) view).setSelection(ss, true);
2632         }
2633       }
2634
2635       selectAndReveal(errorPosition.getOffset(), errorPosition.getLength());
2636 //      setStatusLineErrorMessage(nextError.getMessage());
2637
2638     } else {
2639
2640       setStatusLineErrorMessage(null);
2641
2642     }
2643   }
2644
2645   private IJavaAnnotation getNextError(int offset, boolean forward, Position errorPosition) {
2646
2647     IJavaAnnotation nextError = null;
2648     Position nextErrorPosition = null;
2649
2650     IDocument document = getDocumentProvider().getDocument(getEditorInput());
2651     int endOfDocument = document.getLength();
2652     int distance = 0;
2653
2654     IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput());
2655     Iterator e = new JavaAnnotationIterator(model, false);
2656     while (e.hasNext()) {
2657
2658       IJavaAnnotation a = (IJavaAnnotation) e.next();
2659       if (a.hasOverlay() || !a.isProblem())
2660         continue;
2661
2662       Position p = model.getPosition((Annotation) a);
2663       if (!p.includes(offset)) {
2664
2665         int currentDistance = 0;
2666
2667         if (forward) {
2668           currentDistance = p.getOffset() - offset;
2669           if (currentDistance < 0)
2670             currentDistance = endOfDocument - offset + p.getOffset();
2671         } else {
2672           currentDistance = offset - p.getOffset();
2673           if (currentDistance < 0)
2674             currentDistance = offset + endOfDocument - p.getOffset();
2675         }
2676
2677         if (nextError == null || currentDistance < distance) {
2678           distance = currentDistance;
2679           nextError = a;
2680           nextErrorPosition = p;
2681         }
2682       }
2683     }
2684
2685     if (nextErrorPosition != null) {
2686       errorPosition.setOffset(nextErrorPosition.getOffset());
2687       errorPosition.setLength(nextErrorPosition.getLength());
2688     }
2689
2690     return nextError;
2691   }
2692   void removeOccurrenceAnnotations() {
2693         IDocumentProvider documentProvider= getDocumentProvider();
2694         if (documentProvider == null)
2695                 return;
2696         
2697         IAnnotationModel annotationModel= documentProvider.getAnnotationModel(getEditorInput());
2698         if (annotationModel == null || fOccurrenceAnnotations == null)
2699                 return;
2700
2701         synchronized (annotationModel) {
2702                 if (annotationModel instanceof IAnnotationModelExtension) {
2703                         ((IAnnotationModelExtension)annotationModel).replaceAnnotations(fOccurrenceAnnotations, null);
2704                 } else {
2705                         for (int i= 0, length= fOccurrenceAnnotations.length; i < length; i++)
2706                                 annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
2707                 }
2708                 fOccurrenceAnnotations= null;
2709         }
2710 }
2711 }