// Copyright 2001-2002 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OWCSSIdentifier.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/CSS.subproj/OWCSSIdentifier.m,v 1.25 2002/03/09 01:53:48 kc Exp $");

@interface OWCSSIdentifier (Private)
+ (OWCSSIdentifier *)_registerIdentifierForString:(NSString *)aString;
- _initWithString:(NSString *)aString;
@end

@implementation OWCSSIdentifier

static OFTrie *identifierTrie;

OWCSSIdentifier *OWCSSPropertyNameIdentifiers[CSSDeclarationsCount];

// functions
OWCSSIdentifier *OWCSSURLIdentifier;

// units
OWCSSIdentifier *OWCSSEMIdentifier, *OWCSSEXIdentifier, *OWCSSPXIdentifier, *OWCSSINIdentifier, *OWCSSCMIdentifier, *OWCSSMMIdentifier, *OWCSSPTIdentifier, *OWCSSPCIdentifier, *OWCSSPercentIdentifier;

// shared
OWCSSIdentifier *OWCSSNoneIdentifier, *OWCSSNormalIdentifier, *OWCSSInheritIdentifier;
OWCSSIdentifier *OWCSSCenterIdentifier, *OWCSSAutoIdentifier;
OWCSSIdentifier *OWCSSFixedIdentifier;

// background: [<'background-color'> || <'background-image'> || <'background-repeat'> || <'background-attachment'> || <'background-position'>] | inherit
OWCSSIdentifier *OWCSSBackgroundIdentifier;
// background-attachment: scroll | fixed | inherit
OWCSSIdentifier *OWCSSBackgroundAttachmentIdentifier;
OWCSSIdentifier *OWCSSScrollIdentifier;
// background-color: <color> | transparent | inherit
OWCSSIdentifier *OWCSSBackgroundColorIdentifier;
OWCSSIdentifier *OWCSSTransparentIdentifier;
// background-image: <uri> | none | inherit
OWCSSIdentifier *OWCSSBackgroundImageIdentifier;
// background-repeat: repeat | repeat-x | repeat-y | no-repeat | inherit
OWCSSIdentifier *OWCSSBackgroundRepeatIdentifier;
OWCSSIdentifier *OWCSSRepeatIdentifier, *OWCSSRepeatXIdentifier, *OWCSSRepeatYIdentifier, *OWCSSNoRepeatIdentifier;

// border: <border-width> || <border-style> || <border-color>
OWCSSIdentifier *OWCSSBorderIdentifier; 
// border-color: <color>
OWCSSIdentifier *OWCSSBorderColorIdentifier;
// border-style: none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset
OWCSSIdentifier *OWCSSBorderStyleIdentifier;
OWCSSIdentifier *OWCSSDottedIdentifier, *OWCSSDashedIdentifier, *OWCSSSolidIdentifier, *OWCSSDoubleIdentifier, *OWCSSGrooveIdentifier, *OWCSSRidgeIdentifier, *OWCSSInsetIdentifier, *OWCSSOutsetIdentifier;
// border-width: thin | medium | thick | <length>
OWCSSIdentifier *OWCSSBorderWidthIdentifier;
OWCSSIdentifier *OWCSSThinIdentifier, *OWCSSThickIdentifier;
// border-top: <border-width> || <border-style> || <border-color>
OWCSSIdentifier *OWCSSBorderTopIdentifier, *OWCSSBorderTopColorIdentifier, *OWCSSBorderTopStyleIdentifier, *OWCSSBorderTopWidthIdentifier; 
// border-right: <border-width> || <border-style> || <border-color>
OWCSSIdentifier *OWCSSBorderRightIdentifier, *OWCSSBorderRightColorIdentifier, *OWCSSBorderRightStyleIdentifier, *OWCSSBorderRightWidthIdentifier;
// border-bottom: <border-width> || <border-style> || <border-color>
OWCSSIdentifier *OWCSSBorderBottomIdentifier, *OWCSSBorderBottomColorIdentifier, *OWCSSBorderBottomStyleIdentifier, *OWCSSBorderBottomWidthIdentifier;
// border-left: <border-width> || <border-style> || <border-color>
OWCSSIdentifier *OWCSSBorderLeftIdentifier, *OWCSSBorderLeftColorIdentifier, *OWCSSBorderLeftStyleIdentifier, *OWCSSBorderLeftWidthIdentifier;
// bottom: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSBottomIdentifier;

// clear: none | left | right | both | inherit
OWCSSIdentifier *OWCSSClearIdentifier;
OWCSSIdentifier *OWCSSBothIdentifier;

// color: <color> | inherit 
OWCSSIdentifier *OWCSSColorIdentifier;

// display: inline | block | list-item | run-in | compact | marker | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit 
OWCSSIdentifier *OWCSSDisplayIdentifier;
OWCSSIdentifier *OWCSSInlineIdentifier, *OWCSSBlockIdentifier, *OWCSSListItemIdentifier, *OWCSSRunInIdentifier, *OWCSSCompactIdentifier, *OWCSSMarkerIdentifier, *OWCSSTableIdentifier, *OWCSSInlineTableIdentifier, *OWCSSTableRowGroupIdentifier, *OWCSSTableHeaderGroupIdentifier, *OWCSSTableFooterGroupIdentifier, *OWCSSTableRowIdentifier, *OWCSSTableColumnGroupIdentifier, *OWCSSTableColumnIdentifier, *OWCSSTableCellIdentifier, *OWCSSTableCaptionIdentifier;

// float: left | right | none | inherit 
OWCSSIdentifier *OWCSSFloatIdentifier;

// font: [ [ <font-style> || <font-variant> || <font-weight> ]? <font-size> [ / <line-height> ]? <font-family> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
OWCSSIdentifier *OWCSSFontIdentifier;
OWCSSIdentifier *OWCSSCaptionIdentifier, *OWCSSIconIdentifier, *OWCSSMenuIdentifier, *OWCSSMessageBoxIdentifier, *OWCSSSmallCaptionIdentifier, *OWCSSStatusBarIdentifier;
// font-family: [[ <family-name> | serif | sans-serif | cursive | fantasy | monospace ],]* [<family-name> | <generic-family>] | inherit 
OWCSSIdentifier *OWCSSFontFamilyIdentifier;
OWCSSIdentifier *OWCSSSerifIdentifier, *OWCSSSansSerifIdentifier, *OWCSSCursiveIdentifier, *OWCSSFantasyIdentifier, *OWCSSMonospaceIdentifier;
// font-size: [xx-small | x-small | small | medium | large | x-large | xx-large ] | [ larger | smaller ] | <length> | <percentage> | inherit 
OWCSSIdentifier *OWCSSFontSizeIdentifier;
OWCSSIdentifier *OWCSSXXSmallIdentifier, *OWCSSXSmallIdentifier, *OWCSSSmallIdentifier, *OWCSSMediumIdentifier, *OWCSSLargeIdentifier, *OWCSSXLargeIdentifier, *OWCSSXXLargeIdentifier, *OWCSSLargerIdentifier, *OWCSSSmallerIdentifier;
// font-size-adjust: <number> | none | inherit
OWCSSIdentifier *OWCSSFontSizeAdjustIdentifier;
// font-stretch: normal | wider | narrower | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit
OWCSSIdentifier *OWCSSFontStretchIdentifier;
OWCSSIdentifier *OWCSSWiderIdentifier, *OWCSSNarrowerIdentifier, *OWCSSUltraCondensedIdentifier, *OWCSSExtraCondensedIdentifier, *OWCSSCondensedIdentifier, *OWCSSSemiCondensedIdentifier, *OWCSSSemiExpandedIdentifier, *OWCSSExpandedIdentifier, *OWCSSExtraExpandedIdentifier, *OWCSSUltraExpandedIdentifier;
// font-style: normal | italic | oblique | inherit
OWCSSIdentifier *OWCSSFontStyleIdentifier;
OWCSSIdentifier *OWCSSItalicIdentifier, *OWCSSObliqueIdentifier;
// font-variant: normal | small-caps | inherit
OWCSSIdentifier *OWCSSFontVariantIdentifier;
OWCSSIdentifier *OWCSSSmallCapsIdentifier;
// font-weight: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit 
OWCSSIdentifier *OWCSSFontWeightIdentifier;
OWCSSIdentifier *OWCSSBoldIdentifier, *OWCSSBolderIdentifier, *OWCSSLighterIdentifier;

// height: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSHeightIdentifier;

// left: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSLeftIdentifier;

// line-height: normal | <number> | <length> | <percentage> | inherit 
OWCSSIdentifier *OWCSSLineHeightIdentifier;

// margin: [ <length> | <percentage> | auto | inherit ] {1,4} | inherit
OWCSSIdentifier *OWCSSMarginIdentifier;
// margin-left, margin-right, margin-top, margin-bottom: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSMarginLeftIdentifier, *OWCSSMarginRightIdentifier, *OWCSSMarginTopIdentifier, *OWCSSMarginBottomIdentifier;

// padding: [ <length> | <percentage> | auto | inherit ] {1,4} | inherit
OWCSSIdentifier *OWCSSPaddingIdentifier;
// padding-left, padding-right, padding-top, padding-bottom: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSPaddingLeftIdentifier, *OWCSSPaddingRightIdentifier, *OWCSSPaddingTopIdentifier, *OWCSSPaddingBottomIdentifier;

// position: static | relative | absolute | fixed | inherit
OWCSSIdentifier *OWCSSPositionIdentifier;
OWCSSIdentifier *OWCSSStaticIdentifier, *OWCSSRelativeIdentifier, *OWCSSAbsoluteIdentifier;

// right: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSRightIdentifier;

// text
// text-align: left | right | center | justify | <string> | inherit 
OWCSSIdentifier *OWCSSTextAlignIdentifier;
OWCSSIdentifier *OWCSSJustifyIdentifier;

// text-decoration: none | [ underline || overline || line-through || blink ] | inherit
OWCSSIdentifier *OWCSSTextDecorationIdentifier;
OWCSSIdentifier *OWCSSUnderlineIdentifier, *OWCSSOverlineIdentifier, *OWCSSLineThroughIdentifier, *OWCSSBlinkIdentifier;

// text-indent: <length> | <percentage> | inherit
OWCSSIdentifier *OWCSSTextIndentIdentifier;

// top: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSTopIdentifier;

// vertical-align: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
OWCSSIdentifier *OWCSSVerticalAlignIdentifier;
OWCSSIdentifier *OWCSSBaselineIdentifier, *OWCSSSubIdentifier, *OWCSSSuperIdentifier, *OWCSSTextTopIdentifier, *OWCSSMiddleIdentifier, *OWCSSTextBottomIdentifier;

// visibility: inherit | visible | hidden
OWCSSIdentifier *OWCSSVisibilityIdentifier;
OWCSSIdentifier *OWCSSVisibleIdentifier, *OWCSSHiddenIdentifier;

// white-space: normal | pre | nowrap | inherit
OWCSSIdentifier *OWCSSWhiteSpaceIdentifier;
OWCSSIdentifier *OWCSSPreIdentifier, *OWCSSNoWrapIdentifier;

// width: <length> | <percentage> | auto | inherit
OWCSSIdentifier *OWCSSWidthIdentifier;

// z-index: auto | <integer>
OWCSSIdentifier *OWCSSZIndexIdentifier;

// @ rules (eg @media, @import)
OWCSSIdentifier *OWCSSMediaIdentifier, *OWCSSImportIdentifier, *OWCSSPageIdentifier;

// media types (for @media and @import)
OWCSSIdentifier *OWCSSAllIdentifier, *OWCSSAuralIdentifier, *OWCSSBrailleIdentifier, *OWCSSEmbossedIdentifier, *OWCSSHandheldIdentifier, *OWCSSPrintIdentifier, *OWCSSProjectionIdentifier, *OWCSSScreenIdentifier, *OWCSSTTYIdentifier, *OWCSSTVIdentifier;

// Fake identifiers (only for internal use by OmniWeb)
OWCSSIdentifier *OWCSSOWNeedsToStartABoxAtThisLevel;

+ (void)initialize;
{
    unsigned int propertyIndex;

    OBINITIALIZE;

    identifierTrie = [[OFTrie alloc] initCaseSensitive:NO];
    
    // functions
    OWCSSURLIdentifier = [self _registerIdentifierForString:@"url"];
    
    // units
    OWCSSEMIdentifier = [self _registerIdentifierForString:@"em"];
    OWCSSEXIdentifier = [self _registerIdentifierForString:@"ex"];
    OWCSSPXIdentifier = [self _registerIdentifierForString:@"px"];
    OWCSSINIdentifier = [self _registerIdentifierForString:@"in"];
    OWCSSCMIdentifier = [self _registerIdentifierForString:@"cm"];
    OWCSSMMIdentifier = [self _registerIdentifierForString:@"mm"];
    OWCSSPTIdentifier = [self _registerIdentifierForString:@"pt"];
    OWCSSPCIdentifier = [self _registerIdentifierForString:@"pc"];
    OWCSSPercentIdentifier = [self _registerIdentifierForString:@"%"];

    // shared
    OWCSSNoneIdentifier = [self _registerIdentifierForString:@"none"];
    OWCSSNormalIdentifier = [self _registerIdentifierForString:@"normal"];
    OWCSSInheritIdentifier = [self _registerIdentifierForString:@"inherit"];
    OWCSSAutoIdentifier = [self _registerIdentifierForString:@"auto"];
    OWCSSCenterIdentifier = [self _registerIdentifierForString:@"center"];
    OWCSSFixedIdentifier = [self _registerIdentifierForString:@"fixed"];

    // background: [<'background-color'> || <'background-image'> || <'background-repeat'> || <'background-attachment'> || <'background-position'>] | inherit
    OWCSSPropertyNameIdentifiers[CSSBackgroundDeclarationIndex] = OWCSSBackgroundIdentifier = [self _registerIdentifierForString:@"background"];
    // background-attachment: scroll | fixed | inherit
    OWCSSPropertyNameIdentifiers[CSSBackgroundAttachmentDeclarationIndex] = OWCSSBackgroundAttachmentIdentifier = [self _registerIdentifierForString:@"background-attachment"];
    OWCSSScrollIdentifier = [self _registerIdentifierForString:@"scroll"];
    // background-color: <color> | transparent | inherit
    OWCSSPropertyNameIdentifiers[CSSBackgroundColorDeclarationIndex] = OWCSSBackgroundColorIdentifier = [self _registerIdentifierForString:@"background-color"];
    OWCSSTransparentIdentifier = [self _registerIdentifierForString:@"transparent"];
    // background-image: <uri> | none | inherit
    OWCSSPropertyNameIdentifiers[CSSBackgroundImageDeclarationIndex] = OWCSSBackgroundImageIdentifier = [self _registerIdentifierForString:@"background-image"];
    // background-repeat: repeat | repeat-x | repeat-y | no-repeat | inherit
    OWCSSPropertyNameIdentifiers[CSSBackgroundRepeatDeclarationIndex] = OWCSSBackgroundRepeatIdentifier = [self _registerIdentifierForString:@"background-repeat"];
    OWCSSRepeatIdentifier = [self _registerIdentifierForString:@"repeat"];
    OWCSSRepeatXIdentifier = [self _registerIdentifierForString:@"repeat-x"];
    OWCSSRepeatYIdentifier = [self _registerIdentifierForString:@"repeat-y"];
    OWCSSNoRepeatIdentifier = [self _registerIdentifierForString:@"no-repeat"];

    // border: <border-width> || <border-style> || <border-color>
    OWCSSPropertyNameIdentifiers[CSSBorderDeclarationIndex] = OWCSSBorderIdentifier = [self _registerIdentifierForString:@"border"];
    // border-width: thin | medium | thick | <length>
    OWCSSPropertyNameIdentifiers[CSSBorderWidthDeclarationIndex] = OWCSSBorderWidthIdentifier = [self _registerIdentifierForString:@"border-width"];
    OWCSSThinIdentifier = [self _registerIdentifierForString:@"thin"];
    OWCSSThickIdentifier = [self _registerIdentifierForString:@"thick"];
    // border-style: none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset
    OWCSSPropertyNameIdentifiers[CSSBorderStyleDeclarationIndex] = OWCSSBorderStyleIdentifier = [self _registerIdentifierForString:@"border-style"];
    OWCSSDottedIdentifier = [self _registerIdentifierForString:@"dotted"];
    OWCSSDashedIdentifier = [self _registerIdentifierForString:@"dashed"];
    OWCSSSolidIdentifier = [self _registerIdentifierForString:@"solid"];
    OWCSSDoubleIdentifier = [self _registerIdentifierForString:@"double"];
    OWCSSGrooveIdentifier = [self _registerIdentifierForString:@"groove"];
    OWCSSRidgeIdentifier = [self _registerIdentifierForString:@"ridge"];
    OWCSSInsetIdentifier = [self _registerIdentifierForString:@"inset"];
    OWCSSOutsetIdentifier = [self _registerIdentifierForString:@"outset"];
    // border-color: <color value>
    OWCSSPropertyNameIdentifiers[CSSBorderColorDeclarationIndex] = OWCSSBorderColorIdentifier = [self _registerIdentifierForString:@"border-color"];
    // border-<top | right | bottom | left>:  <border-width> || <border-style> || <border-color>
    OWCSSPropertyNameIdentifiers[CSSBorderTopDeclarationIndex] = OWCSSBorderTopIdentifier = [self _registerIdentifierForString:@"border-top"];
    OWCSSPropertyNameIdentifiers[CSSBorderTopColorDeclarationIndex] = OWCSSBorderTopIdentifier = [self _registerIdentifierForString:@"border-top-color"];
    OWCSSPropertyNameIdentifiers[CSSBorderTopStyleDeclarationIndex] = OWCSSBorderTopIdentifier = [self _registerIdentifierForString:@"border-top-style"];
    OWCSSPropertyNameIdentifiers[CSSBorderTopWidthDeclarationIndex] = OWCSSBorderTopIdentifier = [self _registerIdentifierForString:@"border-top-width"];
    OWCSSPropertyNameIdentifiers[CSSBorderRightDeclarationIndex] = OWCSSBorderRightIdentifier = [self _registerIdentifierForString:@"border-right"];
    OWCSSPropertyNameIdentifiers[CSSBorderRightColorDeclarationIndex] = OWCSSBorderRightIdentifier = [self _registerIdentifierForString:@"border-right-color"];
    OWCSSPropertyNameIdentifiers[CSSBorderRightStyleDeclarationIndex] = OWCSSBorderRightIdentifier = [self _registerIdentifierForString:@"border-right-style"];
    OWCSSPropertyNameIdentifiers[CSSBorderRightWidthDeclarationIndex] = OWCSSBorderRightIdentifier = [self _registerIdentifierForString:@"border-right-width"];
    OWCSSPropertyNameIdentifiers[CSSBorderBottomDeclarationIndex] = OWCSSBorderBottomIdentifier = [self _registerIdentifierForString:@"border-bottom"];
    OWCSSPropertyNameIdentifiers[CSSBorderBottomColorDeclarationIndex] = OWCSSBorderBottomIdentifier = [self _registerIdentifierForString:@"border-bottom-color"];
    OWCSSPropertyNameIdentifiers[CSSBorderBottomStyleDeclarationIndex] = OWCSSBorderBottomIdentifier = [self _registerIdentifierForString:@"border-bottom-style"];
    OWCSSPropertyNameIdentifiers[CSSBorderBottomWidthDeclarationIndex] = OWCSSBorderBottomIdentifier = [self _registerIdentifierForString:@"border-bottom-width"];
    OWCSSPropertyNameIdentifiers[CSSBorderLeftDeclarationIndex] = OWCSSBorderLeftIdentifier = [self _registerIdentifierForString:@"border-left"];
    OWCSSPropertyNameIdentifiers[CSSBorderLeftColorDeclarationIndex] = OWCSSBorderLeftIdentifier = [self _registerIdentifierForString:@"border-left-color"];
    OWCSSPropertyNameIdentifiers[CSSBorderLeftStyleDeclarationIndex] = OWCSSBorderLeftIdentifier = [self _registerIdentifierForString:@"border-left-style"];
    OWCSSPropertyNameIdentifiers[CSSBorderLeftWidthDeclarationIndex] = OWCSSBorderLeftIdentifier = [self _registerIdentifierForString:@"border-left-width"];

    // bottom: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSBottomDeclarationIndex] = OWCSSBottomIdentifier = [self _registerIdentifierForString:@"bottom"];

    // clear: none | left | right | both | inherit
    OWCSSPropertyNameIdentifiers[CSSClearDeclarationIndex] = OWCSSClearIdentifier = [self _registerIdentifierForString:@"clear"];
    OWCSSBothIdentifier = [self _registerIdentifierForString:@"both"];

    // color: <color> | inherit 
    OWCSSPropertyNameIdentifiers[CSSColorDeclarationIndex] = OWCSSColorIdentifier = [self _registerIdentifierForString:@"color"];

    // display: inline | block | list-item | run-in | compact | marker | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit 
    OWCSSPropertyNameIdentifiers[CSSDisplayDeclarationIndex] = OWCSSDisplayIdentifier = [self _registerIdentifierForString:@"display"];
    OWCSSInlineIdentifier = [self _registerIdentifierForString:@"inline"];
    OWCSSBlockIdentifier = [self _registerIdentifierForString:@"block"];
    OWCSSListItemIdentifier = [self _registerIdentifierForString:@"list-tiem"];
    OWCSSRunInIdentifier = [self _registerIdentifierForString:@"run-in"];
    OWCSSCompactIdentifier = [self _registerIdentifierForString:@"compact"];
    OWCSSMarkerIdentifier = [self _registerIdentifierForString:@"marker"];
    OWCSSTableIdentifier = [self _registerIdentifierForString:@"table"];
    OWCSSInlineTableIdentifier = [self _registerIdentifierForString:@"inline-table"];
    OWCSSTableRowGroupIdentifier = [self _registerIdentifierForString:@"table-row-group"];
    OWCSSTableHeaderGroupIdentifier = [self _registerIdentifierForString:@"table-header-group"];
    OWCSSTableFooterGroupIdentifier = [self _registerIdentifierForString:@"table-footer-group"];
    OWCSSTableRowIdentifier = [self _registerIdentifierForString:@"table-row"];
    OWCSSTableColumnGroupIdentifier = [self _registerIdentifierForString:@"table-column-group"];
    OWCSSTableColumnIdentifier = [self _registerIdentifierForString:@"table-column"];
    OWCSSTableCellIdentifier = [self _registerIdentifierForString:@"table-cell"];
    OWCSSTableCaptionIdentifier = [self _registerIdentifierForString:@"table-caption"];

    // float: left | right | none | inherit 
    OWCSSPropertyNameIdentifiers[CSSFloatDeclarationIndex] = OWCSSFloatIdentifier = [self _registerIdentifierForString:@"float"];

    // font: [ [ <font-style> || <font-variant> || <font-weight> ]? <font-size> [ / <line-height> ]? <font-family> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
    OWCSSPropertyNameIdentifiers[CSSFontDeclarationIndex] = OWCSSFontIdentifier = [self _registerIdentifierForString:@"font"];
    OWCSSCaptionIdentifier = [self _registerIdentifierForString:@"caption"];
    OWCSSIconIdentifier = [self _registerIdentifierForString:@"icon"];
    OWCSSMenuIdentifier = [self _registerIdentifierForString:@"menu"];
    OWCSSMessageBoxIdentifier = [self _registerIdentifierForString:@"message-box"];
    OWCSSSmallCaptionIdentifier = [self _registerIdentifierForString:@"small-caption"];
    OWCSSStatusBarIdentifier = [self _registerIdentifierForString:@"status-bar"];
    // font-family: [[ <family-name> | serif | sans-serif | cursive | fantasy | monospace ],]* [<family-name> | <generic-family>] | inherit 
    OWCSSPropertyNameIdentifiers[CSSFontFamilyDeclarationIndex] = OWCSSFontFamilyIdentifier = [self _registerIdentifierForString:@"font-family"];
    OWCSSSerifIdentifier = [self _registerIdentifierForString:@"serif"];
    OWCSSSansSerifIdentifier = [self _registerIdentifierForString:@"sans-serif"];
    OWCSSCursiveIdentifier = [self _registerIdentifierForString:@"cursive"];
    OWCSSFantasyIdentifier = [self _registerIdentifierForString:@"fantasy"];
    OWCSSMonospaceIdentifier = [self _registerIdentifierForString:@"monospace"];
    // font-size: [xx-small | x-small | small | medium | large | x-large | xx-large ] | [ larger | smaller ] | <length> | <percentage> | inherit 
    OWCSSPropertyNameIdentifiers[CSSFontSizeDeclarationIndex] = OWCSSFontSizeIdentifier = [self _registerIdentifierForString:@"font-size"];
    OWCSSXXSmallIdentifier = [self _registerIdentifierForString:@"xx-small"];
    OWCSSXSmallIdentifier = [self _registerIdentifierForString:@"x-small"];
    OWCSSSmallIdentifier = [self _registerIdentifierForString:@"small"];
    OWCSSMediumIdentifier = [self _registerIdentifierForString:@"medium"];
    OWCSSLargeIdentifier = [self _registerIdentifierForString:@"large"];
    OWCSSXLargeIdentifier = [self _registerIdentifierForString:@"x-large"];
    OWCSSXXLargeIdentifier = [self _registerIdentifierForString:@"xx-large"];
    OWCSSLargerIdentifier = [self _registerIdentifierForString:@"larger"];
    OWCSSSmallerIdentifier = [self _registerIdentifierForString:@"smaller"];
    // font-size-adjust: <number> | none | inherit
    OWCSSPropertyNameIdentifiers[CSSFontSizeAdjustDeclarationIndex] = OWCSSFontSizeAdjustIdentifier = [self _registerIdentifierForString:@"font-size-adjust"];
    // font-stretch: normal | wider | narrower | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit
    OWCSSPropertyNameIdentifiers[CSSFontStretchDeclarationIndex] = OWCSSFontStretchIdentifier = [self _registerIdentifierForString:@"font-stretch"];
    OWCSSWiderIdentifier = [self _registerIdentifierForString:@"wider"];
    OWCSSNarrowerIdentifier = [self _registerIdentifierForString:@"narrower"];
    OWCSSUltraCondensedIdentifier = [self _registerIdentifierForString:@"ultra-condensed"];
    OWCSSExtraCondensedIdentifier = [self _registerIdentifierForString:@"extra-condensed"];
    OWCSSCondensedIdentifier = [self _registerIdentifierForString:@"condensed"];
    OWCSSSemiCondensedIdentifier = [self _registerIdentifierForString:@"semi-condensed"];
    OWCSSSemiExpandedIdentifier = [self _registerIdentifierForString:@"semi-expanded"];
    OWCSSExpandedIdentifier = [self _registerIdentifierForString:@"expanded"];
    OWCSSExtraExpandedIdentifier = [self _registerIdentifierForString:@"extra-expanded"];
    OWCSSUltraExpandedIdentifier = [self _registerIdentifierForString:@"ultra-expanded"];
    // font-style: normal | italic | oblique | inherit
    OWCSSPropertyNameIdentifiers[CSSFontStyleDeclarationIndex] = OWCSSFontStyleIdentifier = [self _registerIdentifierForString:@"font-style"];
    OWCSSItalicIdentifier = [self _registerIdentifierForString:@"italic"];
    OWCSSObliqueIdentifier = [self _registerIdentifierForString:@"oblique"];
    // font-variant: normal | small-caps | inherit
    OWCSSPropertyNameIdentifiers[CSSFontVariantDeclarationIndex] = OWCSSFontVariantIdentifier = [self _registerIdentifierForString:@"font-variant"];
    OWCSSSmallCapsIdentifier = [self _registerIdentifierForString:@"small-caps"];
    // font-weight: normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit 
    OWCSSPropertyNameIdentifiers[CSSFontWeightDeclarationIndex] = OWCSSFontWeightIdentifier = [self _registerIdentifierForString:@"font-weight"];
    OWCSSBoldIdentifier = [self _registerIdentifierForString:@"bold"];
    OWCSSBolderIdentifier = [self _registerIdentifierForString:@"bolder"];
    OWCSSLighterIdentifier = [self _registerIdentifierForString:@"lighter"];

    // height: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSHeightDeclarationIndex] = OWCSSHeightIdentifier = [self _registerIdentifierForString:@"height"];

    // left: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSLeftDeclarationIndex] = OWCSSLeftIdentifier = [self _registerIdentifierForString:@"left"];

    // line-height: normal | <number> | <length> | <percentage> | inherit 
    OWCSSPropertyNameIdentifiers[CSSLineHeightDeclarationIndex] = OWCSSLineHeightIdentifier = [self _registerIdentifierForString:@"line-height"];

    // margin: [ <length> | <percentage> | auto | inherit ] {1,4} | inherit
    OWCSSPropertyNameIdentifiers[CSSMarginDeclarationIndex] = OWCSSMarginIdentifier = [self _registerIdentifierForString:@"margin"];
    // margin-left, margin-right, margin-top, margin-bottom: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSMarginBottomDeclarationIndex] = OWCSSMarginBottomIdentifier = [self _registerIdentifierForString:@"margin-bottom"];
    OWCSSPropertyNameIdentifiers[CSSMarginLeftDeclarationIndex] = OWCSSMarginLeftIdentifier = [self _registerIdentifierForString:@"margin-left"];
    OWCSSPropertyNameIdentifiers[CSSMarginRightDeclarationIndex] = OWCSSMarginRightIdentifier = [self _registerIdentifierForString:@"margin-right"];
    OWCSSPropertyNameIdentifiers[CSSMarginTopDeclarationIndex] = OWCSSMarginTopIdentifier = [self _registerIdentifierForString:@"margin-top"];

    // padding: [ <length> | <percentage> | auto | inherit ] {1,4} | inherit
    OWCSSPropertyNameIdentifiers[CSSPaddingDeclarationIndex] = OWCSSPaddingIdentifier = [self _registerIdentifierForString:@"padding"];
    // padding-left, padding-right, padding-top, padding-bottom: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSPaddingBottomDeclarationIndex] = OWCSSPaddingBottomIdentifier = [self _registerIdentifierForString:@"padding-bottom"];
    OWCSSPropertyNameIdentifiers[CSSPaddingLeftDeclarationIndex] = OWCSSPaddingLeftIdentifier = [self _registerIdentifierForString:@"padding-left"];
    OWCSSPropertyNameIdentifiers[CSSPaddingRightDeclarationIndex] = OWCSSPaddingRightIdentifier = [self _registerIdentifierForString:@"padding-right"];
    OWCSSPropertyNameIdentifiers[CSSPaddingTopDeclarationIndex] = OWCSSPaddingTopIdentifier = [self _registerIdentifierForString:@"padding-top"];

    // position: static | relative | absolute | fixed | inherit
    OWCSSPropertyNameIdentifiers[CSSPositionDeclarationIndex] = OWCSSPositionIdentifier = [self _registerIdentifierForString:@"position"];
    OWCSSStaticIdentifier = [self _registerIdentifierForString:@"static"];
    OWCSSRelativeIdentifier = [self _registerIdentifierForString:@"relative"];
    OWCSSAbsoluteIdentifier = [self _registerIdentifierForString:@"absolute"];

    // right: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSRightDeclarationIndex] = OWCSSRightIdentifier = [self _registerIdentifierForString:@"right"];

    // text
    // text-align: left | right | center | justify | <string> | inherit 
    OWCSSPropertyNameIdentifiers[CSSTextAlignDeclarationIndex] = OWCSSTextAlignIdentifier = [self _registerIdentifierForString:@"text-align"];
    OWCSSJustifyIdentifier = [self _registerIdentifierForString:@"justify"];

    // text-decoration: none | [ underline || overline || line-through || blink ] | inherit
    OWCSSPropertyNameIdentifiers[CSSTextDecorationDeclarationIndex] = OWCSSTextDecorationIdentifier = [self _registerIdentifierForString:@"text-decoration"];
    OWCSSUnderlineIdentifier = [self _registerIdentifierForString:@"underline"];
    OWCSSOverlineIdentifier = [self _registerIdentifierForString:@"overline"];
    OWCSSLineThroughIdentifier = [self _registerIdentifierForString:@"line-through"];
    OWCSSBlinkIdentifier = [self _registerIdentifierForString:@"blink"];

    // text-indent: <length> | <percentage> | inherit
    OWCSSPropertyNameIdentifiers[CSSTextIndentDeclarationIndex] = OWCSSTextIndentIdentifier = [self _registerIdentifierForString:@"text-indent"];

    // top: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSTopDeclarationIndex] = OWCSSTopIdentifier = [self _registerIdentifierForString:@"top"];

    // vertical-align: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
    OWCSSPropertyNameIdentifiers[CSSVerticalAlignDeclarationIndex] = OWCSSVerticalAlignIdentifier = [self _registerIdentifierForString:@"vertical-align"];
    OWCSSBaselineIdentifier = [self _registerIdentifierForString:@"baseline"];
    OWCSSSubIdentifier = [self _registerIdentifierForString:@"sub"];
    OWCSSSuperIdentifier = [self _registerIdentifierForString:@"super"];
    OWCSSTextTopIdentifier = [self _registerIdentifierForString:@"text-top"];
    OWCSSMiddleIdentifier = [self _registerIdentifierForString:@"middle"];
    OWCSSTextBottomIdentifier = [self _registerIdentifierForString:@"text-bottom"];

    // visibility: visible | hidden | inherit
    OWCSSPropertyNameIdentifiers[CSSVisibilityDeclarationIndex] = OWCSSVisibilityIdentifier = [self _registerIdentifierForString:@"visibility"];
    OWCSSVisibleIdentifier = [self _registerIdentifierForString:@"visible"];
    OWCSSHiddenIdentifier = [self _registerIdentifierForString:@"hidden"];

    // white-space: normal | pre | nowrap | inherit
    OWCSSPropertyNameIdentifiers[CSSWhiteSpaceDeclarationIndex] = OWCSSWhiteSpaceIdentifier = [self _registerIdentifierForString:@"white-space"];
    OWCSSPreIdentifier = [self _registerIdentifierForString:@"pre"];
    OWCSSNoWrapIdentifier = [self _registerIdentifierForString:@"nowrap"];

    // width: <length> | <percentage> | auto | inherit
    OWCSSPropertyNameIdentifiers[CSSWidthDeclarationIndex] = OWCSSWidthIdentifier = [self _registerIdentifierForString:@"width"];

    // z-index: auto | <integer>
    OWCSSPropertyNameIdentifiers[CSSZIndexDeclarationIndex] = OWCSSZIndexIdentifier = [self _registerIdentifierForString:@"z-index"];

    // @ rules (eg @media, @import)
    OWCSSMediaIdentifier = [self _registerIdentifierForString:@"media"];
    OWCSSImportIdentifier = [self _registerIdentifierForString:@"import"];
    OWCSSPageIdentifier = [self _registerIdentifierForString:@"page"];

    // media types (for @media and @import)
    OWCSSAllIdentifier = [self _registerIdentifierForString:@"all"];
    OWCSSAuralIdentifier = [self _registerIdentifierForString:@"aural"];
    OWCSSBrailleIdentifier = [self _registerIdentifierForString:@"braille"];
    OWCSSEmbossedIdentifier = [self _registerIdentifierForString:@"embossed"];
    OWCSSHandheldIdentifier = [self _registerIdentifierForString:@"handheld"];
    OWCSSPrintIdentifier = [self _registerIdentifierForString:@"print"];
    OWCSSProjectionIdentifier = [self _registerIdentifierForString:@"projection"];
    OWCSSScreenIdentifier = [self _registerIdentifierForString:@"screen"];
    OWCSSTTYIdentifier = [self _registerIdentifierForString:@"tty"];
    OWCSSTVIdentifier = [self _registerIdentifierForString:@"tv"];

    for (propertyIndex = 0; propertyIndex < CSSDeclarationsCount; propertyIndex++)
        [OWCSSPropertyNameIdentifiers[propertyIndex] setDeclarationIndex:propertyIndex];
}

+ (OFTrie *)identifierTrie;
{
    return identifierTrie;
}

// Init and dealloc

- init;
{
    OBRejectUnusedImplementation(self, _cmd);
    return nil;
}

- (void)dealloc;
{
    [string release];
    [super dealloc];
}


// API

- (NSString *)string;
{
    return string;
}

- (void)setDeclarationIndex:(unsigned int)newIndex;
{
    declarationIndex = newIndex;
}
- (unsigned int)declarationIndex;
{
    return declarationIndex;
}

/*
- (BOOL)isZZZIdentifier;
{
    return self == OWCSS
        || self == OWCSS
        || self == OWCSS
        || self == OWCSSInheritIdentifier;
}
*/

// Border

- (BOOL)isBorderWidthIdentifier;
{
    return self == OWCSSThinIdentifier
        || self == OWCSSMediumIdentifier
        || self == OWCSSThickIdentifier;
}

- (BOOL)isBorderStyleIdentifier;
{
    return self == OWCSSNoneIdentifier
        || self == OWCSSDottedIdentifier
        || self == OWCSSDashedIdentifier
        || self == OWCSSSolidIdentifier
        || self == OWCSSDoubleIdentifier
        || self == OWCSSGrooveIdentifier
        || self == OWCSSRidgeIdentifier
        || self == OWCSSInsetIdentifier
        || self == OWCSSOutsetIdentifier;
}

// Font

- (BOOL)isFontFamilyIdentifier;
{
    return self == OWCSSSerifIdentifier
        || self == OWCSSSansSerifIdentifier
        || self == OWCSSCursiveIdentifier
        || self == OWCSSFantasyIdentifier
        || self == OWCSSMonospaceIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontSizeIdentifier;
{
    return self == OWCSSXXSmallIdentifier
        || self == OWCSSXSmallIdentifier
        || self == OWCSSSmallIdentifier
        || self == OWCSSMediumIdentifier
        || self == OWCSSLargeIdentifier
        || self == OWCSSXLargeIdentifier
        || self == OWCSSXXLargeIdentifier
        || self == OWCSSLargerIdentifier
        || self == OWCSSSmallerIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontSizeAdjustIdentifier;
{
    return self == OWCSSNoneIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontStretchIdentifier;
{
    return self == OWCSSNormalIdentifier
        || self == OWCSSWiderIdentifier
        || self == OWCSSNarrowerIdentifier
        || self == OWCSSUltraCondensedIdentifier
        || self == OWCSSExtraCondensedIdentifier
        || self == OWCSSCondensedIdentifier
        || self == OWCSSSemiCondensedIdentifier
        || self == OWCSSSemiExpandedIdentifier
        || self == OWCSSExpandedIdentifier
        || self == OWCSSExtraExpandedIdentifier
        || self == OWCSSUltraExpandedIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontStyleIdentifier;
{
    return self == OWCSSNormalIdentifier
        || self == OWCSSItalicIdentifier
        || self == OWCSSObliqueIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontVariantIdentifier;
{
    return self == OWCSSNormalIdentifier
        || self == OWCSSSmallCapsIdentifier
        || self == OWCSSInheritIdentifier;
}

- (BOOL)isFontWeightIdentifier;
{
    return self == OWCSSNormalIdentifier
        || self == OWCSSBoldIdentifier
        || self == OWCSSBolderIdentifier
        || self == OWCSSLighterIdentifier
        || self == OWCSSInheritIdentifier;
}

@end

@implementation OWCSSIdentifier (Private)

+ (OWCSSIdentifier *)_registerIdentifierForString:(NSString *)aString;
{
    OWCSSIdentifier *identifier;

    OBPRECONDITION([identifierTrie bucketForString:aString] == nil);
    identifier = [[self alloc] _initWithString:aString];
    [identifierTrie addBucket:identifier forString:aString];
    return identifier;
}

- _initWithString:(NSString *)aString;
{
    if (![super init])
        return nil;
    string = [aString retain];
    declarationIndex = NSNotFound;
    return self;
}

- (NSString *)descriptionWithLocale:(NSDictionary *)locale indent:(unsigned)level;
{
    return [NSString stringWithFormat:@"[%@]", string];
}

@end
