summaryrefslogtreecommitdiffstats
path: root/WebCore/css/CSSSelector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/css/CSSSelector.cpp')
-rw-r--r--WebCore/css/CSSSelector.cpp304
1 files changed, 218 insertions, 86 deletions
diff --git a/WebCore/css/CSSSelector.cpp b/WebCore/css/CSSSelector.cpp
index 9053596..17fbd64 100644
--- a/WebCore/css/CSSSelector.cpp
+++ b/WebCore/css/CSSSelector.cpp
@@ -4,6 +4,7 @@
* 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
* 2001-2003 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2002, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Smith (catfish.man@gmail.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,7 +25,14 @@
#include "config.h"
#include "CSSSelector.h"
+#include "wtf/Assertions.h"
+#include "HTMLNames.h"
+
+#include <wtf/StdLibExtras.h>
+
namespace WebCore {
+
+using namespace HTMLNames;
unsigned int CSSSelector::specificity()
{
@@ -50,8 +58,8 @@ unsigned int CSSSelector::specificity()
break;
}
- if (m_tagHistory)
- s += m_tagHistory->specificity();
+ if (CSSSelector* tagHistory = this->tagHistory())
+ s += tagHistory->specificity();
// make sure it doesn't overflow
return s & 0xffffff;
@@ -62,75 +70,77 @@ void CSSSelector::extractPseudoType() const
if (m_match != PseudoClass && m_match != PseudoElement)
return;
- static AtomicString active("active");
- static AtomicString after("after");
- static AtomicString anyLink("-webkit-any-link");
- static AtomicString autofill("-webkit-autofill");
- static AtomicString before("before");
- static AtomicString checked("checked");
- static AtomicString fileUploadButton("-webkit-file-upload-button");
- static AtomicString disabled("disabled");
- static AtomicString readOnly("read-only");
- static AtomicString readWrite("read-write");
- static AtomicString drag("-webkit-drag");
- static AtomicString dragAlias("-khtml-drag"); // was documented with this name in Apple documentation, so keep an alias
- static AtomicString empty("empty");
- static AtomicString enabled("enabled");
- static AtomicString firstChild("first-child");
- static AtomicString firstLetter("first-letter");
- static AtomicString firstLine("first-line");
- static AtomicString firstOfType("first-of-type");
- static AtomicString fullPageMedia("-webkit-full-page-media");
- static AtomicString nthChild("nth-child(");
- static AtomicString nthOfType("nth-of-type(");
- static AtomicString nthLastChild("nth-last-child(");
- static AtomicString nthLastOfType("nth-last-of-type(");
- static AtomicString focus("focus");
- static AtomicString hover("hover");
- static AtomicString indeterminate("indeterminate");
- static AtomicString inputPlaceholder("-webkit-input-placeholder");
- static AtomicString lastChild("last-child");
- static AtomicString lastOfType("last-of-type");
- static AtomicString link("link");
- static AtomicString lang("lang(");
- static AtomicString mediaControlsPanel("-webkit-media-controls-panel");
- static AtomicString mediaControlsMuteButton("-webkit-media-controls-mute-button");
- static AtomicString mediaControlsPlayButton("-webkit-media-controls-play-button");
- static AtomicString mediaControlsTimeDisplay("-webkit-media-controls-time-display");
- static AtomicString mediaControlsTimeline("-webkit-media-controls-timeline");
- static AtomicString mediaControlsSeekBackButton("-webkit-media-controls-seek-back-button");
- static AtomicString mediaControlsSeekForwardButton("-webkit-media-controls-seek-forward-button");
- static AtomicString mediaControlsFullscreenButton("-webkit-media-controls-fullscreen-button");
- static AtomicString notStr("not(");
- static AtomicString onlyChild("only-child");
- static AtomicString onlyOfType("only-of-type");
- static AtomicString resizer("-webkit-resizer");
- static AtomicString root("root");
- static AtomicString scrollbar("-webkit-scrollbar");
- static AtomicString scrollbarButton("-webkit-scrollbar-button");
- static AtomicString scrollbarCorner("-webkit-scrollbar-corner");
- static AtomicString scrollbarThumb("-webkit-scrollbar-thumb");
- static AtomicString scrollbarTrack("-webkit-scrollbar-track");
- static AtomicString scrollbarTrackPiece("-webkit-scrollbar-track-piece");
- static AtomicString searchCancelButton("-webkit-search-cancel-button");
- static AtomicString searchDecoration("-webkit-search-decoration");
- static AtomicString searchResultsDecoration("-webkit-search-results-decoration");
- static AtomicString searchResultsButton("-webkit-search-results-button");
- static AtomicString selection("selection");
- static AtomicString sliderThumb("-webkit-slider-thumb");
- static AtomicString target("target");
- static AtomicString visited("visited");
- static AtomicString windowInactive("window-inactive");
- static AtomicString decrement("decrement");
- static AtomicString increment("increment");
- static AtomicString start("start");
- static AtomicString end("end");
- static AtomicString horizontal("horizontal");
- static AtomicString vertical("vertical");
- static AtomicString doubleButton("double-button");
- static AtomicString singleButton("single-button");
- static AtomicString noButton("no-button");
- static AtomicString cornerPresent("corner-present");
+ DEFINE_STATIC_LOCAL(AtomicString, active, ("active"));
+ DEFINE_STATIC_LOCAL(AtomicString, after, ("after"));
+ DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link"));
+ DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill"));
+ DEFINE_STATIC_LOCAL(AtomicString, before, ("before"));
+ DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked"));
+ DEFINE_STATIC_LOCAL(AtomicString, fileUploadButton, ("-webkit-file-upload-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled"));
+ DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only"));
+ DEFINE_STATIC_LOCAL(AtomicString, readWrite, ("read-write"));
+ DEFINE_STATIC_LOCAL(AtomicString, drag, ("-webkit-drag"));
+ DEFINE_STATIC_LOCAL(AtomicString, dragAlias, ("-khtml-drag")); // was documented with this name in Apple documentation, so keep an alia
+ DEFINE_STATIC_LOCAL(AtomicString, empty, ("empty"));
+ DEFINE_STATIC_LOCAL(AtomicString, enabled, ("enabled"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstChild, ("first-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstLetter, ("first-letter"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstLine, ("first-line"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstOfType, ("first-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, fullPageMedia, ("-webkit-full-page-media"));
+ DEFINE_STATIC_LOCAL(AtomicString, nthChild, ("nth-child("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthOfType, ("nth-of-type("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthLastChild, ("nth-last-child("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthLastOfType, ("nth-last-of-type("));
+ DEFINE_STATIC_LOCAL(AtomicString, focus, ("focus"));
+ DEFINE_STATIC_LOCAL(AtomicString, hover, ("hover"));
+ DEFINE_STATIC_LOCAL(AtomicString, indeterminate, ("indeterminate"));
+ DEFINE_STATIC_LOCAL(AtomicString, inputPlaceholder, ("-webkit-input-placeholder"));
+ DEFINE_STATIC_LOCAL(AtomicString, lastChild, ("last-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, lastOfType, ("last-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, link, ("link"));
+ DEFINE_STATIC_LOCAL(AtomicString, lang, ("lang("));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPanel, ("-webkit-media-controls-panel"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsMuteButton, ("-webkit-media-controls-mute-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPlayButton, ("-webkit-media-controls-play-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeline, ("-webkit-media-controls-timeline"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekBackButton, ("-webkit-media-controls-seek-back-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekForwardButton, ("-webkit-media-controls-seek-forward-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsFullscreenButton, ("-webkit-media-controls-fullscreen-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimelineContainer, ("-webkit-media-controls-timeline-container"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsCurrentTimeDisplay, ("-webkit-media-controls-current-time-display"));
+ DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeRemainingDisplay, ("-webkit-media-controls-time-remaining-display"));
+ DEFINE_STATIC_LOCAL(AtomicString, notStr, ("not("));
+ DEFINE_STATIC_LOCAL(AtomicString, onlyChild, ("only-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer"));
+ DEFINE_STATIC_LOCAL(AtomicString, root, ("root"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbar, ("-webkit-scrollbar"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarButton, ("-webkit-scrollbar-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarCorner, ("-webkit-scrollbar-corner"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarThumb, ("-webkit-scrollbar-thumb"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrack, ("-webkit-scrollbar-track"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrackPiece, ("-webkit-scrollbar-track-piece"));
+ DEFINE_STATIC_LOCAL(AtomicString, searchCancelButton, ("-webkit-search-cancel-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, searchDecoration, ("-webkit-search-decoration"));
+ DEFINE_STATIC_LOCAL(AtomicString, searchResultsDecoration, ("-webkit-search-results-decoration"));
+ DEFINE_STATIC_LOCAL(AtomicString, searchResultsButton, ("-webkit-search-results-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection"));
+ DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb"));
+ DEFINE_STATIC_LOCAL(AtomicString, target, ("target"));
+ DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited"));
+ DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive"));
+ DEFINE_STATIC_LOCAL(AtomicString, decrement, ("decrement"));
+ DEFINE_STATIC_LOCAL(AtomicString, increment, ("increment"));
+ DEFINE_STATIC_LOCAL(AtomicString, start, ("start"));
+ DEFINE_STATIC_LOCAL(AtomicString, end, ("end"));
+ DEFINE_STATIC_LOCAL(AtomicString, horizontal, ("horizontal"));
+ DEFINE_STATIC_LOCAL(AtomicString, vertical, ("vertical"));
+ DEFINE_STATIC_LOCAL(AtomicString, doubleButton, ("double-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, singleButton, ("single-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present"));
bool element = false; // pseudo-element
bool compat = false; // single colon compatbility mode
@@ -211,8 +221,11 @@ void CSSSelector::extractPseudoType() const
} else if (m_value == mediaControlsPlayButton) {
m_pseudoType = PseudoMediaControlsPlayButton;
element = true;
- } else if (m_value == mediaControlsTimeDisplay) {
- m_pseudoType = PseudoMediaControlsTimeDisplay;
+ } else if (m_value == mediaControlsCurrentTimeDisplay) {
+ m_pseudoType = PseudoMediaControlsCurrentTimeDisplay;
+ element = true;
+ } else if (m_value == mediaControlsTimeRemainingDisplay) {
+ m_pseudoType = PseudoMediaControlsTimeRemainingDisplay;
element = true;
} else if (m_value == mediaControlsTimeline) {
m_pseudoType = PseudoMediaControlsTimeline;
@@ -226,6 +239,9 @@ void CSSSelector::extractPseudoType() const
} else if (m_value == mediaControlsFullscreenButton) {
m_pseudoType = PseudoMediaControlsFullscreenButton;
element = true;
+ } else if (m_value == mediaControlsTimelineContainer) {
+ m_pseudoType = PseudoMediaControlsTimelineContainer;
+ element = true;
} else if (m_value == notStr)
m_pseudoType = PseudoNot;
else if (m_value == nthChild)
@@ -322,14 +338,14 @@ bool CSSSelector::operator==(const CSSSelector& other)
const CSSSelector* sel2 = &other;
while (sel1 && sel2) {
- if (sel1->m_tag != sel2->m_tag || sel1->m_attr != sel2->m_attr ||
+ if (sel1->m_tag != sel2->m_tag || sel1->attribute() != sel2->attribute() ||
sel1->relation() != sel2->relation() || sel1->m_match != sel2->m_match ||
sel1->m_value != sel2->m_value ||
sel1->pseudoType() != sel2->pseudoType() ||
- sel1->m_argument != sel2->m_argument)
+ sel1->argument() != sel2->argument())
return false;
- sel1 = sel1->m_tagHistory;
- sel2 = sel2->m_tagHistory;
+ sel1 = sel1->tagHistory();
+ sel2 = sel2->tagHistory();
}
if (sel1 || sel2)
@@ -363,11 +379,15 @@ String CSSSelector::selectorText() const
str += ":";
str += cs->m_value;
if (cs->pseudoType() == PseudoNot) {
- if (CSSSelector* subSel = cs->m_simpleSelector)
+ if (CSSSelector* subSel = cs->simpleSelector())
str += subSel->selectorText();
str += ")";
- } else if (cs->pseudoType() == PseudoLang) {
- str += cs->m_argument;
+ } else if (cs->pseudoType() == PseudoLang
+ || cs->pseudoType() == PseudoNthChild
+ || cs->pseudoType() == PseudoNthLastChild
+ || cs->pseudoType() == PseudoNthOfType
+ || cs->pseudoType() == PseudoNthLastOfType) {
+ str += cs->argument();
str += ")";
}
} else if (cs->m_match == CSSSelector::PseudoElement) {
@@ -375,10 +395,10 @@ String CSSSelector::selectorText() const
str += cs->m_value;
} else if (cs->hasAttribute()) {
str += "[";
- const AtomicString& prefix = cs->m_attr.prefix();
+ const AtomicString& prefix = cs->attribute().prefix();
if (!prefix.isNull())
str += prefix + "|";
- str += cs->m_attr.localName();
+ str += cs->attribute().localName();
switch (cs->m_match) {
case CSSSelector::Exact:
str += "=";
@@ -411,13 +431,13 @@ String CSSSelector::selectorText() const
str += "\"]";
}
}
- if (cs->relation() != CSSSelector::SubSelector || !cs->m_tagHistory)
+ if (cs->relation() != CSSSelector::SubSelector || !cs->tagHistory())
break;
- cs = cs->m_tagHistory;
+ cs = cs->tagHistory();
}
- if (cs->m_tagHistory) {
- String tagHistoryText = cs->m_tagHistory->selectorText();
+ if (CSSSelector* tagHistory = cs->tagHistory()) {
+ String tagHistoryText = tagHistory->selectorText();
if (cs->relation() == CSSSelector::DirectAdjacent)
str = tagHistoryText + " + " + str;
else if (cs->relation() == CSSSelector::IndirectAdjacent)
@@ -431,5 +451,117 @@ String CSSSelector::selectorText() const
return str;
}
+
+void CSSSelector::setTagHistory(CSSSelector* tagHistory)
+{
+ if (m_hasRareData)
+ m_data.m_rareData->m_tagHistory.set(tagHistory);
+ else
+ m_data.m_tagHistory = tagHistory;
+}
+
+const QualifiedName& CSSSelector::attribute() const
+{
+ switch (m_match) {
+ case Id:
+ return idAttr;
+ case Class:
+ return classAttr;
+ default:
+ return m_hasRareData ? m_data.m_rareData->m_attribute : anyQName();
+ }
+}
+void CSSSelector::setAttribute(const QualifiedName& value)
+{
+ createRareData();
+ m_data.m_rareData->m_attribute = value;
+}
+
+void CSSSelector::setArgument(const AtomicString& value)
+{
+ createRareData();
+ m_data.m_rareData->m_argument = value;
+}
+
+void CSSSelector::setSimpleSelector(CSSSelector* value)
+{
+ createRareData();
+ m_data.m_rareData->m_simpleSelector.set(value);
+}
+
+bool CSSSelector::parseNth()
+{
+ if (!m_hasRareData)
+ return false;
+ if (m_parsedNth)
+ return true;
+ m_parsedNth = m_data.m_rareData->parseNth();
+ return m_parsedNth;
+}
+
+bool CSSSelector::matchNth(int count)
+{
+ ASSERT(m_hasRareData);
+ return m_data.m_rareData->matchNth(count);
+}
+
+// a helper function for parsing nth-arguments
+bool CSSSelector::RareData::parseNth()
+{
+ const String& argument = m_argument;
+
+ if (argument.isEmpty())
+ return false;
+
+ m_a = 0;
+ m_b = 0;
+ if (argument == "odd") {
+ m_a = 2;
+ m_b = 1;
+ } else if (argument == "even") {
+ m_a = 2;
+ m_b = 0;
+ } else {
+ int n = argument.find('n');
+ if (n != -1) {
+ if (argument[0] == '-') {
+ if (n == 1)
+ m_a = -1; // -n == -1n
+ else
+ m_a = argument.substring(0, n).toInt();
+ } else if (!n)
+ m_a = 1; // n == 1n
+ else
+ m_a = argument.substring(0, n).toInt();
+
+ int p = argument.find('+', n);
+ if (p != -1)
+ m_b = argument.substring(p + 1, argument.length() - p - 1).toInt();
+ else {
+ p = argument.find('-', n);
+ m_b = -argument.substring(p + 1, argument.length() - p - 1).toInt();
+ }
+ } else
+ m_b = argument.toInt();
+ }
+ return true;
+}
+
+// a helper function for checking nth-arguments
+bool CSSSelector::RareData::matchNth(int count)
+{
+ if (!m_a)
+ return count == m_b;
+ else if (m_a > 0) {
+ if (count < m_b)
+ return false;
+ return (count - m_b) % m_a == 0;
+ } else {
+ if (count > m_b)
+ return false;
+ return (m_b - count) % (-m_a) == 0;
+ }
+}
+
} // namespace WebCore