View Javadoc

1   /*
2    *  Java HTML Tidy - JTidy
3    *  HTML parser and pretty printer
4    *
5    *  Copyright (c) 1998-2000 World Wide Web Consortium (Massachusetts
6    *  Institute of Technology, Institut National de Recherche en
7    *  Informatique et en Automatique, Keio University). All Rights
8    *  Reserved.
9    *
10   *  Contributing Author(s):
11   *
12   *     Dave Raggett <dsr@w3.org>
13   *     Andy Quick <ac.quick@sympatico.ca> (translation to Java)
14   *     Gary L Peskin <garyp@firstech.com> (Java development)
15   *     Sami Lempinen <sami@lempinen.net> (release management)
16   *     Fabrizio Giustina <fgiust at users.sourceforge.net>
17   *
18   *  The contributing author(s) would like to thank all those who
19   *  helped with testing, bug fixes, and patience.  This wouldn't
20   *  have been possible without all of you.
21   *
22   *  COPYRIGHT NOTICE:
23   *
24   *  This software and documentation is provided "as is," and
25   *  the copyright holders and contributing author(s) make no
26   *  representations or warranties, express or implied, including
27   *  but not limited to, warranties of merchantability or fitness
28   *  for any particular purpose or that the use of the software or
29   *  documentation will not infringe any third party patents,
30   *  copyrights, trademarks or other rights.
31   *
32   *  The copyright holders and contributing author(s) will not be
33   *  liable for any direct, indirect, special or consequential damages
34   *  arising out of any use of the software or documentation, even if
35   *  advised of the possibility of such damage.
36   *
37   *  Permission is hereby granted to use, copy, modify, and distribute
38   *  this source code, or portions hereof, documentation and executables,
39   *  for any purpose, without fee, subject to the following restrictions:
40   *
41   *  1. The origin of this source code must not be misrepresented.
42   *  2. Altered versions must be plainly marked as such and must
43   *     not be misrepresented as being the original source.
44   *  3. This Copyright notice may not be removed or altered from any
45   *     source or altered source distribution.
46   *
47   *  The copyright holders and contributing author(s) specifically
48   *  permit, without fee, and encourage the use of this source code
49   *  as a component for supporting the Hypertext Markup Language in
50   *  commercial products. If you use this source code in a product,
51   *  acknowledgment is not required but would be appreciated.
52   *
53   */
54  package org.w3c.tidy;
55  
56  import java.io.FileInputStream;
57  import java.io.FileNotFoundException;
58  import java.io.FileOutputStream;
59  import java.io.FileWriter;
60  import java.io.IOException;
61  import java.io.InputStream;
62  import java.io.OutputStream;
63  import java.io.PrintWriter;
64  import java.io.Reader;
65  import java.io.Serializable;
66  import java.io.Writer;
67  import java.util.HashMap;
68  import java.util.Map;
69  import java.util.Properties;
70  
71  
72  /**
73   * HTML parser and pretty printer.
74   * @author Dave Raggett <a href="mailto:dsr@w3.org">dsr@w3.org </a>
75   * @author Andy Quick <a href="mailto:ac.quick@sympatico.ca">ac.quick@sympatico.ca </a> (translation to Java)
76   * @author Fabrizio Giustina
77   * @version $Revision: 807 $ ($Author: fgiust $)
78   */
79  public class Tidy implements Serializable
80  {
81  
82      /**
83       * Serial Version UID to avoid problems during serialization.
84       */
85      static final long serialVersionUID = -2794371560623987718L;
86  
87      /**
88       * Alias for configuration options accepted in command line.
89       */
90      private static final Map CMDLINE_ALIAS = new HashMap();
91  
92      static
93      {
94          CMDLINE_ALIAS.put("xml", "input-xml");
95          CMDLINE_ALIAS.put("xml", "output-xhtml");
96          CMDLINE_ALIAS.put("asxml", "output-xhtml");
97          CMDLINE_ALIAS.put("ashtml", "output-html");
98          CMDLINE_ALIAS.put("omit", "hide-endtags");
99          CMDLINE_ALIAS.put("upper", "uppercase-tags");
100         CMDLINE_ALIAS.put("raw", "output-raw");
101         CMDLINE_ALIAS.put("numeric", "numeric-entities");
102         CMDLINE_ALIAS.put("change", "write-back");
103         CMDLINE_ALIAS.put("update", "write-back");
104         CMDLINE_ALIAS.put("modify", "write-back");
105         CMDLINE_ALIAS.put("errors", "only-errors");
106         CMDLINE_ALIAS.put("slides", "split");
107         CMDLINE_ALIAS.put("lang", "language");
108         CMDLINE_ALIAS.put("w", "wrap");
109         CMDLINE_ALIAS.put("file", "error-file");
110         CMDLINE_ALIAS.put("f", "error-file");
111     }
112 
113     /**
114      * Error output stream.
115      */
116     private PrintWriter errout;
117 
118     private PrintWriter stderr;
119 
120     private Configuration configuration;
121 
122     private String inputStreamName = "InputStream";
123 
124     private int parseErrors;
125 
126     private int parseWarnings;
127 
128     private Report report;
129 
130     /**
131      * Instantiates a new Tidy instance. It's reccomended that a new instance is used at each parsing.
132      */
133     public Tidy()
134     {
135         this.report = new Report();
136         configuration = new Configuration(this.report);
137 
138         TagTable tt = new TagTable();
139         tt.setConfiguration(configuration);
140         configuration.tt = tt;
141 
142         configuration.errfile = null;
143         stderr = new PrintWriter(System.err, true);
144         errout = stderr;
145     }
146 
147     /**
148      * Returns the actual configuration
149      * @return tidy configuration
150      */
151     public Configuration getConfiguration()
152     {
153         return configuration;
154     }
155 
156     public PrintWriter getStderr()
157     {
158         return stderr;
159     }
160 
161     /**
162      * ParseErrors - the number of errors that occurred in the most recent parse operation.
163      * @return number of errors that occurred in the most recent parse operation.
164      */
165     public int getParseErrors()
166     {
167         return parseErrors;
168     }
169 
170     /**
171      * ParseWarnings - the number of warnings that occurred in the most recent parse operation.
172      * @return number of warnings that occurred in the most recent parse operation.
173      */
174     public int getParseWarnings()
175     {
176         return parseWarnings;
177     }
178 
179     /**
180      * InputStreamName - the name of the input stream (printed in the header information).
181      * @param name input stream name
182      */
183     public void setInputStreamName(String name)
184     {
185         if (name != null)
186         {
187             inputStreamName = name;
188         }
189     }
190 
191     public String getInputStreamName()
192     {
193         return inputStreamName;
194     }
195 
196     /**
197      * Errout - the error output stream.
198      * @return error output stream.
199      */
200     public PrintWriter getErrout()
201     {
202         return errout;
203     }
204 
205     public void setErrout(PrintWriter out)
206     {
207         this.errout = out;
208     }
209 
210     /**
211      * Sets the configuration from a configuration file.
212      * @param filename configuration file name/path.
213      */
214     public void setConfigurationFromFile(String filename)
215     {
216         configuration.parseFile(filename);
217     }
218 
219     /**
220      * Sets the configuration from a properties object.
221      * @param props Properties object
222      */
223     public void setConfigurationFromProps(Properties props)
224     {
225         configuration.addProps(props);
226     }
227 
228     /**
229      * Creates an empty DOM Document.
230      * @return a new org.w3c.dom.Document
231      */
232     public static org.w3c.dom.Document createEmptyDocument()
233     {
234         Node document = new Node(Node.ROOT_NODE, new byte[0], 0, 0);
235         Node node = new Node(Node.START_TAG, new byte[0], 0, 0, "html", new TagTable());
236         if (document != null && node != null)
237         {
238             document.insertNodeAtStart(node);
239             return (org.w3c.dom.Document) document.getAdapter();
240         }
241 
242         return null;
243     }
244 
245     /**
246      * Reads from the given input and returns the root Node. If out is non-null, pretty prints to out. Warning: caller
247      * is responsible for calling close() on input and output after calling this method.
248      * @param in input
249      * @param out optional destination for pretty-printed document
250      * @return parsed org.w3c.tidy.Node
251      */
252     public Node parse(InputStream in, OutputStream out)
253     {
254 
255         StreamIn streamIn = StreamInFactory.getStreamIn(configuration, in);
256 
257         Out o = null;
258         if (out != null)
259         {
260             o = OutFactory.getOut(this.configuration, out); // normal output stream
261         }
262 
263         return parse(streamIn, o);
264     }
265 
266     /**
267      * Reads from the given input and returns the root Node. If out is non-null, pretty prints to out. Warning: caller
268      * is responsible for calling close() on input and output after calling this method.
269      * @param in input
270      * @param out optional destination for pretty-printed document
271      * @return parsed org.w3c.tidy.Node
272      */
273     public Node parse(Reader in, OutputStream out)
274     {
275 
276         StreamIn streamIn = StreamInFactory.getStreamIn(configuration, in);
277 
278         Out o = null;
279         if (out != null)
280         {
281             o = OutFactory.getOut(this.configuration, out); // normal output stream
282         }
283 
284         return parse(streamIn, o);
285     }
286 
287     /**
288      * Reads from the given input and returns the root Node. If out is non-null, pretty prints to out. Warning: caller
289      * is responsible for calling close() on input and output after calling this method.
290      * @param in input
291      * @param out optional destination for pretty-printed document
292      * @return parsed org.w3c.tidy.Node
293      */
294     public Node parse(Reader in, Writer out)
295     {
296         StreamIn streamIn = StreamInFactory.getStreamIn(configuration, in);
297 
298         Out o = null;
299         if (out != null)
300         {
301             o = OutFactory.getOut(this.configuration, out); // normal output stream
302         }
303 
304         return parse(streamIn, o);
305     }
306 
307     /**
308      * Reads from the given input and returns the root Node. If out is non-null, pretty prints to out. Warning: caller
309      * is responsible for calling close() on input and output after calling this method.
310      * @param in input
311      * @param out optional destination for pretty-printed document
312      * @return parsed org.w3c.tidy.Node
313      */
314     public Node parse(InputStream in, Writer out)
315     {
316         StreamIn streamIn = StreamInFactory.getStreamIn(configuration, in);
317 
318         Out o = null;
319         if (out != null)
320         {
321             o = OutFactory.getOut(this.configuration, out); // normal output stream
322         }
323 
324         return parse(streamIn, o);
325     }
326 
327     /**
328      * Parses InputStream in and returns a DOM Document node. If out is non-null, pretty prints to OutputStream out.
329      * @param in input stream
330      * @param out optional output stream
331      * @return parsed org.w3c.dom.Document
332      */
333     public org.w3c.dom.Document parseDOM(InputStream in, OutputStream out)
334     {
335         Node document = parse(in, out);
336         if (document != null)
337         {
338             return (org.w3c.dom.Document) document.getAdapter();
339         }
340         return null;
341     }
342 
343     /**
344      * Pretty-prints a DOM Document. Must be an instance of org.w3c.tidy.DOMDocumentImpl. Caller is responsible for
345      * closing the outputStream after calling this method.
346      * @param doc org.w3c.dom.Document
347      * @param out output stream
348      */
349     public void pprint(org.w3c.dom.Document doc, OutputStream out)
350     {
351         if (!(doc instanceof DOMDocumentImpl))
352         {
353             // @todo should we inform users that tidy can't print a generic Document or change the method signature?
354             return;
355         }
356 
357         pprint(((DOMDocumentImpl) doc).adaptee, out);
358     }
359 
360     /**
361      * Pretty-prints a DOM Node. Caller is responsible for closing the outputStream after calling this method.
362      * @param node org.w3c.dom.Node. Must be an instance of org.w3c.tidy.DOMNodeImpl.
363      * @param out output stream
364      */
365     public void pprint(org.w3c.dom.Node node, OutputStream out)
366     {
367         if (!(node instanceof DOMNodeImpl))
368         {
369             // @todo should we inform users than tidy can't print a generic Node or change the method signature?
370             return;
371         }
372 
373         pprint(((DOMNodeImpl) node).adaptee, out);
374     }
375 
376     /**
377      * Internal routine that actually does the parsing.
378      * @param streamIn tidy StreamIn
379      * @param o tidy Out
380      * @return parsed org.w3c.tidy.Node
381      */
382     private Node parse(StreamIn streamIn, Out o)
383     {
384         Lexer lexer;
385         Node document = null;
386         Node doctype;
387         PPrint pprint;
388 
389         if (errout == null)
390         {
391             return null;
392         }
393 
394         // ensure config is self-consistent
395         configuration.adjust();
396 
397         parseErrors = 0;
398         parseWarnings = 0;
399 
400         lexer = new Lexer(streamIn, configuration, this.report);
401         lexer.errout = errout;
402 
403         // store pointer to lexer in input stream to allow character encoding errors to be reported
404         streamIn.setLexer(lexer);
405 
406         this.report.setFilename(inputStreamName); // #431895 - fix by Dave Bryan 04 Jan 01
407 
408         if (!configuration.quiet)
409         {
410             this.report.helloMessage(errout);
411         }
412 
413         // Tidy doesn't alter the doctype for generic XML docs
414         if (configuration.xmlTags)
415         {
416             document = ParserImpl.parseXMLDocument(lexer);
417             if (!document.checkNodeIntegrity())
418             {
419                 if (!configuration.quiet)
420                 {
421                     report.badTree(errout);
422                 }
423                 return null;
424             }
425         }
426         else
427         {
428             lexer.warnings = 0;
429 
430             document = ParserImpl.parseDocument(lexer);
431 
432             if (!document.checkNodeIntegrity())
433             {
434                 if (!configuration.quiet)
435                 {
436                     this.report.badTree(errout);
437                 }
438                 return null;
439             }
440 
441             Clean cleaner = new Clean(configuration.tt);
442 
443             // simplifies <b><b> ... </b> ... </b> etc.
444             cleaner.nestedEmphasis(document);
445 
446             // cleans up <dir> indented text </dir> etc.
447             cleaner.list2BQ(document);
448             cleaner.bQ2Div(document);
449 
450             // replaces i by em and b by strong
451             if (configuration.logicalEmphasis)
452             {
453                 cleaner.emFromI(document);
454             }
455 
456             if (configuration.word2000 && cleaner.isWord2000(document))
457             {
458                 // prune Word2000's <![if ...]> ... <![endif]>
459                 cleaner.dropSections(lexer, document);
460 
461                 // drop style & class attributes and empty p, span elements
462                 cleaner.cleanWord2000(lexer, document);
463             }
464 
465             // replaces presentational markup by style rules
466             if (configuration.makeClean || configuration.dropFontTags)
467             {
468                 cleaner.cleanTree(lexer, document);
469             }
470 
471             if (!document.checkNodeIntegrity())
472             {
473                 this.report.badTree(errout);
474                 return null;
475             }
476 
477             doctype = document.findDocType();
478 
479             // remember given doctype
480             if (doctype != null)
481             {
482                 doctype = (Node) doctype.clone();
483             }
484 
485             if (document.content != null)
486             {
487                 if (configuration.xHTML)
488                 {
489                     lexer.setXHTMLDocType(document);
490                 }
491                 else
492                 {
493                     lexer.fixDocType(document);
494                 }
495 
496                 if (configuration.tidyMark)
497                 {
498                     lexer.addGenerator(document);
499                 }
500             }
501 
502             // ensure presence of initial <?XML version="1.0"?>
503             if (configuration.xmlOut && configuration.xmlPi)
504             {
505                 lexer.fixXmlDecl(document);
506             }
507 
508             if (!configuration.quiet && document.content != null)
509             {
510                 this.report.reportVersion(errout, lexer, inputStreamName, doctype);
511             }
512         }
513 
514         if (!configuration.quiet)
515         {
516             parseWarnings = lexer.warnings;
517             parseErrors = lexer.errors;
518             this.report.reportNumWarnings(errout, lexer);
519         }
520 
521         if (!configuration.quiet && lexer.errors > 0 && !configuration.forceOutput)
522         {
523             this.report.needsAuthorIntervention(errout);
524         }
525 
526         if (!configuration.onlyErrors && (lexer.errors == 0 || configuration.forceOutput))
527         {
528             if (configuration.burstSlides)
529             {
530                 Node body;
531 
532                 body = null;
533                 // remove doctype to avoid potential clash with markup introduced when bursting into slides
534 
535                 // discard the document type
536                 doctype = document.findDocType();
537 
538                 if (doctype != null)
539                 {
540                     Node.discardElement(doctype);
541                 }
542 
543                 /* slides use transitional features */
544                 lexer.versions |= Dict.VERS_HTML40_LOOSE;
545 
546                 // and patch up doctype to match
547                 if (configuration.xHTML)
548                 {
549                     lexer.setXHTMLDocType(document);
550                 }
551                 else
552                 {
553                     lexer.fixDocType(document);
554                 }
555 
556                 // find the body element which may be implicit
557                 body = document.findBody(configuration.tt);
558 
559                 if (body != null)
560                 {
561                     pprint = new PPrint(configuration);
562                     if (!configuration.quiet)
563                     {
564                         this.report.reportNumberOfSlides(errout, pprint.countSlides(body));
565                     }
566                     pprint.createSlides(lexer, document);
567                 }
568                 else if (!configuration.quiet)
569                 {
570                     this.report.missingBody(errout);
571                 }
572             }
573             else if (o != null)
574             {
575                 pprint = new PPrint(configuration);
576 
577                 if (document.findDocType() == null)
578                 {
579                     // only use numeric character references if no doctype could be determined (e.g., because
580                     // the document contains proprietary features) to ensure well-formedness.
581                     configuration.numEntities = true;
582                 }
583                 if (configuration.bodyOnly)
584                 {
585                     // Feature request #434940 - fix by Dave Raggett/Ignacio Vazquez-Abrams 21 Jun 01
586                     pprint.printBody(o, lexer, document, configuration.xmlOut);
587                 }
588                 else if (configuration.xmlOut && !configuration.xHTML)
589                 {
590                     pprint.printXMLTree(o, (short) 0, 0, lexer, document);
591                 }
592                 else
593                 {
594                     pprint.printTree(o, (short) 0, 0, lexer, document);
595                 }
596 
597                 pprint.flushLine(o, 0);
598                 o.flush();
599             }
600 
601         }
602 
603         if (!configuration.quiet)
604         {
605             this.report.errorSummary(lexer);
606         }
607 
608         return document;
609     }
610 
611     /**
612      * Internal routine that actually does the parsing. The caller can pass either an InputStream or file name. If both
613      * are passed, the file name is preferred.
614      * @param in input stream (used only if <code>file</code> is null)
615      * @param file file name
616      * @param out output stream
617      * @return parsed org.w3c.tidy.Node
618      * @throws FileNotFoundException if <code>file</code> is not null but it can't be found
619      * @throws IOException for errors in reading input stream or file
620      */
621     private Node parse(InputStream in, String file, OutputStream out) throws FileNotFoundException, IOException
622     {
623 
624         StreamIn streamIn;
625         Out o = null;
626         boolean inputStreamOpen = false;
627         boolean outputStreamOpen = false;
628 
629         if (file != null)
630         {
631             in = new FileInputStream(file);
632             inputStreamOpen = true;
633             inputStreamName = file;
634         }
635         else if (in == null)
636         {
637             in = System.in;
638             inputStreamName = "stdin";
639         }
640 
641         streamIn = StreamInFactory.getStreamIn(configuration, in);
642 
643         if (configuration.writeback && (file != null))
644         {
645             out = new FileOutputStream(file);
646             outputStreamOpen = true;
647         }
648 
649         if (out != null)
650         {
651             o = OutFactory.getOut(this.configuration, out); // normal output stream
652         }
653 
654         Node node = parse(streamIn, o);
655 
656         // Try to close the InputStream but only if if we created it.
657         if (inputStreamOpen)
658         {
659             try
660             {
661                 in.close();
662             }
663             catch (IOException e)
664             {
665                 // ignore
666             }
667         }
668 
669         // Try to close the OutputStream but only if if we created it.
670         if (outputStreamOpen)
671         {
672             try
673             {
674                 out.close();
675             }
676             catch (IOException e)
677             {
678                 // ignore
679             }
680         }
681 
682         return node;
683 
684     }
685 
686     /**
687      * Pretty-prints a tidy Node.
688      * @param node org.w3c.tidy.Node
689      * @param out output stream
690      */
691     private void pprint(Node node, OutputStream out)
692     {
693         PPrint pprint;
694 
695         if (out != null)
696         {
697 
698             Out o = OutFactory.getOut(this.configuration, out);
699 
700             Lexer lexer = new Lexer(null, this.configuration, this.report);
701 
702             pprint = new PPrint(configuration);
703 
704             if (configuration.xmlTags)
705             {
706                 pprint.printXMLTree(o, (short) 0, 0, lexer, node);
707             }
708             else
709             {
710                 pprint.printTree(o, (short) 0, 0, lexer, node);
711             }
712 
713             pprint.flushLine(o, 0);
714 
715             try
716             {
717                 out.flush();
718             }
719             catch (IOException e)
720             {
721                 // ignore exception on flush?
722             }
723         }
724     }
725 
726     /**
727      * Command line interface to parser and pretty printer.
728      * @param argv command line parameters
729      */
730     public static void main(String[] argv)
731     {
732         Tidy tidy = new Tidy();
733         int returnCode = tidy.mainExec(argv);
734         System.exit(returnCode);
735     }
736 
737     /**
738      * Main method, but returns the return code as an int instead of calling System.exit(code). Needed for testing main
739      * method without shutting down tests.
740      * @param argv command line parameters
741      * @return return code
742      */
743     protected int mainExec(String[] argv)
744     {
745         String file;
746         int argCount = argv.length;
747         int argIndex = 0;
748 
749         // read command line
750         Properties properties = new Properties();
751 
752         while (argCount > 0)
753         {
754             if (argv[argIndex].startsWith("-"))
755             {
756                 // support -foo and --foo
757                 String argName = argv[argIndex].toLowerCase();
758                 while (argName.length() > 0 && argName.charAt(0) == '-')
759                 {
760                     argName = argName.substring(1);
761                 }
762 
763                 // "exclusive" options
764                 if (argName.equals("help") || argName.equals("h") || argName.equals("?"))
765                 {
766                     this.report.helpText(new PrintWriter(System.out, true));
767                     return 0;
768                 }
769                 else if (argName.equals("help-config"))
770                 {
771                     configuration.printConfigOptions(new PrintWriter(System.out, true), false);
772                     return 0;
773                 }
774                 else if (argName.equals("show-config"))
775                 {
776                     configuration.adjust(); // ensure config is self-consistent
777                     configuration.printConfigOptions(errout, true);
778                     return 0;
779                 }
780                 else if (argName.equals("version") || argName.equals("v"))
781                 {
782                     this.report.showVersion(errout);
783                     return 0;
784                 }
785 
786                 // optional value for non boolean options
787                 String argValue = null;
788                 if (argCount > 2 && !argv[argIndex + 1].startsWith("-"))
789                 {
790                     argValue = argv[argIndex + 1];
791                     --argCount;
792                     ++argIndex;
793                 }
794 
795                 // handle "special" aliases
796                 String alias = (String) CMDLINE_ALIAS.get(argName);
797                 if (alias != null)
798                 {
799                     argName = alias;
800                 }
801 
802                 if (Configuration.isKnownOption(argName)) // handle any standard config option
803                 {
804                     properties.setProperty(argName, (argValue == null ? "" : argName));
805                 }
806                 else if (argName.equals("config")) // parse a property file
807                 {
808                     if (argValue != null)
809                     {
810                         configuration.parseFile(argValue);
811                     }
812                 }
813                 else if (TidyUtils.isCharEncodingSupported(argName)) // handle any encoding name
814                 {
815                     properties.setProperty("char-encoding", argName);
816                 }
817                 else
818                 {
819 
820                     for (int i = 0; i < argName.length(); i++)
821                     {
822                         switch (argName.charAt(i))
823                         {
824                             case 'i' :
825                                 configuration.indentContent = true;
826                                 configuration.smartIndent = true;
827                                 break;
828 
829                             case 'o' :
830                                 configuration.hideEndTags = true;
831                                 break;
832 
833                             case 'u' :
834                                 configuration.upperCaseTags = true;
835                                 break;
836 
837                             case 'c' :
838                                 configuration.makeClean = true;
839                                 break;
840 
841                             case 'b' :
842                                 configuration.makeBare = true;
843                                 break;
844 
845                             case 'n' :
846                                 configuration.numEntities = true;
847                                 break;
848 
849                             case 'm' :
850                                 configuration.writeback = true;
851                                 break;
852 
853                             case 'e' :
854                                 configuration.onlyErrors = true;
855                                 break;
856 
857                             case 'q' :
858                                 configuration.quiet = true;
859                                 break;
860 
861                             default :
862                                 this.report.unknownOption(this.errout, argName.charAt(i));
863                                 break;
864                         }
865                     }
866                 }
867 
868                 --argCount;
869                 ++argIndex;
870                 continue;
871             }
872 
873             configuration.addProps(properties);
874 
875             // ensure config is self-consistent
876             configuration.adjust();
877 
878             // user specified error file
879             if (configuration.errfile != null)
880             {
881 
882                 String errorfile = "stderr";
883 
884                 // is it same as the currently opened file?
885                 if (!configuration.errfile.equals(errorfile))
886                 {
887                     // no so close previous error file
888 
889                     if (this.errout != this.stderr)
890                     {
891                         this.errout.close();
892                     }
893 
894                     // and try to open the new error file
895                     try
896                     {
897                         this.setErrout(new PrintWriter(new FileWriter(configuration.errfile), true));
898                         errorfile = configuration.errfile;
899                     }
900                     catch (IOException e)
901                     {
902                         // can't be opened so fall back to stderr
903                         errorfile = "stderr";
904                         this.setErrout(stderr);
905                     }
906                 }
907             }
908 
909             if (argCount > 0)
910             {
911                 file = argv[argIndex];
912             }
913             else
914             {
915                 file = "stdin";
916             }
917 
918             try
919             {
920                 parse(null, file, System.out);
921             }
922             catch (FileNotFoundException fnfe)
923             {
924                 this.report.unknownFile(this.errout, file);
925             }
926             catch (IOException ioe)
927             {
928                 this.report.unknownFile(this.errout, file);
929             }
930 
931             --argCount;
932             ++argIndex;
933 
934             if (argCount <= 0)
935             {
936                 break;
937             }
938         }
939 
940         if (this.parseErrors + this.parseWarnings > 0 && !configuration.quiet)
941         {
942             this.report.generalInfo(this.errout);
943         }
944 
945         if (this.errout != this.stderr)
946         {
947             this.errout.close();
948         }
949 
950         // return status can be used by scripts
951         if (this.parseErrors > 0)
952         {
953             return 2;
954         }
955 
956         if (this.parseWarnings > 0)
957         {
958             return 1;
959         }
960 
961         // 0 means all is ok
962         return 0;
963     }
964 
965     /**
966      * Attach a TidyMessageListener which will be notified for messages and errors.
967      * @param listener TidyMessageListener implementation
968      */
969     public void setMessageListener(TidyMessageListener listener)
970     {
971         this.report.addMessageListener(listener);
972     }
973 
974     /**
975      * <code>indent-spaces</code>- default indentation.
976      * @param spaces number of spaces used for indentation
977      * @see Configuration#spaces
978      */
979     public void setSpaces(int spaces)
980     {
981         configuration.spaces = spaces;
982     }
983 
984     /**
985      * <code>indent-spaces</code>- default indentation.
986      * @return number of spaces used for indentation
987      * @see Configuration#spaces
988      */
989     public int getSpaces()
990     {
991         return configuration.spaces;
992     }
993 
994     /**
995      * <code>wrap</code>- default wrap margin.
996      * @param wraplen default wrap margin
997      * @see Configuration#wraplen
998      */
999     public void setWraplen(int wraplen)
1000     {
1001         configuration.wraplen = wraplen;
1002     }
1003 
1004     /**
1005      * <code>wrap</code>- default wrap margin.
1006      * @return default wrap margin
1007      * @see Configuration#wraplen
1008      */
1009     public int getWraplen()
1010     {
1011         return configuration.wraplen;
1012     }
1013 
1014     /**
1015      * <code>tab-size</code>- tab size in chars.
1016      * @param tabsize tab size in chars
1017      * @see Configuration#tabsize
1018      */
1019     public void setTabsize(int tabsize)
1020     {
1021         configuration.tabsize = tabsize;
1022     }
1023 
1024     /**
1025      * <code>tab-size</code>- tab size in chars.
1026      * @return tab size in chars
1027      * @see Configuration#tabsize
1028      */
1029     public int getTabsize()
1030     {
1031         return configuration.tabsize;
1032     }
1033 
1034     /**
1035      * Errfile - file name to write errors to.
1036      * @param errfile file name to write errors to
1037      * @see Configuration#errfile
1038      */
1039     public void setErrfile(String errfile)
1040     {
1041         configuration.errfile = errfile;
1042     }
1043 
1044     /**
1045      * Errfile - file name to write errors to.
1046      * @return error file name
1047      * @see Configuration#errfile
1048      */
1049     public String getErrfile()
1050     {
1051         return configuration.errfile;
1052     }
1053 
1054     /**
1055      * writeback - if true then output tidied markup. NOTE: this property is ignored when parsing from an InputStream.
1056      * @param writeback <code>true</code>= output tidied markup
1057      * @see Configuration#writeback
1058      */
1059     public void setWriteback(boolean writeback)
1060     {
1061         configuration.writeback = writeback;
1062     }
1063 
1064     /**
1065      * writeback - if true then output tidied markup. NOTE: this property is ignored when parsing from an InputStream.
1066      * @return <code>true</code> if tidy will output tidied markup in input file
1067      * @see Configuration#writeback
1068      */
1069     public boolean getWriteback()
1070     {
1071         return configuration.writeback;
1072     }
1073 
1074     /**
1075      * only-errors - if true normal output is suppressed.
1076      * @param onlyErrors if <code>true</code> normal output is suppressed.
1077      * @see Configuration#onlyErrors
1078      */
1079     public void setOnlyErrors(boolean onlyErrors)
1080     {
1081         configuration.onlyErrors = onlyErrors;
1082     }
1083 
1084     /**
1085      * only-errors - if true normal output is suppressed.
1086      * @return <code>true</code> if normal output is suppressed.
1087      * @see Configuration#onlyErrors
1088      */
1089     public boolean getOnlyErrors()
1090     {
1091         return configuration.onlyErrors;
1092     }
1093 
1094     /**
1095      * show-warnings - show warnings? (errors are always shown).
1096      * @param showWarnings if <code>false</code> warnings are not shown
1097      * @see Configuration#showWarnings
1098      */
1099     public void setShowWarnings(boolean showWarnings)
1100     {
1101         configuration.showWarnings = showWarnings;
1102     }
1103 
1104     /**
1105      * show-warnings - show warnings? (errors are always shown).
1106      * @return <code>false</code> if warnings are not shown
1107      * @see Configuration#showWarnings
1108      */
1109     public boolean getShowWarnings()
1110     {
1111         return configuration.showWarnings;
1112     }
1113 
1114     /**
1115      * quiet - no 'Parsing X', guessed DTD or summary.
1116      * @param quiet <code>true</code>= don't output summary, warnings or errors
1117      * @see Configuration#quiet
1118      */
1119     public void setQuiet(boolean quiet)
1120     {
1121         configuration.quiet = quiet;
1122     }
1123 
1124     /**
1125      * quiet - no 'Parsing X', guessed DTD or summary.
1126      * @return <code>true</code> if tidy will not output summary, warnings or errors
1127      * @see Configuration#quiet
1128      */
1129     public boolean getQuiet()
1130     {
1131         return configuration.quiet;
1132     }
1133 
1134     /**
1135      * indent - indent content of appropriate tags.
1136      * @param indentContent indent content of appropriate tags
1137      * @see Configuration#indentContent
1138      */
1139     public void setIndentContent(boolean indentContent)
1140     {
1141         configuration.indentContent = indentContent;
1142     }
1143 
1144     /**
1145      * indent - indent content of appropriate tags.
1146      * @return <code>true</code> if tidy will indent content of appropriate tags
1147      * @see Configuration#indentContent
1148      */
1149     public boolean getIndentContent()
1150     {
1151         return configuration.indentContent;
1152     }
1153 
1154     /**
1155      * SmartIndent - does text/block level content effect indentation.
1156      * @param smartIndent <code>true</code> if text/block level content should effect indentation
1157      * @see Configuration#smartIndent
1158      */
1159     public void setSmartIndent(boolean smartIndent)
1160     {
1161         configuration.smartIndent = smartIndent;
1162     }
1163 
1164     /**
1165      * SmartIndent - does text/block level content effect indentation.
1166      * @return <code>true</code> if text/block level content should effect indentation
1167      * @see Configuration#smartIndent
1168      */
1169     public boolean getSmartIndent()
1170     {
1171         return configuration.smartIndent;
1172     }
1173 
1174     /**
1175      * hide-endtags - suppress optional end tags.
1176      * @param hideEndTags <code>true</code>= suppress optional end tags
1177      * @see Configuration#hideEndTags
1178      */
1179     public void setHideEndTags(boolean hideEndTags)
1180     {
1181         configuration.hideEndTags = hideEndTags;
1182     }
1183 
1184     /**
1185      * hide-endtags - suppress optional end tags.
1186      * @return <code>true</code> if tidy will suppress optional end tags
1187      * @see Configuration#hideEndTags
1188      */
1189     public boolean getHideEndTags()
1190     {
1191         return configuration.hideEndTags;
1192     }
1193 
1194     /**
1195      * input-xml - treat input as XML.
1196      * @param xmlTags <code>true</code> if tidy should treat input as XML
1197      * @see Configuration#xmlTags
1198      */
1199     public void setXmlTags(boolean xmlTags)
1200     {
1201         configuration.xmlTags = xmlTags;
1202     }
1203 
1204     /**
1205      * input-xml - treat input as XML.
1206      * @return <code>true</code> if tidy will treat input as XML
1207      * @see Configuration#xmlTags
1208      */
1209     public boolean getXmlTags()
1210     {
1211         return configuration.xmlTags;
1212     }
1213 
1214     /**
1215      * output-xml - create output as XML.
1216      * @param xmlOut <code>true</code> if tidy should create output as xml
1217      * @see Configuration#xmlOut
1218      */
1219     public void setXmlOut(boolean xmlOut)
1220     {
1221         configuration.xmlOut = xmlOut;
1222     }
1223 
1224     /**
1225      * output-xml - create output as XML.
1226      * @return <code>true</code> if tidy will create output as xml
1227      * @see Configuration#xmlOut
1228      */
1229     public boolean getXmlOut()
1230     {
1231         return configuration.xmlOut;
1232     }
1233 
1234     /**
1235      * output-xhtml - output extensible HTML.
1236      * @param xhtml <code>true</code> if tidy should output XHTML
1237      * @see Configuration#xHTML
1238      */
1239     public void setXHTML(boolean xhtml)
1240     {
1241         configuration.xHTML = xhtml;
1242     }
1243 
1244     /**
1245      * output-xhtml - output extensible HTML.
1246      * @return <code>true</code> if tidy will output XHTML
1247      * @see Configuration#xHTML
1248      */
1249     public boolean getXHTML()
1250     {
1251         return configuration.xHTML;
1252     }
1253 
1254     /**
1255      * uppercase-tags - output tags in upper case.
1256      * @param upperCaseTags <code>true</code> if tidy should output tags in upper case (default is lowercase)
1257      * @see Configuration#upperCaseTags
1258      */
1259     public void setUpperCaseTags(boolean upperCaseTags)
1260     {
1261         configuration.upperCaseTags = upperCaseTags;
1262     }
1263 
1264     /**
1265      * uppercase-tags - output tags in upper case.
1266      * @return <code>true</code> if tidy should will tags in upper case
1267      * @see Configuration#upperCaseTags
1268      */
1269     public boolean getUpperCaseTags()
1270     {
1271         return configuration.upperCaseTags;
1272     }
1273 
1274     /**
1275      * uppercase-attributes - output attributes in upper case.
1276      * @param upperCaseAttrs <code>true</code> if tidy should output attributes in upper case (default is lowercase)
1277      * @see Configuration#upperCaseAttrs
1278      */
1279     public void setUpperCaseAttrs(boolean upperCaseAttrs)
1280     {
1281         configuration.upperCaseAttrs = upperCaseAttrs;
1282     }
1283 
1284     /**
1285      * uppercase-attributes - output attributes in upper case.
1286      * @return <code>true</code> if tidy should will attributes in upper case
1287      * @see Configuration#upperCaseAttrs
1288      */
1289     public boolean getUpperCaseAttrs()
1290     {
1291         return configuration.upperCaseAttrs;
1292     }
1293 
1294     /**
1295      * make-clean - remove presentational clutter.
1296      * @param makeClean true to remove presentational clutter
1297      * @see Configuration#makeClean
1298      */
1299     public void setMakeClean(boolean makeClean)
1300     {
1301         configuration.makeClean = makeClean;
1302     }
1303 
1304     /**
1305      * make-clean - remove presentational clutter.
1306      * @return true if tidy will remove presentational clutter
1307      * @see Configuration#makeClean
1308      */
1309     public boolean getMakeClean()
1310     {
1311         return configuration.makeClean;
1312     }
1313 
1314     /**
1315      * make-bare - remove Microsoft cruft.
1316      * @param makeBare true to remove Microsoft cruft
1317      * @see Configuration#makeBare
1318      */
1319     public void setMakeBare(boolean makeBare)
1320     {
1321         configuration.makeBare = makeBare;
1322     }
1323 
1324     /**
1325      * make-clean - remove Microsoft cruft.
1326      * @return true if tidy will remove Microsoft cruft
1327      * @see Configuration#makeBare
1328      */
1329     public boolean getMakeBare()
1330     {
1331         return configuration.makeBare;
1332     }
1333 
1334     /**
1335      * break-before-br - output newline before &lt;br&gt;.
1336      * @param breakBeforeBR <code>true</code> if tidy should output a newline before &lt;br&gt;
1337      * @see Configuration#breakBeforeBR
1338      */
1339     public void setBreakBeforeBR(boolean breakBeforeBR)
1340     {
1341         configuration.breakBeforeBR = breakBeforeBR;
1342     }
1343 
1344     /**
1345      * break-before-br - output newline before &lt;br&gt;.
1346      * @return <code>true</code> if tidy will output a newline before &lt;br&gt;
1347      * @see Configuration#breakBeforeBR
1348      */
1349     public boolean getBreakBeforeBR()
1350     {
1351         return configuration.breakBeforeBR;
1352     }
1353 
1354     /**
1355      * <code>split</code>- create slides on each h2 element.
1356      * @param burstSlides <code>true</code> if tidy should create slides on each h2 element
1357      * @see Configuration#burstSlides
1358      */
1359     public void setBurstSlides(boolean burstSlides)
1360     {
1361         configuration.burstSlides = burstSlides;
1362     }
1363 
1364     /**
1365      * <code>split</code>- create slides on each h2 element.
1366      * @return <code>true</code> if tidy will create slides on each h2 element
1367      * @see Configuration#burstSlides
1368      */
1369     public boolean getBurstSlides()
1370     {
1371         return configuration.burstSlides;
1372     }
1373 
1374     /**
1375      * <code>numeric-entities</code>- output entities other than the built-in HTML entities in the numeric rather
1376      * than the named entity form.
1377      * @param numEntities <code>true</code> if tidy should output entities in the numeric form.
1378      * @see Configuration#numEntities
1379      */
1380     public void setNumEntities(boolean numEntities)
1381     {
1382         configuration.numEntities = numEntities;
1383     }
1384 
1385     /**
1386      * <code>numeric-entities</code>- output entities other than the built-in HTML entities in the numeric rather
1387      * than the named entity form.
1388      * @return <code>true</code> if tidy will output entities in the numeric form.
1389      * @see Configuration#numEntities
1390      */
1391     public boolean getNumEntities()
1392     {
1393         return configuration.numEntities;
1394     }
1395 
1396     /**
1397      * <code>quote-marks</code>- output " marks as &amp;quot;.
1398      * @param quoteMarks <code>true</code> if tidy should output " marks as &amp;quot;
1399      * @see Configuration#quoteMarks
1400      */
1401     public void setQuoteMarks(boolean quoteMarks)
1402     {
1403         configuration.quoteMarks = quoteMarks;
1404     }
1405 
1406     /**
1407      * <code>quote-marks</code>- output " marks as &amp;quot;.
1408      * @return <code>true</code> if tidy will output " marks as &amp;quot;
1409      * @see Configuration#quoteMarks
1410      */
1411     public boolean getQuoteMarks()
1412     {
1413         return configuration.quoteMarks;
1414     }
1415 
1416     /**
1417      * <code>quote-nbsp</code>- output non-breaking space as entity.
1418      * @param quoteNbsp <code>true</code> if tidy should output non-breaking space as entity
1419      * @see Configuration#quoteNbsp
1420      */
1421     public void setQuoteNbsp(boolean quoteNbsp)
1422     {
1423         configuration.quoteNbsp = quoteNbsp;
1424     }
1425 
1426     /**
1427      * <code>quote-nbsp</code>- output non-breaking space as entity.
1428      * @return <code>true</code> if tidy will output non-breaking space as entity
1429      * @see Configuration#quoteNbsp
1430      */
1431     public boolean getQuoteNbsp()
1432     {
1433         return configuration.quoteNbsp;
1434     }
1435 
1436     /**
1437      * <code>quote-ampersand</code>- output naked ampersand as &amp;.
1438      * @param quoteAmpersand <code>true</code> if tidy should output naked ampersand as &amp;
1439      * @see Configuration#quoteAmpersand
1440      */
1441     public void setQuoteAmpersand(boolean quoteAmpersand)
1442     {
1443         configuration.quoteAmpersand = quoteAmpersand;
1444     }
1445 
1446     /**
1447      * <code>quote-ampersand</code>- output naked ampersand as &amp;.
1448      * @return <code>true</code> if tidy will output naked ampersand as &amp;
1449      * @see Configuration#quoteAmpersand
1450      */
1451     public boolean getQuoteAmpersand()
1452     {
1453         return configuration.quoteAmpersand;
1454     }
1455 
1456     /**
1457      * <code>wrap-attributes</code>- wrap within attribute values.
1458      * @param wrapAttVals <code>true</code> if tidy should wrap within attribute values
1459      * @see Configuration#wrapAttVals
1460      */
1461     public void setWrapAttVals(boolean wrapAttVals)
1462     {
1463         configuration.wrapAttVals = wrapAttVals;
1464     }
1465 
1466     /**
1467      * <code>wrap-attributes</code>- wrap within attribute values.
1468      * @return <code>true</code> if tidy will wrap within attribute values
1469      * @see Configuration#wrapAttVals
1470      */
1471     public boolean getWrapAttVals()
1472     {
1473         return configuration.wrapAttVals;
1474     }
1475 
1476     /**
1477      * <code>wrap-script-literals</code>- wrap within JavaScript string literals.
1478      * @param wrapScriptlets <code>true</code> if tidy should wrap within JavaScript string literals
1479      * @see Configuration#wrapScriptlets
1480      */
1481     public void setWrapScriptlets(boolean wrapScriptlets)
1482     {
1483         configuration.wrapScriptlets = wrapScriptlets;
1484     }
1485 
1486     /**
1487      * <code>wrap-script-literals</code>- wrap within JavaScript string literals.
1488      * @return <code>true</code> if tidy will wrap within JavaScript string literals
1489      * @see Configuration#wrapScriptlets
1490      */
1491     public boolean getWrapScriptlets()
1492     {
1493         return configuration.wrapScriptlets;
1494     }
1495 
1496     /**
1497      * <code>wrap-sections</code>- wrap within &lt;![ ... ]&gt; section tags
1498      * @param wrapSection <code>true</code> if tidy should wrap within &lt;![ ... ]&gt; section tags
1499      * @see Configuration#wrapSection
1500      */
1501     public void setWrapSection(boolean wrapSection)
1502     {
1503         configuration.wrapSection = wrapSection;
1504     }
1505 
1506     /**
1507      * <code>wrap-sections</code>- wrap within &lt;![ ... ]&gt; section tags
1508      * @return <code>true</code> if tidy will wrap within &lt;![ ... ]&gt; section tags
1509      * @see Configuration#wrapSection
1510      */
1511     public boolean getWrapSection()
1512     {
1513         return configuration.wrapSection;
1514     }
1515 
1516     /**
1517      * <code>alt-text</code>- default text for alt attribute.
1518      * @param altText default text for alt attribute
1519      * @see Configuration#altText
1520      */
1521     public void setAltText(String altText)
1522     {
1523         configuration.altText = altText;
1524     }
1525 
1526     /**
1527      * <code>alt-text</code>- default text for alt attribute.
1528      * @return default text for alt attribute
1529      * @see Configuration#altText
1530      */
1531     public String getAltText()
1532     {
1533         return configuration.altText;
1534     }
1535 
1536     /**
1537      * <code>add-xml-pi</code>- add &lt;?xml?&gt; for XML docs.
1538      * @param xmlPi <code>true</code> if tidy should add &lt;?xml?&gt; for XML docs
1539      * @see Configuration#xmlPi
1540      */
1541     public void setXmlPi(boolean xmlPi)
1542     {
1543         configuration.xmlPi = xmlPi;
1544     }
1545 
1546     /**
1547      * <code>add-xml-pi</code>- add &lt;?xml?&gt; for XML docs.
1548      * @return <code>true</code> if tidy will add &lt;?xml?&gt; for XML docs
1549      * @see Configuration#xmlPi
1550      */
1551     public boolean getXmlPi()
1552     {
1553         return configuration.xmlPi;
1554     }
1555 
1556     /**
1557      * <code>drop-font-tags</code>- discard presentation tags.
1558      * @param dropFontTags <code>true</code> if tidy should discard presentation tags
1559      * @see Configuration#dropFontTags
1560      */
1561     public void setDropFontTags(boolean dropFontTags)
1562     {
1563         configuration.dropFontTags = dropFontTags;
1564     }
1565 
1566     /**
1567      * <code>drop-font-tags</code>- discard presentation tags.
1568      * @return <code>true</code> if tidy will discard presentation tags
1569      * @see Configuration#dropFontTags
1570      */
1571     public boolean getDropFontTags()
1572     {
1573         return configuration.dropFontTags;
1574     }
1575 
1576     /**
1577      * <code>drop-proprietary-attributes</code>- discard proprietary attributes.
1578      * @param dropProprietaryAttributes <code>true</code> if tidy should discard proprietary attributes
1579      * @see Configuration#dropProprietaryAttributes
1580      */
1581     public void setDropProprietaryAttributes(boolean dropProprietaryAttributes)
1582     {
1583         configuration.dropProprietaryAttributes = dropProprietaryAttributes;
1584     }
1585 
1586     /**
1587      * <code>drop-proprietary-attributes</code>- discard proprietary attributes.
1588      * @return <code>true</code> if tidy will discard proprietary attributes
1589      * @see Configuration#dropProprietaryAttributes
1590      */
1591     public boolean getDropProprietaryAttributes()
1592     {
1593         return configuration.dropProprietaryAttributes;
1594     }
1595 
1596     /**
1597      * <code>drop-empty-paras</code>- discard empty p elements.
1598      * @param dropEmptyParas <code>true</code> if tidy should discard empty p elements
1599      * @see Configuration#dropEmptyParas
1600      */
1601     public void setDropEmptyParas(boolean dropEmptyParas)
1602     {
1603         configuration.dropEmptyParas = dropEmptyParas;
1604     }
1605 
1606     /**
1607      * <code>drop-empty-paras</code>- discard empty p elements.
1608      * @return <code>true</code> if tidy will discard empty p elements
1609      * @see Configuration#dropEmptyParas
1610      */
1611     public boolean getDropEmptyParas()
1612     {
1613         return configuration.dropEmptyParas;
1614     }
1615 
1616     /**
1617      * <code>fix-bad-comments</code>- fix comments with adjacent hyphens.
1618      * @param fixComments <code>true</code> if tidy should fix comments with adjacent hyphens
1619      * @see Configuration#fixComments
1620      */
1621     public void setFixComments(boolean fixComments)
1622     {
1623         configuration.fixComments = fixComments;
1624     }
1625 
1626     /**
1627      * <code>fix-bad-comments</code>- fix comments with adjacent hyphens.
1628      * @return <code>true</code> if tidy will fix comments with adjacent hyphens
1629      * @see Configuration#fixComments
1630      */
1631     public boolean getFixComments()
1632     {
1633         return configuration.fixComments;
1634     }
1635 
1636     /**
1637      * <code>wrap-asp</code>- wrap within ASP pseudo elements.
1638      * @param wrapAsp <code>true</code> if tidy should wrap within ASP pseudo elements
1639      * @see Configuration#wrapAsp
1640      */
1641     public void setWrapAsp(boolean wrapAsp)
1642     {
1643         configuration.wrapAsp = wrapAsp;
1644     }
1645 
1646     /**
1647      * <code>wrap-asp</code>- wrap within ASP pseudo elements.
1648      * @return <code>true</code> if tidy will wrap within ASP pseudo elements
1649      * @see Configuration#wrapAsp
1650      */
1651     public boolean getWrapAsp()
1652     {
1653         return configuration.wrapAsp;
1654     }
1655 
1656     /**
1657      * <code>wrap-jste</code>- wrap within JSTE pseudo elements.
1658      * @param wrapJste <code>true</code> if tidy should wrap within JSTE pseudo elements
1659      * @see Configuration#wrapJste
1660      */
1661     public void setWrapJste(boolean wrapJste)
1662     {
1663         configuration.wrapJste = wrapJste;
1664     }
1665 
1666     /**
1667      * <code>wrap-jste</code>- wrap within JSTE pseudo elements.
1668      * @return <code>true</code> if tidy will wrap within JSTE pseudo elements
1669      * @see Configuration#wrapJste
1670      */
1671     public boolean getWrapJste()
1672     {
1673         return configuration.wrapJste;
1674     }
1675 
1676     /**
1677      * <code>wrap-php</code>- wrap within PHP pseudo elements.
1678      * @param wrapPhp <code>true</code> if tidy should wrap within PHP pseudo elements
1679      * @see Configuration#wrapPhp
1680      */
1681     public void setWrapPhp(boolean wrapPhp)
1682     {
1683         configuration.wrapPhp = wrapPhp;
1684     }
1685 
1686     /**
1687      * <code>wrap-php</code>- wrap within PHP pseudo elements.
1688      * @return <code>true</code> if tidy will wrap within PHP pseudo elements
1689      * @see Configuration#wrapPhp
1690      */
1691     public boolean getWrapPhp()
1692     {
1693         return configuration.wrapPhp;
1694     }
1695 
1696     /**
1697      * <code>fix-backslash</code>- fix URLs by replacing \ with /.
1698      * @param fixBackslash <code>true</code> if tidy should fix URLs by replacing \ with /
1699      * @see Configuration#fixBackslash
1700      */
1701     public void setFixBackslash(boolean fixBackslash)
1702     {
1703         configuration.fixBackslash = fixBackslash;
1704     }
1705 
1706     /**
1707      * <code>fix-backslash</code>- fix URLs by replacing \ with /.
1708      * @return <code>true</code> if tidy will fix URLs by replacing \ with /
1709      * @see Configuration#fixBackslash
1710      */
1711     public boolean getFixBackslash()
1712     {
1713         return configuration.fixBackslash;
1714     }
1715 
1716     /**
1717      * <code>indent-attributes</code>- newline+indent before each attribute.
1718      * @param indentAttributes <code>true</code> if tidy should output a newline+indent before each attribute
1719      * @see Configuration#indentAttributes
1720      */
1721     public void setIndentAttributes(boolean indentAttributes)
1722     {
1723         configuration.indentAttributes = indentAttributes;
1724     }
1725 
1726     /**
1727      * <code>indent-attributes</code>- newline+indent before each attribute.
1728      * @return <code>true</code> if tidy will output a newline+indent before each attribute
1729      * @see Configuration#indentAttributes
1730      */
1731     public boolean getIndentAttributes()
1732     {
1733         return configuration.indentAttributes;
1734     }
1735 
1736     /**
1737      * <code>doctype</code>- user specified doctype.
1738      * @param doctype <code>omit | auto | strict | loose | <em>fpi</em></code> where the <em>fpi </em> is a string
1739      * similar to &quot;-//ACME//DTD HTML 3.14159//EN&quot; Note: for <em>fpi </em> include the double-quotes in the
1740      * string.
1741      * @see Configuration#docTypeStr
1742      * @see Configuration#docTypeMode
1743      */
1744     public void setDocType(String doctype)
1745     {
1746         if (doctype != null)
1747         {
1748             configuration.docTypeStr = (String) ParsePropertyImpl.DOCTYPE.parse(doctype, "doctype", configuration);
1749         }
1750     }
1751 
1752     /**
1753      * <code>doctype</code>- user specified doctype.
1754      * @return <code>omit | auto | strict | loose | <em>fpi</em></code> where the <em>fpi </em> is a string similar
1755      * to &quot;-//ACME//DTD HTML 3.14159//EN&quot; Note: for <em>fpi </em> include the double-quotes in the string.
1756      * @see Configuration#docTypeStr
1757      * @see Configuration#docTypeMode
1758      */
1759     public String getDocType()
1760     {
1761         String result = null;
1762         switch (configuration.docTypeMode)
1763         {
1764             case Configuration.DOCTYPE_OMIT :
1765                 result = "omit";
1766                 break;
1767             case Configuration.DOCTYPE_AUTO :
1768                 result = "auto";
1769                 break;
1770             case Configuration.DOCTYPE_STRICT :
1771                 result = "strict";
1772                 break;
1773             case Configuration.DOCTYPE_LOOSE :
1774                 result = "loose";
1775                 break;
1776             case Configuration.DOCTYPE_USER :
1777                 result = configuration.docTypeStr;
1778                 break;
1779         }
1780         return result;
1781     }
1782 
1783     /**
1784      * <code>logical-emphasis</code>- replace i by em and b by strong.
1785      * @param logicalEmphasis <code>true</code> if tidy should replace i by em and b by strong
1786      * @see Configuration#logicalEmphasis
1787      */
1788     public void setLogicalEmphasis(boolean logicalEmphasis)
1789     {
1790         configuration.logicalEmphasis = logicalEmphasis;
1791     }
1792 
1793     /**
1794      * <code>logical-emphasis</code>- replace i by em and b by strong.
1795      * @return <code>true</code> if tidy will replace i by em and b by strong
1796      * @see Configuration#logicalEmphasis
1797      */
1798     public boolean getLogicalEmphasis()
1799     {
1800         return configuration.logicalEmphasis;
1801     }
1802 
1803     /**
1804      * <code>assume-xml-procins</code> This option specifies if Tidy should change the parsing of processing
1805      * instructions to require ?> as the terminator rather than >. This option is automatically set if the input is in
1806      * XML.
1807      * @param xmlPIs <code>true</code> if tidy should expect a ?> at the end of processing instructions
1808      * @see Configuration#xmlPIs
1809      */
1810     public void setXmlPIs(boolean xmlPIs)
1811     {
1812         configuration.xmlPIs = xmlPIs;
1813     }
1814 
1815     /**
1816      * <code>assume-xml-procins</code> This option specifies if Tidy should change the parsing of processing
1817      * instructions to require ?> as the terminator rather than >. This option is automatically set if the input is in
1818      * XML.
1819      * @return <code>true</code> if tidy will expect a ?> at the end of processing instructions
1820      * @see Configuration#xmlPIs
1821      */
1822     public boolean getXmlPIs()
1823     {
1824         return configuration.xmlPIs;
1825     }
1826 
1827     /**
1828      * <code>enclose-text</code>- if true text at body is wrapped in &lt;p&gt;'s.
1829      * @param encloseText <code>true</code> if tidy should wrap text at body in &lt;p&gt;'s.
1830      * @see Configuration#encloseBodyText
1831      */
1832     public void setEncloseText(boolean encloseText)
1833     {
1834         configuration.encloseBodyText = encloseText;
1835     }
1836 
1837     /**
1838      * <code>enclose-text</code>- if true text at body is wrapped in &lt;p&gt;'s.
1839      * @return <code>true</code> if tidy will wrap text at body in &lt;p&gt;'s.
1840      * @see Configuration#encloseBodyText
1841      */
1842     public boolean getEncloseText()
1843     {
1844         return configuration.encloseBodyText;
1845     }
1846 
1847     /**
1848      * <code>enclose-block-text</code>- if true text in blocks is wrapped in &lt;p&gt;'s.
1849      * @param encloseBlockText <code>true</code> if tidy should wrap text text in blocks in &lt;p&gt;'s.
1850      * @see Configuration#encloseBlockText
1851      */
1852     public void setEncloseBlockText(boolean encloseBlockText)
1853     {
1854         configuration.encloseBlockText = encloseBlockText;
1855     }
1856 
1857     /**
1858      * <code>enclose-block-text</code>- if true text in blocks is wrapped in &lt;p&gt;'s. return <code>true</code>
1859      * if tidy should will text text in blocks in &lt;p&gt;'s.
1860      * @see Configuration#encloseBlockText
1861      */
1862     public boolean getEncloseBlockText()
1863     {
1864         return configuration.encloseBlockText;
1865     }
1866 
1867     /**
1868      * <code>word-2000</code>- draconian cleaning for Word2000.
1869      * @param word2000 <code>true</code> if tidy should clean word2000 documents
1870      * @see Configuration#word2000
1871      */
1872     public void setWord2000(boolean word2000)
1873     {
1874         configuration.word2000 = word2000;
1875     }
1876 
1877     /**
1878      * <code>word-2000</code>- draconian cleaning for Word2000.
1879      * @return <code>true</code> if tidy will clean word2000 documents
1880      * @see Configuration#word2000
1881      */
1882     public boolean getWord2000()
1883     {
1884         return configuration.word2000;
1885     }
1886 
1887     /**
1888      * <code>tidy-mark</code>- add meta element indicating tidied doc.
1889      * @param tidyMark <code>true</code> if tidy should add meta element indicating tidied doc
1890      * @see Configuration#tidyMark
1891      */
1892     public void setTidyMark(boolean tidyMark)
1893     {
1894         configuration.tidyMark = tidyMark;
1895     }
1896 
1897     /**
1898      * <code>tidy-mark</code>- add meta element indicating tidied doc.
1899      * @return <code>true</code> if tidy will add meta element indicating tidied doc
1900      * @see Configuration#tidyMark
1901      */
1902     public boolean getTidyMark()
1903     {
1904         return configuration.tidyMark;
1905     }
1906 
1907     /**
1908      * <code>add-xml-space</code>- if set to yes adds xml:space attr as needed.
1909      * @param xmlSpace <code>true</code> if tidy should add xml:space attr as needed
1910      * @see Configuration#xmlSpace
1911      */
1912     public void setXmlSpace(boolean xmlSpace)
1913     {
1914         configuration.xmlSpace = xmlSpace;
1915     }
1916 
1917     /**
1918      * <code>add-xml-space</code>- if set to yes adds xml:space attr as needed.
1919      * @return <code>true</code> if tidy will add xml:space attr as needed
1920      * @see Configuration#xmlSpace
1921      */
1922     public boolean getXmlSpace()
1923     {
1924         return configuration.xmlSpace;
1925     }
1926 
1927     /**
1928      * <code>gnu-emacs</code>- if true format error output for GNU Emacs.
1929      * @param emacs <code>true</code> if tidy should format error output for GNU Emacs
1930      * @see Configuration#emacs
1931      */
1932     public void setEmacs(boolean emacs)
1933     {
1934         configuration.emacs = emacs;
1935     }
1936 
1937     /**
1938      * <code>gnu-emacs</code>- if true format error output for GNU Emacs.
1939      * @return <code>true</code> if tidy will format error output for GNU Emacs
1940      * @see Configuration#emacs
1941      */
1942     public boolean getEmacs()
1943     {
1944         return configuration.emacs;
1945     }
1946 
1947     /**
1948      * <code>literal-attributes</code>- if true attributes may use newlines.
1949      * @param literalAttribs <code>true</code> if attributes may use newlines
1950      * @see Configuration#literalAttribs
1951      */
1952     public void setLiteralAttribs(boolean literalAttribs)
1953     {
1954         configuration.literalAttribs = literalAttribs;
1955     }
1956 
1957     /**
1958      * <code>literal-attributes</code>- if true attributes may use newlines.
1959      * @return <code>true</code> if attributes may use newlines
1960      * @see Configuration#literalAttribs
1961      */
1962     public boolean getLiteralAttribs()
1963     {
1964         return configuration.literalAttribs;
1965     }
1966 
1967     /**
1968      * <code>print-body-only</code>- output BODY content only.
1969      * @param bodyOnly true = print only the document body
1970      * @see Configuration#bodyOnly
1971      */
1972     public void setPrintBodyOnly(boolean bodyOnly)
1973     {
1974         configuration.bodyOnly = bodyOnly;
1975     }
1976 
1977     /**
1978      * <code>print-body-only</code>- output BODY content only.
1979      * @return true if tidy will print only the document body
1980      */
1981     public boolean getPrintBodyOnly()
1982     {
1983         return configuration.bodyOnly;
1984     }
1985 
1986     /**
1987      * <code>fix-uri</code>- fix uri references applying URI encoding if necessary.
1988      * @param fixUri true = fix uri references
1989      * @see Configuration#fixUri
1990      */
1991     public void setFixUri(boolean fixUri)
1992     {
1993         configuration.fixUri = fixUri;
1994     }
1995 
1996     /**
1997      * <code>fix-uri</code>- output BODY content only.
1998      * @return true if tidy will fix uri references
1999      */
2000     public boolean getFixUri()
2001     {
2002         return configuration.fixUri;
2003     }
2004 
2005     /**
2006      * <code>lower-literals</code>- folds known attribute values to lower case.
2007      * @param lowerLiterals true = folds known attribute values to lower case
2008      * @see Configuration#lowerLiterals
2009      */
2010     public void setLowerLiterals(boolean lowerLiterals)
2011     {
2012         configuration.lowerLiterals = lowerLiterals;
2013     }
2014 
2015     /**
2016      * <code>lower-literals</code>- folds known attribute values to lower case.
2017      * @return true if tidy will folds known attribute values to lower case
2018      */
2019     public boolean getLowerLiterals()
2020     {
2021         return configuration.lowerLiterals;
2022     }
2023 
2024     /**
2025      * <code>hide-comments</code>- hides all (real) comments in output.
2026      * @param hideComments true = hides all comments in output
2027      * @see Configuration#hideComments
2028      */
2029     public void setHideComments(boolean hideComments)
2030     {
2031         configuration.hideComments = hideComments;
2032     }
2033 
2034     /**
2035      * <code>hide-comments</code>- hides all (real) comments in output.
2036      * @return true if tidy will hide all comments in output
2037      */
2038     public boolean getHideComments()
2039     {
2040         return configuration.hideComments;
2041     }
2042 
2043     /**
2044      * <code>indent-cdata</code>- indent CDATA sections.
2045      * @param indentCdata true = indent CDATA sections
2046      * @see Configuration#indentCdata
2047      */
2048     public void setIndentCdata(boolean indentCdata)
2049     {
2050         configuration.indentCdata = indentCdata;
2051     }
2052 
2053     /**
2054      * <code>indent-cdata</code>- indent CDATA sections.
2055      * @return true if tidy will indent CDATA sections
2056      */
2057     public boolean getIndentCdata()
2058     {
2059         return configuration.indentCdata;
2060     }
2061 
2062     /**
2063      * <code>force-output</code>- output document even if errors were found.
2064      * @param forceOutput true = output document even if errors were found
2065      * @see Configuration#forceOutput
2066      */
2067     public void setForceOutput(boolean forceOutput)
2068     {
2069         configuration.forceOutput = forceOutput;
2070     }
2071 
2072     /**
2073      * <code>force-output</code>- output document even if errors were found.
2074      * @return true if tidy will output document even if errors were found
2075      */
2076     public boolean getForceOutput()
2077     {
2078         return configuration.forceOutput;
2079     }
2080 
2081     /**
2082      * <code>show-errors</code>- set the number of errors to put out.
2083      * @param showErrors number of errors to put out
2084      * @see Configuration#showErrors
2085      */
2086     public void setShowErrors(int showErrors)
2087     {
2088         configuration.showErrors = showErrors;
2089     }
2090 
2091     /**
2092      * <code>show-errors</code>- number of errors to put out.
2093      * @return the number of errors tidy will put out
2094      */
2095     public int getShowErrors()
2096     {
2097         return configuration.showErrors;
2098     }
2099 
2100     /**
2101      * <code>ascii-chars</code>- convert quotes and dashes to nearest ASCII char.
2102      * @param asciiChars true = convert quotes and dashes to nearest ASCII char
2103      * @see Configuration#asciiChars
2104      */
2105     public void setAsciiChars(boolean asciiChars)
2106     {
2107         configuration.asciiChars = asciiChars;
2108     }
2109 
2110     /**
2111      * <code>ascii-chars</code>- convert quotes and dashes to nearest ASCII char.
2112      * @return true if tidy will convert quotes and dashes to nearest ASCII char
2113      */
2114     public boolean getAsciiChars()
2115     {
2116         return configuration.asciiChars;
2117     }
2118 
2119     /**
2120      * <code>join-classes</code>- join multiple class attributes.
2121      * @param joinClasses true = join multiple class attributes
2122      * @see Configuration#joinClasses
2123      */
2124     public void setJoinClasses(boolean joinClasses)
2125     {
2126         configuration.joinClasses = joinClasses;
2127     }
2128 
2129     /**
2130      * <code>join-classes</code>- join multiple class attributes.
2131      * @return true if tidy will join multiple class attributes
2132      */
2133     public boolean getJoinClasses()
2134     {
2135         return configuration.joinClasses;
2136     }
2137 
2138     /**
2139      * <code>join-styles</code>- join multiple style attributes.
2140      * @param joinStyles true = join multiple style attributes
2141      * @see Configuration#joinStyles
2142      */
2143     public void setJoinStyles(boolean joinStyles)
2144     {
2145         configuration.joinStyles = joinStyles;
2146     }
2147 
2148     /**
2149      * <code>join-styles</code>- join multiple style attributes.
2150      * @return true if tidy will join multiple style attributes
2151      */
2152     public boolean getJoinStyles()
2153     {
2154         return configuration.joinStyles;
2155     }
2156 
2157     /**
2158      * <code>trim-empty-elements</code>- trim empty elements.
2159      * @param trim-empty-elements true = trim empty elements
2160      * @see Configuration#trimEmpty
2161      */
2162     public void setTrimEmptyElements(boolean trimEmpty)
2163     {
2164         configuration.trimEmpty = trimEmpty;
2165     }
2166 
2167     /**
2168      * <code>trim-empty-elements</code>- trim empty elements.
2169      * @return true if tidy will trim empty elements
2170      */
2171     public boolean getTrimEmptyElements()
2172     {
2173         return configuration.trimEmpty;
2174     }
2175 
2176     /**
2177      * <code>replace-color</code>- replace hex color attribute values with names.
2178      * @param replaceColor true = replace hex color attribute values with names
2179      * @see Configuration#replaceColor
2180      */
2181     public void setReplaceColor(boolean replaceColor)
2182     {
2183         configuration.replaceColor = replaceColor;
2184     }
2185 
2186     /**
2187      * <code>replace-color</code>- replace hex color attribute values with names.
2188      * @return true if tidy will replace hex color attribute values with names
2189      */
2190     public boolean getReplaceColor()
2191     {
2192         return configuration.replaceColor;
2193     }
2194 
2195     /**
2196      * <code>escape-cdata</code>- replace CDATA sections with escaped text.
2197      * @param escapeCdata true = replace CDATA sections with escaped text
2198      * @see Configuration#escapeCdata
2199      */
2200     public void setEscapeCdata(boolean escapeCdata)
2201     {
2202         configuration.escapeCdata = escapeCdata;
2203     }
2204 
2205     /**
2206      * <code>escape-cdata</code> -replace CDATA sections with escaped text.
2207      * @return true if tidy will replace CDATA sections with escaped text
2208      */
2209     public boolean getEscapeCdata()
2210     {
2211         return configuration.escapeCdata;
2212     }
2213 
2214     /**
2215      * <code>repeated-attributes</code>- keep first or last duplicate attribute.
2216      * @param repeatedAttributes <code>Configuration.KEEP_FIRST | Configuration.KEEP_LAST</code>
2217      * @see Configuration#duplicateAttrs
2218      */
2219     public void setRepeatedAttributes(int repeatedAttributes)
2220     {
2221         configuration.duplicateAttrs = repeatedAttributes;
2222     }
2223 
2224     /**
2225      * <code>repeated-attributes</code>- keep first or last duplicate attribute.
2226      * @return <code>Configuration.KEEP_FIRST | Configuration.KEEP_LAST</code>
2227      */
2228     public int getRepeatedAttributes()
2229     {
2230         return configuration.duplicateAttrs;
2231     }
2232 
2233     /**
2234      * <code>keep-time</code>- if true last modified time is preserved.
2235      * @param keepFileTimes <code>true</code> if tidy should preserved last modified time in input file.
2236      * @todo <strong>this is NOT supported at this time. </strong>
2237      * @see Configuration#keepFileTimes
2238      */
2239     public void setKeepFileTimes(boolean keepFileTimes)
2240     {
2241         configuration.keepFileTimes = keepFileTimes;
2242     }
2243 
2244     /**
2245      * <code>keep-time</code>- if true last modified time is preserved.
2246      * @return <code>true</code> if tidy will preserved last modified time in input file.
2247      * @todo <strong>this is NOT supported at this time. </strong>
2248      * @see Configuration#keepFileTimes
2249      */
2250     public boolean getKeepFileTimes()
2251     {
2252         return configuration.keepFileTimes;
2253     }
2254 
2255     /**
2256      * <code>output-raw</code>- avoid mapping values > 127 to entities. This has the same effect of specifying a
2257      * "raw" encoding in the original version of tidy.
2258      * @param rawOut avoid mapping values > 127 to entities
2259      * @see Configuration#rawOut
2260      */
2261     public void setRawOut(boolean rawOut)
2262     {
2263         configuration.rawOut = rawOut;
2264     }
2265 
2266     /**
2267      * <code>output-raw</code>- avoid mapping values > 127 to entities.
2268      * @return <code>true</code> if tidy will not map values > 127 to entities
2269      * @see Configuration#rawOut
2270      */
2271     public boolean getRawOut()
2272     {
2273         return configuration.rawOut;
2274     }
2275 
2276     /**
2277      * <code>input-encoding</code> the character encoding used for input.
2278      * @param encoding a valid java encoding name
2279      */
2280     public void setInputEncoding(String encoding)
2281     {
2282         configuration.setInCharEncodingName(encoding);
2283     }
2284 
2285     /**
2286      * <code>input-encoding</code> the character encoding used for input.
2287      * @return the java name of the encoding currently used for input
2288      */
2289     public String getInputEncoding()
2290     {
2291         return configuration.getInCharEncodingName();
2292     }
2293 
2294     /**
2295      * <code>output-encoding</code> the character encoding used for output.
2296      * @param encoding a valid java encoding name
2297      */
2298     public void setOutputEncoding(String encoding)
2299     {
2300         configuration.setOutCharEncodingName(encoding);
2301     }
2302 
2303     /**
2304      * <code>output-encoding</code> the character encoding used for output.
2305      * @return the java name of the encoding currently used for output
2306      */
2307     public String getOutputEncoding()
2308     {
2309         return configuration.getOutCharEncodingName();
2310     }
2311 
2312 }