Make nsPseudoClassList capable of storing integer pairs for :nth-*(). b=75375 r+sr=bzbarsky

This commit is contained in:
L. David Baron 2008-06-02 20:17:35 -07:00
parent 1eef72cec5
commit 8b2c14530a
6 changed files with 131 additions and 32 deletions

View File

@ -2560,9 +2560,7 @@ CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
isTree ||
#endif
nsCSSPseudoClasses::notPseudo == pseudo ||
nsCSSPseudoClasses::lang == pseudo ||
nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudo ||
nsCSSPseudoClasses::mozSystemMetric == pseudo)) {
nsCSSPseudoClasses::HasStringArg(pseudo))) {
// There are no other function pseudos
REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
UngetToken();
@ -2593,9 +2591,7 @@ CSSParserImpl::ParsePseudoSelector(PRInt32& aDataMask,
}
else if (!parsingPseudoElement && isPseudoClass) {
aDataMask |= SEL_MASK_PCLASS;
if (nsCSSPseudoClasses::lang == pseudo ||
nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudo ||
nsCSSPseudoClasses::mozSystemMetric == pseudo) {
if (nsCSSPseudoClasses::HasStringArg(pseudo)) {
nsSelectorParsingStatus parsingStatus =
ParsePseudoClassWithIdentArg(aSelector, pseudo, aErrorCode);
if (eSelectorParsingStatus_Continue != parsingStatus) {

View File

@ -68,3 +68,16 @@ PRBool nsCSSPseudoClasses::IsPseudoClass(nsIAtom *aAtom)
NS_ARRAY_LENGTH(CSSPseudoClasses_info));
}
PRBool
nsCSSPseudoClasses::HasStringArg(nsIAtom* aAtom)
{
return aAtom == nsCSSPseudoClasses::lang ||
aAtom == nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname ||
aAtom == nsCSSPseudoClasses::mozSystemMetric;
}
PRBool
nsCSSPseudoClasses::HasNthPairArg(nsIAtom* aAtom)
{
return PR_FALSE;
}

View File

@ -53,6 +53,8 @@ public:
static void AddRefAtoms();
static PRBool IsPseudoClass(nsIAtom *aAtom);
static PRBool HasStringArg(nsIAtom* aAtom);
static PRBool HasNthPairArg(nsIAtom* aAtom);
#define CSS_PSEUDO_CLASS(_name, _value) static nsICSSPseudoClass* _name;
#include "nsCSSPseudoClassList.h"

View File

@ -1161,7 +1161,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
result = (child == nsnull);
}
else if (nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudoClass->mAtom) {
NS_ASSERTION(pseudoClass->mString, "Must have string!");
NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
nsIContent *child = nsnull;
nsIContent *element = data.mContent;
PRInt32 index = -1;
@ -1174,15 +1174,15 @@ static PRBool SelectorMatches(RuleProcessorData &data,
} while (child &&
(!IsSignificantChild(child, PR_TRUE, PR_FALSE) ||
(child->GetNameSpaceID() == element->GetNameSpaceID() &&
child->Tag()->Equals(nsDependentString(pseudoClass->mString)))));
child->Tag()->Equals(nsDependentString(pseudoClass->u.mString)))));
result = (child == nsnull);
}
else if (nsCSSPseudoClasses::mozSystemMetric == pseudoClass->mAtom) {
if (!sSystemMetrics && !InitSystemMetrics()) {
return PR_FALSE;
}
NS_ASSERTION(pseudoClass->mString, "Must have string!");
nsCOMPtr<nsIAtom> metric = do_GetAtom(pseudoClass->mString);
NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
nsCOMPtr<nsIAtom> metric = do_GetAtom(pseudoClass->u.mString);
result = sSystemMetrics->IndexOf(metric) !=
sSystemMetrics->NoIndex;
}
@ -1215,9 +1215,9 @@ static PRBool SelectorMatches(RuleProcessorData &data,
result = (data.mScopedRoot && data.mScopedRoot == data.mContent);
}
else if (nsCSSPseudoClasses::lang == pseudoClass->mAtom) {
NS_ASSERTION(nsnull != pseudoClass->mString, "null lang parameter");
NS_ASSERTION(nsnull != pseudoClass->u.mString, "null lang parameter");
result = PR_FALSE;
if (pseudoClass->mString && *pseudoClass->mString) {
if (pseudoClass->u.mString && *pseudoClass->u.mString) {
// We have to determine the language of the current element. Since
// this is currently no property and since the language is inherited
// from the parent we have to be prepared to look at all parent
@ -1225,7 +1225,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
const nsString* lang = data.GetLang();
if (lang && !lang->IsEmpty()) { // null check for out-of-memory
result = nsStyleUtil::DashMatchCompare(*lang,
nsDependentString(pseudoClass->mString),
nsDependentString(pseudoClass->u.mString),
nsCaseInsensitiveStringComparator());
}
else if (data.mContent) {
@ -1238,7 +1238,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
nsAutoString language;
doc->GetContentLanguage(language);
nsDependentString langString(pseudoClass->mString);
nsDependentString langString(pseudoClass->u.mString);
language.StripWhitespace();
PRInt32 begin = 0;
PRInt32 len = language.Length();

View File

@ -22,6 +22,7 @@
* Contributor(s):
* David Hyatt <hyatt@netscape.com>
* Daniel Glazman <glazman@netscape.com>
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -73,6 +74,7 @@
#include "nsCSSPseudoElements.h"
#include "nsIPrincipal.h"
#include "nsComponentManagerUtils.h"
#include "nsCSSPseudoClasses.h"
#include "nsContentUtils.h"
#include "nsContentErrors.h"
@ -158,20 +160,53 @@ nsAtomList::~nsAtomList(void)
NS_IF_DEEP_DELETE(nsAtomList, mNext);
}
nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRUnichar* aString)
nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom)
: mAtom(aAtom),
mString(nsnull),
mNext(nsnull)
{
NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aAtom) &&
!nsCSSPseudoClasses::HasNthPairArg(aAtom),
"unexpected pseudo-class");
MOZ_COUNT_CTOR(nsPseudoClassList);
if (aString)
mString = NS_strdup(aString);
u.mMemory = nsnull;
}
nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRUnichar* aString)
: mAtom(aAtom),
mNext(nsnull)
{
NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aAtom),
"unexpected pseudo-class");
NS_ASSERTION(aString, "string expected");
MOZ_COUNT_CTOR(nsPseudoClassList);
u.mString = NS_strdup(aString);
}
nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRInt32* aIntPair)
: mAtom(aAtom),
mNext(nsnull)
{
NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aAtom),
"unexpected pseudo-class");
NS_ASSERTION(aIntPair, "integer pair expected");
MOZ_COUNT_CTOR(nsPseudoClassList);
u.mNumbers =
static_cast<PRInt32*>(nsMemory::Clone(aIntPair, sizeof(PRInt32) * 2));
}
nsPseudoClassList*
nsPseudoClassList::Clone(PRBool aDeep) const
{
nsPseudoClassList *result = new nsPseudoClassList(mAtom, mString);
nsPseudoClassList *result;
if (!u.mMemory) {
result = new nsPseudoClassList(mAtom);
} else if (nsCSSPseudoClasses::HasStringArg(mAtom)) {
result = new nsPseudoClassList(mAtom, u.mString);
} else {
NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(mAtom),
"unexpected pseudo-class");
result = new nsPseudoClassList(mAtom, u.mNumbers);
}
if (aDeep)
NS_IF_DEEP_CLONE(nsPseudoClassList, mNext, (PR_FALSE));
@ -182,8 +217,8 @@ nsPseudoClassList::Clone(PRBool aDeep) const
nsPseudoClassList::~nsPseudoClassList(void)
{
MOZ_COUNT_DTOR(nsPseudoClassList);
if (mString)
NS_Free(mString);
if (u.mMemory)
NS_Free(u.mMemory);
NS_IF_DEEP_DELETE(nsPseudoClassList, mNext);
}
@ -347,16 +382,30 @@ void nsCSSSelector::AddClass(const nsString& aClass)
}
}
void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass)
{
AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass));
}
void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
const PRUnichar* aString)
{
if (nsnull != aPseudoClass) {
nsPseudoClassList** list = &mPseudoClassList;
while (nsnull != *list) {
list = &((*list)->mNext);
}
*list = new nsPseudoClassList(aPseudoClass, aString);
AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aString));
}
void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
const PRInt32* aIntPair)
{
AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aIntPair));
}
void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
{
nsPseudoClassList** list = &mPseudoClassList;
while (nsnull != *list) {
list = &((*list)->mNext);
}
*list = aPseudoClass;
}
void nsCSSSelector::AddAttribute(PRInt32 aNameSpace, const nsString& aAttr)
@ -628,9 +677,31 @@ void nsCSSSelector::ToStringInternal(nsAString& aString,
while (list != nsnull) {
list->mAtom->ToString(temp);
aString.Append(temp);
if (nsnull != list->mString) {
if (list->u.mMemory) {
aString.Append(PRUnichar('('));
aString.Append(list->mString);
if (nsCSSPseudoClasses::HasStringArg(list->mAtom)) {
aString.Append(list->u.mString);
} else {
NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(list->mAtom),
"unexpected pseudo-class");
PRInt32 a = list->u.mNumbers[0],
b = list->u.mNumbers[1];
temp.Truncate();
if (a != 0) {
if (a == -1) {
temp.Append(PRUnichar('-'));
} else if (a != 1) {
temp.AppendInt(a);
}
temp.Append(PRUnichar('n'));
}
if (b != 0 || a == 0) {
if (b >= 0 && a != 0) // check a != 0 for whether we printed above
temp.Append(PRUnichar('+'));
temp.AppendInt(b);
}
aString.Append(temp);
}
aString.Append(PRUnichar(')'));
}
list = list->mNext;

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Daniel Glazman <glazman@netscape.com>
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -77,14 +78,27 @@ private:
struct nsPseudoClassList {
public:
nsPseudoClassList(nsIAtom* aAtom, const PRUnichar *aString = nsnull);
nsPseudoClassList(nsIAtom* aAtom);
nsPseudoClassList(nsIAtom* aAtom, const PRUnichar *aString);
nsPseudoClassList(nsIAtom* aAtom, const PRInt32 *aIntPair);
~nsPseudoClassList(void);
/** Do a deep clone. Should be used only on the first in the linked list. */
nsPseudoClassList* Clone() const { return Clone(PR_TRUE); }
nsCOMPtr<nsIAtom> mAtom;
PRUnichar* mString;
union {
// For a given value of mAtom, we have either:
// a. no value, which means mMemory is always null
// (if neither of the conditions for (b) or (c) is true)
// b. a string value, which means mString/mMemory is non-null
// (if nsCSSPseudoClasses::HasStringArg(mAtom))
// c. an integer pair value, which means mNumbers/mMemory is non-null
// (if nsCSSPseudoClasses::HasNthPairArg(mAtom))
void* mMemory; // both pointer types use NS_Alloc/NS_Free
PRUnichar* mString;
PRInt32* mNumbers;
} u;
nsPseudoClassList* mNext;
private:
nsPseudoClassList* Clone(PRBool aDeep) const;
@ -141,7 +155,9 @@ public:
void SetTag(const nsString& aTag);
void AddID(const nsString& aID);
void AddClass(const nsString& aClass);
void AddPseudoClass(nsIAtom* aPseudoClass, const PRUnichar* aString = nsnull);
void AddPseudoClass(nsIAtom* aPseudoClass);
void AddPseudoClass(nsIAtom* aPseudoClass, const PRUnichar* aString);
void AddPseudoClass(nsIAtom* aPseudoClass, const PRInt32* aIntPair);
void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr);
void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunc,
const nsString& aValue, PRBool aCaseSensitive);
@ -153,6 +169,7 @@ public:
PRBool aAppend = PR_FALSE) const;
private:
void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass);
nsCSSSelector* Clone(PRBool aDeepNext, PRBool aDeepNegations) const;
void AppendNegationToString(nsAString& aString);