1: /* Copyright (C) 2003 Shayne Steele
   2:  * License and warranty are under the terms of the GNU General Public License 
   3:  * Version 2.0.  See http://www.gnu.org for license and warranty details. 
   4:  */
   5: 
   6: /** Java2xhtml.java  Version 0.9
   7:  *  Produces an XHTML file from Java source code with syntax highlighting,
   8:  *  includes additional options (line numbering, tab spacing, etc.)
   9:  * <P>
  10:  * NOTE: Common java naming structure is assumed
  11:  *       Capitalize the first letter that appears in a class or interface name
  12:  *       Use lowercase for the first letter in a method or variable name
  13:  *       Use only uppercase letters when naming constants 
  14:  *
  15:  * @version     0.9, March 2003
  16:  * @author      Shayne Steele
  17:  */ 
  18: import java.io.*;
  19: import java.util.*;
  20: 
  21: public class Java2xhtml
  22: {
  23:     // parse the command line arguments
  24:     // give a decent responce for bad input
  25:     // call the HTMLifier on good input
  26:     public static void main(String args[])
  27:     {
  28:         // parse the invokation arguments 
  29:         if (args.length < 1 || args.length > 3) // invoked program incorrectly
  30:         {
  31:             System.out.println("Java2xhtml Version 0.9 (C) 2003 Shayne Steele");
  32:             System.out.println("    Produces an XHTML file of Java source" +
  33:                                " code with syntax highlighting,");
  34:             System.out.println("    includes additional options " +
  35:                                "(line numbering, tab spacing, etc.)");
  36:             System.out.println("    License and warranty are under the terms " +
  37:                                "of the GNU General Public License");
  38:             System.out.println("        (GPL) Version 2.0");
  39:             System.out.println("    See http://www.gnu.org for license and " +
  40:                                "warranty details.");
  41:             System.out.println("    NOTE: Common java naming structure is " +
  42:                                "assumed");
  43:             System.out.println("");
  44:             System.out.println("USAGE:");
  45:             System.out.println("java  [java options]  Java2xhtml  " +
  46:                                "source.java  [options file]  " +
  47:                                "[output file]");
  48:             System.out.println("");
  49:             System.out.println("  - java is the name of the Java interpreter");
  50:             System.out.println("  - [java options] are the optional options " +
  51:                                "of the Java interpreter");
  52:             System.out.println("  - Java2xhtml is the name of this " +
  53:                                "application");
  54:             System.out.println("  - source is a file or the directory to the " +
  55:                                "Java source file(s)");
  56:             System.out.println("  - [options file] is the optional " +
  57:                                "path of a file with");
  58:             System.out.println("    a structure like this:");
  59:             System.out.println("        externalStyleSheetName=file_name" +
  60:                                " (default style.css)");
  61:             System.out.println("        tabSize=integer  (default value is 4)");
  62:             System.out.println("        extraIndentation=integer  " +
  63:                                "(default value is 0)");
  64:             System.out.println("        lineModulus=integer (default value 5)");
  65:             System.out.println("        isCodeSnippet=boolean" +
  66:                                " (default false)");
  67:             System.out.println("        isXHTML_1_1=boolean" +
  68:                                " (default true)");
  69:             System.out.println("        hasInternalStyleSheet=boolean" +
  70:                                " (default true)");
  71:             System.out.println("        hasExternalStyleSheet=boolean" +
  72:                                " (default true)");
  73:             System.out.println("        hasTitle=boolean" +
  74:                                " (default false)");
  75:             System.out.println("        hasLegend=boolean" +
  76:                                " (default false)");
  77:             System.out.println("        hasAllBoldSourceCode=boolean" +
  78:                                " (default false)");
  79:             System.out.println("        hasLineNumbers=boolean" +
  80:                                " (default false)");
  81:             System.out.println("        hasLineModulusDrawnLines=boolean" + 
  82:                                " (default false)");
  83:             System.out.println("        hasLineModulusCodeBlocks=boolean" +
  84:                                " (default false)");
  85:             System.out.println("        hasFooter=boolean" + 
  86:                                " (default false)");
  87:             System.out.println("        hasFooterIcons=boolean" + 
  88:                                " (default false)");
  89:             System.out.println("        hasFooterDate=boolean" + 
  90:                                " (default true)");
  91:             System.out.println("    NOTE: filename must end with '.prop'");
  92:             System.out.println("    Default [options file] is " +
  93:                                "options.prop");
  94:             System.out.println("  - [output file] is name of the XHTML file " +
  95:                                "that is produced");
  96:             System.out.println("    Default [output file] is source_java.html");
  97:             System.out.println("");
  98:             System.out.println("Output: source.java --> [output file]");
  99:             System.out.println("    Default Output is ");
 100:             System.out.println("    source.java --> source_java.html");
 101:             System.out.println("");
 102:             System.out.println("Examples of calling the program:");
 103:             System.out.println(" process one file (say Java2xhtml.java):");
 104:             System.out.println("    java  Java2xhtml  Java2xhtml.java");
 105:             System.out.println(" process one directory (say C:\\HOME):");
 106:             System.out.println("    java  Java2xhtml  C:\\HOME");
 107:             System.out.println(" process one directory (say C:\\HOME with a " +
 108:                                "given options file (options.prop)):");
 109:             System.out.println("    java  Java2xhtml  C:\\HOME options.prop");
 110:         }
 111:         else  
 112:         {
 113:             // invoked program correctly, now get command line arguments
 114:             // get the source file name
 115:             String sourceName;
 116:             sourceName = args[0];
 117:             // make sure that the source file exist and if so HTMLify it
 118:             File sourceFilePath = new File(sourceName);
 119:             if (sourceFilePath.exists())  
 120:             {
 121:                 // good pathname so HTMLify it
 122:                 // get the default html options file name
 123:                 String propertiesFileName = "options.prop";
 124:                 // create a unique default html file name, 
 125:                 // bubba.java -> bubba_java.html
 126:                 String htmlFileName = sourceName.replace('.', '_') + ".html";
 127:                 if (args.length == 2 || args.length == 3)
 128:                 {
 129:                     if (args[1].endsWith(".prop"))
 130:                     {
 131:                         // get the user supplied html options file name
 132:                         propertiesFileName = args[1];
 133:                     }
 134:                     else
 135:                     {
 136:                         // get the user supplied html outputfile name
 137:                         htmlFileName = args[1];
 138:                     }
 139:                 }
 140:                 if (args.length == 3) 
 141:                 {
 142:                     if (args[2].endsWith(".prop"))
 143:                     {
 144:                         // get the user supplied html options file name
 145:                         propertiesFileName = args[2];
 146:                     }
 147:                     else
 148:                     {
 149:                         // get the user supplied html outputfile name
 150:                         htmlFileName = args[2];
 151:                     }
 152:                 }
 153:                 new Java2xhtml(propertiesFileName, sourceFilePath, 
 154:                                htmlFileName);
 155:             }
 156:             else // source file does not exist, print message and exit normally
 157:             {
 158:                 System.out.println("The source parameter must be an existent" +
 159:                                    " file or directory");
 160:                 System.out.println("Run Java2xHtml without parameters for " +
 161:                                    "help");
 162:             }                 
 163:         }
 164:     }
 165:     
 166:     // collect various sets of keywords
 167:     Collection keywordCollection;
 168:     Collection primitiveTypeCollection;
 169:     Collection primitiveLiteralCollection;
 170:     Collection javadocTagCollection;
 171: 
 172:     // all these variables are changeable by a options file
 173:     int extraIndentation = 0;
 174:     int tabSize = 4;
 175:     int lineModulus = 5;
 176:     boolean hasLegend = false;
 177:     boolean hasLineNumbers = false;
 178:     boolean hasLineModulusDrawnLines = false;
 179:     boolean hasLineModulusCodeBlocks = false;
 180:     boolean hasFooter = false;
 181:     boolean hasFooterIcons = false;
 182:     boolean hasFooterDate = true;
 183:     boolean isCodeSnippet = false;
 184:     boolean isXHTML_1_1 = true;
 185:     boolean hasTitle = false;
 186:     boolean hasAllBoldSourceCode = false;
 187:     boolean hasInternalStyleSheet = true;
 188:     boolean hasExternalStyleSheet = true;
 189:     String externalStyleSheetName = "style.css";
 190: 
 191:     // create the various keyword collections 
 192:     // parse the html options file
 193:     Java2xhtml(String propertiesFileName, File sourceFilePath, 
 194:                String htmlFileName)
 195:     {
 196:         
 197:         // collection type is Hashset for unique elements and fast retieval 
 198:         String keywordArray[] =
 199:             {
 200:                 "abstract", "default",      "if",           "private",      
 201:                 "do",       "implements",   "protected",    "throws",
 202:                 "break",    "import",       "public",       "transient",
 203:                 "else",     "instanceof",   "return",       "try",
 204:                 "case",     "extends",      "throw",        "static",
 205:                 "catch",    "final",        "interface",    "while",       
 206:                 "volatile", "finally",      "super",        "synchronized",
 207:                 "class",    "native",       "switch",       "package",
 208:                 "const",    "for",          "new",          "goto",
 209:                 "continue", "this",         "assert",       "strictfp"       
 210:             };
 211:         keywordCollection = new HashSet(Arrays.asList(keywordArray));
 212:         String primitiveTypeArray[] =
 213:             {
 214:                 "boolean",  "char",     "byte",         "short",        "int",
 215:                 "long",     "float",    "double",       "void"
 216:             };
 217:         primitiveTypeCollection = 
 218:             new HashSet(Arrays.asList(primitiveTypeArray));
 219:         String primitiveLiteralArray[]=
 220:             {
 221:                 "false", "null", "true"
 222:             };
 223:         primitiveLiteralCollection = 
 224:             new HashSet(Arrays.asList(primitiveLiteralArray));
 225:         String javadocTagArray[]=
 226:             {
 227:                 "see", "author", "version", "param", "return", "exception", 
 228:                 "deprecated", "throws", "link", "since", "serial", 
 229:                 "serialField","serialData", "beaninfo"
 230:             };
 231:         javadocTagCollection = new HashSet(Arrays.asList(javadocTagArray)); 
 232:         // get html properties (use defaults if necessary)
 233:         File propertiesFilePath = new File (propertiesFileName);
 234:         if (propertiesFilePath.exists())
 235:         {
 236:             // html properies file exist try parsing it
 237:             try 
 238:             {
 239:                 InputStream propertiesFile = 
 240:                     new FileInputStream(propertiesFileName);
 241:                 Properties htmlProperties = new Properties();
 242:                 htmlProperties.load(propertiesFile);
 243:                 propertiesFile.close();
 244:                 hasLegend = Boolean.valueOf(
 245:                     htmlProperties.getProperty("hasLegend", 
 246:                                                "false")).booleanValue();
 247:                 extraIndentation = Integer.parseInt(
 248:                     htmlProperties.getProperty("extraIndentation", "0"));
 249:                 tabSize = Integer.parseInt(
 250:                     htmlProperties.getProperty("tabSize", "4"));
 251:                 hasLineNumbers = Boolean.valueOf(
 252:                     htmlProperties.getProperty("hasLineNumbers",
 253:                                                "false")).booleanValue();
 254:                 lineModulus = Integer.parseInt(
 255:                     htmlProperties.getProperty("lineModulus", "5"));
 256:                 hasLineModulusDrawnLines = Boolean.valueOf(
 257:                     htmlProperties.getProperty("hasLineModulusDrawnLines",
 258:                                                "false")).booleanValue();
 259:                 hasLineModulusCodeBlocks = Boolean.valueOf(
 260:                     htmlProperties.getProperty("hasLineModulusCodeBlocks",
 261:                                                "false")).booleanValue();
 262:                 hasFooter = Boolean.valueOf(
 263:                     htmlProperties.getProperty("hasFooter",
 264:                                                "false")).booleanValue();
 265:                 hasFooterIcons = Boolean.valueOf(
 266:                     htmlProperties.getProperty("hasFooterIcons",
 267:                                                "false")).booleanValue();
 268:                 hasFooterDate = Boolean.valueOf(
 269:                     htmlProperties.getProperty("hasFooterDate",
 270:                                                "true")).booleanValue();
 271:                 isXHTML_1_1 = Boolean.valueOf(
 272:                     htmlProperties.getProperty("isXHTML_1_1",
 273:                                                "true")).booleanValue();
 274:                 isCodeSnippet = Boolean.valueOf(
 275:                     htmlProperties.getProperty("isCodeSnippet",
 276:                                                "false")).booleanValue();
 277:                 hasTitle = Boolean.valueOf(
 278:                     htmlProperties.getProperty("hasTitle",
 279:                                                "false")).booleanValue();
 280:                 hasAllBoldSourceCode = Boolean.valueOf(
 281:                     htmlProperties.getProperty("hasAllBoldSourceCode",
 282:                                                "false")).booleanValue();
 283:                 hasInternalStyleSheet = Boolean.valueOf(
 284:                     htmlProperties.getProperty("hasInternalStyleSheet",
 285:                                                "true")).booleanValue();
 286:                 hasExternalStyleSheet = Boolean.valueOf(
 287:                     htmlProperties.getProperty("hasExternalStyleSheet",
 288:                                                "true")).booleanValue();
 289:                 externalStyleSheetName = htmlProperties.getProperty(
 290:                     "externalStyleSheetName", "style.css");
 291:             }
 292:             catch (IOException exception) 
 293:             {
 294:                 System.out.println(exception);  
 295:             }
 296:         }
 297:         if (sourceFilePath.isFile())
 298:         {
 299:             // process the file 
 300:             processFile(sourceFilePath, htmlFileName);
 301:         }
 302:         else if (sourceFilePath.isDirectory())
 303:         {
 304:             // process a directory
 305:             File [] sourceFilePathArray = sourceFilePath.listFiles();
 306:             for (int i = 0; i < sourceFilePathArray.length; i++)
 307:             {
 308:                 if (((sourceFilePathArray[i]).getName()).endsWith(".java"))
 309:                 {
 310:                     // process each file that ends in .java 
 311:                     // create a unique default html file name, 
 312:                     // bubba.java -> bubba_java.html
 313:                     htmlFileName = ((sourceFilePathArray[i]).getName()).replace(
 314:                         '.', '_') + ".html";
 315:                     processFile(sourceFilePathArray[i], htmlFileName);
 316:                 }
 317:             }
 318:         }
 319:     }
 320:     
 321:     
 322:     // read the file and put it into a stringbuffer
 323:     void processFile(File sourceFilePath, String htmlFileName)
 324:     {
 325:         // open the file, copy it to a Stringbuffer , process into an 
 326:         // HTMLified String and convert result into an HTML file
 327:         try
 328:         {
 329:             BufferedReader sourceReader = 
 330:                 new BufferedReader(new FileReader(sourceFilePath));
 331:             StringBuffer bufferIn = new StringBuffer();
 332:             int readInInt = 0;
 333:             char presentChar = 0;
 334:             // copy file into a Stringbuffer
 335:             while (readInInt != -1) // -1 value means end of stream/file 
 336:             {
 337:                 // put the file into a Stringbuffer
 338:                 readInInt= sourceReader.read();
 339:                 presentChar = ((readInInt >= 0) ? (char) readInInt : 0);
 340:                 bufferIn.append(presentChar);
 341:             }
 342:             sourceReader.close();
 343:             BufferedWriter tempBufferedWriter = 
 344:                 new BufferedWriter(new FileWriter(htmlFileName));
 345:             tempBufferedWriter.write(makeHTML(bufferIn, 
 346:                                               sourceFilePath.getName()));
 347:             tempBufferedWriter.close();     
 348:             System.out.println(sourceFilePath.getName() + " --> " + 
 349:                                htmlFileName);
 350:         }
 351:         catch (IOException exception) 
 352:         {
 353:             System.out.println(exception);  
 354:         }
 355:     }
 356:     
 357:     // constant 'States' java source code can be in 
 358:     public final static class State
 359:     {
 360:         public final static State TEXT = new State();
 361:         public final static State IMPORT_NAME = new State();
 362:         public final static State PARAM_VARIABLE = new State();
 363:         public final static State JAVADOC = new State();
 364:         public final static State PACKAGE_NAME = new State();
 365:         public final static State DOUBLE_QUOTE = new State();
 366:         public final static State SINGLE_QUOTE = new State();
 367:         public final static State TRADITIONAL_COMMENT = new State();
 368:         public final static State LINE_COMMENT = new State();
 369:         
 370:         // empty constructor 
 371:         private State()
 372:         {
 373:             // empty body
 374:         }
 375:     }
 376:     
 377:     // Convert java source code StringBufffer into colorized (and tab spaced) 
 378:     // HTML String .
 379:     // Assumes that Java naming convention is used
 380:     // Uses a very basic state machine design.   
 381:     String makeHTML(StringBuffer bufferIn, String sourceFileName)
 382:     {
 383:         int codeLineNumber = 0;
 384:         boolean isNewLine = true;
 385:         boolean isNewBlock = true;
 386:         int identifierLength = 0;
 387:         int qualifiedIdentifierLength = 0;
 388:         int presentIndex = -1;
 389:         int spaceLength = 0;
 390:         int saveIndex = 0;
 391:         char presentChar = 0;
 392:         State presentState = State.TEXT;
 393:         StringBuffer bufferOut = new StringBuffer();
 394:         if (!isCodeSnippet)
 395:         {
 396:             bufferOut.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"); 
 397:             if (isXHTML_1_1)
 398:             {
 399:                 bufferOut.append("<!DOCTYPE html PUBLIC " +
 400:                                  "\"-//W3C//DTD XHTML 1.1//EN\"\r\n");
 401:                 bufferOut.append("    \"http://www.w3.org/TR/xhtml11/DTD/" +
 402:                                  "xhtml11.dtd\">\r\n");
 403:                 bufferOut.append("<html xmlns=\"http://www.w3.org/1999/xhtml\""+
 404:                                  " xml:lang=\"en\">\r\n");
 405:             }
 406:             else
 407:             {
 408:                 bufferOut.append("<!DOCTYPE html PUBLIC " +
 409:                                  "\"-//W3C//DTD XHTML 1.0 Strict//EN\"\r\n");
 410:                 bufferOut.append("    \"http://www.w3.org/TR/xhtml1/DTD/" +
 411:                                  "xhtml1-strict.dtd\">\r\n");
 412:                 bufferOut.append("<html xmlns=\"http://www.w3.org/1999/xhtml\""+
 413:                                  " xml:lang=\"en\" lang=\"en\">\r\n");
 414:             }
 415:             bufferOut.append(" <head>\r\n");
 416:             bufferOut.append("  <title>\r\n");
 417:             bufferOut.append("   " + sourceFileName + "\r\n");
 418:             bufferOut.append("  </title>\r\n");
 419:             bufferOut.append("  <meta name=\"generator\"\r\n");
 420:             bufferOut.append("        content=\"Java2xhtml 0.9\" />\r\n");
 421:             if (hasInternalStyleSheet)
 422:             {
 423:                 bufferOut.append("  <style type=\"text/css\">\r\n");
 424:                 bufferOut.append("   <!-- /* <![CDATA[ */\r\n");
 425:                 bufferOut.append("    .sourceCodeStyle\r\n");
 426:                 bufferOut.append("     {\r\n");
 427:                 bufferOut.append("       color: #000000;\r\n");
 428:                 bufferOut.append("       background-color: #FFFFFF;\r\n");
 429:                 if (hasAllBoldSourceCode)
 430:                 {
 431:                     bufferOut.append("       font-weight: bold;\r\n");
 432:                 }
 433:                 bufferOut.append("     }\r\n");
 434:                 bufferOut.append("    .lineNumberStyle\r\n");
 435:                 bufferOut.append("     {\r\n");
 436:                 bufferOut.append("       font-weight: normal;\r\n");
 437:                 bufferOut.append("       color: #000000;\r\n");
 438:                 bufferOut.append("       background-color: transparent;\r\n");
 439:                 bufferOut.append("     }\r\n");
 440:                 if (lineModulus > 0)
 441:                 {
 442:                     bufferOut.append("    .modulusLineNumberStyle\r\n");
 443:                     bufferOut.append("     {\r\n");
 444:                     bufferOut.append("       font-weight: bold;\r\n");
 445:                     bufferOut.append("       color: #000000;\r\n");
 446:                     bufferOut.append("       background-color: "); 
 447:                     bufferOut.append("transparent;\r\n");
 448:                     bufferOut.append("     }\r\n");
 449:                     if (hasLineModulusDrawnLines)
 450:                     {
 451:                         bufferOut.append("    .modulusLineStyle\r\n");
 452:                         bufferOut.append("     {\r\n");
 453:                         bufferOut.append("       text-decoration: ");
 454:                         bufferOut.append("line-through;\r\n");
 455:                         bufferOut.append("       color: #000000;\r\n");
 456:                         bufferOut.append("       background-color: ");
 457:                         bufferOut.append("transparent;\r\n");
 458:                         bufferOut.append("     }\r\n");
 459:                     }
 460:                     if (hasLineModulusCodeBlocks)
 461:                     {
 462:                         bufferOut.append("    .modulusBlockPREStyle\r\n");
 463:                         bufferOut.append("     {\r\n");
 464:                         bufferOut.append("       margin: 0em\r\n");
 465:                         bufferOut.append("     }\r\n");
 466:                         bufferOut.append("    .modulusBlockStyle\r\n");
 467:                         bufferOut.append("     {\r\n");
 468:                         bufferOut.append("       color: #000000;\r\n");
 469:                         bufferOut.append("       background-color: ");
 470:                         bufferOut.append("#CCCCCC;\r\n"); 
 471:                         bufferOut.append("     }\r\n");
 472:                     }
 473:                 }
 474:                 bufferOut.append("    .keywordStyle\r\n");
 475:                 bufferOut.append("     {\r\n");
 476:                 bufferOut.append("       color: #9900FF;\r\n");
 477:                 bufferOut.append("       background-color: transparent;\r\n");
 478:                 bufferOut.append("     }\r\n");
 479:                 bufferOut.append("    .methodStyle\r\n");
 480:                 bufferOut.append("     {\r\n");
 481:                 bufferOut.append("       color: #0000FF;\r\n"); 
 482:                 bufferOut.append("       background-color: transparent;\r\n");
 483:                 bufferOut.append("     }\r\n");
 484:                 bufferOut.append("    .variableStyle\r\n");
 485:                 bufferOut.append("     {\r\n");
 486:                 bufferOut.append("       color: #CC9933;\r\n"); 
 487:                 bufferOut.append("       background-color: transparent;\r\n");
 488:                 bufferOut.append("     }\r\n");
 489:                 bufferOut.append("    .singleLineCommentStyle\r\n");
 490:                 bufferOut.append("     {\r\n");
 491:                 bufferOut.append("       color: #CC3333;\r\n");
 492:                 bufferOut.append("       background-color: transparent;\r\n");
 493:                 bufferOut.append("     }\r\n");
 494:                 bufferOut.append("    .traditionalCommentStyle\r\n");
 495:                 bufferOut.append("     {\r\n");
 496:                 bufferOut.append("       color: #FF0000;\r\n"); 
 497:                 bufferOut.append("       background-color: transparent;\r\n");
 498:                 bufferOut.append("     }\r\n");
 499:                 bufferOut.append("    .javadocCommentStyle\r\n");
 500:                 bufferOut.append("     {\r\n");
 501:                 bufferOut.append("       color: #CC0033;\r\n");
 502:                 bufferOut.append("       background-color: transparent;\r\n");
 503:                 bufferOut.append("     }\r\n");
 504:                 bufferOut.append("    .javadocTagStyle\r\n");
 505:                 bufferOut.append("     {\r\n");
 506:                 bufferOut.append("       color: #0099CC;\r\n");
 507:                 bufferOut.append("       background-color: transparent;\r\n");
 508:                 bufferOut.append("     }\r\n");
 509:                 bufferOut.append("    .importNameStyle\r\n");
 510:                 bufferOut.append("     {\r\n");
 511:                 bufferOut.append("       color: #33CCCC;\r\n");
 512:                 bufferOut.append("       background-color: transparent;\r\n");
 513:                 bufferOut.append("     }\r\n");
 514:                 bufferOut.append("    .packageNameStyle\r\n");
 515:                 bufferOut.append("     {\r\n");
 516:                 bufferOut.append("       color: #339999;\r\n");
 517:                 bufferOut.append("       background-color: transparent;\r\n");
 518:                 bufferOut.append("     }\r\n");
 519:                 bufferOut.append("    .primitiveTypeStyle\r\n");
 520:                 bufferOut.append("     {\r\n");
 521:                 bufferOut.append("       color: #009900;\r\n");
 522:                 bufferOut.append("       background-color: transparent;\r\n");
 523:                 bufferOut.append("     }\r\n");
 524:                 bufferOut.append("    .nonPrimitiveTypeStyle\r\n");
 525:                 bufferOut.append("     {\r\n");
 526:                 bufferOut.append("       color: #009966;\r\n");
 527:                 bufferOut.append("       background-color: transparent;\r\n");
 528:                 bufferOut.append("     }\r\n");
 529:                 bufferOut.append("    .constructorStyle\r\n"); 
 530:                 bufferOut.append("     {\r\n");
 531:                 bufferOut.append("       color: #3300CC;\r\n");
 532:                 bufferOut.append("       background-color: transparent;\r\n");
 533:                 bufferOut.append("     }\r\n");
 534:                 bufferOut.append("    .constantStyle\r\n");
 535:                 bufferOut.append("     {\r\n");
 536:                 bufferOut.append("       color: #666666;\r\n");
 537:                 bufferOut.append("       background-color: transparent;\r\n");
 538:                 bufferOut.append("     }\r\n");
 539:                 bufferOut.append("    .doubleQuoteStyle\r\n");
 540:                 bufferOut.append("     {\r\n");
 541:                 bufferOut.append("       color: #996633;\r\n");
 542:                 bufferOut.append("       background-color: transparent;\r\n");
 543:                 bufferOut.append("       font-style: italic;\r\n");
 544:                 bufferOut.append("     }\r\n");
 545:                 bufferOut.append("    .singleQuoteStyle\r\n");
 546:                 bufferOut.append("     {\r\n");
 547:                 bufferOut.append("       color: #663333;\r\n");
 548:                 bufferOut.append("       background-color: transparent;\r\n");
 549:                 bufferOut.append("       font-style: oblique;\r\n");
 550:                 bufferOut.append("     }\r\n");
 551:                 bufferOut.append("    .numericalLiteralStyle\r\n"); 
 552:                 bufferOut.append("     {\r\n");
 553:                 bufferOut.append("       color: #333300;\r\n"); 
 554:                 bufferOut.append("       background-color: transparent;\r\n");
 555:                 bufferOut.append("     }\r\n");
 556:                 bufferOut.append("    .primitiveLiteralStyle\r\n");
 557:                 bufferOut.append("     {\r\n");
 558:                 bufferOut.append("       color: #006600;\r\n"); 
 559:                 bufferOut.append("       background-color: transparent;\r\n");
 560:                 bufferOut.append("     }\r\n");
 561:                 if (hasFooterIcons)
 562:                 {
 563:                     bufferOut.append("    .iconStyle\r\n");
 564:                     bufferOut.append("     {\r\n");
 565:                     bufferOut.append("       border-style: none;\r\n"); 
 566:                     bufferOut.append("     }\r\n");
 567:                 }
 568:                 if (hasTitle)
 569:                 {
 570:                     bufferOut.append("    #title\r\n");
 571:                     bufferOut.append("     {\r\n"); 
 572:                     bufferOut.append("       text-align: center;\r\n");
 573:                     bufferOut.append("       font-size: xx-large;\r\n");
 574:                     bufferOut.append("     }\r\n");
 575:                 }
 576:                 if (hasLegend)
 577:                 {
 578:                     bufferOut.append("    #legendTitle\r\n");
 579:                     bufferOut.append("     {\r\n"); 
 580:                     bufferOut.append("       text-align: center;\r\n");
 581:                     bufferOut.append("       font-size: x-large;\r\n");
 582:                     bufferOut.append("     }\r\n");
 583:                     bufferOut.append("    #legend\r\n");
 584:                     bufferOut.append("     {\r\n"); 
 585:                     bufferOut.append("       font-family: monospace;\r\n");
 586:                     bufferOut.append("       font-size: large;\r\n");
 587:                     bufferOut.append("     }\r\n");
 588:                 }                
 589:                 if (hasFooter)
 590:                 {
 591:                     bufferOut.append("    #footer\r\n");
 592:                     bufferOut.append("     {\r\n"); 
 593:                     bufferOut.append("       font-size: xx-small;\r\n");
 594:                     bufferOut.append("     }\r\n");
 595:                 }
 596:                 bufferOut.append("   /* ]]> */ -->\r\n");
 597:                 bufferOut.append("  </style>\r\n");
 598:             }
 599:             if (hasExternalStyleSheet)
 600:             {
 601:                 bufferOut.append("  <link rel=\"stylesheet\" " +
 602:                                  "type=\"text/css\" href=\"" + 
 603:                                  externalStyleSheetName + "\" />\r\n");
 604:             }
 605:             bufferOut.append(" </head>\r\n");
 606:             bufferOut.append(" <body>\r\n");
 607:         }
 608:         if (hasTitle)
 609:         {
 610:             bufferOut.append("  <div id=\"title\">\r\n");
 611:             bufferOut.append("   " + sourceFileName + "\r\n");
 612:             bufferOut.append("  </div>\r\n");
 613:             bufferOut.append("  <hr />\r\n");
 614:         }
 615:         if (hasLegend)
 616:         {
 617:             bufferOut.append("  <div id=\"legendTitle\">\r\n");
 618:             bufferOut.append("   Legend\r\n");
 619:             bufferOut.append("  </div>\r\n");
 620:             bufferOut.append("  <div class=\"sourceCodeStyle\">\r\n");
 621:             bufferOut.append("   <div id=\"legend\">\r\n");
 622:             bufferOut.append("    <span class=\"keywordStyle\">");
 623:             bufferOut.append("keyword</span>\r\n");
 624:             bufferOut.append("    <span class=\"methodStyle\">");
 625:             bufferOut.append("method</span>\r\n");
 626:             bufferOut.append("    <span class=\"variableStyle\">variable" +
 627:                              "</span>\r\n");
 628:             bufferOut.append("    <span class=\"singleLineCommentStyle\">" +
 629:                              "singleLineComment</span>\r\n");
 630:             bufferOut.append("    <span class=\"traditionalCommentStyle\">" +
 631:                              "traditionalComment</span>\r\n");
 632:             bufferOut.append("    <span class=\"javadocCommentStyle\">" +
 633:                              "javadocComment</span>\r\n");
 634:             bufferOut.append("    <span class=\"javadocTagStyle\">javadocTag" +
 635:                              "</span>\r\n");
 636:             bufferOut.append("    <span class=\"importNameStyle\">" +
 637:                              "importName</span>\r\n");
 638:             bufferOut.append("    <span class=\"packageNameStyle\">" +
 639:                              "packageName</span>\r\n");
 640:             bufferOut.append("    <span class=\"primitiveTypeStyle\">" +
 641:                              "primitiveType</span>\r\n");
 642:             bufferOut.append("    <span class=\"nonPrimitiveTypeStyle\">" +
 643:                              "nonPrimitiveType</span>\r\n");
 644:             bufferOut.append("    <span class=\"constructorStyle\">" +
 645:                              "constructor</span>\r\n");
 646:             bufferOut.append("    <span class=\"constantStyle\">" +
 647:                              "constant</span>\r\n");
 648:             bufferOut.append("    <span class=\"doubleQuoteStyle\">" +
 649:                              "doubleQuote</span>\r\n");
 650:             bufferOut.append("    <span class=\"singleQuoteStyle\">" +
 651:                              "singleQuote</span>\r\n");
 652:             bufferOut.append("    <span class=\"numericalLiteralStyle\">" +
 653:                              "numericalLiteral</span>\r\n");
 654:             bufferOut.append("    <span class=\"primitiveLiteralStyle\">" +
 655:                              "primitiveLiteral</span>\r\n");
 656:             bufferOut.append("   </div>\r\n");
 657:             bufferOut.append("  </div>\r\n");
 658:             bufferOut.append("  <hr />\r\n");
 659:         }
 660:         bufferOut.append("  <div class=\"sourceCodeStyle\">\r\n");
 661:         if (hasLineModulusCodeBlocks)
 662:         {
 663:             bufferOut.append("<pre class=\"modulusBlockPREStyle\">\r\n");
 664:         }
 665:         else
 666:         {
 667:             bufferOut.append("<pre>\r\n");
 668:         }
 669:         // process the input Java code Stringbuffer
 670:         // subtract 2 from the bufferIn.length() to get EOF marker
 671:         while (presentIndex++ != (bufferIn.length() - 2))
 672:         {
 673:             for (int i = 0; i < extraIndentation; i++)
 674:             {
 675:                 bufferOut.append(" ");
 676:             }
 677:             if ((hasLineNumbers || hasLineModulusCodeBlocks) && isNewLine)
 678:             {
 679:                 // add line numbers if desired
 680:                 // line numbers are 1 - 9999 then rotate line numbers
 681:                 codeLineNumber = (++codeLineNumber)%10000;
 682:                 if ((lineModulus > 0) && hasLineModulusCodeBlocks && 
 683:                     (codeLineNumber%lineModulus == 1))
 684:                 {
 685:                     if (isNewBlock)
 686:                     {
 687:                         if ((State.TRADITIONAL_COMMENT == presentState) ||
 688:                             (State.JAVADOC == presentState))
 689:                         {
 690:                                 bufferOut.insert((bufferOut.length() - 
 691:                                                   ("\r\n").length()), 
 692:                                                  "</span>");
 693:                         }
 694:                         bufferOut.append("</pre>\r\n");
 695:                         bufferOut.append("   <div class=");
 696:                         bufferOut.append("\"modulusBlockStyle\">");
 697:                         bufferOut.append("\r\n<pre class=\"");
 698:                         bufferOut.append("modulusBlockPREStyle\">\r\n");
 699:                         if (State.TRADITIONAL_COMMENT == presentState)
 700:                         {
 701:                             bufferOut.append("<span class=" +
 702:                                              "\"traditionalCommentStyle\">");
 703:                         }
 704:                         if (State.JAVADOC == presentState)
 705:                         {
 706:                             bufferOut.append("<span class=" +
 707:                                              "\"javadocCommentStyle\">");
 708:                         }
 709:                     }
 710:                     isNewBlock = !isNewBlock;
 711:                 }
 712:                 // make straight columns of line numbers
 713:                 if (codeLineNumber < 1000)
 714:                 {
 715:                     bufferOut.append(" ");
 716:                 }
 717:                 if (codeLineNumber < 100)
 718:                 {
 719:                     bufferOut.append(" ");
 720:                 }
 721:                 if (codeLineNumber < 10)
 722:                 {
 723:                     bufferOut.append(" ");
 724:                 }
 725:                 if (hasLineNumbers)
 726:                 {
 727:                     if ((lineModulus > 0) && (codeLineNumber%lineModulus == 0))
 728:                     {
 729:                         bufferOut.append("<span class=" +
 730:                                          "\"modulusLineNumberStyle\">");
 731:                         bufferOut.append(codeLineNumber);
 732:                         bufferOut.append(": </span>");
 733:                         if (hasLineModulusDrawnLines)
 734:                         {
 735:                             // compute spaceLength so a line can be drawn
 736:                             while ((presentIndex != (bufferIn.length() - 1)) &&
 737:                                    ((Character.isSpaceChar(
 738:                                      bufferIn.charAt(presentIndex))) ||
 739:                                     (bufferIn.charAt(presentIndex) == '\t')))
 740:                             {
 741:                                 // for each tab, insert tabSize spaces 
 742:                                 if (bufferIn.charAt(presentIndex) == '\t')
 743:                                 {
 744:                                     for (int i = 0; i < tabSize; i++)
 745:                                     {
 746:                                         bufferIn.insert(presentIndex + 1, " ");
 747:                                     }
 748:                                     presentIndex++;
 749:                                     continue;
 750:                                 }
 751:                                 if (' ' == bufferIn.charAt(presentIndex))
 752:                                 {
 753:                                     // read a space so place a space
 754:                                     bufferOut.append(" ");
 755:                                     spaceLength += (" ").length();
 756:                                 }
 757:                                 else
 758:                                 {
 759:                                     // a white space character was read
 760:                                     bufferOut.append(bufferIn.charAt(
 761:                                         presentIndex));
 762:                                     ++spaceLength;
 763:                                 }
 764:                                 presentIndex++;
 765:                             }
 766:                             // check if line is empty 
 767:                             // (no printable characters on line)
 768:                             if ((presentIndex == (bufferIn.length() - 1)) ||
 769:                                 (Character.isWhitespace(bufferIn.charAt(
 770:                                      presentIndex))))
 771:                             {
 772:                                 spaceLength = 0;
 773:                             }
 774:                             // draw the line
 775:                             if (spaceLength > 1)
 776:                             {
 777:                                 bufferOut.insert((bufferOut.length() - 
 778:                                                   spaceLength), "<span class=" +
 779:                                                  "\"modulusLineStyle\">");
 780:                                 bufferOut.insert((bufferOut.length() - 
 781:                                                   (" ").length()), "</span>");
 782:                             }
 783:                             spaceLength = 0;
 784:                         }
 785:                     }
 786:                     else 
 787:                     {
 788:                         // line numbers are in lineNumberColor 
 789:                         bufferOut.append("<span class=\"lineNumberStyle\">");
 790:                         bufferOut.append(codeLineNumber);
 791:                         bufferOut.append(":</span> ");
 792:                     }
 793:                 }
 794:                 isNewLine = false;
 795:             }
 796:             // a state machine
 797:             presentChar = bufferIn.charAt(presentIndex);
 798:             if ((Character.isJavaIdentifierPart(presentChar)) ||
 799:                 ((State.IMPORT_NAME == presentState) && (presentChar == '*')))
 800:             {
 801:                 // this is an identifier
 802:                 bufferOut.append(presentChar);
 803:                 identifierLength++;
 804:                 continue; // keep adding characters until identifier is done
 805:             } 
 806:             if (identifierLength > 0)
 807:             {
 808:                 // identifier
 809:                 qualifiedIdentifierLength = 
 810:                     qualifiedIdentifierLength + identifierLength;
 811:                 if (bufferIn.charAt(presentIndex) == '.')
 812:                 {
 813:                     // qualified identifier 
 814:                     bufferOut.append(presentChar);
 815:                     qualifiedIdentifierLength++;
 816:                     identifierLength = 0;
 817:                     continue;  // keep adding characters to qualified identifier
 818:                 }
 819:                 String identifier = 
 820:                     bufferOut.toString().substring(bufferOut.length() - 
 821:                                                    identifierLength);
 822:                 if ((State.PARAM_VARIABLE == presentState))
 823:                 {
 824:                     // any identifier after a param in a javadoc is assumed to
 825:                     // be a variable 
 826:                     bufferOut.insert(bufferOut.length() -
 827:                                      qualifiedIdentifierLength,
 828:                                      "<span class=\"variableStyle\">");
 829:                     bufferOut.append("</span>");
 830:                     presentState = State.JAVADOC;
 831:                 }
 832:                 else if (State.JAVADOC == presentState)
 833:                 {
 834:                     // in javadoc state 
 835:                     if ((javadocTagCollection.contains(identifier)) &&
 836:                         (bufferIn.charAt(presentIndex - 
 837:                                          (identifierLength + 1)) == '@'))
 838:                     {
 839:                         // identifier is a javadocTag
 840:                         bufferOut.insert(bufferOut.length() - identifierLength,
 841:                                          "<span class=\"javadocTagStyle\">");
 842:                         bufferOut.append("</span>");
 843:                         if (("param").equals(identifier))
 844:                         {
 845:                             // any identifier after a param is assumed to
 846:                             // be a variable, get into a state to do this 
 847:                             presentState = State.PARAM_VARIABLE;
 848:                         }
 849:                     }
 850:                 }
 851:                 else if (State.IMPORT_NAME == presentState)
 852:                 {
 853:                     // import identifier
 854:                     bufferOut.insert(bufferOut.length() - 
 855:                                      qualifiedIdentifierLength,
 856:                                      "<span class=\"importNameStyle\">");
 857:                     bufferOut.append("</span>");
 858:                     presentState = State.TEXT;
 859:                 }
 860:                 else if (State.PACKAGE_NAME == presentState)
 861:                 {
 862:                     // package identifier
 863:                     bufferOut.insert(bufferOut.length() - 
 864:                                      qualifiedIdentifierLength,
 865:                                      "<span class=\"packageNameStyle\">");
 866:                     bufferOut.append("</span>");
 867:                     presentState = State.TEXT;
 868:                 }
 869:                 else if (State.TEXT == presentState)
 870:                 {
 871:                     if (keywordCollection.contains(identifier))
 872:                     {
 873:                         // identifier is a keyword 
 874:                         bufferOut.insert(bufferOut.length() - 
 875:                                          qualifiedIdentifierLength,
 876:                                          "<span class=\"keywordStyle\">");
 877:                         bufferOut.append("</span>");
 878:                         if (("import").equals(identifier))
 879:                         {
 880:                             // anything after an import in text mode must be 
 881:                             // an import name, so enter state to process this
 882:                             presentState = State.IMPORT_NAME;
 883:                         }
 884:                         else if (("package").equals(identifier))
 885:                         {
 886:                             // anything after an package in text mode must be 
 887:                             // an package name, so enter state to process this
 888:                             presentState = State.PACKAGE_NAME;
 889:                         }
 890:                     }
 891:                     else if (primitiveTypeCollection.contains(identifier))
 892:                     {
 893:                         // identifier is a primitive type  
 894:                         bufferOut.insert(bufferOut.length() -
 895:                                          qualifiedIdentifierLength,
 896:                                          "<span class=\"primitiveTypeStyle\">");
 897:                         bufferOut.append("</span>");
 898:                     }
 899:                     else if ((identifier.equals(identifier.toUpperCase())) &&
 900:                              (!(Character.isDigit(identifier.charAt(0)))))
 901:                     {
 902:                         // identifier is a constant
 903:                         bufferOut.insert(bufferOut.length() -
 904:                                          qualifiedIdentifierLength, 
 905:                                          "<span class=\"constantStyle\">");
 906:                         bufferOut.append("</span>");
 907:                     }
 908:                     else if (Character.isUpperCase(identifier.charAt(0)))
 909:                     {
 910:                         // identifier is a constructor or non-primitive type
 911:                         // eat white space 
 912:                         saveIndex = presentIndex;
 913:                         while (Character.isWhitespace(
 914:                                    bufferIn.charAt(saveIndex++)))
 915:                         {
 916:                             //empty body
 917:                         }
 918:                         if (bufferIn.charAt(--saveIndex) == '(')
 919:                         {   // identifier is a constructor
 920:                             bufferOut.insert(bufferOut.length() -
 921:                                              qualifiedIdentifierLength,
 922:                                              "<span class=" +
 923:                                              "\"constructorStyle\">");
 924:                             bufferOut.append("</span>");
 925:                         }
 926:                         else
 927:                         {
 928:                             // identifier is a non-primitive type 
 929:                             bufferOut.insert(bufferOut.length() -
 930:                                              qualifiedIdentifierLength,
 931:                                              "<span class=" + 
 932:                                              "\"nonPrimitiveTypeStyle\">");
 933:                             bufferOut.append("</span>");
 934:                         }
 935:                     }
 936:                     else if (!(Character.isDigit(identifier.charAt(0)) ||
 937:                                primitiveLiteralCollection.contains(identifier)))
 938:                     {
 939:                         // identifier is a method or a variable
 940:                         // eat white space
 941:                         saveIndex = presentIndex;
 942:                         while (Character.isWhitespace(
 943:                                    bufferIn.charAt(saveIndex++)))
 944:                         {
 945:                             // empty body
 946:                         }
 947:                         --saveIndex;
 948:                         // identifier is a method
 949:                         if (bufferIn.charAt(saveIndex) == '(')
 950:                         {
 951:                             bufferOut.insert(bufferOut.length() - 
 952:                                              qualifiedIdentifierLength, 
 953:                                              "<span class=\"methodStyle\">");
 954:                             bufferOut.append("</span>");                 
 955:                         }
 956:                         else if (bufferIn.charAt(saveIndex) == ',')
 957:                         {
 958:                             // comma seperated variables
 959:                             bufferOut.insert(bufferOut.length() - 
 960:                                              qualifiedIdentifierLength, 
 961:                                              "<span class=\"variableStyle\">");
 962:                             bufferOut.append("</span>"); 
 963:                         }
 964:                         else
 965:                         {
 966:                             // a variable
 967:                             // take care of cases such as array[index].variable
 968:                             if (bufferIn.charAt(presentIndex - 
 969:                                                 (qualifiedIdentifierLength 
 970:                                                  + 1)) == '.')
 971:                             {
 972:                                 qualifiedIdentifierLength++;
 973:                             }
 974:                             bufferOut.insert(bufferOut.length() - 
 975:                                              qualifiedIdentifierLength, 
 976:                                              "<span class=\"variableStyle\">");
 977:                             bufferOut.append("</span>");                        
 978:                         }
 979:                     }
 980:                     else
 981:                     {
 982:                         if (primitiveLiteralCollection.contains(identifier))
 983:                         {
 984:                             // primitiveLiteral (boolean or null)
 985:                             bufferOut.insert(bufferOut.length() -
 986:                                              identifierLength, "<span class=" +
 987:                                              "\"primitiveLiteralStyle\">");
 988:                             bufferOut.append("</span>");
 989:                         }
 990:                         // a numerical literal
 991:                         else 
 992:                         {
 993:                             if (((presentIndex - 
 994:                                   (qualifiedIdentifierLength + 1)) > 0) && 
 995:                                 (bufferIn.charAt(presentIndex - 
 996:                                      (qualifiedIdentifierLength + 1)) == '.'))
 997:                             {
 998:                                 qualifiedIdentifierLength++;
 999:                             }
1000:                             bufferOut.insert(bufferOut.length() - 
1001:                                              qualifiedIdentifierLength, 
1002:                                              "<span class=" +
1003:                                              "\"numericalLiteralStyle\">");
1004:                             bufferOut.append("</span>");
1005:                         }
1006:                     }
1007:                 }
1008:                 qualifiedIdentifierLength = 0;
1009:                 identifierLength = 0;
1010:             }
1011:             // process characters NOT in identifiers 
1012:             switch (presentChar)
1013:             {
1014:                 case '&': //ampersand
1015:                     bufferOut.append("&amp;");  // HTMLify character
1016:                     break;
1017:                 case '<': // less than sign
1018:                     bufferOut.append("&lt;");   // HTMLify character
1019:                     break;
1020:                 case '>': // greater than sign
1021:                     bufferOut.append("&gt;");   // HTMLify character
1022:                     break;
1023:                 case '\"': // double quote
1024:                     bufferOut.append("&quot;"); // HTMLify character
1025:                     if (State.TEXT == presentState)
1026:                     {
1027:                         presentState = State.DOUBLE_QUOTE;
1028:                         bufferOut.insert(bufferOut.length()-("&quot;").length(),
1029:                                          "<span class=\"doubleQuoteStyle\">");
1030:                     }   
1031:                     else if (State.DOUBLE_QUOTE == presentState)
1032:                     {
1033:                         presentState = State.TEXT;
1034:                         bufferOut.append("</span>");
1035:                     }
1036:                     break;
1037:                 case '\'': // single quote
1038:                     bufferOut.append("\'");
1039:                     if (State.TEXT == presentState)
1040:                     {
1041:                         presentState = State.SINGLE_QUOTE;
1042:                         bufferOut.insert(bufferOut.length() - ("\'").length(), 
1043:                                          "<span class=\"singleQuoteStyle\">");
1044:                     }
1045:                     else if (State.SINGLE_QUOTE == presentState)
1046:                     {
1047:                         presentState = State.TEXT;
1048:                         bufferOut.append("</span>");
1049:                     }
1050:                     break;
1051:                 case '\\': // backslash
1052:                     bufferOut.append("\\");
1053:                     if ((State.DOUBLE_QUOTE == presentState) || 
1054:                          (State.SINGLE_QUOTE == presentState))
1055:                     {
1056:                         // treat as a character escape sequence 
1057:                         bufferOut.append(bufferIn.charAt(++presentIndex));
1058:                     }
1059:                     break;
1060:                 case '\t': // tab
1061:                     // replace tabs with tabsize number of spaces
1062:                     for (int i = 0; i < tabSize; i++) 
1063:                     {
1064:                         bufferOut.append(' ');
1065:                     }
1066:                     break;
1067:                 case '*': // star
1068:                     bufferOut.append("*");
1069:                     if ((State.TEXT ==  presentState) && 
1070:                         (bufferIn.charAt(presentIndex - 1) == '/'))
1071:                     {
1072:                         if (((bufferIn.length() - 1) > presentIndex)  &&
1073:                             (bufferIn.charAt(presentIndex + 1) == '*'))
1074:                         {
1075:                             presentState = State.JAVADOC;
1076:                             bufferOut.insert(bufferOut.length() - 
1077:                                              ("/*").length(), "<span class=" +
1078:                                              "\"javadocCommentStyle\">");
1079:                         }
1080:                         else
1081:                         {                        
1082:                             presentState = State.TRADITIONAL_COMMENT;
1083:                             bufferOut.insert(bufferOut.length() - 
1084:                                              ("/*").length(), "<span class=" +
1085:                                              "\"traditionalCommentStyle\">");
1086:                         }
1087:                     }
1088:                     break;
1089:                 case '/': // foward slash
1090:                     bufferOut.append("/");
1091:                     if (((State.TRADITIONAL_COMMENT == presentState) || 
1092:                          (State.JAVADOC == presentState)) &&
1093:                         (bufferIn.charAt(presentIndex - 1) == '*'))
1094:                     {
1095:                         bufferOut.append("</span>");
1096:                         presentState = State.TEXT;
1097:                     }
1098:                     if ((State.TEXT == presentState) && 
1099:                         (presentIndex > 0)  &&
1100:                         (bufferIn.charAt(presentIndex - 1) == '/'))
1101:                     {   
1102:                         bufferOut.insert(bufferOut.length() - ("//").length(), 
1103:                                          "<span class=" + 
1104:                                          "\"singleLineCommentStyle\">");
1105:                         presentState = State.LINE_COMMENT;
1106:                     } 
1107:                     break;
1108:                 case '\r': // carriage return
1109:                     // fall through  
1110:                 case '\n': // line feed
1111:                     // all HTML lines end in \r\n
1112:                     if ((bufferIn.charAt(presentIndex) == '\r') &&
1113:                         ((bufferIn.length() - 1) > presentIndex)  &&
1114:                         (bufferIn.charAt(presentIndex + 1) == '\n'))
1115:                     {    
1116:                         ++presentIndex;
1117:                     }
1118:                     // end single line comments
1119:                     if (State.LINE_COMMENT == presentState)
1120:                     {
1121:                         bufferOut.append("</span>");
1122:                         presentState = State.TEXT;
1123:                     }
1124:                     // end of block  
1125:                     if ((lineModulus > 0) && hasLineModulusCodeBlocks && 
1126:                         ((codeLineNumber%lineModulus == 0) && !isNewBlock))
1127:                     {
1128:                         // end multi-line spanning states
1129:                         if ((State.TRADITIONAL_COMMENT == presentState) ||
1130:                             (State.JAVADOC == presentState))
1131:                         {
1132:                              bufferOut.append("</span>");
1133:                         }
1134:                         bufferOut.append("\r\n");
1135:                         bufferOut.append("</pre>\r\n");
1136:                         bufferOut.append("   </div>\r\n");
1137:                         bufferOut.append("<pre class=\"");
1138:                         bufferOut.append("modulusBlockPREStyle\">\r\n");
1139:                         // restart multi-line spanning states
1140:                         if (State.TRADITIONAL_COMMENT == presentState)
1141:                         {
1142:                             bufferOut.append("<span class=" +
1143:                                              "\"traditionalCommentStyle\">");
1144:                         }
1145:                         if (State.JAVADOC == presentState)
1146:                         {
1147:                             bufferOut.append("<span class=" +
1148:                                              "\"javadocCommentStyle\">");
1149:                         }
1150:                     }
1151:                     else
1152:                     {
1153:                         // div automatically starts new line 
1154:                         bufferOut.append("\r\n");
1155:                     }
1156:                     isNewLine = true;
1157:                     break;
1158:                 case 0: // nul character
1159:                     if ((State.LINE_COMMENT == presentState) && 
1160:                         (presentIndex == (bufferIn.length() - 1)))
1161:                     {
1162:                         bufferOut.append("</span>");
1163:                     }
1164:                     break;
1165:                 default:  // everything else 
1166:                     bufferOut.append(presentChar);
1167:             }
1168:             qualifiedIdentifierLength = 0;
1169:         }
1170:         bufferOut.append("</pre>\r\n");
1171:         // end block early if no more source code
1172:         if ((lineModulus > 0) && hasLineModulusCodeBlocks && !isNewBlock && 
1173:             (codeLineNumber%lineModulus != 0))
1174:         {
1175:             bufferOut.append("   </div>\r\n");
1176:         }
1177:         bufferOut.append("  </div>\r\n");  // end div of sourceCodeStyle 
1178:         // if code snippet then don't add ending tags of xhtml page
1179:         if (!isCodeSnippet)
1180:         {
1181:             // if footer mode then add a footer
1182:             if (hasFooter)
1183:             {
1184:                 bufferOut.append("  <hr />\r\n");
1185:                 bufferOut.append("  <div id=\"footer\">\r\n");
1186:                 if (hasFooterIcons)
1187:                 {
1188:                     if (hasFooterDate)
1189:                     {
1190:                         bufferOut.append("   <script type=\"text/javaScript\"");
1191:                         bufferOut.append(">\r\n");
1192:                         bufferOut.append("    <!-- // <![CDATA[\r\n");
1193:                         bufferOut.append("     document.write(\"Document last");
1194:                         bufferOut.append(" modified on \"");
1195:                         bufferOut.append(" + document.lastModified + ");
1196:                         bufferOut.append("\"<br />\");\r\n");
1197:                         bufferOut.append("    // ]]> -->\r\n");
1198:                         bufferOut.append("   </script>\r\n");
1199:                     }
1200:                     bufferOut.append("   <a href=\"");
1201:                     bufferOut.append("http://validator.w3.org/check/referer");
1202:                     bufferOut.append("\">\r\n");
1203:                     bufferOut.append("    <img class=\"iconStyle\" src=\"");
1204:                     bufferOut.append("http://www.w3.org/Icons/");
1205:                     if (isXHTML_1_1)
1206:                     {
1207:                         bufferOut.append("valid-xhtml11\"\r\n");
1208:                         bufferOut.append("         alt=\"Valid XHTML 1.1!\"");
1209:                     }
1210:                     else
1211:                     {
1212:                         bufferOut.append("valid-xhtml10\"\r\n");
1213:                         bufferOut.append("         alt=\"Valid XHTML 1.0!\"");
1214:                     }
1215:                     bufferOut.append(" height=\"31\" ");
1216:                     bufferOut.append("width=\"88\" />\r\n");
1217:                     bufferOut.append("   </a>\r\n");
1218:                     bufferOut.append("   &#160;\r\n");
1219:                     bufferOut.append("   <a href=\"");
1220:                     bufferOut.append("http://jigsaw.w3.org");
1221:                     bufferOut.append("/css-validator/check/referer");
1222:                     bufferOut.append("\">\r\n");
1223:                     bufferOut.append("    <img class=\"iconStyle\" src=\"");
1224:                     bufferOut.append("http://jigsaw.w3.org/");
1225:                     bufferOut.append("css-validator/images/vcss");
1226:                     bufferOut.append("\"\r\n");
1227:                     bufferOut.append("         alt=\"Valid CSS!\"");
1228:                     bufferOut.append(" height=\"31\" width=\"88\" />\r\n");
1229:                     bufferOut.append("   </a>\r\n");
1230:                 }
1231:                 else
1232:                 {
1233:                     bufferOut.append("   This is a valid\r\n"); 
1234:                     bufferOut.append("   <a href=\"http://"); 
1235:                     bufferOut.append("validator.w3.org/check/referer");
1236:                     if (isXHTML_1_1)
1237:                     {
1238:                         bufferOut.append("\">XHTML 1.1</a>\r\n");
1239:                     }
1240:                     else
1241:                     {
1242:                         bufferOut.append("\">XHTML 1.0</a>\r\n");
1243:                     }
1244:                     bufferOut.append("   with\r\n");
1245:                     bufferOut.append("   <a href=\"http://");
1246:                     bufferOut.append("jigsaw.w3.org");
1247:                     bufferOut.append("/css-validator/check/referer");
1248:                     bufferOut.append("\">CSS</a>\r\n");
1249:                     bufferOut.append("   document \r\n"); 
1250:                     if (hasFooterDate)
1251:                     {
1252:                         bufferOut.append("   <script type=\"text/javaScript\"");
1253:                         bufferOut.append(">\r\n");
1254:                         bufferOut.append("    <!-- // <![CDATA[\r\n");
1255:                         bufferOut.append("     document.write(\"last modified");
1256:                         bufferOut.append(" on \" + document.lastModified);");
1257:                         bufferOut.append("\r\n");
1258:                         bufferOut.append("    // ]]> -->\r\n");
1259:                         bufferOut.append("   </script>\r\n");
1260:                     }
1261:                 }
1262:                 bufferOut.append("  </div>\r\n");
1263:             }
1264:             bufferOut.append(" </body>\r\n");
1265:             bufferOut.append("</html>\r\n");
1266:         }
1267:         return bufferOut.toString();
1268:     }
1269: }