1/*
2 * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package javax.swing.text.html;
26
27import java.io.*;
28import java.util.Hashtable;
29import javax.swing.text.AttributeSet;
30import javax.swing.text.StyleConstants;
31import javax.swing.text.StyleContext;
32
33/**
34 * Constants used in the <code>HTMLDocument</code>.  These
35 * are basically tag and attribute definitions.
36 *
37 * @author  Timothy Prinzing
38 * @author  Sunita Mani
39 *
40 */
41public class HTML {
42
43    /**
44     * Typesafe enumeration for an HTML tag.  Although the
45     * set of HTML tags is a closed set, we have left the
46     * set open so that people can add their own tag types
47     * to their custom parser and still communicate to the
48     * reader.
49     */
50    public static class Tag {
51
52        /** @since 1.3 */
53        public Tag() {}
54
55        /**
56         * Creates a new <code>Tag</code> with the specified <code>id</code>,
57         * and with <code>causesBreak</code> and <code>isBlock</code>
58         * set to <code>false</code>.
59         *
60         * @param id  the id of the new tag
61         */
62        protected Tag(String id) {
63            this(id, false, false);
64        }
65
66        /**
67         * Creates a new <code>Tag</code> with the specified <code>id</code>;
68         * <code>causesBreak</code> and <code>isBlock</code> are defined
69         * by the user.
70         *
71         * @param id the id of the new tag
72         * @param causesBreak  <code>true</code> if this tag
73         *    causes a break to the flow of data
74         * @param isBlock <code>true</code> if the tag is used
75         *    to add structure to a document
76         */
77        protected Tag(String id, boolean causesBreak, boolean isBlock) {
78            name = id;
79            this.breakTag = causesBreak;
80            this.blockTag = isBlock;
81        }
82
83        /**
84         * Returns <code>true</code> if this tag is a block
85         * tag, which is a tag used to add structure to a
86         * document.
87         *
88         * @return <code>true</code> if this tag is a block
89         *   tag, otherwise returns <code>false</code>
90         */
91        public boolean isBlock() {
92            return blockTag;
93        }
94
95        /**
96         * Returns <code>true</code> if this tag causes a
97         * line break to the flow of data, otherwise returns
98         * <code>false</code>.
99         *
100         * @return <code>true</code> if this tag causes a
101         *   line break to the flow of data, otherwise returns
102         *   <code>false</code>
103         */
104        public boolean breaksFlow() {
105            return breakTag;
106        }
107
108        /**
109         * Returns <code>true</code> if this tag is pre-formatted,
110         * which is true if the tag is either <code>PRE</code> or
111         * <code>TEXTAREA</code>.
112         *
113         * @return <code>true</code> if this tag is pre-formatted,
114         *   otherwise returns <code>false</code>
115         */
116        public boolean isPreformatted() {
117            return (this == PRE || this == TEXTAREA);
118        }
119
120        /**
121         * Returns the string representation of the
122         * tag.
123         *
124         * @return the <code>String</code> representation of the tag
125         */
126        public String toString() {
127            return name;
128        }
129
130        /**
131         * Returns <code>true</code> if this tag is considered to be a paragraph
132         * in the internal HTML model. <code>false</code> - otherwise.
133         *
134         * @return <code>true</code> if this tag is considered to be a paragraph
135         *         in the internal HTML model. <code>false</code> - otherwise.
136         * @see HTMLDocument.HTMLReader.ParagraphAction
137         */
138        boolean isParagraph() {
139            return (
140                this == P
141                   || this == IMPLIED
142                   || this == DT
143                   || this == H1
144                   || this == H2
145                   || this == H3
146                   || this == H4
147                   || this == H5
148                   || this == H6
149            );
150        }
151
152        boolean blockTag;
153        boolean breakTag;
154        String name;
155        boolean unknown;
156
157        // --- Tag Names -----------------------------------
158
159        /**
160         * Tag &lt;a&gt;
161         */
162        public static final Tag A = new Tag("a");
163
164        /**
165         * Tag &lt;address&gt;
166         */
167        public static final Tag ADDRESS = new Tag("address");
168        /**
169         * Tag &lt;applet&gt;
170         */
171        public static final Tag APPLET = new Tag("applet");
172
173        /**
174         * Tag &lt;area&gt;
175         */
176        public static final Tag AREA = new Tag("area");
177
178        /**
179         * Tag &lt;b&gt;
180         */
181        public static final Tag B = new Tag("b");
182
183        /**
184         * Tag &lt;base&gt;
185         */
186        public static final Tag BASE = new Tag("base");
187
188        /**
189         * Tag &lt;basefont&gt;
190         */
191        public static final Tag BASEFONT = new Tag("basefont");
192
193        /**
194         * Tag &lt;big&gt;
195         */
196        public static final Tag BIG = new Tag("big");
197
198        /**
199         * Tag &lt;blockquote&gt;
200         */
201        public static final Tag BLOCKQUOTE = new Tag("blockquote", true, true);
202
203        /**
204         * Tag &lt;body&gt;
205         */
206        public static final Tag BODY = new Tag("body", true, true);
207
208        /**
209         * Tag &lt;br&gt;
210         */
211        public static final Tag BR = new Tag("br", true, false);
212
213        /**
214         * Tag &lt;caption&gt;
215         */
216        public static final Tag CAPTION = new Tag("caption");
217
218        /**
219         * Tag &lt;center&gt;
220         */
221        public static final Tag CENTER = new Tag("center", true, false);
222
223        /**
224         * Tag &lt;cite&gt;
225         */
226        public static final Tag CITE = new Tag("cite");
227
228        /**
229         * Tag &lt;code&gt;
230         */
231        public static final Tag CODE = new Tag("code");
232
233        /**
234         * Tag &lt;dd&gt;
235         */
236        public static final Tag DD = new Tag("dd", true, true);
237
238        /**
239         * Tag &lt;dfn&gt;
240         */
241        public static final Tag DFN = new Tag("dfn");
242
243        /**
244         * Tag &lt;dir&gt;
245         */
246        public static final Tag DIR = new Tag("dir", true, true);
247
248        /**
249         * Tag &lt;div&gt;
250         */
251        public static final Tag DIV = new Tag("div", true, true);
252
253        /**
254         * Tag &lt;dl&gt;
255         */
256        public static final Tag DL = new Tag("dl", true, true);
257
258        /**
259         * Tag &lt;dt&gt;
260         */
261        public static final Tag DT = new Tag("dt", true, true);
262
263        /**
264         * Tag &lt;em&gt;
265         */
266        public static final Tag EM = new Tag("em");
267
268        /**
269         * Tag &lt;font&gt;
270         */
271        public static final Tag FONT = new Tag("font");
272
273        /**
274         * Tag &lt;form&gt;
275         */
276        public static final Tag FORM = new Tag("form", true, false);
277
278        /**
279         * Tag &lt;frame&gt;
280         */
281        public static final Tag FRAME = new Tag("frame");
282
283        /**
284         * Tag &lt;frameset&gt;
285         */
286        public static final Tag FRAMESET = new Tag("frameset");
287
288        /**
289         * Tag &lt;h1&gt;
290         */
291        public static final Tag H1 = new Tag("h1", true, true);
292
293        /**
294         * Tag &lt;h2&gt;
295         */
296        public static final Tag H2 = new Tag("h2", true, true);
297
298        /**
299         * Tag &lt;h3&gt;
300         */
301        public static final Tag H3 = new Tag("h3", true, true);
302
303        /**
304         * Tag &lt;h4&gt;
305         */
306        public static final Tag H4 = new Tag("h4", true, true);
307
308        /**
309         * Tag &lt;h5&gt;
310         */
311        public static final Tag H5 = new Tag("h5", true, true);
312
313        /**
314         * Tag &lt;h6&gt;
315         */
316        public static final Tag H6 = new Tag("h6", true, true);
317
318        /**
319         * Tag &lt;head&gt;
320         */
321        public static final Tag HEAD = new Tag("head", true, true);
322
323        /**
324         * Tag &lt;hr&gt;
325         */
326        public static final Tag HR = new Tag("hr", true, false);
327
328        /**
329         * Tag &lt;html&gt;
330         */
331        public static final Tag HTML = new Tag("html", true, false);
332
333        /**
334         * Tag &lt;i&gt;
335         */
336        public static final Tag I = new Tag("i");
337
338        /**
339         * Tag &lt;img&gt;
340         */
341        public static final Tag IMG = new Tag("img");
342
343        /**
344         * Tag &lt;input&gt;
345         */
346        public static final Tag INPUT = new Tag("input");
347
348        /**
349         * Tag &lt;isindex&gt;
350         */
351        public static final Tag ISINDEX = new Tag("isindex", true, false);
352
353        /**
354         * Tag &lt;kbd&gt;
355         */
356        public static final Tag KBD = new Tag("kbd");
357
358        /**
359         * Tag &lt;li&gt;
360         */
361        public static final Tag LI = new Tag("li", true, true);
362
363        /**
364         * Tag &lt;link&gt;
365         */
366        public static final Tag LINK = new Tag("link");
367
368        /**
369         * Tag &lt;map&gt;
370         */
371        public static final Tag MAP = new Tag("map");
372
373        /**
374         * Tag &lt;menu&gt;
375         */
376        public static final Tag MENU = new Tag("menu", true, true);
377
378        /**
379         * Tag &lt;meta&gt;
380         */
381        public static final Tag META = new Tag("meta");
382        /*public*/ static final Tag NOBR = new Tag("nobr");
383
384        /**
385         * Tag &lt;noframes&gt;
386         */
387        public static final Tag NOFRAMES = new Tag("noframes", true, true);
388
389        /**
390         * Tag &lt;object&gt;
391         */
392        public static final Tag OBJECT = new Tag("object");
393
394        /**
395         * Tag &lt;ol&gt;
396         */
397        public static final Tag OL = new Tag("ol", true, true);
398
399        /**
400         * Tag &lt;option&gt;
401         */
402        public static final Tag OPTION = new Tag("option");
403
404        /**
405         * Tag &lt;p&gt;
406         */
407        public static final Tag P = new Tag("p", true, true);
408
409        /**
410         * Tag &lt;param&gt;
411         */
412        public static final Tag PARAM = new Tag("param");
413
414        /**
415         * Tag &lt;pre&gt;
416         */
417        public static final Tag PRE = new Tag("pre", true, true);
418
419        /**
420         * Tag &lt;samp&gt;
421         */
422        public static final Tag SAMP = new Tag("samp");
423
424        /**
425         * Tag &lt;script&gt;
426         */
427        public static final Tag SCRIPT = new Tag("script");
428
429        /**
430         * Tag &lt;select&gt;
431         */
432        public static final Tag SELECT = new Tag("select");
433
434        /**
435         * Tag &lt;small&gt;
436         */
437        public static final Tag SMALL = new Tag("small");
438
439        /**
440         * Tag &lt;span&gt;
441         */
442        public static final Tag SPAN = new Tag("span");
443
444        /**
445         * Tag &lt;strike&gt;
446         */
447        public static final Tag STRIKE = new Tag("strike");
448
449        /**
450         * Tag &lt;s&gt;
451         */
452        public static final Tag S = new Tag("s");
453
454        /**
455         * Tag &lt;strong&gt;
456         */
457        public static final Tag STRONG = new Tag("strong");
458
459        /**
460         * Tag &lt;style&gt;
461         */
462        public static final Tag STYLE = new Tag("style");
463
464        /**
465         * Tag &lt;sub&gt;
466         */
467        public static final Tag SUB = new Tag("sub");
468
469        /**
470         * Tag &lt;sup&gt;
471         */
472        public static final Tag SUP = new Tag("sup");
473
474        /**
475         * Tag &lt;table&gt;
476         */
477        public static final Tag TABLE = new Tag("table", false, true);
478
479        /**
480         * Tag &lt;td&gt;
481         */
482        public static final Tag TD = new Tag("td", true, true);
483
484        /**
485         * Tag &lt;textarea&gt;
486         */
487        public static final Tag TEXTAREA = new Tag("textarea");
488
489        /**
490         * Tag &lt;th&gt;
491         */
492        public static final Tag TH = new Tag("th", true, true);
493
494        /**
495         * Tag &lt;title&gt;
496         */
497        public static final Tag TITLE = new Tag("title", true, true);
498
499        /**
500         * Tag &lt;tr&gt;
501         */
502        public static final Tag TR = new Tag("tr", false, true);
503
504        /**
505         * Tag &lt;tt&gt;
506         */
507        public static final Tag TT = new Tag("tt");
508
509        /**
510         * Tag &lt;u&gt;
511         */
512        public static final Tag U = new Tag("u");
513
514        /**
515         * Tag &lt;ul&gt;
516         */
517        public static final Tag UL = new Tag("ul", true, true);
518
519        /**
520         * Tag &lt;var&gt;
521         */
522        public static final Tag VAR = new Tag("var");
523
524        /**
525         * All text content must be in a paragraph element.
526         * If a paragraph didn't exist when content was
527         * encountered, a paragraph is manufactured.
528         * <p>
529         * This is a tag synthesized by the HTML reader.
530         * Since elements are identified by their tag type,
531         * we create a some fake tag types to mark the elements
532         * that were manufactured.
533         */
534        public static final Tag IMPLIED = new Tag("p-implied");
535
536        /**
537         * All text content is labeled with this tag.
538         * <p>
539         * This is a tag synthesized by the HTML reader.
540         * Since elements are identified by their tag type,
541         * we create a some fake tag types to mark the elements
542         * that were manufactured.
543         */
544        public static final Tag CONTENT = new Tag("content");
545
546        /**
547         * All comments are labeled with this tag.
548         * <p>
549         * This is a tag synthesized by the HTML reader.
550         * Since elements are identified by their tag type,
551         * we create a some fake tag types to mark the elements
552         * that were manufactured.
553         */
554        public static final Tag COMMENT = new Tag("comment");
555
556        static final Tag allTags[]  = {
557            A, ADDRESS, APPLET, AREA, B, BASE, BASEFONT, BIG,
558            BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
559            DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
560            FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
561            I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
562            META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
563            PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
564            STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
565            TH, TITLE, TR, TT, U, UL, VAR
566        };
567
568        static {
569            // Force HTMLs static initialize to be loaded.
570            getTag("html");
571        }
572    }
573
574    /**
575     * Class represents unknown HTML tag.
576     */
577    // There is no unique instance of UnknownTag, so we allow it to be
578    // Serializable.
579    @SuppressWarnings("serial") // Same-version serialization only
580    public static class UnknownTag extends Tag implements Serializable {
581
582        /**
583         * Creates a new <code>UnknownTag</code> with the specified
584         * <code>id</code>.
585         * @param id the id of the new tag
586         */
587        public UnknownTag(String id) {
588            super(id);
589        }
590
591        /**
592         * Returns the hash code which corresponds to the string
593         * for this tag.
594         */
595        public int hashCode() {
596            return toString().hashCode();
597        }
598
599        /**
600         * Compares this object to the specified object.
601         * The result is <code>true</code> if and only if the argument is not
602         * <code>null</code> and is an <code>UnknownTag</code> object
603         * with the same name.
604         *
605         * @param     obj   the object to compare this tag with
606         * @return    <code>true</code> if the objects are equal;
607         *            <code>false</code> otherwise
608         */
609        public boolean equals(Object obj) {
610            if (obj instanceof UnknownTag) {
611                return toString().equals(obj.toString());
612            }
613            return false;
614        }
615
616        private void writeObject(java.io.ObjectOutputStream s)
617                     throws IOException {
618            s.defaultWriteObject();
619            s.writeBoolean(blockTag);
620            s.writeBoolean(breakTag);
621            s.writeBoolean(unknown);
622            s.writeObject(name);
623        }
624
625        private void readObject(ObjectInputStream s)
626            throws ClassNotFoundException, IOException {
627            s.defaultReadObject();
628            blockTag = s.readBoolean();
629            breakTag = s.readBoolean();
630            unknown = s.readBoolean();
631            name = (String)s.readObject();
632        }
633    }
634
635    /**
636     * Typesafe enumeration representing an HTML
637     * attribute.
638     */
639    public static final class Attribute {
640
641        /**
642         * Creates a new <code>Attribute</code> with the specified
643         * <code>id</code>.
644         *
645         * @param id the id of the new <code>Attribute</code>
646         */
647        Attribute(String id) {
648            name = id;
649        }
650
651        /**
652         * Returns the string representation of this attribute.
653         * @return the string representation of this attribute
654         */
655        public String toString() {
656            return name;
657        }
658
659        private String name;
660
661
662        /**
663         * Attribute "size"
664         */
665        public static final Attribute SIZE = new Attribute("size");
666
667        /**
668         * Attribute "color"
669         */
670        public static final Attribute COLOR = new Attribute("color");
671
672        /**
673         * Attribute "clear"
674         */
675        public static final Attribute CLEAR = new Attribute("clear");
676
677        /**
678         * Attribute "background"
679         */
680        public static final Attribute BACKGROUND = new Attribute("background");
681
682        /**
683         * Attribute "bgcolor"
684         */
685        public static final Attribute BGCOLOR = new Attribute("bgcolor");
686
687        /**
688         * Attribute "text"
689         */
690        public static final Attribute TEXT = new Attribute("text");
691
692        /**
693         * Attribute "link"
694         */
695        public static final Attribute LINK = new Attribute("link");
696
697        /**
698         * Attribute "vlink"
699         */
700        public static final Attribute VLINK = new Attribute("vlink");
701
702        /**
703         * Attribute "alink"
704         */
705        public static final Attribute ALINK = new Attribute("alink");
706
707        /**
708         * Attribute "width"
709         */
710        public static final Attribute WIDTH = new Attribute("width");
711
712        /**
713         * Attribute "height"
714         */
715        public static final Attribute HEIGHT = new Attribute("height");
716
717        /**
718         * Attribute "align"
719         */
720        public static final Attribute ALIGN = new Attribute("align");
721
722        /**
723         * Attribute "name"
724         */
725        public static final Attribute NAME = new Attribute("name");
726
727        /**
728         * Attribute "href"
729         */
730        public static final Attribute HREF = new Attribute("href");
731
732        /**
733         * Attribute "rel"
734         */
735        public static final Attribute REL = new Attribute("rel");
736
737        /**
738         * Attribute "rev"
739         */
740        public static final Attribute REV = new Attribute("rev");
741
742        /**
743         * Attribute "title"
744         */
745        public static final Attribute TITLE = new Attribute("title");
746
747        /**
748         * Attribute "target"
749         */
750        public static final Attribute TARGET = new Attribute("target");
751
752        /**
753         * Attribute "shape"
754         */
755        public static final Attribute SHAPE = new Attribute("shape");
756
757        /**
758         * Attribute "coords"
759         */
760        public static final Attribute COORDS = new Attribute("coords");
761
762        /**
763         * Attribute "ismap"
764         */
765        public static final Attribute ISMAP = new Attribute("ismap");
766
767        /**
768         * Attribute "nohref"
769         */
770        public static final Attribute NOHREF = new Attribute("nohref");
771
772        /**
773         * Attribute "alt"
774         */
775        public static final Attribute ALT = new Attribute("alt");
776
777        /**
778         * Attribute "id"
779         */
780        public static final Attribute ID = new Attribute("id");
781
782        /**
783         * Attribute "src"
784         */
785        public static final Attribute SRC = new Attribute("src");
786
787        /**
788         * Attribute "hspace"
789         */
790        public static final Attribute HSPACE = new Attribute("hspace");
791
792        /**
793         * Attribute "vspace"
794         */
795        public static final Attribute VSPACE = new Attribute("vspace");
796
797        /**
798         * Attribute "usemap"
799         */
800        public static final Attribute USEMAP = new Attribute("usemap");
801
802        /**
803         * Attribute "lowsrc"
804         */
805        public static final Attribute LOWSRC = new Attribute("lowsrc");
806
807        /**
808         * Attribute "codebase"
809         */
810        public static final Attribute CODEBASE = new Attribute("codebase");
811
812        /**
813         * Attribute "code"
814         */
815        public static final Attribute CODE = new Attribute("code");
816
817        /**
818         * Attribute "archive"
819         */
820        public static final Attribute ARCHIVE = new Attribute("archive");
821
822        /**
823         * Attribute "value"
824         */
825        public static final Attribute VALUE = new Attribute("value");
826
827        /**
828         * Attribute "valuetype"
829         */
830        public static final Attribute VALUETYPE = new Attribute("valuetype");
831
832        /**
833         * Attribute "type"
834         */
835        public static final Attribute TYPE = new Attribute("type");
836
837        /**
838         * Attribute "class"
839         */
840        public static final Attribute CLASS = new Attribute("class");
841
842        /**
843         * Attribute "style"
844         */
845        public static final Attribute STYLE = new Attribute("style");
846
847        /**
848         * Attribute "lang"
849         */
850        public static final Attribute LANG = new Attribute("lang");
851
852        /**
853         * Attribute "face"
854         */
855        public static final Attribute FACE = new Attribute("face");
856
857        /**
858         * Attribute "dir"
859         */
860        public static final Attribute DIR = new Attribute("dir");
861
862        /**
863         * Attribute "declare"
864         */
865        public static final Attribute DECLARE = new Attribute("declare");
866
867        /**
868         * Attribute "classid"
869         */
870        public static final Attribute CLASSID = new Attribute("classid");
871
872        /**
873         * Attribute "data"
874         */
875        public static final Attribute DATA = new Attribute("data");
876
877        /**
878         * Attribute "codetype"
879         */
880        public static final Attribute CODETYPE = new Attribute("codetype");
881
882        /**
883         * Attribute "standby"
884         */
885        public static final Attribute STANDBY = new Attribute("standby");
886
887        /**
888         * Attribute "border"
889         */
890        public static final Attribute BORDER = new Attribute("border");
891
892        /**
893         * Attribute "shapes"
894         */
895        public static final Attribute SHAPES = new Attribute("shapes");
896
897        /**
898         * Attribute "noshade"
899         */
900        public static final Attribute NOSHADE = new Attribute("noshade");
901
902        /**
903         * Attribute "compact"
904         */
905        public static final Attribute COMPACT = new Attribute("compact");
906
907        /**
908         * Attribute "start"
909         */
910        public static final Attribute START = new Attribute("start");
911
912        /**
913         * Attribute "action"
914         */
915        public static final Attribute ACTION = new Attribute("action");
916
917        /**
918         * Attribute "method"
919         */
920        public static final Attribute METHOD = new Attribute("method");
921
922        /**
923         * Attribute "enctype"
924         */
925        public static final Attribute ENCTYPE = new Attribute("enctype");
926
927        /**
928         * Attribute "checked"
929         */
930        public static final Attribute CHECKED = new Attribute("checked");
931
932        /**
933         * Attribute "maxlength"
934         */
935        public static final Attribute MAXLENGTH = new Attribute("maxlength");
936
937        /**
938         * Attribute "multiple"
939         */
940        public static final Attribute MULTIPLE = new Attribute("multiple");
941
942        /**
943         * Attribute "selected"
944         */
945        public static final Attribute SELECTED = new Attribute("selected");
946
947        /**
948         * Attribute "rows"
949         */
950        public static final Attribute ROWS = new Attribute("rows");
951
952        /**
953         * Attribute "cols"
954         */
955        public static final Attribute COLS = new Attribute("cols");
956
957        /**
958         * Attribute "dummy"
959         */
960        public static final Attribute DUMMY = new Attribute("dummy");
961
962        /**
963         * Attribute "cellspacing"
964         */
965        public static final Attribute CELLSPACING = new Attribute("cellspacing");
966
967        /**
968         * Attribute "cellpadding"
969         */
970        public static final Attribute CELLPADDING = new Attribute("cellpadding");
971
972        /**
973         * Attribute "valign"
974         */
975        public static final Attribute VALIGN = new Attribute("valign");
976
977        /**
978         * Attribute "halign"
979         */
980        public static final Attribute HALIGN = new Attribute("halign");
981
982        /**
983         * Attribute "nowrap"
984         */
985        public static final Attribute NOWRAP = new Attribute("nowrap");
986
987        /**
988         * Attribute "rowspan"
989         */
990        public static final Attribute ROWSPAN = new Attribute("rowspan");
991
992        /**
993         * Attribute "colspan"
994         */
995        public static final Attribute COLSPAN = new Attribute("colspan");
996
997        /**
998         * Attribute "prompt"
999         */
1000        public static final Attribute PROMPT = new Attribute("prompt");
1001
1002        /**
1003         * Attribute "http-equiv"
1004         */
1005        public static final Attribute HTTPEQUIV = new Attribute("http-equiv");
1006
1007        /**
1008         * Attribute "content"
1009         */
1010        public static final Attribute CONTENT = new Attribute("content");
1011
1012        /**
1013         * Attribute "language"
1014         */
1015        public static final Attribute LANGUAGE = new Attribute("language");
1016
1017        /**
1018         * Attribute "version"
1019         */
1020        public static final Attribute VERSION = new Attribute("version");
1021
1022        /**
1023         * Attribute "n"
1024         */
1025        public static final Attribute N = new Attribute("n");
1026
1027        /**
1028         * Attribute "frameborder"
1029         */
1030        public static final Attribute FRAMEBORDER = new Attribute("frameborder");
1031
1032        /**
1033         * Attribute "marginwidth"
1034         */
1035        public static final Attribute MARGINWIDTH = new Attribute("marginwidth");
1036
1037        /**
1038         * Attribute "marginheight"
1039         */
1040        public static final Attribute MARGINHEIGHT = new Attribute("marginheight");
1041
1042        /**
1043         * Attribute "scrolling"
1044         */
1045        public static final Attribute SCROLLING = new Attribute("scrolling");
1046
1047        /**
1048         * Attribute "noresize"
1049         */
1050        public static final Attribute NORESIZE = new Attribute("noresize");
1051
1052        /**
1053         * Attribute "endtag"
1054         */
1055        public static final Attribute ENDTAG = new Attribute("endtag");
1056
1057        /**
1058         * Attribute "comment"
1059         */
1060        public static final Attribute COMMENT = new Attribute("comment");
1061        static final Attribute MEDIA = new Attribute("media");
1062
1063        static final Attribute allAttributes[] = {
1064            FACE,
1065            COMMENT,
1066            SIZE,
1067            COLOR,
1068            CLEAR,
1069            BACKGROUND,
1070            BGCOLOR,
1071            TEXT,
1072            LINK,
1073            VLINK,
1074            ALINK,
1075            WIDTH,
1076            HEIGHT,
1077            ALIGN,
1078            NAME,
1079            HREF,
1080            REL,
1081            REV,
1082            TITLE,
1083            TARGET,
1084            SHAPE,
1085            COORDS,
1086            ISMAP,
1087            NOHREF,
1088            ALT,
1089            ID,
1090            SRC,
1091            HSPACE,
1092            VSPACE,
1093            USEMAP,
1094            LOWSRC,
1095            CODEBASE,
1096            CODE,
1097            ARCHIVE,
1098            VALUE,
1099            VALUETYPE,
1100            TYPE,
1101            CLASS,
1102            STYLE,
1103            LANG,
1104            DIR,
1105            DECLARE,
1106            CLASSID,
1107            DATA,
1108            CODETYPE,
1109            STANDBY,
1110            BORDER,
1111            SHAPES,
1112            NOSHADE,
1113            COMPACT,
1114            START,
1115            ACTION,
1116            METHOD,
1117            ENCTYPE,
1118            CHECKED,
1119            MAXLENGTH,
1120            MULTIPLE,
1121            SELECTED,
1122            ROWS,
1123            COLS,
1124            DUMMY,
1125            CELLSPACING,
1126            CELLPADDING,
1127            VALIGN,
1128            HALIGN,
1129            NOWRAP,
1130            ROWSPAN,
1131            COLSPAN,
1132            PROMPT,
1133            HTTPEQUIV,
1134            CONTENT,
1135            LANGUAGE,
1136            VERSION,
1137            N,
1138            FRAMEBORDER,
1139            MARGINWIDTH,
1140            MARGINHEIGHT,
1141            SCROLLING,
1142            NORESIZE,
1143            MEDIA,
1144            ENDTAG
1145        };
1146    }
1147
1148    // The secret to 73, is that, given that the Hashtable contents
1149    // never change once the static initialization happens, the initial size
1150    // that the hashtable grew to was determined, and then that very size
1151    // is used.
1152    //
1153    private static final Hashtable<String, Tag> tagHashtable = new Hashtable<String, Tag>(73);
1154
1155    /** Maps from StyleConstant key to HTML.Tag. */
1156    private static final Hashtable<Object, Tag> scMapping = new Hashtable<Object, Tag>(8);
1157
1158    static {
1159
1160        for (int i = 0; i < Tag.allTags.length; i++ ) {
1161            tagHashtable.put(Tag.allTags[i].toString(), Tag.allTags[i]);
1162            StyleContext.registerStaticAttributeKey(Tag.allTags[i]);
1163        }
1164        StyleContext.registerStaticAttributeKey(Tag.IMPLIED);
1165        StyleContext.registerStaticAttributeKey(Tag.CONTENT);
1166        StyleContext.registerStaticAttributeKey(Tag.COMMENT);
1167        for (int i = 0; i < Attribute.allAttributes.length; i++) {
1168            StyleContext.registerStaticAttributeKey(Attribute.
1169                                                    allAttributes[i]);
1170        }
1171        StyleContext.registerStaticAttributeKey(HTML.NULL_ATTRIBUTE_VALUE);
1172        scMapping.put(StyleConstants.Bold, Tag.B);
1173        scMapping.put(StyleConstants.Italic, Tag.I);
1174        scMapping.put(StyleConstants.Underline, Tag.U);
1175        scMapping.put(StyleConstants.StrikeThrough, Tag.STRIKE);
1176        scMapping.put(StyleConstants.Superscript, Tag.SUP);
1177        scMapping.put(StyleConstants.Subscript, Tag.SUB);
1178        scMapping.put(StyleConstants.FontFamily, Tag.FONT);
1179        scMapping.put(StyleConstants.FontSize, Tag.FONT);
1180    }
1181
1182    /**
1183     * Returns the set of actual HTML tags that
1184     * are recognized by the default HTML reader.
1185     * This set does not include tags that are
1186     * manufactured by the reader.
1187     *
1188     * @return the set of actual HTML tags that
1189     * are recognized by the default HTML reader
1190     */
1191    public static Tag[] getAllTags() {
1192        Tag[] tags = new Tag[Tag.allTags.length];
1193        System.arraycopy(Tag.allTags, 0, tags, 0, Tag.allTags.length);
1194        return tags;
1195    }
1196
1197    /**
1198     * Fetches a tag constant for a well-known tag name (i.e. one of
1199     * the tags in the set {A, ADDRESS, APPLET, AREA, B,
1200     * BASE, BASEFONT, BIG,
1201     * BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
1202     * DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
1203     * FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
1204     * I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
1205     * META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
1206     * PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
1207     * STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
1208     * TH, TITLE, TR, TT, U, UL, VAR}.  If the given
1209     * name does not represent one of the well-known tags, then
1210     * <code>null</code> will be returned.
1211     *
1212     * @param tagName the <code>String</code> name requested
1213     * @return a tag constant corresponding to the <code>tagName</code>,
1214     *    or <code>null</code> if not found
1215     */
1216    public static Tag getTag(String tagName) {
1217
1218        Tag t =  tagHashtable.get(tagName);
1219        return (t == null ? null : t);
1220    }
1221
1222    /**
1223     * Returns the HTML <code>Tag</code> associated with the
1224     * <code>StyleConstants</code> key <code>sc</code>.
1225     * If no matching <code>Tag</code> is found, returns
1226     * <code>null</code>.
1227     *
1228     * @param sc the <code>StyleConstants</code> key
1229     * @return tag which corresponds to <code>sc</code>, or
1230     *   <code>null</code> if not found
1231     */
1232    static Tag getTagForStyleConstantsKey(StyleConstants sc) {
1233        return scMapping.get(sc);
1234    }
1235
1236    /**
1237     * Fetches an integer attribute value.  Attribute values
1238     * are stored as a string, and this is a convenience method
1239     * to convert to an actual integer.
1240     *
1241     * @param attr the set of attributes to use to try to fetch a value
1242     * @param key the key to use to fetch the value
1243     * @param def the default value to use if the attribute isn't
1244     *  defined or there is an error converting to an integer
1245     * @return an attribute value
1246     */
1247    public static int getIntegerAttributeValue(AttributeSet attr,
1248                                               Attribute key, int def) {
1249        int value = def;
1250        String istr = (String) attr.getAttribute(key);
1251        if (istr != null) {
1252            try {
1253                value = Integer.valueOf(istr).intValue();
1254            } catch (NumberFormatException e) {
1255                value = def;
1256            }
1257        }
1258        return value;
1259    }
1260
1261    /**
1262     *  {@code NULL_ATTRIBUTE_VALUE} used in cases where the value for the attribute has not
1263     *  been specified.
1264     */
1265    public static final String NULL_ATTRIBUTE_VALUE = "#DEFAULT";
1266
1267    // size determined similar to size of tagHashtable
1268    private static final Hashtable<String, Attribute> attHashtable = new Hashtable<String, Attribute>(77);
1269
1270    static {
1271
1272        for (int i = 0; i < Attribute.allAttributes.length; i++ ) {
1273            attHashtable.put(Attribute.allAttributes[i].toString(), Attribute.allAttributes[i]);
1274        }
1275    }
1276
1277    /**
1278     * Returns the set of HTML attributes recognized.
1279     * @return the set of HTML attributes recognized
1280     */
1281    public static Attribute[] getAllAttributeKeys() {
1282        Attribute[] attributes = new Attribute[Attribute.allAttributes.length];
1283        System.arraycopy(Attribute.allAttributes, 0,
1284                         attributes, 0, Attribute.allAttributes.length);
1285        return attributes;
1286    }
1287
1288    /**
1289     * Fetches an attribute constant for a well-known attribute name
1290     * (i.e. one of the attributes in the set {FACE, COMMENT, SIZE,
1291     * COLOR, CLEAR, BACKGROUND, BGCOLOR, TEXT, LINK, VLINK, ALINK,
1292     * WIDTH, HEIGHT, ALIGN, NAME, HREF, REL, REV, TITLE, TARGET,
1293     * SHAPE, COORDS, ISMAP, NOHREF, ALT, ID, SRC, HSPACE, VSPACE,
1294     * USEMAP, LOWSRC, CODEBASE, CODE, ARCHIVE, VALUE, VALUETYPE,
1295     * TYPE, CLASS, STYLE, LANG, DIR, DECLARE, CLASSID, DATA, CODETYPE,
1296     * STANDBY, BORDER, SHAPES, NOSHADE, COMPACT, START, ACTION, METHOD,
1297     * ENCTYPE, CHECKED, MAXLENGTH, MULTIPLE, SELECTED, ROWS, COLS,
1298     * DUMMY, CELLSPACING, CELLPADDING, VALIGN, HALIGN, NOWRAP, ROWSPAN,
1299     * COLSPAN, PROMPT, HTTPEQUIV, CONTENT, LANGUAGE, VERSION, N,
1300     * FRAMEBORDER, MARGINWIDTH, MARGINHEIGHT, SCROLLING, NORESIZE,
1301     * MEDIA, ENDTAG}).
1302     * If the given name does not represent one of the well-known attributes,
1303     * then <code>null</code> will be returned.
1304     *
1305     * @param attName the <code>String</code> requested
1306     * @return the <code>Attribute</code> corresponding to <code>attName</code>
1307     */
1308    public static Attribute getAttributeKey(String attName) {
1309        Attribute a = attHashtable.get(attName);
1310        if (a == null) {
1311          return null;
1312        }
1313        return a;
1314    }
1315
1316}
1317