/* Copyright (C) 2003 Shayne Steele * License and warranty are under the terms of the GNU General Public License * Version 2.0. See http://www.gnu.org for license and warranty details. */ /** Java2xhtml.java Version 0.9 * Produces an XHTML file from Java source code with syntax highlighting, * includes additional options (line numbering, tab spacing, etc.) *

* NOTE: Common java naming structure is assumed * Capitalize the first letter that appears in a class or interface name * Use lowercase for the first letter in a method or variable name * Use only uppercase letters when naming constants * * @version 0.9, March 2003 * @author Shayne Steele */ package gnu.classpath.tools.java2xhtml; import java.io.*; import java.util.*; public class Java2xhtml { // parse the command line arguments // give a decent responce for bad input // call the HTMLifier on good input public static void main(String args[]) { // parse the invokation arguments if (args.length < 1 || args.length > 3) // invoked program incorrectly { System.out.println("Java2xhtml Version 0.9 (C) 2003 Shayne Steele"); System.out.println(" Produces an XHTML file of Java source" + " code with syntax highlighting,"); System.out.println(" includes additional options " + "(line numbering, tab spacing, etc.)"); System.out.println(" License and warranty are under the terms " + "of the GNU General Public License"); System.out.println(" (GPL) Version 2.0"); System.out.println(" See http://www.gnu.org for license and " + "warranty details."); System.out.println(" NOTE: Common java naming structure is " + "assumed"); System.out.println(""); System.out.println("USAGE:"); System.out.println("java [java options] Java2xhtml " + "source.java [options file] " + "[output file]"); System.out.println(""); System.out.println(" - java is the name of the Java interpreter"); System.out.println(" - [java options] are the optional options " + "of the Java interpreter"); System.out.println(" - Java2xhtml is the name of this " + "application"); System.out.println(" - source is a file or the directory to the " + "Java source file(s)"); System.out.println(" - [options file] is the optional " + "path of a file with"); System.out.println(" a structure like this:"); System.out.println(" externalStyleSheetName=file_name" + " (default style.css)"); System.out.println(" tabSize=integer (default value is 4)"); System.out.println(" extraIndentation=integer " + "(default value is 0)"); System.out.println(" lineModulus=integer (default value 5)"); System.out.println(" isCodeSnippet=boolean" + " (default false)"); System.out.println(" isXHTML_1_1=boolean" + " (default true)"); System.out.println(" hasInternalStyleSheet=boolean" + " (default true)"); System.out.println(" hasExternalStyleSheet=boolean" + " (default true)"); System.out.println(" hasTitle=boolean" + " (default false)"); System.out.println(" hasLegend=boolean" + " (default false)"); System.out.println(" hasAllBoldSourceCode=boolean" + " (default false)"); System.out.println(" hasLineNumbers=boolean" + " (default false)"); System.out.println(" hasLineModulusDrawnLines=boolean" + " (default false)"); System.out.println(" hasLineModulusCodeBlocks=boolean" + " (default false)"); System.out.println(" hasFooter=boolean" + " (default false)"); System.out.println(" hasFooterIcons=boolean" + " (default false)"); System.out.println(" hasFooterDate=boolean" + " (default true)"); System.out.println(" NOTE: filename must end with '.prop'"); System.out.println(" Default [options file] is " + "options.prop"); System.out.println(" - [output file] is name of the XHTML file " + "that is produced"); System.out.println(" Default [output file] is source_java.html"); System.out.println(""); System.out.println("Output: source.java --> [output file]"); System.out.println(" Default Output is "); System.out.println(" source.java --> source_java.html"); System.out.println(""); System.out.println("Examples of calling the program:"); System.out.println(" process one file (say Java2xhtml.java):"); System.out.println(" java Java2xhtml Java2xhtml.java"); System.out.println(" process one directory (say C:\\HOME):"); System.out.println(" java Java2xhtml C:\\HOME"); System.out.println(" process one directory (say C:\\HOME with a " + "given options file (options.prop)):"); System.out.println(" java Java2xhtml C:\\HOME options.prop"); } else { // invoked program correctly, now get command line arguments // get the source file name String sourceName; sourceName = args[0]; // make sure that the source file exist and if so HTMLify it File sourceFilePath = new File(sourceName); if (sourceFilePath.exists()) { // good pathname so HTMLify it // get the default html options file name String propertiesFileName = "options.prop"; // create a unique default html file name, // bubba.java -> bubba_java.html String htmlFileName = sourceName.replace('.', '_') + ".html"; if (args.length == 2 || args.length == 3) { if (args[1].endsWith(".prop")) { // get the user supplied html options file name propertiesFileName = args[1]; } else { // get the user supplied html outputfile name htmlFileName = args[1]; } } if (args.length == 3) { if (args[2].endsWith(".prop")) { // get the user supplied html options file name propertiesFileName = args[2]; } else { // get the user supplied html outputfile name htmlFileName = args[2]; } } new Java2xhtml(propertiesFileName, sourceFilePath, htmlFileName); } else // source file does not exist, print message and exit normally { System.out.println("The source parameter must be an existent" + " file or directory"); System.out.println("Run Java2xHtml without parameters for " + "help"); } } } // collect various sets of keywords static Collection keywordCollection; static Collection primitiveTypeCollection; static Collection primitiveLiteralCollection; static Collection javadocTagCollection; // all these variables are changeable by a options file int extraIndentation = 0; int tabSize = 4; int lineModulus = 5; boolean hasLegend = false; boolean hasLineNumbers = false; boolean hasLineModulusDrawnLines = false; boolean hasLineModulusCodeBlocks = false; boolean hasFooter = false; boolean hasFooterIcons = false; boolean hasFooterDate = true; boolean isCodeSnippet = false; boolean isXHTML_1_1 = true; boolean hasTitle = false; boolean hasAllBoldSourceCode = false; boolean hasInternalStyleSheet = true; boolean hasExternalStyleSheet = true; String externalStyleSheetName = "style.css"; static { // collection type is Hashset for unique elements and fast retieval String keywordArray[] = { "abstract", "default", "if", "private", "do", "implements", "protected", "throws", "break", "import", "public", "transient", "else", "instanceof", "return", "try", "case", "extends", "throw", "static", "catch", "final", "interface", "while", "volatile", "finally", "super", "synchronized", "class", "native", "switch", "package", "const", "for", "new", "goto", "continue", "this", "assert", "strictfp" }; keywordCollection = new HashSet(Arrays.asList(keywordArray)); String primitiveTypeArray[] = { "boolean", "char", "byte", "short", "int", "long", "float", "double", "void" }; primitiveTypeCollection = new HashSet(Arrays.asList(primitiveTypeArray)); String primitiveLiteralArray[]= { "false", "null", "true" }; primitiveLiteralCollection = new HashSet(Arrays.asList(primitiveLiteralArray)); String javadocTagArray[]= { "see", "author", "version", "param", "return", "exception", "deprecated", "throws", "link", "since", "serial", "serialField","serialData", "beaninfo" }; javadocTagCollection = new HashSet(Arrays.asList(javadocTagArray)); } public Java2xhtml() { } // create the various keyword collections // parse the html options file Java2xhtml(String propertiesFileName, File sourceFilePath, String htmlFileName) { // get html properties (use defaults if necessary) File propertiesFilePath = new File (propertiesFileName); if (propertiesFilePath.exists()) { // html properies file exist try parsing it try { InputStream propertiesFile = new FileInputStream(propertiesFileName); Properties htmlProperties = new Properties(); htmlProperties.load(propertiesFile); propertiesFile.close(); setProperties(htmlProperties); } catch (IOException exception) { System.out.println(exception); } } if (sourceFilePath.isFile()) { // process the file processFile(sourceFilePath, htmlFileName); } else if (sourceFilePath.isDirectory()) { // process a directory File [] sourceFilePathArray = sourceFilePath.listFiles(); for (int i = 0; i < sourceFilePathArray.length; i++) { if (((sourceFilePathArray[i]).getName()).endsWith(".java")) { // process each file that ends in .java // create a unique default html file name, // bubba.java -> bubba_java.html htmlFileName = ((sourceFilePathArray[i]).getName()).replace( '.', '_') + ".html"; processFile(sourceFilePathArray[i], htmlFileName); } } } } public void setProperties(Properties htmlProperties) { hasLegend = Boolean.valueOf(htmlProperties.getProperty("hasLegend", "false")).booleanValue(); extraIndentation = Integer.parseInt(htmlProperties.getProperty("extraIndentation", "0")); tabSize = Integer.parseInt(htmlProperties.getProperty("tabSize", "4")); hasLineNumbers = Boolean.valueOf(htmlProperties.getProperty("hasLineNumbers", "false")).booleanValue(); lineModulus = Integer.parseInt(htmlProperties.getProperty("lineModulus", "5")); hasLineModulusDrawnLines = Boolean.valueOf(htmlProperties.getProperty("hasLineModulusDrawnLines", "false")).booleanValue(); hasLineModulusCodeBlocks = Boolean.valueOf(htmlProperties.getProperty("hasLineModulusCodeBlocks", "false")).booleanValue(); hasFooter = Boolean.valueOf(htmlProperties.getProperty("hasFooter", "false")).booleanValue(); hasFooterIcons = Boolean.valueOf(htmlProperties.getProperty("hasFooterIcons", "false")).booleanValue(); hasFooterDate = Boolean.valueOf(htmlProperties.getProperty("hasFooterDate", "true")).booleanValue(); isXHTML_1_1 = Boolean.valueOf(htmlProperties.getProperty("isXHTML_1_1", "true")).booleanValue(); isCodeSnippet = Boolean.valueOf(htmlProperties.getProperty("isCodeSnippet", "false")).booleanValue(); hasTitle = Boolean.valueOf(htmlProperties.getProperty("hasTitle", "false")).booleanValue(); hasAllBoldSourceCode = Boolean.valueOf(htmlProperties.getProperty("hasAllBoldSourceCode", "false")).booleanValue(); hasInternalStyleSheet = Boolean.valueOf(htmlProperties.getProperty("hasInternalStyleSheet", "true")).booleanValue(); hasExternalStyleSheet = Boolean.valueOf(htmlProperties.getProperty("hasExternalStyleSheet", "true")).booleanValue(); externalStyleSheetName = htmlProperties.getProperty("externalStyleSheetName", "style.css"); } // read the file and put it into a stringbuffer void processFile(File sourceFilePath, String htmlFileName) { // open the file, copy it to a Stringbuffer , process into an // HTMLified String and convert result into an HTML file try { BufferedReader sourceReader = new BufferedReader(new FileReader(sourceFilePath)); StringBuffer bufferIn = new StringBuffer(); int readInInt = 0; char presentChar = 0; // copy file into a Stringbuffer while (readInInt != -1) // -1 value means end of stream/file { // put the file into a Stringbuffer readInInt= sourceReader.read(); presentChar = ((readInInt >= 0) ? (char) readInInt : 0); bufferIn.append(presentChar); } sourceReader.close(); BufferedWriter tempBufferedWriter = new BufferedWriter(new FileWriter(htmlFileName)); tempBufferedWriter.write(makeHTML(bufferIn, sourceFilePath.getName())); tempBufferedWriter.close(); System.out.println(sourceFilePath.getName() + " --> " + htmlFileName); } catch (IOException exception) { System.out.println(exception); } } // constant 'States' java source code can be in public final static class State { public final static State TEXT = new State(); public final static State IMPORT_NAME = new State(); public final static State PARAM_VARIABLE = new State(); public final static State JAVADOC = new State(); public final static State PACKAGE_NAME = new State(); public final static State DOUBLE_QUOTE = new State(); public final static State SINGLE_QUOTE = new State(); public final static State TRADITIONAL_COMMENT = new State(); public final static State LINE_COMMENT = new State(); // empty constructor private State() { // empty body } } // Convert java source code StringBufffer into colorized (and tab spaced) // HTML String . // Assumes that Java naming convention is used // Uses a very basic state machine design. public String makeHTML(StringBuffer bufferIn, String sourceFileName) { int codeLineNumber = 0; boolean isNewLine = true; boolean isNewBlock = true; int identifierLength = 0; int qualifiedIdentifierLength = 0; int presentIndex = -1; int spaceLength = 0; int saveIndex = 0; char presentChar = 0; State presentState = State.TEXT; StringBuffer bufferOut = new StringBuffer(); if (!isCodeSnippet) { bufferOut.append("\r\n"); if (isXHTML_1_1) { bufferOut.append("\r\n"); bufferOut.append("\r\n"); } else { bufferOut.append("\r\n"); bufferOut.append("\r\n"); } bufferOut.append(" \r\n"); bufferOut.append(" \r\n"); bufferOut.append(" " + sourceFileName + "\r\n"); bufferOut.append(" \r\n"); bufferOut.append(" \r\n"); if (hasInternalStyleSheet) { bufferOut.append(" \r\n"); } if (hasExternalStyleSheet) { bufferOut.append(" \r\n"); } bufferOut.append(" \r\n"); bufferOut.append(" \r\n"); } if (hasTitle) { bufferOut.append("

\r\n"); bufferOut.append(" " + sourceFileName + "\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); } if (hasLegend) { bufferOut.append("
\r\n"); bufferOut.append(" Legend\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); bufferOut.append(" "); bufferOut.append("keyword\r\n"); bufferOut.append(" "); bufferOut.append("method\r\n"); bufferOut.append(" variable" + "\r\n"); bufferOut.append(" " + "singleLineComment\r\n"); bufferOut.append(" " + "traditionalComment\r\n"); bufferOut.append(" " + "javadocComment\r\n"); bufferOut.append(" javadocTag" + "\r\n"); bufferOut.append(" " + "importName\r\n"); bufferOut.append(" " + "packageName\r\n"); bufferOut.append(" " + "primitiveType\r\n"); bufferOut.append(" " + "nonPrimitiveType\r\n"); bufferOut.append(" " + "constructor\r\n"); bufferOut.append(" " + "constant\r\n"); bufferOut.append(" " + "doubleQuote\r\n"); bufferOut.append(" " + "singleQuote\r\n"); bufferOut.append(" " + "numericalLiteral\r\n"); bufferOut.append(" " + "primitiveLiteral\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); } bufferOut.append("
\r\n"); if (hasLineModulusCodeBlocks) { bufferOut.append("
\r\n");
        }
        else
        {
            bufferOut.append("
\r\n");
        }
        // process the input Java code Stringbuffer
        // subtract 2 from the bufferIn.length() to get EOF marker
        while (presentIndex++ != (bufferIn.length() - 2))
        {
            for (int i = 0; i < extraIndentation; i++)
            {
                bufferOut.append(" ");
            }
            if ((hasLineNumbers || hasLineModulusCodeBlocks) && isNewLine)
            {
                // add line numbers if desired
                // line numbers are 1 - 9999 then rotate line numbers
                codeLineNumber = (++codeLineNumber)%10000;
                if ((lineModulus > 0) && hasLineModulusCodeBlocks && 
                    (codeLineNumber%lineModulus == 1))
                {
                    if (isNewBlock)
                    {
                        if ((State.TRADITIONAL_COMMENT == presentState) ||
                            (State.JAVADOC == presentState))
                        {
                                bufferOut.insert((bufferOut.length() - 
                                                  ("\r\n").length()), 
                                                 "");
                        }
                        bufferOut.append("
\r\n"); bufferOut.append("
"); bufferOut.append("\r\n
\r\n");
                        if (State.TRADITIONAL_COMMENT == presentState)
                        {
                            bufferOut.append("");
                        }
                        if (State.JAVADOC == presentState)
                        {
                            bufferOut.append("");
                        }
                    }
                    isNewBlock = !isNewBlock;
                }
                // make straight columns of line numbers
                if (codeLineNumber < 1000)
                {
                    bufferOut.append(" ");
                }
                if (codeLineNumber < 100)
                {
                    bufferOut.append(" ");
                }
                if (codeLineNumber < 10)
                {
                    bufferOut.append(" ");
                }
                bufferOut.append("");

                if (hasLineNumbers)
                {
                    if ((lineModulus > 0) && (codeLineNumber%lineModulus == 0))
                    {
                        bufferOut.append("");
                        bufferOut.append(codeLineNumber);
                        bufferOut.append(": ");
                        if (hasLineModulusDrawnLines)
                        {
                            // compute spaceLength so a line can be drawn
                            while ((presentIndex != (bufferIn.length() - 1)) &&
                                   ((Character.isSpaceChar(
                                     bufferIn.charAt(presentIndex))) ||
                                    (bufferIn.charAt(presentIndex) == '\t')))
                            {
                                // for each tab, insert tabSize spaces 
                                if (bufferIn.charAt(presentIndex) == '\t')
                                {
                                    for (int i = 0; i < tabSize; i++)
                                    {
                                        bufferIn.insert(presentIndex + 1, " ");
                                    }
                                    presentIndex++;
                                    continue;
                                }
                                if (' ' == bufferIn.charAt(presentIndex))
                                {
                                    // read a space so place a space
                                    bufferOut.append(" ");
                                    spaceLength += (" ").length();
                                }
                                else
                                {
                                    // a white space character was read
                                    bufferOut.append(bufferIn.charAt(
                                        presentIndex));
                                    ++spaceLength;
                                }
                                presentIndex++;
                            }
                            // check if line is empty 
                            // (no printable characters on line)
                            if ((presentIndex == (bufferIn.length() - 1)) ||
                                (Character.isWhitespace(bufferIn.charAt(
                                     presentIndex))))
                            {
                                spaceLength = 0;
                            }
                            // draw the line
                            if (spaceLength > 1)
                            {
                                bufferOut.insert((bufferOut.length() - 
                                                  spaceLength), "");
                                bufferOut.insert((bufferOut.length() - 
                                                  (" ").length()), "");
                            }
                            spaceLength = 0;
                        }
                    }
                    else 
                    {
                        // line numbers are in lineNumberColor 
                        bufferOut.append("");
                        bufferOut.append(codeLineNumber);
                        bufferOut.append(": ");
                    }
                }
                isNewLine = false;
            }
            // a state machine
            presentChar = bufferIn.charAt(presentIndex);
            if ((Character.isJavaIdentifierPart(presentChar)) ||
                ((State.IMPORT_NAME == presentState) && (presentChar == '*')))
            {
                // this is an identifier
                bufferOut.append(presentChar);
                identifierLength++;
                continue; // keep adding characters until identifier is done
            } 
            if (identifierLength > 0)
            {
                // identifier
                qualifiedIdentifierLength = 
                    qualifiedIdentifierLength + identifierLength;
                if (bufferIn.charAt(presentIndex) == '.')
                {
                    // qualified identifier 
                    bufferOut.append(presentChar);
                    qualifiedIdentifierLength++;
                    identifierLength = 0;
                    continue;  // keep adding characters to qualified identifier
                }
                String identifier = 
                    bufferOut.toString().substring(bufferOut.length() - 
                                                   identifierLength);
                if ((State.PARAM_VARIABLE == presentState))
                {
                    // any identifier after a param in a javadoc is assumed to
                    // be a variable 
                    bufferOut.insert(bufferOut.length() -
                                     qualifiedIdentifierLength,
                                     "");
                    bufferOut.append("");
                    presentState = State.JAVADOC;
                }
                else if (State.JAVADOC == presentState)
                {
                    // in javadoc state 
                    if ((javadocTagCollection.contains(identifier)) &&
                        (bufferIn.charAt(presentIndex - 
                                         (identifierLength + 1)) == '@'))
                    {
                        // identifier is a javadocTag
                        bufferOut.insert(bufferOut.length() - identifierLength,
                                         "");
                        bufferOut.append("");
                        if (("param").equals(identifier))
                        {
                            // any identifier after a param is assumed to
                            // be a variable, get into a state to do this 
                            presentState = State.PARAM_VARIABLE;
                        }
                    }
                }
                else if (State.IMPORT_NAME == presentState)
                {
                    // import identifier
                    bufferOut.insert(bufferOut.length() - 
                                     qualifiedIdentifierLength,
                                     "");
                    bufferOut.append("");
                    presentState = State.TEXT;
                }
                else if (State.PACKAGE_NAME == presentState)
                {
                    // package identifier
                    bufferOut.insert(bufferOut.length() - 
                                     qualifiedIdentifierLength,
                                     "");
                    bufferOut.append("");
                    presentState = State.TEXT;
                }
                else if (State.TEXT == presentState)
                {
                    if (keywordCollection.contains(identifier))
                    {
                        // identifier is a keyword 
                        bufferOut.insert(bufferOut.length() - 
                                         qualifiedIdentifierLength,
                                         "");
                        bufferOut.append("");
                        if (("import").equals(identifier))
                        {
                            // anything after an import in text mode must be 
                            // an import name, so enter state to process this
                            presentState = State.IMPORT_NAME;
                        }
                        else if (("package").equals(identifier))
                        {
                            // anything after an package in text mode must be 
                            // an package name, so enter state to process this
                            presentState = State.PACKAGE_NAME;
                        }
                    }
                    else if (primitiveTypeCollection.contains(identifier))
                    {
                        // identifier is a primitive type  
                        bufferOut.insert(bufferOut.length() -
                                         qualifiedIdentifierLength,
                                         "");
                        bufferOut.append("");
                    }
                    else if ((identifier.equals(identifier.toUpperCase())) &&
                             (!(Character.isDigit(identifier.charAt(0)))))
                    {
                        // identifier is a constant
                        bufferOut.insert(bufferOut.length() -
                                         qualifiedIdentifierLength, 
                                         "");
                        bufferOut.append("");
                    }
                    else if (Character.isUpperCase(identifier.charAt(0)))
                    {
                        // identifier is a constructor or non-primitive type
                        // eat white space 
                        saveIndex = presentIndex;
                        while (Character.isWhitespace(
                                   bufferIn.charAt(saveIndex++)))
                        {
                            //empty body
                        }
                        if (bufferIn.charAt(--saveIndex) == '(')
                        {   // identifier is a constructor
                            bufferOut.insert(bufferOut.length() -
                                             qualifiedIdentifierLength,
                                             "");
                            bufferOut.append("");
                        }
                        else
                        {
                            // identifier is a non-primitive type 
                            bufferOut.insert(bufferOut.length() -
                                             qualifiedIdentifierLength,
                                             "");
                            bufferOut.append("");
                        }
                    }
                    else if (!(Character.isDigit(identifier.charAt(0)) ||
                               primitiveLiteralCollection.contains(identifier)))
                    {
                        // identifier is a method or a variable
                        // eat white space
                        saveIndex = presentIndex;
                        while (Character.isWhitespace(
                                   bufferIn.charAt(saveIndex++)))
                        {
                            // empty body
                        }
                        --saveIndex;
                        // identifier is a method
                        if (bufferIn.charAt(saveIndex) == '(')
                        {
                            bufferOut.insert(bufferOut.length() - 
                                             qualifiedIdentifierLength, 
                                             "");
                            bufferOut.append("");                 
                        }
                        else if (bufferIn.charAt(saveIndex) == ',')
                        {
                            // comma seperated variables
                            bufferOut.insert(bufferOut.length() - 
                                             qualifiedIdentifierLength, 
                                             "");
                            bufferOut.append(""); 
                        }
                        else
                        {
                            // a variable
                            // take care of cases such as array[index].variable
                            if (bufferIn.charAt(presentIndex - 
                                                (qualifiedIdentifierLength 
                                                 + 1)) == '.')
                            {
                                qualifiedIdentifierLength++;
                            }
                            bufferOut.insert(bufferOut.length() - 
                                             qualifiedIdentifierLength, 
                                             "");
                            bufferOut.append("");                        
                        }
                    }
                    else
                    {
                        if (primitiveLiteralCollection.contains(identifier))
                        {
                            // primitiveLiteral (boolean or null)
                            bufferOut.insert(bufferOut.length() -
                                             identifierLength, "");
                            bufferOut.append("");
                        }
                        // a numerical literal
                        else 
                        {
                            if (((presentIndex - 
                                  (qualifiedIdentifierLength + 1)) > 0) && 
                                (bufferIn.charAt(presentIndex - 
                                     (qualifiedIdentifierLength + 1)) == '.'))
                            {
                                qualifiedIdentifierLength++;
                            }
                            bufferOut.insert(bufferOut.length() - 
                                             qualifiedIdentifierLength, 
                                             "");
                            bufferOut.append("");
                        }
                    }
                }
                qualifiedIdentifierLength = 0;
                identifierLength = 0;
            }
            // process characters NOT in identifiers 
            switch (presentChar)
            {
                case '&': //ampersand
                    bufferOut.append("&");  // HTMLify character
                    break;
                case '<': // less than sign
                    bufferOut.append("<");   // HTMLify character
                    break;
                case '>': // greater than sign
                    bufferOut.append(">");   // HTMLify character
                    break;
                case '\"': // double quote
                    bufferOut.append("""); // HTMLify character
                    if (State.TEXT == presentState)
                    {
                        presentState = State.DOUBLE_QUOTE;
                        bufferOut.insert(bufferOut.length()-(""").length(),
                                         "");
                    }   
                    else if (State.DOUBLE_QUOTE == presentState)
                    {
                        presentState = State.TEXT;
                        bufferOut.append("");
                    }
                    break;
                case '\'': // single quote
                    bufferOut.append("\'");
                    if (State.TEXT == presentState)
                    {
                        presentState = State.SINGLE_QUOTE;
                        bufferOut.insert(bufferOut.length() - ("\'").length(), 
                                         "");
                    }
                    else if (State.SINGLE_QUOTE == presentState)
                    {
                        presentState = State.TEXT;
                        bufferOut.append("");
                    }
                    break;
                case '\\': // backslash
                    bufferOut.append("\\");
                    if ((State.DOUBLE_QUOTE == presentState) || 
                         (State.SINGLE_QUOTE == presentState))
                    {
                        // treat as a character escape sequence 
                        bufferOut.append(bufferIn.charAt(++presentIndex));
                    }
                    break;
                case '\t': // tab
                    // replace tabs with tabsize number of spaces
                    for (int i = 0; i < tabSize; i++) 
                    {
                        bufferOut.append(' ');
                    }
                    break;
                case '*': // star
                    bufferOut.append("*");
                    if ((State.TEXT ==  presentState) && 
                        (bufferIn.charAt(presentIndex - 1) == '/'))
                    {
                        if (((bufferIn.length() - 1) > presentIndex)  &&
                            (bufferIn.charAt(presentIndex + 1) == '*'))
                        {
                            presentState = State.JAVADOC;
                            bufferOut.insert(bufferOut.length() - 
                                             ("/*").length(), "");
                        }
                        else
                        {                        
                            presentState = State.TRADITIONAL_COMMENT;
                            bufferOut.insert(bufferOut.length() - 
                                             ("/*").length(), "");
                        }
                    }
                    break;
                case '/': // foward slash
                    bufferOut.append("/");
                    if (((State.TRADITIONAL_COMMENT == presentState) || 
                         (State.JAVADOC == presentState)) &&
                        (bufferIn.charAt(presentIndex - 1) == '*'))
                    {
                        bufferOut.append("");
                        presentState = State.TEXT;
                    }
                    if ((State.TEXT == presentState) && 
                        (presentIndex > 0)  &&
                        (bufferIn.charAt(presentIndex - 1) == '/'))
                    {   
                        bufferOut.insert(bufferOut.length() - ("//").length(), 
                                         "");
                        presentState = State.LINE_COMMENT;
                    } 
                    break;
                case '\r': // carriage return
                    // fall through  
                case '\n': // line feed
                    // all HTML lines end in \r\n
                    if ((bufferIn.charAt(presentIndex) == '\r') &&
                        ((bufferIn.length() - 1) > presentIndex)  &&
                        (bufferIn.charAt(presentIndex + 1) == '\n'))
                    {    
                        ++presentIndex;
                    }
                    // end single line comments
                    if (State.LINE_COMMENT == presentState)
                    {
                        bufferOut.append("");
                        presentState = State.TEXT;
                    }
                    // end of block  
                    if ((lineModulus > 0) && hasLineModulusCodeBlocks && 
                        ((codeLineNumber%lineModulus == 0) && !isNewBlock))
                    {
                        // end multi-line spanning states
                        if ((State.TRADITIONAL_COMMENT == presentState) ||
                            (State.JAVADOC == presentState))
                        {
                             bufferOut.append("");
                        }
                        bufferOut.append("\r\n");
                        bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); bufferOut.append("
\r\n");
                        // restart multi-line spanning states
                        if (State.TRADITIONAL_COMMENT == presentState)
                        {
                            bufferOut.append("");
                        }
                        if (State.JAVADOC == presentState)
                        {
                            bufferOut.append("");
                        }
                    }
                    else
                    {
                        // div automatically starts new line 
                        bufferOut.append("\r\n");
                    }
                    isNewLine = true;
                    break;
                case 0: // nul character
                    if ((State.LINE_COMMENT == presentState) && 
                        (presentIndex == (bufferIn.length() - 1)))
                    {
                        bufferOut.append("");
                    }
                    break;
                default:  // everything else 
                    bufferOut.append(presentChar);
            }
            qualifiedIdentifierLength = 0;
        }
        if (presentState == State.LINE_COMMENT) {
            bufferOut.append("\r\n");
        }

        bufferOut.append("
\r\n"); // end block early if no more source code if ((lineModulus > 0) && hasLineModulusCodeBlocks && !isNewBlock && (codeLineNumber%lineModulus != 0)) { bufferOut.append("
\r\n"); } bufferOut.append(" \r\n"); // end div of sourceCodeStyle // if code snippet then don't add ending tags of xhtml page if (!isCodeSnippet) { // if footer mode then add a footer if (hasFooter) { bufferOut.append("
\r\n"); bufferOut.append("
\r\n"); if (hasFooterIcons) { if (hasFooterDate) { bufferOut.append(" \r\n"); } bufferOut.append(" \r\n"); bufferOut.append(" \"Valid\r\n"); bufferOut.append(" \r\n"); bufferOut.append("  \r\n"); bufferOut.append(" \r\n"); bufferOut.append(" \"Valid\r\n"); bufferOut.append(" \r\n"); } else { bufferOut.append(" This is a valid\r\n"); bufferOut.append(" XHTML 1.1\r\n"); } else { bufferOut.append("\">XHTML 1.0\r\n"); } bufferOut.append(" with\r\n"); bufferOut.append(" CSS\r\n"); bufferOut.append(" document \r\n"); if (hasFooterDate) { bufferOut.append(" \r\n"); } } bufferOut.append("
\r\n"); } bufferOut.append(" \r\n"); bufferOut.append("\r\n"); } return bufferOut.toString(); } }