internal void AppendQuery(CssMediaQuery query) { mArray.Add(query); }
internal bool ParseMediaQueryExpression(nsMediaQuery aQuery) { if (!ExpectSymbol('(', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpectedExpressionStart", mToken); }; return false; } if (! GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpressionEOF"); }; return false; } if (nsCSSTokenType.Ident != mToken.mType) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpectedFeatureName", mToken); }; UngetToken(); SkipUntil(')'); return false; } nsMediaExpression expr = aQuery.NewExpression(); // case insensitive from CSS - must be lower cased mToken.mIdentStr = mToken.mIdentStr.ToLower(); string featureString; if (StringBeginsWith(mToken.mIdentStr, "min-")) { expr.mRange = nsMediaExpression.RangeType.Min; featureString = mToken.mIdentStr.Substring(4); } else if (StringBeginsWith(mToken.mIdentStr, "max-")) { expr.mRange = nsMediaExpression.RangeType.Max; featureString = mToken.mIdentStr.Substring(4); } else { expr.mRange = nsMediaExpression.RangeType.Equal; featureString = mToken.mIdentStr; } string mediaFeatureAtom = String.Intern(featureString); if (mediaFeatureAtom == null) { Debug.Fail("String.Intern failed - out of memory?"); } nsMediaFeature feature = nsMediaFeatures.GetFeature(mediaFeatureAtom); if (feature.mName == null || (expr.mRange != nsMediaExpression.RangeType.Equal && feature.mRangeType != nsMediaFeature.RangeType.MinMaxAllowed)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpectedFeatureName", mToken); }; SkipUntil(')'); return false; } expr.mFeature = feature; if (!GetToken(true) || mToken.IsSymbol(')')) { // Query expressions for any feature can be given without a value. // However, min/max prefixes are not allowed. if (expr.mRange != nsMediaExpression.RangeType.Equal) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQNoMinMaxWithoutValue"); }; return false; } expr.mValue.Reset(); return true; } if (!mToken.IsSymbol(':')) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpectedFeatureNameEnd", mToken); }; UngetToken(); SkipUntil(')'); return false; } bool rv = false; switch (feature.mValueType) { case nsMediaFeature.ValueType.Length: rv = ParseNonNegativeVariant(ref expr.mValue, VARIANT_LENGTH, null); break; case nsMediaFeature.ValueType.Integer: case nsMediaFeature.ValueType.BoolInteger: rv = ParseNonNegativeVariant(ref expr.mValue, VARIANT_INTEGER, null); // Enforce extra restrictions for eBoolInteger if (rv && feature.mValueType == nsMediaFeature.ValueType.BoolInteger && expr.mValue.GetIntValue() > 1) rv = false; break; case nsMediaFeature.ValueType.Float: rv = ParseNonNegativeVariant(ref expr.mValue, VARIANT_NUMBER, null); break; case nsMediaFeature.ValueType.IntRatio: { // Two integers separated by '/', with optional whitespace on // either side of the '/'. nsCSSValue[] a = new nsCSSValue[2]; expr.mValue.SetArrayValue(a, nsCSSUnit.Array); // We don't bother with ParseNonNegativeVariant since we have to // check for != 0 as well; no need to worry about the UngetToken // since we're throwing out up to the next ')' anyway. rv = ParseVariant(ref a[0], VARIANT_INTEGER, null) && a[0].GetIntValue() > 0 && ExpectSymbol('/', true) && ParseVariant(ref a[1], VARIANT_INTEGER, null) && a[1].GetIntValue() > 0; } break; case nsMediaFeature.ValueType.Resolution: rv = GetToken(true); if (!rv) break; rv = mToken.mType == nsCSSTokenType.Dimension && mToken.mNumber > 0.0f; if (!rv) { UngetToken(); break; } // No worries about whether unitless zero is allowed, since the // value must be positive (and we checked that above). Debug.Assert(!mToken.mIdentStr.IsEmpty(), "unit lied"); if (mToken.mIdentStr.LowerCaseEqualsLiteral("dpi")) { expr.mValue.SetFloatValue(mToken.mNumber, nsCSSUnit.Inch); } else if (mToken.mIdentStr.LowerCaseEqualsLiteral("dppx")) { expr.mValue.SetFloatValue(mToken.mNumber, nsCSSUnit.Pixel); } else if (mToken.mIdentStr.LowerCaseEqualsLiteral("dpcm")) { expr.mValue.SetFloatValue(mToken.mNumber, nsCSSUnit.Centimeter); } else { rv = false; } break; case nsMediaFeature.ValueType.Enumerated: rv = ParseVariant(ref expr.mValue, VARIANT_KEYWORD, feature.mData.mKeywordTable); break; case nsMediaFeature.ValueType.Ident: rv = ParseVariant(ref expr.mValue, VARIANT_IDENTIFIER, null); break; } if (!rv || !ExpectSymbol(')', true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEMQExpectedFeatureValue"); }; SkipUntil(')'); return false; } return true; }
internal bool ParseMediaQuery(bool aInAtRule, ref nsMediaQuery aQuery, ref bool aHitStop) { aQuery = null; aHitStop = false; // "If the comma-separated list is the empty list it is assumed to // specify the media query 'all'." (css3-mediaqueries, section // "Media Queries") if (!GetToken(true)) { aHitStop = true; // expected termination by EOF if (!aInAtRule) return true; // unexpected termination by EOF { if (!mSuppressErrors) mReporter.ReportUnexpected("PEGatherMediaEOF"); }; return true; } if (nsCSSTokenType.Symbol == mToken.mType && aInAtRule && (mToken.mSymbol == ';' || mToken.mSymbol == '{' || mToken.mSymbol == '}' )) { aHitStop = true; UngetToken(); return true; } UngetToken(); nsMediaQuery query = new nsMediaQuery(); aQuery = query; if (ExpectSymbol('(', true)) { // we got an expression without a media type UngetToken(); // so ParseMediaQueryExpression can handle it query.SetType(nsGkAtoms.all); query.SetTypeOmitted(); // Just parse the first expression here. if (!ParseMediaQueryExpression(query)) { mReporter.OutputError(); query.SetHadUnknownExpression(); } } else { string mediaType; bool gotNotOrOnly = false; for (;;) { if (!GetToken(true)) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEGatherMediaEOF"); }; return false; } if (nsCSSTokenType.Ident != mToken.mType) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEGatherMediaNotIdent", mToken); }; UngetToken(); return false; } // case insensitive from CSS - must be lower cased mToken.mIdentStr = mToken.mIdentStr.ToLower(); mediaType = String.Intern(mToken.mIdentStr); if (mediaType == null) { Debug.Fail("String.Intern failed - out of memory?"); } if (gotNotOrOnly || (mediaType != nsGkAtoms._not && mediaType != nsGkAtoms.only)) break; gotNotOrOnly = true; if (mediaType == nsGkAtoms._not) query.SetNegated(); else query.SetHasOnly(); } query.SetType(mediaType); } for (;;) { if (!GetToken(true)) { aHitStop = true; // expected termination by EOF if (!aInAtRule) break; // unexpected termination by EOF { if (!mSuppressErrors) mReporter.ReportUnexpected("PEGatherMediaEOF"); }; break; } if (nsCSSTokenType.Symbol == mToken.mType && aInAtRule && (mToken.mSymbol == ';' || mToken.mSymbol == '{' || mToken.mSymbol == '}')) { aHitStop = true; UngetToken(); break; } if (nsCSSTokenType.Symbol == mToken.mType && mToken.mSymbol == ',') { // Done with the expressions for this query break; } if (nsCSSTokenType.Ident != mToken.mType || !mToken.mIdentStr.LowerCaseEqualsLiteral("and")) { { if (!mSuppressErrors) mReporter.ReportUnexpected("PEGatherMediaNotComma", mToken); }; UngetToken(); return false; } if (!ParseMediaQueryExpression(query)) { mReporter.OutputError(); query.SetHadUnknownExpression(); } } return true; }