householder documentation page was missing some improvements
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / SciNotes.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2010 - 2011 - Calixte DENIZET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.scinotes;
18
19 import java.awt.Color;
20 import java.awt.Component;
21 import java.awt.Font;
22 import java.awt.event.FocusEvent;
23 import java.awt.event.FocusListener;
24 import java.io.BufferedReader;
25 import java.io.BufferedWriter;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileOutputStream;
30 import java.io.InputStreamReader;
31 import java.io.IOException;
32 import java.io.OutputStreamWriter;
33 import java.io.StringReader;
34 import java.lang.reflect.Constructor;
35 import java.lang.reflect.InvocationTargetException;
36 import java.nio.charset.CharacterCodingException;
37 import java.nio.charset.Charset;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.StringTokenizer;
45 import java.util.UUID;
46 import java.util.logging.Logger;
47
48 import javax.swing.BorderFactory;
49 import javax.swing.JButton;
50 import javax.swing.JComponent;
51 import javax.swing.JFileChooser;
52 import javax.swing.JFrame;
53 import javax.swing.JOptionPane;
54 import javax.swing.JPanel;
55 import javax.swing.JSplitPane;
56 import javax.swing.KeyStroke;
57 import javax.swing.SwingUtilities;
58 import javax.swing.event.ChangeEvent;
59 import javax.swing.event.ChangeListener;
60 import javax.swing.text.BadLocationException;
61 import javax.swing.text.EditorKit;
62 import javax.swing.text.View;
63 import javax.swing.undo.UndoManager;
64
65 import org.w3c.dom.Document;
66
67 import org.flexdock.docking.event.DockingEvent;
68 import org.scilab.modules.commons.CommonFileUtils;
69 import org.scilab.modules.commons.gui.ScilabKeyStroke;
70 import org.scilab.modules.commons.xml.ScilabXMLUtilities;
71 import org.scilab.modules.commons.xml.XConfiguration;
72 import static org.scilab.modules.commons.xml.XConfiguration.XConfAttribute;
73 import org.scilab.modules.core.Scilab;
74 import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser;
75 import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel;
76 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
77 import org.scilab.modules.gui.filechooser.Juigetfile;
78 import org.scilab.modules.gui.filechooser.ScilabFileChooser;
79 import org.scilab.modules.gui.menubar.MenuBar;
80 import org.scilab.modules.gui.messagebox.MessageBox;
81 import org.scilab.modules.gui.messagebox.ScilabMessageBox;
82 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
83 import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption;
84 import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType;
85 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
86 import org.scilab.modules.gui.tab.SimpleTab;
87 import org.scilab.modules.gui.tabfactory.ScilabTabFactory;
88 import org.scilab.modules.gui.textbox.TextBox;
89 import org.scilab.modules.gui.toolbar.ToolBar;
90 import org.scilab.modules.gui.utils.ClosingOperationsManager;
91 import org.scilab.modules.gui.utils.ConfigManager;
92 import org.scilab.modules.gui.utils.Position;
93 import org.scilab.modules.gui.utils.SciFileFilter;
94 import org.scilab.modules.gui.utils.Size;
95 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
96
97 import org.scilab.modules.scinotes.actions.DoubleQuoteStringAction;
98 import org.scilab.modules.scinotes.actions.EncodingAction;
99 import org.scilab.modules.scinotes.actions.EndOfLineAction;
100 import org.scilab.modules.scinotes.actions.ExitAction;
101 import org.scilab.modules.scinotes.actions.FindAction;
102 import org.scilab.modules.scinotes.actions.IncrementalSearchAction;
103 import org.scilab.modules.scinotes.actions.IndentAction;
104 import org.scilab.modules.scinotes.actions.InsertOverwriteAction;
105 import org.scilab.modules.scinotes.actions.LineBeautifierAction;
106 import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction;
107 import org.scilab.modules.scinotes.actions.RecentFileAction;
108 import org.scilab.modules.scinotes.actions.RegisterFavoriteDirsAction;
109 import org.scilab.modules.scinotes.actions.RemoveTrailingWhiteAction;
110 import org.scilab.modules.scinotes.actions.RestoreOpenedFilesAction;
111 import org.scilab.modules.scinotes.actions.SciNotesCompletionAction;
112 import org.scilab.modules.scinotes.actions.SearchWordInFilesAction;
113 import org.scilab.modules.scinotes.tabfactory.CodeNavigatorTab;
114 import org.scilab.modules.scinotes.tabfactory.SciNotesTab;
115 import org.scilab.modules.scinotes.tabfactory.SciNotesTabFactory;
116 import org.scilab.modules.scinotes.tabfactory.SearchInFilesTab;
117 import org.scilab.modules.scinotes.utils.ConfigSciNotesManager;
118 import org.scilab.modules.scinotes.utils.DropFilesListener;
119 import org.scilab.modules.scinotes.utils.NavigatorWindow;
120 import org.scilab.modules.scinotes.utils.SaveFile;
121 import org.scilab.modules.scinotes.utils.SciNotesContents;
122 import org.scilab.modules.scinotes.utils.SciNotesMessages;
123 import org.scilab.modules.scinotes.utils.ScilabTabbedPane;
124 import org.scilab.modules.scinotes.utils.SearchFile;
125
126 /**
127  * Main SciNotes class.
128  *
129  * @author Bruno JOFRET
130  * @author Calixte DENIZET
131  */
132 public class SciNotes extends SwingScilabDockablePanel {
133
134     private static final long serialVersionUID = -6410183357490518676L;
135
136     private static final String XPATH_SCINOTES_KEY = "//general/shortcuts/body/actions/action-folder[@name='Scinotes']/action";
137     private static final String XPATH_SCINOTES_ACTION = "/map/scinotes/entry";
138
139     private static final String SCINOTES = "SciNotes";
140     private static final String SCI_EXTENSION = ".sci";
141     private static final String SCE_EXTENSION = ".sce";
142     private static final String TST_EXTENSION = ".tst";
143     private static final String QUIT_EXTENSION = ".quit";
144     private static final String DEM_EXTENSION = ".dem";
145     private static final String START_EXTENSION = ".start";
146     private static final String ALL_TST_FILES = "*.tst";
147     private static final String ALL_QUIT_FILES = "*.quit";
148     private static final String ALL_START_FILES = "*.start";
149     private static final String ALL_SCI_FILES = "*.sci";
150     private static final String ALL_SCE_FILES = "*.sce";
151     private static final String ALL_DEM_FILES = "*.dem";
152     private static final String ALL_SCX_FILES = "*.sc*";
153     private static final String ALL_SCILAB = "all";
154     private static final String ALL_FILES = "*.*";
155     private static final String DOT = ".";
156
157     private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions";
158
159     private static final Map<String, String> actionToName;
160     private static Map<String, KeyStroke> actionKeys;
161
162     private static List<SciNotes> scinotesList = new ArrayList<SciNotes>();
163     private static SciNotes editor;
164     private static boolean mustWrapLines;
165
166     private SwingScilabWindow parentWindow;
167     private UUID uuid;
168
169     private ScilabTabbedPane tabPane;
170     private final SciNotesContents contentPane;
171     private NavigatorWindow navigator;
172     private SearchFile searchInFiles;
173
174     private int numberOfUntitled;
175     private EditorKit editorKit;
176
177     private JButton undoButton;
178     private JButton redoButton;
179
180     private boolean protectOpenFileList;
181     private boolean restored;
182     private boolean firstOpen = true;
183
184     private final List<Integer> tabList = new ArrayList<Integer>();
185     private final List<Integer> closedTabList = new ArrayList<Integer>();
186
187     static {
188         ConfigSciNotesManager.createUserCopy();
189         ScilabTabFactory.getInstance().addTabFactory(SciNotesTabFactory.getInstance());
190         Scilab.registerInitialHook(new Runnable() {
191             @Override
192             public void run() {
193                 updateSciNotes();
194             }
195         });
196
197         Document doc = ScilabXMLUtilities.readDocument(System.getenv("SCI") + "/modules/console/etc/Actions-Configuration.xml");
198         actionToName = XConfiguration.get(doc, "name", String.class, "action", String.class, XPATH_SCINOTES_ACTION);
199         XConfiguration.addXConfigurationListener(new SciNotesConfiguration());
200     }
201
202     /**
203      * Create SciNotes instance
204      */
205     public SciNotes(String uuid) {
206         super(SCINOTES, uuid);
207         setWindowIcon("accessories-text-editor");
208         setAssociatedXMLIDForHelp("scinotes");
209         this.uuid = UUID.fromString(uuid);
210         SciNotesAutosave.autosave();
211         editor = this;
212         scinotesList.add(this);
213         numberOfUntitled = 0;
214         mustWrapLines = SciNotesOptions.getSciNotesDisplay().wrapLines;
215         editorKit = new ScilabEditorKit(!mustWrapLines);
216         protectOpenFileList = false;
217         contentPane = new SciNotesContents(this);
218         tabPane = contentPane.getScilabTabbedPane();
219         tabPane.addChangeListener(new ChangeListener() {
220             @Override
221             public void stateChanged(ChangeEvent e) {
222                 if (getTextPane() != null) {
223                     // updateUI();
224                     getTextPane().updateInfosWhenFocused();
225                     getTextPane().requestFocus();
226                     getTextPane().highlightWords(IncrementalSearchAction.getWord(SciNotes.this), IncrementalSearchAction.getExact(SciNotes.this));
227
228                     // Update encoding menu
229                     EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
230
231                     // Update End Of Line menu
232                     EndOfLineAction.updateEolMenu((ScilabDocument) getTextPane().getDocument());
233                     setTitle(getTextPane().getTitle());
234                 }
235             }
236         });
237         this.setContentPane(contentPane);
238     }
239
240     /**
241      * Default constructor
242      */
243     public SciNotes() {
244         this(UUID.randomUUID().toString());
245     }
246
247     public static void configurationChanged(SciNotesConfiguration.Conf conf) {
248         setWhereamiLineNumbering();
249         setAutoIndent();
250         setHorizontalWrap();
251         setDefaultTabulation();
252         if (conf.keymap) {
253             actionKeys = null;
254             setKeyStrokeActions();
255             setAllMenus();
256         }
257         if (conf.autosave) {
258             SciNotesAutosave.stopAutosave();
259             SciNotesAutosave.autosave();
260         }
261         if (conf.preferences) {
262             RecentFileAction.updateRecentOpenedFilesMenu();
263         }
264
265         updatePanes(conf);
266     }
267
268     public static Map<String, KeyStroke> getActionKeys() {
269         if (actionKeys == null) {
270             Document doc = XConfiguration.getXConfigurationDocument();
271             actionKeys = XConfiguration.get(doc, "name", String.class, "key", KeyStroke.class, XPATH_SCINOTES_KEY);
272         }
273
274         return actionKeys;
275     }
276
277     public static Map<String, String> getActionName() {
278         return actionToName;
279     }
280
281     /**
282      * Get an opened editor from its uuid
283      *
284      * @param uuid
285      *            the uuid
286      * @return the corresponding editor
287      */
288     public static SciNotes getEditorFromUUID(String uuid) {
289         for (SciNotes ed : scinotesList) {
290             if (ed.getPersistentId().equals(uuid)) {
291                 return ed;
292             }
293         }
294
295         return null;
296     }
297
298     public void setParentWindow() {
299         this.parentWindow = SwingScilabWindow.createWindow(true);
300         parentWindow.setLocation(150, 50);
301         parentWindow.setSize(650, 550);
302     }
303
304     /**
305      * {@inheritDoc}
306      */
307     @Override
308     public void setTitle(String title) {
309         super.setTitle(title);
310         SwingScilabWindow window = (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, tabPane);
311         if (window != null) {
312             window.setTitle(title);
313         }
314     }
315
316     public void insertBottomComponent(Component c) {
317         contentPane.insertBottomComponent(c);
318     }
319
320     /**
321      * @return the SwingScilabWindow containing this editor
322      */
323     public SwingScilabWindow getSwingParentWindow() {
324         return (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this);
325     }
326
327     /**
328      * {@inheritDoc}
329      */
330     @Override
331     public void undockingComplete(DockingEvent evt) {
332         super.undockingComplete(evt);
333         if (navigator != null) {
334             navigator.addToolBar(null);
335         }
336         if (searchInFiles != null) {
337             searchInFiles.addToolBar(null);
338         }
339     }
340
341     /**
342      * {@inheritDoc}
343      */
344     @Override
345     public void dockingComplete(DockingEvent evt) {
346         super.dockingComplete(evt);
347         if (navigator != null) {
348             navigator.changeToolBar();
349         }
350         if (searchInFiles != null) {
351             searchInFiles.changeToolBar();
352         }
353     }
354
355     /**
356      * Add a code navigator
357      */
358     public void addNavigator() {
359         if (navigator == null) {
360             String navUUID = ConfigSciNotesManager.getCodeNavigatorStateForEditor(getPersistentId());
361             boolean success = WindowsConfigurationManager.restoreUUID(navUUID);
362             if (!success) {
363                 navigator = CodeNavigatorTab.getCodeNavigatorInstance(this, null);
364                 navigator.setParentWindow();
365             }
366             int count = getTabPane().getTabCount();
367             for (int i = 0; i < count; i++) {
368                 navigator.addEditorPane(getTextPane(i));
369             }
370         }
371     }
372
373     /**
374      * Add a code navigator
375      */
376     public void addNavigator(NavigatorWindow navigator) {
377         this.navigator = navigator;
378     }
379
380     /**
381      * Remove the navigator
382      */
383     public void removeNavigator() {
384         navigator = null;
385     }
386
387     /**
388      * @return the navigator associated with this editor
389      */
390     public NavigatorWindow getNavigator() {
391         return navigator;
392     }
393
394     /**
395      * Add a Search in files
396      */
397     public void addSearchInFiles() {
398         if (searchInFiles == null) {
399             String sfUUID = ConfigSciNotesManager.getSearchInFilesStateForEditor(getPersistentId());
400             boolean success = WindowsConfigurationManager.restoreUUID(sfUUID);
401             if (!success) {
402                 searchInFiles = SearchInFilesTab.getSearchInFilesTabInstance(this, null);
403                 searchInFiles.setParentWindow();
404             }
405         }
406     }
407
408     /**
409      * Add a Search In Files
410      */
411     public void addSearchInFiles(SearchFile sf) {
412         this.searchInFiles = sf;
413     }
414
415     /**
416      * Remove Search in Files
417      */
418     public void removeSearchInFiles() {
419         searchInFiles = null;
420     }
421
422     /**
423      * @return the Search In Files associated with this editor
424      */
425     public SearchFile getSearchInFiles() {
426         return searchInFiles;
427     }
428
429     /**
430      * Update the editor
431      */
432     public static void updateSciNotes() {
433         ScilabLexer.update();
434         for (SciNotes editor : scinotesList) {
435             if (editor.getTextPane() != null) {
436                 editor.getTextPane().repaint();
437             }
438         }
439     }
440
441     /**
442      * Launch SciNotes with an empty file
443      *
444      * This method *must not* be called on the EDT thread.
445      */
446     public static void scinotes() {
447         ScilabLexer.update();
448         try {
449             SwingUtilities.invokeAndWait(new Runnable() {
450
451                 @Override
452                 public void run() {
453                     launchSciNotes();
454                     // Open an empty file if no tabs were opened at launch.
455                     if (editor.getTabPane().getTabCount() == 0) {
456                         editor.openFile(null, 0, null);
457                     }
458                 }
459             });
460         } catch (InterruptedException e) {
461             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
462             throw new RuntimeException(e);
463         } catch (InvocationTargetException e) {
464             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
465             e.printStackTrace();
466             throw new RuntimeException(e);
467         }
468     }
469
470     /**
471      * Launch SciNotes with a file name to open.
472      *
473      * @param filePath
474      *            the name of the file to open
475      *
476      *            This method *must not* be called on the EDT thread.
477      */
478     public static void scinotes(final String filePath) {
479         ScilabLexer.update();
480         try {
481             SwingUtilities.invokeAndWait(new Runnable() {
482
483                 @Override
484                 public void run() {
485                     launchSciNotes();
486                     editor.openFile(filePath, 0, null);
487                 }
488             });
489         } catch (InterruptedException e) {
490             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
491             throw new RuntimeException(e);
492         } catch (InvocationTargetException e) {
493             e.printStackTrace();
494             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
495             throw new RuntimeException(e);
496         }
497     }
498
499     /**
500      * Launch SciNotes with a file name to open and a line to highlight.
501      *
502      * @param filePath
503      *            the name of the file to open
504      * @param lineNumber
505      *            the line to highlight
506      *
507      *            This method *must not* be called on the EDT thread.
508      */
509     public static void scinotes(final String filePath, final int lineNumber, final String functionName) {
510         ScilabLexer.update();
511         try {
512             SwingUtilities.invokeAndWait(new Runnable() {
513
514                 @Override
515                 public void run() {
516                     launchSciNotes();
517                     editor.openFile(filePath, lineNumber, functionName);
518                 }
519             });
520         } catch (InterruptedException e) {
521             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
522             throw new RuntimeException(e);
523         } catch (InvocationTargetException e) {
524             e.printStackTrace();
525             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
526             throw new RuntimeException(e);
527         }
528     }
529
530     /**
531      * Launch SciNotes with a file name to open and a line to highlight.
532      *
533      * @param filePath
534      *            the name of the file to open
535      * @param option
536      *            such as 'readonly'
537      *
538      *            This method *must not* be called on the EDT thread.
539      */
540     public static void scinotes(final String filePath, final String[] options) throws Exception {
541         boolean hasAction = false;
542         if (options != null && options.length != 0) {
543             try {
544                 hasAction = executeAction(filePath, options);
545             } catch (FileNotFoundException e) {
546                 throw new Exception(String.format(SciNotesMessages.INVALID_FILE, filePath));
547             } catch (IOException e) {
548                 throw new Exception(String.format(SciNotesMessages.IO_EXCEPTION, e.getLocalizedMessage()));
549             }
550         }
551
552         if (hasAction) {
553             return;
554         }
555
556         ScilabLexer.update();
557         try {
558             SwingUtilities.invokeAndWait(new Runnable() {
559
560                 @Override
561                 public void run() {
562                     launchSciNotes();
563                     if (options != null && options.length != 0) {
564                         editor.openFile(filePath, 0, options[0]);
565                     } else {
566                         editor.openFile(filePath, 0, "");
567                     }
568                 }
569             });
570         } catch (InterruptedException e) {
571             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
572             throw new RuntimeException(e);
573         } catch (InvocationTargetException e) {
574             e.printStackTrace();
575             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
576             throw new RuntimeException(e);
577         }
578     }
579
580     /**
581      * Launch SciNotes with a provided text (from the help for example).
582      *
583      * @param text
584      *            the text which should be modified
585      */
586     public static void scinotesWithText(String text) {
587         ScilabLexer.update();
588         launchSciNotes();
589         ScilabEditorPane theTextPane;
590         if (editor.getTabPane().getTabCount() != 0 && editor.getTextPane(0) != null) {
591             String name = editor.getTextPane(0).getName();
592             if (name == null) {
593                 theTextPane = editor.getTextPane(0);
594             } else {
595                 theTextPane = editor.addEmptyTab();
596             }
597         } else {
598             theTextPane = editor.addEmptyTab();
599         }
600
601         ScilabDocument styleDocument = (ScilabDocument) theTextPane.getDocument();
602         try {
603             editor.getEditorKit().read(new StringReader(text), styleDocument, theTextPane.getCaretPosition());
604         } catch (IOException e) {
605             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
606         } catch (BadLocationException e) {
607             System.err.println(SciNotesMessages.ERROR_WITH_STRING);
608         }
609     }
610
611     /**
612      * Clone the current tab and if b is true close the tab
613      *
614      * @param ed
615      *            the editor where the tab is
616      * @param b
617      *            a boolean
618      */
619     public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b) {
620         ScilabDocument cdoc = (ScilabDocument) ed.getTextPane().getDocument();
621         String title = ed.getTabPane().getScilabTitleAt(ed.getTabPane().getSelectedIndex());
622         ScilabEditorPane currentSep = ed.getTextPane();
623         String winTitle = ed.getTitle();
624
625         if (b) {
626             ed.closeTabAtWithoutConfirmation(ed.getTabPane().getSelectedIndex());
627             if (ed.getTabPane().getTabCount() == 0) {
628                 ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabDockablePanel) ed);
629                 ConfigSciNotesManager.removeEditorUUID(ed.uuid.toString());
630             }
631         }
632
633         editor = null;
634
635         scinotesWithText(cdoc.getText());
636         ScilabEditorPane sep = editor.getTextPane();
637
638         if (currentSep.getName() != null) {
639             sep.setTitle(title);
640             editor.setTitle(winTitle);
641         }
642
643         currentSep.copyProps(sep);
644         ScilabDocument sdoc = (ScilabDocument) sep.getDocument();
645         sdoc.setContentModified(cdoc.isContentModified());
646         sdoc.getUndoManager().discardAllEdits();
647         sep.setCaretPosition(0);
648         editor.enableUndoButton(false);
649         editor.enableRedoButton(false);
650         ConfigSciNotesManager.saveToOpenFiles(sep.getName(), editor, editor.getTextPane());
651
652         editor.activeRestoreTab();
653     }
654
655     /**
656      * Clone the current tab and if b is true close the tab
657      *
658      * @param ed
659      *            the editor where the tab is
660      * @param b
661      *            a boolean
662      */
663     public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b, int x, int y) {
664         cloneAndCloseCurrentTab(ed, b);
665         editor.getSwingParentWindow().setLocation(x, y);
666     }
667
668     /**
669      * Execute after when the restoration is finished
670      */
671     @Override
672     public void endedRestoration() {
673         if (!SwingUtilities.isEventDispatchThread()) {
674             try {
675                 SwingUtilities.invokeAndWait(new Runnable() {
676
677                     @Override
678                     public void run() {
679                         restorePreviousSession();
680                     }
681                 });
682             } catch (InterruptedException e) {
683                 Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
684                 throw new RuntimeException(e);
685             } catch (InvocationTargetException e) {
686                 Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
687                 throw new RuntimeException(e);
688             }
689         } else {
690             restorePreviousSession();
691         }
692     }
693
694     /**
695      * Restore the previous session
696      */
697     public void restorePreviousSession() {
698         restored = true;
699         if (!SciNotesOptions.getSciNotesPreferences().restartOpen || !ConfigSciNotesManager.getRestoreOpenedFiles() || ConfigSciNotesManager.countExistingOpenFiles(getUUID()) == 0) {
700             if (getTabPane().getTabCount() == 0) {
701                 openFile(null, 0, null);
702             }
703
704             WindowsConfigurationManager.restorationFinished(this);
705
706             return;
707         }
708
709         addRestoreTab();
710         WindowsConfigurationManager.restorationFinished(SciNotes.this);
711     }
712
713     /**
714      * Create SciNotes instance
715      *
716      * @return the instance
717      */
718     public static void launchSciNotes() {
719         if (editor == null) {
720             List<String> uuids = ConfigSciNotesManager.getEditorsUUID();
721             boolean success = false;
722             if (!uuids.isEmpty()) {
723                 for (String uuid : uuids) {
724                     boolean exists = false;
725                     for (SciNotes ed : scinotesList) {
726                         if (ed.uuid.toString().equals(uuid)) {
727                             exists = true;
728                             break;
729                         }
730                     }
731                     if (!exists) {
732                         success = WindowsConfigurationManager.restoreUUID(uuid);
733                         if (success) {
734                             break;
735                         }
736                         ConfigSciNotesManager.removeEditorUUID(uuid);
737                     }
738                 }
739             }
740             if (!success) {
741                 editor = SciNotesTab.getEditorInstance(null);
742                 editor.setParentWindow();
743                 ConfigSciNotesManager.saveEditorUUID(editor.getPersistentId());
744                 SciNotesGUI.init(editor.getParentWindow(), editor, SCINOTES);
745                 WindowsConfigurationManager.unregisterEndedRestoration(editor);
746             }
747         }
748
749         if (!editor.restored) {
750             editor.restorePreviousSession();
751         }
752     }
753
754     /**
755      * Open a file.
756      *
757      * This method *must* be called on the EDT thread.
758      *
759      * @param filePath
760      *            the file path (may be null)
761      * @param lineNumber
762      *            the line number (use 0 for unspecified)
763      * @param option
764      *            the options (may be null)
765      */
766     public void openFile(String filePath, int lineNumber, String option) {
767         if (!SwingUtilities.isEventDispatchThread()) {
768             throw new RuntimeException("called outside the EDT thread.");
769         }
770
771         if (filePath == null) {
772             addEmptyTab();
773             activeRestoreTab();
774             return;
775         }
776
777         File f = fileToCanonicalFile(new File(filePath));
778         if (!f.getParentFile().exists()) {
779             JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.OPEN_ERROR);
780             addEmptyTab();
781             activeRestoreTab();
782             return;
783         }
784
785         if (f.isDirectory()) { /* Bug 5131 */
786             ConfigManager.saveLastOpenedDirectory(f.getPath());
787             addEmptyTab();
788             activeRestoreTab();
789             return;
790         }
791
792         readFileAndWait(f);
793         if (option == null || option.length() == 0 || "readonly".equals(option.toLowerCase())) {
794             getTextPane().scrollTextToLineNumber(lineNumber, true);
795         } else {
796             getTextPane().scrollTextToLineNumberInWhereami(lineNumber, option, true);
797         }
798         if ((option != null && "readonly".equals(option.toLowerCase()))) {
799             getTextPane().setReadOnly(true);
800             getInfoBar().setText(getTextPane().getInfoBarText());
801             ConfigSciNotesManager.removeFromOpenFiles(this, getTextPane());
802         } else {
803             ConfigSciNotesManager.saveToRecentOpenedFiles(filePath);
804             RecentFileAction.updateRecentOpenedFilesMenu(this);
805         }
806
807         activeRestoreTab();
808     }
809
810     public void activeRestoreTab() {
811         if (getTextPane(0) == null) {
812             tabPane.setSelectedIndex(0);
813             getInfoBar().setText("");
814         }
815     }
816
817     /**
818      * Close SciNotes instance including all tabs.
819      */
820     public void closeSciNotes() {
821         for (int i = 0; i < getTabPane().getTabCount(); i++) {
822             ScilabEditorPane textPaneAt = getTextPane(i);
823             if (textPaneAt != null) {
824                 textPaneAt.destroy();
825             }
826         }
827
828         FindAction.close();
829         IncrementalSearchAction.close(this);
830         RecentFileAction.close(this);
831         OpenSourceFileOnKeywordAction.closeOpenSourceWindow();
832         SearchWordInFilesAction.closeWindow();
833
834         /*
835          * setProtectOpenFileList(true); while (getTabPane().getTabCount() > 0)
836          * { closeTabAt(0, true); } setProtectOpenFileList(false);
837          */
838
839         scinotesList.remove(this);
840         if (scinotesList.size() == 0) {
841             SciNotesAutosave.stopAutosave();
842             ScilabEditorPane.clean();
843             RegisterFavoriteDirsAction.close();
844             OpenSourceFileOnKeywordAction.close();
845             EncodingAction.close();
846             EndOfLineAction.close();
847             HelpOnTypingManager.close();
848         }
849
850         editor = null;
851         SciNotesGUI.clean(this);
852         close();
853         ConfigSciNotesManager.resetDocument();
854     }
855
856     public boolean canClose() {
857         int numberOfTab = getTabPane().getTabCount();
858         setProtectOpenFileList(true);
859
860         for (int i = 0; i < numberOfTab; i++) {
861             boolean ans = checkToCloseTabAt(i);
862             if (!ans) {
863                 setProtectOpenFileList(false);
864                 return false;
865             }
866         }
867         setProtectOpenFileList(false);
868
869         return true;
870     }
871
872     public String askForClosing() {
873         int numberOfTab = getTabPane().getTabCount();
874         boolean isContentModified = false;
875         for (int i = 0; i < getTabPane().getTabCount(); i++) {
876             ScilabEditorPane textPaneAt = getTextPane(i);
877             if (textPaneAt != null && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
878                 isContentModified = true;
879                 break;
880             }
881         }
882
883         if (isContentModified) {
884             return "SciNotes";
885         }
886
887         return null;
888     }
889
890     public static void closeEditor(SciNotes ed) {
891         if (scinotesList.size() > 1) {
892             ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabDockablePanel) ed);
893         } else {
894             ClosingOperationsManager.startClosingOperation((SwingScilabDockablePanel) ed);
895         }
896     }
897
898     /**
899      * Close a tab using its index.
900      *
901      * @param indexTab
902      *            the index of the tab
903      * @return if the tab has been really closed
904      */
905     public boolean closeTabAtWithoutConfirmation(int indexTab) {
906         return closeTabAt(indexTab, false, false);
907     }
908
909     /**
910      * Close a tab using its index.
911      *
912      * @param indexTab
913      *            the index of the tab
914      * @return if the tab has been really closed
915      */
916     public boolean closeTabAt(int indexTab) {
917         return closeTabAt(indexTab, false, true);
918     }
919
920     /**
921      * Close a tab using its index.
922      *
923      * @param indexTab
924      *            the index of the tab
925      * @param scilabClose
926      *            if true, save dialog confirmation cannot be canceled
927      * @return if the tab has been really closed
928      */
929     public boolean closeTabAt(int indexTab, boolean scilabClose, boolean confirmation) {
930         ScilabEditorPane textPaneAt = getTextPane(indexTab);
931
932         /*
933          * Test for modification added after bug 5103 fix: do not ask the user
934          * for an Untitled not-modified file saving when closing SciNotes
935          */
936         if (confirmation && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
937             if (!save(indexTab, false, scilabClose)) {
938                 return false;
939             }
940         }
941
942         textPaneAt.close();
943
944         if (textPaneAt.getName() == null) {
945             String closedTabName = tabPane.getScilabTitleAt(indexTab);
946             String closedTabNameIndex = closedTabName.substring(closedTabName.length() - 1, closedTabName.length());
947             tabList.remove(Integer.valueOf(closedTabNameIndex));
948             closedTabList.add(Integer.valueOf(closedTabNameIndex));
949         }
950
951         // correction for bug 5404, closing the last tabPane generate an
952         // exception
953         // that's why we need to remove ChangeListeners before closing
954         if ((indexTab == 0) && (getTabPane().getTabCount() == 1)) {
955             for (int i = 0; i < tabPane.getChangeListeners().length; i++) {
956                 tabPane.removeChangeListener(tabPane.getChangeListeners()[i]);
957             }
958         }
959
960         // Remove the filename associated with the tab from the list of open
961         // files.
962         if (!protectOpenFileList) {
963             ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt);
964         }
965
966         if (navigator != null) {
967             navigator.removePane(textPaneAt);
968         }
969
970         tabPane.remove(indexTab);
971
972         textPaneAt = getTextPane();
973         if (textPaneAt != null) {
974             if (navigator != null) {
975                 navigator.update((ScilabDocument) textPaneAt.getDocument());
976             }
977         }
978         return true;
979     }
980
981     public boolean checkToCloseTabAt(int index) {
982         ScilabEditorPane textPaneAt = getTextPane(index);
983
984         /*
985          * Test for modification added after bug 5103 fix: do not ask the user
986          * for an Untitled not-modified file saving when closing SciNotes
987          */
988         if (textPaneAt != null && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) {
989             if (!save(index, false, false)) {
990                 return false;
991             }
992         }
993
994         return true;
995     }
996
997     /**
998      * Set or unset protection of the currently open file list. Call before
999      * closing tabs if the tabs should be restored when scinotes restarts.
1000      *
1001      * @param protect
1002      *            Enables protection of the open file list if true.
1003      */
1004     public void setProtectOpenFileList(boolean protect) {
1005         protectOpenFileList = protect;
1006     }
1007
1008     /**
1009      * Determines if this editor is the only editor instance.
1010      *
1011      * @return true if this is the last editor instance.
1012      */
1013     public boolean isOnlyInstance() {
1014         if (scinotesList.size() > 1) {
1015             return false;
1016         }
1017
1018         return true;
1019     }
1020
1021     /**
1022      * @return the list of the different openened editors
1023      */
1024     public static List<SciNotes> getSciNotesList() {
1025         return scinotesList;
1026     }
1027
1028     /**
1029      * Save a file.
1030      *
1031      * @param indexTab
1032      *            the textPane index containing the file contents
1033      * @return execution status
1034      */
1035     public boolean save(int indexTab) {
1036         return save(indexTab, false, false);
1037     }
1038
1039     /**
1040      * Save a file.
1041      *
1042      * @param indexTab
1043      *            the textPane index containing the file contents
1044      * @param force
1045      *            : force save without confirmation dialog ( SaveAction )
1046      * @return execution status
1047      */
1048     public boolean save(int indexTab, boolean force) {
1049         return save(indexTab, force, false);
1050     }
1051
1052     /**
1053      * Save a file.
1054      *
1055      * @param indexTab
1056      *            the textPane index containing the file contents
1057      * @param force
1058      *            : force save without confirmation dialog ( SaveAction )
1059      * @param scilabClose
1060      *            : if true, save dialog confirmation cannot be canceled
1061      * @return execution status
1062      */
1063     public boolean save(int indexTab, boolean force, boolean scilabClose) {
1064         ScilabEditorPane textPaneAt = getTextPane(indexTab);
1065         getTabPane().setSelectedIndex(indexTab);
1066
1067         // if the file ( empty, new or loaded ) is not modified, exit save
1068         // process and return true
1069         if (!textPaneAt.checkExternalModif() && !((ScilabDocument) textPaneAt.getDocument()).isContentModified() && (textPaneAt.getName() != null)) {
1070             /*
1071              * Bug
1072              * 5103
1073              * fix
1074              */
1075             return true;
1076         }
1077
1078         if (!force) {
1079             AnswerOption answer;
1080             if (scilabClose) {
1081                 answer = ScilabModalDialog.show(this, String.format(SciNotesMessages.MODIFIED, textPaneAt.getShortName()), SciNotesMessages.SCILAB_EDITOR,
1082                                                 IconType.QUESTION_ICON, ButtonType.YES_NO);
1083             } else {
1084                 answer = ScilabModalDialog.show(this, String.format(SciNotesMessages.MODIFIED, textPaneAt.getShortName()), SciNotesMessages.SCILAB_EDITOR,
1085                                                 IconType.QUESTION_ICON, ButtonType.YES_NO_CANCEL);
1086             }
1087
1088             switch (answer) {
1089                 case YES_OPTION: // Yes, continue
1090                     break;
1091                 case NO_OPTION:// No, exit and returns true
1092                     return true;
1093                 case CANCEL_OPTION: // Cancel, exit and return false
1094                     return false;
1095                 default:
1096                     break;
1097             }
1098         }
1099
1100         String fileToSave = textPaneAt.getName();
1101         if (fileToSave == null) {
1102             // need a filename, call chooseFileToSave
1103             fileToSave = chooseFileToSave(SciNotesMessages.SAVE);
1104         } else {
1105             // check if the file has been modified by external software
1106             fileToSave = checkExternalModification(fileToSave);
1107         }
1108
1109         if (fileToSave == null || fileToSave.length() == 0) {
1110             return true; /*
1111                           * Bug 5189: The user cancels ==> do not want an error
1112                           * message
1113                           */
1114         }
1115
1116         File newSavedFile = new File(fileToSave);
1117
1118         if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) {
1119             return false;
1120         }
1121
1122         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
1123         styledDocument.setContentModified(false);
1124
1125         textPaneAt.setLastModified(newSavedFile.lastModified());
1126
1127         if (textPaneAt.getName() == null) {
1128             String name = getTabPane().getScilabTitleAt(indexTab);
1129             String index = name.substring(name.length() - 1, name.length());
1130             tabList.remove(Integer.valueOf(index));
1131             closedTabList.add(Integer.valueOf(index));
1132         }
1133
1134         textPaneAt.setName(fileToSave);
1135         getTabPane().setTitleAt(indexTab, newSavedFile.getName());
1136
1137         setTitle(textPaneAt.getTitle());
1138         ConfigSciNotesManager.saveToOpenFiles(fileToSave, this, textPaneAt);
1139
1140         return true;
1141     }
1142
1143     /**
1144      * Overwrite the file at a given index.
1145      *
1146      * @param indexTab
1147      *            the textPane index containing the file contents
1148      * @return execution status
1149      */
1150     public boolean overwrite(int indexTab) {
1151         ScilabEditorPane textPaneAt = getTextPane(indexTab);
1152         String fileToSave = textPaneAt.getName();
1153         if (fileToSave == null) {
1154             return true;
1155         }
1156
1157         File newSavedFile = new File(fileToSave);
1158         if (!newSavedFile.exists()) {
1159             return true;
1160         }
1161
1162         if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) {
1163             return false;
1164         }
1165
1166         ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument();
1167         styledDocument.setContentModified(false);
1168
1169         getTabPane().setTitleAt(getTabPane().getSelectedIndex(), newSavedFile.getName());
1170
1171         // Get current file path for Execute file into Scilab
1172         getTextPane().setLastModified(newSavedFile.lastModified());
1173
1174         textPaneAt.setName(fileToSave);
1175         setTitle(textPaneAt.getTitle());
1176
1177         return true;
1178     }
1179
1180     /**
1181      * Check for external modification. If it is the case, propose to select a
1182      * new file name.
1183      *
1184      * @param filename
1185      *            The name of the file
1186      * @return the filename where to save
1187      */
1188     public String checkExternalModification(String filename) {
1189         File newSavedFile = new File(filename);
1190         if (newSavedFile.lastModified() > getTextPane().getLastModified()) {
1191             if (ScilabModalDialog.show(this, String.format(SciNotesMessages.EXTERNAL_MODIFICATION, newSavedFile.getPath()),
1192                                        SciNotesMessages.REPLACE_FILE_TITLE, IconType.QUESTION_ICON, ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
1193                 return chooseFileToSave(SciNotesMessages.SAVE);
1194             }
1195         }
1196         return filename;
1197     }
1198
1199     /**
1200      * Return through a file selector the name of the selected file.
1201      *
1202      * @param title
1203      *            the title for JFileChooser
1204      * @return the file picked up by the user
1205      */
1206     public String chooseFileToSave(String title) {
1207         return chooseFileToSave(title, null);
1208     }
1209
1210     /**
1211      * Return through a file selector the name of the selected file.
1212      *
1213      * @param title
1214      *            the title for JFileChooser
1215      * @param path
1216      *            the path where to open the filechooser
1217      * @return the file picked up by the user
1218      */
1219     public String chooseFileToSave(String title, String path) {
1220         String extension = new String();
1221
1222         String initialDirectoryPath = path;
1223         if (initialDirectoryPath == null) {
1224             initialDirectoryPath = getTextPane().getName();
1225         }
1226         if (initialDirectoryPath == null) {
1227             if (firstOpen) {
1228                 initialDirectoryPath = CommonFileUtils.getCWD();
1229                 firstOpen = false;
1230             } else {
1231                 initialDirectoryPath = ConfigManager.getLastOpenedDirectory();
1232             }
1233         }
1234
1235         SciFileFilter sceFilter = new SciFileFilter(ALL_SCE_FILES, null, 0);
1236         SciFileFilter sciFilter = new SciFileFilter(ALL_SCI_FILES, null, 1);
1237         SciFileFilter scxFilter = new SciFileFilter(ALL_SCX_FILES, null, 2);
1238         SciFileFilter tstFilter = new SciFileFilter(ALL_TST_FILES, null, 3);
1239         SciFileFilter startFilter = new SciFileFilter(ALL_START_FILES, null, 4);
1240         SciFileFilter quitFilter = new SciFileFilter(ALL_QUIT_FILES, null, 5);
1241         SciFileFilter demFilter = new SciFileFilter(ALL_DEM_FILES, null, 6);
1242         SciFileFilter allFilter = new SciFileFilter(ALL_FILES, null, 7);
1243         SciFileFilter allScilabFilter = new SciFileFilter(ALL_SCILAB, null, 8);
1244
1245         SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser());
1246
1247         fileChooser.setAcceptAllFileFilterUsed(false);
1248         fileChooser.setInitialDirectory(initialDirectoryPath);
1249         fileChooser.setUiDialogType(Juigetfile.SAVE_DIALOG);
1250
1251         // order is also important here
1252         fileChooser.addChoosableFileFilter(sceFilter);
1253         fileChooser.addChoosableFileFilter(sciFilter);
1254         fileChooser.addChoosableFileFilter(scxFilter);
1255         fileChooser.addChoosableFileFilter(tstFilter);
1256         fileChooser.addChoosableFileFilter(startFilter);
1257         fileChooser.addChoosableFileFilter(quitFilter);
1258         fileChooser.addChoosableFileFilter(demFilter);
1259         fileChooser.addChoosableFileFilter(allFilter);
1260         fileChooser.addChoosableFileFilter(allScilabFilter);
1261
1262         // select default file type
1263         fileChooser.setFileFilter(sceFilter);
1264         fileChooser.setTitle(title);
1265
1266         String name = getTextPane().getName();
1267         if (name == null) {
1268             name = ((ScilabDocument) getTextPane().getDocument()).getFirstFunctionName();
1269             if (name != null) {
1270                 name += SCI_EXTENSION;
1271             }
1272         }
1273
1274         if (name != null) {
1275             fileChooser.setSelectedFile(new File(name));
1276         }
1277
1278         int retval = fileChooser.showSaveDialog(this);
1279
1280         if (retval == JFileChooser.APPROVE_OPTION) {
1281             File f = fileToCanonicalFile(fileChooser.getSelectedFile());
1282             initialDirectoryPath = f.getPath();
1283             if (f.exists()) {
1284                 if (ScilabModalDialog.show(this, SciNotesMessages.REPLACE_FILE_TITLE, SciNotesMessages.FILE_ALREADY_EXIST, IconType.QUESTION_ICON,
1285                                            ButtonType.YES_NO) == AnswerOption.NO_OPTION) {
1286                     return chooseFileToSave(SciNotesMessages.SAVE);
1287                 }
1288             }
1289
1290             /* we test if the file has already a scilab extension */
1291             boolean hasNoExtension = true;
1292
1293             // if the file name is like this : any character , a dot , then
1294             // 2,3or 4 characters, then
1295             // we consider the file has already an extension
1296             // we previously only check for .sci and .sce extension, but what if
1297             // the user open a txt file
1298             String fileName = f.getName();
1299             if (fileName.lastIndexOf(DOT) != -1) {
1300                 if (fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() >= 2
1301                         && fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() <= 4) {
1302                     hasNoExtension = false;
1303                 }
1304             }
1305
1306             /* if no extension , we add it */
1307             if (hasNoExtension) {
1308                 if (fileChooser.getFileFilter() == sciFilter) {
1309                     extension = SCI_EXTENSION;
1310                 } else if (fileChooser.getFileFilter() == sceFilter) {
1311                     extension = SCE_EXTENSION;
1312                 } else if (fileChooser.getFileFilter() == scxFilter) {
1313                     extension = SCE_EXTENSION;
1314                 } else if (fileChooser.getFileFilter() == tstFilter) {
1315                     extension = TST_EXTENSION;
1316                 } else if (fileChooser.getFileFilter() == startFilter) {
1317                     extension = START_EXTENSION;
1318                 } else if (fileChooser.getFileFilter() == quitFilter) {
1319                     extension = QUIT_EXTENSION;
1320                 } else if (fileChooser.getFileFilter() == demFilter) {
1321                     extension = DEM_EXTENSION;
1322                 } else {
1323                     extension = "";
1324                 }
1325                 return f.getPath() + extension;
1326             }
1327
1328             if (initialDirectoryPath != null) {
1329                 ConfigManager.saveLastOpenedDirectory(initialDirectoryPath);
1330             }
1331
1332             return f.getPath();
1333         } else if (retval == JFileChooser.CANCEL_OPTION) {
1334             return "";
1335         }
1336
1337         return null;
1338     }
1339
1340     /**
1341      * Save a file.
1342      *
1343      * @param path
1344      *            the initial path where the filechooser will be open
1345      * @return execution status
1346      */
1347     public boolean saveAs(String path) {
1348         String filename = chooseFileToSave(SciNotesMessages.SAVE_AS, path);
1349         if (filename == null || filename.length() == 0) {
1350             return true;
1351         }
1352
1353         File f = new File(filename);
1354         ScilabDocument styledDocument = (ScilabDocument) getTextPane().getDocument();
1355
1356         if (!SaveFile.doSave(getTextPane(), getTabPane().getSelectedIndex(), f, editorKit)) {
1357             return false;
1358         }
1359
1360         if (getTextPane().getName() == null) {
1361             String name = getTabPane().getScilabTitleAt(getTabPane().getSelectedIndex());
1362             String index = name.substring(name.length() - 1, name.length());
1363             tabList.remove(Integer.valueOf(index));
1364             closedTabList.add(Integer.valueOf(index));
1365         }
1366
1367         firstOpen = false;
1368         ConfigManager.saveLastOpenedDirectory(f.getPath());
1369         ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
1370         ConfigSciNotesManager.renameOpenFilesItem(f.getPath(), this, getTextPane());
1371         getTextPane().setName(f.getPath());
1372         getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
1373         setTitle(getTextPane().getTitle());
1374
1375         RecentFileAction.updateRecentOpenedFilesMenu(this);
1376
1377         if (navigator != null) {
1378             navigator.update(styledDocument);
1379         }
1380
1381         styledDocument.setContentModified(false);
1382         getTextPane().setLastModified(f.lastModified());
1383         getTextPane().setReadOnly(false);
1384         getInfoBar().setText(getTextPane().getInfoBarText());
1385
1386         return true;
1387     }
1388
1389     /**
1390      * Create a new tab in SciNotes.
1391      *
1392      * @param title
1393      *            the title of the tab
1394      * @return the text component inside the tab
1395      */
1396     public ScilabEditorPane addTab(String title) {
1397         return addTab(title, Integer.MAX_VALUE);
1398     }
1399
1400     /**
1401      * Create a new tab in SciNotes.
1402      *
1403      * @param title
1404      *            the title of the tab
1405      * @param index
1406      *            the index where to put the new tab
1407      * @return the text component inside the tab
1408      */
1409     public ScilabEditorPane addTab(String title, int index) {
1410         return addTab(title, index, 0);
1411     }
1412
1413     /**
1414      * Create a new tab in SciNotes.
1415      *
1416      * @param title
1417      *            the title of the tab
1418      * @param index
1419      *            the index where to put the new tab
1420      * @return the text component inside the tab
1421      */
1422     public ScilabEditorPane addTab(String title, int index, int caretPos) {
1423         ScilabEditorPane sep = new ScilabEditorPane(this);
1424         initPane(sep);
1425         int ind = Math.min(Math.max(0, index), tabPane.getTabCount());
1426         tabPane.insertTab(title, null, sep.getEditorComponent(), "", ind);
1427         tabPane.setSelectedIndex(ind);
1428         initInputMap(sep);
1429         updateTabTitle();
1430         getInfoBar().setText(sep.getInfoBarText());
1431         repaint();
1432         sep.init(caretPos);
1433         return sep;
1434     }
1435
1436     public void addRestoreTab() {
1437         try {
1438             JPanel panel = RestoreOpenedFilesAction.getTab(this, getUUID().toString());
1439             if (panel != null) {
1440                 tabPane.addTab("Restore", panel);
1441             }
1442         } catch (Exception e) {
1443             System.err.println(e);
1444         }
1445     }
1446
1447     /**
1448      * Init a pane
1449      *
1450      * @param pane
1451      *            the pane to init
1452      */
1453     public void initPane(ScilabEditorPane pane) {
1454         initPane(pane, !SciNotesOptions.getSciNotesDisplay().wrapLines);
1455     }
1456
1457     /**
1458      * Init the EditorPane.
1459      *
1460      * @param pane
1461      *            the EditorPane
1462      * @param plain
1463      *            true for a plain view or false for a wrapped view
1464      */
1465     public void initPane(ScilabEditorPane pane, boolean plain) {
1466         setHighlight(pane);
1467         ScilabEditorKit kit = new ScilabEditorKit(plain);
1468         pane.setEditorKit(kit);
1469
1470         // Panel of line number for the text pane
1471         pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1472         activateHelpOnTyping(pane);
1473
1474         pane.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
1475         pane.setFont(kit.getStylePreferences().tokenFonts[0]);
1476
1477         pane.setBackground(SciNotesOptions.getSciNotesDisplay().backgroundColor);
1478         pane.setCaretColor(SciNotesOptions.getSciNotesDisplay().caretColor);
1479
1480         pane.setFocusable(true);
1481         pane.setRequestFocusEnabled(true);
1482         pane.setDragEnabled(true); /* Bug 5497 */
1483
1484         DropFilesListener dndTarget = new DropFilesListener(pane);
1485
1486         pane.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(this));
1487     }
1488
1489     /**
1490      * Init the EditorPane with the InputMap found in ConfigSciNotesManager
1491      *
1492      * @param pane
1493      *            the EditorPane
1494      */
1495     public void initInputMap(ScilabEditorPane pane) {
1496         setKeyStrokeAction(pane, this);
1497         LineBeautifierAction.putInInputMap(pane);
1498         InsertOverwriteAction.putInInputMap(pane);
1499     }
1500
1501     /**
1502      * Split the EditorPane
1503      *
1504      * @param vertical
1505      *            true for a vertical split
1506      */
1507     public void splitTab(boolean vertical) {
1508         ScilabEditorPane pane = getTextPane();
1509         Component bottom = pane.getEditorComponent().getBottom();
1510         int state = pane.getXln().getState();
1511         ScilabEditorPane leftPane = new ScilabEditorPane(editor);
1512         ScilabEditorPane rightPane = new ScilabEditorPane(editor);
1513         if (navigator != null) {
1514             navigator.changePaneOnSplit(pane, leftPane);
1515         }
1516         initPane(leftPane, true);
1517         initPane(rightPane, true);
1518         leftPane.setOtherPaneInSplit(rightPane);
1519         rightPane.setOtherPaneInSplit(leftPane);
1520         pane.copyProps(leftPane);
1521         pane.copyProps(rightPane);
1522         ScilabDocument doc = (ScilabDocument) pane.getDocument();
1523         leftPane.setDocument(doc);
1524         rightPane.setDocument(doc);
1525         leftPane.setCaretPosition(0);
1526         rightPane.setCaretPosition(0);
1527         JSplitPane split;
1528         if (vertical) {
1529             split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
1530         } else {
1531             split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
1532         }
1533         leftPane.getXln().setWhereamiLineNumbering(state);
1534         rightPane.getXln().setWhereamiLineNumbering(state);
1535         split.setLeftComponent(leftPane.getScrollPane());
1536         split.setRightComponent(rightPane.getScrollPane());
1537         split.setResizeWeight(0.5);
1538         rightPane.setEditorComponent(leftPane.getEditorComponent());
1539         leftPane.setSplitPane(split);
1540         rightPane.setSplitPane(split);
1541
1542         activateHelpOnTyping(leftPane);
1543         activateHelpOnTyping(rightPane);
1544         initInputMap(leftPane);
1545         initInputMap(rightPane);
1546         if (doc.getBinary()) {
1547             leftPane.setBinary(true);
1548             rightPane.setBinary(true);
1549         }
1550         getInfoBar().setText(leftPane.getInfoBarText());
1551         updateTabTitle();
1552         tabPane.setComponentAt(tabPane.getSelectedIndex(), leftPane.getEditorComponent());
1553         leftPane.getEditorComponent().insertBottomComponent(bottom);
1554         leftPane.requestFocus();
1555     }
1556
1557     /**
1558      * Remove a split
1559      */
1560     public void removeSplit() {
1561         if (((EditorComponent) tabPane.getSelectedComponent()).isSplited()) {
1562             ScilabEditorPane pane = new ScilabEditorPane(editor);
1563             ScilabEditorPane textpane = getTextPane();
1564             Component bottom = textpane.getEditorComponent().getBottom();
1565             if (navigator != null) {
1566                 navigator.changePaneOnSplit(textpane, pane);
1567             }
1568             initPane(pane);
1569             textpane.setOtherPaneInSplit(null);
1570             textpane.copyProps(pane);
1571             ScilabDocument doc = (ScilabDocument) textpane.getDocument();
1572             pane.setDocument(doc);
1573             pane.setCaretPosition(0);
1574             activateHelpOnTyping(pane);
1575             tabPane.setComponentAt(tabPane.getSelectedIndex(), pane.getEditorComponent());
1576             initInputMap(pane);
1577             if (doc.getBinary()) {
1578                 pane.setBinary(true);
1579             }
1580             getInfoBar().setText(pane.getInfoBarText());
1581             updateTabTitle();
1582             pane.getEditorComponent().insertBottomComponent(bottom);
1583             pane.requestFocus();
1584         }
1585     }
1586
1587     /**
1588      * Create an empty tab inside SciNotes.
1589      *
1590      * @return the text component inside the tab
1591      */
1592     public ScilabEditorPane addEmptyTab() {
1593         ScilabEditorPane sep;
1594         int n = getNumberForEmptyTab();
1595         sep = addTab(SciNotesMessages.UNTITLED + n);
1596         sep.setShortName(SciNotesMessages.UNTITLED + n);
1597         sep.setTitle(SciNotesMessages.UNTITLED + n);
1598         setTitle(sep.getTitle());
1599         SciNotesOptions.Header header = SciNotesOptions.getSciNotesHeader();
1600         if (header.header != null) {
1601             ((ScilabDocument) sep.getDocument()).disableUndoManager();
1602             try {
1603                 sep.getDocument().insertString(0, header.header, null);
1604             } catch (BadLocationException e) { }
1605             sep.init(header.header.length());
1606             ((ScilabDocument) sep.getDocument()).setContentModified(false);
1607             ((ScilabDocument) sep.getDocument()).enableUndoManager();
1608         }
1609
1610         return sep;
1611     }
1612
1613     /**
1614      * Get an integer used for untitled document
1615      */
1616     public int getNumberForEmptyTab() {
1617         if (closedTabList.size() > 0) {
1618             Integer n = Collections.min(closedTabList);
1619             closedTabList.remove(n);
1620             return n.intValue();
1621         } else {
1622             numberOfUntitled++;
1623             tabList.add(Integer.valueOf(numberOfUntitled));
1624             return numberOfUntitled;
1625         }
1626     }
1627
1628     /**
1629      * Add or remove '*' prefix in current tab tile according to
1630      * isContentModified().
1631      */
1632     public void updateTabTitle() {
1633         updateTabTitle(getTabPane().getSelectedIndex());
1634     }
1635
1636     /**
1637      * Add or remove '*' prefix in tab title (corresponding to the given index) according to
1638      * isContentModified().
1639      */
1640     public void updateTabTitle(int index) {
1641         StringBuffer newTitle = new StringBuffer();
1642         ScilabEditorPane currentTextPane = getTextPane(index);
1643         if (((ScilabDocument) currentTextPane.getDocument()).isContentModified()) {
1644             newTitle.append('*');
1645         }
1646
1647         String textPaneName = currentTextPane.getName();
1648         try {
1649             File f = new File(textPaneName);
1650             newTitle.append(f.getName());
1651         } catch (NullPointerException e) { // not a file name, no path prefix to
1652             // remove, but maybe a '*'
1653             textPaneName = getTabPane().getScilabTitleAt(index);
1654             if (textPaneName.charAt(0) == '*') {
1655                 newTitle.append(textPaneName.substring(1, textPaneName.length()));
1656             } else {
1657                 newTitle.append(textPaneName);
1658             }
1659         }
1660         getTabPane().setTitleAt(index, newTitle.toString());
1661     }
1662
1663     /**
1664      * @param button
1665      *            the UndoButton used in this editor
1666      */
1667     public void setUndoButton(JButton button) {
1668         undoButton = button;
1669         enableUndoButton(false);
1670     }
1671
1672     /**
1673      * @param b
1674      *            true to enable the button
1675      */
1676     public void enableUndoButton(boolean b) {
1677         if (undoButton != null) {
1678             undoButton.setEnabled(b);
1679         }
1680     }
1681
1682     /**
1683      * Undo last modification.
1684      */
1685     public void undo() {
1686         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1687         synchronized (doc) {
1688             doc.getUndoManager().undo();
1689         }
1690     }
1691
1692     /**
1693      * @param button
1694      *            the RedoButton used in this editor
1695      */
1696     public void setRedoButton(JButton button) {
1697         redoButton = button;
1698         enableRedoButton(false);
1699     }
1700
1701     /**
1702      * @param b
1703      *            true to enable the button
1704      */
1705     public void enableRedoButton(boolean b) {
1706         if (redoButton != null) {
1707             redoButton.setEnabled(b);
1708         }
1709     }
1710
1711     /**
1712      * Redo last modification.
1713      */
1714     public void redo() {
1715         ScilabDocument doc = (ScilabDocument) getTextPane().getDocument();
1716         synchronized (doc) {
1717             doc.getUndoManager().redo();
1718         }
1719     }
1720
1721     /**
1722      * Reload a file inside SciNotes.
1723      *
1724      * @param index
1725      *            the index
1726      */
1727     public void reload(int index) {
1728         ScilabEditorPane textPaneAt = getTextPane(index);
1729         if (textPaneAt != null && textPaneAt.getName() != null) {
1730             if ((index == 0) && (getTabPane().getTabCount() == 1)) {
1731                 for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1732                     tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1733                 }
1734             }
1735             ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt);
1736             tabPane.remove(index);
1737             File f = new File(textPaneAt.getName());
1738             if (f.exists()) {
1739                 loadFile(f, index);
1740             } else {
1741                 createNewFile(f);
1742             }
1743         }
1744     }
1745
1746     /**
1747      * Load a file inside SciNotes.
1748      *
1749      * @param f
1750      *            the file to open
1751      */
1752     public void readFile(File f) {
1753         /** Is this file already opened */
1754         boolean alreadyOpened = false;
1755         for (int i = 0; i < tabPane.getTabCount(); i++) {
1756             ScilabEditorPane textPaneAt = getTextPane(i);
1757             if (f.getAbsolutePath().equals(textPaneAt.getName())) {
1758                 /* File is already opnened */
1759                 tabPane.setSelectedIndex(i);
1760                 alreadyOpened = true;
1761                 break;
1762             }
1763         }
1764
1765         if (!alreadyOpened) {
1766             if (f.exists()) {
1767                 loadFile(f);
1768             } else {
1769                 createNewFile(f);
1770             }
1771         }
1772     }
1773
1774     /**
1775      * Load a file inside SciNotes.
1776      *
1777      * @param file
1778      *            the file to open
1779      */
1780     public void readFileAndWait(File file) {
1781         /** Is this file already opened */
1782         File f = file;
1783         boolean alreadyOpened = false;
1784         int index = -1;
1785         for (int i = 0; i < tabPane.getTabCount(); i++) {
1786             ScilabEditorPane textPaneAt = getTextPane(i);
1787             if (textPaneAt != null && f.getAbsolutePath().equals(textPaneAt.getName())) {
1788                 /* File is already opened */
1789                 tabPane.setSelectedIndex(i);
1790                 if (f.lastModified() > textPaneAt.getLastModified()) {
1791
1792                     /*
1793                      * Create a new messagebox to know what the user wants to do
1794                      * if the file has been modified outside SciNotes
1795                      */
1796                     MessageBox messageBox = ScilabMessageBox.createMessageBox();
1797                     messageBox.setTitle(SciNotesMessages.REPLACE_FILE_TITLE);
1798                     messageBox.setMessage(String.format(SciNotesMessages.EXTERNAL_MODIFICATION, textPaneAt.getName()));
1799
1800                     String[] labels = new String[] { SciNotesMessages.RELOAD, SciNotesMessages.OVERWRITE, SciNotesMessages.IGNORE };
1801                     messageBox.setButtonsLabels(labels);
1802
1803                     messageBox.setIcon("question"); // Question icon
1804
1805                     messageBox.setParentForLocation(this); // Centered on
1806                     // SciNotes main
1807                     // window
1808
1809                     messageBox.displayAndWait(); // Waits for a user action
1810
1811                     switch (messageBox.getSelectedButton()) {
1812                         case 1: // Reload
1813                             if ((i == 0) && (getTabPane().getTabCount() == 1)) {
1814                                 for (int j = 0; j < tabPane.getChangeListeners().length; j++) {
1815                                     tabPane.removeChangeListener(tabPane.getChangeListeners()[j]);
1816                                 }
1817                             }
1818                             tabPane.remove(i);
1819                             f = new File(textPaneAt.getName());
1820                             index = i;
1821                             break;
1822                         case 2: // Overwrite 2
1823                             overwrite(i);
1824                             alreadyOpened = true;
1825                             break;
1826                         default: // Ignore
1827                             alreadyOpened = true;
1828                     }
1829                 } else {
1830                     alreadyOpened = true;
1831                 }
1832                 break;
1833             }
1834         }
1835
1836         if (!alreadyOpened) {
1837             if (f.exists()) {
1838                 loadFile(f, index);
1839             } else {
1840                 createNewFile(f);
1841             }
1842         }
1843     }
1844
1845     public int getTextPaneIndex(ScilabEditorPane sep) {
1846         int n = tabPane.getTabCount();
1847         for (int i = 0; i < n; ++i) {
1848             ScilabEditorPane pane = getTextPane(i);
1849             if (pane != null && (pane == sep || pane.getOtherPaneInSplit() == sep)) {
1850                 return i;
1851             }
1852         }
1853
1854         return -1;
1855     }
1856
1857     /**
1858      * Get current text component. If the window is splitted, then return the
1859      * focused text component.
1860      *
1861      * @return the text component
1862      */
1863     public ScilabEditorPane getTextPane() {
1864         try {
1865             if (tabPane.getSelectedComponent() instanceof EditorComponent) {
1866                 EditorComponent c = (EditorComponent) tabPane.getSelectedComponent();
1867                 ScilabEditorPane pane = c.getEditorPane();
1868                 if (ScilabEditorPane.getFocusedPane() == pane.getOtherPaneInSplit()) {
1869                     return pane.getOtherPaneInSplit();
1870                 }
1871
1872                 return pane;
1873             }
1874         } catch (NullPointerException e) {
1875         } catch (ArrayIndexOutOfBoundsException e) {
1876         }
1877
1878         return null;
1879     }
1880
1881     /**
1882      * Get text component at index.
1883      *
1884      * @param index
1885      *            the index of the textpane
1886      * @return the text component
1887      */
1888     public ScilabEditorPane getTextPane(int index) {
1889         try {
1890             if (tabPane.getComponentAt(index) instanceof EditorComponent) {
1891                 EditorComponent c = (EditorComponent) tabPane.getComponentAt(index);
1892                 ScilabEditorPane pane = c.getEditorPane();
1893                 if (ScilabEditorPane.getFocusedPane() == pane.getOtherPaneInSplit()) {
1894                     return pane.getOtherPaneInSplit();
1895                 }
1896
1897                 return pane;
1898             }
1899         } catch (NullPointerException e) {
1900         } catch (ArrayIndexOutOfBoundsException e) {
1901         }
1902
1903         return null;
1904     }
1905
1906     /**
1907      * Set the keystroke actions
1908      */
1909     public static void setAllMenus() {
1910         for (SciNotes ed : scinotesList) {
1911             SciNotesGUI.reinitMenus(ed);
1912             int n = ed.getTabPane().getTabCount();
1913             for (int i = 0; i < n; i++) {
1914                 ScilabEditorPane sep = ed.getTextPane(i);
1915                 sep.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed));
1916                 if (sep.getOtherPaneInSplit() != null) {
1917                     sep.getOtherPaneInSplit().setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed));
1918                 }
1919             }
1920         }
1921     }
1922
1923     /**
1924      * Set the keystroke actions
1925      */
1926     public static void setKeyStrokeActions() {
1927         for (SciNotes ed : scinotesList) {
1928             int n = ed.getTabPane().getTabCount();
1929             for (int i = 0; i < n; i++) {
1930                 ScilabEditorPane sep = ed.getTextPane(i);
1931                 ed.initInputMap(sep);
1932                 if (sep.getOtherPaneInSplit() != null) {
1933                     ed.initInputMap(sep.getOtherPaneInSplit());
1934                 }
1935             }
1936         }
1937     }
1938
1939     /**
1940      * Enable the whereami-line numbering
1941      *
1942      * @param state
1943      *            int
1944      */
1945     public static void setWhereamiLineNumbering() {
1946         for (SciNotes ed : scinotesList) {
1947             int n = ed.getTabPane().getTabCount();
1948             for (int i = 0; i < n; i++) {
1949                 ScilabEditorPane sep = ed.getTextPane(i);
1950                 sep.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1951                 if (sep.getOtherPaneInSplit() != null) {
1952                     sep.getOtherPaneInSplit().getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1953                 }
1954             }
1955             ed.repaint();
1956         }
1957     }
1958
1959     /**
1960      * Auto-indent mode management
1961      *
1962      * @param b
1963      *            true to activate auto-indent mode
1964      */
1965     public static void setAutoIndent() {
1966         for (SciNotes ed : scinotesList) {
1967             int n = ed.getTabPane().getTabCount();
1968             for (int i = 0; i < n; i++) {
1969                 ScilabEditorPane sep = ed.getTextPane(i);
1970                 ((ScilabDocument) sep.getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent);
1971                 if (sep.getOtherPaneInSplit() != null) {
1972                     ((ScilabDocument) sep.getOtherPaneInSplit().getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent);
1973                 }
1974             }
1975         }
1976     }
1977
1978     /**
1979      * Horizontal Wrap mode management
1980      *
1981      * @param b
1982      *            true to activate horizontal wrapping mode
1983      */
1984     public static void setHorizontalWrap() {
1985         if (SciNotesOptions.getSciNotesDisplay().wrapLines != mustWrapLines) {
1986             mustWrapLines = SciNotesOptions.getSciNotesDisplay().wrapLines;
1987             for (SciNotes ed : scinotesList) {
1988                 int n = ed.getTabPane().getTabCount();
1989                 for (int i = 0; i < n; i++) {
1990                     ScilabEditorPane sep = ed.getTextPane(i);
1991                     if (sep.getOtherPaneInSplit() == null) {
1992                         ScilabEditorPane pane = new ScilabEditorPane(editor);
1993                         ed.initPane(pane, !mustWrapLines);
1994                         sep.copyProps(pane);
1995                         pane.setDocument(sep.getDocument());
1996                         pane.setCaretPosition(sep.getCaretPosition());
1997                         pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami);
1998                         ed.tabPane.setComponentAt(i, pane.getEditorComponent());
1999                         SciNotes.activateHelpOnTyping(pane);
2000                         ed.initInputMap(pane);
2001                         if (((ScilabDocument) sep.getDocument()).getBinary()) {
2002                             pane.setBinary(true);
2003                         }
2004                         ed.getInfoBar().setText(pane.getInfoBarText());
2005                     }
2006                 }
2007             }
2008         }
2009     }
2010
2011     /**
2012      * Set a line numbering compatible with the whereami function
2013      * @param state 0 for nothing, 1 for normal and 2 for whereami
2014      */
2015
2016     /**
2017      * Enable the highlighted line in this editor
2018      *
2019      * @param b
2020      *            boolean
2021      */
2022     public static void enableHighlightedLine(boolean b) {
2023         for (SciNotes ed : scinotesList) {
2024             int n = ed.getTabPane().getTabCount();
2025             for (int i = 0; i < n; i++) {
2026                 ScilabEditorPane sep = ed.getTextPane(i);
2027                 sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
2028                 if (sep.getOtherPaneInSplit() != null) {
2029                     sep.getOtherPaneInSplit().enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
2030                 }
2031             }
2032         }
2033     }
2034
2035     /**
2036      * Enable the help on typing in the current textPane
2037      *
2038      * @param pane
2039      *            the pane
2040      */
2041     public static void activateHelpOnTyping(ScilabEditorPane pane) {
2042         pane.activateHelpOnTyping();
2043     }
2044
2045     /**
2046      * Enable the help on typing in this editor
2047      */
2048     public static void activateHelpOnTyping() {
2049         for (SciNotes ed : scinotesList) {
2050             int n = ed.getTabPane().getTabCount();
2051             for (int i = 0; i < n; i++) {
2052                 ScilabEditorPane sep = ed.getTextPane(i);
2053                 sep.activateHelpOnTyping();
2054                 if (sep.getOtherPaneInSplit() != null) {
2055                     sep.getOtherPaneInSplit().activateHelpOnTyping();
2056                 }
2057             }
2058         }
2059     }
2060
2061     /**
2062      * Set the color of the highlighted line in this editor
2063      *
2064      * @param c
2065      *            Color
2066      */
2067     public static void setDefaultTabulation() {
2068         TabManager.Tabulation tab = new TabManager.Tabulation();
2069         for (SciNotes ed : scinotesList) {
2070             int n = ed.getTabPane().getTabCount();
2071             for (int i = 0; i < n; i++) {
2072                 ScilabEditorPane sep = ed.getTextPane(i);
2073                 sep.getTabManager().setTabulation(tab);
2074                 View view = ((ScilabDocument) sep.getDocument()).getView();
2075                 if (view != null) {
2076                     if (view instanceof ScilabView) {
2077                         ((ScilabView) view).setTabRepresentation(tab);
2078                         ((ScilabView) view).reinitialize();
2079                     } else {
2080                         ((ScilabPlainView) view).setTabRepresentation(tab);
2081                         ((ScilabPlainView) view).reinitialize();
2082                     }
2083                 }
2084             }
2085         }
2086     }
2087
2088     /**
2089      * Set the color of the highlighted line in this editor
2090      *
2091      * @param c
2092      *            Color
2093      */
2094     public static void updatePanes(SciNotesConfiguration.Conf conf) {
2095         for (SciNotes ed : scinotesList) {
2096             int n = ed.getTabPane().getTabCount();
2097             for (int i = 0; i < n; i++) {
2098                 ScilabEditorPane sep = ed.getTextPane(i);
2099                 sep.configurationChanged(conf);
2100                 if (sep.getOtherPaneInSplit() != null) {
2101                     sep.getOtherPaneInSplit().configurationChanged(conf);
2102                 }
2103                 sep.repaint();
2104             }
2105         }
2106     }
2107
2108     public static void updateFontSize(int inc) {
2109         Font baseFont = null;
2110         for (SciNotes ed : scinotesList) {
2111             int n = ed.getTabPane().getTabCount();
2112             for (int i = 0; i < n; i++) {
2113                 ScilabEditorPane sep = ed.getTextPane(i);
2114                 ((ScilabEditorKit) sep.getEditorKit()).getStylePreferences().changeBaseFontSize(inc);
2115                 if (baseFont == null) {
2116                     baseFont = ((ScilabEditorKit) sep.getEditorKit()).getStylePreferences().getBaseFont();
2117                 }
2118                 if (sep.getOtherPaneInSplit() != null) {
2119                     ((ScilabEditorKit) sep.getOtherPaneInSplit().getEditorKit()).getStylePreferences().changeBaseFontSize(n);
2120                     sep.getOtherPaneInSplit().resetFont();
2121                 }
2122                 sep.resetFont();
2123             }
2124         }
2125
2126         if (baseFont != null) {
2127             ScilabContext.saveFont(baseFont);
2128         }
2129     }
2130
2131     /**
2132      * Set the color of the highlighted line in this editor
2133      *
2134      * @param c
2135      *            Color
2136      */
2137     public static void setHighlightedLineColor() {
2138         for (SciNotes ed : scinotesList) {
2139             int n = ed.getTabPane().getTabCount();
2140             for (int i = 0; i < n; i++) {
2141                 ScilabEditorPane sep = ed.getTextPane(i);
2142                 sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2143                 if (sep.getOtherPaneInSplit() != null) {
2144                     sep.getOtherPaneInSplit().setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2145                 }
2146             }
2147         }
2148     }
2149
2150     /**
2151      * Set the color of the contour of the highlighted line in this editor
2152      *
2153      * @param c
2154      *            Color
2155      */
2156     public static void setHighlightedContourColor() {
2157         for (SciNotes ed : scinotesList) {
2158             int n = ed.getTabPane().getTabCount();
2159             for (int i = 0; i < n; i++) {
2160                 ScilabEditorPane sep = ed.getTextPane(i);
2161                 sep.setHighlightedContourColor(null);
2162                 if (sep.getOtherPaneInSplit() != null) {
2163                     sep.getOtherPaneInSplit().setHighlightedContourColor(null);
2164                 }
2165             }
2166         }
2167     }
2168
2169     /**
2170      * Set the highlighted line in this textPane
2171      *
2172      * @param sep
2173      *            ScilabEditorPane
2174      */
2175     public static void setHighlight(ScilabEditorPane sep) {
2176         sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine);
2177         sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor);
2178         sep.setHighlightedContourColor(null);
2179     }
2180
2181     /**
2182      * Get SciNotes as a Tab.
2183      *
2184      * @return SciNotes instance
2185      * @see org.scilab.modules.gui.tab.Tab#getAsSimpleTab()
2186      */
2187     public SimpleTab getAsSimpleTab() {
2188         return this;
2189     }
2190
2191     /**
2192      * Get SciNotes parent Window.
2193      *
2194      * @return parent Window
2195      * @see org.scilab.modules.gui.tab.Tab#getParentWindow()
2196      */
2197     public SwingScilabWindow getParentWindow() {
2198         if (parentWindow == null) {
2199             return super.getParentWindow();
2200         }
2201         return parentWindow;
2202     }
2203
2204     /**
2205      * Get the UUID associated with the editor instance.
2206      *
2207      * @return unique identifier
2208      */
2209     public UUID getUUID() {
2210         return uuid;
2211     }
2212
2213     /**
2214      * Add a status bar to SciNotes.
2215      *
2216      * @param infoBarToAdd
2217      *            the status bar to be added
2218      * @see org.scilab.modules.gui.uielement.UIElement#addInfoBar(org.scilab.modules.gui.textbox.TextBox)
2219      */
2220     public void addInfoBar(TextBox infoBarToAdd) {
2221         setInfoBar(infoBarToAdd);
2222     }
2223
2224     /**
2225      * Add a menu bar to SciNotes.
2226      *
2227      * @param menuBarToAdd
2228      *            the menu bar to be added
2229      * @see org.scilab.modules.gui.uielement.UIElement#addMenuBar(org.scilab.modules.gui.menubar.MenuBar)
2230      */
2231     public void addMenuBar(MenuBar menuBarToAdd) {
2232         setMenuBar(menuBarToAdd);
2233     }
2234
2235     /**
2236      * Add a tool bar to SciNotes.
2237      *
2238      * @param toolBarToAdd
2239      *            the tool bar to be added
2240      * @see org.scilab.modules.gui.uielement.UIElement#addToolBar(org.scilab.modules.gui.toolbar.ToolBar)
2241      */
2242     public void addToolBar(ToolBar toolBarToAdd) {
2243         setToolBar(toolBarToAdd);
2244     }
2245
2246     /**
2247      * Get SciNotes main ScilabTabbedPane.
2248      *
2249      * @return SciNotes main ScilabTabbedPane
2250      */
2251     public ScilabTabbedPane getTabPane() {
2252         return tabPane;
2253     }
2254
2255     /**
2256      * Set SciNotes main ScilabTabbedPane.
2257      *
2258      * @param tabPane
2259      *            SciNotes main ScilabTabbedPane
2260      */
2261     public void setTabPane(ScilabTabbedPane tabPane) {
2262         this.tabPane = tabPane;
2263     }
2264
2265     /**
2266      * Load a file and add it at the end
2267      *
2268      * @param f
2269      *            the file to load
2270      */
2271     public void loadFile(File f) {
2272         loadFile(f, -1);
2273     }
2274
2275     /**
2276      * Load a file and add it at the index
2277      *
2278      * @param f
2279      *            the file to load
2280      * @param index
2281      *            the index where to put the file
2282      */
2283     public void loadFile(File f, int index) {
2284         ScilabDocument styleDocument = null;
2285         ScilabEditorPane theTextPane;
2286
2287         // File exist
2288         if (f.exists()) {
2289             if (!f.canRead()) {
2290                 ScilabModalDialog.show(this, SciNotesMessages.NOTREADABLE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON);
2291                 if (getTabPane().getTabCount() == 0) {
2292                     addEmptyTab();
2293                 }
2294                 return;
2295             }
2296
2297             getInfoBar().setText(SciNotesMessages.LOADING);
2298
2299             if (index != -1) {
2300                 theTextPane = addTab(f.getName(), index);
2301             } else {
2302                 theTextPane = addTab(f.getName());
2303             }
2304             styleDocument = (ScilabDocument) theTextPane.getDocument();
2305             styleDocument.disableUndoManager();
2306             theTextPane.setLastModified(f.lastModified());
2307
2308             try {
2309                 styleDocument.setUpdater(false);
2310                 boolean indentMode = styleDocument.getAutoIndent();
2311                 styleDocument.setAutoIndent(false);
2312                 try {
2313                     ((ScilabEditorKit) editorKit).read(this, f, styleDocument, 0);
2314                 } catch (BadLocationException e) {
2315                     e.printStackTrace();
2316                 }
2317                 styleDocument.setAutoIndent(indentMode);
2318                 styleDocument.setUpdater(true);
2319             } catch (IOException ioex) {
2320                 ioex.printStackTrace();
2321             }
2322
2323             theTextPane.setName(f.getAbsolutePath());
2324             getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
2325             setTitle(theTextPane.getTitle());
2326             styleDocument.setContentModified(false);
2327             styleDocument.enableUndoManager();
2328
2329             if (styleDocument.getBinary()) {
2330                 theTextPane.setBinary(true);
2331             }
2332
2333             if (!f.canWrite()) {
2334                 getTextPane().setReadOnly(true);
2335                 JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.READONLY);
2336             }
2337
2338             getInfoBar().setText(theTextPane.getInfoBarText());
2339
2340             EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument());
2341
2342             firstOpen = false;
2343             ConfigManager.saveLastOpenedDirectory(f.getPath());
2344             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
2345             ConfigSciNotesManager.saveToOpenFiles(f.getPath(), this, getTextPane());
2346
2347             // Empty the undo Manager
2348             UndoManager undo = ((ScilabDocument) getTextPane().getDocument()).getUndoManager();
2349             undo.discardAllEdits();
2350
2351             if (getTabPane().getTabCount() == 2) {
2352                 ScilabEditorPane pane = getTextPane(0);
2353                 if (pane != null && pane.getName() == null && !((ScilabDocument) pane.getDocument()).isContentModified()) {
2354                     closeTabAt(0);
2355                 }
2356             }
2357         }
2358     }
2359
2360     /**
2361      * Creates a file if it doesn't exist
2362      *
2363      * @param f
2364      *            the file to create
2365      */
2366     public void createNewFile(File f) {
2367         ScilabEditorPane theTextPane = addEmptyTab();
2368         ScilabDocument styleDocument = null;
2369         int choice = JOptionPane.showConfirmDialog(SciNotes.this, String.format(SciNotesMessages.FILE_DOESNT_EXIST, f.getName()), SCINOTES,
2370                      JOptionPane.YES_NO_OPTION);
2371         if (choice == 0) { // OK
2372             styleDocument = (ScilabDocument) theTextPane.getDocument();
2373             styleDocument.disableUndoManager();
2374
2375             BufferedWriter bw = null;
2376             OutputStreamWriter osw = null;
2377             FileOutputStream fos = null;
2378
2379             try {
2380                 fos = new FileOutputStream(f);
2381                 osw = new OutputStreamWriter(fos, styleDocument.getEncoding());
2382                 bw = new BufferedWriter(osw);
2383                 editorKit.write(bw, styleDocument, 0, styleDocument.getLength());
2384                 bw.flush();
2385             } catch (IOException e) {
2386                 System.err.println(e);
2387             } catch (BadLocationException e) {
2388                 System.err.println(e);
2389             } finally {
2390                 try {
2391                     if (fos != null) {
2392                         fos.close();
2393                     }
2394                     if (osw != null) {
2395                         osw.close();
2396                     }
2397                     if (bw != null) {
2398                         bw.close();
2399                     }
2400                 } catch (IOException e) {
2401                     System.err.println(e);
2402                 }
2403             }
2404
2405             firstOpen = false;
2406             ConfigManager.saveLastOpenedDirectory(f.getPath());
2407             ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath());
2408             ConfigSciNotesManager.saveToOpenFiles(theTextPane.getName(), this, theTextPane);
2409
2410             theTextPane.setName(f.getPath());
2411             getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName());
2412             setTitle(theTextPane.getTitle());
2413             RecentFileAction.updateRecentOpenedFilesMenu(this);
2414
2415             styleDocument.setContentModified(false);
2416             styleDocument.enableUndoManager();
2417             theTextPane.setLastModified(f.lastModified());
2418         }
2419
2420         getInfoBar().setText("");
2421     }
2422
2423     /**
2424      * EditorKit Getter
2425      *
2426      * @return EditorKit
2427      */
2428     public EditorKit getEditorKit() {
2429         return editorKit;
2430     }
2431
2432     /**
2433      * @param scinotes
2434      *            the focused editor
2435      */
2436     public static void setEditor(SciNotes scinotes) {
2437         editor = scinotes;
2438     }
2439
2440     /**
2441      * @return the focused editor
2442      */
2443     public static SciNotes getEditor() {
2444         return editor;
2445     }
2446
2447     /**
2448      * EditorKit Setter
2449      *
2450      * @param editorKit
2451      *            EditorKit
2452      */
2453     public void setEditorKit(EditorKit editorKit) {
2454         this.editorKit = editorKit;
2455     }
2456
2457     /**
2458      * Close scinotes from scilab.
2459      *
2460      * This method can be called outside the EDT thread.
2461      */
2462     public static void closeSciNotesFromScilab() {
2463         try {
2464             SwingUtilities.invokeAndWait(new Runnable() {
2465
2466                 @Override
2467                 public void run() {
2468                     SciNotes[] arr = scinotesList.toArray(new SciNotes[0]);
2469                     for (int i = 0; i < arr.length; i++) {
2470                         arr[i].setProtectOpenFileList(true);
2471                         ExitAction.doExit(arr[i]);
2472                     }
2473                     scinotesList.clear();
2474                 }
2475             });
2476         } catch (InterruptedException e) {
2477             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
2478         } catch (InvocationTargetException e) {
2479             Logger.getLogger(SciNotes.class.getName()).severe(e.toString());
2480         }
2481     }
2482
2483     /**
2484      * @param f
2485      *            the file
2486      * @return the canonical file if possible
2487      */
2488     public static File fileToCanonicalFile(File f) {
2489         /* Fix bug 5648 */
2490         try {
2491             return f.getCanonicalFile();
2492         } catch (IOException e) {
2493             return f;
2494         }
2495     }
2496
2497     /**
2498      * Set the shortcuts in the pane relatively to the file
2499      * keysConfiguration.xml
2500      *
2501      * @param sep
2502      *            the textpane
2503      * @param ed
2504      *            the SciNotes editor
2505      */
2506     private static void setKeyStrokeAction(ScilabEditorPane sep, SciNotes ed) {
2507         ScilabEditorPane s = ed.getTextPane(0);
2508         if (s != null && s != sep) {
2509             sep.setInputMap(JComponent.WHEN_FOCUSED, s.getInputMap());
2510             return;
2511         }
2512
2513         Map<String, KeyStroke> map = getActionKeys();
2514         ClassLoader loader = ClassLoader.getSystemClassLoader();
2515
2516         for (Map.Entry<String, KeyStroke> entry : map.entrySet()) {
2517             String actionName = entry.getKey();
2518             KeyStroke key = entry.getValue();
2519             String action = actionToName.get(actionName);
2520             if (key != null) {
2521                 if (!action.equals("SciNotesCompletionAction")) {
2522                     String className;
2523                     if (action.lastIndexOf(DOT) != -1) {
2524                         className = action;
2525                     } else {
2526                         className = DEFAULTACTIONPATH + DOT + action;
2527                     }
2528                     try {
2529                         Class clazz = loader.loadClass(className);
2530                         Constructor constructor = clazz.getConstructor(new Class[] { String.class, SciNotes.class });
2531                         Object act = constructor.newInstance(new Object[] { "", ed });
2532                         sep.getInputMap().put(key, act);
2533                     } catch (ClassNotFoundException e) {
2534                         System.err.println("No action: " + className);
2535                     } catch (InstantiationException e) {
2536                         System.err.println("Problem to instantiate in action: " + className);
2537                     } catch (NoSuchMethodException e) {
2538                         System.err.println("No valid constructor in action: " + className);
2539                     } catch (IllegalAccessException e) {
2540                         System.err.println("The constructor must be public: " + className);
2541                     } catch (InvocationTargetException e) {
2542                         System.err.println("The constructor in " + className + " threw an exception :");
2543                         e.printStackTrace();
2544                     }
2545                 } else {
2546                     sep.getInputMap().put(key, new SciNotesCompletionAction(sep, ed));
2547                 }
2548             }
2549         }
2550
2551         // Add default common shortcuts
2552         sep.getInputMap().put(KeyStroke.getKeyStroke("shift DELETE"), sep.getInputMap().get(map.get("scinotes-cut")));
2553         sep.getInputMap().put(KeyStroke.getKeyStroke("CUT"), sep.getInputMap().get(map.get("scinotes-cut")));
2554         sep.getInputMap().put(ScilabKeyStroke.getKeyStroke("OSSCKEY INSERT"), sep.getInputMap().get(map.get("scinotes-copy")));
2555         sep.getInputMap().put(KeyStroke.getKeyStroke("COPY"), sep.getInputMap().get(map.get("scinotes-copy")));
2556         sep.getInputMap().put(KeyStroke.getKeyStroke("shift INSERT"), sep.getInputMap().get(map.get("scinotes-paste")));
2557         sep.getInputMap().put(KeyStroke.getKeyStroke("PASTE"), sep.getInputMap().get(map.get("scinotes-paste")));
2558     }
2559
2560     /**
2561      * Execute an action on file
2562      * @param fileName the name of the file
2563      * @param action the action
2564      */
2565     public static void executeAction(String fileName, ActionOnDocument action) throws IOException {
2566         Charset charset = null;
2567         try {
2568             charset = ScilabEditorKit.tryToGuessEncoding(new File(fileName));
2569         } catch (CharacterCodingException e) {
2570             throw new IOException(SciNotesMessages.CANNOT_GUESS_ENCODING + ": " + fileName);
2571         }
2572         FileInputStream fis = new FileInputStream(fileName);
2573         InputStreamReader isr = new InputStreamReader(fis, charset);
2574         BufferedReader reader = new BufferedReader(isr);
2575         ScilabDocument doc = new ScilabDocument();
2576         ScilabEditorKit kit = new ScilabEditorKit();
2577         try {
2578             kit.read(reader, doc, 0);
2579         } catch (BadLocationException e) {
2580             System.err.println(e);
2581         }
2582
2583         doc.addDocumentListener(doc);
2584         if (!doc.getBinary()) {
2585             action.actionOn(doc);
2586         }
2587
2588         reader.close();
2589         if (doc.isContentModified()) {
2590             SaveFile.doSave(doc, new File(fileName), kit);
2591         }
2592     }
2593
2594     /**
2595      * Execute an action on file
2596      * @param fileName the name of the file
2597      * @param actionsName the actions as an array
2598      */
2599     public static boolean executeAction(String fileName, final String[] actionsName) throws IOException {
2600         final boolean[] hasAction = new boolean[] { false };
2601         ActionOnDocument action = new ActionOnDocument() {
2602             public void actionOn(ScilabDocument doc) throws IOException {
2603                 for (String act : actionsName) {
2604                     if (act.equalsIgnoreCase("indent")) {
2605                         hasAction[0] = true;
2606                         org.scilab.modules.scinotes.actions.IndentAction.getActionOnDocument().actionOn(doc);
2607                     } else if (act.equalsIgnoreCase("trailing")) {
2608                         hasAction[0] = true;
2609                         org.scilab.modules.scinotes.actions.RemoveTrailingWhiteAction.getActionOnDocument().actionOn(doc);
2610                     } else if (act.equalsIgnoreCase("quote")) {
2611                         hasAction[0] = true;
2612                         org.scilab.modules.scinotes.actions.DoubleQuoteStringAction.getActionOnDocument().actionOn(doc);
2613                     }
2614                 }
2615             }
2616         };
2617
2618         executeAction(fileName, action);
2619
2620         return hasAction[0];
2621     }
2622
2623     /**
2624      * Execute an action on file
2625      * @param fileName the name of the file
2626      * @param acts actions separated with , or ;
2627      */
2628     public static void executeAction(String fileName, String acts) throws IOException {
2629         StringTokenizer toks = new StringTokenizer(acts, ",;");
2630         String[] actions = new String[toks.countTokens()];
2631         for (int i = 0; i < actions.length; i++) {
2632             actions[i] = toks.nextToken();
2633         }
2634         executeAction(fileName, actions);
2635     }
2636
2637     /**
2638      * An interface to implement to execute an action on a document
2639      */
2640     public static interface ActionOnDocument {
2641
2642         public void actionOn(ScilabDocument doc) throws IOException;
2643     }
2644 }