diff options
Diffstat (limited to 'WebCore/css/CSSSelector.cpp')
-rw-r--r-- | WebCore/css/CSSSelector.cpp | 304 |
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 |