1 /*
   2  * Copyright (c) 1998, 2018, 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  */
  25 package javax.swing.text.html;
  26 
  27 import java.io.*;
  28 import java.util.Hashtable;
  29 import javax.swing.text.AttributeSet;
  30 import javax.swing.text.StyleConstants;
  31 import 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  */
  41 public 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 }