OSDN Git Service

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