mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-31 02:48:48 +00:00
Make nsPseudoClassList capable of storing integer pairs for :nth-*(). b=75375 r+sr=bzbarsky
This commit is contained in:
parent
1eef72cec5
commit
8b2c14530a
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user