OSDN Git Service

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