return ((100 <= intValue) && (intValue <= 900) && (0 == (intValue % 100)));
if ((100 <= intValue) && (intValue <= 900) && (0 == (intValue % 100))) { return PR_TRUE; } else { UngetToken(); return PR_FALSE; }
void CSSParserImpl::ParsePseudoSelector(PRInt32&  aDataMask,                                      nsCSSSelector& aSelector,                                      PRInt32& aParsingStatus,                                      PRInt32& aErrorCode,                                      PRBool aIsNegated){  nsAutoString buffer;  if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof    REPORT_UNEXPECTED_EOF();    aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;    return;  }  buffer.Truncate();  buffer.AppendWithConversion(':');  buffer.Append(mToken.mIdent);  buffer.ToLowerCase();  nsIAtom* pseudo = NS_NewAtom(buffer);  if (eCSSToken_Ident != mToken.mType) {  // malformed selector    if (eCSSToken_Function != mToken.mType ||        !(#ifdef INCLUDE_XUL          // -moz-outliner is a pseudo-element and therefore cannot be negated          (!aIsNegated && IsOutlinerPseudoElement(mToken.mIdent)) ||#endif          // the negation pseudo-class is a function          (nsCSSAtoms::notPseudo == pseudo))) {      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Expected identifier for pseudo-class selector not found"));      NS_RELEASE(pseudo);      UngetToken();      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;      return;#ifdef INCLUDE_XUL    }#endif  }  if (nsCSSAtoms::notPseudo == pseudo) {    NS_RELEASE(pseudo);    if (aIsNegated) { // :not() can't be itself negated      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Negation pseudo-class can't be negated"));      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;      return;    }    // CSS 3 Negation pseudo-class takes one simple selector as argument    ParseNegatedSimpleSelector(aDataMask, aSelector, aParsingStatus, aErrorCode);    if (SELECTOR_PARSING_ENDED_OK != aParsingStatus) {      return;    }  }      else if (IsPseudoClass(pseudo)) {    // XXX parse pseudo classes accepting arguments    aDataMask |= SEL_MASK_PCLASS;    aSelector.AddPseudoClass(pseudo);    NS_RELEASE(pseudo);  }  else {    if (aIsNegated) { // pseudo-elements can't be negated      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Pseudo-elements can't be negated"));      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;      return;    }    if (0 == (aDataMask & SEL_MASK_PELEM)) {      aDataMask |= SEL_MASK_PELEM;      aSelector.AddPseudoClass(pseudo); // store it here, it gets pulled later      NS_RELEASE(pseudo);#ifdef INCLUDE_XUL      if (eCSSToken_Function == mToken.mType &&           IsOutlinerPseudoElement(mToken.mIdent)) {        // We have encountered a pseudoelement of the form        // -moz-outliner-xxxx(a,b,c).  We parse (a,b,c) and add each        // item in the list to the pseudoclass list.  They will be pulled        // from the list later along with the pseudoelement.        if (!ParseOutlinerPseudoElement(aErrorCode, aSelector))          aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;          return;      }#endif      // ensure selector ends here, must be followed by EOF, space, '{' or ','      if (GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)        if ((eCSSToken_WhiteSpace == mToken.mType) ||             (mToken.IsSymbol('{') || mToken.IsSymbol(','))) {          UngetToken();          aParsingStatus = SELECTOR_PARSING_STOPPED_OK;          return;        }        REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Found trailing token after pseudo-element, which must be the last part of a selector: "));        UngetToken();        aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;        return;      }    }    else {  // multiple pseudo elements, not legal      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Extra pseudo-element"));      UngetToken();      NS_RELEASE(pseudo);      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;      return;    }  }  aParsingStatus = SELECTOR_PARSING_ENDED_OK;}//// Parse the argument of a negation pseudo-class :not()//void CSSParserImpl::ParseNegatedSimpleSelector(PRInt32&  aDataMask,                                      nsCSSSelector& aSelector,                                      PRInt32& aParsingStatus,                                      PRInt32& aErrorCode){  // Check if we have the first parenthesis  if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {        if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof      REPORT_UNEXPECTED_EOF();      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;      return;    }    aParsingStatus = SELECTOR_PARSING_ENDED_OK;    nsCSSSelector* newSel = new nsCSSSelector();    if (nsnull == aSelector.mNegations &&        ((eCSSToken_ID == mToken.mType) ||          mToken.IsSymbol('.') ||          mToken.IsSymbol(':') ||          mToken.IsSymbol('['))) {      // ID, class and attribute selectors and pseudo-classes are stored in      // the first mNegations attached to a selector      aSelector.mNegations = newSel;    }    if (eCSSToken_ID == mToken.mType) {   // #id      ParseIDSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);    }    else if (mToken.IsSymbol('.')) {  // .class      ParseClassSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);    }    else if (mToken.IsSymbol(':')) { // :pseudo      ParsePseudoSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode, PR_TRUE);    }    else if (mToken.IsSymbol('[')) {  // attribute      ParseAttributeSelector(aDataMask, *aSelector.mNegations, aParsingStatus, aErrorCode);    }    else {      // then it should be a type element or universal selector      if (nsnull == aSelector.mNegations) {        aSelector.mNegations = newSel;      }      newSel = new nsCSSSelector();      nsCSSSelector* negations = aSelector.mNegations;      while (nsnull != negations->mNegations) {        negations = negations->mNegations;      }      // negated type element selectors and universal selectors are stored after the first      // mNegations containing only negated IDs, classes, attributes and pseudo-classes      negations->mNegations = newSel;      ParseTypeOrUniversalSelector(aDataMask, *newSel, aParsingStatus, aErrorCode, PR_TRUE);    }    if (SELECTOR_PARSING_STOPPED_ERROR == aParsingStatus) {      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Malformed simple selector as negation pseudo-class argument"));      return;    }    // close the parenthesis    if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Missing closing ')' in negation pseudo-class"));      aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;    }  }  else {    REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Missing argument in negation pseudo-class"));    aParsingStatus = SELECTOR_PARSING_STOPPED_ERROR;  }}/** * This is the format for selectors: * operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]* */PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode,                                nsCSSSelector& aSelector){  PRInt32  dataMask = 0;  PRInt32  parsingStatus = SELECTOR_PARSING_ENDED_OK;  if (! GetToken(aErrorCode, PR_TRUE)) {    REPORT_UNEXPECTED_EOF();    return PR_FALSE;  }  ParseTypeOrUniversalSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);  if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {    return PR_TRUE;  }  else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {    return PR_FALSE;  }  for (;;) {    parsingStatus = SELECTOR_PARSING_ENDED_OK;    if (eCSSToken_ID == mToken.mType) {   // #id      ParseIDSelector(dataMask, aSelector, parsingStatus, aErrorCode);    }    else if (mToken.IsSymbol('.')) {  // .class      ParseClassSelector(dataMask, aSelector, parsingStatus, aErrorCode);    }    else if (mToken.IsSymbol(':')) { // :pseudo      ParsePseudoSelector(dataMask, aSelector, parsingStatus, aErrorCode, PR_FALSE);    }    else if (mToken.IsSymbol('[')) {  // attribute      ParseAttributeSelector(dataMask, aSelector, parsingStatus, aErrorCode);    }    else {  // not a selector token, we're done      break;    }        if (SELECTOR_PARSING_STOPPED_OK == parsingStatus) {      return PR_TRUE;    }    else if (SELECTOR_PARSING_STOPPED_ERROR == parsingStatus) {      return PR_FALSE;    }        if (! GetToken(aErrorCode, PR_FALSE)) { // premature eof is ok (here!)      return PR_TRUE;    }  }  UngetToken();  return PRBool(0 != dataMask);}nsICSSDeclaration*CSSParserImpl::ParseDeclarationBlock(PRInt32& aErrorCode,                                     PRBool aCheckForBraces){  if (aCheckForBraces) {    if (!ExpectSymbol(aErrorCode, '{', PR_TRUE)) {      REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Expected '{' to begin declaration block but found"));      OUTPUT_ERROR();      return nsnull;    }  }  nsICSSDeclaration* declaration = nsnull;  if (NS_OK == NS_NewCSSDeclaration(&declaration)) {    PRInt32 count = 0;    PRBool dropDeclaration = PR_FALSE;    for (;;) {      PRInt32 hint = NS_STYLE_HINT_NONE;      if (ParseDeclaration(aErrorCode, declaration, aCheckForBraces, hint)) {        count++;  // count declarations      }      else {      	dropDeclaration = (aErrorCode == NS_CSS_PARSER_DROP_DECLARATION);        if (!SkipDeclaration(aErrorCode, aCheckForBraces)) {          break;        }        if (aCheckForBraces) {          if (ExpectSymbol(aErrorCode, '}', PR_TRUE)) {            break;          }        }        // Since the skipped declaration didn't end the block we parse        // the next declaration.      }    }    if (dropDeclaration ||        (0 == count)) { // didn't get any XXX is this ok with the DOM?      NS_RELEASE(declaration);    }  }  return declaration;}PRBool CSSParserImpl::ParseColor(PRInt32& aErrorCode, nsCSSValue& aValue){  if (!GetToken(aErrorCode, PR_TRUE)) {    REPORT_UNEXPECTED_EOF();    return PR_FALSE;  }  nsCSSToken* tk = &mToken;  nscolor rgba;  switch (tk->mType) {    case eCSSToken_ID:      // #xxyyzz      if (NS_HexToRGB(tk->mIdent, &rgba)) {        aValue.SetColorValue(rgba);        return PR_TRUE;      }      break;    case eCSSToken_Ident:      if (NS_ColorNameToRGB(tk->mIdent, &rgba)) {        aValue.SetStringValue(tk->mIdent, eCSSUnit_String);        return PR_TRUE;      }      else {        nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(tk->mIdent);        if (eCSSKeyword_UNKNOWN < keyword) { // known keyword          PRInt32 index = SearchKeywordTable(keyword, nsCSSProps::kColorKTable);          if (0 < index) {            aValue.SetIntValue(nsCSSProps::kColorKTable[index], eCSSUnit_Integer);            return PR_TRUE;          }        }      }      break;    case eCSSToken_Function:      if (mToken.mIdent.EqualsIgnoreCase("rgb")) {        // rgb ( component , component , component )        PRUint8 r, g, b;        if (ExpectSymbol(aErrorCode, '(', PR_FALSE) && // this won't fail            ParseColorComponent(aErrorCode, r, ',') &&            ParseColorComponent(aErrorCode, g, ',') &&            ParseColorComponent(aErrorCode, b, ')')) {          rgba = NS_RGB(r,g,b);          aValue.SetColorValue(rgba);          return PR_TRUE;        }        return PR_FALSE;  // already pushed back      }      break;    default:      break;  }  // try 'xxyyzz' without '#' prefix for compatibility with IE and Nav4x (bug 23236 and 45804)  if (mNavQuirkMode && !IsParsingCompoundProperty()) {  	// - If the string starts with 'a-f', the nsCSSScanner builds the token  	//   as a eCSSToken_Ident and we can parse the string as a 'xxyyzz' RGB color.  	// - If it only contains '0-9' digits, the token is a eCSSToken_Number and it  	//   must be converted back to a 6 characters string to be parsed as a RGB color.  	// - If it starts with '0-9' and contains any 'a-f', the token is a eCSSToken_Dimension,  	//   the mNumber part must be converted back to a string and the mIdent part must be  	//   appended to that string so that the resulting string has 6 characters.		// Note: This is a hack for Nav compatibility. Do not attempt to simplify it		// by hacking into the ncCSSScanner. This would be very bad.		nsAutoString str;		char  buffer[10];		switch (tk->mType) {			case eCSSToken_Ident:				str.Assign(tk->mIdent);				break;			case eCSSToken_Number:				if (tk->mIntegerValid) {					sprintf(buffer, "%06d", tk->mInteger);					str.AssignWithConversion(buffer);				}				break;			case eCSSToken_Dimension:				if (tk->mIdent.Length() <= 6) {					sprintf(buffer, "%06.0f", tk->mNumber);					nsAutoString temp;					temp.AssignWithConversion(buffer);					temp.Right(str, 6 - tk->mIdent.Length());					str.Append(tk->mIdent);				}				break;			default:				// There is a whole bunch of cases that are				// not handled by this switch.  Ignore them.				break;		}	  if (NS_HexToRGB(str, &rgba)) {	    aValue.SetColorValue(rgba);	    return PR_TRUE;	  }  }  // It's not a color  REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Expected color but found"));  UngetToken();  return PR_FALSE;}PRBool CSSParserImpl::ParseColorComponent(PRInt32& aErrorCode,                                          PRUint8& aComponent,                                          char aStop){  if (!GetToken(aErrorCode, PR_TRUE)) {    REPORT_UNEXPECTED_EOF();    return PR_FALSE;  }  float value;  nsCSSToken* tk = &mToken;  switch (tk->mType) {  case eCSSToken_Number:    value = tk->mNumber;    break;  case eCSSToken_Percentage:    value = tk->mNumber * 255.0f;    break;  default:    REPORT_UNEXPECTED_TOKEN(      NS_LITERAL_STRING("Expected number or percentage in rgb() but found"));    UngetToken();    return PR_FALSE;  }  if (ExpectSymbol(aErrorCode, aStop, PR_TRUE)) {    if (value < 0.0f) value = 0.0f;    if (value > 255.0f) value = 255.0f;    aComponent = (PRUint8) value;    return PR_TRUE;  }  PRUnichar stopString[2];  stopString[0] = PRUnichar(aStop);  stopString[1] = PRUnichar(0);  REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Expected ") +                          nsDependentString(stopString, 1) +                          NS_LITERAL_STRING(" but found"));  return PR_FALSE;}#ifdef INCLUDE_XULPRBool CSSParserImpl::ParseOutlinerPseudoElement(PRInt32& aErrorCode,                                                 nsCSSSelector& aSelector){  if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {    while (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {      if (!GetToken(aErrorCode, PR_TRUE)) {        return PR_FALSE;      }      else if (eCSSToken_Ident == mToken.mType) {        nsCOMPtr<nsIAtom> pseudo = getter_AddRefs(NS_NewAtom(mToken.mIdent));        aSelector.AddPseudoClass(pseudo);      }      else if (eCSSToken_Symbol == mToken.mType) {        if (!mToken.IsSymbol(','))          return PR_FALSE;      }      else return PR_FALSE;    }    return PR_TRUE;  }  return PR_FALSE; }#endif//----------------------------------------------------------------------PRBoolCSSParserImpl::ParseDeclaration(PRInt32& aErrorCode,                                nsICSSDeclaration* aDeclaration,                                PRBool aCheckForBraces,                                PRInt32& aChangeHint){  // Get property name  nsCSSToken* tk = &mToken;  nsAutoString propertyName;  for (;;) {    if (!GetToken(aErrorCode, PR_TRUE)) {      if (aCheckForBraces) {        REPORT_UNEXPECTED_EOF();      }      return PR_FALSE;    }    if (eCSSToken_Ident == tk->mType) {      propertyName = tk->mIdent;      // grab the ident before the ExpectSymbol trashes the token      if (!ExpectSymbol(aErrorCode, ':', PR_TRUE)) {        REPORT_UNEXPECTED_TOKEN(NS_LITERAL_STRING("Expected ':' but found"));        REPORT_UNEXPECTED(NS_LITERAL_STRING("Declaration dropped."));        OUTPUT_ERROR();        return PR_FALSE;      }      break;    }    if (tk->IsSymbol(';')) {      // dangling semicolons are skipped      continue;    }    if (!tk->IsSymbol('}')) {      REPORT_UNEXPECTED_TOKEN(        NS_LITERAL_STRING("Expected declaration but found"));      REPORT_UNEXPECTED(NS_LITERAL_STRING("Skipped to next declaration."));      OUTPUT_ERROR();    }    // Not a declaration...    UngetToken();    return PR_FALSE;  }  // Map property name to it's ID and then parse the property  nsCSSProperty propID = nsCSSProps::LookupProperty(propertyName);  if (eCSSProperty_UNKNOWN == propID) { // unknown property    REPORT_UNEXPECTED(NS_LITERAL_STRING("Unknown property '") +                       propertyName +                       NS_LITERAL_STRING("'.  Declaration dropped."));    OUTPUT_ERROR();    return PR_FALSE;  }  if (! ParseProperty(aErrorCode, aDeclaration, propID, aChangeHint)) {    // XXX Much better to put stuff in the value parsers instead...    REPORT_UNEXPECTED(      NS_LITERAL_STRING("Error in parsing value for property '") +      propertyName +      NS_LITERAL_STRING("'.  Declaration dropped."));    OUTPUT_ERROR();    return PR_FALSE;  }  CLEAR_ERROR();  // See if the declaration is followed by a "!important" declaration  PRBool isImportant = PR_FALSE;  if (!GetToken(aErrorCode, PR_TRUE)) {    if (aCheckForBraces) {      // Premature eof is not ok when proper termination is mandated      REPORT_UNEXPECTED_EOF();      return PR_FALSE;    }    return PR_TRUE;  }  else {    if (eCSSToken_Symbol == tk->mType) {      if ('!' == tk->mSymbol) {        // Look for important ident        if (!GetToken(aErrorCode, PR_TRUE)) {          // Premature eof is not ok          REPORT_UNEXPECTED_EOF();          return PR_FALSE;        }        if ((eCSSToken_Ident != tk->mType) ||            !tk->mIdent.EqualsIgnoreCase("important")) {          REPORT_UNEXPECTED_TOKEN(            NS_LITERAL_STRING("Expected 'important' but found"));          OUTPUT_ERROR();          UngetToken();          return PR_FALSE;        }        isImportant = PR_TRUE;      }      else {        // Not a !important declaration        UngetToken();      }    }    else {      // Not a !important declaration      UngetToken();    }  }  if (PR_TRUE == isImportant) {    aDeclaration->SetValueImportant(propID);  }  // Make sure valid property declaration is terminated with either a  // semicolon or a right-curly-brace (when aCheckForBraces is true).  // When aCheckForBraces is false, proper termination is either  // semicolon or EOF.  if (!GetToken(aErrorCode, PR_TRUE)) {    if (aCheckForBraces) {      // Premature eof is not ok      REPORT_UNEXPECTED_EOF();      return PR_FALSE;    }    return PR_TRUE;  }   if (eCSSToken_Symbol == tk->mType) {    if (';' == tk->mSymbol) {      return PR_TRUE;    }    if (!aCheckForBraces) {      // If we didn't hit eof and we didn't see a semicolon then the      // declaration is not properly terminated.      REPORT_UNEXPECTED_TOKEN(        NS_LITERAL_STRING("Expected ';' to terminate declaration but found"));      REPORT_UNEXPECTED(NS_LITERAL_STRING("Declaration dropped."));      OUTPUT_ERROR();      return PR_FALSE;    }    if ('}' == tk->mSymbol) {      UngetToken();      return PR_TRUE;    }  }  REPORT_UNEXPECTED_TOKEN(    aCheckForBraces      ? NS_LITERAL_STRING("Expected ';' or '}' to terminate declaration but found")      : NS_LITERAL_STRING("Expected ';' to terminate declaration but found"));  REPORT_UNEXPECTED(NS_LITERAL_STRING("Declaration dropped."));  OUTPUT_ERROR();  return PR_FALSE;}// Flags for ParseVariant method#define VARIANT_KEYWORD         0x000001  // K#define VARIANT_LENGTH          0x000002  // L#define VARIANT_PERCENT         0x000004  // P#define VARIANT_COLOR           0x000008  // C#define VARIANT_URL             0x000010  // U#define VARIANT_NUMBER          0x000020  // N#define VARIANT_INTEGER         0x000040  // I#define VARIANT_ANGLE           0x000080  // G#define VARIANT_FREQUENCY       0x000100  // F#define VARIANT_TIME            0x000200  // T#define VARIANT_STRING          0x000400  // S#define VARIANT_COUNTER         0x000800  // #define VARIANT_ATTR            0x001000  //#define VARIANT_IDENTIFIER      0x002000  // D#define VARIANT_AUTO            0x010000  // A#define VARIANT_INHERIT         0x020000  // H#define VARIANT_NONE            0x040000  // O#define VARIANT_NORMAL          0x080000  // M// Common combinations of variants#define VARIANT_AL   (VARIANT_AUTO | VARIANT_LENGTH)#define VARIANT_LP   (VARIANT_LENGTH | VARIANT_PERCENT)#define VARIANT_AH   (VARIANT_AUTO | VARIANT_INHERIT)#define VARIANT_AHLP (VARIANT_AH | VARIANT_LP)#define VARIANT_AHI  (VARIANT_AH | VARIANT_INTEGER)#define VARIANT_AHK  (VARIANT_AH | VARIANT_KEYWORD)#define VARIANT_AHUK (VARIANT_AH | VARIANT_URL | VARIANT_KEYWORD)#define VARIANT_AHL  (VARIANT_AH | VARIANT_LENGTH)#define VARIANT_AHKL (VARIANT_AHK | VARIANT_LENGTH)#define VARIANT_HK   (VARIANT_INHERIT | VARIANT_KEYWORD)#define VARIANT_HKF  (VARIANT_HK | VARIANT_FREQUENCY)#define VARIANT_HKL  (VARIANT_HK | VARIANT_LENGTH)#define VARIANT_HKLP (VARIANT_HK | VARIANT_LP)#define VARIANT_HL   (VARIANT_INHERIT | VARIANT_LENGTH)#define VARIANT_HI   (VARIANT_INHERIT | VARIANT_INTEGER)#define VARIANT_HLP  (VARIANT_HL | VARIANT_PERCENT)#define VARIANT_HLPN (VARIANT_HLP | VARIANT_NUMBER)#define VARIANT_HLPO (VARIANT_HLP | VARIANT_NONE)#define VARIANT_HTP  (VARIANT_INHERIT | VARIANT_TIME | VARIANT_PERCENT)#define VARIANT_HMK  (VARIANT_HK | VARIANT_NORMAL)#define VARIANT_HMKI (VARIANT_HMK | VARIANT_INTEGER)#define VARIANT_HC   (VARIANT_INHERIT | VARIANT_COLOR)#define VARIANT_HCK  (VARIANT_HK | VARIANT_COLOR)#define VARIANT_HUO  (VARIANT_INHERIT | VARIANT_URL | VARIANT_NONE)#define VARIANT_AHUO (VARIANT_AUTO | VARIANT_HUO)#define VARIANT_HPN  (VARIANT_INHERIT | VARIANT_PERCENT | VARIANT_NUMBER)#define VARIANT_HOK  (VARIANT_HK | VARIANT_NONE)#define VARIANT_HN   (VARIANT_INHERIT | VARIANT_NUMBER)#define VARIANT_HON  (VARIANT_HN | VARIANT_NONE)#define VARIANT_HOS  (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING)static const nsCSSProperty kBorderTopIDs[] = {  eCSSProperty_border_top_width,  eCSSProperty_border_top_style,  eCSSProperty_border_top_color};static const nsCSSProperty kBorderRightIDs[] = {  eCSSProperty_border_right_width,  eCSSProperty_border_right_style,  eCSSProperty_border_right_color};static const nsCSSProperty kBorderBottomIDs[] = {  eCSSProperty_border_bottom_width,  eCSSProperty_border_bottom_style,  eCSSProperty_border_bottom_color};static const nsCSSProperty kBorderLeftIDs[] = {  eCSSProperty_border_left_width,  eCSSProperty_border_left_style,  eCSSProperty_border_left_color};PRInt32 CSSParserImpl::SearchKeywordTable(nsCSSKeyword aKeyword, const PRInt32 aKeywordTable[]){  PRInt32 index = 0;  while (0 <= aKeywordTable[index]) {    if (aKeyword == nsCSSKeyword(aKeywordTable[index++])) {      return index;    }    index++;  }  return -1;}PRBool CSSParserImpl::ParseEnum(PRInt32& aErrorCode, nsCSSValue& aValue,                                const PRInt32 aKeywordTable[]){  nsString* ident = NextIdent(aErrorCode);  if (nsnull == ident) {    return PR_FALSE;  }  nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(*ident);  if (eCSSKeyword_UNKNOWN < keyword) {    PRInt32 index = SearchKeywordTable(keyword, aKeywordTable);    if (0 < index) {      aValue.SetIntValue(aKeywordTable[index], eCSSUnit_Enumerated);      return PR_TRUE;    }  }  // Put the unknown identifier back and return  UngetToken();  return PR_FALSE;}PRBool CSSParserImpl::TranslateDimension(PRInt32& aErrorCode,                                         nsCSSValue& aValue,                                         PRInt32 aVariantMask,                                         float aNumber,                                         const nsString& aUnit){  nsCSSUnit units;  PRInt32   type = 0;  if (0 != aUnit.Length()) {    nsCSSKeyword id = nsCSSKeywords::LookupKeyword(aUnit);    switch (id) {      case eCSSKeyword_em:    units = eCSSUnit_EM;          type = VARIANT_LENGTH;  break;      case eCSSKeyword_ex:    units = eCSSUnit_XHeight;     type = VARIANT_LENGTH;  break;      case eCSSKeyword_ch:    units = eCSSUnit_Char;        type = VARIANT_LENGTH;  break;      case eCSSKeyword_px:    units = eCSSUnit_Pixel;       type = VARIANT_LENGTH;  break;      case eCSSKeyword_in:    units = eCSSUnit_Inch;        type = VARIANT_LENGTH;  break;      case eCSSKeyword_cm:    units = eCSSUnit_Centimeter;  type = VARIANT_LENGTH;  break;      case eCSSKeyword_mm:    units = eCSSUnit_Millimeter;  type = VARIANT_LENGTH;  break;      case eCSSKeyword_pt:    units = eCSSUnit_Point;       type = VARIANT_LENGTH;  break;      case eCSSKeyword_pc:    units = eCSSUnit_Pica;        type = VARIANT_LENGTH;  break;      case eCSSKeyword_deg:   units = eCSSUnit_Degree;      type = VARIANT_ANGLE;   break;      case eCSSKeyword_grad:  units = eCSSUnit_Grad;        type = VARIANT_ANGLE;   break;      case eCSSKeyword_rad:   units = eCSSUnit_Radian;      type = VARIANT_ANGLE;   break;      case eCSSKeyword_hz:    units = eCSSUnit_Hertz;       type = VARIANT_FREQUENCY; break;      case eCSSKeyword_khz:   units = eCSSUnit_Kilohertz;   type = VARIANT_FREQUENCY; break;      case eCSSKeyword_s:     units = eCSSUnit_Seconds;       type = VARIANT_TIME;  break;      case eCSSKeyword_ms:    units = eCSSUnit_Milliseconds;  type = VARIANT_TIME;  break;      default:        // unknown unit        aErrorCode = NS_ERROR_ILLEGAL_VALUE;        return PR_FALSE;    }  } else {    // Must be a zero number...    NS_ASSERTION(0 == aNumber, "numbers without units must be 0");    if ((VARIANT_LENGTH & aVariantMask) != 0) {      units = eCSSUnit_Point;      type = VARIANT_LENGTH;    }    else if ((VARIANT_ANGLE & aVariantMask) != 0) {      units = eCSSUnit_Degree;      type = VARIANT_ANGLE;    }    else if ((VARIANT_FREQUENCY & aVariantMask) != 0) {      units = eCSSUnit_Hertz;      type = VARIANT_FREQUENCY;    }    else if ((VARIANT_TIME & aVariantMask) != 0) {      units = eCSSUnit_Seconds;      type = VARIANT_TIME;    }  }  if ((type & aVariantMask) != 0) {    aValue.SetFloatValue(aNumber, units);    return PR_TRUE;  }  return PR_FALSE;}PRBool CSSParserImpl::ParsePositiveVariant(PRInt32& aErrorCode,                                            nsCSSValue& aValue,                                            PRInt32 aVariantMask,                                            const PRInt32 aKeywordTable[]) {   if (ParseVariant(aErrorCode, aValue, aVariantMask, aKeywordTable)) {     if (eCSSUnit_Number == aValue.GetUnit() ||         aValue.IsLengthUnit()){       if (aValue.GetFloatValue() < 0) {         return PR_FALSE;       }     }     else if(aValue.GetUnit() == eCSSUnit_Percent) {       if (aValue.GetPercentValue() < 0) {         return PR_FALSE;       }     }     return PR_TRUE;   }   return PR_FALSE; } PRBool CSSParserImpl::ParseVariant(PRInt32& aErrorCode, nsCSSValue& aValue,                                   PRInt32 aVariantMask,                                   const PRInt32 aKeywordTable[]){  if (!GetToken(aErrorCode, PR_TRUE)) {    return PR_FALSE;  }  nsCSSToken* tk = &mToken;  if (((aVariantMask & (VARIANT_AHK | VARIANT_NORMAL | VARIANT_NONE)) != 0) &&      (eCSSToken_Ident == tk->mType)) {    nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(tk->mIdent);    if (eCSSKeyword_UNKNOWN < keyword) { // known keyword      if ((aVariantMask & VARIANT_AUTO) != 0) {        if (eCSSKeyword_auto == keyword) {          aValue.SetAutoValue();          return PR_TRUE;        }      }      if ((aVariantMask & VARIANT_INHERIT) != 0) {        if (eCSSKeyword_inherit == keyword) {          aValue.SetInheritValue();          return PR_TRUE;        }        else if (eCSSKeyword__moz_initial == keyword) { // anything that can inherit can also take an initial val.          aValue.SetInitialValue();          return PR_TRUE;        }      }      if ((aVariantMask & VARIANT_NONE) != 0) {        if (eCSSKeyword_none == keyword) {          aValue.SetNoneValue();          return PR_TRUE;        }      }      if ((aVariantMask & VARIANT_NORMAL) != 0) {        if (eCSSKeyword_normal == keyword) {          aValue.SetNormalValue();          return PR_TRUE;        }      }      if ((aVariantMask & VARIANT_KEYWORD) != 0) {        PRInt32 index = SearchKeywordTable(keyword, aKeywordTable);        if (0 < index) {          aValue.SetIntValue(aKeywordTable[index], eCSSUnit_Enumerated);          return PR_TRUE;        }      }    }  }  if (((aVariantMask & (VARIANT_LENGTH | VARIANT_ANGLE | VARIANT_FREQUENCY | VARIANT_TIME)) != 0) &&       tk->IsDimension()) {    return TranslateDimension(aErrorCode, aValue, aVariantMask, tk->mNumber, tk->mIdent);  }  if (((aVariantMask & VARIANT_PERCENT) != 0) &&      (eCSSToken_Percentage == tk->mType)) {    aValue.SetPercentValue(tk->mNumber);    return PR_TRUE;  }  if (((aVariantMask & VARIANT_NUMBER) != 0) &&      (eCSSToken_Number == tk->mType)) {    aValue.SetFloatValue(tk->mNumber, eCSSUnit_Number);    return PR_TRUE;  }  if (((aVariantMask & VARIANT_INTEGER) != 0) &&      (eCSSToken_Number == tk->mType) && tk->mIntegerValid) {    aValue.SetIntValue(tk->mInteger, eCSSUnit_Integer);    return PR_TRUE;  }  if (mNavQuirkMode && !IsParsingCompoundProperty()) { // NONSTANDARD: Nav interprets unitless numbers as px    if (((aVariantMask & VARIANT_LENGTH) != 0) &&        (eCSSToken_Number == tk->mType)) {      aValue.SetFloatValue(tk->mNumber, eCSSUnit_Pixel);      return PR_TRUE;    }  }  if (((aVariantMask & VARIANT_URL) != 0) &&      (eCSSToken_Function == tk->mType) &&       tk->mIdent.EqualsIgnoreCase("url")) {    if (ParseURL(aErrorCode, aValue)) {      return PR_TRUE;    }    return PR_FALSE;  }  if ((aVariantMask & VARIANT_COLOR) != 0) {    if ((mNavQuirkMode && !IsParsingCompoundProperty()) || // NONSTANDARD: Nav interprets 'xxyyzz' values even without '#' prefix    		(eCSSToken_ID == tk->mType) ||         (eCSSToken_Ident == tk->mType) ||        ((eCSSToken_Function == tk->mType) &&          (tk->mIdent.EqualsIgnoreCase("rgb")))) {      // Put token back so that parse color can get it      UngetToken();      if (ParseColor(aErrorCode, aValue)) {        return PR_TRUE;      }      return PR_FALSE;    }  }  if (((aVariantMask & VARIANT_STRING) != 0) &&       (eCSSToken_String == tk->mType)) {    nsAutoString  buffer;    buffer.Append(tk->mSymbol);    buffer.Append(tk->mIdent);    buffer.Append(tk->mSymbol);    aValue.SetStringValue(buffer, eCSSUnit_String);    return PR_TRUE;  }  if (((aVariantMask & VARIANT_IDENTIFIER) != 0) &&       (eCSSToken_Ident == tk->mType)) {    aValue.SetStringValue(tk->mIdent, eCSSUnit_String);    return PR_TRUE;  }  if (((aVariantMask & VARIANT_COUNTER) != 0) &&      (eCSSToken_Function == tk->mType) &&      (tk->mIdent.EqualsIgnoreCase("counter") ||        tk->mIdent.EqualsIgnoreCase("counters"))) {#ifdef ENABLE_COUNTERS    if (ParseCounter(aErrorCode, aValue)) {      return PR_TRUE;    }#endif    return PR_FALSE;  }  if (((aVariantMask & VARIANT_ATTR) != 0) &&      (eCSSToken_Function == tk->mType) &&      tk->mIdent.EqualsIgnoreCase("attr")) {        if (ParseAttr(aErrorCode, aValue)) {      return PR_TRUE;    }    return PR_FALSE;  }  UngetToken();  return PR_FALSE;}PRBool CSSParserImpl::ParseCounter(PRInt32& aErrorCode, nsCSSValue& aValue){  nsCSSUnit unit = (mToken.mIdent.EqualsIgnoreCase("counter") ?                     eCSSUnit_Counter : eCSSUnit_Counters);  if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {    if (GetToken(aErrorCode, PR_TRUE)) {      if (eCSSToken_Ident == mToken.mType) {        nsAutoString  counter;        counter.Append(mToken.mIdent);        if (eCSSUnit_Counters == unit) {          // get mandatory string          if (! ExpectSymbol(aErrorCode, ',', PR_TRUE)) {            return PR_FALSE;          }          if (GetToken(aErrorCode, PR_TRUE) && (eCSSToken_String == mToken.mType)) {            counter.AppendWithConversion(',');            counter.Append(mToken.mSymbol); // quote too            counter.Append(mToken.mIdent);            counter.Append(mToken.mSymbol); // quote too          }          else {            UngetToken();            return PR_FALSE;          }        }        // get optional type        if (ExpectSymbol(aErrorCode, ',', PR_TRUE)) {          if (GetToken(aErrorCode, PR_TRUE) && (eCSSToken_Ident == mToken.mType)) {            nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);            if ((eCSSKeyword_UNKNOWN < keyword) &&                 (0 < SearchKeywordTable(keyword, nsCSSProps::kListStyleKTable))) {              counter.AppendWithConversion(',');              counter.Append(mToken.mIdent);            }            else {              return PR_FALSE;            }          }          else {            UngetToken();            return PR_FALSE;          }        }        if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) {          aValue.SetStringValue(counter, unit);          return PR_TRUE;        }      }      else {        UngetToken();      }    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseAttr(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {    if (GetToken(aErrorCode, PR_TRUE)) {      nsAutoString attr;      if (eCSSToken_Ident == mToken.mType) {  // attr name or namespace        nsAutoString  holdIdent(mToken.mIdent);        if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {  // namespace          PRInt32 nameSpaceID = kNameSpaceID_Unknown;          if (mNameSpace) {            nsIAtom* prefix;            holdIdent.ToLowerCase(); // always case insensitive, since stays within CSS            prefix = NS_NewAtom(holdIdent);            mNameSpace->FindNameSpaceID(prefix, nameSpaceID);            NS_IF_RELEASE(prefix);          } // else, no delcared namespaces          if (kNameSpaceID_Unknown == nameSpaceID) {  // unknown prefix, dump it            return PR_FALSE;          }          attr.AppendInt(nameSpaceID, 10);          attr.AppendWithConversion('|');          if (! GetToken(aErrorCode, PR_FALSE)) {            return PR_FALSE;          }          if (eCSSToken_Ident == mToken.mType) {            if (mCaseSensitive) {              attr.Append(mToken.mIdent);            } else {              nsAutoString buffer;              mToken.mIdent.ToLowerCase(buffer);              attr.Append(buffer);            }          }          else {            UngetToken();            return PR_FALSE;          }        }        else {  // no namespace          if (mCaseSensitive) {            attr = holdIdent;          }          else {            holdIdent.ToLowerCase(attr);          }        }      }      else if (mToken.IsSymbol('*')) {  // namespace wildcard        if (ExpectSymbol(aErrorCode, '|', PR_FALSE)) {          attr.AppendInt(kNameSpaceID_Unknown, 10);          attr.AppendWithConversion('|');          if (! GetToken(aErrorCode, PR_FALSE)) {            return PR_FALSE;          }          if (eCSSToken_Ident == mToken.mType) {            attr.Append(mToken.mIdent);          }          else {            UngetToken();            return PR_FALSE;          }        }        else {          return PR_FALSE;        }      }      else if (mToken.IsSymbol('|')) {  // explicit NO namespace        if (! GetToken(aErrorCode, PR_FALSE)) {          return PR_FALSE;        }        if (eCSSToken_Ident == mToken.mType) {          if (mCaseSensitive) {            attr.Append(mToken.mIdent);          } else {            nsAutoString buffer;            mToken.mIdent.ToLowerCase(buffer);            attr.Append(buffer);          }        }        else {          UngetToken();          return PR_FALSE;        }      }      else {        UngetToken();        return PR_FALSE;      }      if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) {        aValue.SetStringValue(attr, eCSSUnit_Attr);        return PR_TRUE;      }    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseURL(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ExpectSymbol(aErrorCode, '(', PR_FALSE)) {    if (! GetURLToken(aErrorCode, PR_TRUE)) {      return PR_FALSE;    }    nsCSSToken* tk = &mToken;    if ((eCSSToken_String == tk->mType) || (eCSSToken_URL == tk->mType)) {      // Translate url into an absolute url if the url is relative to      // the style sheet.      // XXX editors won't like this - too bad for now      nsAutoString absURL;      if (nsnull != mURL) {        nsAutoString baseURL;        nsresult rv;        nsCOMPtr<nsIURI> base;        rv = mURL->Clone(getter_AddRefs(base));        if (NS_SUCCEEDED(rv)) {          rv = NS_MakeAbsoluteURI(absURL, tk->mIdent, base);        }        if (NS_FAILED(rv)) {          absURL = tk->mIdent;        }      }      else {        absURL = tk->mIdent;      }      if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) {        aValue.SetStringValue(absURL, eCSSUnit_URL);        return PR_TRUE;      }    }  }  return PR_FALSE;}PRInt32 CSSParserImpl::ParseChoice(PRInt32& aErrorCode, nsCSSValue aValues[],                                   const nsCSSProperty aPropIDs[], PRInt32 aNumIDs){  PRInt32 found = 0;  SetParsingCompoundProperty(PR_TRUE);  PRInt32 loop;  for (loop = 0; loop < aNumIDs; loop++) {    // Try each property parser in order    PRInt32 hadFound = found;    PRInt32 index;    for (index = 0; index < aNumIDs; index++) {      PRInt32 bit = 1 << index;      if ((found & bit) == 0) {        if (ParseSingleValueProperty(aErrorCode, aValues[index], aPropIDs[index])) {          found |= bit;        }        if (aErrorCode == NS_ERROR_ILLEGAL_VALUE) { // bug 47138          aErrorCode = NS_OK;          found = 0;          goto done;        }      }    }    if (found == hadFound) {  // found nothing new      break;    }  }  if (0 < found) {    if (1 == found) { // only first property      if (eCSSUnit_Inherit == aValues[0].GetUnit()) { // one inherit, all inherit        for (loop = 1; loop < aNumIDs; loop++) {          aValues[loop].SetInheritValue();        }        found = ((1 << aNumIDs) - 1);      }      else if (eCSSUnit_Initial == aValues[0].GetUnit()) { // one initial, all initial        for (loop = 1; loop < aNumIDs; loop++) {          aValues[loop].SetInitialValue();        }        found = ((1 << aNumIDs) - 1);      }    }    else {  // more than one value, verify no inherits or initials      for (loop = 0; loop < aNumIDs; loop++) {        if (eCSSUnit_Inherit == aValues[loop].GetUnit()) {          found = -1;          break;        }        else if (eCSSUnit_Initial == aValues[loop].GetUnit()) {          found = -1;          break;        }      }    }  }done:  SetParsingCompoundProperty(PR_FALSE);  return found;}nsresult CSSParserImpl::AppendValue(nsICSSDeclaration* aDeclaration, nsCSSProperty aPropID,                                    const nsCSSValue& aValue, PRInt32& aChangeHint){  nsresult  result;  nsCSSValue  oldValue;  result = aDeclaration->GetValue(aPropID, oldValue);  if (aValue != oldValue) {    result = aDeclaration->AppendValue(aPropID, aValue);    if (aChangeHint < nsCSSProps::kHintTable[aPropID]) {      aChangeHint = nsCSSProps::kHintTable[aPropID];    }  }  return result;}/** * Parse a "box" property. Box properties have 1 to 4 values. When less * than 4 values are provided a standard mapping is used to replicate * existing values.  */PRBool CSSParserImpl::ParseBoxProperties(PRInt32& aErrorCode,                                         nsICSSDeclaration* aDeclaration,                                         const nsCSSProperty aPropIDs[],                                         PRInt32& aChangeHint){  // Get up to four values for the property  nsCSSValue  values[4];  PRInt32 count = 0;  PRInt32 index;  for (index = 0; index < 4; index++) {    if (! ParseSingleValueProperty(aErrorCode, values[index], aPropIDs[index])) {      if (aErrorCode == NS_ERROR_ILLEGAL_VALUE) { // bug 47138        aErrorCode = NS_OK;        count = 0;      }      break;    }    count++;  }  if ((count == 0) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  if (1 < count) { // verify no more than single inherit or initial    for (index = 0; index < 4; index++) {      if (eCSSUnit_Inherit == values[index].GetUnit() ||          eCSSUnit_Initial == values[index].GetUnit()) {        return PR_FALSE;      }    }  }  // Provide missing values by replicating some of the values found  switch (count) {    case 1: // Make right == top      values[1] = values[0];    case 2: // Make bottom == top      values[2] = values[0];    case 3: // Make left == right      values[3] = values[1];  }  for (index = 0; index < 4; index++) {    AppendValue(aDeclaration, aPropIDs[index], values[index], aChangeHint);  }  return PR_TRUE;}PRBool CSSParserImpl::ParseProperty(PRInt32& aErrorCode,                                    nsICSSDeclaration* aDeclaration,                                    nsCSSProperty aPropID,                                    PRInt32& aChangeHint){  switch (aPropID) {  // handle shorthand or multiple properties  case eCSSProperty_background:    return ParseBackground(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_background_position:    return ParseBackgroundPosition(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_border:    return ParseBorder(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_border_color:    return ParseBorderColor(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_border_spacing:    return ParseBorderSpacing(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_border_style:    return ParseBorderStyle(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_border_bottom:    return ParseBorderSide(aErrorCode, aDeclaration, kBorderBottomIDs, aChangeHint);  case eCSSProperty_border_left:    return ParseBorderSide(aErrorCode, aDeclaration, kBorderLeftIDs, aChangeHint);  case eCSSProperty_border_right:    return ParseBorderSide(aErrorCode, aDeclaration, kBorderRightIDs, aChangeHint);  case eCSSProperty_border_top:    return ParseBorderSide(aErrorCode, aDeclaration, kBorderTopIDs, aChangeHint);  case eCSSProperty_border_width:    return ParseBorderWidth(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty__moz_border_radius:    return ParseBorderRadius(aErrorCode, aDeclaration, aChangeHint);#ifdef ENABLE_OUTLINE  case eCSSProperty__moz_outline_radius:    return ParseOutlineRadius(aErrorCode, aDeclaration, aChangeHint);#endif  case eCSSProperty_clip:    return ParseClip(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_content:    return ParseContent(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_counter_increment:  case eCSSProperty_counter_reset:    return ParseCounterData(aErrorCode, aDeclaration, aPropID, aChangeHint);  case eCSSProperty_cue:    return ParseCue(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_cursor:    return ParseCursor(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_font:    return ParseFont(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_list_style:    return ParseListStyle(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_margin:    return ParseMargin(aErrorCode, aDeclaration, aChangeHint);#ifdef ENABLE_OUTLINE  case eCSSProperty_outline:    return ParseOutline(aErrorCode, aDeclaration, aChangeHint);#endif  case eCSSProperty_padding:    return ParsePadding(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_pause:    return ParsePause(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_play_during:    return ParsePlayDuring(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_quotes:    return ParseQuotes(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_size:    return ParseSize(aErrorCode, aDeclaration, aChangeHint);  case eCSSProperty_text_shadow:    return ParseTextShadow(aErrorCode, aDeclaration, aChangeHint);  // Strip out properties we use internally. These properties are used  // by compound property parsing routines (e.g. "background-position").  case eCSSProperty_background_x_position:  case eCSSProperty_background_y_position:  case eCSSProperty_border_x_spacing:  case eCSSProperty_border_y_spacing:  case eCSSProperty_clip_bottom:  case eCSSProperty_clip_left:  case eCSSProperty_clip_right:  case eCSSProperty_clip_top:  case eCSSProperty_play_during_flags:  case eCSSProperty_quotes_close:  case eCSSProperty_quotes_open:  case eCSSProperty_size_height:  case eCSSProperty_size_width:  case eCSSProperty_text_shadow_color:  case eCSSProperty_text_shadow_radius:  case eCSSProperty_text_shadow_x:  case eCSSProperty_text_shadow_y:    // The user can't use these    REPORT_UNEXPECTED(NS_LITERAL_STRING("Attempt to use inaccessible property"));    return PR_FALSE;  default:  // must be single property    {      nsCSSValue  value;      if (ParseSingleValueProperty(aErrorCode, value, aPropID)) {        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          aErrorCode = AppendValue(aDeclaration, aPropID, value, aChangeHint);          return PR_TRUE;        }        // XXX Report errors?      }      // XXX Report errors?    }  }  return PR_FALSE;}// Bits used in determining which background position info we have#define BG_CENTER  0x01#define BG_TOP     0x02#define BG_BOTTOM  0x04#define BG_LEFT    0x08#define BG_RIGHT   0x10#define BG_CENTER1 0x20#define BG_CENTER2 0x40// Note: Don't change this table unless you update// parseBackgroundPosition!static const PRInt32 kBackgroundXYPositionKTable[] = {  eCSSKeyword_center, BG_CENTER,  eCSSKeyword_top, BG_TOP,  eCSSKeyword_bottom, BG_BOTTOM,  eCSSKeyword_left, BG_LEFT,  eCSSKeyword_right, BG_RIGHT,  -1,};PRBool CSSParserImpl::ParseSingleValueProperty(PRInt32& aErrorCode,                                               nsCSSValue& aValue,                                               nsCSSProperty aPropID){  switch (aPropID) {  case eCSSProperty_UNKNOWN:  case eCSSProperty_background:  case eCSSProperty_background_position:  case eCSSProperty_border:  case eCSSProperty_border_color:  case eCSSProperty_border_spacing:  case eCSSProperty_border_style:  case eCSSProperty_border_bottom:  case eCSSProperty_border_left:  case eCSSProperty_border_right:  case eCSSProperty_border_top:  case eCSSProperty_border_width:  case eCSSProperty_clip:  case eCSSProperty_content:  case eCSSProperty_counter_increment:  case eCSSProperty_counter_reset:  case eCSSProperty_cue:  case eCSSProperty_cursor:  case eCSSProperty_font:  case eCSSProperty_list_style:  case eCSSProperty_margin:#ifdef ENABLE_OUTLINE  case eCSSProperty_outline:#endif  case eCSSProperty_padding:  case eCSSProperty_pause:  case eCSSProperty_play_during:  case eCSSProperty_quotes:  case eCSSProperty_size:  case eCSSProperty_text_shadow:  case eCSSProperty_COUNT:    NS_ERROR("not a single value property");    return PR_FALSE;  case eCSSProperty_border_x_spacing:  case eCSSProperty_border_y_spacing:  case eCSSProperty_clip_bottom:  case eCSSProperty_clip_left:  case eCSSProperty_clip_right:  case eCSSProperty_clip_top:  case eCSSProperty_play_during_flags:  case eCSSProperty_quotes_close:  case eCSSProperty_quotes_open:  case eCSSProperty_size_height:  case eCSSProperty_size_width:  case eCSSProperty_text_shadow_color:  case eCSSProperty_text_shadow_radius:  case eCSSProperty_text_shadow_x:  case eCSSProperty_text_shadow_y:    NS_ERROR("not currently parsed here");    return PR_FALSE;  case eCSSProperty_azimuth:    return ParseAzimuth(aErrorCode, aValue);  case eCSSProperty_background_attachment:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBackgroundAttachmentKTable);  case eCSSProperty_background_color:    return ParseVariant(aErrorCode, aValue, VARIANT_HCK,                        nsCSSProps::kBackgroundColorKTable);  case eCSSProperty_background_image:    return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);  case eCSSProperty_background_repeat:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBackgroundRepeatKTable);  case eCSSProperty_background_x_position:  case eCSSProperty_background_y_position:    return ParseVariant(aErrorCode, aValue, VARIANT_HKLP,                        kBackgroundXYPositionKTable);  case eCSSProperty_binding:    return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);  case eCSSProperty_border_collapse:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBorderCollapseKTable);  case eCSSProperty_border_bottom_color:  case eCSSProperty_border_left_color:  case eCSSProperty_border_right_color:  case eCSSProperty_border_top_color:    return ParseVariant(aErrorCode, aValue, VARIANT_HCK,                         nsCSSProps::kBorderColorKTable);  case eCSSProperty_border_bottom_style:  case eCSSProperty_border_left_style:  case eCSSProperty_border_right_style:  case eCSSProperty_border_top_style:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kBorderStyleKTable);  case eCSSProperty_border_bottom_width:  case eCSSProperty_border_left_width:  case eCSSProperty_border_right_width:  case eCSSProperty_border_top_width:    return ParseVariant(aErrorCode, aValue, VARIANT_HKL,                        nsCSSProps::kBorderWidthKTable);  case eCSSProperty__moz_border_radius_topLeft:  case eCSSProperty__moz_border_radius_topRight:  case eCSSProperty__moz_border_radius_bottomRight:  case eCSSProperty__moz_border_radius_bottomLeft:    return ParseVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);#ifdef ENABLE_OUTLINE  case eCSSProperty__moz_outline_radius_topLeft:  case eCSSProperty__moz_outline_radius_topRight:  case eCSSProperty__moz_outline_radius_bottomRight:  case eCSSProperty__moz_outline_radius_bottomLeft:    return ParseVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);#endif  case eCSSProperty_bottom:  case eCSSProperty_top:  case eCSSProperty_left:  case eCSSProperty_right:	  return ParseVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);#ifdef INCLUDE_XUL  case eCSSProperty_box_align:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBoxAlignKTable);  case eCSSProperty_box_direction:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBoxDirectionKTable);  case eCSSProperty_box_flex:    return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);  case eCSSProperty_box_orient:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBoxOrientKTable);  case eCSSProperty_box_pack:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBoxPackKTable);#endif  case eCSSProperty_box_sizing:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kBoxSizingKTable);  case eCSSProperty_height:  case eCSSProperty_width:    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);  case eCSSProperty_caption_side:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                         nsCSSProps::kCaptionSideKTable);  case eCSSProperty_clear:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kClearKTable);  case eCSSProperty_color:    return ParseVariant(aErrorCode, aValue, VARIANT_HC, nsnull);  case eCSSProperty_cue_after:  case eCSSProperty_cue_before:    return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);  case eCSSProperty_direction:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kDirectionKTable);  case eCSSProperty_display:    if (ParseVariant(aErrorCode, aValue, VARIANT_HOK, nsCSSProps::kDisplayKTable)) {			if (aValue.GetUnit() == eCSSUnit_Enumerated) {				switch (aValue.GetIntValue()) {					case NS_STYLE_DISPLAY_MARKER:        // bug 2055					case NS_STYLE_DISPLAY_RUN_IN:		 // bug 2056					case NS_STYLE_DISPLAY_COMPACT:       // bug 14983					case NS_STYLE_DISPLAY_INLINE_TABLE:  // bug 18218						//aErrorCode = NS_CSS_PARSER_DROP_DECLARATION;  // bug 15432 (commented out for bug 46562 and 38397)						return PR_FALSE;				}			}      return PR_TRUE;		}    return PR_FALSE;  case eCSSProperty_elevation:    return ParseVariant(aErrorCode, aValue, VARIANT_HK | VARIANT_ANGLE,                        nsCSSProps::kElevationKTable);  case eCSSProperty_empty_cells:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kEmptyCellsKTable);  case eCSSProperty_float:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kFloatKTable);  case eCSSProperty_float_edge:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kFloatEdgeKTable);  case eCSSProperty_font_family:    return ParseFamily(aErrorCode, aValue);  case eCSSProperty_font_size:     {      // NONSTANDARD: *** Nav 4 ignores font-size values with no units ***      //              if quirk mode AND the value had no units (type=Number) and      //              it was otherwise successful, we need to ignore it      PRBool bRetVal = ParsePositiveVariant(aErrorCode, aValue, VARIANT_HKLP,                                            nsCSSProps::kFontSizeKTable);      if (bRetVal == PR_TRUE &&          mNavQuirkMode == PR_TRUE &&           mToken.mType == eCSSToken_Number){        return bRetVal = PR_FALSE;      }      return bRetVal;    }  case eCSSProperty_font_size_adjust:    return ParseVariant(aErrorCode, aValue, VARIANT_HON,                        nsnull);  case eCSSProperty_font_stretch:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK,                        nsCSSProps::kFontStretchKTable);  case eCSSProperty_font_style:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK,                        nsCSSProps::kFontStyleKTable);  case eCSSProperty_font_variant:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK,                        nsCSSProps::kFontVariantKTable);  case eCSSProperty_font_weight:    return ParseFontWeight(aErrorCode, aValue);  case eCSSProperty_letter_spacing:  case eCSSProperty_word_spacing:    return ParseVariant(aErrorCode, aValue, VARIANT_HL | VARIANT_NORMAL, nsnull);  case eCSSProperty_key_equivalent:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kKeyEquivalentKTable);  case eCSSProperty_line_height:    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLPN | VARIANT_NORMAL, nsnull);  case eCSSProperty_list_style_image:    return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);  case eCSSProperty_list_style_position:    return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kListStylePositionKTable);  case eCSSProperty_list_style_type:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK, nsCSSProps::kListStyleKTable);  case eCSSProperty_margin_bottom:  case eCSSProperty_margin_left:  case eCSSProperty_margin_right:  case eCSSProperty_margin_top:    return ParseVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);  case eCSSProperty_marker_offset:    return ParseVariant(aErrorCode, aValue, VARIANT_AHL, nsnull);  case eCSSProperty_marks:    return ParseMarks(aErrorCode, aValue);  case eCSSProperty_max_height:  case eCSSProperty_max_width:    return ParseVariant(aErrorCode, aValue, VARIANT_HLPO, nsnull);  case eCSSProperty_min_height:  case eCSSProperty_min_width:    return ParseVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);  case eCSSProperty_opacity:    return ParseVariant(aErrorCode, aValue, VARIANT_HPN, nsnull);  case eCSSProperty_orphans:  case eCSSProperty_widows:    return ParseVariant(aErrorCode, aValue, VARIANT_HI, nsnull);#ifdef ENABLE_OUTLINE  case eCSSProperty_outline_color:    return ParseVariant(aErrorCode, aValue, VARIANT_HCK,                         nsCSSProps::kOutlineColorKTable);  case eCSSProperty_outline_style:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                         nsCSSProps::kBorderStyleKTable);  case eCSSProperty_outline_width:    return ParseVariant(aErrorCode, aValue, VARIANT_HKL,                        nsCSSProps::kBorderWidthKTable);#endif  case eCSSProperty_overflow:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK,                        nsCSSProps::kOverflowKTable);  case eCSSProperty_padding_bottom:  case eCSSProperty_padding_left:  case eCSSProperty_padding_right:  case eCSSProperty_padding_top:    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);  case eCSSProperty_page:    return ParseVariant(aErrorCode, aValue, VARIANT_AUTO | VARIANT_IDENTIFIER, nsnull);  case eCSSProperty_page_break_after:  case eCSSProperty_page_break_before:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK,                         nsCSSProps::kPageBreakKTable);  case eCSSProperty_page_break_inside:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK,                         nsCSSProps::kPageBreakInsideKTable);  case eCSSProperty_pause_after:  case eCSSProperty_pause_before:    return ParseVariant(aErrorCode, aValue, VARIANT_HTP, nsnull);  case eCSSProperty_pitch:    return ParseVariant(aErrorCode, aValue, VARIANT_HKF, nsCSSProps::kPitchKTable);  case eCSSProperty_pitch_range:    return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);  case eCSSProperty_position:    return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kPositionKTable);  case eCSSProperty_resizer:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK | VARIANT_NONE,                        nsCSSProps::kResizerKTable);  case eCSSProperty_richness:    return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);  case eCSSProperty_speak:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK | VARIANT_NONE,                        nsCSSProps::kSpeakKTable);  case eCSSProperty_speak_header:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kSpeakHeaderKTable);  case eCSSProperty_speak_numeral:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kSpeakNumeralKTable);  case eCSSProperty_speak_punctuation:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kSpeakPunctuationKTable);  case eCSSProperty_speech_rate:    return ParseVariant(aErrorCode, aValue, VARIANT_HN | VARIANT_KEYWORD,                        nsCSSProps::kSpeechRateKTable);  case eCSSProperty_stress:    return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);  case eCSSProperty_table_layout:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK,                        nsCSSProps::kTableLayoutKTable);  case eCSSProperty_text_align:    return ParseVariant(aErrorCode, aValue, VARIANT_HK | VARIANT_STRING,                        nsCSSProps::kTextAlignKTable);  case eCSSProperty_text_decoration:    return ParseTextDecoration(aErrorCode, aValue);  case eCSSProperty_text_indent:    return ParseVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);  case eCSSProperty_text_transform:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kTextTransformKTable);  case eCSSProperty_unicode_bidi:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK,                        nsCSSProps::kUnicodeBidiKTable);  case eCSSProperty_user_focus:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK | VARIANT_NONE,                        nsCSSProps::kUserFocusKTable);  case eCSSProperty_user_input:    return ParseVariant(aErrorCode, aValue, VARIANT_AHK | VARIANT_NONE,                        nsCSSProps::kUserInputKTable);  case eCSSProperty_user_modify:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                        nsCSSProps::kUserModifyKTable);  case eCSSProperty_user_select:    return ParseVariant(aErrorCode, aValue, VARIANT_HOK,                        nsCSSProps::kUserSelectKTable);  case eCSSProperty_vertical_align:    return ParseVariant(aErrorCode, aValue, VARIANT_HKLP,                        nsCSSProps::kVerticalAlignKTable);  case eCSSProperty_visibility:    return ParseVariant(aErrorCode, aValue, VARIANT_HK,                         nsCSSProps::kVisibilityKTable);  case eCSSProperty_voice_family:    return ParseFamily(aErrorCode, aValue);  case eCSSProperty_volume:    return ParseVariant(aErrorCode, aValue, VARIANT_HPN | VARIANT_KEYWORD,                        nsCSSProps::kVolumeKTable);  case eCSSProperty_white_space:    return ParseVariant(aErrorCode, aValue, VARIANT_HMK,                        nsCSSProps::kWhitespaceKTable);  case eCSSProperty_z_index:    return ParseVariant(aErrorCode, aValue, VARIANT_AHI, nsnull);  }  // explicitly do NOT have a default case to let the compiler  // help find missing properties  return PR_FALSE;}PRBool CSSParserImpl::ParseAzimuth(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ParseVariant(aErrorCode, aValue, VARIANT_HK | VARIANT_ANGLE,                    nsCSSProps::kAzimuthKTable)) {    if (eCSSUnit_Enumerated == aValue.GetUnit()) {      PRInt32 intValue = aValue.GetIntValue();      if ((NS_STYLE_AZIMUTH_LEFT_SIDE <= intValue) &&           (intValue <= NS_STYLE_AZIMUTH_BEHIND)) {  // look for optional modifier        nsCSSValue  modifier;        if (ParseEnum(aErrorCode, modifier, nsCSSProps::kAzimuthKTable)) {          PRInt32 enumValue = modifier.GetIntValue();          if (((intValue == NS_STYLE_AZIMUTH_BEHIND) &&                (NS_STYLE_AZIMUTH_LEFT_SIDE <= enumValue) && (enumValue <= NS_STYLE_AZIMUTH_RIGHT_SIDE)) ||              ((enumValue == NS_STYLE_AZIMUTH_BEHIND) &&                (NS_STYLE_AZIMUTH_LEFT_SIDE <= intValue) && (intValue <= NS_STYLE_AZIMUTH_RIGHT_SIDE))) {            aValue.SetIntValue(intValue | enumValue, eCSSUnit_Enumerated);            return PR_TRUE;          }          // Put the unknown identifier back and return          UngetToken();          return PR_FALSE;        }      }    }    return PR_TRUE;  }  return PR_FALSE;}PRBool CSSParserImpl::ParseBackground(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                       PRInt32& aChangeHint){  const PRInt32 numProps = 6;  static const nsCSSProperty kBackgroundIDs[numProps] = {    eCSSProperty_background_color,    eCSSProperty_background_image,    eCSSProperty_background_repeat,    eCSSProperty_background_attachment,    eCSSProperty_background_x_position,    eCSSProperty_background_y_position  };  nsCSSValue  values[numProps];  PRInt32 found = ParseChoice(aErrorCode, values, kBackgroundIDs, numProps);  if ((found < 1) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  if (0 != (found & 0x30)) {  // found one or more position values, validate them    if (0 == (found & 0x20)) {  // x value only      if (eCSSUnit_Enumerated == values[4].GetUnit()) {        switch (values[4].GetIntValue()) {          case BG_CENTER:            values[4].SetIntValue(50, eCSSUnit_Enumerated);            values[5].SetIntValue(50, eCSSUnit_Enumerated);            break;          case BG_TOP:            values[4].SetIntValue(50, eCSSUnit_Enumerated);            values[5].SetIntValue(0, eCSSUnit_Enumerated);            break;          case BG_BOTTOM:            values[4].SetIntValue(50, eCSSUnit_Enumerated);            values[5].SetIntValue(100, eCSSUnit_Enumerated);            break;          case BG_LEFT:            values[4].SetIntValue(0, eCSSUnit_Enumerated);            values[5].SetIntValue(50, eCSSUnit_Enumerated);            break;          case BG_RIGHT:            values[4].SetIntValue(100, eCSSUnit_Enumerated);            values[5].SetIntValue(50, eCSSUnit_Enumerated);            break;        }      }      else if (eCSSUnit_Inherit == values[4].GetUnit()) {        values[5].SetInheritValue();      }      else if (eCSSUnit_Initial == values[4].GetUnit()) {        values[5].SetInitialValue();      }      else {        values[5].SetPercentValue(0.5f);      }    }    else { // both x & y values      nsCSSUnit xUnit = values[4].GetUnit();      nsCSSUnit yUnit = values[5].GetUnit();      if (eCSSUnit_Enumerated == xUnit) { // if one is enumerated, both must be        if (eCSSUnit_Enumerated == yUnit) {          PRInt32 xValue = values[4].GetIntValue();          PRInt32 yValue = values[5].GetIntValue();          if (0 != (xValue & (BG_LEFT | BG_CENTER | BG_RIGHT))) {  // x is really an x value            if (0 != (yValue & (BG_LEFT | BG_RIGHT))) { // y is also an x value              return PR_FALSE;            }          }          else {  // x is a y value            if (0 != (yValue & (BG_TOP | BG_BOTTOM))) { // y is also a y value              return PR_FALSE;            }            PRInt32 holdXValue = xValue;            xValue = yValue;            yValue = holdXValue;          }          switch (xValue) {            case BG_LEFT:              values[4].SetIntValue(0, eCSSUnit_Enumerated);              break;            case BG_CENTER:              values[4].SetIntValue(50, eCSSUnit_Enumerated);              break;            case BG_RIGHT:              values[4].SetIntValue(100, eCSSUnit_Enumerated);              break;            default:              NS_ERROR("bad x value");          }          switch (yValue) {            case BG_TOP:              values[5].SetIntValue(0, eCSSUnit_Enumerated);              break;            case BG_CENTER:              values[5].SetIntValue(50, eCSSUnit_Enumerated);              break;            case BG_BOTTOM:              values[5].SetIntValue(100, eCSSUnit_Enumerated);              break;            default:              NS_ERROR("bad y value");          }        }        else {          return PR_FALSE;        }      }      else {        if (eCSSUnit_Enumerated == yUnit) {          return PR_FALSE;        }      }    }  }  // Provide missing values  if ((found & 0x01) == 0) {    values[0].SetIntValue(NS_STYLE_BG_COLOR_TRANSPARENT, eCSSUnit_Enumerated);  }  if ((found & 0x02) == 0) {    values[1].SetNoneValue();  }  if ((found & 0x04) == 0) {    values[2].SetIntValue(NS_STYLE_BG_REPEAT_XY, eCSSUnit_Enumerated);  }  if ((found & 0x08) == 0) {    values[3].SetIntValue(NS_STYLE_BG_ATTACHMENT_SCROLL, eCSSUnit_Enumerated);  }  if ((found & 0x30) == 0) {    values[4].SetPercentValue(0.0f);    values[5].SetPercentValue(0.0f);  }  PRInt32 index;  for (index = 0; index < numProps; index++) {    AppendValue(aDeclaration, kBackgroundIDs[index], values[index], aChangeHint);  }  return PR_TRUE;}PRBool CSSParserImpl::ParseBackgroundPosition(PRInt32& aErrorCode,                                              nsICSSDeclaration* aDeclaration,                                              PRInt32& aChangeHint){  // First try a number or a length value  nsCSSValue  xValue;  if (ParseVariant(aErrorCode, xValue, VARIANT_HLP, nsnull)) {    if (eCSSUnit_Inherit == xValue.GetUnit() ||        eCSSUnit_Initial == xValue.GetUnit()) {  // both are inherited or both are set to initial      if (ExpectEndProperty(aErrorCode, PR_TRUE)) {        AppendValue(aDeclaration, eCSSProperty_background_x_position, xValue, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_background_y_position, xValue, aChangeHint);        return PR_TRUE;      }      return PR_FALSE;    }    // We have one number/length. Get the optional second number/length.    nsCSSValue yValue;    if (ParseVariant(aErrorCode, yValue, VARIANT_LP, nsnull)) {      // We have two numbers      if (ExpectEndProperty(aErrorCode, PR_TRUE)) {        AppendValue(aDeclaration, eCSSProperty_background_x_position, xValue, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_background_y_position, yValue, aChangeHint);        return PR_TRUE;      }      return PR_FALSE;    }    // We have one number which is the x position. Create an value for    // the vertical position which is of value 50%    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_background_x_position, xValue, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_background_y_position, nsCSSValue(0.5f, eCSSUnit_Percent), aChangeHint);      return PR_TRUE;    }    return PR_FALSE;  }  // Now try keywords. We do this manually to allow for the first  // appearance of "center" to apply to the either the x or y  // position (it's ambiguous so we have to disambiguate). Each  // allowed keyword value is assigned it's own bit. We don't allow  // any duplicate keywords other than center. We try to get two  // keywords but it's okay if there is only one.  PRInt32 mask = 0;  PRInt32 centerBit = BG_CENTER1;  for (PRInt32 i = 0; i < 2; i++) {    if (PR_FALSE == ParseEnum(aErrorCode, xValue, kBackgroundXYPositionKTable)) {      break;    }    PRInt32 bit = xValue.GetIntValue();    if (BG_CENTER == bit) {      // Special hack for center bits: We can have two of them      mask |= centerBit;      centerBit <<= 1;      continue;    } else if ((mask & bit) != 0) {      // no duplicate values allowed (other than center)      return PR_FALSE;    }    mask |= bit;  }  // Check for bad input. Bad input consists of no matching keywords,  // or pairs of x keywords or pairs of y keywords.  if ((mask == 0) || (mask == (BG_TOP | BG_BOTTOM)) ||      (mask == (BG_LEFT | BG_RIGHT))) {    return PR_FALSE;  }  // Map good input  PRInt32 xEnumValue = 50;  if ((mask & (BG_LEFT | BG_RIGHT)) != 0) {    // We have an x value    xEnumValue = ((mask & BG_LEFT) != 0) ? 0 : 100;  }  PRInt32 yEnumValue = 50;  if ((mask & (BG_TOP | BG_BOTTOM)) != 0) {    // We have a y value    yEnumValue = ((mask & BG_TOP) != 0) ? 0 : 100;  }  if (ExpectEndProperty(aErrorCode, PR_TRUE)) {    // Create style values    AppendValue(aDeclaration, eCSSProperty_background_x_position, nsCSSValue(xEnumValue, eCSSUnit_Enumerated), aChangeHint);    AppendValue(aDeclaration, eCSSProperty_background_y_position, nsCSSValue(yEnumValue, eCSSUnit_Enumerated), aChangeHint);    return PR_TRUE;  }  return PR_FALSE;}// These must be in CSS order (top,right,bottom,left) for indexing to workstatic const nsCSSProperty kBorderStyleIDs[] = {  eCSSProperty_border_top_style,  eCSSProperty_border_right_style,  eCSSProperty_border_bottom_style,  eCSSProperty_border_left_style};static const nsCSSProperty kBorderWidthIDs[] = {  eCSSProperty_border_top_width,  eCSSProperty_border_right_width,  eCSSProperty_border_bottom_width,  eCSSProperty_border_left_width};static const nsCSSProperty kBorderColorIDs[] = {  eCSSProperty_border_top_color,  eCSSProperty_border_right_color,  eCSSProperty_border_bottom_color,  eCSSProperty_border_left_color};static const nsCSSProperty kBorderRadiusIDs[] = {  eCSSProperty__moz_border_radius_topLeft,  eCSSProperty__moz_border_radius_topRight,  eCSSProperty__moz_border_radius_bottomRight,  eCSSProperty__moz_border_radius_bottomLeft};static const nsCSSProperty kOutlineRadiusIDs[] = {  eCSSProperty__moz_outline_radius_topLeft,  eCSSProperty__moz_outline_radius_topRight,  eCSSProperty__moz_outline_radius_bottomRight,  eCSSProperty__moz_outline_radius_bottomLeft};PRBool CSSParserImpl::ParseBorder(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                  PRInt32& aChangeHint){  const PRInt32 numProps = 3;  static const nsCSSProperty kBorderIDs[] = {    eCSSProperty_border_top_width,  // only one value per property    eCSSProperty_border_top_style,    eCSSProperty_border_top_color  };  nsCSSValue  values[numProps];  PRInt32 found = ParseChoice(aErrorCode, values, kBorderIDs, numProps);  if ((found < 1) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  if (0 == (found & 1)) { // provide missing border width's    values[0].SetIntValue(NS_STYLE_BORDER_WIDTH_MEDIUM, eCSSUnit_Enumerated);  }    if (0 == (found & 2)) { // provide missing border style's    values[1].SetNoneValue();  }  if (0 == (found & 4)) { // text color will be used    values[2].SetIntValue(NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, eCSSUnit_Enumerated);  }  PRInt32 index;  for (index = 0; index < 4; index++) {    AppendValue(aDeclaration, kBorderWidthIDs[index], values[0], aChangeHint);    AppendValue(aDeclaration, kBorderStyleIDs[index], values[1], aChangeHint);    AppendValue(aDeclaration, kBorderColorIDs[index], values[2], aChangeHint);  }  return PR_TRUE;}PRBool CSSParserImpl::ParseBorderColor(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                        PRInt32& aChangeHint){  return ParseBoxProperties(aErrorCode, aDeclaration, kBorderColorIDs, aChangeHint);}PRBool CSSParserImpl::ParseBorderSpacing(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                         PRInt32& aChangeHint){  nsCSSValue  xValue;  if (ParseVariant(aErrorCode, xValue, VARIANT_HL, nsnull)) {    if (xValue.IsLengthUnit()) {      // We have one length. Get the optional second length.      nsCSSValue yValue;      if (ParseVariant(aErrorCode, yValue, VARIANT_LENGTH, nsnull)) {        // We have two numbers        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          AppendValue(aDeclaration, eCSSProperty_border_x_spacing, xValue, aChangeHint);          AppendValue(aDeclaration, eCSSProperty_border_y_spacing, yValue, aChangeHint);          return PR_TRUE;        }        return PR_FALSE;      }    }    // We have one length which is the horizontal spacing. Create a value for    // the vertical spacing which is equal    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_border_x_spacing, xValue, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_border_y_spacing, xValue, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseBorderSide(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                      const nsCSSProperty aPropIDs[], PRInt32& aChangeHint){  const PRInt32 numProps = 3;  nsCSSValue  values[numProps];  PRInt32 found = ParseChoice(aErrorCode, values, aPropIDs, numProps);  if ((found < 1) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  if ((found & 1) == 0) { // Provide default border-width    values[0].SetIntValue(NS_STYLE_BORDER_WIDTH_MEDIUM, eCSSUnit_Enumerated);  }  if ((found & 2) == 0) { // Provide default border-style    values[1].SetNoneValue();  }  if ((found & 4) == 0) { // reset border-color so color property gets used    values[2].Reset();  }  PRInt32 index;  for (index = 0; index < numProps; index++) {    AppendValue(aDeclaration, aPropIDs[index], values[index], aChangeHint);  }  return PR_TRUE;}PRBool CSSParserImpl::ParseBorderStyle(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                        PRInt32& aChangeHint){  return ParseBoxProperties(aErrorCode, aDeclaration, kBorderStyleIDs, aChangeHint);}PRBool CSSParserImpl::ParseBorderWidth(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                        PRInt32& aChangeHint){  return ParseBoxProperties(aErrorCode, aDeclaration, kBorderWidthIDs, aChangeHint);}PRBool CSSParserImpl::ParseBorderRadius(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                        PRInt32& aChangeHint){  return ParseBoxProperties(aErrorCode, aDeclaration, kBorderRadiusIDs, aChangeHint);}#ifdef ENABLE_OUTLINEPRBool CSSParserImpl::ParseOutlineRadius(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                        PRInt32& aChangeHint){  return ParseBoxProperties(aErrorCode, aDeclaration, kOutlineRadiusIDs, aChangeHint);}#endifPRBool CSSParserImpl::ParseClip(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                PRInt32& aChangeHint){  static const nsCSSProperty kClipIDs[] = {    eCSSProperty_clip_top,    eCSSProperty_clip_right,    eCSSProperty_clip_bottom,    eCSSProperty_clip_left  };  if (! GetToken(aErrorCode, PR_TRUE)) {    return PR_FALSE;  }  PRInt32 index;  if ((eCSSToken_Ident == mToken.mType) &&       mToken.mIdent.EqualsIgnoreCase("auto")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      nsCSSValue valueAuto(eCSSUnit_Auto);      for (index = 0; index < 4; index++) {        AppendValue(aDeclaration, kClipIDs[index], valueAuto, aChangeHint);      }      return PR_TRUE;    }  } else if ((eCSSToken_Ident == mToken.mType) &&              mToken.mIdent.EqualsIgnoreCase("inherit")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      nsCSSValue  inherit(eCSSUnit_Inherit);      for (index = 0; index < 4; index++) {        AppendValue(aDeclaration, kClipIDs[index], inherit, aChangeHint);      }      return PR_TRUE;    }  }   else if ((eCSSToken_Ident == mToken.mType) &&              mToken.mIdent.EqualsIgnoreCase("-moz-initial")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      nsCSSValue  initial(eCSSUnit_Initial);      for (index = 0; index < 4; index++) {        AppendValue(aDeclaration, kClipIDs[index], initial, aChangeHint);      }      return PR_TRUE;    }  } else if ((eCSSToken_Function == mToken.mType) &&              mToken.mIdent.EqualsIgnoreCase("rect")) {    if (!ExpectSymbol(aErrorCode, '(', PR_TRUE)) {      return PR_FALSE;    }    nsCSSValue  values[4];    for (index = 0; index < 4; index++) {      if (! ParseVariant(aErrorCode, values[index], VARIANT_AL, nsnull)) {        return PR_FALSE;      }      if (3 != index) {        // skip optional commas between elements        ExpectSymbol(aErrorCode, ',', PR_TRUE);      }    }    if (!ExpectSymbol(aErrorCode, ')', PR_TRUE)) {      return PR_FALSE;    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      for (index = 0; index < 4; index++) {        AppendValue(aDeclaration, kClipIDs[index], values[index], aChangeHint);      }      return PR_TRUE;    }  } else {    UngetToken();  }  return PR_FALSE;}#define VARIANT_CONTENT (VARIANT_STRING | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR | \                         VARIANT_KEYWORD)PRBool CSSParserImpl::ParseContent(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                   PRInt32& aChangeHint){  nsCSSValue  value;  if (ParseVariant(aErrorCode, value, VARIANT_CONTENT | VARIANT_INHERIT,                    nsCSSProps::kContentKTable)) {    if (eCSSUnit_Inherit == value.GetUnit() || eCSSUnit_Initial == value.GetUnit()) {      if (ExpectEndProperty(aErrorCode, PR_TRUE)) {        AppendValue(aDeclaration, eCSSProperty_content, value, aChangeHint);        return PR_TRUE;      }      return PR_FALSE;    }    nsCSSValueList* listHead = new nsCSSValueList();    nsCSSValueList* list = listHead;    if (nsnull == list) {      aErrorCode = NS_ERROR_OUT_OF_MEMORY;      return PR_FALSE;    }    list->mValue = value;    while (nsnull != list) {      if (ExpectEndProperty(aErrorCode, PR_TRUE)) {        if (aChangeHint < nsCSSProps::kHintTable[eCSSProperty_content]) {          aChangeHint = nsCSSProps::kHintTable[eCSSProperty_content];        }        aErrorCode = aDeclaration->AppendStructValue(eCSSProperty_content, listHead);        return NS_SUCCEEDED(aErrorCode);      }      if (ParseVariant(aErrorCode, value, VARIANT_CONTENT, nsCSSProps::kContentKTable)) {        list->mNext = new nsCSSValueList();        list = list->mNext;        if (nsnull != list) {          list->mValue = value;        }        else {          aErrorCode = NS_ERROR_OUT_OF_MEMORY;        }      }      else {        break;      }    }    delete listHead;  }  return PR_FALSE;}PRBool CSSParserImpl::ParseCounterData(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                       nsCSSProperty aPropID, PRInt32& aChangeHint){  nsString* ident = NextIdent(aErrorCode);  if (nsnull == ident) {    return PR_FALSE;  }  if (ident->EqualsIgnoreCase("none")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, aPropID, nsCSSValue(eCSSUnit_None), aChangeHint);      return PR_TRUE;    }    return PR_FALSE;  }  else if (ident->EqualsIgnoreCase("inherit")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, aPropID, nsCSSValue(eCSSUnit_Inherit), aChangeHint);      return PR_TRUE;    }    return PR_FALSE;  }  else if (ident->EqualsIgnoreCase("-moz-initial")) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, aPropID, nsCSSValue(eCSSUnit_Initial), aChangeHint);      return PR_TRUE;    }    return PR_FALSE;  }  else {    nsCSSCounterData* dataHead = new nsCSSCounterData();    nsCSSCounterData* data = dataHead;    if (nsnull == data) {      aErrorCode = NS_ERROR_OUT_OF_MEMORY;      return PR_FALSE;    }    data->mCounter.SetStringValue(*ident, eCSSUnit_String);    while (nsnull != data) {      if (ExpectEndProperty(aErrorCode, PR_TRUE)) {        if (aChangeHint < nsCSSProps::kHintTable[aPropID]) {          aChangeHint = nsCSSProps::kHintTable[aPropID];        }        aErrorCode = aDeclaration->AppendStructValue(aPropID, dataHead);        return NS_SUCCEEDED(aErrorCode);      }      if (! GetToken(aErrorCode, PR_TRUE)) {        break;      }      if ((eCSSToken_Number == mToken.mType) && (mToken.mIntegerValid)) {        data->mValue.SetIntValue(mToken.mInteger, eCSSUnit_Integer);        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          if (aChangeHint < nsCSSProps::kHintTable[aPropID]) {            aChangeHint = nsCSSProps::kHintTable[aPropID];          }          aErrorCode = aDeclaration->AppendStructValue(aPropID, dataHead);          return NS_SUCCEEDED(aErrorCode);        }        if (! GetToken(aErrorCode, PR_TRUE)) {          break;        }      }      if (eCSSToken_Ident == mToken.mType) {        data->mNext = new nsCSSCounterData();        data = data->mNext;        if (nsnull != data) {          data->mCounter.SetStringValue(mToken.mIdent, eCSSUnit_String);        }        else {          aErrorCode = NS_ERROR_OUT_OF_MEMORY;        }      }      else {        break;      }    }    delete dataHead;  }  return PR_FALSE;}PRBool CSSParserImpl::ParseCue(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                PRInt32& aChangeHint){  nsCSSValue before;  if (ParseSingleValueProperty(aErrorCode, before, eCSSProperty_cue_before)) {    if (eCSSUnit_URL == before.GetUnit()) {      nsCSSValue after;      if (ParseSingleValueProperty(aErrorCode, after, eCSSProperty_cue_after)) {        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          AppendValue(aDeclaration, eCSSProperty_cue_before, before, aChangeHint);          AppendValue(aDeclaration, eCSSProperty_cue_after, after, aChangeHint);          return PR_TRUE;        }        return PR_FALSE;      }    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_cue_before, before, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_cue_after, before, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseCursor(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                   PRInt32& aChangeHint){  nsCSSValue  value;  if (ParseVariant(aErrorCode, value, VARIANT_AHUK, nsCSSProps::kCursorKTable)) {    if (eCSSUnit_URL == value.GetUnit()) {      nsCSSValueList* listHead = new nsCSSValueList();      nsCSSValueList* list = listHead;      if (nsnull == list) {        aErrorCode = NS_ERROR_OUT_OF_MEMORY;        return PR_FALSE;      }      list->mValue = value;      while (nsnull != list) {        if (eCSSUnit_URL != value.GetUnit()) {          if (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE)) {            return PR_FALSE;          }        }        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          if (aChangeHint < nsCSSProps::kHintTable[eCSSProperty_cursor]) {            aChangeHint = nsCSSProps::kHintTable[eCSSProperty_cursor];          }          aErrorCode = aDeclaration->AppendStructValue(eCSSProperty_cursor, listHead);          return NS_SUCCEEDED(aErrorCode);        }        if (ParseVariant(aErrorCode, value, VARIANT_AHUK, nsCSSProps::kCursorKTable)) {          list->mNext = new nsCSSValueList();          list = list->mNext;          if (nsnull != list) {            list->mValue = value;          }          else {            aErrorCode = NS_ERROR_OUT_OF_MEMORY;          }        }        else {          break;        }      }      delete listHead;      return PR_FALSE;    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_cursor, value, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseFont(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                 PRInt32& aChangeHint){  static const nsCSSProperty fontIDs[] = {    eCSSProperty_font_style,    eCSSProperty_font_variant,    eCSSProperty_font_weight  };  nsCSSValue  family;  if (ParseVariant(aErrorCode, family, VARIANT_HK, nsCSSProps::kFontKTable)) {    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      if (eCSSUnit_Inherit == family.GetUnit()) {        AppendValue(aDeclaration, eCSSProperty_font_family, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_style, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_variant, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_weight, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_size, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_line_height, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_stretch, family, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_size_adjust, family, aChangeHint);      }      else {        AppendValue(aDeclaration, eCSSProperty_font_family, family, aChangeHint);  // keyword value overrides everything else        nsCSSValue empty;        AppendValue(aDeclaration, eCSSProperty_font_style, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_variant, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_weight, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_size, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_line_height, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_stretch, empty, aChangeHint);        AppendValue(aDeclaration, eCSSProperty_font_size_adjust, empty, aChangeHint);      }      return PR_TRUE;    }    return PR_FALSE;  }  // Get optional font-style, font-variant and font-weight (in any order)  const PRInt32 numProps = 3;  nsCSSValue  values[numProps];  PRInt32 found = ParseChoice(aErrorCode, values, fontIDs, numProps);  if ((found < 0) || (eCSSUnit_Inherit == values[0].GetUnit()) ||       (eCSSUnit_Initial == values[0].GetUnit())) { // illegal data    return PR_FALSE;  }  if ((found & 1) == 0) {    // Provide default font-style    values[0].SetNormalValue();  }  if ((found & 2) == 0) {    // Provide default font-variant    values[1].SetNormalValue();  }  if ((found & 4) == 0) {    // Provide default font-weight    values[2].SetNormalValue();  }  // Get mandatory font-size  nsCSSValue  size;  if (! ParseVariant(aErrorCode, size, VARIANT_KEYWORD | VARIANT_LP, nsCSSProps::kFontSizeKTable)) {    return PR_FALSE;  }  // Get optional "/" line-height  nsCSSValue  lineHeight;  if (ExpectSymbol(aErrorCode, '/', PR_TRUE)) {    if (! ParseVariant(aErrorCode, lineHeight, VARIANT_NUMBER | VARIANT_LP | VARIANT_NORMAL, nsnull)) {      return PR_FALSE;    }  }  else {    lineHeight.SetNormalValue();  }  // Get final mandatory font-family  if (ParseFamily(aErrorCode, family)) {    if ((eCSSUnit_Inherit != family.GetUnit()) && (eCSSUnit_Initial != family.GetUnit()) &&        ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_font_family, family, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_style, values[0], aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_variant, values[1], aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_weight, values[2], aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_size, size, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_line_height, lineHeight, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_stretch, nsCSSValue(eCSSUnit_Normal), aChangeHint);      AppendValue(aDeclaration, eCSSProperty_font_size_adjust, nsCSSValue(eCSSUnit_None), aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseFontWeight(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ParseVariant(aErrorCode, aValue, VARIANT_HMKI, nsCSSProps::kFontWeightKTable)) {    if (eCSSUnit_Integer == aValue.GetUnit()) { // ensure unit value      PRInt32 intValue = aValue.GetIntValue();      return ((100 <= intValue) && (intValue <= 900) &&              (0 == (intValue % 100)));    }    return PR_TRUE;  }  return PR_FALSE;}PRBool CSSParserImpl::ParseFamily(PRInt32& aErrorCode, nsCSSValue& aValue){  nsCSSToken* tk = &mToken;  nsAutoString family;  PRBool firstOne = PR_TRUE;  for (;;) {    if (!GetToken(aErrorCode, PR_TRUE)) {      break;    }    if (eCSSToken_Ident == tk->mType) {      if (firstOne) {        if (tk->mIdent.EqualsIgnoreCase("inherit")) {          aValue.SetInheritValue();          return PR_TRUE;        }        else if (tk->mIdent.EqualsIgnoreCase("initial")) {          aValue.SetInitialValue();          return PR_TRUE;        }      }      else {        family.Append(PRUnichar(','));      }      family.Append(tk->mIdent);      for (;;) {        if (!GetToken(aErrorCode, PR_FALSE)) {          break;        }        if (eCSSToken_Ident == tk->mType) {          family.Append(tk->mIdent);        } else if (eCSSToken_WhiteSpace == tk->mType) {          // Lookahead one token and drop whitespace if we ending the          // font name.          if (!GetToken(aErrorCode, PR_TRUE)) {            break;          }          if (eCSSToken_Ident != tk->mType) {            UngetToken();            break;          }          UngetToken();          family.Append(PRUnichar(' '));        } else {          UngetToken();          break;        }      }      firstOne = PR_FALSE;    } else if (eCSSToken_String == tk->mType) {      if (!firstOne) {        family.Append(PRUnichar(','));      }      family.Append(tk->mSymbol); // replace the quotes      family.Append(tk->mIdent);      family.Append(tk->mSymbol);      firstOne = PR_FALSE;    } else if (eCSSToken_Symbol == tk->mType) {      if (',' != tk->mSymbol) {        UngetToken();        break;      }    } else {      UngetToken();      break;    }  }  if (family.Length() == 0) {    return PR_FALSE;  }  aValue.SetStringValue(family, eCSSUnit_String);  return PR_TRUE;}PRBool CSSParserImpl::ParseListStyle(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                      PRInt32& aChangeHint){  const PRInt32 numProps = 3;  static const nsCSSProperty listStyleIDs[] = {    eCSSProperty_list_style_type,    eCSSProperty_list_style_position,    eCSSProperty_list_style_image  };  nsCSSValue  values[numProps];  PRInt32 index;  PRInt32 found = ParseChoice(aErrorCode, values, listStyleIDs, numProps);  if ((found < 1) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  // Provide default values  if ((found & 1) == 0) {    values[0].SetIntValue(NS_STYLE_LIST_STYLE_DISC, eCSSUnit_Enumerated);  }  if ((found & 2) == 0) {    values[1].SetIntValue(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE, eCSSUnit_Enumerated);  }  if ((found & 4) == 0) {    values[2].SetNoneValue();  }  for (index = 0; index < numProps; index++) {    AppendValue(aDeclaration, listStyleIDs[index], values[index], aChangeHint);  }  return PR_TRUE;}PRBool CSSParserImpl::ParseMargin(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                   PRInt32& aChangeHint){  static const nsCSSProperty kMarginSideIDs[] = {    eCSSProperty_margin_top,    eCSSProperty_margin_right,    eCSSProperty_margin_bottom,    eCSSProperty_margin_left  };  return ParseBoxProperties(aErrorCode, aDeclaration, kMarginSideIDs, aChangeHint);}PRBool CSSParserImpl::ParseMarks(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ParseVariant(aErrorCode, aValue, VARIANT_HOK, nsCSSProps::kPageMarksKTable)) {    if (eCSSUnit_Enumerated == aValue.GetUnit()) {      if (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE)) {        nsCSSValue  second;        if (ParseEnum(aErrorCode, second, nsCSSProps::kPageMarksKTable)) {          aValue.SetIntValue(aValue.GetIntValue() | second.GetIntValue(), eCSSUnit_Enumerated);          return PR_TRUE;        }        return PR_FALSE;      }    }    return PR_TRUE;  }  return PR_FALSE;}#ifdef ENABLE_OUTLINEPRBool CSSParserImpl::ParseOutline(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                    PRInt32& aChangeHint){  const PRInt32 numProps = 3;  static const nsCSSProperty kOutlineIDs[] = {    eCSSProperty_outline_color,    eCSSProperty_outline_style,    eCSSProperty_outline_width  };  nsCSSValue  values[numProps];  PRInt32 found = ParseChoice(aErrorCode, values, kOutlineIDs, numProps);  if ((found < 1) || (PR_FALSE == ExpectEndProperty(aErrorCode, PR_TRUE))) {    return PR_FALSE;  }  // Provide default values  if ((found & 1) == 0) {    values[0].SetIntValue(NS_STYLE_COLOR_INVERT, eCSSUnit_Enumerated);  }  if ((found & 2) == 0) {    values[1].SetNoneValue();  }  if ((found & 4) == 0) {    values[2].SetIntValue(NS_STYLE_BORDER_WIDTH_MEDIUM, eCSSUnit_Enumerated);  }  PRInt32 index;  for (index = 0; index < numProps; index++) {    AppendValue(aDeclaration, kOutlineIDs[index], values[index], aChangeHint);  }  return PR_TRUE;}#endifPRBool CSSParserImpl::ParsePadding(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                    PRInt32& aChangeHint){  static const nsCSSProperty kPaddingSideIDs[] = {    eCSSProperty_padding_top,    eCSSProperty_padding_right,    eCSSProperty_padding_bottom,    eCSSProperty_padding_left  };  return ParseBoxProperties(aErrorCode, aDeclaration, kPaddingSideIDs, aChangeHint);}PRBool CSSParserImpl::ParsePause(PRInt32& aErrorCode,                                 nsICSSDeclaration* aDeclaration, PRInt32& aChangeHint){  nsCSSValue  before;  if (ParseSingleValueProperty(aErrorCode, before, eCSSProperty_pause_before)) {    if (eCSSUnit_Inherit != before.GetUnit() && eCSSUnit_Initial != before.GetUnit()) {      nsCSSValue after;      if (ParseSingleValueProperty(aErrorCode, after, eCSSProperty_pause_after)) {        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          AppendValue(aDeclaration, eCSSProperty_pause_before, before, aChangeHint);          AppendValue(aDeclaration, eCSSProperty_pause_after, after, aChangeHint);          return PR_TRUE;        }        return PR_FALSE;      }    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_pause_before, before, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_pause_after, before, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParsePlayDuring(PRInt32& aErrorCode,                                      nsICSSDeclaration* aDeclaration,                                       PRInt32& aChangeHint){  nsCSSValue  playDuring;  nsCSSValue  flags;  if (ParseVariant(aErrorCode, playDuring, VARIANT_AHUO, nsnull)) {    if (eCSSUnit_URL == playDuring.GetUnit()) {      if (ParseEnum(aErrorCode, flags, nsCSSProps::kPlayDuringKTable)) {        PRInt32 intValue = flags.GetIntValue();        if (ParseEnum(aErrorCode, flags, nsCSSProps::kPlayDuringKTable)) {          flags.SetIntValue(intValue | flags.GetIntValue(), eCSSUnit_Enumerated);        }      }    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_play_during, playDuring, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_play_during_flags, flags, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseQuotes(PRInt32& aErrorCode,                                  nsICSSDeclaration* aDeclaration,                                   PRInt32 &aChangeHint){  nsCSSValue  open;  if (ParseVariant(aErrorCode, open, VARIANT_HOS, nsnull)) {    if (eCSSUnit_String == open.GetUnit()) {      nsCSSQuotes* quotesHead = new nsCSSQuotes();      nsCSSQuotes* quotes = quotesHead;      if (nsnull == quotes) {        aErrorCode = NS_ERROR_OUT_OF_MEMORY;        return PR_FALSE;      }      quotes->mOpen = open;      while (nsnull != quotes) {        // get mandatory close        if (ParseVariant(aErrorCode, quotes->mClose, VARIANT_STRING, nsnull)) {          if (ExpectEndProperty(aErrorCode, PR_TRUE)) {            if (aChangeHint < nsCSSProps::kHintTable[eCSSProperty_quotes]) {              aChangeHint = nsCSSProps::kHintTable[eCSSProperty_quotes];            }            aErrorCode = aDeclaration->AppendStructValue(eCSSProperty_quotes, quotesHead);            return NS_SUCCEEDED(aErrorCode);          }          // look for another open          if (ParseVariant(aErrorCode, open, VARIANT_STRING, nsnull)) {            quotes->mNext = new nsCSSQuotes();            quotes = quotes->mNext;            if (nsnull != quotes) {              quotes->mOpen = open;              continue;            }            aErrorCode = NS_ERROR_OUT_OF_MEMORY;          }        }        break;      }      delete quotesHead;      return PR_FALSE;    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_quotes_open, open, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseSize(PRInt32& aErrorCode, nsICSSDeclaration* aDeclaration,                                 PRInt32& aChangeHint){  nsCSSValue width;  if (ParseVariant(aErrorCode, width, VARIANT_AHKL, nsCSSProps::kPageSizeKTable)) {    if (width.IsLengthUnit()) {      nsCSSValue  height;      if (ParseVariant(aErrorCode, height, VARIANT_LENGTH, nsnull)) {        if (ExpectEndProperty(aErrorCode, PR_TRUE)) {          AppendValue(aDeclaration, eCSSProperty_size_width, width, aChangeHint);          AppendValue(aDeclaration, eCSSProperty_size_height, height, aChangeHint);          return PR_TRUE;        }        return PR_FALSE;      }    }    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_size_width, width, aChangeHint);      AppendValue(aDeclaration, eCSSProperty_size_height, width, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}PRBool CSSParserImpl::ParseTextDecoration(PRInt32& aErrorCode, nsCSSValue& aValue){  if (ParseVariant(aErrorCode, aValue, VARIANT_HOK, nsCSSProps::kTextDecorationKTable)) {    if (eCSSUnit_Enumerated == aValue.GetUnit()) {  // look for more keywords      PRInt32 intValue = aValue.GetIntValue();      nsCSSValue  keyword;      PRInt32 index;      for (index = 0; index < 3; index++) {        if (ParseEnum(aErrorCode, keyword, nsCSSProps::kTextDecorationKTable)) {          intValue |= keyword.GetIntValue();        }        else {          break;        }      }      aValue.SetIntValue(intValue, eCSSUnit_Enumerated);    }    return PR_TRUE;  }  return PR_FALSE;}PRBool CSSParserImpl::ParseTextShadow(PRInt32& aErrorCode,                                      nsICSSDeclaration* aDeclaration,                                       PRInt32& aChangeHint){  nsCSSValue  value;  if (ParseVariant(aErrorCode, value, VARIANT_HC | VARIANT_LENGTH | VARIANT_NONE, nsnull)) {    nsCSSUnit unit = value.GetUnit();    if ((eCSSUnit_Color == unit) || (eCSSUnit_String == unit) || value.IsLengthUnit()) {      nsCSSShadow*  shadowHead = new nsCSSShadow();      nsCSSShadow*  shadow = shadowHead;      if (nsnull == shadow) {        aErrorCode = NS_ERROR_OUT_OF_MEMORY;        return PR_FALSE;      }      while (nsnull != shadow) {        PRBool  haveColor = PR_FALSE;        if (value.IsLengthUnit()) {          shadow->mXOffset = value;        }        else {          haveColor = PR_TRUE;          shadow->mColor = value;          if (ParseVariant(aErrorCode, value, VARIANT_LENGTH, nsnull)) {            shadow->mXOffset = value;          }          else {            break;          }        }        if (ParseVariant(aErrorCode, value, VARIANT_LENGTH, nsnull)) {          shadow->mYOffset = value;        }        else {          break;        }        if (ParseVariant(aErrorCode, value, VARIANT_LENGTH, nsnull)) {          shadow->mRadius = value;        } // optional        if (PR_FALSE == haveColor) {          if (ParseVariant(aErrorCode, value, VARIANT_COLOR, nsnull)) {            shadow->mColor = value;          }        }        if (ExpectSymbol(aErrorCode, ',', PR_TRUE)) {          shadow->mNext = new nsCSSShadow();          shadow = shadow->mNext;          if (nsnull == shadow) {            aErrorCode = NS_ERROR_OUT_OF_MEMORY;            break;          }          if (PR_FALSE == ParseVariant(aErrorCode, value, VARIANT_COLOR | VARIANT_LENGTH, nsnull)) {            break;          }        }        else {          if (ExpectEndProperty(aErrorCode, PR_TRUE)) {            if (aChangeHint < nsCSSProps::kHintTable[eCSSProperty_text_shadow]) {              aChangeHint = nsCSSProps::kHintTable[eCSSProperty_text_shadow];            }            aErrorCode = aDeclaration->AppendStructValue(eCSSProperty_text_shadow, shadowHead);            return NS_SUCCEEDED(aErrorCode);          }          break;        }      }      delete shadowHead;      return PR_FALSE;    }    // value is inherit or none    if (ExpectEndProperty(aErrorCode, PR_TRUE)) {      AppendValue(aDeclaration, eCSSProperty_text_shadow_x, value, aChangeHint);      return PR_TRUE;    }  }  return PR_FALSE;}NS_IMETHODIMP CSSParserImpl::GetCharset(/*out*/nsAWritableString &aCharsetDest) const{   aCharsetDest = mCharset;   return NS_OK;}NS_IMETHODIMP CSSParserImpl::SetCharset(/*in*/ const nsAReadableString &aCharsetSrc){  mCharset = aCharsetSrc;  return NS_OK;}