From 0c17ea7bbc2dfcbcab021103dc8cc78af3d647cb Mon Sep 17 00:00:00 2001 From: "glazman%netscape.com" Date: Sat, 3 Mar 2001 00:54:04 +0000 Subject: [PATCH] enhancement for the 3 new attributes selectors in CSS 3. r=dbaron, sr=attinasi git-svn-id: svn://10.0.0.236/trunk@88435 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/html/style/src/nsCSSParser.cpp | 14 ++++++++++- .../content/html/style/src/nsCSSScanner.cpp | 20 ++++++++++++++-- mozilla/content/html/style/src/nsCSSScanner.h | 6 ++++- .../content/html/style/src/nsCSSStyleRule.cpp | 9 ++++++++ .../html/style/src/nsCSSStyleSheet.cpp | 23 ++++++++++++++++++- .../content/html/style/src/nsICSSStyleRule.h | 3 +++ mozilla/layout/style/nsCSSParser.cpp | 14 ++++++++++- mozilla/layout/style/nsCSSScanner.cpp | 20 ++++++++++++++-- mozilla/layout/style/nsCSSScanner.h | 6 ++++- mozilla/layout/style/nsCSSStyleRule.cpp | 9 ++++++++ mozilla/layout/style/nsCSSStyleSheet.cpp | 23 ++++++++++++++++++- mozilla/layout/style/nsICSSStyleRule.h | 3 +++ 12 files changed, 140 insertions(+), 10 deletions(-) diff --git a/mozilla/content/html/style/src/nsCSSParser.cpp b/mozilla/content/html/style/src/nsCSSParser.cpp index 399fdee4115..1f78dc087de 100644 --- a/mozilla/content/html/style/src/nsCSSParser.cpp +++ b/mozilla/content/html/style/src/nsCSSParser.cpp @@ -1855,7 +1855,10 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, } if ((eCSSToken_Symbol == mToken.mType) || (eCSSToken_Includes == mToken.mType) || - (eCSSToken_Dashmatch == mToken.mType)) { + (eCSSToken_Dashmatch == mToken.mType) || + (eCSSToken_Beginsmatch == mToken.mType) || + (eCSSToken_Endsmatch == mToken.mType) || + (eCSSToken_Containsmatch == mToken.mType)) { mToken.AppendToString(aSource); PRUint8 func; if (eCSSToken_Includes == mToken.mType) { @@ -1864,6 +1867,15 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, else if (eCSSToken_Dashmatch == mToken.mType) { func = NS_ATTR_FUNC_DASHMATCH; } + else if (eCSSToken_Beginsmatch == mToken.mType) { + func = NS_ATTR_FUNC_BEGINSMATCH; + } + else if (eCSSToken_Endsmatch == mToken.mType) { + func = NS_ATTR_FUNC_ENDSMATCH; + } + else if (eCSSToken_Containsmatch == mToken.mType) { + func = NS_ATTR_FUNC_CONTAINSMATCH; + } else if (']' == mToken.mSymbol) { dataMask |= SEL_MASK_ATTRIB; aSelector.AddAttribute(nameSpaceID, attr); diff --git a/mozilla/content/html/style/src/nsCSSScanner.cpp b/mozilla/content/html/style/src/nsCSSScanner.cpp index a6130965379..db2cd4d7166 100644 --- a/mozilla/content/html/style/src/nsCSSScanner.cpp +++ b/mozilla/content/html/style/src/nsCSSScanner.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Daniel Glazman */ #include "nsCSSScanner.h" #include "nsIInputStream.h" @@ -501,10 +502,25 @@ PRBool nsCSSScanner::Next(PRInt32& aErrorCode, nsCSSToken& aToken) } // INCLUDES ("~=") and DASHMATCH ("|=") - if (( ch == '|' ) || ( ch == '~')) { + if (( ch == '|' ) || ( ch == '~' ) || ( ch == '^' ) || + ( ch == '$' ) || ( ch == '*' )) { PRInt32 nextChar = Read(aErrorCode); if ( nextChar == '=' ) { - aToken.mType = (ch == '~') ? eCSSToken_Includes : eCSSToken_Dashmatch; + if (ch == '~') { + aToken.mType = eCSSToken_Includes; + } + else if (ch == '|') { + aToken.mType = eCSSToken_Dashmatch; + } + else if (ch == '^') { + aToken.mType = eCSSToken_Beginsmatch; + } + else if (ch == '$') { + aToken.mType = eCSSToken_Endsmatch; + } + else if (ch == '*') { + aToken.mType = eCSSToken_Containsmatch; + } return PR_TRUE; } else { Pushback(nextChar); diff --git a/mozilla/content/html/style/src/nsCSSScanner.h b/mozilla/content/html/style/src/nsCSSScanner.h index 30af7d91403..bf5df043203 100644 --- a/mozilla/content/html/style/src/nsCSSScanner.h +++ b/mozilla/content/html/style/src/nsCSSScanner.h @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Daniel Glazman */ #ifndef nsCSSScanner_h___ #define nsCSSScanner_h___ @@ -67,7 +68,10 @@ enum nsCSSTokenType { eCSSToken_HTMLComment = 12, // "" eCSSToken_Includes = 13, // "~=" - eCSSToken_Dashmatch = 14 // "|=" + eCSSToken_Dashmatch = 14, // "|=" + eCSSToken_Beginsmatch = 15, // "^=" + eCSSToken_Endsmatch = 16, // "$=" + eCSSToken_Containsmatch = 17 // "*=" }; diff --git a/mozilla/content/html/style/src/nsCSSStyleRule.cpp b/mozilla/content/html/style/src/nsCSSStyleRule.cpp index 468dac7cbdc..c629319d87f 100644 --- a/mozilla/content/html/style/src/nsCSSStyleRule.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleRule.cpp @@ -732,6 +732,15 @@ nsresult nsCSSSelector::ToString( nsAWritableString& aString, nsICSSStyleSheet* } else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH) { aString.Append(PRUnichar('|')); aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH) { + aString.Append(PRUnichar('^')); + aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH) { + aString.Append(PRUnichar('$')); + aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH) { + aString.Append(PRUnichar('*')); + aString.Append(PRUnichar('=')); } // Append the value aString.Append(list->mValue); diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index 74d84555303..0835332b0fe 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -2951,7 +2951,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, } else { nsAttrSelector* attr = aSelector->mAttrList; do { - nsAutoString value; + nsAutoString value, partValue; nsresult attrState = data.mContent->GetAttribute(attr->mNameSpace, attr->mAttr, value); if (NS_FAILED(attrState) || (NS_CONTENT_ATTR_NOT_THERE == attrState)) { result = PR_FALSE; @@ -2974,6 +2974,27 @@ static PRBool SelectorMatches(SelectorMatchesData &data, case NS_ATTR_FUNC_DASHMATCH: result = ValueDashMatch(value, attr->mValue, isCaseSensitive); break; + case NS_ATTR_FUNC_ENDSMATCH: + value.Right(partValue, attr->mValue.Length()); + if (isCaseSensitive) { + result = partValue.Equals(attr->mValue); + } + else { + result = partValue.EqualsIgnoreCase(attr->mValue); + } + break; + case NS_ATTR_FUNC_BEGINSMATCH: + value.Left(partValue, attr->mValue.Length()); + if (isCaseSensitive) { + result = partValue.Equals(attr->mValue); + } + else { + result = partValue.EqualsIgnoreCase(attr->mValue); + } + break; + case NS_ATTR_FUNC_CONTAINSMATCH: + result = (-1 != value.Find(attr->mValue, isCaseSensitive)); + break; } } attr = attr->mNext; diff --git a/mozilla/content/html/style/src/nsICSSStyleRule.h b/mozilla/content/html/style/src/nsICSSStyleRule.h index 0bae18801e6..6fb1b739bfc 100644 --- a/mozilla/content/html/style/src/nsICSSStyleRule.h +++ b/mozilla/content/html/style/src/nsICSSStyleRule.h @@ -51,6 +51,9 @@ public: #define NS_ATTR_FUNC_EQUALS 1 // [attr=value] #define NS_ATTR_FUNC_INCLUDES 2 // [attr~=value] (space separated) #define NS_ATTR_FUNC_DASHMATCH 3 // [attr|=value] ('-' truncated) +#define NS_ATTR_FUNC_BEGINSMATCH 4 // [attr^=value] (begins with) +#define NS_ATTR_FUNC_ENDSMATCH 5 // [attr$=value] (ends with) +#define NS_ATTR_FUNC_CONTAINSMATCH 6 // [attr*=value] (contains substring) struct nsAttrSelector { public: diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 399fdee4115..1f78dc087de 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -1855,7 +1855,10 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, } if ((eCSSToken_Symbol == mToken.mType) || (eCSSToken_Includes == mToken.mType) || - (eCSSToken_Dashmatch == mToken.mType)) { + (eCSSToken_Dashmatch == mToken.mType) || + (eCSSToken_Beginsmatch == mToken.mType) || + (eCSSToken_Endsmatch == mToken.mType) || + (eCSSToken_Containsmatch == mToken.mType)) { mToken.AppendToString(aSource); PRUint8 func; if (eCSSToken_Includes == mToken.mType) { @@ -1864,6 +1867,15 @@ PRBool CSSParserImpl::ParseSelector(PRInt32& aErrorCode, else if (eCSSToken_Dashmatch == mToken.mType) { func = NS_ATTR_FUNC_DASHMATCH; } + else if (eCSSToken_Beginsmatch == mToken.mType) { + func = NS_ATTR_FUNC_BEGINSMATCH; + } + else if (eCSSToken_Endsmatch == mToken.mType) { + func = NS_ATTR_FUNC_ENDSMATCH; + } + else if (eCSSToken_Containsmatch == mToken.mType) { + func = NS_ATTR_FUNC_CONTAINSMATCH; + } else if (']' == mToken.mSymbol) { dataMask |= SEL_MASK_ATTRIB; aSelector.AddAttribute(nameSpaceID, attr); diff --git a/mozilla/layout/style/nsCSSScanner.cpp b/mozilla/layout/style/nsCSSScanner.cpp index a6130965379..db2cd4d7166 100644 --- a/mozilla/layout/style/nsCSSScanner.cpp +++ b/mozilla/layout/style/nsCSSScanner.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Daniel Glazman */ #include "nsCSSScanner.h" #include "nsIInputStream.h" @@ -501,10 +502,25 @@ PRBool nsCSSScanner::Next(PRInt32& aErrorCode, nsCSSToken& aToken) } // INCLUDES ("~=") and DASHMATCH ("|=") - if (( ch == '|' ) || ( ch == '~')) { + if (( ch == '|' ) || ( ch == '~' ) || ( ch == '^' ) || + ( ch == '$' ) || ( ch == '*' )) { PRInt32 nextChar = Read(aErrorCode); if ( nextChar == '=' ) { - aToken.mType = (ch == '~') ? eCSSToken_Includes : eCSSToken_Dashmatch; + if (ch == '~') { + aToken.mType = eCSSToken_Includes; + } + else if (ch == '|') { + aToken.mType = eCSSToken_Dashmatch; + } + else if (ch == '^') { + aToken.mType = eCSSToken_Beginsmatch; + } + else if (ch == '$') { + aToken.mType = eCSSToken_Endsmatch; + } + else if (ch == '*') { + aToken.mType = eCSSToken_Containsmatch; + } return PR_TRUE; } else { Pushback(nextChar); diff --git a/mozilla/layout/style/nsCSSScanner.h b/mozilla/layout/style/nsCSSScanner.h index 30af7d91403..bf5df043203 100644 --- a/mozilla/layout/style/nsCSSScanner.h +++ b/mozilla/layout/style/nsCSSScanner.h @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Daniel Glazman */ #ifndef nsCSSScanner_h___ #define nsCSSScanner_h___ @@ -67,7 +68,10 @@ enum nsCSSTokenType { eCSSToken_HTMLComment = 12, // "" eCSSToken_Includes = 13, // "~=" - eCSSToken_Dashmatch = 14 // "|=" + eCSSToken_Dashmatch = 14, // "|=" + eCSSToken_Beginsmatch = 15, // "^=" + eCSSToken_Endsmatch = 16, // "$=" + eCSSToken_Containsmatch = 17 // "*=" }; diff --git a/mozilla/layout/style/nsCSSStyleRule.cpp b/mozilla/layout/style/nsCSSStyleRule.cpp index 468dac7cbdc..c629319d87f 100644 --- a/mozilla/layout/style/nsCSSStyleRule.cpp +++ b/mozilla/layout/style/nsCSSStyleRule.cpp @@ -732,6 +732,15 @@ nsresult nsCSSSelector::ToString( nsAWritableString& aString, nsICSSStyleSheet* } else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH) { aString.Append(PRUnichar('|')); aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH) { + aString.Append(PRUnichar('^')); + aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH) { + aString.Append(PRUnichar('$')); + aString.Append(PRUnichar('=')); + } else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH) { + aString.Append(PRUnichar('*')); + aString.Append(PRUnichar('=')); } // Append the value aString.Append(list->mValue); diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index 74d84555303..0835332b0fe 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -2951,7 +2951,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, } else { nsAttrSelector* attr = aSelector->mAttrList; do { - nsAutoString value; + nsAutoString value, partValue; nsresult attrState = data.mContent->GetAttribute(attr->mNameSpace, attr->mAttr, value); if (NS_FAILED(attrState) || (NS_CONTENT_ATTR_NOT_THERE == attrState)) { result = PR_FALSE; @@ -2974,6 +2974,27 @@ static PRBool SelectorMatches(SelectorMatchesData &data, case NS_ATTR_FUNC_DASHMATCH: result = ValueDashMatch(value, attr->mValue, isCaseSensitive); break; + case NS_ATTR_FUNC_ENDSMATCH: + value.Right(partValue, attr->mValue.Length()); + if (isCaseSensitive) { + result = partValue.Equals(attr->mValue); + } + else { + result = partValue.EqualsIgnoreCase(attr->mValue); + } + break; + case NS_ATTR_FUNC_BEGINSMATCH: + value.Left(partValue, attr->mValue.Length()); + if (isCaseSensitive) { + result = partValue.Equals(attr->mValue); + } + else { + result = partValue.EqualsIgnoreCase(attr->mValue); + } + break; + case NS_ATTR_FUNC_CONTAINSMATCH: + result = (-1 != value.Find(attr->mValue, isCaseSensitive)); + break; } } attr = attr->mNext; diff --git a/mozilla/layout/style/nsICSSStyleRule.h b/mozilla/layout/style/nsICSSStyleRule.h index 0bae18801e6..6fb1b739bfc 100644 --- a/mozilla/layout/style/nsICSSStyleRule.h +++ b/mozilla/layout/style/nsICSSStyleRule.h @@ -51,6 +51,9 @@ public: #define NS_ATTR_FUNC_EQUALS 1 // [attr=value] #define NS_ATTR_FUNC_INCLUDES 2 // [attr~=value] (space separated) #define NS_ATTR_FUNC_DASHMATCH 3 // [attr|=value] ('-' truncated) +#define NS_ATTR_FUNC_BEGINSMATCH 4 // [attr^=value] (begins with) +#define NS_ATTR_FUNC_ENDSMATCH 5 // [attr$=value] (ends with) +#define NS_ATTR_FUNC_CONTAINSMATCH 6 // [attr*=value] (contains substring) struct nsAttrSelector { public: