added pseudo-class rule matching
This commit is contained in:
@@ -753,7 +753,7 @@ static PRBool IsPseudoClass(const nsString& aBuffer)
|
|||||||
return (aBuffer.EqualsIgnoreCase("link") ||
|
return (aBuffer.EqualsIgnoreCase("link") ||
|
||||||
aBuffer.EqualsIgnoreCase("visited") ||
|
aBuffer.EqualsIgnoreCase("visited") ||
|
||||||
aBuffer.EqualsIgnoreCase("hover") ||
|
aBuffer.EqualsIgnoreCase("hover") ||
|
||||||
aBuffer.EqualsIgnoreCase("out-of-date") || // XXX ??
|
aBuffer.EqualsIgnoreCase("out-of-date") || // our extension
|
||||||
aBuffer.EqualsIgnoreCase("active"));
|
aBuffer.EqualsIgnoreCase("active"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void nsCSSSelector::Set(const nsString& aTag, const nsString& aID,
|
|||||||
mClass = NS_NewAtom(aClass);
|
mClass = NS_NewAtom(aClass);
|
||||||
}
|
}
|
||||||
if (0 < aPseudoClass.Length()) {
|
if (0 < aPseudoClass.Length()) {
|
||||||
aPseudoClass.ToLowerCase(buffer);
|
aPseudoClass.ToUpperCase(buffer);
|
||||||
mPseudoClass = NS_NewAtom(buffer);
|
mPseudoClass = NS_NewAtom(buffer);
|
||||||
if (nsnull == mTag) {
|
if (nsnull == mTag) {
|
||||||
mTag = nsHTMLAtoms::a;
|
mTag = nsHTMLAtoms::a;
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
#include "nsICSSStyleRule.h"
|
#include "nsICSSStyleRule.h"
|
||||||
#include "nsIHTMLContent.h"
|
#include "nsIHTMLContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIPresContext.h"
|
||||||
|
#include "nsILinkHandler.h"
|
||||||
|
#include "nsHTMLAtoms.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsIPtr.h"
|
#include "nsIPtr.h"
|
||||||
@@ -54,7 +58,8 @@ public:
|
|||||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||||
NS_IMETHOD_(nsrefcnt) Release();
|
NS_IMETHOD_(nsrefcnt) Release();
|
||||||
|
|
||||||
virtual PRBool SelectorMatches(nsCSSSelector* aSelector,
|
virtual PRBool SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector,
|
||||||
nsIContent* aContent);
|
nsIContent* aContent);
|
||||||
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
@@ -186,17 +191,64 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID,
|
|||||||
return NS_NOINTERFACE;
|
return NS_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool CSSStyleSheetImpl::SelectorMatches(nsCSSSelector* aSelector, nsIContent* aContent)
|
PRBool CSSStyleSheetImpl::SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector, nsIContent* aContent)
|
||||||
{
|
{
|
||||||
PRBool result = PR_FALSE;
|
PRBool result = PR_FALSE;
|
||||||
|
nsIAtom* contentTag = aContent->GetTag();
|
||||||
|
|
||||||
if ((nsnull == aSelector->mTag) || (aSelector->mTag == aContent->GetTag())) {
|
if ((nsnull == aSelector->mTag) || (aSelector->mTag == contentTag)) {
|
||||||
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID)) {
|
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID) ||
|
||||||
|
(nsnull != aSelector->mPseudoClass)) {
|
||||||
nsIHTMLContentPtr htmlContent;
|
nsIHTMLContentPtr htmlContent;
|
||||||
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
||||||
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
||||||
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
||||||
result = PR_TRUE;
|
if ((contentTag == nsHTMLAtoms::a) && (nsnull != aSelector->mPseudoClass)) {
|
||||||
|
// test link state
|
||||||
|
nsILinkHandler* linkHandler;
|
||||||
|
|
||||||
|
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
|
||||||
|
nsAutoString base, href; // XXX base??
|
||||||
|
htmlContent->GetAttribute("href", href);
|
||||||
|
|
||||||
|
nsIURL* docURL = nsnull;
|
||||||
|
nsIDocument* doc = aContent->GetDocument();
|
||||||
|
if (nsnull != doc) {
|
||||||
|
docURL = doc->GetDocumentURL();
|
||||||
|
NS_RELEASE(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString absURLSpec;
|
||||||
|
nsresult rv = NS_MakeAbsoluteURL(docURL, base, href, absURLSpec);
|
||||||
|
NS_IF_RELEASE(docURL);
|
||||||
|
|
||||||
|
nsLinkState state;
|
||||||
|
if (NS_OK == linkHandler->GetLinkState(absURLSpec, state)) {
|
||||||
|
switch (state) {
|
||||||
|
case eLinkState_Unvisited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::link);
|
||||||
|
break;
|
||||||
|
case eLinkState_Visited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::visited);
|
||||||
|
break;
|
||||||
|
case eLinkState_OutOfDate:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::outOfDate);
|
||||||
|
break;
|
||||||
|
case eLinkState_Active:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::active);
|
||||||
|
break;
|
||||||
|
case eLinkState_Hover:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::hover);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(linkHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = PR_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +289,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
||||||
|
|
||||||
nsCSSSelector* selector = rule->FirstSelector();
|
nsCSSSelector* selector = rule->FirstSelector();
|
||||||
if (SelectorMatches(selector, aContent)) {
|
if (SelectorMatches(aPresContext, selector, aContent)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
nsIFrame* frame = aParentFrame;
|
nsIFrame* frame = aParentFrame;
|
||||||
nsIContentPtr lastContent;
|
nsIContentPtr lastContent;
|
||||||
@@ -245,7 +297,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
@@ -295,7 +347,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
|
|||||||
@@ -753,7 +753,7 @@ static PRBool IsPseudoClass(const nsString& aBuffer)
|
|||||||
return (aBuffer.EqualsIgnoreCase("link") ||
|
return (aBuffer.EqualsIgnoreCase("link") ||
|
||||||
aBuffer.EqualsIgnoreCase("visited") ||
|
aBuffer.EqualsIgnoreCase("visited") ||
|
||||||
aBuffer.EqualsIgnoreCase("hover") ||
|
aBuffer.EqualsIgnoreCase("hover") ||
|
||||||
aBuffer.EqualsIgnoreCase("out-of-date") || // XXX ??
|
aBuffer.EqualsIgnoreCase("out-of-date") || // our extension
|
||||||
aBuffer.EqualsIgnoreCase("active"));
|
aBuffer.EqualsIgnoreCase("active"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void nsCSSSelector::Set(const nsString& aTag, const nsString& aID,
|
|||||||
mClass = NS_NewAtom(aClass);
|
mClass = NS_NewAtom(aClass);
|
||||||
}
|
}
|
||||||
if (0 < aPseudoClass.Length()) {
|
if (0 < aPseudoClass.Length()) {
|
||||||
aPseudoClass.ToLowerCase(buffer);
|
aPseudoClass.ToUpperCase(buffer);
|
||||||
mPseudoClass = NS_NewAtom(buffer);
|
mPseudoClass = NS_NewAtom(buffer);
|
||||||
if (nsnull == mTag) {
|
if (nsnull == mTag) {
|
||||||
mTag = nsHTMLAtoms::a;
|
mTag = nsHTMLAtoms::a;
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
#include "nsICSSStyleRule.h"
|
#include "nsICSSStyleRule.h"
|
||||||
#include "nsIHTMLContent.h"
|
#include "nsIHTMLContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIPresContext.h"
|
||||||
|
#include "nsILinkHandler.h"
|
||||||
|
#include "nsHTMLAtoms.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsIPtr.h"
|
#include "nsIPtr.h"
|
||||||
@@ -54,7 +58,8 @@ public:
|
|||||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||||
NS_IMETHOD_(nsrefcnt) Release();
|
NS_IMETHOD_(nsrefcnt) Release();
|
||||||
|
|
||||||
virtual PRBool SelectorMatches(nsCSSSelector* aSelector,
|
virtual PRBool SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector,
|
||||||
nsIContent* aContent);
|
nsIContent* aContent);
|
||||||
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
@@ -186,17 +191,64 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID,
|
|||||||
return NS_NOINTERFACE;
|
return NS_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool CSSStyleSheetImpl::SelectorMatches(nsCSSSelector* aSelector, nsIContent* aContent)
|
PRBool CSSStyleSheetImpl::SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector, nsIContent* aContent)
|
||||||
{
|
{
|
||||||
PRBool result = PR_FALSE;
|
PRBool result = PR_FALSE;
|
||||||
|
nsIAtom* contentTag = aContent->GetTag();
|
||||||
|
|
||||||
if ((nsnull == aSelector->mTag) || (aSelector->mTag == aContent->GetTag())) {
|
if ((nsnull == aSelector->mTag) || (aSelector->mTag == contentTag)) {
|
||||||
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID)) {
|
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID) ||
|
||||||
|
(nsnull != aSelector->mPseudoClass)) {
|
||||||
nsIHTMLContentPtr htmlContent;
|
nsIHTMLContentPtr htmlContent;
|
||||||
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
||||||
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
||||||
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
||||||
result = PR_TRUE;
|
if ((contentTag == nsHTMLAtoms::a) && (nsnull != aSelector->mPseudoClass)) {
|
||||||
|
// test link state
|
||||||
|
nsILinkHandler* linkHandler;
|
||||||
|
|
||||||
|
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
|
||||||
|
nsAutoString base, href; // XXX base??
|
||||||
|
htmlContent->GetAttribute("href", href);
|
||||||
|
|
||||||
|
nsIURL* docURL = nsnull;
|
||||||
|
nsIDocument* doc = aContent->GetDocument();
|
||||||
|
if (nsnull != doc) {
|
||||||
|
docURL = doc->GetDocumentURL();
|
||||||
|
NS_RELEASE(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString absURLSpec;
|
||||||
|
nsresult rv = NS_MakeAbsoluteURL(docURL, base, href, absURLSpec);
|
||||||
|
NS_IF_RELEASE(docURL);
|
||||||
|
|
||||||
|
nsLinkState state;
|
||||||
|
if (NS_OK == linkHandler->GetLinkState(absURLSpec, state)) {
|
||||||
|
switch (state) {
|
||||||
|
case eLinkState_Unvisited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::link);
|
||||||
|
break;
|
||||||
|
case eLinkState_Visited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::visited);
|
||||||
|
break;
|
||||||
|
case eLinkState_OutOfDate:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::outOfDate);
|
||||||
|
break;
|
||||||
|
case eLinkState_Active:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::active);
|
||||||
|
break;
|
||||||
|
case eLinkState_Hover:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::hover);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(linkHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = PR_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +289,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
||||||
|
|
||||||
nsCSSSelector* selector = rule->FirstSelector();
|
nsCSSSelector* selector = rule->FirstSelector();
|
||||||
if (SelectorMatches(selector, aContent)) {
|
if (SelectorMatches(aPresContext, selector, aContent)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
nsIFrame* frame = aParentFrame;
|
nsIFrame* frame = aParentFrame;
|
||||||
nsIContentPtr lastContent;
|
nsIContentPtr lastContent;
|
||||||
@@ -245,7 +297,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
@@ -295,7 +347,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
|
|||||||
@@ -753,7 +753,7 @@ static PRBool IsPseudoClass(const nsString& aBuffer)
|
|||||||
return (aBuffer.EqualsIgnoreCase("link") ||
|
return (aBuffer.EqualsIgnoreCase("link") ||
|
||||||
aBuffer.EqualsIgnoreCase("visited") ||
|
aBuffer.EqualsIgnoreCase("visited") ||
|
||||||
aBuffer.EqualsIgnoreCase("hover") ||
|
aBuffer.EqualsIgnoreCase("hover") ||
|
||||||
aBuffer.EqualsIgnoreCase("out-of-date") || // XXX ??
|
aBuffer.EqualsIgnoreCase("out-of-date") || // our extension
|
||||||
aBuffer.EqualsIgnoreCase("active"));
|
aBuffer.EqualsIgnoreCase("active"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void nsCSSSelector::Set(const nsString& aTag, const nsString& aID,
|
|||||||
mClass = NS_NewAtom(aClass);
|
mClass = NS_NewAtom(aClass);
|
||||||
}
|
}
|
||||||
if (0 < aPseudoClass.Length()) {
|
if (0 < aPseudoClass.Length()) {
|
||||||
aPseudoClass.ToLowerCase(buffer);
|
aPseudoClass.ToUpperCase(buffer);
|
||||||
mPseudoClass = NS_NewAtom(buffer);
|
mPseudoClass = NS_NewAtom(buffer);
|
||||||
if (nsnull == mTag) {
|
if (nsnull == mTag) {
|
||||||
mTag = nsHTMLAtoms::a;
|
mTag = nsHTMLAtoms::a;
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
#include "nsICSSStyleRule.h"
|
#include "nsICSSStyleRule.h"
|
||||||
#include "nsIHTMLContent.h"
|
#include "nsIHTMLContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIPresContext.h"
|
||||||
|
#include "nsILinkHandler.h"
|
||||||
|
#include "nsHTMLAtoms.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsIPtr.h"
|
#include "nsIPtr.h"
|
||||||
@@ -54,7 +58,8 @@ public:
|
|||||||
NS_IMETHOD_(nsrefcnt) AddRef();
|
NS_IMETHOD_(nsrefcnt) AddRef();
|
||||||
NS_IMETHOD_(nsrefcnt) Release();
|
NS_IMETHOD_(nsrefcnt) Release();
|
||||||
|
|
||||||
virtual PRBool SelectorMatches(nsCSSSelector* aSelector,
|
virtual PRBool SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector,
|
||||||
nsIContent* aContent);
|
nsIContent* aContent);
|
||||||
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
virtual PRInt32 RulesMatching(nsIPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
@@ -186,17 +191,64 @@ nsresult CSSStyleSheetImpl::QueryInterface(const nsIID& aIID,
|
|||||||
return NS_NOINTERFACE;
|
return NS_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool CSSStyleSheetImpl::SelectorMatches(nsCSSSelector* aSelector, nsIContent* aContent)
|
PRBool CSSStyleSheetImpl::SelectorMatches(nsIPresContext* aPresContext,
|
||||||
|
nsCSSSelector* aSelector, nsIContent* aContent)
|
||||||
{
|
{
|
||||||
PRBool result = PR_FALSE;
|
PRBool result = PR_FALSE;
|
||||||
|
nsIAtom* contentTag = aContent->GetTag();
|
||||||
|
|
||||||
if ((nsnull == aSelector->mTag) || (aSelector->mTag == aContent->GetTag())) {
|
if ((nsnull == aSelector->mTag) || (aSelector->mTag == contentTag)) {
|
||||||
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID)) {
|
if ((nsnull != aSelector->mClass) || (nsnull != aSelector->mID) ||
|
||||||
|
(nsnull != aSelector->mPseudoClass)) {
|
||||||
nsIHTMLContentPtr htmlContent;
|
nsIHTMLContentPtr htmlContent;
|
||||||
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, htmlContent.Query())) {
|
||||||
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
if ((nsnull == aSelector->mClass) || (aSelector->mClass == htmlContent->GetClass())) {
|
||||||
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
if ((nsnull == aSelector->mID) || (aSelector->mID == htmlContent->GetID())) {
|
||||||
result = PR_TRUE;
|
if ((contentTag == nsHTMLAtoms::a) && (nsnull != aSelector->mPseudoClass)) {
|
||||||
|
// test link state
|
||||||
|
nsILinkHandler* linkHandler;
|
||||||
|
|
||||||
|
if (NS_OK == aPresContext->GetLinkHandler(&linkHandler)) {
|
||||||
|
nsAutoString base, href; // XXX base??
|
||||||
|
htmlContent->GetAttribute("href", href);
|
||||||
|
|
||||||
|
nsIURL* docURL = nsnull;
|
||||||
|
nsIDocument* doc = aContent->GetDocument();
|
||||||
|
if (nsnull != doc) {
|
||||||
|
docURL = doc->GetDocumentURL();
|
||||||
|
NS_RELEASE(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString absURLSpec;
|
||||||
|
nsresult rv = NS_MakeAbsoluteURL(docURL, base, href, absURLSpec);
|
||||||
|
NS_IF_RELEASE(docURL);
|
||||||
|
|
||||||
|
nsLinkState state;
|
||||||
|
if (NS_OK == linkHandler->GetLinkState(absURLSpec, state)) {
|
||||||
|
switch (state) {
|
||||||
|
case eLinkState_Unvisited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::link);
|
||||||
|
break;
|
||||||
|
case eLinkState_Visited:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::visited);
|
||||||
|
break;
|
||||||
|
case eLinkState_OutOfDate:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::outOfDate);
|
||||||
|
break;
|
||||||
|
case eLinkState_Active:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::active);
|
||||||
|
break;
|
||||||
|
case eLinkState_Hover:
|
||||||
|
result = PRBool (aSelector->mPseudoClass == nsHTMLAtoms::hover);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NS_RELEASE(linkHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = PR_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +289,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
nsICSSStyleRulePtr rule = (nsICSSStyleRule*)mRules->ElementAt(index);
|
||||||
|
|
||||||
nsCSSSelector* selector = rule->FirstSelector();
|
nsCSSSelector* selector = rule->FirstSelector();
|
||||||
if (SelectorMatches(selector, aContent)) {
|
if (SelectorMatches(aPresContext, selector, aContent)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
nsIFrame* frame = aParentFrame;
|
nsIFrame* frame = aParentFrame;
|
||||||
nsIContentPtr lastContent;
|
nsIContentPtr lastContent;
|
||||||
@@ -245,7 +297,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
@@ -295,7 +347,7 @@ PRInt32 CSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext,
|
|||||||
nsIContentPtr content;
|
nsIContentPtr content;
|
||||||
frame->GetContent(content.AssignRef());
|
frame->GetContent(content.AssignRef());
|
||||||
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
if ((content != lastContent) && // skip pseudo frames (actually we're skipping pseudo's parent, but same result)
|
||||||
SelectorMatches(selector, content)) {
|
SelectorMatches(aPresContext, selector, content)) {
|
||||||
selector = selector->mNext;
|
selector = selector->mNext;
|
||||||
}
|
}
|
||||||
frame->GetGeometricParent(frame);
|
frame->GetGeometricParent(frame);
|
||||||
|
|||||||
Reference in New Issue
Block a user