auto-indent with bugs
[scilab.git] / scilab / modules / xpad / src / java / org / scilab / modules / xpad / style / ScilabStyleDocument.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.xpad.style;
14
15 import java.awt.Color;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Hashtable;
19 import java.util.Vector;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 import javax.swing.SwingUtilities;
24 import javax.swing.event.DocumentEvent;
25 import javax.swing.event.DocumentListener;
26 import javax.swing.event.UndoableEditEvent;
27 import javax.swing.text.BadLocationException;
28 import javax.swing.text.DefaultStyledDocument;
29 import javax.swing.text.Document;
30 import javax.swing.text.Element;
31 import javax.swing.text.Style;
32 import javax.swing.text.StyleConstants;
33 import javax.swing.undo.UndoManager;
34
35 import org.scilab.modules.xpad.ScilabKeywords;
36 import org.scilab.modules.xpad.Xpad;
37 import org.scilab.modules.xpad.actions.ColorizeAction;
38 import org.scilab.modules.xpad.actions.IndentAction;
39 import org.scilab.modules.xpad.utils.ConfigXpadManager;
40
41 public class ScilabStyleDocument extends DefaultStyledDocument implements DocumentListener {
42
43         private UndoManager undo = new UndoManager() {
44                 public void undoableEditHappened(UndoableEditEvent e) {
45                                         
46                         if ( (EventType.equals(DocumentEvent.EventType.INSERT.toString()) || EventType.equals(DocumentEvent.EventType.REMOVE.toString()) ) && (e.getEdit().canUndo()) ){
47                                 /*
48                                 if ( EventType.equals(DocumentEvent.EventType.REMOVE.toString())){
49                                         System.out.println("remove");
50                                         System.out.println(indentInprogress) ;
51                                 }
52                                 */
53                                 if (!indentInprogress){ 
54                                 undo.addEdit(e.getEdit());
55                                 
56                                 EventType = "" ;
57                                 }
58                         }
59
60                                         
61                 }
62         };
63
64         private boolean autoIndent = true;
65         private boolean autoColorize = true;
66         private boolean colorizeInprogress = false;
67         private boolean indentInprogress = false;
68         private boolean updaterDisabled = false;
69
70         private String EventType ;
71         
72         //private final String[] quotations = {"[^A-Z](\"|')[^{\n}]*?(\"|')"};
73         private final String[] quotations = {"(\"|')[^{\n}]*?(\"|')"};
74         private final String[] bools = {"%T", "%F", "%t", "%f"};
75         private final String[] comments = {"//[^{\n}]*", "/\\*.*?\\*/"};
76         private final String[] operators = {"=", "\\+", "-", "\\*", "/", "\\\\", "\\^", 
77                         "\\./", "\\.\\\\", "\\.\\^", 
78                         "\\.\\*\\.", "\\./\\.", "\\.\\\\\\.",
79                         "==", "<", ">", "<=", ">=", "~=", "@=",
80                         "&", "\\|", "@", "~",
81         "\\.\\.[\\.]*"};
82
83         private final String IN = "IN";
84         private final String OUT = "OUT";
85         private final String TABULATION = "  ";
86         private final int BOOLS = 0;
87         private final int COMMANDS = 1;
88         private final int COMMENTS = 2;
89         private final int FUNCTIONS = 3;
90         private final int MACROS = 4;
91         private final int OPERATORS = 5;
92         private final int QUOTATIONS = 6;
93         
94         private int lineStartPosition;
95         private int lineEndPosition;
96         private boolean singleLine = false;
97         private int currentLine;
98         
99         private boolean contentModified ;
100         
101         //private XpadStyles xpadStyles ; 
102         
103         Hashtable<String, String[]> keywords;
104         String[] commands;
105         String[] functions;
106         String[] macros;
107         
108         Xpad editor;
109
110         /*if you want to add a new style just add it in the xml*/
111         private ArrayList<String> listStylesName ;
112         //private final String[] allStyles = {"Operator", "Command","String","Bool" ,"Comment"} ;
113         private Style defaultStyle;
114
115
116         public ScilabStyleDocument(Xpad editor) {
117                 super();
118                 EventType = new String();
119                 
120                 this.editor = editor ;
121                 Hashtable< String, Color>stylesColorsTable =  ConfigXpadManager.getAllForegroundColors();
122                 Hashtable< String, Boolean>stylesIsBoldTable = ConfigXpadManager.getAllisBold()  ;
123                 listStylesName  =  ConfigXpadManager.getAllStyleName();
124
125                 //xpadStyles = XpadStyles.getInstance() ;
126                 addDocumentListener(this);
127                 addUndoableEditListener(undo);
128                 defaultStyle = this.addStyle("Default", null);
129                 StyleConstants.setBold(defaultStyle, stylesIsBoldTable.get("Default"));
130                 StyleConstants.setFontFamily(defaultStyle, ConfigXpadManager.getFont().getFontName() );
131                 StyleConstants.setForeground(defaultStyle, stylesColorsTable.get("Default"));
132                 StyleConstants.setFontSize(defaultStyle, ConfigXpadManager.getFontSize());
133                 StyleConstants.setLeftIndent(defaultStyle, 0);
134
135                 /* set default style settings*/
136                 /*that way if we want to had a new style, we just need to had an element to the xml*/
137                 for(int i = 0 ; i < listStylesName.size() ; ++i) {
138                         Style otherStyle = this.addStyle(listStylesName.get(i), defaultStyle);
139                         StyleConstants.setBold(otherStyle, stylesIsBoldTable.get(listStylesName.get(i)));
140                         StyleConstants.setForeground(otherStyle, stylesColorsTable.get(listStylesName.get(i)));
141                 }
142                 
143                 loadingsForColorisation();
144                 setContentModified(false );
145                 
146                 this.addDocumentListener( new DocumentListener(){
147                         
148                          public void changedUpdate(DocumentEvent documentEvent) {
149
150                               }
151                               public void insertUpdate(DocumentEvent documentEvent) {
152                                 handleEvent(documentEvent);
153                               }
154                               public void removeUpdate(DocumentEvent documentEvent) {
155                                   handleEvent(documentEvent);
156                               }
157                               private void handleEvent(DocumentEvent documentEvent) {
158                                 DocumentEvent.EventType type = documentEvent.getType();
159                                 if (type.equals(DocumentEvent.EventType.INSERT) || type.equals(DocumentEvent.EventType.REMOVE) ) {
160                                  
161                                         int index = getEditor().getTabPane().getSelectedIndex();
162                                         if ( ! isContentModified()){
163                                                 getEditor().getTabPane().setTitleAt( index  , "*" + getEditor().getTabPane().getTitleAt(index ) );
164                                         }
165                                         setContentModified(true);
166                                 }  
167
168                               }
169                 });
170                 
171         }
172
173
174         
175         /**
176          * DOCUMENT COLORISATION START
177          */
178         
179         public void loadingsForColorisation() {
180                 // Scilab keywords to be colored
181                 keywords = getScilabKeywords();         
182                 commands = (String[])keywords.get("command");
183                 functions = (String[])keywords.get("function");
184                 macros = (String[])keywords.get("macro");
185
186                 // Regexp for Scilab keywords  (for commands, functions & macros) 
187                 for (int i = 0; i < commands.length; i++) {
188                         commands[i] = "\\b" + commands[i] + "\\b"; 
189                 }       
190                 for (int i = 0; i < functions.length; i++) {
191                         functions[i] = "\\b" + functions[i] + "\\b"; 
192                 }       
193                 for (int i = 0; i < macros.length; i++) {
194                         macros[i] = "\\b" + macros[i] + "\\b"; 
195                 }
196         }
197         
198         public void colorize() {
199                 
200                 singleLine = false;
201                 
202                 // We parse all words which are susceptible to be colored
203                 Vector<Vector<Integer>> boundaries_list = parse(bools, commands, comments, functions, macros, operators, quotations, singleLine, 0, 0);
204
205                 if (!colorizeInprogress) {
206                         colorizeInprogress = true;
207                         this.removeUndoableEditListener(undo);
208                         this.addUndoableEditListener(null);
209                         resetStyle();
210                         try {
211                                 applyStyle(boundaries_list.elementAt(BOOLS), getStyle("Bool"));
212                                 applyStyle(boundaries_list.get(COMMANDS), getStyle("Command"));
213                                 applyStyle(boundaries_list.get(FUNCTIONS), getStyle("Function"));
214                                 applyStyle(boundaries_list.get(MACROS), getStyle("Macro"));
215                                 applyStyle(boundaries_list.get(OPERATORS), getStyle("Operator"));
216                                 applyStyle(boundaries_list.get(QUOTATIONS), getStyle("String"));
217                                 applyStyle(boundaries_list.get(COMMENTS), getStyle("Comment"));
218                         } catch (BadLocationException e) {
219                                 e.printStackTrace();
220                         }
221                         finally {
222                                 this.addUndoableEditListener(undo);
223                                 colorizeInprogress = false;
224                         }
225                 }
226         }
227
228         
229         public void colorizeSingleLine(int lineStartPosition, int lineEndPosition) {
230
231                 singleLine = true;
232
233                 // We parse all words which are susceptible to be colored
234                 Vector<Vector<Integer>> boundaries_list = parse(bools, commands, comments, functions, macros, operators, quotations, singleLine, lineStartPosition, lineEndPosition);
235
236                 if (!colorizeInprogress) {
237                         colorizeInprogress = true;
238                         this.removeUndoableEditListener(undo);
239                         this.addUndoableEditListener(null);
240                         resetSingleLineStyle(lineStartPosition, lineEndPosition);
241                         try {
242                                 applyStyleToSingleLine(boundaries_list.elementAt(BOOLS), getStyle("Bool"), lineStartPosition, lineEndPosition);
243                                 applyStyleToSingleLine(boundaries_list.get(COMMANDS), getStyle("Command"), lineStartPosition, lineEndPosition);
244                                 applyStyleToSingleLine(boundaries_list.get(FUNCTIONS), getStyle("Function"), lineStartPosition, lineEndPosition);
245                                 applyStyleToSingleLine(boundaries_list.get(MACROS), getStyle("Macro"), lineStartPosition, lineEndPosition);
246                                 applyStyleToSingleLine(boundaries_list.get(OPERATORS), getStyle("Operator"), lineStartPosition, lineEndPosition);
247                                 applyStyleToSingleLine(boundaries_list.get(QUOTATIONS), getStyle("String"), lineStartPosition, lineEndPosition);
248                                 applyStyleToSingleLine(boundaries_list.get(COMMENTS), getStyle("Comment"), lineStartPosition, lineEndPosition);
249                         } catch (BadLocationException e) {
250                                 e.printStackTrace();
251                         }
252                         finally {
253                                 this.addUndoableEditListener(undo);
254                                 colorizeInprogress = false;
255                         }
256                 }
257         }
258         /*
259         public Style getStyle(String styleName ){
260                 Style plop =  xpadStyles.getStyle(styleName);
261                 
262                 return plop ;
263         }
264         */
265         private void resetStyle() {
266                 // Reset Color
267                 this.removeUndoableEditListener(undo);
268                 this.setCharacterAttributes(0, this.getLength(), this.getStyle("Default"), true);
269                 this.setParagraphAttributes(0, this.getLength(), this.getStyle("Default"), true);
270                 this.addUndoableEditListener(undo);
271         }
272         
273         private void resetSingleLineStyle(int line_start, int line_end) {
274                 // Reset Color
275                 this.removeUndoableEditListener(undo);
276                 this.setCharacterAttributes(line_start, line_end-line_start, this.getStyle("Default"), true);
277                 this.setParagraphAttributes(line_start, line_end-line_start, this.getStyle("Default"), true);
278                 this.addUndoableEditListener(undo);
279         }
280
281         
282         private void applyStyle(Vector<Integer> boundaries, Style style) throws BadLocationException {
283                 for(int i = 0 ; i < boundaries.size() ; i=i+2)  {
284                         this.setCharacterAttributes(boundaries.elementAt(i), boundaries.elementAt(i+1)-boundaries.elementAt(i), style, false);
285                         this.setParagraphAttributes(boundaries.elementAt(i), boundaries.elementAt(i+1)-boundaries.elementAt(i), style, false);
286                 }
287         }
288         
289         private void applyStyleToSingleLine(Vector<Integer> boundaries, Style style, int start, int end) throws BadLocationException {
290                 for(int i = 0 ; i < boundaries.size() ; i=i+2)  {
291                         this.setCharacterAttributes(boundaries.elementAt(i), boundaries.elementAt(i+1)-boundaries.elementAt(i), style, false);
292                         this.setParagraphAttributes(boundaries.elementAt(i), boundaries.elementAt(i+1)-boundaries.elementAt(i), style, false);
293                 }
294         }
295
296         public boolean getColorize() {
297                 //DEBUG("setColorize("+autoColorize+")");
298                 return autoColorize;
299         }
300
301         public void setColorize(boolean b) {
302                 //DEBUG("setColorize("+b+")");
303                 autoColorize = b;
304         }
305         /**
306          * DOCUMENT COLORISATION END
307          */
308
309
310         /**
311          * DOCUMENT INDENTATION START
312          */
313         public void indent() {
314                 if (!indentInprogress) {
315                         disableUpdaters();
316                         indentInprogress = true;
317                         resetStyle();
318                         
319                         applySelectionIndent();
320                         
321                         colorize();
322                         indentInprogress = false;
323                         enableUpdaters();
324                 }
325         }
326
327         
328         
329         
330         
331         
332         
333         
334         
335         
336         public void applyAutoIndent(int start, int end, String previous_tab) throws BadLocationException {
337
338                 String indentedText = "";
339                 boolean got_case = false;
340
341                 String text_to_indent = ""; // the entire document
342                 Vector<String> command_list = new Vector<String>(); // list of commands in the document
343
344                 try {
345                         // Get the document text to indent
346                         text_to_indent = this.getText(start, end-start);
347                         System.out.println("{"+text_to_indent+"}");
348                 } catch (BadLocationException e) {
349                         e.printStackTrace();
350                 }
351
352                 // Get all line break positions &
353                 // each line of the document
354                 Vector<Integer> line_break = new Vector<Integer>(); // positions of line break
355                 Vector<String> all_lines = new Vector<String>(); // the document line by line
356                 String line = "";
357                 for (int i = 0; i < text_to_indent.length(); i++) {
358                         line = line.concat(text_to_indent.charAt(i)+"");
359
360                         if (text_to_indent.charAt(i)=='\n') {
361                                 line_break.add(i);
362                                 all_lines.add(line);
363                                 line = "";
364                         }
365                         if (i==text_to_indent.length()-1) {
366                                 all_lines.add(line);
367                                 line = "";
368                         }
369                 }
370
371                 Vector<String> all_lines_without_spaces = new Vector<String>(); // the document line by line
372                 // without spaces
373                 for (int i = 0; i < all_lines.size(); i++) {
374                         String no_space_line = removeFirstSpaces(all_lines.elementAt(i));
375                         all_lines_without_spaces.add(no_space_line);
376                 }
377
378                 boolean got_select = false;
379                 int indent_level = 0;
380
381                 for (int i = 0; i < all_lines_without_spaces.size(); i++) {
382                         
383                         // Get commands for each lines
384                         command_list = getOperatorList(all_lines_without_spaces.elementAt(i));
385
386                         // Check if in one line all operators are matching,
387                         // so we can know if the next line needs indentation or not
388                         // ex: if %T then function foo(1) endfunction end => doesn't need indentation
389                         // Warning: vector_match looks like [IN, if, IN function, OUT, endfunction, OUT, end]
390                         Vector<String> vector_match = matchingOperators(command_list);
391
392
393                         indentedText += previous_tab;
394
395                         // Here start the indentation process
396                         if (vector_match.size() > 0) {
397
398                                 // If we have 'IN' command
399                                 if (vector_match.elementAt(0).equals(IN)) {
400                                         
401                                         if ((vector_match.elementAt(1).toLowerCase().equals("else")) || 
402                                                         (vector_match.elementAt(1).toLowerCase().equals("elseif"))) {
403                                                 
404                                                 if (autoIndent == true && all_lines_without_spaces.size() == 2) {
405                                                         indentedText = previous_tab + all_lines_without_spaces.elementAt(i);
406                                                         if (indentedText.length() >= 2) {
407                                                                 String text_tab = indentedText.substring(0, 2);
408                                                                 if (text_tab.equals("  ")) {
409                                                                         indentedText = indentedText.substring(2, indentedText.length());
410                                                                 }
411                                                         }
412                                                         indentedText += previous_tab;
413                                                         break;
414                                                 }
415                                                 
416                                         } else if (vector_match.elementAt(1).toLowerCase().equals("select")) {
417                                                 
418                                                 got_select = true;
419                                                 
420                                                 if (autoIndent == true && all_lines_without_spaces.size() == 2) {
421                                                         indentedText = previous_tab + all_lines_without_spaces.elementAt(i);
422                                                         indentedText += previous_tab + TABULATION;
423                                                         break;
424                                                 }
425
426                                                 // If we have 'case' command, case needs 'select' to be correct
427                                         } else if ((vector_match.elementAt(1).toLowerCase().equals("case"))) {
428                                                 
429                                                 if (autoIndent == true && all_lines_without_spaces.size() == 2) {
430                                                         
431                                                         String tmp_cas_tab = "";
432                                                         tmp_cas_tab = getLineTabulations(indentedText);
433                                                         
434                                                         if (tmp_cas_tab.length() == 2) {
435                                                                 System.out.println("222222222222222");
436                                                         } else {
437                                                                 System.out.println(tmp_cas_tab.length());
438                                                         }
439                                                         
440                                                         
441                                                         
442                                                         if (previous_tab.length() == 2) {
443                                                                 indentedText += all_lines_without_spaces.elementAt(i);
444                                                                 indentedText += previous_tab + TABULATION;
445                                                         } else if (previous_tab.length() >= 2) {
446                                                                 String tmp_tab = previous_tab.substring(0, 2);
447                                                                 if (tmp_tab.equals("  ")) {
448                                                                         indentedText = previous_tab.substring(2, previous_tab.length());
449                                                                         indentedText += all_lines_without_spaces.elementAt(i);
450                                                                         indentedText += previous_tab.substring(2, previous_tab.length()) + TABULATION;
451                                                                 }
452                                                         }
453                                                         
454 //                                                      String case_tab = "";
455 //                                                      if (previous_tab.length() > 2) {
456 //                                                              case_tab = TABULATION;
457 //                                                      } else {
458 //                                                              case_tab = "";
459 //                                                      }
460 //                                                      
461 //                                                      indentedText += case_tab + all_lines_without_spaces.elementAt(i);
462 //                                                      indentedText += previous_tab + TABULATION;
463                                                         break;
464                                                 }
465                                                 
466                                         } else {
467                                                 
468                                                 if (autoIndent == true && all_lines_without_spaces.size() == 2) {
469                                                         indentedText = previous_tab + all_lines_without_spaces.elementAt(i);
470                                                         indentedText += previous_tab + TABULATION;
471                                                         break;
472                                                 }
473                                         }
474
475                                         // If we have "OUT' operator
476                                 } else if (vector_match.elementAt(0).equals(OUT)) {
477                                         
478                                         if (autoIndent == true && all_lines_without_spaces.size() == 2) {
479                                                 
480                                                 if (previous_tab.length() >= 2 && got_select == false) {
481                                                         String tmp_tab = previous_tab.substring(0, 2);
482                                                         if (tmp_tab.equals("  ")) {
483                                                                 indentedText = previous_tab.substring(2, previous_tab.length());
484                                                                 indentedText += all_lines_without_spaces.elementAt(i);
485                                                                 indentedText += previous_tab.substring(2, previous_tab.length());
486                                                         }
487                                                 }
488                                                 break;
489                                         }
490                                 } 
491                         } else {
492                                 
493                                 if (autoIndent == true && all_lines_without_spaces.size() == 2) {
494                                         indentedText = previous_tab + all_lines_without_spaces.elementAt(i);
495                                         indentedText += previous_tab;
496                                         break;
497                                 }
498                         }
499                         vector_match.clear();
500
501                 } // end for
502
503                 // Display the indentation
504                 this.replace(start, end-start, indentedText, null);
505
506         }
507         
508         
509         
510         
511         
512         
513         
514         
515         
516         
517         
518         
519         
520         
521         
522         
523         
524         
525         
526         
527         
528         
529         
530         
531         
532         public void applyIndent(int start, int end, String previous_tab, int level_one) throws BadLocationException {
533                 
534                 String indentedText = "";
535                 boolean got_case = false;
536
537                 String text_to_indent = ""; // the entire document
538                 Vector<String> command_list = new Vector<String>(); // list of commands in the document
539
540                 try {
541                         // Get the document text to indent
542                         text_to_indent = this.getText(start, end-start);
543                         System.out.println("{"+text_to_indent+"}");
544                 } catch (BadLocationException e) {
545                         e.printStackTrace();
546                 }
547
548                 // Get all line break positions &
549                 // each line of the document
550                 Vector<Integer> line_break = new Vector<Integer>(); // positions of line break
551                 Vector<String> all_lines = new Vector<String>(); // the document line by line
552                 String line = "";
553                 for (int i = 0; i < text_to_indent.length(); i++) {
554                         line = line.concat(text_to_indent.charAt(i)+"");
555
556                         if (text_to_indent.charAt(i)=='\n') {
557                                 line_break.add(i);
558                                 all_lines.add(line);
559                                 line = "";
560                         }
561                         if (i==text_to_indent.length()-1) {
562                                 all_lines.add(line);
563                                 line = "";
564                         }
565                 }
566
567                 Vector<String> all_lines_without_spaces = new Vector<String>(); // the document line by line
568                 // without spaces
569                 for (int i = 0; i < all_lines.size(); i++) {
570                         String no_space_line = removeFirstSpaces(all_lines.elementAt(i));
571                         all_lines_without_spaces.add(no_space_line);
572                 }
573
574                 boolean got_select = false;
575                 int indent_level = 0;
576                 indent_level = level_one;
577
578                 for (int i = 0; i < all_lines_without_spaces.size(); i++) {
579                         
580                         //System.out.println("indent_level["+ (i+1) +"] = " + indent_level);
581
582                         // Get commands for each lines
583                         command_list = getOperatorList(all_lines_without_spaces.elementAt(i));
584
585                         // Check if in one line all operators are matching,
586                         // so we can know if the next line needs indentation or not
587                         // ex: if %T then function foo(1) endfunction end => doesn't need indentation
588                         // Warning: vector_match looks like [IN, if, IN function, OUT, endfunction, OUT, end]
589                         Vector<String> vector_match = matchingOperators(command_list);
590
591
592                         indentedText += previous_tab;
593
594                         // Here start the indentation process
595                         if (vector_match.size() > 0) {
596
597                                 // If we have 'IN' command
598                                 if (vector_match.elementAt(0).equals(IN)) {
599                                         
600                                         for (int j = 0; j < indent_level; j++) {
601                                                 indentedText += TABULATION;
602                                         }
603
604                                         if ((vector_match.elementAt(1).toLowerCase().equals("else")) || 
605                                                         (vector_match.elementAt(1).toLowerCase().equals("elseif"))) {
606                                                 
607                                                 if (indentedText.length() >= 2) {
608                                                         String text_tab = indentedText.substring(indentedText.length()-2, indentedText.length());
609                                                         if (text_tab.equals("  ") && indent_level > 0) {
610                                                                 indentedText = indentedText.substring(0, indentedText.length()-2);
611                                                                 indent_level--;
612                                                         }
613                                                 }
614                                                 indent_level++;
615                                         
616                                         } else if (vector_match.elementAt(1).toLowerCase().equals("select")) {
617                                                 got_select = true;
618                                                 indent_level++;
619                                                 
620                                                 // If we have 'case' command, case needs 'select' to be correct
621                                         } else if ((vector_match.elementAt(1).toLowerCase().equals("case")) && 
622                                                         (got_case == false) && (got_select == true) ) {
623                                                 got_case = true;
624                                                 indent_level++;
625                                                 
626                                         } else {
627                                                 indent_level++;
628                                         }
629
630                                         indentedText += all_lines_without_spaces.elementAt(i);
631                                         
632
633                                         // If we have "OUT' operator
634                                 } else if (vector_match.elementAt(0).equals(OUT)) {
635                                         
636                                         if (indent_level > 0) {
637                                                 indent_level--;
638                                         }
639                                         
640                                         for (int j = 0; j < indent_level; j++) {
641                                                 indentedText += TABULATION;
642                                         }
643
644                                         if (got_select == true && got_case == true &&
645                                                         vector_match.elementAt(1).toLowerCase().equals("end")) {
646                                                 got_select = false;
647                                                 got_case = false;
648                                         }
649                                         
650                                         indentedText += all_lines_without_spaces.elementAt(i);
651                                 } 
652                         } else {
653                                 
654                                 for (int j = 0; j < indent_level; j++) {
655                                         indentedText += TABULATION;
656                                 }
657                                 indentedText += all_lines_without_spaces.elementAt(i);
658
659                                 if (got_case) {
660                                         if (indent_level > 0) {
661                                                 indent_level--;
662                                         }
663                                 }
664                         }
665                         vector_match.clear();
666                         
667                         //System.out.println("_______________indent_level["+ (i+1) +"] = " + indent_level);
668
669                 } // end for
670
671                 // Display the indentation
672                 this.replace(start, end-start, indentedText, null);
673
674                 // ATTENTION, ces cas ne sont pas traité: 
675                 //            - gestion des commentaire /* */
676                 //                        - analyser la ligne du document qui est modifie et non plus le document en entier pour la colorisation
677                 //                              dans le cas d'une quotation ou commentaire(/* */) analyser le document en entier
678                 
679         }
680
681         
682         public void applySelectionIndent() {
683                 
684                 editor = getEditor();
685                 String tab = "";
686                 int selection_start = 0;
687                 int selection_end = 0;
688                 int level_one = 0;
689                 
690                 // Get start & end offsets of the selected text
691                 selection_start = editor.getTextPane().getSelectionStart();
692                 selection_end = editor.getTextPane().getSelectionEnd();
693                 
694                 
695                 // Get start offsets of the first selected line & end offsets of the last selected line
696                 lineStartPosition =  this.getParagraphElement(selection_start).getStartOffset();
697                 lineEndPosition = this.getParagraphElement(selection_end).getEndOffset()-1;
698                 
699 //              System.out.println(lineStartPosition);
700 //              System.out.println(lineEndPosition);
701                 
702                 
703                 
704                 int previous_line_start = 0;
705                 int previous_line_end = 0;
706                 String previous_line;
707                 
708                 int current_line_start = 0;
709                 int current_line_end = 0;
710                 
711                 if (lineStartPosition == 0) {
712                         tab = "";
713                 } else {
714                         // Get previous line
715                         previous_line_start =  this.getParagraphElement(lineStartPosition-1).getStartOffset();
716                         previous_line_end = this.getParagraphElement(lineStartPosition-1).getEndOffset()-1;
717                         previous_line = "";
718                         
719                         current_line_start = this.getParagraphElement(selection_start).getStartOffset();
720                         current_line_end = this.getParagraphElement(selection_end).getEndOffset()-1;
721                         String current_line = "";
722                         
723                         try {
724                                 previous_line = this.getText(previous_line_start, previous_line_end-previous_line_start);
725                                 current_line = this.getText(current_line_start, current_line_end-current_line_start);
726                                 System.out.println("previous_line = "+previous_line);
727                                 
728                                 // Get previous line's tabulation
729                                 tab = getLineTabulations(previous_line);
730                                 // Check if we have commands and if they match in the previous line
731                                 Vector<String> previous_command_list = getOperatorList(previous_line);
732                                 Vector<String> previous_vector_match = matchingOperators(previous_command_list);
733                                 
734                                 // Check if we have commands and if they match in the current line
735                                 Vector<String> current_command_list = getOperatorList(current_line);
736                                 Vector<String> current_vector_match = matchingOperators(current_command_list);
737                                 
738                                 if (!autoIndent) {
739
740                                         if (previous_vector_match.size() > 0) {
741                                                 if (previous_vector_match.elementAt(0).equals(IN)) {
742                                                         level_one = 1;
743                                                 } 
744                                         } else {
745                                                 level_one = 0;
746                                         }
747                                 }
748                                 
749                         } catch (BadLocationException e) {
750                                 e.printStackTrace();
751                         }
752                 }
753                                 
754                 try {
755                         if (autoIndent) {
756                                 lineStartPosition = previous_line_start;
757                                 lineEndPosition = current_line_start;
758                                 
759                                 System.out.println("-------> "+lineStartPosition);
760                                 System.out.println("-------> "+lineEndPosition);
761                                 System.out.println("TAB = {"+tab+"}");
762                                 
763                                 applyAutoIndent(lineStartPosition, lineEndPosition, tab);
764                                 tab = "";
765                                 
766                         } else {
767                                 applyIndent(lineStartPosition, lineEndPosition, tab, level_one);
768                                 tab = "";
769                         }
770                 } catch (BadLocationException e) {
771                         e.printStackTrace();
772                 }
773
774         }
775         
776         public String getLineTabulations(String line) {
777                 String spaces = "";
778
779                 for (int j = 0; j < line.length(); j++) {
780                         if ((line.charAt(j) == '\t') || (line.charAt(j) == ' ')) {
781                                 spaces = spaces.concat(line.charAt(j)+"");
782                         } else {
783                                 break;
784                         }                               
785                 }                       
786
787                 return spaces;
788         }
789         
790         /*
791          * Remove all spaces or tabulations at the begining a string
792          * This function is used for the indentation only
793          * ex: '   hello world' will be tranformed into 'hello world'
794          */
795         public String removeFirstSpaces(String line) {
796                 int spaces = 0;
797
798                 for (int j = 0; j < line.length(); j++) {
799                         if ((line.charAt(j) == '\t') || (line.charAt(j) == ' ')) {
800                                 spaces++;
801                         } else {
802                                 break;
803                         }                               
804                 }                       
805                 line = line.substring(spaces, line.length());   
806
807                 return line;
808         }
809
810         /*
811          * Get all commands given in the string
812          * This function is used for the indentation only
813          */
814         public Vector<String> getOperatorList(String text) {
815                 Vector<String> operator_list = new Vector<String>();
816                 Vector<String> op = new Vector<String>();
817
818                 Vector<Integer> comments_boundaries = new Vector<Integer>();
819                 Vector<Integer> quotations_boundaries = new Vector<Integer>();
820                 Vector<Integer> tmp_comm_and_quot = new Vector<Integer>();
821
822                 Vector<Integer> commands_boundaries = new Vector<Integer>();
823
824                 String[] commands_in = {"if", "else", "elseif", "while", "for", "do", "select", "case", "function"};
825                 String[] commands_out = {"end", "endfunction"};
826
827                 String[] allCommands = {"if", "else", "elseif", "while", "for", "do", "select", "case", "function", "end", "endfunction"};
828
829                 // Regexp for Scilab commands
830                 for (int i = 0; i < allCommands.length; i++) {
831                         allCommands[i] = "\\b" + allCommands[i] + "\\b";
832                 }
833
834                 // Find command boundaries in the given text
835                 commands_boundaries = findBoundaries(allCommands, false, 0, this.getLength(), text);
836                 comments_boundaries = findBoundaries(comments, false, 0, this.getLength(), text);
837                 quotations_boundaries = findBoundaries(quotations, false, 0, this.getLength(), text);
838                 
839                 // Remove comments which are into quotations
840                 comments_boundaries = startNotIn(comments_boundaries, quotations_boundaries);
841                 // Remove quotations which are into comments
842                 quotations_boundaries = startNotIn(quotations_boundaries, comments_boundaries);
843
844                 // Union of comments & quotations to remove keywords
845                 tmp_comm_and_quot.addAll(comments_boundaries);
846                 tmp_comm_and_quot.addAll(quotations_boundaries);
847
848                 // Remove commads which are into quotations or comments
849                 commands_boundaries = startNotIn(commands_boundaries, tmp_comm_and_quot);
850
851                 // Sort commands_boudaries
852                 Collections.sort(commands_boundaries);
853                 
854                 // The function applyIndent needs a vector in this format, ex: IN,IF,OUT,END
855                 for (int i = 0; i < commands_boundaries.size(); i=i+2) {
856                         op.add(text.substring(commands_boundaries.elementAt(i), commands_boundaries.elementAt(i+1)));
857                 }
858                 
859                 for (int i = 0; i < op.size(); i++) {
860                         for (int j = 0; j < commands_in.length; j++) {
861                                 if (op.elementAt(i).toLowerCase().equals(commands_in[j])) {
862                                         operator_list.add(IN);
863                                         operator_list.add(op.elementAt(i));
864                                 }
865                         }
866                         for (int j = 0; j < commands_out.length; j++) {
867                                 if (op.elementAt(i).toLowerCase().equals(commands_out[j])) {
868                                         operator_list.add(OUT);
869                                         operator_list.add(op.elementAt(i));
870                                 }
871                         }
872                 }
873                 
874                 return operator_list;
875         }
876
877         /*
878          * Check if in one line all commands are matching,
879          * by this way we can know if the next line needs indentation or not
880          * ex: if %T then function foo(1) endfunction end => doesn't need indentation
881          * ex: if %T then foo(1) end for => need indentation
882          * This function is used for the indentation only
883          * WARNING: command_list looks like [IN, if, IN function, OUT, endfunction, OUT, end]
884          */
885         public Vector<String> matchingOperators(Vector<String> command_list) {
886
887                 int tmp_size = command_list.size();
888
889                 for (int i = 0; i < command_list.size() - 3; i=i+2) {
890                         if ((command_list.elementAt(i+1).toLowerCase().equals("function") && 
891                                         command_list.elementAt(i+3).toLowerCase().equals("endfunction"))
892                                         ||
893                                         (command_list.elementAt(i+3).toLowerCase().equals("end") && 
894                                                         !(command_list.elementAt(i+1).toLowerCase().equals("function")) &&
895                                                         !(command_list.elementAt(i+1).toLowerCase().equals("endfunction")) && 
896                                                         !(command_list.elementAt(i+1).toLowerCase().equals("end")) )) {
897                                 command_list.removeElementAt(i+3);                                      
898                                 command_list.removeElementAt(i+2);
899                                 command_list.removeElementAt(i+1);
900                                 command_list.removeElementAt(i);
901                                 i = i -2;
902                         } 
903                 }
904                 if (tmp_size == command_list.size()) {
905                         return command_list;
906                 }
907                 return matchingOperators(command_list);
908         }
909         /**
910          * DOCUMENT INDENTATION END
911          */
912
913
914         /**
915          * DOCUMENT COMMENT ACTION
916          */
917         public void commentText(int start_position, int end_position) {
918
919                 String text_to_comment = "";
920                 try {
921                         // Get the document text to comment
922                         text_to_comment = this.getText(start_position, end_position-start_position);
923                 } catch (BadLocationException e) {
924                         e.printStackTrace();
925                 }
926
927                 Vector<Integer> line_break = new Vector<Integer>(); // positions of line break
928                 Vector<String> all_lines = new Vector<String>(); // the document line by line
929                 String line = "";
930
931                 if (start_position != end_position) {
932                         for (int i = 0; i < text_to_comment.length(); i++) {
933                                 line = line.concat(text_to_comment.charAt(i)+"");
934
935                                 if (text_to_comment.charAt(i)=='\n') {
936                                         line_break.add(i);
937                                         all_lines.add(line);
938                                         line = "";
939                                 }
940                                 if (i==text_to_comment.length()-1) {
941                                         all_lines.add(line);
942                                         line = "";
943                                 }
944                         }
945
946                         String commented_text = "";
947                         for (int i = 0; i < all_lines.size(); i++) {
948                                 String tmp = "";
949                                 if (!(all_lines.elementAt(i).equals(""))) {
950                                         if (all_lines.elementAt(i).length() >= 2) {
951                                                 if (all_lines.elementAt(i).substring(0, 2).equals("//")) {
952                                                         tmp = all_lines.elementAt(i).substring(2, all_lines.elementAt(i).length());
953                                                 } else {
954                                                         tmp = "//" + all_lines.elementAt(i);
955                                                 }
956                                         }
957                                 }
958                                 commented_text += tmp;
959                         }
960
961                         // Display the text commented
962                         try {
963                                 this.replace(start_position, end_position-start_position, commented_text, null);
964                         } catch (BadLocationException e) {
965                                 e.printStackTrace();
966                         }
967                 }
968
969                 line_break.clear();
970                 all_lines.clear();
971         }
972         /**
973          * DOCUMENT COMMENT ACTION END
974          */
975
976
977         /**
978          * FIND AND REPLACE START
979          */
980         public ArrayList<Integer[]> findWord(String word, boolean caseSensitive , boolean wholeWord , boolean useRegexp ) {
981                 String fullText = getFullDocument(); 
982                 int lastIndex = 0;
983                 int wordSize = word.length();
984                 ArrayList<Integer[]> offsetList = new ArrayList<Integer[]>();
985
986                 //If we don't give any word to find
987                 if ( (word != null) && !(word.equals("")) ) {
988                         // prepare word for each kind of search
989                         if (wholeWord){
990                                 word = "\\b" + word + "\\b" ;
991                         }
992                         if (!caseSensitive){
993                                 if (useRegexp || wholeWord ){
994                                         word = "(?i)" + word ;
995                                 }
996                                 else{
997                                         fullText = fullText.toLowerCase();
998                                         word = word.toLowerCase();
999                                 }
1000                         }               
1001
1002
1003                         //We find matching words ...
1004                         // ... for regexp or whole words
1005                         if (useRegexp || wholeWord){
1006                                 Pattern pattern = Pattern.compile(word);
1007                                 Matcher matcher = pattern.matcher(fullText);
1008
1009                                 while (matcher.find()) {
1010                                         offsetList.add(new Integer[] {matcher.start() ,matcher.end()});
1011                                 }
1012                                 // ... for other case
1013                         }else {
1014                                 while ((lastIndex = fullText.indexOf(word, lastIndex)) != -1) {
1015                                         int endIndex = lastIndex + wordSize;
1016                                         offsetList.add(new Integer[] {lastIndex,endIndex} );
1017                                         lastIndex = endIndex;
1018                                 }
1019                         }
1020                 }
1021                 return offsetList;
1022         }
1023         
1024         public ArrayList<Integer[]> findWord(String word,int currentSelectStart ,int currentSelectEnd, boolean caseSensitive , boolean wholeWord , boolean useRegexp ) {
1025                 String fullText = getseletecDocumentLines(currentSelectStart, currentSelectEnd) ;
1026                 
1027                 int offset = this.getParagraphElement(currentSelectStart).getStartOffset() ;
1028                 int lastIndex = 0;
1029                 int wordSize = word.length();;
1030                 ArrayList<Integer[]> offsetList = new ArrayList<Integer[]>();
1031
1032                 //If we don't give any word to find
1033                 if ( (word != null) && !(word.equals("")) ) {
1034                         // prepare word for each kind of search
1035                         if (wholeWord){
1036                                 word = "\\b" + word + "\\b" ;
1037                         }
1038                         if (!caseSensitive){
1039                                 if (useRegexp || wholeWord ){
1040                                         word = "(?i)" + word ;
1041                                 }
1042                                 else{
1043                                         fullText = fullText.toLowerCase();
1044                                         word = word.toLowerCase();
1045                                 }
1046                         }               
1047
1048
1049                         //We find matching words ...
1050                         // ... for regexp or whole words
1051                         if (useRegexp || wholeWord){
1052                                 Pattern pattern = Pattern.compile(word);
1053                                 Matcher matcher = pattern.matcher(fullText);
1054
1055                                 while (matcher.find()) {
1056                                         offsetList.add(new Integer[] {matcher.start()+offset ,matcher.end()+offset});
1057                                 }
1058                                 // ... for other case
1059                         }else {
1060                                 while ((lastIndex = fullText.indexOf(word, lastIndex)) != -1) {
1061                                         int endIndex = lastIndex + wordSize;
1062                                         offsetList.add(new Integer[] {lastIndex+offset ,endIndex+offset } );
1063                                         lastIndex = endIndex;
1064                                 }
1065                         }
1066                 }
1067                 return offsetList;
1068         }
1069
1070         public int[] readText(int s, int e) {
1071                 int startOffset;
1072                 int endOffset;
1073                 String textLine = "";
1074                 String text = "";
1075                 Vector<Integer> min = new Vector<Integer>();
1076                 Vector<Integer> max = new Vector<Integer>();
1077                 int[] interval = new int[2];
1078
1079                 //We read the document
1080                 for (int i = 0; i < this.getLength();) {
1081                         startOffset = this.getParagraphElement(i).getStartOffset();
1082                         endOffset = this.getParagraphElement(i).getEndOffset();
1083                         min.add(startOffset);
1084                         max.add(endOffset);
1085
1086                         try {
1087                                 //Get the document line by line
1088                                 textLine = this.getText(startOffset, endOffset - startOffset);
1089                         } catch (BadLocationException ex) {
1090                                 ex.printStackTrace();
1091                         }
1092                         i = endOffset;
1093                         text += textLine;
1094                 }
1095
1096                 //If we only select a part of a line
1097                 for (int i = 0; i < min.size(); i++) {
1098                         if (s > min.elementAt(i)) {
1099                                 interval[0] = min.elementAt(i);
1100                         }
1101                 }
1102                 for (int i = 0; i < max.size(); i++) {
1103                         if (e > max.elementAt(i)) {
1104                                 interval[1] = max.elementAt(i);
1105                                 interval[1] = interval[1] - 1 ;
1106                         }
1107                 }
1108                 return interval;
1109         }
1110
1111         /**
1112          * Get the next expression matching the search after the caret current position
1113          * @param word , the word or regexp to find
1114          * @param currentPos, the position where the search start
1115          * @param caseSensitive , whether the search is sensitive or not to case
1116          * @param wholeWord  , whether the search will only look to separate word or not
1117          * @param useRegexp  , whether the string to search should be interpreted as a regexp or not
1118          */
1119         public int[] findNextWord (String word ,int currentPos, boolean caseSensitive , boolean wholeWord , boolean useRegexp ){
1120                 String fullText = getFullDocument();
1121                 int index = -1 ;
1122                 int end = -1 ;
1123
1124
1125
1126                 if ( (word != null) && (!word.equals(""))  ) {
1127                         // prepare word for each kind of search
1128                         if (wholeWord){
1129                                 word = "\\b" + word + "\\b" ;
1130                         }
1131                         if (!caseSensitive){
1132                                 if (useRegexp || wholeWord ){
1133                                         word = "(?i)" + word ;
1134                                 }
1135                                 else{
1136                                         fullText = fullText.toLowerCase();
1137                                         word = word.toLowerCase();
1138                                 }
1139                         }               
1140
1141
1142                         //We find matching words ...
1143                         // ... for regexp or whole words
1144                         if (useRegexp || wholeWord){
1145                                 Pattern pattern = Pattern.compile(word);
1146                                 Matcher matcher = pattern.matcher(fullText.substring(currentPos));
1147
1148                                 if (matcher.find()) {
1149                                         index = matcher.start()+currentPos;
1150                                         end = matcher.end()+currentPos;
1151                                 }else{
1152                                         index = -1 ;
1153                                         end  = -1 ;
1154                                 }
1155
1156                                 // ... for other case
1157                         }else {
1158                                 index = fullText.indexOf(word,currentPos);
1159                                 end = index + word.length();
1160                         }
1161                 }
1162
1163                         return new int [] {index , end } ;
1164         }
1165
1166         public int[] findNextWord (String word ,int currentPos,int currentSelectStart ,int currentSelectEnd, boolean caseSensitive , boolean wholeWord , boolean useRegexp ){
1167                 
1168                 String fullText = getseletecDocumentLines(currentSelectStart, currentSelectEnd) ;
1169                 int offset = this.getParagraphElement(currentSelectStart).getStartOffset() ;
1170                 System.out.println(currentPos) ;
1171                 currentPos -=  offset ;
1172                 
1173                 int index = -1 ;
1174                 int end = -1 ;
1175
1176
1177                 if ( (word != null) && (!word.equals(""))  ) {
1178                         // prepare word for each kind of search
1179                         if (wholeWord){
1180                                 word = "\\b" + word + "\\b" ;
1181                         }
1182                         if (!caseSensitive){
1183                                 if (useRegexp || wholeWord ){
1184                                         word = "(?i)" + word ;
1185                                 }
1186                                 else{
1187                                         fullText = fullText.toLowerCase();
1188                                         word = word.toLowerCase();
1189                                 }
1190                         }               
1191
1192
1193                         //We find matching words ...
1194                         // ... for regexp or whole words
1195                         if (useRegexp || wholeWord){
1196                                 Pattern pattern = Pattern.compile(word);
1197                                 Matcher matcher = pattern.matcher(fullText.substring(currentPos));
1198
1199                                 if (matcher.find()) {
1200                                         index = matcher.start()+currentPos+offset;
1201                                         end = matcher.end()+currentPos+offset;
1202                                 }else{
1203                                         index = -1 ;
1204                                         end  = -1 ;
1205                                 }
1206
1207                                 // ... for other case
1208                         }else {
1209                         
1210                                 index = fullText.indexOf(word,currentPos);
1211                                 if (index != -1) index += offset ;
1212                                 end = index + word.length();
1213                         }
1214                 }
1215
1216                         return new int [] {index , end } ;
1217         }
1218         
1219         
1220         
1221         /**
1222          * Get the previous expression matching the search before the caret current position
1223          * @param word , the word or regexp to find
1224          * @param currentPos, the position where the search start
1225          * @param caseSensitive , whether the search is sensitive or not to case
1226          * @param wholeWord  , whether the search will only look to separate word or not
1227          * @param useRegexp  , whether the string to search should be interpreted as a regexp or not
1228          */
1229         public int[] findPreviousWord (String word , int currentPos, boolean caseSensitive , boolean wholeWord , boolean useRegexp ){
1230                 String fullText = getFullDocument();
1231                 int index = -1 ;
1232                 int end = -1 ;
1233                 Pattern pattern;
1234
1235                 if ( (word != null) && (!word.equals(""))  ) {
1236
1237                         // prepare word for each kind of search
1238                         if (wholeWord){
1239                                 word = "\\b" + word + "\\b" ;
1240                         }
1241                         if (!caseSensitive){
1242                                 if (useRegexp || wholeWord ){
1243                                         word = "(?i)" + word ;
1244                                 }
1245                                 else{
1246                                         fullText = fullText.toLowerCase();
1247                                         word = word.toLowerCase();
1248                                 }
1249                         }               
1250
1251
1252                         //We find matching words ...
1253                         // ... for regexp or whole words
1254
1255                         if (useRegexp || wholeWord){
1256                                  pattern = Pattern.compile(word);
1257                         }else{// ... for other case
1258                                 // we use regexp in both case cause of a nasty bug when you have string like 
1259                                 //121212  and you search "121" forward then backward
1260                                 pattern = Pattern.compile(word , Pattern.LITERAL );
1261                                 
1262                         }
1263                                 Matcher matcher = pattern.matcher(fullText.substring(0,currentPos));
1264
1265                                 boolean found = false ;
1266                                 while (matcher.find()) {
1267                                         index = matcher.start();
1268                                         end = matcher.end();
1269                                         found = true ;
1270                                 }
1271
1272                                 if(!found){
1273                                         index = -1 ;
1274                                         end = -1;
1275                                 }
1276                 }
1277
1278
1279                 /*if nothing index and end will both be equal to -1*/
1280                 return new int [] {index , end } ;
1281
1282
1283         }
1284         
1285         
1286         public int[] findPreviousWord (String word , int currentPos,int currentSelectStart ,int currentSelectEnd, boolean caseSensitive , boolean wholeWord , boolean useRegexp ){
1287                 String fullText = getseletecDocumentLines(currentSelectStart, currentSelectEnd) ;
1288                 int offset = this.getParagraphElement(currentSelectStart).getStartOffset() ;
1289                 System.out.println(currentPos) ;
1290                 currentPos -=  offset ;
1291                 int index = -1 ;
1292                 int end = -1 ;
1293                 Pattern pattern;
1294
1295                 if ( (word != null) && (!word.equals(""))  ) {
1296
1297                         // prepare word for each kind of search
1298                         if (wholeWord){
1299                                 word = "\\b" + word + "\\b" ;
1300                         }
1301                         if (!caseSensitive){
1302                                 if (useRegexp || wholeWord ){
1303                                         word = "(?i)" + word ;
1304                                 }
1305                                 else{
1306                                         fullText = fullText.toLowerCase();
1307                                         word = word.toLowerCase();
1308                                 }
1309                         }               
1310
1311
1312                         //We find matching words ...
1313                         // ... for regexp or whole words
1314
1315                         if (useRegexp || wholeWord){
1316                                  pattern = Pattern.compile(word);
1317                         }else{// ... for other case
1318                                 // we use regexp in both case cause of a nasty bug when you have string like 
1319                                 //121212  and you search "121" forward then backward
1320                                 pattern = Pattern.compile(word , Pattern.LITERAL );
1321                                 
1322                         }
1323                                 System.out.println(currentPos) ;
1324                                 Matcher matcher = pattern.matcher(fullText.substring(0,currentPos));
1325
1326                                 boolean found = false ;
1327                                 while (matcher.find()) {
1328                                         index = matcher.start() + offset;
1329                                         end = matcher.end() + offset;
1330                                         found = true ;
1331                                 }
1332
1333                                 if(!found){
1334                                         index = -1 ;
1335                                         end = -1;
1336                                 }
1337                 }
1338
1339
1340                 /*if nothing index and end will both be equal to -1*/
1341                 return new int [] {index , end } ;
1342
1343
1344         }
1345         
1346         
1347         /**
1348          * FIND AND REPLACE END
1349          */
1350
1351
1352         /**
1353          * UTILITARIAN FUNCTIONS START
1354          */
1355         /*
1356          * Get all Scilab's keywords into a hashtable
1357          */
1358         public Hashtable<String, String[]> getScilabKeywords() {
1359                 //Get all Scilab keywords with SWIG
1360                 String[] commands =  ScilabKeywords.GetCommandsName();
1361                 String[] functions =  ScilabKeywords.GetFunctionsName();
1362                 String[] macros =  ScilabKeywords.GetMacrosName();
1363                 //String[] variables =  ScilabKeywords.GetVariablesName();
1364
1365                 Hashtable<String, String[]> keywords = new Hashtable<String, String[]>();
1366
1367                 for (int i = 0; i < commands.length; i++) {
1368                         keywords.put("command", commands);
1369                 }
1370                 for (int i = 0; i < functions.length; i++) {
1371                         keywords.put("function", functions);
1372                 }
1373                 for (int i = 0; i < macros.length; i++) {
1374                         keywords.put("macro", macros);
1375                 }
1376                 return keywords;
1377         }
1378
1379         /*
1380          * Parse all Scilab keywords
1381          * This function is used for the syntactic colorization
1382          */
1383         private Vector<Vector<Integer>> parse(String[] bools, String[] commands, String[] comments, 
1384                         String[] functions, String[] macros, String[] operators, String[] quotations, boolean singleLine, int start, int end) {
1385
1386                 Vector<Integer> boolsBoundaries, commandsBoundaries, 
1387                 commentsBoundaries, functionsBoundaries, 
1388                 macrosBoundaries, operatorsBoundaries, 
1389                 quotationsBoundaries;
1390
1391                 Vector<Vector<Integer>> boundaries_list = new Vector<Vector<Integer>>();
1392
1393                 boolsBoundaries = findBoundaries(bools, singleLine, start, end, null);
1394                 commandsBoundaries = findBoundaries(commands, singleLine, start, end, null);
1395                 commentsBoundaries = findBoundaries(comments, singleLine, start, end, null);
1396                 functionsBoundaries = findBoundaries(functions, singleLine, start, end, null);
1397                 macrosBoundaries = findBoundaries(macros, singleLine, start, end, null);
1398                 operatorsBoundaries = findBoundaries(operators, singleLine, start, end, null);
1399                 quotationsBoundaries = findBoundaries(quotations, singleLine, start, end, null);        
1400
1401
1402                 boundaries_list = organizeBoundaries(boolsBoundaries, commandsBoundaries, commentsBoundaries, functionsBoundaries, 
1403                                 macrosBoundaries, operatorsBoundaries, quotationsBoundaries);
1404
1405                 return boundaries_list;
1406         }
1407
1408         /*
1409          * Get start & end position for each keywords
1410          * String[] keyword is a type of keywords(ex: operators, commands, macros..)
1411          * String text is where we make the search, 
1412          * if text is null we apply the research to the entire document
1413          */
1414         private Vector<Integer> findBoundaries(String[] keyword, boolean singleLine, int start, int end, String text) {
1415
1416                 Pattern pattern;
1417                 Matcher matcher = null;
1418                 Vector<Integer> bound = new Vector<Integer>();
1419                 
1420                 for(int i = 0 ; i < keyword.length ; i++)       {
1421                         pattern = Pattern.compile(keyword[i], Pattern.DOTALL);
1422                         try {
1423                                 if (singleLine && text == null) {
1424                                         matcher = pattern.matcher(this.getText(start, end - start));
1425                                         while(matcher.find()){
1426                                                 //System.err.println("Match Found : "+(matcher.start())+","+(matcher.end()/*-matcher.start()*/));
1427                                                 bound.add(new Integer(matcher.start() + start));        
1428                                                 bound.add(new Integer(matcher.end() + start));
1429                                         }
1430
1431                                 } else {
1432                                         if (text != null) {
1433                                                 matcher = pattern.matcher(text);
1434                                         } else {
1435                                                 matcher = pattern.matcher(this.getText(0, this.getLength()));
1436                                         }
1437                                         
1438                                         while(matcher.find()){
1439                                                 //System.err.println("Match Found : "+(matcher.start())+","+(matcher.end()/*-matcher.start()*/));
1440                                                 bound.add(new Integer(matcher.start()));        
1441                                                 bound.add(new Integer(matcher.end()));
1442                                         }
1443                                 }
1444                         } catch (BadLocationException e) {
1445                                 e.printStackTrace();
1446                         }
1447                 }
1448                 return bound;
1449         }
1450
1451         /*
1452          * When we have all boundaries for each type of keywords
1453          * we filter 'bad' boundaries
1454          * ex: if we have quotations into comments (and the opposite), keywords into quotations or comments 
1455          */
1456         private Vector<Vector<Integer>> organizeBoundaries(Vector<Integer> boolsBoundaries, Vector<Integer> commandsBoundaries,
1457                         Vector<Integer> commentsBoundaries, Vector<Integer> functionsBoundaries, 
1458                         Vector<Integer> macrosBoundaries, Vector<Integer> operatorsBoundaries, 
1459                         Vector<Integer> quotationsBoundaries) {
1460
1461                 Vector<Integer> tmp_comm_and_quot = new Vector<Integer>();
1462                 Vector<Vector<Integer>> vector_list = new Vector<Vector<Integer>>();
1463
1464                 // Remove comments which are into quotations
1465                 commentsBoundaries = startNotIn(commentsBoundaries, quotationsBoundaries);
1466                 // Remove quotations which are into comments
1467                 quotationsBoundaries = startNotIn(quotationsBoundaries, commentsBoundaries);
1468
1469                 // Union of comments & quotations to remove keywords
1470                 tmp_comm_and_quot.addAll(commentsBoundaries);
1471                 tmp_comm_and_quot.addAll(quotationsBoundaries);
1472
1473                 // Remove keywords which are into comments & quotations
1474                 boolsBoundaries = strictlyNotIn(boolsBoundaries, tmp_comm_and_quot);
1475                 commandsBoundaries = strictlyNotIn(commandsBoundaries, tmp_comm_and_quot);
1476                 functionsBoundaries = strictlyNotIn(functionsBoundaries, tmp_comm_and_quot);
1477                 macrosBoundaries = strictlyNotIn(macrosBoundaries, tmp_comm_and_quot);
1478                 operatorsBoundaries = strictlyNotIn(operatorsBoundaries, tmp_comm_and_quot);
1479
1480                 vector_list.add(boolsBoundaries);
1481                 vector_list.add(commandsBoundaries);
1482                 vector_list.add(commentsBoundaries);
1483                 vector_list.add(functionsBoundaries);
1484                 vector_list.add(macrosBoundaries);
1485                 vector_list.add(operatorsBoundaries);
1486                 vector_list.add(quotationsBoundaries);
1487
1488                 return vector_list;
1489         }
1490
1491         private Vector<Integer> strictlyNotIn(Vector<Integer> v1, Vector<Integer> v2) {
1492                 int v1_start = 0;
1493                 int v1_end = 0;
1494                 int v2_start = 0;
1495                 int v2_end = 0;
1496
1497                 Vector<Integer> vector_strictlyNotIn = new Vector<Integer>();
1498
1499                 // Remove interval from v1 which are include in interval of v2
1500                 for(int i=0; i < v1.size(); i=i+2) {
1501                         boolean dropMe = false;
1502                         v1_start = v1.elementAt(i);
1503                         v1_end = v1.elementAt(i+1);
1504
1505                         for(int j=0; j < v2.size(); j=j+2) {
1506                                 v2_start = v2.elementAt(j);
1507                                 v2_end = v2.elementAt(j+1);
1508
1509                                 if(((v1_start >= v2_start) && (v1_start <= v2_end)) && ((v1_end >= v2_start) && (v1_end <= v2_end))) {
1510                                         dropMe = true;
1511                                 }
1512                         }
1513                         if (!dropMe) {
1514                                 vector_strictlyNotIn.addElement(v1.elementAt(i));
1515                                 vector_strictlyNotIn.addElement(v1.elementAt(i+1));
1516                         }
1517
1518                         //System.out.println("vector_strictlyNotIn"+vector_strictlyNotIn);
1519                 }
1520                 return vector_strictlyNotIn;
1521         }
1522
1523         private Vector<Integer> startNotIn(Vector<Integer> v1, Vector<Integer> v2) {
1524                 int v1_start = 0;
1525                 int v2_start = 0;
1526                 int v2_end = 0;
1527                 Vector<Integer> vector_startNotIn = new Vector<Integer>();
1528
1529                 for(int i=0; i < v1.size(); i=i+2) {
1530                         boolean dropMe = false;
1531                         v1_start = v1.elementAt(i);
1532
1533                         for(int j=0; j < v2.size(); j=j+2) {
1534                                 v2_start = v2.elementAt(j);
1535                                 v2_end = v2.elementAt(j+1);
1536
1537                                 if(((v1_start >= v2_start) && (v1_start <= v2_end))) {
1538                                         dropMe = true;
1539                                 }
1540                         }
1541                         if (!dropMe) {
1542                                 vector_startNotIn.addElement(v1.elementAt(i));
1543                                 vector_startNotIn.addElement(v1.elementAt(i+1));
1544                         }
1545
1546                         //System.out.println("vector_startNotIn"+vector_startNotIn);
1547                 }
1548                 return vector_startNotIn;
1549         }
1550         /**
1551          * UTILITARIAN FUNCTIONS END
1552          */
1553
1554         private final void DEBUG(String msg) {
1555                 System.err.println("[DEBUG] "+msg);
1556         }
1557         public void disableUpdaters() {
1558                 updaterDisabled = true;
1559         }
1560
1561         public String getFullDocument() {
1562                 int startOffset;
1563                 int endOffset;
1564                 String textLine = "";
1565                 String text = "";
1566
1567                 //We read the document and put the document into the String text
1568                 for (int i = 0; i < this.getLength();) {
1569                         startOffset = this.getParagraphElement(i).getStartOffset();
1570                         endOffset = this.getParagraphElement(i).getEndOffset();
1571
1572                         try {
1573                                 //Get the document line by line
1574                                 textLine = this.getText(startOffset, endOffset - startOffset);
1575                         } catch (BadLocationException ex) {
1576                                 ex.printStackTrace();
1577                         }
1578                         i = endOffset;
1579                         text += textLine;
1580                 }
1581                 return text;
1582         }
1583
1584         public String getseletecDocumentLines(int start , int end ) {
1585                 int startOffset;
1586                 int endOffset;
1587
1588                 String text = "";
1589
1590                 startOffset = this.getParagraphElement(start).getStartOffset();
1591                 endOffset = this.getParagraphElement(end).getEndOffset();
1592                 //We read the document and put the document into the String text
1593
1594                 try {
1595                         //Get the document line by line
1596                         text = this.getText(startOffset, endOffset - startOffset);
1597                 } catch (BadLocationException ex) {
1598                         ex.printStackTrace();
1599                 }
1600
1601
1602                 return text;
1603         }
1604
1605         public void enableUpdaters() {
1606                 updaterDisabled = false;
1607         }
1608
1609         public void insertUpdate(DocumentEvent e) {
1610                 if (e != null){
1611                         EventType = e.getType().toString();
1612                         //Element[] pouet =  e.getChange( this.getParagraphElement(editor.getTextPane().getCaretPosition())).getChildrenAdded();
1613                 }
1614                 
1615                 //System.err.println("--- Calling insertUpdate");
1616                 if (!updaterDisabled) {
1617                         SwingUtilities.invokeLater(new Runnable() {
1618                                 public void run() {
1619                                         //resetStyle();
1620                                         if (autoIndent) {
1621                                                 
1622                                                 IndentAction.getXpadEditor();
1623                                                 editor = getEditor();
1624                                                 int  caretPosition = editor.getTextPane().getCaretPosition();
1625                                                 
1626                                                 try {
1627                                                         if (editor.getTextPane().getText(caretPosition-1, 1).equals("\n")) {
1628                                                                 System.out.println("------------ SAUTE de LIGNE ------------");
1629                                                                 indent();
1630                                                         }
1631                                                 } catch (BadLocationException e) {
1632                                                         e.printStackTrace();
1633                                                 }
1634                                                 
1635                                                 //indent();
1636                                         }
1637                                         if (autoColorize) {
1638                                                 //colorize();
1639                                                 setSingleLine(true);
1640                                                 ColorizeAction.getXpadEditor();
1641                                                 editor = getEditor();
1642                                                 
1643                                                 // Get the current line (position of the caret) 
1644                                                 int  caretPosition = editor.getTextPane().getCaretPosition();
1645                                                 currentLine = editor.getTextPane().getStyledDocument().getDefaultRootElement().getElementIndex(caretPosition);
1646
1647                                                 // Get current line's start & end offsets
1648                                                 lineStartPosition =  editor.getTextPane().getStyledDocument().getParagraphElement(caretPosition).getStartOffset();
1649                                                 lineEndPosition = editor.getTextPane().getStyledDocument().getParagraphElement(caretPosition).getEndOffset()-1;
1650                                                 
1651                                                 // If we add a line (by pressing return)
1652                                                 if (lineStartPosition == lineEndPosition) {
1653                                                         lineStartPosition = lineStartPosition + lineEndPosition;
1654                                                         lineEndPosition = lineEndPosition + lineEndPosition;
1655                                                 } 
1656                                                 
1657                                                 if (lineStartPosition != lineEndPosition) {
1658                                                         colorizeSingleLine(lineStartPosition, lineEndPosition);
1659                                                 }
1660                                                 setSingleLine(false);
1661                                         }
1662                                 }
1663                         });  
1664                 }
1665         }
1666         public void removeUpdate(DocumentEvent e) {
1667                 
1668                 EventType = e.getType().toString() ;
1669                 //System.err.println("--- Calling ScilabStyleDocument.removeUpdate");
1670                 if (!updaterDisabled) {
1671                         SwingUtilities.invokeLater(new Runnable() {
1672                                 public void run() {
1673                                         //resetStyle();
1674                                         if (autoIndent) {
1675
1676                                                 IndentAction.getXpadEditor();
1677                                                 editor = getEditor();
1678                                                 int  caretPosition = editor.getTextPane().getCaretPosition();
1679                                                 
1680                                                 try {
1681                                                         if (editor.getTextPane().getText(caretPosition-1, 1).equals("\n")) {
1682                                                                 System.out.println("------------ SAUTE de LIGNE ------------");
1683                                                                 indent();
1684                                                         }
1685                                                 } catch (BadLocationException e) {
1686                                                         e.printStackTrace();
1687                                                 }
1688                                         }
1689                                         if (autoColorize) {
1690                                                 //colorize();
1691                                                 setSingleLine(true);
1692                                                 ColorizeAction.getXpadEditor();
1693                                                 editor = getEditor();
1694                                                 
1695                                                 
1696                                                 // Get the current line (position of the caret) 
1697                                                 int  caretPosition = editor.getTextPane().getCaretPosition();
1698                                                 currentLine = editor.getTextPane().getStyledDocument().getDefaultRootElement().getElementIndex(caretPosition);
1699
1700                                                 // Get current line's start & end offsets
1701                                                 lineStartPosition =  editor.getTextPane().getStyledDocument().getParagraphElement(caretPosition).getStartOffset();
1702                                                 lineEndPosition = editor.getTextPane().getStyledDocument().getParagraphElement(caretPosition).getEndOffset()-1;
1703                                                 
1704                                                 // If we add a line (by pressing return)
1705                                                 if (lineStartPosition == lineEndPosition) {
1706                                                         lineStartPosition = lineStartPosition + lineEndPosition;
1707                                                         lineEndPosition = lineEndPosition + lineEndPosition;
1708                                                 } 
1709                                                 
1710                                                 if (lineStartPosition != lineEndPosition) {
1711                                                         colorizeSingleLine(lineStartPosition, lineEndPosition);
1712                                                 }
1713                                                 setSingleLine(false);
1714                                         }
1715                                 }
1716                         });
1717                 }
1718         }
1719
1720         public void changedUpdate(DocumentEvent arg0) {
1721                 
1722                 EventType = arg0.getType().toString() ;
1723                 // TODO Auto-generated method stub
1724         }
1725
1726         public void setAutoIndent(boolean b) {
1727                 //DEBUG("setAutoIndent("+b+")");
1728                 autoIndent = b;
1729         }
1730         public boolean getAutoIndent() {
1731                 //DEBUG("getAutoIndent("+autoIndent+")");
1732                 return autoIndent;
1733         }
1734         public UndoManager getUndoManager() {
1735                 return undo;
1736         }
1737
1738         
1739         public boolean isContentModified(){
1740                 return contentModified ;
1741         }
1742         
1743         public void setContentModified(boolean contentModified){
1744                 this.contentModified = contentModified ;
1745         }
1746         
1747         
1748         public boolean isSingleLine() {
1749                 return singleLine;
1750         }
1751
1752         public void setSingleLine(boolean singleLine) {
1753                 this.singleLine = singleLine;
1754         }
1755
1756         public int getLineToColor() {
1757                 return currentLine;
1758         }
1759
1760         public void setLineToColor(int lineToColor) {
1761                 this.currentLine = lineToColor;
1762         }
1763
1764         
1765         public int getLineEndPosition() {
1766                 return lineEndPosition;
1767         }
1768
1769         public void setLineEndPosition(int lineEndPosition) {
1770                 this.lineEndPosition = lineEndPosition;
1771         }
1772
1773         public int getLineStartPosition() {
1774                 return lineStartPosition;
1775         }
1776
1777         public void setLineStartPosition(int lineStartPosition) {
1778                 this.lineStartPosition = lineStartPosition;
1779         }
1780
1781         
1782         
1783         
1784         public Xpad getEditor() {
1785                 return editor;
1786         }
1787
1788         public void setEditor(Xpad editor) {
1789                 this.editor = editor;
1790         }
1791
1792         
1793
1794         
1795 }