Added INDENT_EACH_LINE reindentation strategy
diff --git a/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90 b/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90
new file mode 100644
index 0000000..6ba1b56
--- /dev/null
+++ b/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90
@@ -0,0 +1,12 @@
+            program program !<<<<<START
+          print *, "Hello"
+    end program program
+
+      subroutine s
+        integer :: i
+          do i = 3, 4
+        do j = 5, 6
+                  print *, i + j
+                     end do
+                             end do
+end subroutine !<<<<<END
diff --git a/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90.result b/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90.result
new file mode 100644
index 0000000..e2f0ef3
--- /dev/null
+++ b/org.eclipse.photran.core.vpg.tests/reindenter-test-code/05-eachline-test.f90.result
@@ -0,0 +1,12 @@
+program program !<<<<<START
+    print *, "Hello"
+end program program
+
+subroutine s
+    integer :: i
+    do i = 3, 4
+        do j = 5, 6
+            print *, i + j
+        end do
+    end do
+end subroutine !<<<<<END
diff --git a/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestCase.java b/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestCase.java
index df9166e..e8c0366 100644
--- a/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestCase.java
+++ b/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestCase.java
@@ -21,6 +21,7 @@
 import org.eclipse.photran.core.vpg.PhotranVPG;
 import org.eclipse.photran.internal.core.refactoring.infrastructure.Reindenter;
 import org.eclipse.photran.internal.core.refactoring.infrastructure.SourcePrinter;
+import org.eclipse.photran.internal.core.refactoring.infrastructure.Reindenter.Strategy;
 import org.eclipse.photran.refactoring.tests.RefactoringTestCase;
 
 public class ReindenterTestCase extends RefactoringTestCase
@@ -28,14 +29,16 @@
     private static final String DIR = "reindenter-test-code";
     
     protected String filename = null;
+    protected Strategy strategy;
     private int fromLine;
     private int thruLine;
 
     public ReindenterTestCase() {;}  // when JUnit invokes a subclass outside a test suite
 
-    public ReindenterTestCase(String filename, Object ignored) // avoid JUnit constructor
+    public ReindenterTestCase(String filename, Strategy strategy)
     {
         this.filename = filename;
+        this.strategy = strategy;
         this.setName("test");
     }
 
@@ -48,7 +51,7 @@
         IFortranAST ast = PhotranVPG.getInstance().acquireTransientAST(thisFile);
         assertNotNull(ast);
         
-        Reindenter.reindent(fromLine, thruLine, ast);
+        Reindenter.reindent(fromLine, thruLine, ast, strategy);
         
         thisFile.setContents(
             new ByteArrayInputStream(SourcePrinter.getSourceCodeFromAST(ast).getBytes()),
diff --git a/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestSuite.java b/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestSuite.java
index 5fb50e3..d88fc9d 100644
--- a/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestSuite.java
+++ b/org.eclipse.photran.core.vpg.tests/src/org/eclipse/photran/refactoring/tests/infrastructure/ReindenterTestSuite.java
@@ -13,23 +13,26 @@
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
+import org.eclipse.photran.internal.core.refactoring.infrastructure.Reindenter.Strategy;
+
 public class ReindenterTestSuite extends TestSuite
 {
     public static Test suite() throws Exception
     {
         TestSuite suite = new TestSuite();
-        suite.addTest(getSuiteFor("01-simple.f90"));
-        suite.addTest(getSuiteFor("02-end-after.f90"));
-        suite.addTest(getSuiteFor("03-blank-after.f90"));
-        suite.addTest(getSuiteFor("04-guess-indent.f90"));
-        //suite.addTest(getSuiteFor("0.f90"));
+        suite.addTest(getSuiteFor("01-simple.f90", Strategy.SHIFT_ENTIRE_BLOCK));
+        suite.addTest(getSuiteFor("02-end-after.f90", Strategy.SHIFT_ENTIRE_BLOCK));
+        suite.addTest(getSuiteFor("03-blank-after.f90", Strategy.SHIFT_ENTIRE_BLOCK));
+        suite.addTest(getSuiteFor("04-guess-indent.f90", Strategy.SHIFT_ENTIRE_BLOCK));
+        suite.addTest(getSuiteFor("05-eachline-test.f90", Strategy.REINDENT_EACH_LINE));
+        //suite.addTest(getSuiteFor("0.f90", Strategy));
         return suite;
     }
     
-    private static TestSuite getSuiteFor(String baseFilename)
+    private static TestSuite getSuiteFor(String baseFilename, Strategy strategy)
     {
         TestSuite subSuite = new TestSuite("Reindenting " + baseFilename);
-        subSuite.addTest(new ReindenterTestCase(baseFilename, null));
+        subSuite.addTest(new ReindenterTestCase(baseFilename, strategy));
         return subSuite;
     }
 }
diff --git a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/infrastructure/Reindenter.java b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/infrastructure/Reindenter.java
index c376b56..44d8f41 100644
--- a/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/infrastructure/Reindenter.java
+++ b/org.eclipse.photran.core.vpg/src/org/eclipse/photran/internal/core/refactoring/infrastructure/Reindenter.java
@@ -25,63 +25,115 @@
  * The Reindenter is used to correct indentation when a node is inserted or
  * moved in an AST so that the affected lines are correctly indented in their
  * new context.
- * <p>
- * The algorithm is fairly straightforward:
- * <ul>
- *   <li> Usually, the reindented region is adjusted to match the indentation of
- *        the next non-empty line following the region.
- *   <li> However, if the next non-empty line starts with "END" (or something),
- *        the reindented region is adjusted to match the indentation of
- *        the last non-empty line above the region.
- *   <li> However, if the last non-empty line above starts with a token like
- *        "PROGRAM" or "IF," then a guess is made, and the indentation is set
- *        to match the following line, but four spaces are added.
- * </ul>
- * <p>
- * This code is very specific to the way Photran's parser uses the whiteBefore and
- * whiteAfter parts of a Token; it will not generalize to parsers that, say, include
- * newlines in the whitetext.
  *  
  * @author Jeff Overbey
  */
+/*
+ * This code is very specific to the way Photran's parser uses the whiteBefore and
+ * whiteAfter parts of a Token; it will not generalize to parsers that, say, include
+ * newlines in the whitetext.
+ */
 public class Reindenter
 {
+    public static enum Strategy
+    {
+        /**
+         * Shifts the entire region left or right to match its new surroundings, keeping
+         * the relative indentation of each line the same.
+         * <p>
+         * The algorithm is as follows:
+         * <ul>
+         *   <li> Usually, the reindented region is adjusted to match the indentation of
+         *        the next non-empty line following the region.
+         *   <li> However, if the next non-empty line starts with "END" (or something),
+         *        the reindented region is adjusted to match the indentation of
+         *        the last non-empty line above the region.
+         *   <li> However, if the last non-empty line above starts with a token like
+         *        "PROGRAM" or "IF," then a guess is made, and the indentation is set
+         *        to match the following line, but four spaces are added.
+         * </ul>
+         */
+        SHIFT_ENTIRE_BLOCK
+        {
+            @Override protected ReindentingVisitor createVisitor(Reindenter reindenter, Token firstTokenInRegion, Token lastTokenInRegion)
+            {
+                return reindenter.new ShiftBlockReindentingVisitor(firstTokenInRegion, lastTokenInRegion);
+            }
+        },
+        
+        /**
+         * Shifts each lines in the region left or right to match its new surroundings.
+         * <p>
+         * The algorithm is as follows:
+         * <ul>
+         *   <li> Initially, the line is indented the same as the previous line.
+         *   <li> If the preceding line starts with PROGRAM, IF, DO, etc., the line is
+         *        indented an additional 4 spaces.
+         *   <li> If the line starts with END, it is unindented 4 spaces.
+         * </ul>
+         */
+        REINDENT_EACH_LINE
+        {
+            @Override protected ReindentingVisitor createVisitor(Reindenter reindenter, Token firstTokenInRegion, Token lastTokenInRegion)
+            {
+                return reindenter.new ReindentEachLineReindentingVisitor(firstTokenInRegion, lastTokenInRegion);
+            }
+        };
+        
+        protected abstract ReindentingVisitor createVisitor(Reindenter reindenter, Token firstTokenInRegion, Token lastTokenInRegion);
+    }
+    
     public static void reindent(IASTNode node, IFortranAST ast)
     {
-        new Reindenter(node, ast);
+        new Reindenter(node, ast, Strategy.SHIFT_ENTIRE_BLOCK);
     }
 
     public static void reindent(Token firstTokenInAffectedNode, Token lastTokenInAffectedNode, IFortranAST ast)
     {
-        new Reindenter(firstTokenInAffectedNode, lastTokenInAffectedNode, ast);
+        new Reindenter(firstTokenInAffectedNode, lastTokenInAffectedNode, ast, Strategy.SHIFT_ENTIRE_BLOCK);
     }
 
     public static void reindent(int fromLine, int thruLine, IFortranAST ast)
     {
-        new Reindenter(fromLine, thruLine, ast);
+        new Reindenter(fromLine, thruLine, ast, Strategy.SHIFT_ENTIRE_BLOCK);
+    }
+    
+    public static void reindent(IASTNode node, IFortranAST ast, Strategy strategy)
+    {
+        new Reindenter(node, ast, strategy);
+    }
+
+    public static void reindent(Token firstTokenInAffectedNode, Token lastTokenInAffectedNode, IFortranAST ast, Strategy strategy)
+    {
+        new Reindenter(firstTokenInAffectedNode, lastTokenInAffectedNode, ast, strategy);
+    }
+
+    public static void reindent(int fromLine, int thruLine, IFortranAST ast, Strategy strategy)
+    {
+        new Reindenter(fromLine, thruLine, ast, strategy);
     }
 
 	private final IFortranAST ast;
 	private final int lineNumOfLastTokenInAST;
 	
-    private Reindenter(IASTNode node, IFortranAST ast)
+    private Reindenter(IASTNode node, IFortranAST ast, Strategy strategy)
 	{
-        this(node.findFirstToken(), node.findLastToken(), ast);
+        this(node.findFirstToken(), node.findLastToken(), ast, strategy);
     }
     
-    private Reindenter(int fromLine, int thruLine, IFortranAST ast)
+    private Reindenter(int fromLine, int thruLine, IFortranAST ast, Strategy strategy)
     {
-        this(ast.findFirstTokenOnLine(fromLine), ast.findLastTokenOnLine(thruLine), ast);
+        this(ast.findFirstTokenOnLine(fromLine), ast.findLastTokenOnLine(thruLine), ast, strategy);
     }
     
-    private Reindenter(Token firstTokenInRegion, Token lastTokenInRegion, IFortranAST ast)
+    private Reindenter(Token firstTokenInRegion, Token lastTokenInRegion, IFortranAST ast, Strategy strategy)
     {
         // Recompute TokenList so that line number-based searches will be correct
         this.lineNumOfLastTokenInAST = recomputeLineColInfo(ast.getRoot());
         this.ast = new FortranAST(ast.getFile(), ast.getRoot(), new TokenList(ast.getRoot()));
         
         if (firstTokenInRegion != null && lastTokenInRegion != null)
-            ast.accept(new ReindentingVisitor(firstTokenInRegion, lastTokenInRegion));
+            ast.accept(strategy.createVisitor(this, firstTokenInRegion, lastTokenInRegion));
     }
 
     private int recomputeLineColInfo(ASTExecutableProgramNode astRoot)
@@ -121,48 +173,25 @@
         }
     }
 
-    private final class ReindentingVisitor extends ASTVisitorWithLoops
+    private abstract class ReindentingVisitor extends ASTVisitorWithLoops
     {
-        private final Token firstTokenInRegion;
-        private final Token lastTokenInRegion;
-        private String removeIndent, addIndent;
+        protected final Token firstTokenInRegion;
+        protected final Token lastTokenInRegion;
+        protected String removeIndent, addIndent;
 
-        private boolean inFormatRegion = false;
-        private Token previousToken = null;
+        protected boolean inFormatRegion = false;
+        protected Token previousToken = null;
 
         /**
          * @param firstTokenInRegion
          * @param lastTokenInRegion
          */
-        private ReindentingVisitor(Token firstTokenInRegion, Token lastTokenInRegion)
+        protected ReindentingVisitor(Token firstTokenInRegion, Token lastTokenInRegion)
         {
             this.lastTokenInRegion = lastTokenInRegion;
             this.firstTokenInRegion = firstTokenInRegion;
             
             //System.out.println("Indenting from " + firstTokenInRegion + " through " + lastTokenInRegion);
-            
-            int firstLineNumToReindent = firstTokenInRegion.getLine();
-            Token firstTokenOnFirstLineToAdjust = ast.findFirstTokenOnLine(firstLineNumToReindent);
-            if (firstTokenOnFirstLineToAdjust != firstTokenInRegion) firstLineNumToReindent++;
-            
-            Token firstTokenOnLineAfterReindentedRegion = findTokenStartingFirstNonemptyLineBelow(lastTokenInRegion.getLine());
-            //if (firstTokenOnLineAfterReindentedRegion != null) System.out.println("Below: " + firstTokenOnLineAfterReindentedRegion.getTerminal() + " - " + firstTokenOnLineAfterReindentedRegion.getText() + " - " + firstTokenOnLineAfterReindentedRegion.getCol() + ";");
-            
-            this.removeIndent = getIndentation(firstTokenOnFirstLineToAdjust);
-            this.addIndent = getIndentation(firstTokenOnLineAfterReindentedRegion);
-            
-            if (endsIndentedRegion(firstTokenOnLineAfterReindentedRegion))
-            {
-                Token firstTokenOnLineAboveReindentedRegion = findTokenStartingLastNonemptyLineAbove(firstTokenInRegion.getLine());
-                //if (firstTokenOnLineAboveReindentedRegion != null) System.out.println("Above: " + firstTokenOnLineAboveReindentedRegion.getTerminal() + " - " + firstTokenOnLineAboveReindentedRegion.getText() + " - " + firstTokenOnLineAboveReindentedRegion.getCol() + ";");
-
-                if (firstTokenOnLineAboveReindentedRegion != null && !startsIndentedRegion(firstTokenOnLineAboveReindentedRegion))
-                    this.addIndent = getIndentation(firstTokenOnLineAboveReindentedRegion);
-                else
-                    this.addIndent = addIndent + "    ";
-            }
-            
-            //System.out.println("Removing [" + removeIndent + "] and adding [" + addIndent + "]");
         }
 
         @Override public void visitToken(Token token)
@@ -175,24 +204,14 @@
             //System.out.println(token.getTerminal() + " - " + inFormatRegion + " - " + token.getLine());
         	
             if (inFormatRegion && (previousToken == null || token.getLine() > previousToken.getLine()))
-                updateIndentation(token, previousToken);
+                updateIndentation(token);
                 
             previousToken = token;
         }
 
-        private void updateIndentation(Token firstTokenOnLine, Token previousToken)
-        {
-            String whiteBeforeFirstTok = firstTokenOnLine.getWhiteBefore();
-            String currentIndentation = getIndentation(firstTokenOnLine);
-            if (!whiteBeforeFirstTok.endsWith(currentIndentation)) return;
-            String comments = whiteBeforeFirstTok.substring(0, whiteBeforeFirstTok.length()-currentIndentation.length());
-            //System.out.println("Reindenting [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
-            
-            firstTokenOnLine.setWhiteBefore(reindentedComments(comments) + newIndentation(currentIndentation));
-            //System.out.println("         to [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
-        }
+        protected abstract void updateIndentation(Token firstTokenOnLine);
 
-        private String reindentedComments(String comments)
+        protected String reindentedComments(String comments)
         {
             StringBuilder sb = new StringBuilder();
             for (String line : splitLines(comments))
@@ -235,7 +254,7 @@
             return newIndentation(indentation) + comment;
         }
 
-        private String newIndentation(String currentIndentation)
+        protected String newIndentation(String currentIndentation)
         {
             String newIndentation;
             if (currentIndentation.startsWith(removeIndent))
@@ -248,6 +267,100 @@
         }
     }
     
+    private final class ShiftBlockReindentingVisitor extends ReindentingVisitor
+    {
+        /**
+         * @param firstTokenInRegion
+         * @param lastTokenInRegion
+         */
+        protected ShiftBlockReindentingVisitor(Token firstTokenInRegion, Token lastTokenInRegion)
+        {
+            super(firstTokenInRegion, lastTokenInRegion);
+            
+            int firstLineNumToReindent = firstTokenInRegion.getLine();
+            Token firstTokenOnFirstLineToAdjust = ast.findFirstTokenOnLine(firstLineNumToReindent);
+            if (firstTokenOnFirstLineToAdjust != firstTokenInRegion) firstLineNumToReindent++;
+            
+            Token firstTokenOnLineAfterReindentedRegion = findTokenStartingFirstNonemptyLineBelow(lastTokenInRegion.getLine());
+            //if (firstTokenOnLineAfterReindentedRegion != null) System.out.println("Below: " + firstTokenOnLineAfterReindentedRegion.getTerminal() + " - " + firstTokenOnLineAfterReindentedRegion.getText() + " - " + firstTokenOnLineAfterReindentedRegion.getCol() + ";");
+            
+            this.removeIndent = getIndentation(firstTokenOnFirstLineToAdjust);
+            this.addIndent = getIndentation(firstTokenOnLineAfterReindentedRegion);
+            
+            if (endsIndentedRegion(firstTokenOnLineAfterReindentedRegion))
+            {
+                Token firstTokenOnLineAboveReindentedRegion = findTokenStartingLastNonemptyLineAbove(firstTokenInRegion.getLine());
+                //if (firstTokenOnLineAboveReindentedRegion != null) System.out.println("Above: " + firstTokenOnLineAboveReindentedRegion.getTerminal() + " - " + firstTokenOnLineAboveReindentedRegion.getText() + " - " + firstTokenOnLineAboveReindentedRegion.getCol() + ";");
+
+                if (firstTokenOnLineAboveReindentedRegion != null && !startsIndentedRegion(firstTokenOnLineAboveReindentedRegion))
+                    this.addIndent = getIndentation(firstTokenOnLineAboveReindentedRegion);
+                else
+                    this.addIndent = addIndent + "    ";
+            }
+            
+            //System.out.println("Removing [" + removeIndent + "] and adding [" + addIndent + "]");
+        }
+
+        protected void updateIndentation(Token firstTokenOnLine)
+        {
+            String whiteBeforeFirstTok = firstTokenOnLine.getWhiteBefore();
+            String currentIndentation = getIndentation(firstTokenOnLine);
+            if (!whiteBeforeFirstTok.endsWith(currentIndentation)) return;
+            String comments = whiteBeforeFirstTok.substring(0, whiteBeforeFirstTok.length()-currentIndentation.length());
+            //System.out.println("Reindenting [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
+            
+            firstTokenOnLine.setWhiteBefore(reindentedComments(comments) + newIndentation(currentIndentation));
+            //System.out.println("         to [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
+        }
+    }
+    
+    private final class ReindentEachLineReindentingVisitor extends ReindentingVisitor
+    {
+        private Token firstTokenOnPreviousLine;
+        private String indentationOfPreviousLine;
+        
+        /**
+         * @param firstTokenInRegion
+         * @param lastTokenInRegion
+         */
+        protected ReindentEachLineReindentingVisitor(Token firstTokenInRegion, Token lastTokenInRegion)
+        {
+            super(firstTokenInRegion, lastTokenInRegion);
+            
+            int firstLineNumToReindent = firstTokenInRegion.getLine();
+            Token firstTokenOnFirstLineToAdjust = ast.findFirstTokenOnLine(firstLineNumToReindent);
+            if (firstTokenOnFirstLineToAdjust != firstTokenInRegion) firstLineNumToReindent++;
+            
+            this.firstTokenOnPreviousLine = findTokenStartingLastNonemptyLineAbove(firstTokenInRegion.getLine());
+            this.indentationOfPreviousLine = getIndentation(firstTokenOnPreviousLine);
+            
+            this.removeIndent = indentationOfPreviousLine;
+            this.addIndent = getIndentation(firstTokenOnFirstLineToAdjust);
+        }
+
+        protected void updateIndentation(Token firstTokenOnLine)
+        {
+            String whiteBeforeFirstTok = firstTokenOnLine.getWhiteBefore();
+            String currentIndentation = getIndentation(firstTokenOnLine);
+            if (!whiteBeforeFirstTok.endsWith(currentIndentation)) return;
+            String comments = whiteBeforeFirstTok.substring(0, whiteBeforeFirstTok.length()-currentIndentation.length());
+            //System.out.println("Reindenting [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
+
+            this.removeIndent = currentIndentation;
+            this.addIndent = indentationOfPreviousLine;
+            if (startsIndentedRegion(firstTokenOnPreviousLine))
+                this.addIndent += "    ";
+            else if (endsIndentedRegion(firstTokenOnLine) && this.addIndent.endsWith("    "))
+                this.addIndent = this.addIndent.substring(0, this.addIndent.length()-4);
+
+            firstTokenOnLine.setWhiteBefore(reindentedComments(comments) + newIndentation(currentIndentation));
+            //System.out.println("         to [" + firstTokenOnLine.getWhiteBefore() + firstTokenOnLine.getText() + "]");
+            
+            this.firstTokenOnPreviousLine = firstTokenOnLine;
+            this.indentationOfPreviousLine = this.addIndent;
+        }
+    }
+
 	private String getIndentation(Token token)
 	{
 		String indent = token == null ? "" : token.getWhiteBefore();