SciNotes: make a little cleanup
[scilab.git] / scilab / modules / scinotes / src / java / org / scilab / modules / scinotes / utils / ConfigSciNotesManager.java
1 /*
2  * Scilab (http://www.scilab.org/) - This file is part of Scilab
3  * Copyright (C) 2009 - INRIA - Allan SIMON
4  * Copyright (C) 2010 - Calixte DENIZET
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 package org.scilab.modules.scinotes.utils;
15
16 import java.awt.Color;
17 import java.awt.Font;
18 import java.awt.Toolkit;
19 import java.awt.print.Paper;
20
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.nio.charset.Charset;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Hashtable;
31 import java.util.Properties;
32 import java.util.Enumeration;
33 import java.util.Map;
34 import java.util.UUID;
35
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.transform.OutputKeys;
40 import javax.xml.transform.Transformer;
41 import javax.xml.transform.TransformerConfigurationException;
42 import javax.xml.transform.TransformerException;
43 import javax.xml.transform.TransformerFactoryConfigurationError;
44 import javax.xml.transform.dom.DOMSource;
45 import javax.xml.transform.stream.StreamResult;
46
47 import org.scilab.modules.commons.ScilabCommons;
48 import org.scilab.modules.commons.ScilabConstants;
49 import org.scilab.modules.commons.ScilabCommonsUtils;
50 import org.scilab.modules.commons.xml.ScilabXMLUtilities;
51 import org.scilab.modules.commons.xml.ScilabDocumentBuilderFactory;
52 import org.scilab.modules.commons.xml.ScilabTransformerFactory;
53 import org.scilab.modules.gui.messagebox.ScilabModalDialog;
54 import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType;
55 import org.scilab.modules.gui.utils.Position;
56 import org.scilab.modules.gui.utils.Size;
57
58 import org.scilab.modules.scinotes.ScilabView;
59 import org.scilab.modules.scinotes.ScilabEditorPane;
60 import org.scilab.modules.scinotes.SciNotes;
61 import org.scilab.modules.scinotes.TabManager;
62 import org.scilab.modules.scinotes.MatchingBlockManager;
63
64 import org.w3c.dom.Document;
65 import org.w3c.dom.Element;
66 import org.w3c.dom.Node;
67 import org.w3c.dom.NodeList;
68 import org.w3c.dom.Text;
69 import org.xml.sax.SAXException;
70
71 /**
72  * Configuration class which interacts with the file etc/scinotesConfiguration.xml
73  */
74 public final class ConfigSciNotesManager {
75
76     public static final String RECENTBASEDIR = "recentBaseDir";
77     public static final String BASEDIR = "baseDir";
78     public static final String RECENTFILEPATTERN = "recentFilePattern";
79     public static final String FILEPATTERN = "filePattern";
80     public static final String RECENTWORDPATTERN = "recentWordPattern";
81     public static final String WORDPATTERN = "wordPattern";
82
83     private static final int BUFSIZE = 1024;
84
85     private static final int MARGIN = 20;
86
87     private static final String ERROR_READ = "Could not load file: ";
88     private static final String ERROR_WRITE = "Could not save file: ";
89     private static final String VALUE = "value";
90     private static final String VERSION = "version";
91     private static final String STYLE = "style";
92     private static final String UNDERLINE = "underline";
93     private static final String DEFAULTUNDERLINE = "defaultUnderline";
94     private static final String STROKE = "stroke";
95     private static final String DEFAULTSTROKE = "defaultStroke";
96     private static final String FONT_SIZE = "FontSize";
97     private static final String FONT_STYLE = "FontStyle";
98     private static final String FONT_NAME = "FontName";
99     private static final String DEFAULT = "default";
100     private static final String WIDTH = "width";
101     private static final String HEIGHT = "height";
102     private static final String XCOORD = "x";
103     private static final String YCOORD = "y";
104     private static final String MAINWINPOSITION = "MainWindowPosition";
105     private static final String MAINWINSIZE = "MainWindowSize";
106     private static final String AUTOINDENT = "AutoIndent";
107     private static final String DEFAULTENCONDING = "DefaultEncoding";
108     private static final String LINEHIGHLIGHTER = "LineHighlighter";
109     private static final String HELPONTYPING = "HelpOnTyping";
110     private static final String LINENUMBERING = "LineNumbering";
111     private static final String EDITOR = "SciNotes";
112     
113     private static final String FOREGROUNDCOLOR = "ForegroundColor";
114     private static final String BACKGROUNDCOLOR = "BackgroundColor";
115     private static final String ALTERNCOLORS = "AlternColors";
116     private static final String COLOR1 = "color1";
117     private static final String COLOR2 = "color2";
118     private static final String LINECOLOR = "linecolor";
119     private static final String CONTOURCOLOR = "contourcolor";
120     private static final String COLORPREFIX = "#";
121
122     private static final String NAME = "name";
123     private static final String NULL = "null";
124
125     private static final String PROFILE = "Profile";
126
127     private static final String RECENT_SEARCH = "recentSearch";
128     private static final String SEARCH = "search";
129     private static final String RECENT_REPLACE = "recentReplace";
130     private static final String REPLACE = "replace";
131     private static final String RECURSIVE = "recursiveSearch";
132     private static final String LINEBYLINE = "readLineByLine";
133     private static final String FILECASE = "fileCase";
134     private static final String SEARCHINFILES = "searchInFiles";
135
136     private static final String EXPRESSION = "exp";
137     private static final String REGULAR_EXPRESION = "regularExp";
138     private static final String CIRCULAR = "circularSearch";
139     private static final String WORD_WARP = "wordWarp";
140     private static final String WHOLE_WORD = "wholeWord";
141     private static final String CASE_SENSITIVE = "caseSensitive";
142     private static final String STATE_FLAG = "state";
143
144     private static final String SETTING = "Setting";
145     private static final String SCINOTES = "scinotes";
146     private static final String TRUE = "true";
147     private static final String FALSE = "false";
148     private static final String DOCUMENT = "document";
149     private static final String PATH = "path";
150     private static final String RECENT_FILES = "recentFiles";
151     private static final String OPEN_FILES = "openFiles";
152     private static final String RESTOREFILES = "RestoreFiles";
153     private static final String EDITORINST = "editorInstance";
154     private static final String EDITORUUID = "EditorUUID";
155     private static final String PANEINST = "paneInstance";
156     private static final String PANEINST_EX = "paneInstanceExtra";
157
158     private static final String FAVORITE_DIRS = "favoriteDirectories";
159     private static final String DIRECTORY = "Directory";
160
161     private static final String PAPER = "PaperFormat";
162     private static final String MARGINLEFT = "MarginLeft";
163     private static final String MARGINRIGHT = "MarginRight";
164     private static final String MARGINTOP = "MarginTop";
165     private static final String MARGINBOTTOM = "MarginBottom";
166
167     private static final String CODENAVIGATOR = "CodeNavigator";
168
169     private static final String SCI = "SCI";
170     private static final String SCINOTES_CONFIG_FILE = System.getenv(SCI) + "/modules/scinotes/etc/scinotesConfiguration.xml";
171
172     private static final int PLAIN = 0;
173     private static final int BOLD =  1;
174     private static final int ITALIC = 2;
175     private static final int BOLDITALIC = 3;
176
177     private static final int DEFAULT_WIDTH = 650;
178     private static final int DEFAULT_HEIGHT = 550;
179
180     private static final int MAXRECENT = 20;
181
182     private static Document document;
183
184     private static boolean updated;
185     private static boolean mustSave = true;
186
187     private static String USER_SCINOTES_CONFIG_FILE = ScilabConstants.SCIHOME.toString() + "/scinotesConfiguration.xml";
188
189     static {
190         if (ScilabConstants.SCIHOME != null && ScilabConstants.SCIHOME.canRead() && ScilabConstants.SCIHOME.canWrite()) {
191             USER_SCINOTES_CONFIG_FILE = ScilabConstants.SCIHOME.toString() + "/scinotesConfiguration.xml";
192         } else {
193             USER_SCINOTES_CONFIG_FILE = SCINOTES_CONFIG_FILE;
194             mustSave = false;
195         }
196     }
197
198     /**
199      * Constructor
200      */
201     private ConfigSciNotesManager() {
202         throw new UnsupportedOperationException();
203     }
204
205     /**
206      * Create a copy of Scilab configuration file in the user directory
207      */
208     public static void createUserCopy() {
209         if (checkVersion() && mustSave) {
210             /* Create a local copy of the configuration file */
211             ScilabCommonsUtils.copyFile(new File(SCINOTES_CONFIG_FILE), new File(USER_SCINOTES_CONFIG_FILE));
212             document = null;
213             updated = true;
214         }
215     }
216
217     /**
218      * Get the name of the user configuration file
219      * @return the name of the configuration file
220      */
221     public static String getUserConfigFile() {
222         return USER_SCINOTES_CONFIG_FILE;
223     }
224
225     /**
226      * @return true if scinotesConfiguration.xml in etc has a version greater than the version in home
227      */
228     public static boolean checkVersion() {
229         if (updated) {
230             return false;
231         }
232
233         File fileConfig = new File(USER_SCINOTES_CONFIG_FILE);
234
235         if (fileConfig.exists()) {
236             document = null;
237             readDocument(SCINOTES_CONFIG_FILE);
238             Node setting = getNodeChild(null, SETTING);
239             String str = ((Element) setting).getAttribute(VERSION);
240             if (str != null && str.length() != 0) {
241                 float versionEtc = Float.parseFloat(str);
242                 document = null;
243                 readDocument();
244                 setting = getNodeChild(null, SETTING);
245                 str = ((Element) setting).getAttribute(VERSION);
246                 document = null;
247
248                 if (str != null && str.length() != 0) {
249                     float versionHome = Float.parseFloat(str);
250                     return versionEtc != versionHome;
251                 }
252             }
253         }
254
255         return true;
256     }
257
258     /**
259      * @return the paper format saved in previous session
260      */
261     public static Paper getPaperFormat() {
262         readDocument();
263
264         Element root = document.getDocumentElement();
265
266         NodeList profiles = root.getElementsByTagName(PROFILE);
267         Element scinotesProfile = (Element) profiles.item(0);
268
269         NodeList allSizeElements = scinotesProfile.getElementsByTagName(PAPER);
270         Element paper = (Element) allSizeElements.item(0);
271
272         if (paper == null) {
273             return new Paper();
274         }
275
276         Paper p = new Paper();
277         double width = Double.parseDouble(paper.getAttribute(WIDTH));
278         double height = Double.parseDouble(paper.getAttribute(HEIGHT));
279         double marginLeft = Double.parseDouble(paper.getAttribute(MARGINLEFT));
280         double marginRight = Double.parseDouble(paper.getAttribute(MARGINRIGHT));
281         double marginTop = Double.parseDouble(paper.getAttribute(MARGINTOP));
282         double marginBottom = Double.parseDouble(paper.getAttribute(MARGINBOTTOM));
283         p.setSize(width, height);
284         p.setImageableArea(marginLeft, marginTop, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
285
286         return p;
287     }
288
289     /**
290      * Save the paper format
291      * @param p the Paper to save
292      */
293     public static void savePaperFormat(Paper p) {
294         readDocument();
295
296         Element root = document.getDocumentElement();
297
298         NodeList profiles = root.getElementsByTagName(PROFILE);
299         Element scinotesProfile = (Element) profiles.item(0);
300
301         NodeList allSizeElements = scinotesProfile.getElementsByTagName(PAPER);
302         Element paper = (Element) allSizeElements.item(0);
303
304         if (paper == null) {
305             paper = document.createElement(PAPER);
306             scinotesProfile.appendChild((Node) paper);
307         }
308
309         double width = p.getWidth();
310         double height = p.getHeight();
311         double marginLeft = p.getImageableX();
312         double marginRight = width - (marginLeft + p.getImageableWidth());
313         double marginTop = p.getImageableY();
314         double marginBottom = height - (marginTop + p.getImageableHeight());
315
316         paper.setAttribute(WIDTH, Double.toString(width));
317         paper.setAttribute(HEIGHT, Double.toString(height));
318         paper.setAttribute(MARGINLEFT, Double.toString(marginLeft));
319         paper.setAttribute(MARGINRIGHT, Double.toString(marginRight));
320         paper.setAttribute(MARGINTOP, Double.toString(marginTop));
321         paper.setAttribute(MARGINBOTTOM, Double.toString(marginBottom));
322
323         writeDocument();
324     }
325
326     /**
327      * @return the color the altern colors for inner function
328      */
329     public static Color[] getAlternColors() {
330         readDocument();
331
332         Element root = document.getDocumentElement();
333
334         NodeList profiles = root.getElementsByTagName(PROFILE);
335         Element scinotesProfile = (Element) profiles.item(0);
336
337         NodeList allSizeElements = scinotesProfile.getElementsByTagName(ALTERNCOLORS);
338         Element alternColors = (Element) allSizeElements.item(0);
339         Color[] arr = new Color[2];
340
341         Color c;
342         if (NULL.equals(alternColors.getAttribute(COLOR1))) {
343             c = null;
344         } else {
345             c = Color.decode(alternColors.getAttribute(COLOR1));
346         }
347
348         arr[0] = c;
349
350         if (NULL.equals(alternColors.getAttribute(COLOR2))) {
351             c = null;
352         } else {
353             c = Color.decode(alternColors.getAttribute(COLOR2));
354         }
355
356         arr[1] = c;
357         return arr;
358     }
359
360     /**
361      * Get all the recent opened files
362      * @return an array of uri
363      */
364     public static List<File> getAllRecentOpenedFiles() {
365         List<File> files = new ArrayList<File>();
366         readDocument();
367         Element root = (Element) document.getDocumentElement().getElementsByTagName(RECENT_FILES).item(0);
368         if (root != null) {
369             NodeList recentFiles = root.getElementsByTagName(DOCUMENT);
370             for (int i = 0; i < recentFiles.getLength(); ++i) {
371                 Element style = (Element) recentFiles.item(i);
372
373                 File temp = new File(style.getAttribute(PATH));
374
375                 if (temp.exists()) {
376                     files.add(temp);
377                 } else {
378                     root.removeChild((Node) style);
379                 }
380             }
381         }
382
383         clean(root);
384         writeDocument();
385
386         return files;
387     }
388
389     /**
390      * Get all the favorite dirs
391      * @return a list of File
392      */
393     public static List<File> getAllFavoriteDirs() {
394         List<File> dirsList = new ArrayList<File>();
395         readDocument();
396         Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0);
397         if (root != null) {
398             NodeList dirs = root.getElementsByTagName(DIRECTORY);
399             for (int i = 0; i < dirs.getLength(); i++) {
400                 Element dir = (Element) dirs.item(i);
401                 File temp = new File(dir.getAttribute(PATH));
402
403                 if (temp.exists()) {
404                     dirsList.add(temp);
405                 } else {
406                     root.removeChild((Node) dir);
407                 }
408             }
409         }
410
411         clean(root);
412         writeDocument();
413
414         return dirsList;
415     }
416
417     /**
418      * Add a path to a favorite directory
419      * @param path the path of the dir
420      */
421     public static void saveFavoriteDirectory(String path) {
422         readDocument();
423
424         Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0);
425         Element newDir =  document.createElement(DIRECTORY);
426         newDir.setAttribute(PATH, path);
427         root.appendChild((Node) newDir);
428
429         clean(root);
430         writeDocument();
431     }
432
433     /**
434      * Remove the last favorite directory
435      */
436     public static void rmLastFavoriteDirectory() {
437         readDocument();
438
439         Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0);
440         NodeList dirs = root.getElementsByTagName(DIRECTORY);
441
442         if (dirs.getLength() != 0) {
443             root.removeChild(dirs.item(dirs.getLength() - 1));
444         }
445
446         clean(root);
447         writeDocument();
448     }
449
450     /**
451      * Add a file to recent Opened Files
452      * @param filePath the path of the files to add
453      */
454     public static void saveToRecentOpenedFiles(String filePath) {
455         readDocument();
456
457         Element root = (Element) document.getDocumentElement().getElementsByTagName(RECENT_FILES).item(0);
458         NodeList recentFiles = root.getElementsByTagName(DOCUMENT);
459         int numberOfFiles = recentFiles.getLength();
460
461         // we remove all the duplicate
462         for (int i = 0; i < recentFiles.getLength();  ++i) {
463             Element style = (Element) recentFiles.item(i);
464             if (filePath.equals(style.getAttribute(PATH))) {
465                 root.removeChild((Node) style);
466                 numberOfFiles--;
467             }
468         }
469
470         // if we have reached the maximun , we remove the oldest files
471         while (recentFiles.getLength() >= MAXRECENT) {
472             root.removeChild(root.getFirstChild());
473         }
474
475         Element newFile =  document.createElement(DOCUMENT);
476         newFile.setAttribute(PATH, filePath);
477         root.appendChild((Node) newFile);
478
479         clean(root);
480         writeDocument();
481     }
482
483     /**
484      * @return true if open files should be restored upon restart.
485      */
486     public static boolean getRestoreOpenedFiles() {
487         readDocument();
488
489         Element root = document.getDocumentElement();
490
491         NodeList profiles = root.getElementsByTagName(PROFILE);
492         Element scinotesProfile = (Element) profiles.item(0);
493
494         NodeList allSizeElements = scinotesProfile.getElementsByTagName(RESTOREFILES);
495         Element restorefiles = (Element) allSizeElements.item(0);
496
497         return TRUE.equals(restorefiles.getAttribute(VALUE));
498     }
499
500     /**
501      * Active/deactive restoration of open files upon restart of scinotes
502      * @param activated active or not
503      */
504     public static void saveRestoreOpenedFiles(boolean activated) {
505         readDocument();
506
507         Element root = document.getDocumentElement();
508
509         NodeList profiles = root.getElementsByTagName(PROFILE);
510         Element scinotesProfile = (Element) profiles.item(0);
511
512         NodeList allSizeElements = scinotesProfile.getElementsByTagName(RESTOREFILES);
513         Element restorefiles = (Element) allSizeElements.item(0);
514         if (restorefiles == null) {
515             Element restoreElement = document.createElement(RESTOREFILES);
516             restorefiles.setAttribute(VALUE, new Boolean(activated).toString());
517             restorefiles.appendChild((Node) restoreElement);
518         } else {
519             restorefiles.setAttribute(VALUE, new Boolean(activated).toString());
520         }
521
522         clean(root);
523         writeDocument();
524     }
525
526     /**
527      * Return a count of the open files that exist. New files, for instance, do not.
528      * @return count
529      */
530     public static int countExistingOpenFiles(UUID uuid) {
531         int count = 0;
532         readDocument();
533         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
534         if (root != null) {
535             NodeList openFiles = root.getElementsByTagName(DOCUMENT);
536             for (int i = 0; i < openFiles.getLength(); ++i) {
537                 Element style = (Element) openFiles.item(i);
538                 if (style.getAttribute(EDITORINST).equals(uuid.toString())) {
539                     File temp = new File(style.getAttribute(PATH));
540                     if (temp.exists()) {
541                         count++;
542                     }
543                 }
544             }
545         }
546         return count;
547     }
548
549     /**
550      * Get the list of open files associated with an editor instance hashcode.
551      * Only files that exist are returned.
552      * @param editorID unique id of an editor instance
553      * @return an array of uri
554      */
555     public static List<File> getOpenFilesByEditor(UUID editorID) {
556         List<File> files = new ArrayList<File>();
557         readDocument();
558         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
559         if (root != null) {
560             NodeList openFiles = root.getElementsByTagName(DOCUMENT);
561
562             /* Loop through the list and return only the files with a matching hash code. */
563             int i = 0;
564             for (; i < openFiles.getLength(); i++) {
565                 Element doc = (Element) openFiles.item(i);
566
567                 if (editorID.equals(UUID.fromString(doc.getAttribute(EDITORINST)))) {
568                     File temp = new File(doc.getAttribute(PATH));
569
570                     /* Check that the file exists and add to file list or else remove the node. */
571                     if (temp.exists() && !files.contains(temp)) {
572                         files.add(temp);
573                     } else {
574                         root.removeChild((Node) doc);
575                         i--;  // Adjust index to account for removed item.
576                     }
577                 }
578             }
579
580             clean(root);
581             writeDocument();
582         }
583         return files;
584     }
585
586     /**
587      * Get a list of unique editor instance identifiers in the list of open files.
588      * @return an array of editor instance identifiers
589      */
590     public static List<UUID> getOpenFilesEditorList() {
591         List<UUID> editorIDlist = new ArrayList<UUID>();
592         readDocument();
593         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
594         if (root != null) {
595             NodeList openFiles = root.getElementsByTagName(DOCUMENT);
596
597             /* Loop through the list and return the list of IDs. */
598             for (int i = 0; i < openFiles.getLength(); ++i) {
599                 Element style = (Element) openFiles.item(i);
600
601                 UUID editorID = UUID.fromString(style.getAttribute(EDITORINST));
602
603                 if (!editorIDlist.contains(editorID)) {
604                     editorIDlist.add(editorID);
605                 }
606             }
607         }
608         return editorIDlist;
609     }
610
611     /**
612      * Add a file to currently open files
613      * @param filePath the path of the files to add
614      * @param editorInstance instance of the editor to associate with the open file
615      * @param sep the pane
616      */
617     public static void saveToOpenFiles(String filePath, SciNotes editorInstance, ScilabEditorPane sep) {
618         saveToOpenFiles(filePath, editorInstance, sep, -1);
619     }
620
621     /**
622      * Add a file to currently open files
623      * @param filePath the path of the files to add
624      * @param editorInstance instance of the editor to associate with the open file
625      * @param sep the pane
626      */
627     public static void saveToOpenFiles(String filePath, SciNotes editorInstance, ScilabEditorPane sep, int pos) {
628         readDocument();
629         removeFromOpenFiles(editorInstance.getUUID(), Arrays.asList(new String[] {filePath}));
630         UUID nil = new UUID(0, 0);
631
632         // Find the element containing the list of open files
633         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
634         // Get the list of open files
635         NodeList openFiles = root.getElementsByTagName(DOCUMENT);
636         int numberOfFiles = openFiles.getLength();
637
638         Node bef = null;
639         if (pos != - 1 && pos < numberOfFiles) {
640             bef = openFiles.item(pos);
641         }
642
643         Element newFile =  document.createElement(DOCUMENT);
644         newFile.setAttribute(PATH, filePath);
645         // Record the editor instance's hash code
646         newFile.setAttribute(EDITORINST, editorInstance.getUUID().toString());
647         //root.appendChild((Node) newFile);
648         // Record the text pane's hash code
649         newFile.setAttribute(PANEINST, sep.getUUID().toString());
650         newFile.setAttribute(PANEINST_EX, nil.toString());
651         if (bef != null) {
652             root.insertBefore((Node) newFile, bef);
653         } else {
654             root.appendChild((Node) newFile);
655         }
656
657         clean(root);
658         writeDocument();
659     }
660
661     /**
662      * Remove a tab with an open file from the list of open files
663      * @param editorInstance instance of the editor
664      * @param sep instance of the editor pane.
665      */
666     public static void removeFromOpenFiles(SciNotes editorInstance, ScilabEditorPane sep) {
667         removeFromOpenFiles(editorInstance.getUUID(), sep.getUUID());
668     }
669
670     /**
671      * Remove from the list of open files all files with a matching editor instance identifer
672      * @param editorID editor instance identifer
673      */
674     public static void removeFromOpenFiles(UUID editorID) {
675         removeFromOpenFiles(editorID, new UUID(0, 0) /* nil UUID */);
676     }
677
678     /**
679      * Remove a tab with an open file from the list of open files
680      * @param editorID editor instance identifer
681      * @param sepID editor pane instance identifer. If a nil UUID is passed,
682      * all files with a matching editor instance identifer are removed.
683      */
684     public static void removeFromOpenFiles(UUID editorID, List<String> toRemove) {
685         readDocument();
686
687         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
688         NodeList openFiles = root.getElementsByTagName(DOCUMENT);
689
690         // Remove item with matching editorID and sepID.
691         for (int i = openFiles.getLength() - 1; i >= 0; i--) {
692             Element doc = (Element) openFiles.item(i);
693             if (editorID.equals(UUID.fromString(doc.getAttribute(EDITORINST)))
694                     && toRemove.contains(doc.getAttribute(PATH))) {
695                 root.removeChild((Node) doc);
696             }
697         }
698
699         clean(root);
700         writeDocument();
701     }
702
703     /**
704      * Remove a tab with an open file from the list of open files
705      * @param editorID editor instance identifer
706      * @param sepID editor pane instance identifer. If a nil UUID is passed,
707      * all files with a matching editor instance identifer are removed.
708      */
709     public static void removeFromOpenFiles(UUID editorID, UUID sepID) {
710         readDocument();
711
712         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
713         NodeList openFiles = root.getElementsByTagName(DOCUMENT);
714
715         // Remove item with matching editorID and sepID.
716         UUID nil = new UUID(0, 0);
717         for (int i = openFiles.getLength() - 1; i >= 0; i--) {
718             Element style = (Element) openFiles.item(i);
719             UUID paneID1 = UUID.fromString(style.getAttribute(PANEINST));
720             UUID paneID2 = UUID.fromString(style.getAttribute(PANEINST_EX));
721
722             if (editorID.equals(UUID.fromString(style.getAttribute(EDITORINST)))
723                     && (sepID.equals(nil) || sepID.equals(paneID1) || sepID.equals(paneID2))) {
724                 root.removeChild((Node) style);
725             }
726         }
727
728         clean(root);
729         writeDocument();
730     }
731
732     /**
733      * Change a filename.
734      * @param newfilePath new pathname of the file
735      * @param editorInstance instance of the editor
736      * @param sep instance of the editor pane
737      */
738     public static void renameOpenFilesItem(String newfilePath, SciNotes editorInstance, ScilabEditorPane sep) {
739         readDocument();
740
741         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
742         Element style = findOpenFileItem(root, editorInstance.getUUID(), sep.getUUID());
743
744         if (style != null) {
745             style.setAttribute(PATH, newfilePath);
746         }
747
748         /* Save changes */
749         writeDocument();
750     }
751
752     /**
753      * Replace a single text pane ID with two pane IDs when a tab split occurs
754      * @param editorInstance instance of the editor
755      * @param old1 old instance of the editor pane
756      * @param new1 first new instance of the tabbed editor pane
757      * @param new2 second new instance of the tabbed editor pane
758      */
759     public static void tabSplitOpenFilesItem(SciNotes editorInstance, ScilabEditorPane old1, ScilabEditorPane new1, ScilabEditorPane new2) {
760         readDocument();
761
762         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
763         Element style = findOpenFileItem(root, editorInstance.getUUID(), old1.getUUID());
764
765         if (style != null) {
766             style.setAttribute(PANEINST, new1.getUUID().toString());
767             style.setAttribute(PANEINST_EX, new2.getUUID().toString());
768         }
769
770         /* Save changes */
771         writeDocument();
772     }
773
774     /**
775      * Replace double pane IDs with a single ID when a tabbed pane is replaced by a single pane.
776      * @param editorInstance instance of the editor
777      * @param old1 one of the old tabbed editor pane
778      * @param new1 new editor pane
779      */
780     public static void removeTabSplitInOpenFilesItem(SciNotes editorInstance, ScilabEditorPane old1, ScilabEditorPane new1) {
781         readDocument();
782
783         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
784         Element style = findOpenFileItem(root, editorInstance.getUUID(), old1.getUUID());
785
786         if (style != null) {
787             UUID nil = new UUID(0, 0);
788             style.setAttribute(PANEINST, new1.getUUID().toString());
789             style.setAttribute(PANEINST_EX, nil.toString());
790         }
791
792         /* Save changes */
793         writeDocument();
794     }
795
796     /**
797      * Find the first element with matching editor and pane identifiers
798      * @param root Document root
799      * @param editorID instance of the editor to find
800      * @param sepID instance of the editor pane to find
801      * @return the corresponding element
802      */
803     public static Element findOpenFileItem(Element root, UUID editorID, UUID sepID) {
804         NodeList openFiles = root.getElementsByTagName(DOCUMENT);
805
806         // Find item with matching editor and pane IDs
807         for (int i = 0; i < openFiles.getLength(); i++) {
808             Element style = (Element) openFiles.item(i);
809             UUID paneID1 = UUID.fromString(style.getAttribute(PANEINST));
810             UUID paneID2 = UUID.fromString(style.getAttribute(PANEINST_EX));
811
812             if (editorID.equals(UUID.fromString(style.getAttribute(EDITORINST)))
813                     && (sepID.equals(paneID1) || sepID.equals(paneID2))) {
814                 return style;
815             }
816         }
817
818         return null;
819     }
820
821     /**
822      * Empty the list of open files. Performed when the editor is opened
823      * and the user opts not to restore the open files.
824      */
825     public static void removeAllOpenFiles() {
826         readDocument();
827
828         Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
829         NodeList openFiles = root.getElementsByTagName(DOCUMENT);
830
831         // Remove all
832         for (int i = openFiles.getLength() - 1; i >= 0;  --i) {
833             Element style = (Element) openFiles.item(i);
834             root.removeChild((Node) style);
835         }
836
837         clean(root);
838         writeDocument();
839     }
840
841     /**
842      * Reset the current conf file
843      */
844     public static void resetDocument() {
845         document = null;
846     }
847
848     /**
849      * Read the file to modify
850      */
851     private static void readDocument() {
852         readDocument(USER_SCINOTES_CONFIG_FILE);
853     }
854
855     /**
856      * Read the file to modify
857      */
858     private static void readDocument(String pathConfSci) {
859         File fileConfig = new File(USER_SCINOTES_CONFIG_FILE);
860         if (!fileConfig.exists()) {
861             createUserCopy();
862         }
863         File xml = null;
864         DocumentBuilder docBuilder = null;
865         String factoryName = ScilabDocumentBuilderFactory.useDefaultDocumentBuilderFactoryImpl();
866
867         try {
868             if (document == null) {
869                 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
870                 docBuilder = factory.newDocumentBuilder();
871
872                 // read content of a XML file with DOM
873                 xml = new File(pathConfSci);
874                 document = docBuilder.parse(xml);
875             }
876         } catch (ParserConfigurationException pce) {
877             System.err.println(ERROR_READ + pathConfSci);
878         } catch (SAXException se) {
879             System.err.println(ERROR_READ + pathConfSci);
880         } catch (IOException ioe) {
881             System.err.println(ERROR_READ + pathConfSci);
882         }
883
884         ScilabDocumentBuilderFactory.restoreDocumentBuilderFactoryImpl(factoryName);
885
886         if (document == null && fileConfig.exists()) {
887             ScilabModalDialog.show(null, SciNotesMessages.CORRUPTED_CONF_FILE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON);
888             fileConfig.delete();
889             createUserCopy();
890             readDocument(pathConfSci);
891         }
892     }
893
894     /**
895      * Save the modifications
896      */
897     private static void writeDocument() {
898         if (mustSave) {
899             Transformer transformer = null;
900             try {
901                 transformer = ScilabTransformerFactory.newInstance().newTransformer();
902             } catch (TransformerConfigurationException e1) {
903                 System.err.println(ERROR_WRITE + USER_SCINOTES_CONFIG_FILE);
904                 System.err.println(e1);
905             } catch (TransformerFactoryConfigurationError e1) {
906                 System.err.println(ERROR_WRITE + USER_SCINOTES_CONFIG_FILE);
907                 System.err.println(e1);
908             }
909
910             if (transformer != null) {
911                 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
912
913                 StreamResult result = new StreamResult(new File(USER_SCINOTES_CONFIG_FILE));
914                 DOMSource source = new DOMSource(document);
915                 try {
916                     transformer.transform(source, result);
917                 } catch (TransformerException e) {
918                     System.err.println(ERROR_WRITE + USER_SCINOTES_CONFIG_FILE);
919                     System.err.println(e);
920                 }
921             }
922         }
923     }
924
925     /**
926      *
927      */
928     public static void saveCodeNavigatorState(String editorUUID, String navUUID) {
929         readDocument();
930
931         Element root = document.getDocumentElement();
932         NodeList navs = root.getElementsByTagName(CODENAVIGATOR);
933         boolean update = false;
934         for (int i = 0; i < navs.getLength(); i++) {
935             Element nav = (Element) navs.item(i);
936             if (nav.getAttribute("uuid").equals(navUUID)) {
937                 nav.setAttribute("depends", editorUUID);
938                 update = true;
939                 break;
940             }
941         }
942
943         if (!update) {
944             ScilabXMLUtilities.createNode(document, root, CODENAVIGATOR, new String[] {"uuid", navUUID, "depends", editorUUID});
945         }
946
947         writeDocument();
948     }
949
950     /**
951      *
952      */
953     public static String getCodeNavigatorState(String navUUID) {
954         readDocument();
955
956         Element root = document.getDocumentElement();
957         NodeList navs = root.getElementsByTagName(CODENAVIGATOR);
958         for (int i = 0; i < navs.getLength(); i++) {
959             Element nav = (Element) navs.item(i);
960             if (nav.getAttribute("uuid").equals(navUUID)) {
961                 return nav.getAttribute("depends");
962             }
963         }
964         return null;
965     }
966
967     /**
968      *
969      */
970     public static String getCodeNavigatorStateForEditor(String editorUUID) {
971         readDocument();
972
973         Element root = document.getDocumentElement();
974         NodeList navs = root.getElementsByTagName(CODENAVIGATOR);
975         for (int i = 0; i < navs.getLength(); i++) {
976             Element nav = (Element) navs.item(i);
977             if (nav.getAttribute("depends").equals(editorUUID)) {
978                 return nav.getAttribute("uuid");
979             }
980         }
981         return null;
982     }
983
984     /**
985      *
986      */
987     public static void saveSearchInFilesState(String editorUUID, String sfUUID) {
988         readDocument();
989
990         Element root = document.getDocumentElement();
991         NodeList sfs = root.getElementsByTagName(SEARCHINFILES);
992         boolean update = false;
993         for (int i = 0; i < sfs.getLength(); i++) {
994             Element sf = (Element) sfs.item(i);
995             if (sf.getAttribute("uuid").equals(sfUUID)) {
996                 sf.setAttribute("depends", editorUUID);
997                 update = true;
998                 break;
999             }
1000         }
1001
1002         if (!update) {
1003             ScilabXMLUtilities.createNode(document, root, SEARCHINFILES, new String[] {"uuid", sfUUID, "depends", editorUUID});
1004         }
1005
1006         writeDocument();
1007     }
1008
1009     /**
1010      *
1011      */
1012     public static String getSearchInFilesState(String sfUUID) {
1013         readDocument();
1014
1015         Element root = document.getDocumentElement();
1016         NodeList sfs = root.getElementsByTagName(SEARCHINFILES);
1017         for (int i = 0; i < sfs.getLength(); i++) {
1018             Element sf = (Element) sfs.item(i);
1019             if (sf.getAttribute("uuid").equals(sfUUID)) {
1020                 return sf.getAttribute("depends");
1021             }
1022         }
1023         return null;
1024     }
1025
1026     /**
1027      *
1028      */
1029     public static String getSearchInFilesStateForEditor(String editorUUID) {
1030         readDocument();
1031
1032         Element root = document.getDocumentElement();
1033         NodeList sfs = root.getElementsByTagName(SEARCHINFILES);
1034         for (int i = 0; i < sfs.getLength(); i++) {
1035             Element sf = (Element) sfs.item(i);
1036             if (sf.getAttribute("depends").equals(editorUUID)) {
1037                 return sf.getAttribute("uuid");
1038             }
1039         }
1040         return null;
1041     }
1042
1043     /**
1044      *
1045      */
1046     public static void saveEditorUUID(String editorUUID) {
1047         readDocument();
1048
1049         Element root = document.getDocumentElement();
1050         NodeList eis = root.getElementsByTagName(EDITORUUID);
1051         for (int i = 0; i < eis.getLength(); i++) {
1052             Element ei = (Element) eis.item(i);
1053             if (ei.getAttribute("uuid").equals(editorUUID)) {
1054                 return;
1055             }
1056         }
1057
1058         ScilabXMLUtilities.createNode(document, root, EDITORUUID, new String[] {"uuid", editorUUID});
1059
1060         writeDocument();
1061     }
1062
1063     /**
1064      *
1065      */
1066     public static void removeEditorUUID(String editorUUID) {
1067         readDocument();
1068
1069         Element root = document.getDocumentElement();
1070         NodeList eis = root.getElementsByTagName(EDITORUUID);
1071         for (int i = 0; i < eis.getLength(); i++) {
1072             Element ei = (Element) eis.item(i);
1073             if (ei.getAttribute("uuid").equals(editorUUID)) {
1074                 root.removeChild(ei);
1075             }
1076         }
1077
1078         root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0);
1079         if (root != null) {
1080             NodeList openFiles = root.getElementsByTagName(DOCUMENT);
1081             for (int i = 0; i < openFiles.getLength(); ++i) {
1082                 Element of = (Element) openFiles.item(i);
1083                 if (of.getAttribute(EDITORINST).equals(editorUUID)) {
1084                     root.removeChild(of);
1085                 }
1086             }
1087         }
1088
1089         writeDocument();
1090     }
1091
1092     /**
1093      *
1094      */
1095     public static List<String> getEditorsUUID() {
1096         readDocument();
1097
1098         Element root = document.getDocumentElement();
1099         NodeList eis = root.getElementsByTagName(EDITORUUID);
1100         List<String> list = new ArrayList<String>();
1101         for (int i = 0; i < eis.getLength(); i++) {
1102             Element ei = (Element) eis.item(i);
1103             list.add(ei.getAttribute("uuid"));
1104         }
1105
1106         return list;
1107     }
1108
1109     /**
1110      * Add a file to recent Opened Files
1111      * @param exp the path of the files to add
1112      */
1113     public static void saveRecentSearch(String exp) {
1114         Node root = getXcosRoot();
1115         if (root == null || exp == null || exp.compareTo("") == 0) {
1116             return;
1117         }
1118
1119         Node recents = getNodeChild(root, RECENT_SEARCH);
1120         if (recents == null) {
1121             recents = document.createElement(RECENT_SEARCH);
1122             root.appendChild(recents);
1123         }
1124
1125         List<Node> search = getNodeChildren(recents, SEARCH);
1126
1127         while (search.size() >= MAXRECENT) {
1128             removeRecentSearch(((Element) search.get(0)).getAttribute(EXPRESSION));
1129             search = getNodeChildren(recents, SEARCH);
1130         }
1131         //if path already in file no need to add it
1132         for (Node item : search) {
1133             if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) {
1134                 return;
1135             }
1136         }
1137
1138         Element newSearch = document.createElement(SEARCH);
1139         newSearch.setAttribute(EXPRESSION, exp);
1140         recents.appendChild((Node) newSearch);
1141
1142         clean(recents);
1143         writeDocument();
1144     }
1145
1146     /**
1147      * @param exp the expression to remove
1148      */
1149     public static void removeRecentSearch(String exp) {
1150         Node root = getXcosRoot();
1151         if (root == null) {
1152             return;
1153         }
1154
1155         Node recent = getNodeChild(root, RECENT_SEARCH);
1156         List<Node> search = getNodeChildren(recent, SEARCH);
1157
1158         // remove node if exists
1159         for (Node file : search) {
1160             if (exp.compareTo(((Element) file).getAttribute(EXPRESSION)) == 0) {
1161                 recent.removeChild(file);
1162                 break;
1163             }
1164         }
1165
1166         clean(recent);
1167         writeDocument();
1168
1169     }
1170
1171     /**
1172      * @return a list of the recent searches
1173      */
1174     public static List<String> getRecentSearch() {
1175         List<String> files = new ArrayList<String>();
1176
1177         Node root = getXcosRoot();
1178         if (root == null) {
1179             return files;
1180         }
1181
1182         Node recent = getNodeChild(root, RECENT_SEARCH);
1183         List<Node> searches = getNodeChildren(recent, SEARCH);
1184         for (Node search : searches) {
1185             String exp = ((Element) search).getAttribute(EXPRESSION);
1186             if (exp != null && exp.compareTo("") != 0) {
1187                 files.add(exp);
1188             }
1189         }
1190
1191         return files;
1192     }
1193
1194     /**
1195      * Add a file to recent Opened Files
1196      * @param exp the path of the files to add
1197      */
1198     public static void saveRecent(String exp, String nodeName, String childNodeName) {
1199         Node root = getXcosRoot();
1200         if (root == null || exp == null || exp.compareTo("") == 0) {
1201             return;
1202         }
1203
1204         Node recents = getNodeChild(root, nodeName);
1205         if (recents == null) {
1206             recents = document.createElement(nodeName);
1207             root.appendChild(recents);
1208         }
1209
1210         List<Node> list = getNodeChildren(recents, childNodeName);
1211
1212         while (list.size() >= MAXRECENT) {
1213             removeRecent(((Element) list.get(0)).getAttribute(EXPRESSION), nodeName, childNodeName);
1214             list = getNodeChildren(recents, childNodeName);
1215         }
1216         //if path already in file no need to add it
1217         for (Node item : list) {
1218             if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) {
1219                 return;
1220             }
1221         }
1222
1223         Element newNode = document.createElement(childNodeName);
1224         newNode.setAttribute(EXPRESSION, exp);
1225         recents.appendChild((Node) newNode);
1226
1227         clean(recents);
1228         writeDocument();
1229     }
1230
1231     /**
1232      * @param exp the expression to remove
1233      */
1234     public static void removeRecent(String exp, String nodeName, String childNodeName) {
1235         Node root = getXcosRoot();
1236         if (root == null) {
1237             return;
1238         }
1239
1240         Node recent = getNodeChild(root, nodeName);
1241         List<Node> list = getNodeChildren(recent, childNodeName);
1242
1243         // remove node if exists
1244         for (Node item : list) {
1245             if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) {
1246                 recent.removeChild(item);
1247                 break;
1248             }
1249         }
1250
1251         clean(recent);
1252         writeDocument();
1253     }
1254
1255     /**
1256      * @return a list of the recent searches
1257      */
1258     public static List<String> getRecent(String nodeName, String childNodeName) {
1259         List<String> files = new ArrayList<String>();
1260
1261         Node root = getXcosRoot();
1262         if (root == null) {
1263             return files;
1264         }
1265
1266         Node recent = getNodeChild(root, nodeName);
1267         List<Node> list = getNodeChildren(recent, childNodeName);
1268         for (Node node : list) {
1269             String exp = ((Element) node).getAttribute(EXPRESSION);
1270             if (exp != null && exp.compareTo("") != 0) {
1271                 files.add(exp);
1272             }
1273         }
1274
1275         return files;
1276     }
1277
1278
1279     /**
1280      * @param exp the recent expression for a replacement
1281      */
1282     public static void saveRecentReplace(String exp) {
1283         Node root = getXcosRoot();
1284         if (root == null || exp == null || exp.compareTo("") == 0) {
1285             return;
1286         }
1287
1288         Node recent = getNodeChild(root, RECENT_REPLACE);
1289         if (recent == null) {
1290             recent = document.createElement(RECENT_REPLACE);
1291             root.appendChild(recent);
1292         }
1293
1294         List<Node> replace = getNodeChildren(recent, REPLACE);
1295
1296         while (replace.size() >= MAXRECENT) {
1297             removeRecentReplace(((Element) replace.get(0)).getAttribute(EXPRESSION));
1298             replace = getNodeChildren(recent, REPLACE);
1299         }
1300         //if path already in file no need to add it
1301         for (Node item : replace) {
1302             if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) {
1303                 return;
1304             }
1305         }
1306
1307         Element newReplace = document.createElement(REPLACE);
1308         newReplace.setAttribute(EXPRESSION, exp);
1309         recent.appendChild((Node) newReplace);
1310
1311         clean(recent);
1312         writeDocument();
1313     }
1314
1315     /**
1316      * @param filePath remove recent replace in the this file
1317      */
1318     public static void removeRecentReplace(String filePath) {
1319
1320         Node root = getXcosRoot();
1321         if (root == null) {
1322             return;
1323         }
1324
1325         Node recent = getNodeChild(root, RECENT_REPLACE);
1326         List<Node> replace = getNodeChildren(recent, REPLACE);
1327
1328         // remove node if exists
1329         for (Node exp : replace) {
1330             if (filePath.compareTo(((Element) exp).getAttribute(EXPRESSION)) == 0) {
1331                 recent.removeChild(exp);
1332                 break;
1333             }
1334
1335         }
1336
1337         clean(recent);
1338         writeDocument();
1339
1340     }
1341
1342     /**
1343      * @return the recent replace
1344      */
1345     public static List<String> getRecentReplace() {
1346         List<String> exps = new ArrayList<String>();
1347
1348         Node root = getXcosRoot();
1349         if (root == null) {
1350             return exps;
1351         }
1352
1353         Node recent = getNodeChild(root, RECENT_REPLACE);
1354         List<Node> replace = getNodeChildren(recent, REPLACE);
1355         for (Node file : replace) {
1356             String exp = ((Element) file).getAttribute(EXPRESSION);
1357             if (exp != null && exp.compareTo("") != 0) {
1358                 exps.add(exp);
1359             }
1360         }
1361
1362         return exps;
1363     }
1364
1365     /**
1366      * @return true for a regexp search
1367      */
1368     public static boolean getRegularExpression() {
1369         return getBooleanAttribute(REGULAR_EXPRESION, STATE_FLAG, false);
1370     }
1371
1372     /**
1373      * @param regualExp for a regexp search
1374      */
1375     public static void saveRegularExpression(boolean regualExp) {
1376         saveBooleanAttribute(REGULAR_EXPRESION, STATE_FLAG, regualExp);
1377     }
1378
1379     /**
1380      * @return true for a wholeWord search
1381      */
1382     public static boolean getWholeWord() {
1383         return getBooleanAttribute(WHOLE_WORD, STATE_FLAG, false);
1384     }
1385
1386     /**
1387      * @param wholeWord for a wholeWord search
1388      */
1389     public static void saveWholeWord(boolean wholeWord) {
1390         saveBooleanAttribute(WHOLE_WORD, STATE_FLAG, wholeWord);
1391     }
1392
1393     /**
1394      * @return true for a recursive search
1395      */
1396     public static boolean getRecursive() {
1397         return getBooleanAttribute(RECURSIVE, STATE_FLAG, true);
1398     }
1399
1400     /**
1401      * @param recursive for a recursive search
1402      */
1403     public static void saveRecursive(boolean recursive) {
1404         saveBooleanAttribute(RECURSIVE, STATE_FLAG, recursive);
1405     }
1406
1407     /**
1408      * @return true for a line by line search
1409      */
1410     public static boolean getLineByLine() {
1411         return getBooleanAttribute(LINEBYLINE, STATE_FLAG, true);
1412     }
1413
1414     /**
1415      * @param lineByLine for a line by line search
1416      */
1417     public static void saveLineByLine(boolean lineByLine) {
1418         saveBooleanAttribute(LINEBYLINE, STATE_FLAG, lineByLine);
1419     }
1420
1421     /**
1422      * @return true for a case sensitive file name
1423      */
1424     public static boolean getFileCase() {
1425         return getBooleanAttribute(FILECASE, STATE_FLAG, false);
1426     }
1427
1428     /**
1429      * @param fileCase for a case sensitive file name
1430      */
1431     public static void saveFileCase(boolean fileCase) {
1432         saveBooleanAttribute(FILECASE, STATE_FLAG, fileCase);
1433     }
1434
1435     /**
1436      * @return true for a circular search
1437      */
1438     public static boolean getCircularSearch() {
1439         return getBooleanAttribute(CIRCULAR, STATE_FLAG, true);
1440     }
1441
1442     /**
1443      * @param circular is true for a circular search
1444      */
1445     public static void saveCircularSearch(boolean circular) {
1446         saveBooleanAttribute(CIRCULAR, STATE_FLAG, circular);
1447     }
1448
1449     /**
1450      * @return true for a case sensitive search
1451      */
1452     public static boolean getCaseSensitive() {
1453         return getBooleanAttribute(CASE_SENSITIVE, STATE_FLAG, false);
1454     }
1455
1456     /**
1457      * @param caseSensitive for a case sensitive search
1458      */
1459     public static void saveCaseSensitive(boolean caseSensitive) {
1460         saveBooleanAttribute(CASE_SENSITIVE, STATE_FLAG, caseSensitive);
1461     }
1462
1463     /**
1464      * getBooleanAttribute
1465      * @param node the node name
1466      * @param attrib the attribute of the node
1467      * @param defaultValue true or false
1468      * @return the found boolean value or defaultValue if not found
1469      */
1470     private static boolean getBooleanAttribute(String node, String attrib, boolean defaultValue) {
1471         boolean flag = false;
1472         Node root = getXcosRoot();
1473         if (root == null) {
1474             return flag;
1475         }
1476         Node recent = getNodeChild(root, node);
1477         if (recent != null) {
1478             String exp = ((Element) recent).getAttribute(attrib);
1479             if (exp.compareTo(TRUE) == 0) {
1480                 flag = true;
1481             }
1482         } else {
1483             return defaultValue;
1484         }
1485         return flag;
1486     }
1487
1488     /**
1489      * saveBooleanAttribute
1490      * @param node the node name
1491      * @param attrib the attribute of the node
1492      * @param state "true" or "false"
1493      */
1494     private static void saveBooleanAttribute(String node, String attrib, boolean state) {
1495         Node root = getXcosRoot();
1496         if (root == null) {
1497             return;
1498         }
1499
1500         Node recent = getNodeChild(root, node);
1501         if (recent == null) {
1502             recent = document.createElement(node);
1503             root.appendChild(recent);
1504         }
1505
1506
1507         ((Element) recent).setAttribute(attrib, new Boolean(state).toString());
1508
1509         root.appendChild(recent);
1510
1511         /* Save changes */
1512         writeDocument();
1513     }
1514
1515     /**
1516      * getNodeChild
1517      * @param par parent
1518      * @param nodeName the name
1519      * @return the node
1520      */
1521     private static Node getNodeChild(Node par, String nodeName) {
1522         Node parent = par;
1523         if (parent == null) {
1524             if (document == null) {
1525                 readDocument();
1526                 if (document == null) {
1527                     return null;
1528                 }
1529             }
1530             parent = document;
1531         }
1532
1533         Node currentNode = parent.getFirstChild();
1534         while (currentNode != null) {
1535             if (currentNode.getNodeName().compareTo(nodeName) == 0) {
1536                 return currentNode;
1537             }
1538             currentNode = currentNode.getNextSibling();
1539         }
1540         return currentNode;
1541     }
1542
1543     /**
1544      * getNodeChildren
1545      * @param par parent
1546      * @param childName the name
1547      * @return a list of nodes
1548      */
1549     private static List<Node> getNodeChildren(Node par, String childName) {
1550         Node parent = par;
1551         List<Node> nodes = new ArrayList<Node>();
1552         if (parent == null) {
1553             if (document == null) {
1554                 readDocument();
1555                 if (document == null) {
1556                     return nodes;
1557                 }
1558             }
1559             parent = document;
1560         }
1561
1562         Node currentNode = parent.getFirstChild();
1563         while (currentNode != null) {
1564             if (currentNode.getNodeName().compareTo(childName) == 0) {
1565                 nodes.add(currentNode);
1566             }
1567             currentNode = currentNode.getNextSibling();
1568         }
1569         return nodes;
1570
1571     }
1572
1573     /**
1574      * @return the root
1575      */
1576     private static Node getXcosRoot() {
1577         if (document == null) {
1578             readDocument();
1579             if (document == null) {
1580                 return null;
1581             }
1582         }
1583
1584         Node setting = getNodeChild(null, SETTING);
1585
1586         if (setting != null) {
1587             List<Node> nodes = getNodeChildren(setting, PROFILE);
1588             for (Node node : nodes) {
1589                 if (((Element) node).getAttribute(NAME).compareTo(SCINOTES) == 0) {
1590                     return node;
1591                 }
1592             }
1593         }
1594         return null;
1595     }
1596
1597     /**
1598      * Remove text at the beginning and at the end
1599      * @param r the element to clean
1600      */
1601     private static void clean(Node r) {
1602         Node n = r.getFirstChild();
1603         if (n != null && n instanceof Text) {
1604             r.removeChild(n);
1605         }
1606         n = r.getLastChild();
1607         if (n != null && n instanceof Text) {
1608             r.removeChild(n);
1609         }
1610     }
1611 }