2a6d8676a6fbe2b067b4634c27ff990ade9195ee
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / ScilabEditorPane.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - 2011 - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.scinotes;
14
15 import java.awt.Color;
16 import java.awt.Cursor;
17 import java.awt.Font;
18 import java.awt.Graphics;
19 import java.awt.Point;
20 import java.awt.Rectangle;
21 import java.awt.Shape;
22 import java.awt.event.FocusEvent;
23 import java.awt.event.FocusListener;
24 import java.awt.event.KeyEvent;
25 import java.awt.event.KeyListener;
26 import java.awt.event.MouseEvent;
27 import java.awt.event.MouseListener;
28 import java.awt.event.MouseMotionListener;
29 import java.io.File;
30 import java.util.ArrayList;
31 import java.util.EventObject;
32 import java.util.List;
33 import java.util.UUID;
34 import java.util.Vector;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37
38 import javax.swing.JEditorPane;
39 import javax.swing.JScrollBar;
40 import javax.swing.JScrollPane;
41 import javax.swing.JSplitPane;
42 import javax.swing.SwingUtilities;
43 import javax.swing.UIManager;
44 import javax.swing.event.CaretEvent;
45 import javax.swing.event.CaretListener;
46 import javax.swing.event.EventListenerList;
47 import javax.swing.text.BadLocationException;
48 import javax.swing.text.Caret;
49 import javax.swing.text.DefaultHighlighter;
50 import javax.swing.text.Document;
51 import javax.swing.text.Element;
52 import javax.swing.text.Highlighter;
53 import javax.swing.text.JTextComponent;
54 import javax.swing.text.View;
55
56 import org.scilab.modules.commons.gui.ScilabCaret;
57 import org.scilab.modules.console.utils.ScilabLaTeXViewer;
58 import org.scilab.modules.gui.utils.WebBrowser;
59 import org.scilab.modules.scinotes.actions.CopyAsHTMLAction;
60 import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction;
61 import org.scilab.modules.scinotes.utils.NavigatorWindow;
62 import org.scilab.modules.scinotes.utils.ScilabScrollPane;
63 import org.scilab.modules.scinotes.utils.SciNotesMessages;
64
65 /**
66  * Class ScilabEditorPane
67  * @author Calixte DENIZET
68  *
69  */
70 public class ScilabEditorPane extends JEditorPane implements Highlighter.HighlightPainter,
71     CaretListener, MouseListener,
72     MouseMotionListener, Cloneable,
73     KeyListener {
74
75     private static final long serialVersionUID = 4322071415211939097L;
76
77     private static final String TIRET = " - ";
78     private static final Cursor HANDCURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
79     private static final Cursor TEXTCURSOR = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
80     private static final DefaultHighlighter.DefaultHighlightPainter HIGHLIGHTER = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
81
82     private static ScilabEditorPane focused;
83
84     private Color highlightColor;
85     private Color highlightContourColor;
86     private boolean highlightEnable;
87     private Object highlightCL;
88     private boolean matchingKeywordsEnable;
89     private boolean matchingOpenersEnable;
90     private boolean overwriteMode;
91     private ScilabLexer lexer;
92     private SciNotes editor;
93     private IndentManager indent;
94     private TabManager tab;
95     private CommentManager com;
96     private HelpOnTypingManager helpOnTyping;
97     private TrailingWhiteManager trailingWhite;
98     private boolean readonly;
99     private boolean binary;
100     private String infoBar = "";
101     private String shortName = "";
102     private String title = "";
103
104     private Point mousePoint;
105
106     private long lastModified;
107
108     /* matchLR matches Left to Right ... */
109     private MatchingBlockManager matchLR;
110     private MatchingBlockManager matchRL;
111
112     private boolean suppressCom = true;
113
114     private SciNotesLineNumberPanel xln;
115     private ScilabEditorPane rightTextPane;
116     private UUID uuid;
117
118     private EditorComponent edComponent;
119
120     private boolean hand;
121     private boolean infoBarChanged;
122     private boolean ctrlHit;
123
124     private Color saveHighlightContourColor;
125     private Color saveHighlightColor;
126     private boolean hasBeenSaved;
127     private boolean saveHighlightEnable;
128
129     private EventListenerList kwListeners = new EventListenerList();
130     private List<Object> highlightedWords = new ArrayList<Object>();
131     private List<Integer> highlightedWordsBegin = new ArrayList<Integer>();
132
133     /**
134      * Constructor
135      * @param editor which uses this pane
136      */
137     public ScilabEditorPane(SciNotes editor) {
138         super();
139         if (focused == null) {
140             focused = this;
141         }
142         this.editor = editor;
143         this.uuid = UUID.randomUUID();
144         edComponent = new EditorComponent(this);
145
146         /*
147           When SciNotes is docked and has two tabs, switching the tabs causes a focus loss.
148           The focus is gave to the other docked component and that generates a toolbar change.
149           The solution is to set FocusCycleRoot to false (set to true by default in JEditorPane).
150         */
151         setFocusCycleRoot(false);
152
153         addCaretListener(this);
154         addMouseMotionListener(this);
155         addMouseListener(this);
156         enableMatchingKeywords(SciNotesOptions.getSciNotesDisplay().highlightKeywords);
157         enableMatchingOpeners(SciNotesOptions.getSciNotesDisplay().highlightBrackets);
158         setFocusable(true);
159         addFocusListener(new FocusListener() {
160             public void focusGained(FocusEvent e) {
161                 updateInfosWhenFocused();
162                 if (ScilabEditorPane.this.editor != null) {
163                     NavigatorWindow nav = ScilabEditorPane.this.editor.getNavigator();
164                     if (nav != null) {
165                         nav.update((ScilabDocument) getDocument());
166                     }
167                 }
168             }
169
170             public void focusLost(FocusEvent e) {
171                 ((ScilabDocument) getDocument()).setFocused(false);
172             }
173         });
174
175         addKeywordListener(new KeywordAdaptater.MouseOverAdaptater() {
176             public void caughtKeyword(KeywordEvent e) {
177                 if (ScilabLexerConstants.isClickable(e.getType())) {
178                     if (ctrlHit) {
179                         setCursor(HANDCURSOR);
180                         hand = true;
181                         try {
182                             String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength());
183                             if (ScilabLexerConstants.isClickable(e.getType())) {
184                                 String text;
185                                 switch (e.getType()) {
186                                     case ScilabLexerConstants.URL :
187                                         text = SciNotesMessages.OPENURL;
188                                         break;
189                                     case ScilabLexerConstants.MAIL :
190                                         text = SciNotesMessages.MAILTO;
191                                         break;
192                                     case ScilabLexerConstants.MACROS :
193                                         text = SciNotesMessages.OPENSOURCE;
194                                         break;
195                                     case ScilabLexerConstants.MACROINFILE :
196                                         text = SciNotesMessages.SHOWSOURCE;
197                                         break;
198                                     default :
199                                         text = null;
200                                 }
201
202                                 if (text != null && ScilabEditorPane.this.editor != null) {
203                                     ScilabEditorPane.this.editor.getInfoBar().setText(text + url);
204                                     infoBarChanged = true;
205                                 }
206                             }
207                         } catch (BadLocationException ex) { }
208                     } else if (ScilabEditorPane.this.editor != null) {
209                         ScilabEditorPane.this.editor.getInfoBar().setText(SciNotesMessages.CLICKABLE_URL);
210                         infoBarChanged = true;
211                     }
212                 } else {
213                     if (hand) {
214                         setCursor(TEXTCURSOR);
215                         hand = false;
216                     }
217                     if (infoBarChanged && ScilabEditorPane.this.editor != null) {
218                         ScilabEditorPane.this.editor.getInfoBar().setText(infoBar);
219                         infoBarChanged = false;
220                     }
221                     if (ScilabLexerConstants.isLaTeX(e.getType())) {
222                         try {
223                             int start = e.getStart();
224                             int end = start + e.getLength();
225                             String exp = ((ScilabDocument) getDocument()).getText(start, e.getLength());
226                             int height = edComponent.getScrollPane().getHeight() + edComponent.getScrollPane().getVerticalScrollBar().getValue();
227                             ScilabLaTeXViewer.displayExpression(ScilabEditorPane.this, height, exp, start, end);
228                         } catch (BadLocationException ex) { }
229                     } else {
230                         ScilabLaTeXViewer.removeLaTeXViewer(ScilabEditorPane.this);
231                     }
232                 }
233             }
234         });
235
236         addKeywordListener(new KeywordAdaptater.MouseClickedAdaptater() {
237             public void caughtKeyword(KeywordEvent e) {
238                 if (ctrlHit && ScilabLexerConstants.isClickable(e.getType())) {
239                     try {
240                         hand = false;
241                         ctrlHit = false;
242                         infoBarChanged = false;
243                         setCursor(TEXTCURSOR);
244                         if (ScilabEditorPane.this.editor != null) {
245                             ScilabEditorPane.this.editor.getInfoBar().setText(infoBar);
246                         }
247                         String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength());
248                         if (ScilabLexerConstants.URL == e.getType() || ScilabLexerConstants.MAIL == e.getType()) {
249                             WebBrowser.openUrl(url);
250                         } else if (ScilabLexerConstants.isOpenable(e.getType())) {
251                             OpenSourceFileOnKeywordAction.openSource(ScilabEditorPane.this, url);
252                         }
253                     } catch (BadLocationException ex) { }
254                 }
255             }
256         });
257
258         addKeyListener(this);
259         setTransferHandler(new CopyAsHTMLAction.HTMLTransferHandler());
260     }
261
262     public void enableColorization(boolean b) {
263         View view = ((ScilabDocument) getDocument()).getView();
264         if (view != null) {
265             if (view instanceof ScilabView) {
266                 ((ScilabView) view).enable(b);
267             } else {
268                 ((ScilabPlainView) view).enable(b);
269             }
270         }
271     }
272
273     public void configurationChanged(SciNotesConfiguration.Conf conf) {
274         ((ScilabEditorKit) getEditorKit()).getStylePreferences().configurationChanged(conf);
275
276         if (conf.font) {
277             resetFont();
278         }
279
280         if (conf.display) {
281             enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
282             setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
283             enableColorization(SciNotesOptions.getSciNotesDisplay().keywordsColorization);
284
285             boolean kw = SciNotesOptions.getSciNotesDisplay().highlightKeywords;
286             boolean op = SciNotesOptions.getSciNotesDisplay().highlightBrackets;
287
288             if ((kw || op) && (!matchingKeywordsEnable && !matchingOpenersEnable)) {
289                 matchLR = new MatchingBlockManager((ScilabDocument) getDocument(), this, true, getHighlighter());
290                 matchLR.setDefaults();
291                 matchRL = new MatchingBlockManager((ScilabDocument) getDocument(), this, false, getHighlighter());
292                 matchRL.setDefaults();
293                 enableMatchingKeywords(kw);
294                 enableMatchingOpeners(op);
295                 return;
296             }
297
298             if ((kw || op) && (matchingKeywordsEnable || matchingOpenersEnable)) {
299                 matchLR.configurationChanged(conf);
300                 matchRL.configurationChanged(conf);
301                 return;
302             }
303
304             if ((!kw && !op) && (matchingKeywordsEnable || matchingOpenersEnable)) {
305                 matchLR.desactivateMouseOver();
306                 matchLR = null;
307                 matchRL.desactivateMouseOver();
308                 matchRL = null;
309                 return;
310             }
311         }
312     }
313
314     /**
315      * @return the lexer
316      */
317     public ScilabLexer getLexer() {
318         return lexer;
319     }
320
321     /**
322      * {@inheritDoc}
323      * When no split and in wrapped view , this method return true and the consequence is
324      * that there is no horizontal scrollbar.
325      */
326     public boolean getScrollableTracksViewportWidth() {
327         return ((ScilabDocument) getDocument()).getView() instanceof ScilabView && !edComponent.isSplited();
328     }
329
330     /**
331      * @return true if the pane is in OverWrite mode (insert)
332      */
333     public boolean getOverwriteMode() {
334         return this.overwriteMode;
335     }
336
337     /**
338      * @param overwriteMode true if the pane is in OverWrite mode (insert)
339      */
340     public void setOverwriteMode(boolean overwriteMode) {
341         this.overwriteMode = overwriteMode;
342         ((ScilabCaret) getCaret()).setOverwriteMode(overwriteMode);
343     }
344
345     /**
346      * {@inheritDoc}
347      */
348     public void replaceSelection(String content) {
349         if (overwriteMode && getSelectionStart() == getSelectionEnd()) {
350             int pos = getCaretPosition();
351             select(pos, pos + content.length());
352         }
353
354         if (((SciNotesCaret) getCaret()).isEmptySelection()) {
355             super.replaceSelection(content);
356         } else {
357             SciNotesCaret caret = (SciNotesCaret) getCaret();
358             int[][] pos = caret.getSelectedPositions();
359             List<Object> sels = caret.getSelections();
360             int len = content.length();
361             int res = 0;
362             int sres;
363             ScilabDocument doc = (ScilabDocument) getDocument();
364             doc.getUndoManager().enableOneShot(true);
365             doc.mergeEditsBegin();
366             caret.protectHighlights(true);
367             for (int i = 0; i < pos.length; i++) {
368                 if (sels.get(i) != null) {
369                     sres = pos[i][0] + res;
370                     try {
371                         doc.replace(sres, pos[i][1] - pos[i][0], content, null);
372                     } catch (BadLocationException e) { }
373                     res = sres + len - pos[i][1];
374                     pos[i][0] = sres + len;
375                     pos[i][1] = sres + len;
376                 }
377             }
378             doc.mergeEditsEnd();
379             doc.getUndoManager().enableOneShot(false);
380             caret.protectHighlights(false);
381             caret.updateHighlights();
382         }
383     }
384
385     /**
386      * Nothing !
387      * @param e the event
388      */
389     public void keyPressed(KeyEvent e) {
390         // Workaround for bug 7238
391         if (e.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD
392                 && e.getKeyCode() == KeyEvent.VK_DELETE
393                 && e.getKeyChar() != KeyEvent.VK_DELETE) {
394             e.setKeyCode(KeyEvent.VK_DECIMAL);
395             ctrlHit = false;
396         } else if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
397             ctrlHit = true;
398         } else {
399             ctrlHit = false;
400         }
401     }
402
403     /**
404      * Nothing !
405      * @param e the event
406      */
407     public void keyReleased(KeyEvent e) {
408         if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
409             ctrlHit = false;
410         }
411     }
412
413     /**
414      * Nothing !
415      * @param e the event
416      */
417     public void keyTyped(KeyEvent e) { }
418
419     /**
420      * @overload #setDocument
421      * @param doc to set
422      */
423     public void setDocument(Document doc) {
424         super.setDocument(doc);
425         if (doc instanceof ScilabDocument) {
426             ((ScilabDocument) doc).getUndoManager().discardAllEdits();
427             initialize((ScilabDocument) doc);
428         }
429     }
430
431     /**
432      * {@inheritDoc}
433      */
434     public void setName(String name) {
435         setNameInSuper(name);
436         setShortNameAndTitle(name);
437         ScilabEditorPane pane = getOtherPaneInSplit();
438         if (pane != null) {
439             // I don't call pane.setName since we will enter in an infinite loop
440             pane.setNameInSuper(name);
441             pane.setShortNameAndTitle(name);
442         }
443     }
444
445     /**
446      * @param name the name
447      */
448     private void setNameInSuper(String name) {
449         super.setName(name);
450     }
451
452     /**
453      * @param name the name
454      */
455     private void setShortNameAndTitle(String name) {
456         if (name != null) {
457             File f = new File(name);
458             setShortName(f.getName());
459             title =  shortName + " (" + f.getAbsolutePath() + ")" + TIRET + SciNotesMessages.SCILAB_EDITOR;
460         }
461     }
462
463     /**
464      * @param title the title
465      */
466     public void setTitle(String title) {
467         this.title = title + TIRET + SciNotesMessages.SCILAB_EDITOR;
468     }
469
470     /**
471      * @return the title
472      */
473     public String getTitle() {
474         return title;
475     }
476
477     /**
478      * @param name the short name
479      */
480     public void setShortName(String name) {
481         this.shortName = name;
482     }
483
484     /**
485      * @return the short name of the file (without the full path)
486      */
487     public String getShortName() {
488         return shortName;
489     }
490
491     /**
492      * Init the pane
493      */
494     public void init() {
495         SwingUtilities.invokeLater(new Runnable() {
496             public void run() {
497                 requestFocus();
498                 setCaretPosition(0);
499             }
500         });
501     }
502
503     /**
504      * Close this pane
505      */
506     public void close() {
507         FocusListener[] l = getFocusListeners();
508         for (int i = 0; i < l.length; i++) {
509             removeFocusListener(l[i]);
510         }
511     }
512
513     /**
514      * Update infos
515      */
516     public void updateInfosWhenFocused() {
517         ScilabDocument doc = (ScilabDocument) getDocument();
518         doc.setFocused(true);
519         SciNotes.setEditor(editor);
520         focused = this;
521         doc.getUndoManager().enableUndoRedoButtons();
522
523         if (editor != null) {
524             if (checkExternalModif()) {
525                 editor.getInfoBar().setText(SciNotesMessages.EXTERNAL_MODIFICATION_INFO);
526             } else {
527                 editor.getInfoBar().setText(getInfoBarText());
528             }
529         }
530     }
531
532     /**
533      * @return true if an external modif occured
534      */
535     public boolean checkExternalModif() {
536         String path = getName();
537         if (path != null) {
538             File f = new File(path);
539             if (f != null && f.exists()) {
540                 return lastModified < f.lastModified();
541             } else {
542                 return true;
543             }
544         }
545         return false;
546     }
547
548     /**
549      * @return the String which must be displayed in the infobar
550      */
551     public String getInfoBarText() {
552         return infoBar;
553     }
554
555     /**
556      * @param text String which must be displayed in the infobar
557      */
558     public void setInfoBarText(String text) {
559         this.infoBar = text;
560         if (editor != null) {
561             editor.getInfoBar().setText(getInfoBarText());
562         }
563     }
564
565     /**
566      * @param readonly true to set Read-Only mode
567      */
568     public void setReadOnly(boolean readonly) {
569         this.readonly = readonly;
570         setEditable(!readonly);
571         setDragEnabled(!readonly);
572         if (readonly) {
573             infoBar = SciNotesMessages.READ_ONLY_MODE;
574         } else {
575             infoBar = "";
576         }
577     }
578
579     /**
580      * @param binary true to set binary mode
581      */
582     public void setBinary(boolean binary) {
583         this.binary = binary;
584         setEditable(!binary);
585         setDragEnabled(!binary);
586         if (binary) {
587             infoBar = SciNotesMessages.BINARY_FILE_MODE;
588             disableAll();
589         } else {
590             infoBar = "";
591         }
592     }
593
594     /**
595      * Copy the props of this textPane to pane
596      * @param pane the pane which receives the same props as this
597      */
598     public void copyProps(ScilabEditorPane pane) {
599         pane.lastModified = lastModified;
600         pane.highlightEnable = highlightEnable;
601         pane.matchingKeywordsEnable = matchingKeywordsEnable;
602         pane.matchingOpenersEnable = matchingOpenersEnable;
603         pane.suppressCom = suppressCom;
604         pane.setName(getName());
605         pane.setShortName(getShortName());
606         pane.setTitle(getTitle().substring(0, getTitle().lastIndexOf(TIRET)));
607         pane.setEditable(isEditable());
608     }
609
610     /**
611      * Get the UUID associated with the editor pane instance.
612      * @return unique identifier
613      */
614     public UUID getUUID() {
615         return uuid;
616     }
617
618     /**
619      * Get the the time where the file associated with this pane
620      * has been modified.
621      * @return the last modified time or 0
622      */
623     public long getLastModified() {
624         return lastModified;
625     }
626
627     /**
628      * Set the last time where the file associated with this pane
629      * has been modified.
630      * @param time the time
631      */
632     public void setLastModified(long time) {
633         this.lastModified = time;
634         ScilabEditorPane pane = getOtherPaneInSplit();
635         if (pane != null) {
636             pane.lastModified = time;
637         }
638     }
639
640     /**
641      * @return the SciNotesLineNumberPanel used with this pane
642      */
643     public SciNotesLineNumberPanel getXln() {
644         return xln;
645     }
646
647     /**
648      * @return the editor
649      */
650     public SciNotes getEditor() {
651         return editor;
652     }
653
654     /**
655      * @param editor to set
656      */
657     public void setEditor(SciNotes editor) {
658         this.editor = editor;
659     }
660
661     /**
662      * Disable all
663      */
664     public void disableAll() {
665         indent = null;
666         tab = null;
667         com = null;
668         trailingWhite = null;
669         enableMatchingKeywords(false);
670         enableMatchingOpeners(false);
671         matchLR.desactivateMouseOver();
672         matchLR = null;
673         matchRL.desactivateMouseOver();
674         matchRL = null;
675     }
676
677     /**
678      * Destroy this component
679      */
680     public void destroy() {
681         FocusListener[] fls = getFocusListeners();
682         for (FocusListener fl : fls) {
683             removeFocusListener(fl);
684         }
685         disableAll();
686     }
687
688     /**
689      * @return the scrollPane or the splitpane associated with this textPane
690      */
691     public EditorComponent getEditorComponent() {
692         return edComponent;
693     }
694
695     /**
696      * @return the scrollPane or the splitpane associated with this textPane
697      */
698     public void setEditorComponent(EditorComponent ed) {
699         this.edComponent = ed;
700     }
701
702     /**
703      * @param split the split used
704      */
705     public void setSplitPane(JSplitPane split) {
706         edComponent.setSplitPane(split);
707     }
708
709     /**
710      * @param split the split used
711      */
712     public JSplitPane getSplitPane() {
713         return edComponent.getSplitPane();
714     }
715
716     /**
717      * Update the title of current tab
718      */
719     public void updateTitle() {
720         if (editor != null) {
721             editor.updateTabTitle();
722         }
723     }
724
725     /**
726      * Scroll the pane to have the line containing pos on the top of the pane
727      * @param pos the position in the document
728      */
729     public void scrollTextToPos(int pos) {
730         scrollTextToPos(pos, true, false);
731     }
732
733     /**
734      * Scroll the pane to have the line containing pos on the top or centered on the pane
735      * @param pos the position in the document
736      * @param setCaret, if true the caret is set at the given position
737      * @param centered, if true the line is centered
738      */
739     public void scrollTextToPos(final int pos, final boolean setCaret, final boolean centered) {
740         SwingUtilities.invokeLater(new Runnable() {
741             public void run() {
742                 try {
743                     if (setCaret) {
744                         setCaretPosition(pos);
745                     }
746                     JScrollBar scrollbar = edComponent.getScrollPane().getVerticalScrollBar();
747                     Rectangle rect = modelToView(pos);
748                     if (centered) {
749                         int value = scrollbar.getValue();
750                         int h = scrollbar.getHeight();
751                         if (rect.y < value || rect.y > value + h) {
752                             scrollbar.setValue(Math.max(0, rect.y - h / 2));
753                         }
754                     } else {
755                         if (rect.y > scrollbar.getMaximum()) {
756                             scrollbar.setMaximum(rect.y);
757                         }
758                         scrollbar.setValue(rect.y);
759                     }
760                 } catch (BadLocationException e) { }
761             }
762         });
763     }
764
765     /**
766      * Scroll the pane to have the line lineNumber on the top of the pane
767      * @param lineNumber the number of the line
768      * @param highlight true to highlight the line
769      */
770     public void scrollTextToLineNumber(int lineNumber, boolean highlight) {
771         scrollTextToLineNumber(lineNumber, highlight, true, false);
772     }
773
774     /**
775      * Scroll the pane to have the line lineNumber on the top or centered on the pane
776      * @param lineNumber the number of the line
777      * @param highlight true to highlight the line
778      * @param setCaret, if true the caret is set at the given line
779      * @param centered, if true the line is centered
780      */
781     public void scrollTextToLineNumber(int lineNumber, final boolean highlight, final boolean setCaret, final boolean centered) {
782         Element root = getDocument().getDefaultRootElement();
783         if (lineNumber >= 1 && lineNumber <= root.getElementCount()) {
784             final int pos = root.getElement(lineNumber - 1).getStartOffset();
785             SwingUtilities.invokeLater(new Runnable() {
786                 public void run() {
787                     scrollTextToPos(pos, setCaret, centered);
788                     if (highlight) {
789                         saveHighlightContourColor = highlightContourColor;
790                         highlightContourColor = null;
791                         saveHighlightColor = highlightColor;
792                         highlightColor = Color.YELLOW;
793                         saveHighlightEnable = highlightEnable;
794                         hasBeenSaved = true;
795                         enableHighlightedLine(false);
796                         enableHighlightedLine(true);
797                     }
798                 }
799             });
800         }
801     }
802
803     /**
804      * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode
805      * The line number is computed regarding the function named funname.
806      * @param lineNumber the number of the line
807      * @param funname the function name
808      * @param highlight true to highlight the line
809      */
810     public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight) {
811         scrollTextToLineNumberInWhereami(lineNumber, funname, highlight, true, false);
812     }
813
814     /**
815      * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode
816      * The line number is computed regarding the function named funname.
817      * @param lineNumber the number of the line
818      * @param funname the function name
819      * @param highlight true to highlight the line
820      * @param setCaret, if true the caret is set at the given line
821      * @param centered, if true the line is centered
822      */
823     public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight, boolean setCaret, boolean centered) {
824         if (funname != null) {
825             Element root = getDocument().getDefaultRootElement();
826             int nlines = root.getElementCount();
827             ScilabDocument.ScilabLeafElement elem;
828             for (int i = 0; i < nlines; i++) {
829                 elem = (ScilabDocument.ScilabLeafElement) root.getElement(i);
830                 if (elem.getFunctionName().equals(funname)) {
831                     lineNumber += i;
832                     break;
833                 }
834             }
835         }
836         scrollTextToLineNumber(lineNumber, highlight, setCaret, centered);
837     }
838
839     /**
840      * @return the width of a white
841      */
842     public int getWhiteWidth() {
843         View view = ((ScilabDocument) getDocument()).getView();
844         if (view != null) {
845             if (view instanceof ScilabView) {
846                 return ((ScilabView) view).getWhiteWidth();
847             } else {
848                 return ((ScilabPlainView) view).getWhiteWidth();
849             }
850         }
851
852         return 0;
853     }
854
855     public void resetFont() {
856         Font font = ((ScilabEditorKit) getEditorKit()).getStylePreferences().getBaseFont();
857         setFont(font);
858         xln.updateFont(font);
859         repaint();
860     }
861
862     /**
863      * Set a new font
864      * @param keyword the type of keyword
865      * @param type an int : -2 to reset italic, -1 to reset bold, 1 to set bold and 2 to set italic
866      */
867     public void resetFont(String keyword, int type) {
868         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genFont(keyword, type);
869     }
870
871     /**
872      * Set a new attribute
873      * @param keyword the type of keyword
874      * @param type an int : 0 nothing, 1 underline, 2 stroke, 3 underline and stroke
875      */
876     public void resetAttribute(String keyword, int type) {
877         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genAttribute(keyword, type);
878     }
879
880     /**
881      * Set a new color
882      * @param keyword the kind of the keyword
883      * @param color the color
884      */
885     public void resetColor(String keyword, Color color) {
886         ((ScilabEditorKit) getEditorKit()).getStylePreferences().genColors(keyword, color);
887     }
888
889     /**
890      * Set to true if the comments must be suppressed when the code is executing in the console
891      * @param b boolean
892      */
893     public void suppressCommentsInExecutingCode(boolean b) {
894         suppressCom = b;
895     }
896
897     /**
898      * Execute the code in the console, the code is the selected text if exists
899      * or the text from beginning to actual position of the caret
900      * Comments are removed if suppressCom is set to true
901      * @return the code to be executed in the console.
902      */
903     public String getCodeToExecute() {
904         String selection;
905         int start, end;
906         start = getSelectionStart();
907         end = getSelectionEnd();
908
909         if (((SciNotesCaret) getCaret()).isEmptySelection()) {
910             try {
911                 if (start == end) {
912                     selection = getDocument().getText(0, start);
913                     start = 0;
914                 } else {
915                     selection = getSelectedText();
916                 }
917             } catch (BadLocationException e) {
918                 selection = "";
919             }
920         } else {
921             selection = getSelectedText();
922         }
923
924         if (suppressCom) {
925             StringBuffer buf = new StringBuffer(selection.length());
926             ScilabLexer.ScilabTokens tokens = ScilabLexer.getScilabTokens(selection);
927             List<Integer> tokType = tokens.getTokenType();
928             List<Integer> tokPos = tokens.getTokenPos();
929             List<String> commands = new ArrayList<String>();
930             int prevPos = 0;
931             for (int i = 0; i < tokType.size(); i++) {
932                 String str = selection.substring(prevPos, tokPos.get(i));
933                 if ("\n".equals(str)) {
934                     commands.add(buf.toString());
935                     buf.setLength(0);
936                 } else if (!ScilabLexerConstants.isComment(tokType.get(i))) {
937                     buf.append(str);
938                 }
939                 prevPos = tokPos.get(i);
940             }
941
942             if (buf.length() != 0) {
943                 commands.add(buf.toString());
944             }
945
946             buf.setLength(0);
947             Pattern pat = Pattern.compile("[ \t]*");
948             for (String command : commands) {
949                 if (!pat.matcher(command).matches()) {
950                     buf.append(command).append("\n");
951                 }
952             }
953
954             return buf.toString();
955         }
956
957         return selection;
958     }
959
960     /**
961      * Add a new KeywordListener
962      * @param kw a KeywordListener
963      */
964     public void addKeywordListener(KeywordListener kw) {
965         kwListeners.add(KeywordListener.class, kw);
966     }
967
968     /**
969      * Remove a new KeywordListener
970      * @param kw a KeywordListener
971      */
972     public void removeKeywordListener(KeywordListener kw) {
973         kwListeners.remove(KeywordListener.class, kw);
974     }
975
976     /**
977      * @return an array of KeywordListener
978      */
979     public KeywordListener[] getKeywordListeners() {
980         return kwListeners.getListeners(KeywordListener.class);
981     }
982
983     /**
984      * Set a new color for the highlighting
985      * @param c the color, can be null (useful if setHighlightedContourColor is used with a
986      * non-null value)
987      */
988     public void setHighlightedLineColor(Color c) {
989         highlightColor = c;
990     }
991
992     /**
993      * Set a new color for the contour of the highlighting
994      * @param c the color, if null no contour is drawn
995      */
996     public void setHighlightedContourColor(Color c) {
997         highlightContourColor = c;
998     }
999
1000     /**
1001      * Activate or desactivate the help on typing
1002      */
1003     public void activateHelpOnTyping() {
1004         boolean isActive = HelpOnTypingManager.isActive();
1005         if (isActive && helpOnTyping == null) {
1006             helpOnTyping = HelpOnTypingManager.getInstance();
1007             addKeyListener(helpOnTyping);
1008         } else if (!isActive && helpOnTyping != null) {
1009             removeKeyListener(helpOnTyping);
1010             helpOnTyping = null;
1011         }
1012     }
1013
1014     /**
1015      * Enable (active true) or disable (active false) the line-highlighting.
1016      * @param active true or false
1017      */
1018     public void enableHighlightedLine(boolean active) {
1019         if (active && !highlightEnable) {
1020             try {
1021                 highlightCL = getHighlighter().addHighlight(0, 0, this);
1022             } catch (BadLocationException e) { }
1023             highlightEnable = true;
1024         }
1025
1026         if (!active && highlightEnable) {
1027             getHighlighter().removeHighlight(highlightCL);
1028             highlightEnable = false;
1029         }
1030
1031         repaint();
1032     }
1033
1034     /**
1035      * Enable (active true) or disable (active false) the matching keywords.
1036      * @param active true or false
1037      */
1038     public void enableMatchingKeywords(boolean active) {
1039         matchingKeywordsEnable = active;
1040     }
1041
1042     /**
1043      * Enable (active true) or disable (active false) the matching keywords.
1044      * @param active true or false
1045      */
1046     public void enableMatchingOpeners(boolean active) {
1047         matchingOpenersEnable = active;
1048     }
1049
1050     /**
1051      * Get a matching manager
1052      * @param lr true if the LR matcher must be returned
1053      * @return the MatchingBlockManager
1054      */
1055     public MatchingBlockManager getMatchingBlockManager(boolean lr) {
1056         if (lr) {
1057             return matchLR;
1058         } else {
1059             return matchRL;
1060         }
1061     }
1062
1063     /**
1064      * This class listens to the caret event
1065      * @param e event
1066      */
1067     public void caretUpdate(CaretEvent e) {
1068         if (hasBeenSaved) {
1069             removeHighlightForLine();
1070         }
1071
1072         if (hasFocus()) {
1073             String str = getSelectedText();
1074             if (str != null && str.length() != 0) {
1075                 highlightWords(str, true);
1076                 removeHighlightOnPosition(getSelectionStart());
1077             } else {
1078                 removeHighlightedWords();
1079             }
1080         }
1081
1082         if (highlightEnable) {
1083             repaint();
1084         }
1085
1086         int pos = getCaretPosition();
1087
1088         if (matchingKeywordsEnable || matchingOpenersEnable) {
1089             int tok = lexer.getKeyword(pos, false);
1090             matchLR.searchMatchingBlock(false, tok, lexer.start + lexer.yychar());
1091             tok = lexer.getKeyword(pos, true);
1092             matchRL.searchMatchingBlock(false, tok, lexer.start + lexer.yychar() + lexer.yylength());
1093         }
1094
1095         if (!readonly && !binary && editor != null) {
1096             editor.getInfoBar().setText(((ScilabDocument) getDocument()).getCurrentFunction(pos));
1097         }
1098     }
1099
1100     /**
1101      * Used to paint the highlighted line
1102      * @param g graphics to use
1103      * @param p0 start
1104      * @param p1 end
1105      * @param bounds the shape representing the area
1106      * @param c this pane
1107      */
1108     public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
1109         if (highlightEnable) {
1110             try {
1111                 Rectangle r = modelToView(getCaretPosition());
1112                 if (highlightColor != null) {
1113                     g.setColor(highlightColor);
1114                     g.fillRect(0, r.y, getWidth(), r.height);
1115                 }
1116                 if (highlightContourColor != null) {
1117                     g.setColor(highlightContourColor);
1118                     g.drawLine(0, r.y - 1, getWidth(), r.y - 1);
1119                     g.drawLine(0, r.y + r.height, getWidth(), r.y + r.height);
1120                 }
1121
1122             } catch (BadLocationException e) { }
1123         }
1124     }
1125
1126     /**
1127      * @return the current TrailingWhiteManager
1128      */
1129     public TrailingWhiteManager getTrailingWhiteManager() {
1130         return trailingWhite;
1131     }
1132
1133     /**
1134      * @return the current IndentManager
1135      */
1136     public IndentManager getIndentManager() {
1137         return indent;
1138     }
1139
1140     /**
1141      * @return the current TabManager
1142      */
1143     public TabManager getTabManager() {
1144         return tab;
1145     }
1146
1147     /**
1148      * @return the current CommentManager
1149      */
1150     public CommentManager getCommentManager() {
1151         return com;
1152     }
1153
1154     /**
1155      * Get a keyword at a position in the document.
1156      * @param position in the document
1157      * @return the KeywordEvent containing infos about keyword.
1158      */
1159     public KeywordEvent getKeywordEvent(int position) {
1160         int tok = lexer.getKeyword(position, true);
1161         return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength());
1162     }
1163
1164     /**
1165      * Get a keyword at the current position in the document.
1166      * @return the KeywordEvent containing infos about keyword.
1167      */
1168     public KeywordEvent getKeywordEvent() {
1169         return getKeywordEvent(getCaretPosition());
1170     }
1171
1172     /**
1173      * Get a keyword at the current position in the document.
1174      * @param caret if true the position is the current caret position in the doc else
1175      * the position is the mouse pointer position projected in the document.
1176      * @param strict if true the char just after the caret is ignored
1177      * @return the KeywordEvent containing infos about keyword.
1178      */
1179     public KeywordEvent getKeywordEvent(boolean caret, boolean strict) {
1180         int tok;
1181         if (caret) {
1182             tok = lexer.getKeyword(getCaretPosition(), strict);
1183         } else {
1184             tok = lexer.getKeyword(viewToModel(mousePoint), strict);
1185         }
1186         return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength());
1187     }
1188
1189     /**
1190      * Get an helpable keyword at the current position in the document.
1191      * @param caret if true the position is the current caret position in the doc else
1192      * the position is the mouse pointer position projected in the document.
1193      * @return the helpable keyword.
1194      */
1195     public String getHelpableKeyword(boolean caret) {
1196         int tok;
1197         int pos;
1198         if (caret) {
1199             pos = getCaretPosition();
1200         } else {
1201             pos = viewToModel(mousePoint);
1202         }
1203
1204         tok = lexer.getKeyword(pos, true);
1205         if (!ScilabLexerConstants.isHelpable(tok)) {
1206             tok = lexer.getKeyword(pos + 1, true);
1207         }
1208
1209         if (ScilabLexerConstants.isHelpable(tok)) {
1210             try {
1211                 return getDocument().getText(lexer.start + lexer.yychar(), lexer.yylength());
1212             } catch (BadLocationException e) { }
1213         }
1214
1215         return null;
1216     }
1217
1218     /**
1219      * Prevents the different KeywordListener that a MouseEvent occured
1220      * @param position of the mouse
1221      * @param ev the event which occured
1222      * @param type of the event : KeywordListener.ONMOUSECLICKED or KeywordListener.ONMOUSEOVER
1223      */
1224     protected void preventConcernedKeywordListener(int position, EventObject ev, int type) {
1225         KeywordEvent kev = null;
1226         Object[] listeners = kwListeners.getListenerList();
1227         for (int i = listeners.length - 2; i >= 0; i -= 2) {
1228             if (listeners[i] == KeywordListener.class && type == ((KeywordListener) listeners[i + 1]).getType()) {
1229                 if (kev == null) {
1230                     int tok = lexer.getKeyword(position, true);
1231                     kev = new KeywordEvent(this, ev, tok, lexer.start + lexer.yychar(), lexer.yylength());
1232                 }
1233
1234                 ((KeywordListener) listeners[i + 1]).caughtKeyword(kev);
1235             }
1236         }
1237     }
1238
1239     /**
1240      * Implements mouseClicked in MouseListener
1241      * @param e event
1242      */
1243     public void mouseClicked(MouseEvent e) {
1244         preventConcernedKeywordListener(getCaretPosition(), e, KeywordListener.ONMOUSECLICKED);
1245     }
1246
1247     /**
1248      * Implements mouseEntered in MouseListener
1249      * @param e event
1250      */
1251     public void mouseEntered(MouseEvent e) {
1252         this.mousePoint = e.getPoint();
1253     }
1254
1255     /**
1256      * Implements mouseExited in MouseListener
1257      * @param e event
1258      */
1259     public void mouseExited(MouseEvent e) { }
1260
1261     /**
1262      * Implements mousePressed in MouseListener
1263      * @param e event
1264      */
1265     public void mousePressed(MouseEvent e) {
1266         if (hasBeenSaved) {
1267             removeHighlightForLine();
1268         }
1269
1270         removeHighlightedWords();
1271
1272         if (highlightEnable) {
1273             repaint();
1274         }
1275     }
1276
1277     /**
1278      * Implements mouseReleseaed in MouseListener
1279      * @param e event
1280      */
1281     public void mouseReleased(MouseEvent e) { }
1282
1283     /**
1284      * Implements mouseMoved in MouseMotionListener
1285      * @param e event
1286      */
1287     public void mouseMoved(MouseEvent e) {
1288         this.mousePoint = e.getPoint();
1289         preventConcernedKeywordListener(viewToModel(mousePoint), e, KeywordListener.ONMOUSEOVER);
1290     }
1291
1292     /**
1293      * Implements mouseDragged in MouseMotionListener
1294      * @param e event
1295      */
1296     public void mouseDragged(MouseEvent e) {
1297         if (hasBeenSaved) {
1298             removeHighlightForLine();
1299         }
1300
1301         removeHighlightedWords();
1302
1303         if (highlightEnable) {
1304             repaint();
1305         }
1306     }
1307
1308     /**
1309      * @return the current mouse poisition in this pane
1310      */
1311     public Point getMousePoint() {
1312         return mousePoint;
1313     }
1314
1315     /**
1316      * @param pane the EditorPane associated with this EditorPane in a splitted view
1317      */
1318     public void setOtherPaneInSplit(ScilabEditorPane pane) {
1319         if (pane == null) {
1320             rightTextPane.rightTextPane = null;
1321         }
1322         rightTextPane = pane;
1323     }
1324
1325     /**
1326      * @return the EditorPane associated with this EditorPane in a splitted view
1327      */
1328     public ScilabEditorPane getOtherPaneInSplit() {
1329         return rightTextPane;
1330     }
1331
1332     /**
1333      * @return the scrollPane associated with this EditorPane
1334      */
1335     public JScrollPane getScrollPane() {
1336         return edComponent.getScrollPane();
1337     }
1338
1339     /**
1340      * @return the current focused editorPane
1341      */
1342     public static ScilabEditorPane getFocusedPane() {
1343         return focused;
1344     }
1345
1346     /**
1347      * {@inheritDoc}
1348      */
1349     public String toString() {
1350         return shortName;
1351     }
1352
1353     /**
1354      * @return true if something has been copied
1355      */
1356     public boolean copyColumnSelectionInClipBoard() {
1357         return ((SciNotesCaret) getCaret()).copyPositionsInClipboard();
1358     }
1359
1360     /**
1361      * @return true if something has been removed
1362      */
1363     public boolean removeColumnSelection() {
1364         return ((SciNotesCaret) getCaret()).removePositions();
1365     }
1366
1367     /**
1368      * {@inheritDoc}
1369      */
1370     public String getSelectedText() {
1371         String str = ((SciNotesCaret) getCaret()).getSelectedText();
1372         if (str == null) {
1373             return super.getSelectedText();
1374         } else {
1375             return str;
1376         }
1377     }
1378
1379     /**
1380      * @param pos the position int the text
1381      * @return null if no column selection on the same line and an array of
1382      * integer (of size 2) containing the position of the selection
1383      */
1384     public int[] isNearColumnSelection(int pos) {
1385         if (!(getCaret() instanceof SciNotesCaret) || ((SciNotesCaret) getCaret()).isEmptySelection()) {
1386             return null;
1387         }
1388
1389         Element root = getDocument().getDefaultRootElement();
1390         int[][] positions = ((SciNotesCaret) getCaret()).getSelectedPositions();
1391         int line = root.getElementIndex(pos);
1392         int min = root.getElementIndex(positions[0][0]);
1393         int max = root.getElementIndex(positions[positions.length - 1][0]);
1394
1395         if (line >= min && line <= max) {
1396             return positions[line - min];
1397         }
1398
1399         return null;
1400     }
1401
1402     /**
1403      * {@inheritDoc}
1404      */
1405     public void setCaret(Caret c) {
1406         if (!(c instanceof ScilabCaret)) {
1407             final Caret caret = new SciNotesCaret(this);
1408             setCaretColor(getCaretColor());
1409             SwingUtilities.invokeLater(new Runnable() {
1410                 public void run() {
1411                     int blinkRate = 500;
1412                     Object o = UIManager.get("TextComponent.caretBlinkRate");
1413                     if ((o != null) && (o instanceof Integer)) {
1414                         Integer rate = (Integer) o;
1415                         blinkRate = rate.intValue();
1416                     }
1417                     caret.setBlinkRate(blinkRate);
1418                     caret.setVisible(true);
1419                 }
1420             });
1421             super.setCaret(caret);
1422         } else {
1423             super.setCaret(c);
1424         }
1425     }
1426
1427     /**
1428      * {@inheritDoc}
1429      */
1430     public void select(int start, int end) {
1431         removeHighlightOnPosition(start);
1432         int docLength = getDocument().getLength();
1433         if (start > docLength) {
1434             start = docLength;
1435         }
1436         if (end > docLength) {
1437             end = docLength;
1438         }
1439         super.setCaretPosition(start);
1440         super.moveCaretPosition(end);
1441     }
1442
1443     /**
1444      * Remove the highlight putted to show the line (for editor('foo',123))
1445      */
1446     private void removeHighlightForLine() {
1447         highlightContourColor = saveHighlightContourColor;
1448         highlightColor = saveHighlightColor;
1449         enableHighlightedLine(false);
1450         if (saveHighlightEnable) {
1451             enableHighlightedLine(true);
1452         }
1453         hasBeenSaved = false;
1454     }
1455
1456     /**
1457      * Remove the highlight at position start
1458      * @param start the beginning of the highlight
1459      */
1460     public void removeHighlightOnPosition(int start) {
1461         int pos = highlightedWordsBegin.indexOf(start);
1462         if (pos != -1) {
1463             getHighlighter().removeHighlight(highlightedWords.remove(pos));
1464             highlightedWordsBegin.remove(pos);
1465         }
1466     }
1467
1468     /**
1469      * Highlight a word in this textpane.
1470      * @param word the word to highlight
1471      * @param exact if true the search is case sensitive
1472      */
1473     public void highlightWords(String word, boolean exact) {
1474         removeHighlightedWords();
1475         if (word != null && word.length() != 0) {
1476             String text = ((ScilabDocument) getDocument()).getText();
1477             if (!exact) {
1478                 text = text.toLowerCase();
1479                 word = word.toLowerCase();
1480             }
1481
1482             int pos = text.indexOf(word, 0);
1483             int len = word.length();
1484             Highlighter highlighter = getHighlighter();
1485             List<Rectangle> marks = new ArrayList<Rectangle>();
1486             while (pos != -1) {
1487                 try {
1488                     highlightedWords.add(highlighter.addHighlight(pos, pos + len, HIGHLIGHTER));
1489                     highlightedWordsBegin.add(pos);
1490                     Rectangle r = modelToView(pos);
1491                     if (marks.size() == 0 || marks.get(marks.size() - 1).y != r.y) {
1492                         marks.add(r);
1493                     }
1494                 } catch (BadLocationException e) { }
1495                 pos = text.indexOf(word, pos + len);
1496             }
1497             ((ScilabScrollPane) edComponent.getScrollPane()).putMarks(marks);
1498         }
1499     }
1500
1501     /**
1502      * Highlight a word according to a pattern in this textpane.
1503      * @param pattern the pattern to highlight
1504      * @param centered, if true the pane is centered on the first occurence
1505      */
1506     public void highlightWords(Pattern pattern, boolean centered) {
1507         if (pattern != null) {
1508             removeHighlightedWords();
1509             int first = -1;
1510             String text = ((ScilabDocument) getDocument()).getText();
1511             Matcher matcher = pattern.matcher(text);
1512
1513             Highlighter highlighter = getHighlighter();
1514             List<Rectangle> marks = new ArrayList<Rectangle>();
1515             while (matcher.find()) {
1516                 if (first == -1) {
1517                     first = matcher.start();
1518                 }
1519                 try {
1520                     int start = matcher.start();
1521                     highlightedWords.add(highlighter.addHighlight(start, matcher.end(), HIGHLIGHTER));
1522                     highlightedWordsBegin.add(start);
1523                     Rectangle r = modelToView(start);
1524                     if (marks.size() == 0 || marks.get(marks.size() - 1).y != r.y) {
1525                         marks.add(r);
1526                     }
1527                 } catch (BadLocationException e) { }
1528             }
1529
1530             ((ScilabScrollPane) edComponent.getScrollPane()).putMarks(marks);
1531
1532             if (centered && first != -1) {
1533                 scrollTextToPos(first, false, true);
1534             }
1535         }
1536     }
1537
1538     /**
1539      * Remove all the highlighted words
1540      */
1541     public void removeHighlightedWords() {
1542         Highlighter highlighter = getHighlighter();
1543         for (Object obj : highlightedWords) {
1544             highlighter.removeHighlight(obj);
1545         }
1546         highlightedWords.clear();
1547         highlightedWordsBegin.clear();
1548         ((ScilabScrollPane) edComponent.getScrollPane()).removeMarks();
1549     }
1550
1551     /**
1552      * Initialize the pane when the document is loaded
1553      * @param doc used with this pane
1554      */
1555     private void initialize(ScilabDocument doc) {
1556         indent = new IndentManager(doc);
1557         tab = new TabManager(doc, indent);
1558         tab.setDefaultTabulation();
1559         com = new CommentManager(doc);
1560         trailingWhite = new TrailingWhiteManager(doc);
1561
1562         if (matchingKeywordsEnable || matchingOpenersEnable) {
1563             matchLR = new MatchingBlockManager(doc, this, true, getHighlighter());
1564             matchLR.setDefaults();
1565             matchRL = new MatchingBlockManager(doc, this, false, getHighlighter());
1566             matchRL.setDefaults();
1567         }
1568
1569         lexer = doc.createLexer();
1570         xln = new SciNotesLineNumberPanel(this);
1571
1572         /* The order of the next two lines is important: the doc
1573            as listener will be called before xln so the resetTypeWhenBroken
1574            will be called before ! */
1575         doc.addDocumentListener(xln);
1576         doc.addDocumentListener(doc);
1577
1578         edComponent.getScrollPane().setRowHeaderView(xln);
1579         doc.setEditorPane(this);
1580
1581         if (editor != null) {
1582             NavigatorWindow nav = editor.getNavigator();
1583             if (nav != null) {
1584                 nav.addEditorPane(this);
1585             }
1586         }
1587
1588         resetFont();
1589     }
1590 }