package eg.document;

/**
 * The auto-indentation which works with spaces.<br>
 * Created in {@link TypingEdit}
 */
public class AutoIndent {

   private final TextDocument textDoc;

   private String indentUnit = "";
   private int indentLength = 0;
   private boolean isOutdentEnabled = false;

   /**
    * @param textDoc  the reference to {@link TextDocument}
    */
   public AutoIndent(TextDocument textDoc) {
      this.textDoc = textDoc;
   }

   /**
    * Sets the indent unit which consists of a certain number of
    * spaces
    *
    * @param indentUnit  the indent unit
    */
   public void setIndentUnit(String indentUnit) {
      if (indentUnit == null
            || (indentUnit.length() > 0 && !indentUnit.matches("[\\s]+"))) {

         throw new IllegalArgumentException(
               "The indent unit must consist of spaces");
      }
      this.indentUnit = indentUnit;
      indentLength = indentUnit.length();
   }

   /**
    * Returns the currently set indent unit
    *
    * @return  the indent unit
    */
   public String getIndentUnit() {
      return indentUnit;
   }

   /**
    * Does indentation if the character at the specified position
    * is a newline. The indentation corresponds to the indentation
    * at the previous line or is increased by this indent unit if
    * an opening brace precedes the newline character
    *
    * @param text  the text
    * @param pos  the position
    */
   public void indent(String text, int pos) {
      boolean isNewLine = '\n' == text.charAt(pos);
      if (isNewLine) {
         String currIndent = currentIndent(text, pos);
         if (pos > 1 && '{' == text.charAt(pos - 1)) {
            currIndent += indentUnit;
         }
         textDoc.insert(pos + 1, currIndent);
      }
   }

   /**
    * Reduces the indentation by this indent unit if the character at
    * the specified position is a closing brace
    *
    * @param text  the text
    * @param pos  the position
    */
   public void closedBracketIndent(String text, int pos) {
      if (pos < indentLength || '}' != text.charAt(pos)) {
         return;
      }
      int outdentPos = pos - indentLength;
      if (text.substring(outdentPos, pos).equals(indentUnit)) {
         textDoc.remove(outdentPos, indentLength);
      }
   }

   //
   //--private--//
   //

   private String currentIndent(String text, int pos) {
      String currIndent = "";
      int lineStart;
      if (pos > 1) {
         lineStart = text.lastIndexOf("\n", pos - 1) + 1;
         char[] line = text.substring(lineStart, pos).toCharArray();
         for (int i = 0; i < line.length && line[i] == ' '; i++) {
            currIndent += " ";
         }
      }
      return currIndent;
   }
}

@@ -71,11 +71,14 @@
 ces.
-%3Cbr
+%0A * %3Cp
 %3E%0A *
@@ -250,53 +250,8 @@
 = 0;
-%0A   private boolean isOutdentEnabled = false;
 %0A%0A  
@@ -1072,12 +1072,18 @@
   * 
-Does
+Inserts an
  ind
@@ -1091,18 +1091,59 @@
 ntation 
-if
+corresponding to the previous line if%0A    *
  the cha
@@ -1174,22 +1174,16 @@
 position
-%0A    *
  is a ne
@@ -1208,69 +1208,14 @@
 tion
- corresponds to the indentation%0A    * at the previous line or
+%0A    *
  is 
@@ -1223,28 +1223,26 @@
 ncreased by 
-this
+an
  indent unit
@@ -1244,22 +1244,16 @@
  unit if
-%0A    *
  an open
@@ -1274,16 +1274,22 @@
 edes the
+%0A    *
  newline
@@ -1534,16 +1534,18 @@
 ntIndent
+At
 (text, p
@@ -1837,16 +1837,69 @@
 ng brace
+ and if the current%0A    * indentation can be reduced 
 %0A    *%0A 
@@ -1982,23 +1982,11 @@
 oid 
-closedBracketIn
+out
 dent
@@ -2143,20 +2143,65 @@
 ;%0A      
-if (
+boolean ok = isOutdent(text, pos)%0A            && 
 text.sub
@@ -2242,16 +2242,31 @@
 entUnit)
+;%0A%0A      if (ok
 ) %7B%0A    
@@ -2349,17 +2349,16 @@
 ivate--/
-/
 %0A   //%0A%0A
@@ -2384,24 +2384,26 @@
 urrentIndent
+At
 (String text
@@ -2761,10 +2761,678 @@
 t;%0A   %7D%0A
+   %0A   private boolean isOutdent(String text, int pos) %7B%0A      int lastOpeningPos = text.lastIndexOf('%7B', pos - 1);%0A      int lastClosingPos = text.lastIndexOf('%7D', pos - 1);%0A      String indentAtChange = currentIndentAt(text, pos);%0A      String indentAtBraceAhead = %22%22;%0A      if (lastOpeningPos %3E lastClosingPos) %7B%0A         indentAtBraceAhead = currentIndentAt(text, lastOpeningPos);%0A         return indentAtChange.length()%0A               - indentAtBraceAhead.length() %3E= indentLength;%0A      %7D%0A      else %7B%0A         indentAtBraceAhead = currentIndentAt(text, lastClosingPos);%0A         return indentAtChange.length() %3E= indentAtBraceAhead.length();%0A      %7D%0A   %7D      %0A
 %7D%0A

add a check if outdent shall happen when closing brace is typed