GotoMatchingBracket implementiert
[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 net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
15 import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
16 import net.sourceforge.phpdt.ui.actions.GenerateActionGroup;
17 import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
18 import net.sourceforge.phpeclipse.IPreferenceConstants;
19 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
20 import net.sourceforge.phpeclipse.phpeditor.php.PHPCodeScanner;
21 import net.sourceforge.phpeclipse.phpeditor.util.PHPColorProvider;
22
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.jface.action.Action;
26 import org.eclipse.jface.action.IAction;
27 import org.eclipse.jface.action.MenuManager;
28 import org.eclipse.jface.preference.IPreferenceStore;
29 import org.eclipse.jface.preference.PreferenceConverter;
30 import org.eclipse.jface.text.BadLocationException;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IRegion;
33 import org.eclipse.jface.text.ITextOperationTarget;
34 import org.eclipse.jface.text.ITextViewer;
35 import org.eclipse.jface.text.ITextViewerExtension3;
36 import org.eclipse.jface.text.Region;
37 import org.eclipse.jface.text.source.AnnotationRulerColumn;
38 import org.eclipse.jface.text.source.CompositeRuler;
39 import org.eclipse.jface.text.source.ISourceViewer;
40 import org.eclipse.jface.text.source.IVerticalRuler;
41 import org.eclipse.jface.text.source.IVerticalRulerColumn;
42 import org.eclipse.jface.text.source.LineNumberRulerColumn;
43 import org.eclipse.jface.util.IPropertyChangeListener;
44 import org.eclipse.jface.util.PropertyChangeEvent;
45 import org.eclipse.swt.custom.StyledText;
46 import org.eclipse.swt.graphics.Point;
47 import org.eclipse.swt.graphics.RGB;
48 import org.eclipse.ui.IEditorInput;
49 import org.eclipse.ui.actions.ActionContext;
50 import org.eclipse.ui.actions.ActionGroup;
51 import org.eclipse.ui.editors.text.TextEditor;
52 import org.eclipse.ui.texteditor.ContentAssistAction;
53 import org.eclipse.ui.texteditor.DefaultRangeIndicator;
54 import org.eclipse.ui.texteditor.IEditorStatusLine;
55 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
56 import org.eclipse.ui.texteditor.TextOperationAction;
57 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
58 /**
59  * PHP specific text editor.
60  */
61 public class PHPEditor extends TextEditor {
62 // extends StatusTextEditor implements IViewPartInputProvider  { // extends TextEditor {
63
64   // protected PHPActionGroup fActionGroups;
65   /** The outline page */
66   private PHPContentOutlinePage fOutlinePage;
67   private IPreferenceStore phpPrefStore;
68
69   /** The editor's bracket matcher */
70   private PHPPairMatcher fBracketMatcher;
71   /** The line number ruler column */
72   private LineNumberRulerColumn fLineNumberRulerColumn;
73
74   protected CompositeActionGroup fActionGroups;
75   /** The standard action groups added to the menu */
76   private GenerateActionGroup fGenerateActionGroup;
77   private CompositeActionGroup fContextMenuGroup;
78   /**
79    * Default constructor.
80    */
81   public PHPEditor() {
82     super();
83     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
84     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
85   }
86   //
87   //    /**
88   //     * @see IMember#getCompilationUnit()
89   //     */
90   //    public ICompilationUnit getCompilationUnit() {
91   //            return this; 
92   //    }
93   //    /**
94   //     * @see org.phpeclipse.phpdt.internal.compiler.env.ICompilationUnit#getContents()
95   //     */
96   //    public char[] getContents() {
97   //            IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
98   //    
99   //            return doc.get().toCharArray();
100   //    }
101
102   /**
103    * Returns this document's complete text.
104    *
105    * @return the document's complete text
106    */
107   public String get() {
108     IDocument doc =
109       this.getDocumentProvider().getDocument(this.getEditorInput());
110     return doc.get();
111   }
112
113   /**
114    *  Returns the standard action group of this editor.
115    */
116   protected ActionGroup getActionGroup() {
117     return fActionGroups;
118   }
119
120   public PHPContentOutlinePage getfOutlinePage() {
121     return fOutlinePage;
122   }
123
124   /** The <code>PHPEditor</code> implementation of this 
125    * <code>AbstractTextEditor</code> method extend the 
126    * actions to add those specific to the receiver
127    */
128   protected void createActions() {
129     super.createActions();
130
131     Action action;
132     //    setAction(
133     //      "ContentAssistProposal",
134     //      new TextOperationAction(
135     //        PHPEditorMessages.getResourceBundle(),
136     //        "ContentAssistProposal.",
137     //        this,
138     //        ISourceViewer.CONTENTASSIST_PROPOSALS));
139     action = new ContentAssistAction(PHPEditorMessages.getResourceBundle(), "ContentAssistProposal.", this); //$NON-NLS-1$
140     action.setActionDefinitionId(
141       PHPEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
142     setAction("ContentAssistProposal", action); //$NON-NLS-1$
143
144     setAction(
145       "ContentAssistTip",
146       new TextOperationAction(
147         PHPEditorMessages.getResourceBundle(),
148         "ContentAssistTip.",
149         this,
150         ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION));
151
152     action =
153       new TextOperationAction(
154         PHPEditorMessages.getResourceBundle(),
155         "Comment.",
156         this,
157         ITextOperationTarget.PREFIX);
158     action.setActionDefinitionId(PHPEditorActionDefinitionIds.COMMENT);
159     setAction("Comment", action);
160
161     action =
162       new TextOperationAction(
163         PHPEditorMessages.getResourceBundle(),
164         "Uncomment.",
165         this,
166         ITextOperationTarget.STRIP_PREFIX);
167     action.setActionDefinitionId(PHPEditorActionDefinitionIds.UNCOMMENT);
168     setAction("Uncomment", action);
169
170     action = new TextOperationAction(PHPEditorMessages.getResourceBundle(), "Format.", this, ISourceViewer.FORMAT); //$NON-NLS-1$
171     action.setActionDefinitionId(PHPEditorActionDefinitionIds.FORMAT);
172     setAction("Format", action); //$NON-NLS-1$
173
174     markAsStateDependentAction("ContentAssistProposal", true); //$NON-NLS-1$
175     markAsStateDependentAction("Comment", true); //$NON-NLS-1$
176     markAsStateDependentAction("Uncomment", true); //$NON-NLS-1$
177     markAsStateDependentAction("Format", true); //$NON-NLS-1$
178
179     action = new GotoMatchingBracketAction(this);
180     action.setActionDefinitionId(
181       PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
182     setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
183
184     fGenerateActionGroup =
185       new GenerateActionGroup(this, ITextEditorActionConstants.GROUP_EDIT);
186
187     fActionGroups =
188       new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
189
190     // We have to keep the context menu group separate to have better control over positioning
191     fContextMenuGroup =
192       new CompositeActionGroup(new ActionGroup[] { fGenerateActionGroup });
193     //      rg, 
194     //      new LocalHistoryActionGroup(this, ITextEditorActionConstants.GROUP_EDIT)});
195   }
196
197   /** The <code>PHPEditor</code> implementation of this 
198    * <code>AbstractTextEditor</code> method performs any extra 
199    * disposal actions required by the php editor.
200    */
201   public void dispose() {
202     PHPEditorEnvironment.disconnect(this);
203     if (fOutlinePage != null)
204       fOutlinePage.setInput(null);
205
206     if (fActionGroups != null)
207       fActionGroups.dispose();
208
209     super.dispose();
210   }
211
212   /** The <code>PHPEditor</code> implementation of this 
213    * <code>AbstractTextEditor</code> method performs any extra 
214    * revert behavior required by the php editor.
215    */
216   public void doRevertToSaved() {
217     super.doRevertToSaved();
218     if (fOutlinePage != null)
219       fOutlinePage.update();
220   }
221
222   /** The <code>PHPEditor</code> implementation of this 
223    * <code>AbstractTextEditor</code> method performs any extra 
224    * save behavior required by the php editor.
225    */
226   public void doSave(IProgressMonitor monitor) {
227     super.doSave(monitor);
228     // compile or not, according to the user preferences
229     IPreferenceStore store = phpPrefStore;
230     if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
231       IAction a = PHPParserAction.getInstance();
232       if (a != null)
233         a.run();
234     }
235     if (fOutlinePage != null)
236       fOutlinePage.update();
237   }
238
239   /** The <code>PHPEditor</code> implementation of this 
240    * <code>AbstractTextEditor</code> method performs any extra 
241    * save as behavior required by the php editor.
242    */
243   public void doSaveAs() {
244     super.doSaveAs();
245     if (fOutlinePage != null)
246       fOutlinePage.update();
247   }
248
249   /** The <code>PHPEditor</code> implementation of this 
250    * <code>AbstractTextEditor</code> method performs sets the 
251    * input of the outline page after AbstractTextEditor has set input.
252    */
253   public void doSetInput(IEditorInput input) throws CoreException {
254     super.doSetInput(input);
255     if (fOutlinePage != null)
256       fOutlinePage.setInput(input);
257   }
258
259   /*
260    * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
261    */
262 //  public Object getViewPartInput() {
263 //    return getEditorInput().getAdapter(IFile.class);
264 //  }
265   
266   /** The <code>PHPEditor</code> implementation of this 
267    * <code>AbstractTextEditor</code> method adds any 
268    * PHPEditor specific entries.
269    */
270   public void editorContextMenuAboutToShow(MenuManager menu) {
271     super.editorContextMenuAboutToShow(menu);
272
273     addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format"); //$NON-NLS-1$
274
275     ActionContext context =
276       new ActionContext(getSelectionProvider().getSelection());
277     fContextMenuGroup.setContext(context);
278     fContextMenuGroup.fillContextMenu(menu);
279     fContextMenuGroup.setContext(null);
280   }
281
282   protected void updateStateDependentActions() {
283     super.updateStateDependentActions();
284     fGenerateActionGroup.editorStateChanged();
285   }
286
287   /** The <code>PHPEditor</code> implementation of this 
288    * <code>AbstractTextEditor</code> method performs gets
289    * the java content outline page if request is for a an 
290    * outline page.
291    */
292   public Object getAdapter(Class required) {
293     if (IContentOutlinePage.class.equals(required)) {
294       if (fOutlinePage == null) {
295         fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
296         if (getEditorInput() != null)
297           fOutlinePage.setInput(getEditorInput());
298       }
299       return fOutlinePage;
300     }
301     return super.getAdapter(required);
302   }
303
304   //  public void openContextHelp() {
305   //    IDocument doc = this.getDocumentProvider().getDocument(this.getEditorInput());
306   //    ITextSelection selection = (ITextSelection) this.getSelectionProvider().getSelection();
307   //    int pos = selection.getOffset();
308   //    String word = getFunctionName(doc, pos);
309   //    openContextHelp(word);
310   //  }
311   //
312   //  private void openContextHelp(String word) {
313   //    open(word);
314   //  }
315   //
316   //  public static void open(String word) {
317   //    IHelp help = WorkbenchHelp.getHelpSupport();
318   //    if (help != null) {
319   //      IHelpResource helpResource = new PHPFunctionHelpResource(word);
320   //      WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
321   //    } else {
322   //      //   showMessage(shell, dialogTitle, ActionMessages.getString("Open help not available"), false); //$NON-NLS-1$
323   //    }
324   //  }
325
326   //    private String getFunctionName(IDocument doc, int pos) {
327   //            Point word = PHPWordExtractor.findWord(doc, pos);
328   //            if (word != null) {
329   //                    try {
330   //                            return doc.get(word.x, word.y).replace('_', '-');
331   //                    } catch (BadLocationException e) {
332   //                    }
333   //            }
334   //            return "";
335   //    }
336
337   /*
338      * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
339      */
340   protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
341
342     try {
343
344       ISourceViewer sourceViewer = getSourceViewer();
345       if (sourceViewer == null)
346         return;
347
348       String property = event.getProperty();
349
350       //      if (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
351       //        Object value= event.getNewValue();
352       //        if (value instanceof Integer) {
353       //          sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
354       //        } else if (value instanceof String) {
355       //          sourceViewer.getTextWidget().setTabs(Integer.parseInt((String) value));
356       //        }
357       //        return;
358       //      }
359
360       if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
361         if (isLineNumberRulerVisible())
362           showLineNumberRuler();
363         else
364           hideLineNumberRuler();
365         return;
366       }
367
368       if (fLineNumberRulerColumn != null
369         && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
370           || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
371           || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
372
373         initializeLineNumberRulerColumn(fLineNumberRulerColumn);
374       }
375
376     } finally {
377       super.handlePreferenceStoreChanged(event);
378     }
379   }
380   /**
381    * Shows the line number ruler column.
382    */
383   private void showLineNumberRuler() {
384     IVerticalRuler v = getVerticalRuler();
385     if (v instanceof CompositeRuler) {
386       CompositeRuler c = (CompositeRuler) v;
387       c.addDecorator(1, createLineNumberRulerColumn());
388     }
389   }
390
391   /**
392   * Return whether the line number ruler column should be 
393   * visible according to the preference store settings.
394   * @return <code>true</code> if the line numbers should be visible
395   */
396   private boolean isLineNumberRulerVisible() {
397     // IPreferenceStore store= getPreferenceStore();
398     return phpPrefStore.getBoolean(IPreferenceConstants.LINE_NUMBER_RULER);
399   }
400   /**
401    * Hides the line number ruler column.
402    */
403   private void hideLineNumberRuler() {
404     IVerticalRuler v = getVerticalRuler();
405     if (v instanceof CompositeRuler) {
406       CompositeRuler c = (CompositeRuler) v;
407       try {
408         c.removeDecorator(1);
409       } catch (Throwable e) {
410       }
411     }
412   }
413
414   /**
415   * Initializes the given line number ruler column from the preference store.
416   * @param rulerColumn the ruler column to be initialized
417   */
418   protected void initializeLineNumberRulerColumn(LineNumberRulerColumn rulerColumn) {
419     //   JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
420     PHPColorProvider manager = PHPEditorEnvironment.getPHPColorProvider();
421
422     if (phpPrefStore != null) {
423
424       RGB rgb = null;
425       // foreground color
426       if (phpPrefStore.contains(IPreferenceConstants.LINE_NUMBER_COLOR)) {
427         if (phpPrefStore.isDefault(IPreferenceConstants.LINE_NUMBER_COLOR))
428           rgb =
429             PreferenceConverter.getDefaultColor(
430               phpPrefStore,
431               IPreferenceConstants.LINE_NUMBER_COLOR);
432         else
433           rgb =
434             PreferenceConverter.getColor(
435               phpPrefStore,
436               IPreferenceConstants.LINE_NUMBER_COLOR);
437       }
438       rulerColumn.setForeground(manager.getColor(rgb));
439
440       rgb = null;
441       // background color
442       if (!phpPrefStore
443         .getBoolean(
444           IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
445         if (phpPrefStore
446           .contains(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND)) {
447           if (phpPrefStore
448             .isDefault(IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND))
449             rgb =
450               PreferenceConverter.getDefaultColor(
451                 phpPrefStore,
452                 IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
453           else
454             rgb =
455               PreferenceConverter.getColor(
456                 phpPrefStore,
457                 IPreferenceConstants.PREFERENCE_COLOR_BACKGROUND);
458         }
459         rulerColumn.setBackground(manager.getColor(rgb));
460       }
461
462     }
463   }
464
465   /**
466    * Creates a new line number ruler column that is appropriately initialized.
467    */
468   protected IVerticalRulerColumn createLineNumberRulerColumn() {
469     fLineNumberRulerColumn = new LineNumberRulerColumn();
470     initializeLineNumberRulerColumn(fLineNumberRulerColumn);
471     return fLineNumberRulerColumn;
472   }
473
474   /*
475    * @see AbstractTextEditor#createVerticalRuler()
476    */
477   protected IVerticalRuler createVerticalRuler() {
478     CompositeRuler ruler = new CompositeRuler();
479     ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
480     if (isLineNumberRulerVisible())
481       ruler.addDecorator(1, createLineNumberRulerColumn());
482     return ruler;
483   }
484
485   /* (non-Javadoc)
486    * Method declared on TextEditor
487    */
488   protected void initializeEditor() {
489     PHPEditorEnvironment.connect(this);
490
491     setSourceViewerConfiguration(new PHPSourceViewerConfiguration(this));
492     setRangeIndicator(new DefaultRangeIndicator());
493     setEditorContextMenuId("#PHPEditorContext"); //$NON-NLS-1$
494     setRulerContextMenuId("#PHPRulerContext"); //$NON-NLS-1$
495     // setDocumentProvider(PHPeclipsePlugin.getCompilationUnitDocumentProvider());
496     phpPrefStore = PHPeclipsePlugin.getDefault().getPreferenceStore();
497
498     phpPrefStore.addPropertyChangeListener(new IPropertyChangeListener() {
499       public void propertyChange(PropertyChangeEvent event) {
500         PHPCodeScanner scanner = PHPEditorEnvironment.getPHPCodeScanner();
501         if (scanner != null) {
502           scanner.updateToken(PHPEditorEnvironment.getPHPColorProvider());
503         }
504         if (getSourceViewer() != null) {
505           getSourceViewer().invalidateTextPresentation();
506         }
507
508         String property = event.getProperty();
509         if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
510           if (isLineNumberRulerVisible())
511             showLineNumberRuler();
512           else
513             hideLineNumberRuler();
514           return;
515         }
516       }
517     });
518   }
519   
520   private static IRegion getSignedSelection(ITextViewer viewer) {
521
522     StyledText text = viewer.getTextWidget();
523     int caretOffset = text.getCaretOffset();
524     Point selection = text.getSelection();
525
526     // caret left
527     int offset, length;
528     if (caretOffset == selection.x) {
529       offset = selection.y;
530       length = selection.x - selection.y;
531
532       // caret right
533     } else {
534       offset = selection.x;
535       length = selection.y - selection.x;
536     }
537
538     return new Region(offset, length);
539   }
540
541   private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
542
543   private static boolean isBracket(char character) {
544     for (int i = 0; i != BRACKETS.length; ++i)
545       if (character == BRACKETS[i])
546         return true;
547     return false;
548   }
549
550   private static boolean isSurroundedByBrackets(
551     IDocument document,
552     int offset) {
553     if (offset == 0 || offset == document.getLength())
554       return false;
555
556     try {
557       return isBracket(document.getChar(offset - 1))
558         && isBracket(document.getChar(offset));
559
560     } catch (BadLocationException e) {
561       return false;
562     }
563   }
564   /**
565     * Jumps to the matching bracket.
566     */
567   public void gotoMatchingBracket() {
568
569     if (fBracketMatcher == null)
570       fBracketMatcher = new PHPPairMatcher(BRACKETS);
571
572     ISourceViewer sourceViewer = getSourceViewer();
573     IDocument document = sourceViewer.getDocument();
574     if (document == null)
575       return;
576
577     IRegion selection = getSignedSelection(sourceViewer);
578
579     int selectionLength = Math.abs(selection.getLength());
580     if (selectionLength > 1) {
581       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$               
582       sourceViewer.getTextWidget().getDisplay().beep();
583       return;
584     }
585
586     // #26314
587     int sourceCaretOffset = selection.getOffset() + selection.getLength();
588     if (isSurroundedByBrackets(document, sourceCaretOffset))
589       sourceCaretOffset -= selection.getLength();
590
591     IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
592     if (region == null) {
593       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$              
594       sourceViewer.getTextWidget().getDisplay().beep();
595       return;
596     }
597
598     int offset = region.getOffset();
599     int length = region.getLength();
600
601     if (length < 1)
602       return;
603
604     int anchor = fBracketMatcher.getAnchor();
605     int targetOffset =
606       (PHPPairMatcher.RIGHT == anchor) ? offset : offset + length - 1;
607
608     boolean visible = false;
609     if (sourceViewer instanceof ITextViewerExtension3) {
610       ITextViewerExtension3 extension = (ITextViewerExtension3) sourceViewer;
611       visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
612     } else {
613       IRegion visibleRegion = sourceViewer.getVisibleRegion();
614       visible =
615         (targetOffset >= visibleRegion.getOffset()
616           && targetOffset < visibleRegion.getOffset() + visibleRegion.getLength());
617     }
618
619     if (!visible) {
620       setStatusLineErrorMessage(PHPEditorMessages.getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$          
621       sourceViewer.getTextWidget().getDisplay().beep();
622       return;
623     }
624
625     if (selection.getLength() < 0)
626       targetOffset -= selection.getLength();
627
628     sourceViewer.setSelectedRange(targetOffset, selection.getLength());
629     sourceViewer.revealRange(targetOffset, selection.getLength());
630   }
631   /**
632      * Ses the given message as error message to this editor's status line.
633      * @param msg message to be set
634      */
635   protected void setStatusLineErrorMessage(String msg) {
636     IEditorStatusLine statusLine =
637       (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
638     if (statusLine != null)
639       statusLine.setMessage(true, msg, null);
640   }
641 }