/*::.
==================================================================================================================================
=================================================¦ Copyright © 2007 Allen Baker ¦=================================================
                                                 +------------------------------+
File:       JavaHtmlFile.java
Originator: Allen Baker (2007.09.07 18:48)
LayoutRev:  5
================================================================================================================================== */



/*.
==========================================================================================
Package
------------------------------------------------------------------------------------------ */
package cosmicabyss.com.lib;



/*.
==========================================================================================
Imports
------------------------------------------------------------------------------------------ */
import java.io.*;
import java.util.*;
import java.net.*;



/*::
======================================================================================================================== *//**
Instances of this class are html files containing syntax-colorized representations of java source code files.

<P>
   <DL>
      <DT>
         <B>
            Example usage:
         </B>
         <DD>
            <BLOCKQUOTE>
               <PRE id="unindent">
                  =========================================================================================
                  create a colorized html representation of the java source code found
                  in the file "../app/subs.java" and put the html into a file
                  named "../app/subs.java.html"
                  -----------------------------------------------------------------------------------------
                  JavaHtmlFile f = new JavaHtmlFile("../app/subs.java.html");
                  f.create();
               </PRE>
            </BLOCKQUOTE>
         </DD>
      </DT>
      <DT>
         <B>
            View Source:
         </B>
         <DD>
            <A href="JavaHtmlFile.java.html">
               JavaHtmlFile.java
            </A>
         </DD>
      </DT>
      <DT>
         <B>
            Author:
         </B>
         <DD>
            <A href="mailto:sourcecode.v01@cosmicabyss.com">
               Allen Baker
            </A>
         </DD>
      </DT>
   </DL>
*//*
======================================================================================================================== */
public class JavaHtmlFile extends TextFile
   {



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#000">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile(XFile xfile) throws Exception
      {
      super(xfile.getCanonicalPath());
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#001">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile(TextFile tfile) throws Exception
      {
      super(tfile.getCanonicalPath());
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#002">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile(JavaHtmlFile tfile) throws Exception
      {
      super(tfile.getCanonicalPath());
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#003">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile(URI uri)
      {
      super(uri);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#004">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile(File file) throws Exception
      {
      super(file.getCanonicalPath());
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#005">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type> JavaHtmlFile(File parent, Type child)
      {
      super(parent,child);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#006">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type> JavaHtmlFile(Type pathname)
      {
      super(pathname);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method creates an instance of the JavaHtmlFile class.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#007">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public <Type1,Type2> JavaHtmlFile(Type1 parent, Type2 child)
      {
      super(parent,child);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method generates and colorizes the html file.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#008">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile create() throws Exception
      {
      /*.
      ==========================================================================================
      This method makes no sense on directory files, this must be a normal file
      ------------------------------------------------------------------------------------------ */
      if (this.isDirectory()) return this;
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      XString  htmlFileName = new XString(this.getCanonicalPath());
      XString  javaFileName = new XString(this.getExtensionlessCanonicalPath());
      /*.
      ==========================================================================================
      Use Java2Html.exe to generate the first pass of the java.html file.
      ------------------------------------------------------------------------------------------ */
      XString  makeHtmlCmd = new XString("java2html -i " + javaFileName + " -o " + htmlFileName + " -d");
      boolean  returnCode  = (Util.runExternalProgram(makeHtmlCmd) == 0);
      if ( ! returnCode)
         {
         cOut.println(Const.WARNING,"HTML generation failed for: " + javaFileName);
         }
      /*.
      ==========================================================================================
      No do some modifications to the Java2Html.exe output
      ------------------------------------------------------------------------------------------ */
      this.modifyJava2HtmlOutput();
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method does additional processing of a file created by Java2Html.exe

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#009">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile modifyJava2HtmlOutput() throws Exception
      {
      /*.
      ==========================================================================================
      This method makes no sense on directory files, this must be a normal file
      ------------------------------------------------------------------------------------------ */
      if (this.isDirectory()) return this;
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      this.detabAndTrim();
      this.fixUp();
      this.extendColorization();
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method sets the ConsoleStream for this object.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#010">View source</A>

   @return
      A reference to this object

   @param
      pConsole is a ConsoleStream through which this objects sends its output.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile setOut(ConsoleStream pConsole)
      {
      cOut = pConsole;
      return this;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This boilerplate method is used for testing an instantiated object of this class and may include any
   code the developer chooses.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#011">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   public JavaHtmlFile test() throws Exception
      {
      cOut.titledPrintf
         (
         "\"HELLO WORLD!\"",
         "%s  %s  %s",
         "I'm an object of the", CLASS_NAME, "class, and I approved this message."
         );
      return this;
      }



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Protected  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Private  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*.
   ==========================================================================================
   Class Constants
      <BLOCKQUOTE>
         <PRE id="unindent">
            CLASS_NAME    : the name of this class
            DFLT_LINE_LEN : the default line length for word wrapping
            CHARQUOTE     : a quote character as it would be represented within a
                            character literal
            QUOTE         : a quote character as it would be represented within a
                            string
            ESCAPE        : an escape character as it would be represented within
                            a string
            TELETYPE      : a tag the delimits the syntax-colorized source code
                            section of an html file.
            TELETYPE_END  : a tag that terminates the syntax-colorized source code
                            section of an html file.
            OLD_GREEN     : the tag generated by the java2html tool to colorize a
                            segment of source code in a green color.
            OLD_RED       : the tag generated by the java2html tool to colorize a
                            segment of source code in a red color.
            OLD_BLUE      : the tag generated by the java2html tool to colorize a
                            segment of source code in a blue color.
            GREEN         : the tag I use to replace the java2html-tool-generated
                            green tag with a color more to my liking.
            RED           : the tag I use to replace the java2html-tool-generated
                            red tag with a color more to my liking.
            BLUE          : the tag I use to replace the java2html-tool-generated
                            blue tag with a color more to my liking.
            BRIGHT_RED    : the tag I use to colorize operators
            BLUE_GREEN    : the tag I use to colorize method names
            END_TAG       : a tag that terminates a colorize chunk of source code.
            END_TAG_LEN   : the size of END_TAG
            CMMT_TAG      : a tag that colorizes comments
            OPER_TAG      : a tag that colorizes operators
            BRCS_TAG      : a tag that colorizes braces
            TAG_LEN       : the size of any of the colorizing tags
            OPERATORS     : an XString containing all the valid operators(except
                            the &, <, and > chars)
            SEPARATORS        : an XString containing all the valid brace characters.
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private static final XString  CLASS_NAME    = new XString(JavaHtmlFile.class.getName());
   private static final int      DFLT_LINE_LEN = ConsoleMessage.defaultLineLength();

   private static final char     CHARQUOTE     = '\'';
   private static final char     QUOTE         = '\"';
   private static final char     ESCAPE        = '\\';

   private static final XString  TELETYPE      = new NCString("<TT>");
   private static final XString  TELETYPE_END  = new NCString("</TT>");

   private static final XString  OLD_GREEN     = new NCString("<font color=#009900>");
   private static final XString  OLD_RED       = new NCString("<font color=#990000>");
   private static final XString  OLD_BLUE      = new NCString("<font color=#0000FF>");

   private static final XString  GREEN         = new NCString("<font color=#92B8A0>");
   private static final XString  RED           = new NCString("<font color=#6A000E>");
   private static final XString  BLUE          = new NCString("<font color=#005080>");
   private static final XString  BRIGHT_RED    = new NCString("<font color=#AA0015>");
   private static final XString  BLUE_GREEN    = new NCString("<font color=#006054>");

   private static final XString  END_TAG       = new NCString("</font>");
   private static final int      END_TAG_LEN   = END_TAG.length();
   private static final XString  CMMT_TAG      = GREEN;
   private static final XString  OPER_TAG      = BRIGHT_RED;
   private static final XString  BRCS_TAG      = RED;
   private static final int      TAG_LEN       = CMMT_TAG.length();

   private static final XString  OPERATORS     = new XString("=!~?:&|+-*/^%");
   private static final XString  SEPARATORS    = new XString("{}[]");
   /*.
   ==========================================================================================
   Class variables
      <BLOCKQUOTE>
         <PRE id="unindent">
            cOut      : console output.
            cPeek     : a place to keep a look ahead string.
            cPeekChar : a place to keep a look ahead character.
         </PRE>
      </BLOCKQUOTE>
   ------------------------------------------------------------------------------------------ */
   private static ConsoleStream  cOut      = ConsoleStream.getSingleton();
   private static XString        cPeek     = XString.EMPTY;
   private static char           cPeekChar = '\0';
   /*.
   ==========================================================================================
   Instance variables
      iVarName : something or other
   ------------------------------------------------------------------------------------------ */



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method modifies some of the tags in a java2html-created file to make the resulting html of the
   source code more to my liking.

      1) It adds a background argument to the starting body tags so that the graph paper background is
         Present,

      2) it modifies the default syntax colors,

      3) it bolds all the text so that width differences between bolded characters and non-bolded
         Characters doesn't throw-off the layout of the the code, and

      4) it sets the font to be small and fixed-point.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#012">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private void fixUp() throws Exception
      {
      /*.
      ==========================================================================================
      Make substitutions to the java.html file to add a background, change the syntax colors,
      and set a fixed font size.
      ------------------------------------------------------------------------------------------ */
      XString[][]  oldSringNewStringPairs =
         {
            {OLD_GREEN                   , GREEN},   // replace green
            {OLD_RED                     , RED  },   // replace red
            {OLD_BLUE                    , BLUE },   // replace blue
            {new NCString("<body"   )    , new NCString("<body background=\"background.gif\"")},   // add background
            {new NCString("<PRE>"   )    , new NCString("<PRE><B>"                           )},   // bold everything
            {new NCString("</title>")    , new NCString("</title><style type=\"text/css\"><!--pre {font-size:7pt}--></style>" )},   // set fixed font size
            {hiddenString(":METH"   )    , new NCString("<A NAME=\"")},
            {hiddenString(":BOOK"   )    , new NCString("\"></A>")},
         };
      this.replace(oldSringNewStringPairs);
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method hides strings in this file from the running of the fixUp() method on this file.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#013">View source</A>

   @return
      Returns a properly assembled version of a string without mentioning that strings value as a
      literal that the fixUp() method would see and try to change.
   @param
      pStr is the hint to this method about which assembled string it should return.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private <Type> XString hiddenString(Type pStr)
      {
      XString  result = NCString.toNCString(pStr);
      if      (result.startsWith(":METH")) result = result.concat("OD:");
      else if (result.startsWith(":BOOK")) result = result.concat("MARK:");
      return result;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method enhancs the colorization of a java2html-created html file.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#014">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private void extendColorization() throws Exception
      {
      /*.
      ==========================================================================================
      We'll output the processed version of the file to a temp file so if the process fails
      midway through, we don't corrupt the original file
      ------------------------------------------------------------------------------------------ */
      File  iFile = new File(this.getCanonicalPath());
      File  oFile = File.createTempFile("Preprocess-",".tmp");
      /*.
      ==========================================================================================
      Process the file
      ------------------------------------------------------------------------------------------ */
      this.extendColorization
         (
         iFile.getCanonicalPath(),
         oFile.getCanonicalPath()
         );
      /*.
      ==========================================================================================
      Delete the original file
      ------------------------------------------------------------------------------------------ */
      if ( ! iFile.delete())
         {
         throw new Exception("Cannot delete " + iFile.getCanonicalPath());
         }
      /*.
      ==========================================================================================
      And replace it with the processed file.
      ------------------------------------------------------------------------------------------ */
      if ( ! oFile.renameTo(iFile))
         {
         throw new Exception("Cannot rename " + oFile.getCanonicalPath());
         }
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method enhancs the colorization of a java html file.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#015">View source</A>

   @param
      pFileIn is the name of the file that will be copied to the output file with the lines colorizeed.
      pFileOut must not be the same as pFileIn. PFileOut and pFileIn must not be null.
   @param
      pFileOut is the name that will be given to the file that is produced. PFileOut must not be the
      same as pFileIn. PFileOut and pFileIn must not be null.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   private <Type1,Type2> void extendColorization
      (
      Type1  pFileIn,
      Type2  pFileOut
      )
      throws Exception
      {
      /*.
      ==========================================================================================
      Check the parameters.
      ------------------------------------------------------------------------------------------ */
      if (pFileIn == null)
         {
         throw new Exception("pFileIn is null");
         }
      if (pFileOut == null)
         {
         throw new Exception("pFileOut is null");
         }
      if (pFileIn.equals(pFileOut))
         {
         throw new Exception("pFileIn and pFileOut are the same file");
         }
      /*.
      ==========================================================================================
      Set up the files
      ------------------------------------------------------------------------------------------ */
      XString            fileIn  = new XString(pFileIn);
      XString            fileOut = new XString(pFileOut);
      TextReaderIterator iter    = new TextReaderIterator(fileIn);
      TextWriter         output  = new TextWriter(fileOut);
      /*.
      ==========================================================================================
      Read and process each line of the input file
      ------------------------------------------------------------------------------------------ */
      XString  line = null;
      if (iter.hasNext())
         {
         /*.
         ==========================================================================================
         Skip past everything before the colorized source code section of the html file.
         ------------------------------------------------------------------------------------------ */
         while (true)
            {
            line = readAnotherLine(iter);
            output.println(line);
            if (line.containsIgnoreCase(TELETYPE)) break;
            }
         /*.
         ==========================================================================================
         Start doing additional colorizing on the colorized source code section of the html file.
         ------------------------------------------------------------------------------------------ */
         notInComment(iter,output,line);
         /*.
         ==========================================================================================
         Skip past everything after the colorized source code section of the html file.
         ------------------------------------------------------------------------------------------ */
         while (iter.hasNext())
            {
            line = readAnotherLine(iter);
            output.println(line);
            }
         }
      /*.
      ==========================================================================================
      Flush the output buffers
      ------------------------------------------------------------------------------------------ */
      output.flush();
      /*.
      ==========================================================================================
      Close the files
      ------------------------------------------------------------------------------------------ */
      output.close();
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method gets the next line and also sets the look ahead line and first look ahead character.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#016">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString readAnotherLine(TextReaderIterator pIter) throws Exception
      {
      XString  line = null;

      if (pIter.hasNext())
         {
         line = pIter.next();
         }
      if (pIter.hasNext())
         {
         cPeek     = pIter.peek().trim();
         if (cPeek.length() > 0)
            {
            cPeekChar = cPeek.charAt(0);
            }
         else
            {
            cPeek = XString.EMPTY;
            }
         }
      else
         {
         cPeek = XString.EMPTY;
         }
      return line;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method parses out non-comment segments of the sorce code section of the html file and enhances
   their colorization.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#017">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private void notInComment(TextReaderIterator pIter, TextWriter pOutput, XString pLine) throws Exception
      {
      while (true)
         {
         int  commentTokenIdx = pLine.indexOf(CMMT_TAG);
         /*.
         ==========================================================================================
         Not in a comment and not going into one on this line
         ------------------------------------------------------------------------------------------ */
         if (commentTokenIdx == (-1))
            {
            XString  colorizedChunk = pLine;
            colorizedChunk = colorizeMethodNames(colorizedChunk);
            colorizedChunk = colorizeChunk(colorizedChunk);

            pOutput.println(colorizedChunk);

            if ( ! pIter.hasNext()) return;
            pLine = readAnotherLine(pIter);
            }
         /*.
         ==========================================================================================
         Not in a comment but going into one on this line
         ------------------------------------------------------------------------------------------ */
         else
            {
            XString  nonCommentChunk = pLine.substring(0,commentTokenIdx);
            int      commentChunkIdx = commentTokenIdx+TAG_LEN;

            XString  colorizedChunk  = nonCommentChunk;
            cPeekChar      = '\0';
            colorizedChunk = colorizeMethodNames(colorizedChunk);
            colorizedChunk = colorizeChunk(colorizedChunk);

            pOutput.print(colorizedChunk);
            pOutput.print(CMMT_TAG);

            if (commentChunkIdx < pLine.length())
               {
               pLine = pLine.substring(commentChunkIdx);
               pLine = inComment(pIter,pOutput,pLine);
               if (pLine == null) return;
               }
            else if (pIter.hasNext())
               {
               pOutput.println();
               pLine = readAnotherLine(pIter);
               pLine = inComment(pIter,pOutput,pLine);
               if (pLine == null) return;
               }
            else
               {
               return;
               }
            }
         }
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method parses out comment segments of the sorce code section of the html file and skips past
   them.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#018">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString inComment(TextReaderIterator pIter, TextWriter pOutput, XString pLine) throws Exception
      {
      while (true)
         {
         int  endTokenIdx = pLine.indexOf(END_TAG);
         /*.
         ==========================================================================================
         In a comment and not getting out of it on this line
         ------------------------------------------------------------------------------------------ */
         if (endTokenIdx == (-1))
            {
            pOutput.println(pLine);
            if ( ! pIter.hasNext()) return null;
            pLine = readAnotherLine(pIter);
            }
         /*.
         ==========================================================================================
         In a comment but getting out of it on this line
         ------------------------------------------------------------------------------------------ */
         else
            {
            XString  commentChunk       = pLine.substring(0,endTokenIdx);
            int      nonCommentChunkIdx = endTokenIdx+END_TAG_LEN;
            pOutput.print(commentChunk);
            pOutput.print(END_TAG);
            if (nonCommentChunkIdx < pLine.length())
               {
               cPeekChar = '\0';
               return pLine.substring(nonCommentChunkIdx);
               }
            else if (pIter.hasNext())
               {
               pOutput.println();
               return readAnotherLine(pIter);
               }
            else
               {
               return null;
               }
            }
         }
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method enhances the colorization of a chunk of the html file.

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#019">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString colorizeChunk(XString pChunk)
      {
      /*.
      ==========================================================================================
      Hide the html character entities so the search for operators doesn't treat the delimiting
      '&' as an operator
      ------------------------------------------------------------------------------------------ */
      pChunk = pChunk.replace("&amp;" , "<_AMP_AMP_COLON_>");
      pChunk = pChunk.replace("&gt;"  , "<_AMP_GT_COLON_>" );
      pChunk = pChunk.replace("&lt;"  , "<_AMP_LT_COLON_>" );
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      StringBuffer  buffer = new StringBuffer(pChunk.length() + ((TAG_LEN + END_TAG_LEN)*6) );
      char[]        chars  = pChunk.toCharArray();
      int           i      = 0;
      char          prevC  = '\0';
      char          thisC  = '\0';
      while (i < chars.length)
         {
         prevC = thisC;
         thisC = chars[i++];
         /*.
         ==========================================================================================
         If we've encountered a separator, colorize it.
         ------------------------------------------------------------------------------------------ */
         if (SEPARATORS.containsChar(thisC))
            {
            buffer.append(RED).append(thisC).append(END_TAG);
            }
         /*.
         ==========================================================================================
         If its the start of a tag, read and write the entire tag without colorizing
         ------------------------------------------------------------------------------------------ */
         else if (thisC == '<')
            {
            buffer.append(thisC);
            while (i < chars.length)
               {
               prevC = thisC;
               thisC = chars[i++];
               buffer.append(thisC);
               if (thisC == '>') break;
               }
            }
         /*.
         ==========================================================================================
         If its the start of a string, read and write the entire string without colorizing
         ------------------------------------------------------------------------------------------ */
         else if (isStringDelimiter(thisC, prevC))
            {
            buffer.append(thisC);
            StringBuffer  accumulator = new StringBuffer();
            while (i < chars.length)
               {
               prevC = thisC;
               thisC = chars[i++];
               accumulator.append(thisC);
               if (isStringDelimiter(thisC, prevC)) break;
               }
            /*.
            ==========================================================================================
            These gyrations prevent &, <, and > in strings from being colored as operators.
            ------------------------------------------------------------------------------------------ */
            XString  accumulatedString = new XString(accumulator);
            accumulatedString = accumulatedString.replace("<_AMP_AMP_COLON_>" , "&amp;");
            accumulatedString = accumulatedString.replace("<_AMP_GT_COLON_>"  , "&gt;" );
            accumulatedString = accumulatedString.replace("<_AMP_LT_COLON_>"  , "&lt;" );
            buffer.append(accumulatedString);
            }
         /*.
         ==========================================================================================
         If its the start of a char literal, read and write the entire char literal without
         colorizing
         ------------------------------------------------------------------------------------------ */
         else if (isCharLiteralDelimiter(thisC, prevC))
            {
            buffer.append(thisC);
            StringBuffer  accumulator = new StringBuffer();
            while (i < chars.length)
               {
               prevC = thisC;
               thisC = chars[i++];
               accumulator.append(thisC);
               if (isCharLiteralDelimiter(thisC, prevC)) break;
               }
            /*.
            ==========================================================================================
            These gyrations prevent &, <, and > in char literals from being colored as operators.
            ------------------------------------------------------------------------------------------ */
            XString  accumulatedCharLiteral = new XString(accumulator);
            accumulatedCharLiteral = accumulatedCharLiteral.replace("<_AMP_AMP_COLON_>" , "&amp;");
            accumulatedCharLiteral = accumulatedCharLiteral.replace("<_AMP_GT_COLON_>"  , "&gt;" );
            accumulatedCharLiteral = accumulatedCharLiteral.replace("<_AMP_LT_COLON_>"  , "&lt;" );
            buffer.append(accumulatedCharLiteral);
            }
         /*.
         ==========================================================================================
         If we've encountered an operator, colorize it.
         ------------------------------------------------------------------------------------------ */
         else if (OPERATORS.containsChar(thisC))
            {
            buffer.append(BRIGHT_RED).append(thisC).append(END_TAG);
            }
         /*.
         ==========================================================================================
         Otherwise, we've encountered something that does not need colorizing.
         ------------------------------------------------------------------------------------------ */
         else
            {
            buffer.append(thisC);
            }
         }
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      XString  result = new XString(buffer);
      /*.
      ==========================================================================================
      Unhide the character entities now and colorize them in their entirety as operators.
      ------------------------------------------------------------------------------------------ */
      result = result.replace("<_AMP_AMP_COLON_>" , BRIGHT_RED + "&amp;" + END_TAG );
      result = result.replace("<_AMP_GT_COLON_>"  , BRIGHT_RED + "&gt;"  + END_TAG );
      result = result.replace("<_AMP_LT_COLON_>"  , BRIGHT_RED + "&lt;"  + END_TAG );
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      return result;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method finds and colorizes method names

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#020">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private XString colorizeMethodNames(XString pChunk)
      {
      /*.
      ==========================================================================================
      Hide the html character entities so they don't mess up the search for method names
      ------------------------------------------------------------------------------------------ */
      pChunk = pChunk.replace("&amp;" , "<_AMP_AMP_COLON_>");
      pChunk = pChunk.replace("&gt;"  , "<_AMP_GT_COLON_>" );
      pChunk = pChunk.replace("&lt;"  , "<_AMP_LT_COLON_>" );
      /*.
      ==========================================================================================
      ------------------------------------------------------------------------------------------ */
      StringBuffer  buffer = new StringBuffer(pChunk.length() + ((TAG_LEN + END_TAG_LEN)*6) );
      char[]        chars  = pChunk.toCharArray();
      int           i      = chars.length;
      char          thisC  = '\0';
      int           begin  = 0;
      int           end    = 0;
      boolean       found  = false;
      /*.
      ==========================================================================================
      Handle the situation where the open paren is on the next line and not in this chunk
      ------------------------------------------------------------------------------------------ */
      if (cPeekChar == '(')
         {
         /*.
         ==========================================================================================
         Skip any whitespace between the method name and the open paren
         ------------------------------------------------------------------------------------------ */
         while ((i > 0) && (Character.isWhitespace(chars[i-1])))
            {
            i--;
            }
         end = i;
         cPeekChar = '\0';
         while (i > 0)
            {
            thisC = chars[--i];
            begin = i;
            while (i > 0)
               {
               thisC = chars[--i];
               if ( ! Character.isJavaIdentifierPart(thisC))
                  {
                  begin = i + 1;
                  break;
                  }
               }
            if (begin != end)
               {
               found = true;
               XString  prefix = pChunk.substring(0,begin);
               XString  method = pChunk.substring(begin,end);
               XString  remain = pChunk.substring(end,pChunk.length());
               buffer.append(colorizeMethodNames(prefix)).append(BLUE_GREEN).append(method).append(END_TAG).append(remain);
               break;
               }
            }
         }
      /*.
      ==========================================================================================
      Else handle the normal situation where only chars in this chunk are looked at
      ------------------------------------------------------------------------------------------ */
      else while (i > 0)
         {
         thisC = chars[--i];
         /*.
         ==========================================================================================
         Skip past strings and char literals
         ------------------------------------------------------------------------------------------ */
         if (isStringDelimiter(thisC, chars[i]))
            {
            while (i > 0)
               {
               thisC = chars[--i];
               if (isStringDelimiter(thisC, chars[i])) break;
               }
            }
         if (isCharLiteralDelimiter(thisC, chars[i]))
            {
            while (i > 0)
               {
               thisC = chars[--i];
               if (isCharLiteralDelimiter(thisC, chars[i])) break;
               }
            }
         else if (thisC == '(')
            {
            /*.
            ==========================================================================================
            Skip any whitespace between the method name and the open paren
            ------------------------------------------------------------------------------------------ */
            while ((i > 0) && (Character.isWhitespace(chars[i-1])))
               {
               i--;
               }
            begin = i;
            end   = i;
            while (i > 0)
               {
               thisC = chars[--i];
               if ( ! Character.isJavaIdentifierPart(thisC))
                  {
                  begin = i + 1;
                  break;
                  }
               }
            if (begin != end)
               {
               found = true;
               XString  prefix = pChunk.substring(0,begin);
               XString  method = pChunk.substring(begin,end);
               XString  remain = pChunk.substring(end,pChunk.length());
               buffer.append(colorizeMethodNames(prefix)).append(BLUE_GREEN).append(method).append(END_TAG).append(remain);
               break;
               }
            }
         }
      /*.
      ==========================================================================================
      Put things back the way they're supposed to be and return.
      ------------------------------------------------------------------------------------------ */
      XString result = found? new XString(buffer) : pChunk;
      result = result.replace("<_AMP_AMP_COLON_>" , "&amp;");
      result = result.replace("<_AMP_GT_COLON_>"  , "&gt;" );
      result = result.replace("<_AMP_LT_COLON_>"  , "&lt;" );
      return result;
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method decides if the two character combination implied by the parameters is a string delimiter
   (single quote) or not (an escaped quote)

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#021">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private boolean isStringDelimiter(char pThisC, char pPrevC)
      {
      return ((pThisC == QUOTE) && (pPrevC != ESCAPE));
      }



   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method decides if the two character combination implied by the parameters is a char literal
   delimiter (single quote) or not (an escaped quote)

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#022">View source</A>

   *//*
   ---------------------------------------------------------------------------------------------------- */
   private boolean isCharLiteralDelimiter(char pThisC, char pPrevC)
      {
      return ((pThisC == CHARQUOTE) && (pPrevC != ESCAPE));
      }



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Inner Classes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Public Static Methods  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */


   /*:                                    
   ====================================================================================================
   [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
   ==================================================================================================== *//**
   This method allows this class file to be unit tested as a standalone application. It's the method
   that's called when the class is invoked from the command line by using the java application launcher
   - "java". Main() is not a required method, but the practice of putting one in each class and
   wrapping class test code within it allows easy unit testing of the class; and main does not need to
   be removed when testing is complete.

   <P>
      <DL>
         <DT>
            <B>
               Command line usage:
            </B>
            <DD>
               Java cosmicabyss.com.lib.JavaHtmlFile
            </DD>
         </DT>
      </DL>

   <P><B>Implementation: </B><A HREF="JavaHtmlFile.java.html#023">View source</A>

   @param
      pArgs contains the command line arguments with which this class was invoked as an application.
   *//*
   ---------------------------------------------------------------------------------------------------- */
   public static void main(String[] pArgs) throws Exception
      {
      /*.
      ==========================================================================================
      Greetings !
      ------------------------------------------------------------------------------------------ */
      cOut.banner(CLASS_NAME);
      /*.
      ==========================================================================================
      Create a colorized html representation of the java source code found in the file
      "../app/subs.java" and put the html into a file named "../app/subs.java.html"
      ------------------------------------------------------------------------------------------ */
      JavaHtmlFile f = new JavaHtmlFile("../app/subs.java.html");
      f.create();
      }



   }  // class JavaHtmlFile



   /*:.
   ==============================================================================================================
   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@[  Notes  ]@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   ============================================================================================================== */