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