experimental jtidy version adapted for phpeclipse
[phpeclipse.git] / net.sourceforge.phpeclipse / src / org / w3c / tidy / Configuration.java
1 /*
2  * @(#)Configuration.java   1.11 2000/08/16
3  *
4  */
5
6 package org.w3c.tidy;
7
8 /**
9  *
10  * Read configuration file and manage configuration properties.
11  *
12  * (c) 1998-2000 (W3C) MIT, INRIA, Keio University
13  * See Tidy.java for the copyright notice.
14  * Derived from <a href="http://www.w3.org/People/Raggett/tidy">
15  * HTML Tidy Release 4 Aug 2000</a>
16  *
17  * @author  Dave Raggett <dsr@w3.org>
18  * @author  Andy Quick <ac.quick@sympatico.ca> (translation to Java)
19  * @version 1.0, 1999/05/22
20  * @version 1.0.1, 1999/05/29
21  * @version 1.1, 1999/06/18 Java Bean
22  * @version 1.2, 1999/07/10 Tidy Release 7 Jul 1999
23  * @version 1.3, 1999/07/30 Tidy Release 26 Jul 1999
24  * @version 1.4, 1999/09/04 DOM support
25  * @version 1.5, 1999/10/23 Tidy Release 27 Sep 1999
26  * @version 1.6, 1999/11/01 Tidy Release 22 Oct 1999
27  * @version 1.7, 1999/12/06 Tidy Release 30 Nov 1999
28  * @version 1.8, 2000/01/22 Tidy Release 13 Jan 2000
29  * @version 1.9, 2000/06/03 Tidy Release 30 Apr 2000
30  * @version 1.10, 2000/07/22 Tidy Release 8 Jul 2000
31  * @version 1.11, 2000/08/16 Tidy Release 4 Aug 2000
32  */
33
34 /*
35   Configuration files associate a property name with a value.
36   The format is that of a Java .properties file.
37 */
38
39 import java.util.Enumeration;
40 import java.util.Properties;
41 import java.util.StringTokenizer;
42 import java.io.FileInputStream;
43 import java.io.IOException;
44
45 public class Configuration implements java.io.Serializable {
46
47     /* character encodings */
48     public static final int RAW         = 0;
49     public static final int ASCII       = 1;
50     public static final int LATIN1      = 2;
51     public static final int UTF8        = 3;
52     public static final int ISO2022     = 4;
53     public static final int MACROMAN    = 5;
54
55     /* mode controlling treatment of doctype */
56     public static final int DOCTYPE_OMIT  = 0;
57     public static final int DOCTYPE_AUTO  = 1;
58     public static final int DOCTYPE_STRICT= 2;
59     public static final int DOCTYPE_LOOSE = 3;
60     public static final int DOCTYPE_USER  = 4;
61
62     protected int spaces =  2;           /* default indentation */
63     protected int wraplen = 68;          /* default wrap margin */
64     protected int CharEncoding = ASCII;
65     protected int tabsize = 4;
66
67     protected int     docTypeMode = DOCTYPE_AUTO; /* see doctype property */
68     protected String  altText = null;      /* default text for alt attribute */
69     protected String  slidestyle = null;    /* style sheet for slides */
70     protected String  docTypeStr = null;    /* user specified doctype */
71     protected String  errfile = null;       /* file name to write errors to */
72     protected boolean writeback = false;        /* if true then output tidied markup */
73
74     protected boolean OnlyErrors = false;       /* if true normal output is suppressed */
75     protected boolean ShowWarnings = true;      /* however errors are always shown */
76     protected boolean Quiet = false;            /* no 'Parsing X', guessed DTD or summary */
77     protected boolean IndentContent = false;    /* indent content of appropriate tags */
78     protected boolean SmartIndent = false;      /* does text/block level content effect indentation */
79     protected boolean HideEndTags = false;      /* suppress optional end tags */
80     protected boolean XmlTags = false;          /* treat input as XML */
81     protected boolean XmlOut = false;           /* create output as XML */
82     protected boolean xHTML = false;            /* output extensible HTML */
83     protected boolean XmlPi = false;             /* add <?xml?> for XML docs */
84     protected boolean RawOut = false;           /* avoid mapping values > 127 to entities */
85     protected boolean UpperCaseTags = false;    /* output tags in upper not lower case */
86     protected boolean UpperCaseAttrs = false;   /* output attributes in upper not lower case */
87     protected boolean MakeClean = false;        /* remove presentational clutter */
88     protected boolean LogicalEmphasis = false;  /* replace i by em and b by strong */
89     protected boolean DropFontTags = false;     /* discard presentation tags */
90     protected boolean DropEmptyParas = true;    /* discard empty p elements */
91     protected boolean FixComments = true;       /* fix comments with adjacent hyphens */
92     protected boolean BreakBeforeBR = false;    /* o/p newline before <br> or not? */
93     protected boolean BurstSlides = false;      /* create slides on each h2 element */
94     protected boolean NumEntities = false;      /* use numeric entities */
95     protected boolean QuoteMarks = false;       /* output " marks as &quot; */
96     protected boolean QuoteNbsp = true;         /* output non-breaking space as entity */
97     protected boolean QuoteAmpersand = true;    /* output naked ampersand as &amp; */
98     protected boolean WrapAttVals = false;      /* wrap within attribute values */
99     protected boolean WrapScriptlets = false;   /* wrap within JavaScript string literals */
100     protected boolean WrapSection = true;       /* wrap within <![ ... ]> section tags */
101     protected boolean WrapAsp = true;           /* wrap within ASP pseudo elements */
102     protected boolean WrapJste = true;          /* wrap within JSTE pseudo elements */
103     protected boolean WrapPhp = true;           /* wrap within PHP pseudo elements */
104     protected boolean FixBackslash = true;      /* fix URLs by replacing \ with / */
105     protected boolean IndentAttributes = false; /* newline+indent before each attribute */
106     protected boolean XmlPIs = false;           /* if set to yes PIs must end with ?> */
107     protected boolean XmlSpace = false;         /* if set to yes adds xml:space attr as needed */
108     protected boolean EncloseBodyText = false;  /* if yes text at body is wrapped in <p>'s */
109     protected boolean EncloseBlockText = false; /* if yes text in blocks is wrapped in <p>'s */
110     protected boolean KeepFileTimes = true;     /* if yes last modied time is preserved */
111     protected boolean Word2000 = false;         /* draconian cleaning for Word2000 */
112     protected boolean TidyMark = true;          /* add meta element indicating tidied doc */
113     protected boolean Emacs = false;            /* if true format error output for GNU Emacs */
114     protected boolean LiteralAttribs = false;   /* if true attributes may use newlines */
115
116     protected TagTable tt;                      /* TagTable associated with this Configuration */
117
118     private transient Properties _properties = new Properties();
119
120     public Configuration()
121     {
122     }
123
124     public void addProps( Properties p )
125     {
126         Enumeration enum = p.propertyNames();
127         while (enum.hasMoreElements())
128         {
129             String key = (String) enum.nextElement();
130             String value = p.getProperty(key);
131             _properties.put(key, value);
132         }
133         parseProps();
134     }
135
136     public void parseFile( String filename )
137     {
138         try
139         {
140             _properties.load( new FileInputStream( filename ) );
141         }
142         catch (IOException e)
143         {
144             System.err.println(filename + e.toString());
145             return;
146         }
147         parseProps();
148     }
149
150     private void parseProps()
151     {
152         String value;
153
154         value = _properties.getProperty("indent-spaces");
155         if (value != null)
156             spaces = parseInt(value, "indent-spaces");
157
158         value = _properties.getProperty("wrap");
159         if (value != null)
160             wraplen = parseInt(value, "wrap");
161
162         value = _properties.getProperty("wrap-attributes");
163         if (value != null)
164             WrapAttVals = parseBool(value, "wrap-attributes");
165
166         value = _properties.getProperty("wrap-script-literals");
167         if (value != null)
168             WrapScriptlets = parseBool(value, "wrap-script-literals");
169
170         value = _properties.getProperty("wrap-sections");
171         if (value != null)
172             WrapSection = parseBool(value, "wrap-sections");
173
174         value = _properties.getProperty("wrap-asp");
175         if (value != null)
176             WrapAsp = parseBool(value, "wrap-asp");
177
178         value = _properties.getProperty("wrap-jste");
179         if (value != null)
180             WrapJste = parseBool(value, "wrap-jste");
181
182         value = _properties.getProperty("wrap-php");
183         if (value != null)
184             WrapPhp = parseBool(value, "wrap-php");
185
186         value = _properties.getProperty("literal-attributes");
187         if (value != null)
188             LiteralAttribs = parseBool(value, "literal-attributes");
189
190         value = _properties.getProperty("tab-size");
191         if (value != null)
192             tabsize = parseInt(value, "tab-size");
193
194         value = _properties.getProperty("markup");
195         if (value != null)
196             OnlyErrors = parseInvBool(value, "markup");
197
198         value = _properties.getProperty("quiet");
199         if (value != null)
200             Quiet = parseBool(value, "quiet");
201
202         value = _properties.getProperty("tidy-mark");
203         if (value != null)
204             TidyMark = parseBool(value, "tidy-mark");
205
206         value = _properties.getProperty("indent");
207         if (value != null)
208             IndentContent = parseIndent(value, "indent");
209
210         value = _properties.getProperty("indent-attributes");
211         if (value != null)
212             IndentAttributes = parseBool(value, "ident-attributes");
213
214         value = _properties.getProperty("hide-endtags");
215         if (value != null)
216             HideEndTags = parseBool(value, "hide-endtags");
217
218         value = _properties.getProperty("input-xml");
219         if (value != null)
220             XmlTags = parseBool(value, "input-xml");
221
222         value = _properties.getProperty("output-xml");
223         if (value != null)
224             XmlOut = parseBool(value, "output-xml");
225
226         value = _properties.getProperty("output-xhtml");
227         if (value != null)
228             xHTML = parseBool(value, "output-xhtml");
229
230         value = _properties.getProperty("add-xml-pi");
231         if (value != null)
232             XmlPi = parseBool(value, "add-xml-pi");
233
234         value = _properties.getProperty("add-xml-decl");
235         if (value != null)
236             XmlPi = parseBool(value, "add-xml-decl");
237
238         value = _properties.getProperty("assume-xml-procins");
239         if (value != null)
240             XmlPIs = parseBool(value, "assume-xml-procins");
241
242         value = _properties.getProperty("raw");
243         if (value != null)
244             RawOut = parseBool(value, "raw");
245
246         value = _properties.getProperty("uppercase-tags");
247         if (value != null)
248             UpperCaseTags = parseBool(value, "uppercase-tags");
249
250         value = _properties.getProperty("uppercase-attributes");
251         if (value != null)
252             UpperCaseAttrs = parseBool(value, "uppercase-attributes");
253
254         value = _properties.getProperty("clean");
255         if (value != null)
256             MakeClean = parseBool(value, "clean");
257
258         value = _properties.getProperty("logical-emphasis");
259         if (value != null)
260             LogicalEmphasis = parseBool(value, "logical-emphasis");
261
262         value = _properties.getProperty("word-2000");
263         if (value != null)
264             Word2000 = parseBool(value, "word-2000");
265
266         value = _properties.getProperty("drop-empty-paras");
267         if (value != null)
268             DropEmptyParas = parseBool(value, "drop-empty-paras");
269
270         value = _properties.getProperty("drop-font-tags");
271         if (value != null)
272             DropFontTags = parseBool(value, "drop-font-tags");
273
274         value = _properties.getProperty("enclose-text");
275         if (value != null)
276             EncloseBodyText = parseBool(value, "enclose-text");
277
278         value = _properties.getProperty("enclose-block-text");
279         if (value != null)
280             EncloseBlockText = parseBool(value, "enclose-block-text");
281
282         value = _properties.getProperty("alt-text");
283         if (value != null)
284             altText = value;
285
286         value = _properties.getProperty("add-xml-space");
287         if (value != null)
288             XmlSpace = parseBool(value, "add-xml-space");
289
290         value = _properties.getProperty("fix-bad-comments");
291         if (value != null)
292             FixComments = parseBool(value, "fix-bad-comments");
293
294         value = _properties.getProperty("split");
295         if (value != null)
296             BurstSlides = parseBool(value, "split");
297
298         value = _properties.getProperty("break-before-br");
299         if (value != null)
300             BreakBeforeBR = parseBool(value, "break-before-br");
301
302         value = _properties.getProperty("numeric-entities");
303         if (value != null)
304             NumEntities = parseBool(value, "numeric-entities");
305
306         value = _properties.getProperty("quote-marks");
307         if (value != null)
308             QuoteMarks = parseBool(value, "quote-marks");
309
310         value = _properties.getProperty("quote-nbsp");
311         if (value != null)
312             QuoteNbsp = parseBool(value, "quote-nbsp");
313
314         value = _properties.getProperty("quote-ampersand");
315         if (value != null)
316             QuoteAmpersand = parseBool(value, "quote-ampersand");
317
318         value = _properties.getProperty("write-back");
319         if (value != null)
320             writeback = parseBool(value, "write-back");
321
322         value = _properties.getProperty("keep-time");
323         if (value != null)
324             KeepFileTimes = parseBool(value, "keep-time");
325
326         value = _properties.getProperty("show-warnings");
327         if (value != null)
328             ShowWarnings = parseBool(value, "show-warnings");
329
330         value = _properties.getProperty("error-file");
331         if (value != null)
332             errfile = parseName(value, "error-file");
333
334         value = _properties.getProperty("slide-style");
335         if (value != null)
336             slidestyle = parseName(value, "slide-style");
337
338         value = _properties.getProperty("new-inline-tags");
339         if (value != null)
340             parseInlineTagNames(value, "new-inline-tags");
341
342         value = _properties.getProperty("new-blocklevel-tags");
343         if (value != null)
344             parseBlockTagNames(value, "new-blocklevel-tags");
345
346         value = _properties.getProperty("new-empty-tags");
347         if (value != null)
348             parseEmptyTagNames(value, "new-empty-tags");
349
350         value = _properties.getProperty("new-pre-tags");
351         if (value != null)
352             parsePreTagNames(value, "new-pre-tags");
353
354         value = _properties.getProperty("char-encoding");
355         if (value != null)
356             CharEncoding = parseCharEncoding(value, "char-encoding");
357
358         value = _properties.getProperty("doctype");
359         if (value != null)
360             docTypeStr = parseDocType(value, "doctype");
361
362         value = _properties.getProperty("fix-backslash");
363         if (value != null)
364             FixBackslash = parseBool(value, "fix-backslash");
365
366         value = _properties.getProperty("gnu-emacs");
367         if (value != null)
368             Emacs = parseBool(value, "gnu-emacs");
369     }
370
371     /* ensure that config is self consistent */
372     public void adjust()
373     {
374         if (EncloseBlockText)
375             EncloseBodyText = true;
376
377         /* avoid the need to set IndentContent when SmartIndent is set */
378
379         if (SmartIndent)
380             IndentContent = true;
381
382         /* disable wrapping */
383         if (wraplen == 0)
384             wraplen = 0x7FFFFFFF;
385
386         /* Word 2000 needs o:p to be declared as inline */
387         if (Word2000)
388         {
389             tt.defineInlineTag("o:p");
390         }
391
392         /* XHTML is written in lower case */
393         if (xHTML)
394         {
395             XmlOut = true;
396             UpperCaseTags = false;
397             UpperCaseAttrs = false;
398         }
399
400         /* if XML in, then XML out */
401         if (XmlTags)
402         {
403             XmlOut = true;
404             XmlPIs = true;
405         }
406
407         /* XML requires end tags */
408         if (XmlOut)
409         {
410             QuoteAmpersand = true;
411             HideEndTags = false;
412         }
413     }
414
415     private static int parseInt( String s, String option )
416     {
417         int i = 0;
418         try {
419             i = Integer.parseInt( s );
420         }
421         catch ( NumberFormatException e ) {
422             Report.badArgument(option);
423             i = -1;
424         }
425         return i;
426     }
427
428     private static boolean parseBool( String s, String option )
429     {
430         boolean b = false;
431         if ( s != null && s.length() > 0 ) {
432             char c = s.charAt(0);
433             if ((c == 't') || (c == 'T') || (c == 'Y') || (c == 'y') || (c == '1'))
434                 b = true;
435             else if ((c == 'f') || (c == 'F') || (c == 'N') || (c == 'n') || (c == '0'))
436                 b = false;
437             else
438                 Report.badArgument(option);
439         }
440         return b;
441     }
442
443     private static boolean parseInvBool( String s, String option )
444     {
445         boolean b = false;
446         if ( s != null && s.length() > 0 ) {
447             char c = s.charAt(0);
448             if ((c == 't') || (c == 'T') || (c == 'Y') || (c == 'y'))
449                 b = true;
450             else if ((c == 'f') || (c == 'F') || (c == 'N') || (c == 'n'))
451                 b = false;
452             else
453                 Report.badArgument(option);
454         }
455         return !b;
456     }
457
458     private static String parseName( String s, String option )
459     {
460         StringTokenizer t = new StringTokenizer( s );
461         String rs = null;
462         if ( t.countTokens() >= 1 )
463             rs = t.nextToken();
464         else
465             Report.badArgument(option);
466         return rs;
467     }
468
469     private static int parseCharEncoding( String s, String option )
470     {
471         int result = ASCII;
472
473         if (Lexer.wstrcasecmp(s, "ascii") == 0)
474             result = ASCII;
475         else if (Lexer.wstrcasecmp(s, "latin1") == 0)
476             result = LATIN1;
477         else if (Lexer.wstrcasecmp(s, "raw") == 0)
478             result = RAW;
479         else if (Lexer.wstrcasecmp(s, "utf8") == 0)
480             result = UTF8;
481         else if (Lexer.wstrcasecmp(s, "iso2022") == 0)
482             result = ISO2022;
483         else if (Lexer.wstrcasecmp(s, "mac") == 0)
484             result = MACROMAN;
485         else
486             Report.badArgument(option);
487
488         return result;
489     }
490
491     /* slight hack to avoid changes to pprint.c */
492     private boolean parseIndent( String s, String option )
493     {
494         boolean b = IndentContent;
495
496         if (Lexer.wstrcasecmp(s, "yes") == 0)
497         {
498             b = true;
499             SmartIndent = false;
500         }
501         else if (Lexer.wstrcasecmp(s, "true") == 0)
502         {
503             b = true;
504             SmartIndent = false;
505         }
506         else if (Lexer.wstrcasecmp(s, "no") == 0)
507         {
508             b = false;
509             SmartIndent = false;
510         }
511         else if (Lexer.wstrcasecmp(s, "false") == 0)
512         {
513             b = false;
514             SmartIndent = false;
515         }
516         else if (Lexer.wstrcasecmp(s, "auto") == 0)
517         {
518             b = true;
519             SmartIndent = true;
520         }
521         else
522             Report.badArgument(option);
523         return b;
524     }
525
526     private void parseInlineTagNames( String s, String option )
527     {
528         StringTokenizer t = new StringTokenizer( s, " \t\n\r," );
529         while ( t.hasMoreTokens() ) {
530             tt.defineInlineTag( t.nextToken() );
531         }
532     }
533
534     private void parseBlockTagNames( String s, String option )
535     {
536         StringTokenizer t = new StringTokenizer( s, " \t\n\r," );
537         while ( t.hasMoreTokens() ) {
538             tt.defineBlockTag( t.nextToken() );
539         }
540     }
541
542     private void parseEmptyTagNames( String s, String option )
543     {
544         StringTokenizer t = new StringTokenizer( s, " \t\n\r," );
545         while ( t.hasMoreTokens() ) {
546             tt.defineEmptyTag( t.nextToken() );
547         }
548     }
549
550     private void parsePreTagNames( String s, String option )
551     {
552         StringTokenizer t = new StringTokenizer( s, " \t\n\r," );
553         while ( t.hasMoreTokens() ) {
554             tt.definePreTag( t.nextToken() );
555         }
556     }
557
558     /*
559        doctype: omit | auto | strict | loose | <fpi>
560
561        where the fpi is a string similar to
562
563           "-//ACME//DTD HTML 3.14159//EN"
564     */
565     protected String parseDocType( String s, String option )
566     {
567         s = s.trim();
568
569         /* "-//ACME//DTD HTML 3.14159//EN" or similar */
570
571         if (s.startsWith("\""))
572         {
573             docTypeMode = DOCTYPE_USER;
574             return s;
575         }
576
577         /* read first word */
578         String word = "";
579         StringTokenizer t = new StringTokenizer( s, " \t\n\r," );
580         if (t.hasMoreTokens())
581             word = t.nextToken();
582
583         if (Lexer.wstrcasecmp(word, "omit") == 0)
584             docTypeMode = DOCTYPE_OMIT;
585         else if (Lexer.wstrcasecmp(word, "strict") == 0)
586             docTypeMode = DOCTYPE_STRICT;
587         else if (Lexer.wstrcasecmp(word, "loose") == 0 ||
588                  Lexer.wstrcasecmp(word, "transitional") == 0)
589             docTypeMode = DOCTYPE_LOOSE;
590         else if (Lexer.wstrcasecmp(word, "auto") == 0)
591             docTypeMode = DOCTYPE_AUTO;
592         else
593         {
594             docTypeMode = DOCTYPE_AUTO;
595             Report.badArgument(option);
596         }
597         return null;
598     }
599
600 }