From 53dfaf64c74ad1c2cb1cf1cd2888bbe560506016 Mon Sep 17 00:00:00 2001 From: "pierre%netscape.com" Date: Fri, 7 Sep 2001 00:23:37 +0000 Subject: [PATCH] Bug 93371 (WRMB: Treat classes case insensitively in quirks mode). Back out ianh's patch in nsCSSParser.cpp and nsHTMLAttributes.cpp. Treat classes and IDs case insensitively as described in Bug 35522. r=glazman (+dbaron/jst) sr=hyatt git-svn-id: svn://10.0.0.236/trunk@102494 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/base/public/nsIStyledContent.h | 2 +- mozilla/content/base/src/nsGenericElement.cpp | 2 +- mozilla/content/base/src/nsGenericElement.h | 2 +- .../html/content/src/nsGenericHTMLElement.cpp | 4 +- .../html/content/src/nsGenericHTMLElement.h | 2 +- .../content/html/style/src/nsCSSParser.cpp | 10 +- .../html/style/src/nsCSSStyleSheet.cpp | 112 +++++++++++++++--- .../html/style/src/nsHTMLAttributes.cpp | 55 ++++----- .../html/style/src/nsIHTMLAttributes.h | 2 +- .../content/xul/content/src/nsXULElement.cpp | 2 +- .../content/xul/content/src/nsXULElement.h | 2 +- mozilla/layout/style/nsCSSParser.cpp | 10 +- mozilla/layout/style/nsCSSStyleSheet.cpp | 112 +++++++++++++++--- 13 files changed, 225 insertions(+), 92 deletions(-) diff --git a/mozilla/content/base/public/nsIStyledContent.h b/mozilla/content/base/public/nsIStyledContent.h index 9b87340260d..d4d7c01ca80 100644 --- a/mozilla/content/base/public/nsIStyledContent.h +++ b/mozilla/content/base/public/nsIStyledContent.h @@ -42,7 +42,7 @@ public: NS_IMETHOD GetID(nsIAtom*& aResult) const = 0; NS_IMETHOD GetClasses(nsVoidArray& aArray) const = 0; - NS_IMETHOD HasClass(nsIAtom* aClass) const = 0; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const = 0; NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker) = 0; NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker) = 0; diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index c055a9e7f69..204d27db38e 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -1808,7 +1808,7 @@ nsGenericElement::GetClasses(nsVoidArray& aArray) const } NS_IMETHODIMP -nsGenericElement::HasClass(nsIAtom* aClass) const +nsGenericElement::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index f3d15f2f686..ad305ecfd0f 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -272,7 +272,7 @@ public: // nsIStyledContent interface methods NS_IMETHOD GetID(nsIAtom*& aResult) const; NS_IMETHOD GetClasses(nsVoidArray& aArray) const; - NS_IMETHOD HasClass(nsIAtom* aClass) const; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const; NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker); NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker); NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32 aModType, diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index 3e010b4cad4..9bce0200b73 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -2019,10 +2019,10 @@ nsGenericHTMLElement::GetClasses(nsVoidArray& aArray) const } nsresult -nsGenericHTMLElement::HasClass(nsIAtom* aClass) const +nsGenericHTMLElement::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const { if (nsnull != mAttributes) { - return mAttributes->HasClass(aClass); + return mAttributes->HasClass(aClass, aCaseSensitive); } return NS_COMFALSE; } diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.h b/mozilla/content/html/content/src/nsGenericHTMLElement.h index a611ab6a458..11baf008d3f 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.h @@ -150,7 +150,7 @@ public: NS_IMETHOD GetHTMLAttribute(nsIAtom* aAttribute, nsHTMLValue& aValue) const; NS_IMETHOD GetID(nsIAtom*& aResult) const; NS_IMETHOD GetClasses(nsVoidArray& aArray) const; - NS_IMETHOD HasClass(nsIAtom* aClass) const; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const; NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker); NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker); NS_IMETHOD GetBaseURL(nsIURI*& aBaseURL) const; diff --git a/mozilla/content/html/style/src/nsCSSParser.cpp b/mozilla/content/html/style/src/nsCSSParser.cpp index 9d16c208920..1e7ef00baf0 100644 --- a/mozilla/content/html/style/src/nsCSSParser.cpp +++ b/mozilla/content/html/style/src/nsCSSParser.cpp @@ -1638,15 +1638,7 @@ void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask, } aDataMask |= SEL_MASK_CLASS; - if (mNavQuirkMode) { - // in quirks mode, we uppercase the class attribute and classes in CSS. - // (see also nsHTMLAttributes.cpp) - nsAutoString buffer; - mToken.mIdent.ToUpperCase(buffer); - aSelector.AddClass(buffer); - } else { - aSelector.AddClass(mToken.mIdent); - } + aSelector.AddClass(mToken.mIdent); aParsingStatus = SELECTOR_PARSING_ENDED_OK; } diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index 144ae666602..e524a085cce 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -83,6 +83,24 @@ //#define DEBUG_RULES //#define EVENT_DEBUG +//#define DEBUG_HASH + +#ifdef DEBUG_HASH +static void DebugHashCount(PRBool hash) { + static gCountHash = 0; + static gCountCompStr = 0; + if (hash) { + if (++gCountHash % 100 == 0) { + printf("gCountHash = %ld\n", gCountHash); + } + } + else { + if (++gCountCompStr % 100 == 0) { + printf("gCountCompStr = %ld\n", gCountCompStr); + } + } +} +#endif //DEBUG_HASH // ---------------------- @@ -97,7 +115,9 @@ class AtomKey_base : public nsHashKey { public: virtual PRUint32 HashCode(void) const; virtual PRBool Equals(const nsHashKey *aKey) const; + virtual void SetKeyCaseSensitive(PRBool aCaseSensitive); nsIAtom* mAtom; + PRBool mCaseSensitive; }; class AtomKey : public AtomKey_base { @@ -108,11 +128,13 @@ public: virtual nsHashKey *Clone(void) const; }; + class DependentAtomKey : public AtomKey_base { public: DependentAtomKey(nsIAtom* aAtom) { mAtom = aAtom; + SetKeyCaseSensitive(PR_TRUE); } DependentAtomKey(const DependentAtomKey& aKey); virtual ~DependentAtomKey(void) @@ -121,26 +143,60 @@ public: virtual nsHashKey *Clone(void) const; }; +void AtomKey_base::SetKeyCaseSensitive(PRBool aCaseSensitive) +{ + mCaseSensitive = aCaseSensitive; +} + PRUint32 AtomKey_base::HashCode(void) const { - return NS_PTR_TO_INT32(mAtom); + if (mCaseSensitive) { + return NS_PTR_TO_INT32(mAtom); + } + else { +#ifdef DEBUG_HASH + DebugHashCount(PR_TRUE); +#endif + nsAutoString myStr; + mAtom->ToString(myStr); + myStr.ToUpperCase(); + return nsCRT::HashCode(myStr.get()); + } } PRBool AtomKey_base::Equals(const nsHashKey* aKey) const { - return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom); + if (mCaseSensitive) { + return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom); + } + +#ifdef DEBUG_HASH + DebugHashCount(PR_FALSE); +#endif + const PRUnichar *myStr = nsnull; + mAtom->GetUnicode(&myStr); + + nsIAtom* theirAtom = ((AtomKey_base*)aKey)->mAtom; + + const PRUnichar *theirStr = nsnull; + theirAtom->GetUnicode(&theirStr); + + return nsCRT::strcasecmp(myStr, theirStr) == 0; } + AtomKey::AtomKey(nsIAtom* aAtom) { mAtom = aAtom; NS_ADDREF(mAtom); + SetKeyCaseSensitive(PR_TRUE); } AtomKey::AtomKey(const AtomKey_base& aKey) { mAtom = aKey.mAtom; NS_ADDREF(mAtom); + SetKeyCaseSensitive(PR_TRUE); } AtomKey::~AtomKey(void) @@ -158,6 +214,7 @@ DependentAtomKey::DependentAtomKey(const DependentAtomKey& aKey) { NS_NOTREACHED("Should never clone to a dependent atom key."); mAtom = aKey.mAtom; + SetKeyCaseSensitive(PR_TRUE); } nsHashKey* DependentAtomKey::Clone(void) const @@ -248,9 +305,10 @@ public: RuleEnumFunc aFunc, void* aData); void EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData); + void SetCaseSensitive(PRBool aCaseSensitive) {mCaseSensitive = aCaseSensitive;}; protected: - void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule); + void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive = PR_TRUE); void AppendRuleToTable(nsHashtable& aTable, PRInt32 aNameSpace, nsICSSStyleRule* aRule); PRInt32 mRuleCount; @@ -262,6 +320,7 @@ protected: RuleValue** mEnumList; PRInt32 mEnumListSize; RuleValue mEndValue; + PRBool mCaseSensitive; #ifdef RULE_HASH_STATS PRUint32 mUniversalSelectors; @@ -287,7 +346,8 @@ RuleHash::RuleHash(void) : mRuleCount(0), mIdTable(), mClassTable(), mTagTable(), mNameSpaceTable(), mEnumList(nsnull), mEnumListSize(0), - mEndValue(nsnull, -1) + mEndValue(nsnull, -1), + mCaseSensitive(PR_TRUE) #ifdef RULE_HASH_STATS , mUniversalSelectors(0), @@ -357,11 +417,12 @@ RuleHash::~RuleHash(void) } } -void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule) +void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive) { NS_ASSERTION(nsnull != aAtom, "null hash key"); DependentAtomKey key(aAtom); + key.SetKeyCaseSensitive(aCaseSensitive); RuleValue* value = (RuleValue*)aTable.Get(&key); if (nsnull == value) { @@ -403,13 +464,13 @@ void RuleHash::AppendRule(nsICSSStyleRule* aRule) { nsCSSSelector* selector = aRule->FirstSelector(); if (nsnull != selector->mIDList) { - AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule); + AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule, mCaseSensitive); #ifdef RULE_HASH_STATS ++mIdSelectors; #endif } else if (nsnull != selector->mClassList) { - AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule); + AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule, mCaseSensitive); #ifdef RULE_HASH_STATS ++mClassSelectors; #endif @@ -507,6 +568,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, } if (nsnull != aID) { DependentAtomKey idKey(aID); + idKey.SetKeyCaseSensitive(mCaseSensitive); RuleValue* value = (RuleValue*)mIdTable.Get(&idKey); if (nsnull != value) { mEnumList[valueCount++] = value; @@ -521,6 +583,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, for (index = 0; index < classCount; index++) { nsIAtom* classAtom = (nsIAtom*)aClassList.ElementAt(index); DependentAtomKey classKey(classAtom); + classKey.SetKeyCaseSensitive(mCaseSensitive); RuleValue* value = (RuleValue*)mClassTable.Get(&classKey); if (nsnull != value) { mEnumList[valueCount++] = value; @@ -648,7 +711,7 @@ public: virtual void SizeOf(nsISizeOfHandler *aSizeofHandler, PRUint32 &aSize); protected: - RuleCascadeData* GetRuleCascade(nsIAtom* aMedium); + RuleCascadeData* GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium); static PRBool CascadeSheetRulesInto(nsISupports* aSheet, void* aData); @@ -3635,6 +3698,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, ((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) { // test for ID & class match result = localFalse; if (data.mStyledContent) { + PRBool isCaseSensitive = !data.mIsQuirkMode; // bug 93371 nsAtomList* IDList = aSelector->mIDList; if (nsnull == IDList) { result = PR_TRUE; @@ -3642,7 +3706,18 @@ static PRBool SelectorMatches(SelectorMatchesData &data, else if (nsnull != data.mContentID) { result = PR_TRUE; while (nsnull != IDList) { - if (localTrue == (IDList->mAtom != data.mContentID)) { + PRBool dontMatch; + if (isCaseSensitive) { + dontMatch = (IDList->mAtom != data.mContentID); + } + else { + nsAutoString s1; + nsAutoString s2; + IDList->mAtom->ToString(s1); + data.mContentID->ToString(s2); + dontMatch = !s1.EqualsIgnoreCase(s2); + } + if (localTrue == dontMatch) { result = PR_FALSE; break; } @@ -3653,7 +3728,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, if (result) { nsAtomList* classList = aSelector->mClassList; while (nsnull != classList) { - if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom))) { + if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom, isCaseSensitive))) { result = PR_FALSE; break; } @@ -3828,7 +3903,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext, NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aRuleWalker, "null arg"); - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { nsIAtom* idAtom = nsnull; @@ -3942,7 +4017,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext, NS_PRECONDITION(nsnull != aPseudoTag, "null arg"); NS_PRECONDITION(nsnull != aRuleWalker, "null arg"); - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aComparator, aRuleWalker); @@ -3993,7 +4068,7 @@ CSSRuleProcessor::HasStateDependentStyle(nsIPresContext* aPresContext, { PRBool isStateful = PR_FALSE; - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { // look up content in state rule list @@ -4142,8 +4217,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) nsCOMPtr tag2 = getter_AddRefs(NS_NewAtom("RuleCascade")); CascadeSizeEnumData data(aSizeOfHandler, uniqueItems, tag2); for (RuleCascadeData *cascadeData = mRuleCascades; - cascadeData; - cascadeData = cascadeData->mNext) { + cascadeData; + cascadeData = cascadeData->mNext) { CascadeSizeEnumFunc(cascadeData, &data); } } @@ -4353,7 +4428,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays, } RuleCascadeData* -CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium) +CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium) { RuleCascadeData **cascadep = &mRuleCascades; RuleCascadeData *cascade; @@ -4372,6 +4447,11 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium) mSheets->EnumerateForwards(CascadeSheetRulesInto, &data); PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules); + nsCompatibility quirkMode = eCompatibility_Standard; + aPresContext->GetCompatibilityMode(&quirkMode); + PRBool isQuirksMode = (eCompatibility_Standard == quirkMode ? PR_FALSE : PR_TRUE); + + cascade->mRuleHash.SetCaseSensitive(!isQuirksMode); cascade->mWeightedRules->EnumerateBackwards(BuildHashEnum, &(cascade->mRuleHash)); cascade->mWeightedRules->EnumerateBackwards(BuildStateEnum, &(cascade->mStateSelectors)); } diff --git a/mozilla/content/html/style/src/nsHTMLAttributes.cpp b/mozilla/content/html/style/src/nsHTMLAttributes.cpp index 8387b679d46..1929fb0c815 100644 --- a/mozilla/content/html/style/src/nsHTMLAttributes.cpp +++ b/mozilla/content/html/style/src/nsHTMLAttributes.cpp @@ -828,7 +828,7 @@ public: NS_IMETHOD GetID(nsIAtom*& aResult) const; NS_IMETHOD GetClasses(nsVoidArray& aArray) const; - NS_IMETHOD HasClass(nsIAtom* aClass) const; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const; NS_IMETHOD Clone(nsIHTMLAttributes** aInstancePtrResult) const; @@ -968,37 +968,11 @@ NS_IMPL_ISUPPORTS1(HTMLAttributesImpl, nsIHTMLAttributes) const PRUnichar kNullCh = PRUnichar('\0'); -static void ParseClasses(const nsAReadableString& aClassString, nsClassList& aClassList, nsIHTMLContent* aContent) +static void ParseClasses(const nsAReadableString& aClassString, nsClassList& aClassList) { nsAutoString classStr(aClassString); // copy to work buffer classStr.Append(kNullCh); // put an extra null at the end - // Find out if we're in quirks mode by walking from aContent - // to the presContext (null-checking all the way) - nsCOMPtr ni; - aContent->GetNodeInfo(*getter_AddRefs(ni)); - if (ni) { - nsCOMPtr doc; - ni->GetDocument(*getter_AddRefs(doc)); - if (doc) { - nsCOMPtr shell; - doc->GetShellAt(0, getter_AddRefs(shell)); - if (shell) { - nsCOMPtr presContext; - shell->GetPresContext(getter_AddRefs(presContext)); - if (presContext) { - nsCompatibility mode; - presContext->GetCompatibilityMode(&mode); - if (mode == eCompatibility_NavQuirks) { - // in quirks mode, we uppercase the class attribute and classes in CSS. - // (see also nsCSSParser.cpp) - classStr.ToUpperCase(); - } - } - } - } - } - PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr.get(); PRUnichar* end = start; @@ -1163,7 +1137,7 @@ HTMLAttributesImpl::SetAttributeFor(nsIAtom* aAttrName, const nsAReadableString& } else if (nsHTMLAtoms::kClass == aAttrName) { mFirstClass.Reset(); - ParseClasses(aValue, mFirstClass, aContent); + ParseClasses(aValue, mFirstClass); } PRBool haveAttr; @@ -1226,7 +1200,7 @@ HTMLAttributesImpl::SetAttributeFor(nsIAtom* aAttrName, if (eHTMLUnit_String == aValue.GetUnit()) { nsAutoString buffer; aValue.GetStringValue(buffer); - ParseClasses(buffer, mFirstClass, aContent); + ParseClasses(buffer, mFirstClass); } } @@ -1399,12 +1373,27 @@ HTMLAttributesImpl::GetClasses(nsVoidArray& aArray) const } NS_IMETHODIMP -HTMLAttributesImpl::HasClass(nsIAtom* aClass) const +HTMLAttributesImpl::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const { const nsClassList* classList = &mFirstClass; while (classList) { - if (classList->mAtom == aClass) { - return NS_OK; + if (aCaseSensitive) { + if (classList->mAtom == aClass) { + return NS_OK; + } + } + else { + nsAutoString s1; + nsAutoString s2; + if (classList->mAtom) { + classList->mAtom->ToString(s1); + } + if (aClass) { + aClass->ToString(s2); + } + if (s1.EqualsIgnoreCase(s2)) { + return NS_OK; + } } classList = classList->mNext; } diff --git a/mozilla/content/html/style/src/nsIHTMLAttributes.h b/mozilla/content/html/style/src/nsIHTMLAttributes.h index c4ac79952f7..9079bf11723 100644 --- a/mozilla/content/html/style/src/nsIHTMLAttributes.h +++ b/mozilla/content/html/style/src/nsIHTMLAttributes.h @@ -73,7 +73,7 @@ public: NS_IMETHOD GetID(nsIAtom*& aResult) const = 0; NS_IMETHOD GetClasses(nsVoidArray& aArray) const = 0; - NS_IMETHOD HasClass(nsIAtom* aClass) const = 0; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const = 0; NS_IMETHOD Clone(nsIHTMLAttributes** aInstancePtrResult) const = 0; diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index 117d6fa4660..53f30443d66 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -4273,7 +4273,7 @@ nsXULElement::GetClasses(nsVoidArray& aArray) const } NS_IMETHODIMP -nsXULElement::HasClass(nsIAtom* aClass) const +nsXULElement::HasClass(nsIAtom* aClass, PRBool /*aCaseSensitive*/) const { nsresult rv = NS_ERROR_NULL_POINTER; if (Attributes()) { diff --git a/mozilla/content/xul/content/src/nsXULElement.h b/mozilla/content/xul/content/src/nsXULElement.h index 6f1822ce30c..79ed8d0a202 100644 --- a/mozilla/content/xul/content/src/nsXULElement.h +++ b/mozilla/content/xul/content/src/nsXULElement.h @@ -417,7 +417,7 @@ public: // nsIStyledContent NS_IMETHOD GetID(nsIAtom*& aResult) const; NS_IMETHOD GetClasses(nsVoidArray& aArray) const; - NS_IMETHOD HasClass(nsIAtom* aClass) const; + NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const; NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker); NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker); diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index 9d16c208920..1e7ef00baf0 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -1638,15 +1638,7 @@ void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask, } aDataMask |= SEL_MASK_CLASS; - if (mNavQuirkMode) { - // in quirks mode, we uppercase the class attribute and classes in CSS. - // (see also nsHTMLAttributes.cpp) - nsAutoString buffer; - mToken.mIdent.ToUpperCase(buffer); - aSelector.AddClass(buffer); - } else { - aSelector.AddClass(mToken.mIdent); - } + aSelector.AddClass(mToken.mIdent); aParsingStatus = SELECTOR_PARSING_ENDED_OK; } diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index 144ae666602..e524a085cce 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -83,6 +83,24 @@ //#define DEBUG_RULES //#define EVENT_DEBUG +//#define DEBUG_HASH + +#ifdef DEBUG_HASH +static void DebugHashCount(PRBool hash) { + static gCountHash = 0; + static gCountCompStr = 0; + if (hash) { + if (++gCountHash % 100 == 0) { + printf("gCountHash = %ld\n", gCountHash); + } + } + else { + if (++gCountCompStr % 100 == 0) { + printf("gCountCompStr = %ld\n", gCountCompStr); + } + } +} +#endif //DEBUG_HASH // ---------------------- @@ -97,7 +115,9 @@ class AtomKey_base : public nsHashKey { public: virtual PRUint32 HashCode(void) const; virtual PRBool Equals(const nsHashKey *aKey) const; + virtual void SetKeyCaseSensitive(PRBool aCaseSensitive); nsIAtom* mAtom; + PRBool mCaseSensitive; }; class AtomKey : public AtomKey_base { @@ -108,11 +128,13 @@ public: virtual nsHashKey *Clone(void) const; }; + class DependentAtomKey : public AtomKey_base { public: DependentAtomKey(nsIAtom* aAtom) { mAtom = aAtom; + SetKeyCaseSensitive(PR_TRUE); } DependentAtomKey(const DependentAtomKey& aKey); virtual ~DependentAtomKey(void) @@ -121,26 +143,60 @@ public: virtual nsHashKey *Clone(void) const; }; +void AtomKey_base::SetKeyCaseSensitive(PRBool aCaseSensitive) +{ + mCaseSensitive = aCaseSensitive; +} + PRUint32 AtomKey_base::HashCode(void) const { - return NS_PTR_TO_INT32(mAtom); + if (mCaseSensitive) { + return NS_PTR_TO_INT32(mAtom); + } + else { +#ifdef DEBUG_HASH + DebugHashCount(PR_TRUE); +#endif + nsAutoString myStr; + mAtom->ToString(myStr); + myStr.ToUpperCase(); + return nsCRT::HashCode(myStr.get()); + } } PRBool AtomKey_base::Equals(const nsHashKey* aKey) const { - return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom); + if (mCaseSensitive) { + return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom); + } + +#ifdef DEBUG_HASH + DebugHashCount(PR_FALSE); +#endif + const PRUnichar *myStr = nsnull; + mAtom->GetUnicode(&myStr); + + nsIAtom* theirAtom = ((AtomKey_base*)aKey)->mAtom; + + const PRUnichar *theirStr = nsnull; + theirAtom->GetUnicode(&theirStr); + + return nsCRT::strcasecmp(myStr, theirStr) == 0; } + AtomKey::AtomKey(nsIAtom* aAtom) { mAtom = aAtom; NS_ADDREF(mAtom); + SetKeyCaseSensitive(PR_TRUE); } AtomKey::AtomKey(const AtomKey_base& aKey) { mAtom = aKey.mAtom; NS_ADDREF(mAtom); + SetKeyCaseSensitive(PR_TRUE); } AtomKey::~AtomKey(void) @@ -158,6 +214,7 @@ DependentAtomKey::DependentAtomKey(const DependentAtomKey& aKey) { NS_NOTREACHED("Should never clone to a dependent atom key."); mAtom = aKey.mAtom; + SetKeyCaseSensitive(PR_TRUE); } nsHashKey* DependentAtomKey::Clone(void) const @@ -248,9 +305,10 @@ public: RuleEnumFunc aFunc, void* aData); void EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData); + void SetCaseSensitive(PRBool aCaseSensitive) {mCaseSensitive = aCaseSensitive;}; protected: - void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule); + void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive = PR_TRUE); void AppendRuleToTable(nsHashtable& aTable, PRInt32 aNameSpace, nsICSSStyleRule* aRule); PRInt32 mRuleCount; @@ -262,6 +320,7 @@ protected: RuleValue** mEnumList; PRInt32 mEnumListSize; RuleValue mEndValue; + PRBool mCaseSensitive; #ifdef RULE_HASH_STATS PRUint32 mUniversalSelectors; @@ -287,7 +346,8 @@ RuleHash::RuleHash(void) : mRuleCount(0), mIdTable(), mClassTable(), mTagTable(), mNameSpaceTable(), mEnumList(nsnull), mEnumListSize(0), - mEndValue(nsnull, -1) + mEndValue(nsnull, -1), + mCaseSensitive(PR_TRUE) #ifdef RULE_HASH_STATS , mUniversalSelectors(0), @@ -357,11 +417,12 @@ RuleHash::~RuleHash(void) } } -void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule) +void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive) { NS_ASSERTION(nsnull != aAtom, "null hash key"); DependentAtomKey key(aAtom); + key.SetKeyCaseSensitive(aCaseSensitive); RuleValue* value = (RuleValue*)aTable.Get(&key); if (nsnull == value) { @@ -403,13 +464,13 @@ void RuleHash::AppendRule(nsICSSStyleRule* aRule) { nsCSSSelector* selector = aRule->FirstSelector(); if (nsnull != selector->mIDList) { - AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule); + AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule, mCaseSensitive); #ifdef RULE_HASH_STATS ++mIdSelectors; #endif } else if (nsnull != selector->mClassList) { - AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule); + AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule, mCaseSensitive); #ifdef RULE_HASH_STATS ++mClassSelectors; #endif @@ -507,6 +568,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, } if (nsnull != aID) { DependentAtomKey idKey(aID); + idKey.SetKeyCaseSensitive(mCaseSensitive); RuleValue* value = (RuleValue*)mIdTable.Get(&idKey); if (nsnull != value) { mEnumList[valueCount++] = value; @@ -521,6 +583,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, for (index = 0; index < classCount; index++) { nsIAtom* classAtom = (nsIAtom*)aClassList.ElementAt(index); DependentAtomKey classKey(classAtom); + classKey.SetKeyCaseSensitive(mCaseSensitive); RuleValue* value = (RuleValue*)mClassTable.Get(&classKey); if (nsnull != value) { mEnumList[valueCount++] = value; @@ -648,7 +711,7 @@ public: virtual void SizeOf(nsISizeOfHandler *aSizeofHandler, PRUint32 &aSize); protected: - RuleCascadeData* GetRuleCascade(nsIAtom* aMedium); + RuleCascadeData* GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium); static PRBool CascadeSheetRulesInto(nsISupports* aSheet, void* aData); @@ -3635,6 +3698,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, ((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) { // test for ID & class match result = localFalse; if (data.mStyledContent) { + PRBool isCaseSensitive = !data.mIsQuirkMode; // bug 93371 nsAtomList* IDList = aSelector->mIDList; if (nsnull == IDList) { result = PR_TRUE; @@ -3642,7 +3706,18 @@ static PRBool SelectorMatches(SelectorMatchesData &data, else if (nsnull != data.mContentID) { result = PR_TRUE; while (nsnull != IDList) { - if (localTrue == (IDList->mAtom != data.mContentID)) { + PRBool dontMatch; + if (isCaseSensitive) { + dontMatch = (IDList->mAtom != data.mContentID); + } + else { + nsAutoString s1; + nsAutoString s2; + IDList->mAtom->ToString(s1); + data.mContentID->ToString(s2); + dontMatch = !s1.EqualsIgnoreCase(s2); + } + if (localTrue == dontMatch) { result = PR_FALSE; break; } @@ -3653,7 +3728,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data, if (result) { nsAtomList* classList = aSelector->mClassList; while (nsnull != classList) { - if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom))) { + if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom, isCaseSensitive))) { result = PR_FALSE; break; } @@ -3828,7 +3903,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext, NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aRuleWalker, "null arg"); - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { nsIAtom* idAtom = nsnull; @@ -3942,7 +4017,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext, NS_PRECONDITION(nsnull != aPseudoTag, "null arg"); NS_PRECONDITION(nsnull != aRuleWalker, "null arg"); - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aComparator, aRuleWalker); @@ -3993,7 +4068,7 @@ CSSRuleProcessor::HasStateDependentStyle(nsIPresContext* aPresContext, { PRBool isStateful = PR_FALSE; - RuleCascadeData* cascade = GetRuleCascade(aMedium); + RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium); if (cascade) { // look up content in state rule list @@ -4142,8 +4217,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize) nsCOMPtr tag2 = getter_AddRefs(NS_NewAtom("RuleCascade")); CascadeSizeEnumData data(aSizeOfHandler, uniqueItems, tag2); for (RuleCascadeData *cascadeData = mRuleCascades; - cascadeData; - cascadeData = cascadeData->mNext) { + cascadeData; + cascadeData = cascadeData->mNext) { CascadeSizeEnumFunc(cascadeData, &data); } } @@ -4353,7 +4428,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays, } RuleCascadeData* -CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium) +CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium) { RuleCascadeData **cascadep = &mRuleCascades; RuleCascadeData *cascade; @@ -4372,6 +4447,11 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium) mSheets->EnumerateForwards(CascadeSheetRulesInto, &data); PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules); + nsCompatibility quirkMode = eCompatibility_Standard; + aPresContext->GetCompatibilityMode(&quirkMode); + PRBool isQuirksMode = (eCompatibility_Standard == quirkMode ? PR_FALSE : PR_TRUE); + + cascade->mRuleHash.SetCaseSensitive(!isQuirksMode); cascade->mWeightedRules->EnumerateBackwards(BuildHashEnum, &(cascade->mRuleHash)); cascade->mWeightedRules->EnumerateBackwards(BuildStateEnum, &(cascade->mStateSelectors)); }