WebCore/css/CSSSelector.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
       
     3  *               1999 Waldo Bastian (bastian@kde.org)
       
     4  *               2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
       
     5  *               2001-2003 Dirk Mueller (mueller@kde.org)
       
     6  * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
       
     7  * Copyright (C) 2008 David Smith (catfish.man@gmail.com)
       
     8  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     9  *
       
    10  * This library is free software; you can redistribute it and/or
       
    11  * modify it under the terms of the GNU Library General Public
       
    12  * License as published by the Free Software Foundation; either
       
    13  * version 2 of the License, or (at your option) any later version.
       
    14  *
       
    15  * This library is distributed in the hope that it will be useful,
       
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18  * Library General Public License for more details.
       
    19  *
       
    20  * You should have received a copy of the GNU Library General Public License
       
    21  * along with this library; see the file COPYING.LIB.  If not, write to
       
    22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    23  * Boston, MA 02110-1301, USA.
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "CSSSelector.h"
       
    28 
       
    29 #include "CSSOMUtils.h"
       
    30 #include "HTMLNames.h"
       
    31 #include <wtf/Assertions.h>
       
    32 #include <wtf/HashMap.h>
       
    33 #include <wtf/StdLibExtras.h>
       
    34 #include <wtf/Vector.h>
       
    35 
       
    36 namespace WebCore {
       
    37     
       
    38 using namespace HTMLNames;
       
    39 
       
    40 // A helper class to hold CSSSelectors.
       
    41 class CSSSelectorBag : public Noncopyable {
       
    42 public:
       
    43     ~CSSSelectorBag()
       
    44     {
       
    45         deleteAllValues(m_stack);
       
    46     }
       
    47 
       
    48     bool isEmpty() const
       
    49     {
       
    50         return m_stack.isEmpty();
       
    51     }
       
    52 
       
    53     void append(PassOwnPtr<CSSSelector> selector)
       
    54     {
       
    55         if (selector)
       
    56             m_stack.append(selector.leakPtr());
       
    57     }
       
    58 
       
    59     PassOwnPtr<CSSSelector> takeAny()
       
    60     {
       
    61         ASSERT(!isEmpty());
       
    62         OwnPtr<CSSSelector> selector = adoptPtr(m_stack.last());
       
    63         m_stack.removeLast();
       
    64         return selector.release();
       
    65     }
       
    66 
       
    67 private:
       
    68     Vector<CSSSelector*, 16> m_stack;
       
    69 };
       
    70 
       
    71 CSSSelector::~CSSSelector()
       
    72 {
       
    73     // We should avoid a recursive destructor call, which causes stack overflow
       
    74     // if CSS Selectors are deeply nested.
       
    75 
       
    76     // Early exit if we have already processed the children of this selector.
       
    77     if (m_hasRareData) {
       
    78         if (!m_data.m_rareData)
       
    79             return;
       
    80     } else if (!m_data.m_tagHistory)
       
    81         return;
       
    82 
       
    83     CSSSelectorBag selectorsToBeDeleted;
       
    84     if (m_hasRareData) {
       
    85         selectorsToBeDeleted.append(m_data.m_rareData->m_tagHistory.release());
       
    86         selectorsToBeDeleted.append(m_data.m_rareData->m_simpleSelector.release());
       
    87         delete m_data.m_rareData;
       
    88     } else
       
    89         selectorsToBeDeleted.append(adoptPtr(m_data.m_tagHistory));
       
    90 
       
    91     // Traverse the tree of CSSSelector and delete each CSSSelector iteratively.
       
    92     while (!selectorsToBeDeleted.isEmpty()) {
       
    93         OwnPtr<CSSSelector> selector(selectorsToBeDeleted.takeAny());
       
    94         ASSERT(selector);
       
    95         if (selector->m_hasRareData) {
       
    96             ASSERT(selector->m_data.m_rareData);
       
    97             selectorsToBeDeleted.append(selector->m_data.m_rareData->m_tagHistory.release());
       
    98             selectorsToBeDeleted.append(selector->m_data.m_rareData->m_simpleSelector.release());
       
    99             delete selector->m_data.m_rareData;
       
   100             // Clear the pointer so that a destructor of the selector, which is
       
   101             // about to be called, can know the children are already processed.
       
   102             selector->m_data.m_rareData = 0;
       
   103         } else {
       
   104             selectorsToBeDeleted.append(adoptPtr(selector->m_data.m_tagHistory));
       
   105             // Clear the pointer for the same reason.
       
   106             selector->m_data.m_tagHistory = 0;
       
   107         }
       
   108     }
       
   109 }
       
   110 
       
   111 unsigned int CSSSelector::specificity()
       
   112 {
       
   113     if (m_isForPage)
       
   114         return specificityForPage();
       
   115 
       
   116     // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
       
   117     // isn't quite correct.
       
   118     int s = (m_tag.localName() == starAtom ? 0 : 1);
       
   119     switch (m_match) {
       
   120         case Id:
       
   121             s += 0x10000;
       
   122             break;
       
   123         case Exact:
       
   124         case Class:
       
   125         case Set:
       
   126         case List:
       
   127         case Hyphen:
       
   128         case PseudoClass:
       
   129         case PseudoElement:
       
   130         case Contain:
       
   131         case Begin:
       
   132         case End:
       
   133             s += 0x100;
       
   134         case None:
       
   135             break;
       
   136     }
       
   137 
       
   138     // FIXME: Avoid recursive calls to prevent possible stack overflow.
       
   139     if (CSSSelector* tagHistory = this->tagHistory())
       
   140         s += tagHistory->specificity();
       
   141 
       
   142     // make sure it doesn't overflow
       
   143     return s & 0xffffff;
       
   144 }
       
   145 
       
   146 unsigned CSSSelector::specificityForPage()
       
   147 {
       
   148     // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context
       
   149     unsigned s = (m_tag.localName() == starAtom ? 0 : 4);
       
   150 
       
   151     switch (pseudoType()) {
       
   152     case PseudoFirstPage:
       
   153         s += 2;
       
   154         break;
       
   155     case PseudoLeftPage:
       
   156     case PseudoRightPage:
       
   157         s += 1;
       
   158         break;
       
   159     case PseudoNotParsed:
       
   160         break;
       
   161     default:
       
   162         ASSERT_NOT_REACHED();
       
   163     }
       
   164     return s;
       
   165 }
       
   166 
       
   167 PseudoId CSSSelector::pseudoId(PseudoType type)
       
   168 {
       
   169     switch (type) {
       
   170     case PseudoFirstLine:
       
   171         return FIRST_LINE;
       
   172     case PseudoFirstLetter:
       
   173         return FIRST_LETTER;
       
   174     case PseudoSelection:
       
   175         return SELECTION;
       
   176     case PseudoBefore:
       
   177         return BEFORE;
       
   178     case PseudoAfter:
       
   179         return AFTER;
       
   180     case PseudoFileUploadButton:
       
   181         return FILE_UPLOAD_BUTTON;
       
   182     case PseudoInputPlaceholder:
       
   183         return INPUT_PLACEHOLDER;
       
   184 #if ENABLE(INPUT_SPEECH)
       
   185     case PseudoInputSpeechButton:
       
   186         return INPUT_SPEECH_BUTTON;
       
   187 #endif
       
   188     case PseudoSliderThumb:
       
   189         return SLIDER_THUMB;
       
   190     case PseudoSearchCancelButton:
       
   191         return SEARCH_CANCEL_BUTTON;
       
   192     case PseudoSearchDecoration:
       
   193         return SEARCH_DECORATION;
       
   194     case PseudoSearchResultsDecoration:
       
   195         return SEARCH_RESULTS_DECORATION;
       
   196     case PseudoSearchResultsButton:
       
   197         return SEARCH_RESULTS_BUTTON;
       
   198     case PseudoMediaControlsPanel:
       
   199         return MEDIA_CONTROLS_PANEL;
       
   200     case PseudoMediaControlsMuteButton:
       
   201         return MEDIA_CONTROLS_MUTE_BUTTON;
       
   202     case PseudoMediaControlsPlayButton:
       
   203         return MEDIA_CONTROLS_PLAY_BUTTON;
       
   204     case PseudoMediaControlsTimelineContainer:
       
   205         return MEDIA_CONTROLS_TIMELINE_CONTAINER;
       
   206     case PseudoMediaControlsVolumeSliderContainer:
       
   207         return MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER;
       
   208     case PseudoMediaControlsCurrentTimeDisplay:
       
   209         return MEDIA_CONTROLS_CURRENT_TIME_DISPLAY;
       
   210     case PseudoMediaControlsTimeRemainingDisplay:
       
   211         return MEDIA_CONTROLS_TIME_REMAINING_DISPLAY;
       
   212     case PseudoMediaControlsTimeline:
       
   213         return MEDIA_CONTROLS_TIMELINE;
       
   214     case PseudoMediaControlsVolumeSlider:
       
   215         return MEDIA_CONTROLS_VOLUME_SLIDER;
       
   216     case PseudoMediaControlsVolumeSliderMuteButton:
       
   217         return MEDIA_CONTROLS_VOLUME_SLIDER_MUTE_BUTTON;
       
   218     case PseudoMediaControlsSeekBackButton:
       
   219         return MEDIA_CONTROLS_SEEK_BACK_BUTTON;
       
   220     case PseudoMediaControlsSeekForwardButton:
       
   221         return MEDIA_CONTROLS_SEEK_FORWARD_BUTTON;
       
   222     case PseudoMediaControlsRewindButton:
       
   223         return MEDIA_CONTROLS_REWIND_BUTTON;
       
   224     case PseudoMediaControlsReturnToRealtimeButton:
       
   225         return MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON;
       
   226     case PseudoMediaControlsToggleClosedCaptions:
       
   227         return MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON;
       
   228     case PseudoMediaControlsStatusDisplay:
       
   229         return MEDIA_CONTROLS_STATUS_DISPLAY;
       
   230     case PseudoMediaControlsFullscreenButton:
       
   231         return MEDIA_CONTROLS_FULLSCREEN_BUTTON;
       
   232     case PseudoScrollbar:
       
   233         return SCROLLBAR;
       
   234     case PseudoScrollbarButton:
       
   235         return SCROLLBAR_BUTTON;
       
   236     case PseudoScrollbarCorner:
       
   237         return SCROLLBAR_CORNER;
       
   238     case PseudoScrollbarThumb:
       
   239         return SCROLLBAR_THUMB;
       
   240     case PseudoScrollbarTrack:
       
   241         return SCROLLBAR_TRACK;
       
   242     case PseudoScrollbarTrackPiece:
       
   243         return SCROLLBAR_TRACK_PIECE;
       
   244     case PseudoResizer:
       
   245         return RESIZER;
       
   246     case PseudoInnerSpinButton:
       
   247         return INNER_SPIN_BUTTON;
       
   248     case PseudoOuterSpinButton:
       
   249         return OUTER_SPIN_BUTTON;
       
   250     case PseudoProgressBarValue:
       
   251 #if ENABLE(PROGRESS_TAG)
       
   252         return PROGRESS_BAR_VALUE;
       
   253 #else
       
   254         ASSERT_NOT_REACHED();
       
   255         return NOPSEUDO;
       
   256 #endif
       
   257 
       
   258 #if ENABLE(METER_TAG)
       
   259     case PseudoMeterHorizontalBar:
       
   260         return METER_HORIZONTAL_BAR;
       
   261     case PseudoMeterHorizontalOptimum:
       
   262         return METER_HORIZONTAL_OPTIMUM;
       
   263     case PseudoMeterHorizontalSuboptimal:
       
   264         return METER_HORIZONTAL_SUBOPTIMAL;
       
   265     case PseudoMeterHorizontalEvenLessGood:
       
   266         return METER_HORIZONTAL_EVEN_LESS_GOOD;
       
   267     case PseudoMeterVerticalBar:
       
   268         return METER_VERTICAL_BAR;
       
   269     case PseudoMeterVerticalOptimum:
       
   270         return METER_VERTICAL_OPTIMUM;
       
   271     case PseudoMeterVerticalSuboptimal:
       
   272         return METER_VERTICAL_SUBOPTIMAL;
       
   273     case PseudoMeterVerticalEvenLessGood:
       
   274         return METER_VERTICAL_EVEN_LESS_GOOD;
       
   275 #else
       
   276     case PseudoMeterHorizontalBar:
       
   277     case PseudoMeterHorizontalOptimum:
       
   278     case PseudoMeterHorizontalSuboptimal:
       
   279     case PseudoMeterHorizontalEvenLessGood:
       
   280     case PseudoMeterVerticalBar:
       
   281     case PseudoMeterVerticalOptimum:
       
   282     case PseudoMeterVerticalSuboptimal:
       
   283     case PseudoMeterVerticalEvenLessGood:
       
   284         ASSERT_NOT_REACHED();
       
   285         return NOPSEUDO;
       
   286 #endif
       
   287 
       
   288     case PseudoInputListButton:
       
   289 #if ENABLE(DATALIST)
       
   290         return INPUT_LIST_BUTTON;
       
   291 #endif
       
   292     case PseudoUnknown:
       
   293     case PseudoEmpty:
       
   294     case PseudoFirstChild:
       
   295     case PseudoFirstOfType:
       
   296     case PseudoLastChild:
       
   297     case PseudoLastOfType:
       
   298     case PseudoOnlyChild:
       
   299     case PseudoOnlyOfType:
       
   300     case PseudoNthChild:
       
   301     case PseudoNthOfType:
       
   302     case PseudoNthLastChild:
       
   303     case PseudoNthLastOfType:
       
   304     case PseudoLink:
       
   305     case PseudoVisited:
       
   306     case PseudoAnyLink:
       
   307     case PseudoAutofill:
       
   308     case PseudoHover:
       
   309     case PseudoDrag:
       
   310     case PseudoFocus:
       
   311     case PseudoActive:
       
   312     case PseudoChecked:
       
   313     case PseudoEnabled:
       
   314     case PseudoFullPageMedia:
       
   315     case PseudoDefault:
       
   316     case PseudoDisabled:
       
   317     case PseudoOptional:
       
   318     case PseudoRequired:
       
   319     case PseudoReadOnly:
       
   320     case PseudoReadWrite:
       
   321     case PseudoValid:
       
   322     case PseudoInvalid:
       
   323     case PseudoIndeterminate:
       
   324     case PseudoTarget:
       
   325     case PseudoLang:
       
   326     case PseudoNot:
       
   327     case PseudoRoot:
       
   328     case PseudoScrollbarBack:
       
   329     case PseudoScrollbarForward:
       
   330     case PseudoWindowInactive:
       
   331     case PseudoCornerPresent:
       
   332     case PseudoDecrement:
       
   333     case PseudoIncrement:
       
   334     case PseudoHorizontal:
       
   335     case PseudoVertical:
       
   336     case PseudoStart:
       
   337     case PseudoEnd:
       
   338     case PseudoDoubleButton:
       
   339     case PseudoSingleButton:
       
   340     case PseudoNoButton:
       
   341     case PseudoFirstPage:
       
   342     case PseudoLeftPage:
       
   343     case PseudoRightPage:
       
   344         return NOPSEUDO;
       
   345     case PseudoNotParsed:
       
   346         ASSERT_NOT_REACHED();
       
   347         return NOPSEUDO;
       
   348     }
       
   349 
       
   350     ASSERT_NOT_REACHED();
       
   351     return NOPSEUDO;
       
   352 }
       
   353 
       
   354 static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap()
       
   355 {
       
   356     DEFINE_STATIC_LOCAL(AtomicString, active, ("active"));
       
   357     DEFINE_STATIC_LOCAL(AtomicString, after, ("after"));
       
   358     DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link"));
       
   359     DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill"));
       
   360     DEFINE_STATIC_LOCAL(AtomicString, before, ("before"));
       
   361     DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked"));
       
   362     DEFINE_STATIC_LOCAL(AtomicString, fileUploadButton, ("-webkit-file-upload-button"));
       
   363 #if ENABLE(INPUT_SPEECH)
       
   364     DEFINE_STATIC_LOCAL(AtomicString, inputSpeechButton, ("-webkit-input-speech-button"));
       
   365 #endif
       
   366     DEFINE_STATIC_LOCAL(AtomicString, defaultString, ("default"));
       
   367     DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled"));
       
   368     DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only"));
       
   369     DEFINE_STATIC_LOCAL(AtomicString, readWrite, ("read-write"));
       
   370     DEFINE_STATIC_LOCAL(AtomicString, valid, ("valid"));
       
   371     DEFINE_STATIC_LOCAL(AtomicString, invalid, ("invalid"));
       
   372     DEFINE_STATIC_LOCAL(AtomicString, drag, ("-webkit-drag"));
       
   373     DEFINE_STATIC_LOCAL(AtomicString, dragAlias, ("-khtml-drag")); // was documented with this name in Apple documentation, so keep an alia
       
   374     DEFINE_STATIC_LOCAL(AtomicString, empty, ("empty"));
       
   375     DEFINE_STATIC_LOCAL(AtomicString, enabled, ("enabled"));
       
   376     DEFINE_STATIC_LOCAL(AtomicString, firstChild, ("first-child"));
       
   377     DEFINE_STATIC_LOCAL(AtomicString, firstLetter, ("first-letter"));
       
   378     DEFINE_STATIC_LOCAL(AtomicString, firstLine, ("first-line"));
       
   379     DEFINE_STATIC_LOCAL(AtomicString, firstOfType, ("first-of-type"));
       
   380     DEFINE_STATIC_LOCAL(AtomicString, fullPageMedia, ("-webkit-full-page-media"));
       
   381     DEFINE_STATIC_LOCAL(AtomicString, nthChild, ("nth-child("));
       
   382     DEFINE_STATIC_LOCAL(AtomicString, nthOfType, ("nth-of-type("));
       
   383     DEFINE_STATIC_LOCAL(AtomicString, nthLastChild, ("nth-last-child("));
       
   384     DEFINE_STATIC_LOCAL(AtomicString, nthLastOfType, ("nth-last-of-type("));
       
   385     DEFINE_STATIC_LOCAL(AtomicString, focus, ("focus"));
       
   386     DEFINE_STATIC_LOCAL(AtomicString, hover, ("hover"));
       
   387     DEFINE_STATIC_LOCAL(AtomicString, indeterminate, ("indeterminate"));
       
   388     DEFINE_STATIC_LOCAL(AtomicString, innerSpinButton, ("-webkit-inner-spin-button"));
       
   389 #if ENABLE(DATALIST)
       
   390     DEFINE_STATIC_LOCAL(AtomicString, inputListButton, ("-webkit-input-list-button"));
       
   391 #endif
       
   392     DEFINE_STATIC_LOCAL(AtomicString, inputPlaceholder, ("-webkit-input-placeholder"));
       
   393     DEFINE_STATIC_LOCAL(AtomicString, lastChild, ("last-child"));
       
   394     DEFINE_STATIC_LOCAL(AtomicString, lastOfType, ("last-of-type"));
       
   395     DEFINE_STATIC_LOCAL(AtomicString, link, ("link"));
       
   396     DEFINE_STATIC_LOCAL(AtomicString, lang, ("lang("));
       
   397     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPanel, ("-webkit-media-controls-panel"));
       
   398     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsMuteButton, ("-webkit-media-controls-mute-button"));
       
   399     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPlayButton, ("-webkit-media-controls-play-button"));
       
   400     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeline, ("-webkit-media-controls-timeline"));
       
   401     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSlider, ("-webkit-media-controls-volume-slider"));
       
   402     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSliderMuteButton, ("-webkit-media-controls-volume-slider-mute-button"));
       
   403     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekBackButton, ("-webkit-media-controls-seek-back-button"));
       
   404     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekForwardButton, ("-webkit-media-controls-seek-forward-button"));
       
   405     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsRewindButton, ("-webkit-media-controls-rewind-button"));
       
   406     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsReturnToRealtimeButton, ("-webkit-media-controls-return-to-realtime-button"));
       
   407     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsToggleClosedCaptionsButton, ("-webkit-media-controls-toggle-closed-captions-button"));
       
   408     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsStatusDisplay, ("-webkit-media-controls-status-display"));
       
   409     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsFullscreenButton, ("-webkit-media-controls-fullscreen-button"));
       
   410     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimelineContainer, ("-webkit-media-controls-timeline-container"));
       
   411     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSliderContainer, ("-webkit-media-controls-volume-slider-container"));
       
   412     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsCurrentTimeDisplay, ("-webkit-media-controls-current-time-display"));
       
   413     DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeRemainingDisplay, ("-webkit-media-controls-time-remaining-display"));
       
   414     DEFINE_STATIC_LOCAL(AtomicString, notStr, ("not("));
       
   415     DEFINE_STATIC_LOCAL(AtomicString, onlyChild, ("only-child"));
       
   416     DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type"));
       
   417     DEFINE_STATIC_LOCAL(AtomicString, optional, ("optional"));
       
   418     DEFINE_STATIC_LOCAL(AtomicString, outerSpinButton, ("-webkit-outer-spin-button"));
       
   419 #if ENABLE(PROGRESS_TAG)
       
   420     DEFINE_STATIC_LOCAL(AtomicString, progressBarValue, ("-webkit-progress-bar-value"));
       
   421 #endif
       
   422 
       
   423 #if ENABLE(METER_TAG)
       
   424     DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalBar, ("-webkit-meter-horizontal-bar"));
       
   425     DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalOptimumValue, ("-webkit-meter-horizontal-optimum-value"));
       
   426     DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalSuboptimalValue, ("-webkit-meter-horizontal-suboptimal-value"));
       
   427     DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalEvenLessGoodValue, ("-webkit-meter-horizontal-even-less-good-value"));
       
   428     DEFINE_STATIC_LOCAL(AtomicString, meterVerticalBar, ("-webkit-meter-vertical-bar"));
       
   429     DEFINE_STATIC_LOCAL(AtomicString, meterVerticalOptimumValue, ("-webkit-meter-vertical-optimum-value"));
       
   430     DEFINE_STATIC_LOCAL(AtomicString, meterVerticalSuboptimalValue, ("-webkit-meter-vertical-suboptimal-value"));
       
   431     DEFINE_STATIC_LOCAL(AtomicString, meterVerticalEvenLessGoodValue, ("-webkit-meter-vertical-even-less-good-value"));
       
   432 #endif
       
   433 
       
   434     DEFINE_STATIC_LOCAL(AtomicString, required, ("required"));
       
   435     DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer"));
       
   436     DEFINE_STATIC_LOCAL(AtomicString, root, ("root"));
       
   437     DEFINE_STATIC_LOCAL(AtomicString, scrollbar, ("-webkit-scrollbar"));
       
   438     DEFINE_STATIC_LOCAL(AtomicString, scrollbarButton, ("-webkit-scrollbar-button"));
       
   439     DEFINE_STATIC_LOCAL(AtomicString, scrollbarCorner, ("-webkit-scrollbar-corner"));
       
   440     DEFINE_STATIC_LOCAL(AtomicString, scrollbarThumb, ("-webkit-scrollbar-thumb"));
       
   441     DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrack, ("-webkit-scrollbar-track"));
       
   442     DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrackPiece, ("-webkit-scrollbar-track-piece"));
       
   443     DEFINE_STATIC_LOCAL(AtomicString, searchCancelButton, ("-webkit-search-cancel-button"));
       
   444     DEFINE_STATIC_LOCAL(AtomicString, searchDecoration, ("-webkit-search-decoration"));
       
   445     DEFINE_STATIC_LOCAL(AtomicString, searchResultsDecoration, ("-webkit-search-results-decoration"));
       
   446     DEFINE_STATIC_LOCAL(AtomicString, searchResultsButton, ("-webkit-search-results-button"));
       
   447     DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection"));
       
   448     DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb"));
       
   449     DEFINE_STATIC_LOCAL(AtomicString, target, ("target"));
       
   450     DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited"));
       
   451     DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive"));
       
   452     DEFINE_STATIC_LOCAL(AtomicString, decrement, ("decrement"));
       
   453     DEFINE_STATIC_LOCAL(AtomicString, increment, ("increment"));
       
   454     DEFINE_STATIC_LOCAL(AtomicString, start, ("start"));
       
   455     DEFINE_STATIC_LOCAL(AtomicString, end, ("end"));
       
   456     DEFINE_STATIC_LOCAL(AtomicString, horizontal, ("horizontal"));
       
   457     DEFINE_STATIC_LOCAL(AtomicString, vertical, ("vertical"));
       
   458     DEFINE_STATIC_LOCAL(AtomicString, doubleButton, ("double-button"));
       
   459     DEFINE_STATIC_LOCAL(AtomicString, singleButton, ("single-button"));
       
   460     DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button"));
       
   461     DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present"));
       
   462     // Paged Media pseudo-classes
       
   463     DEFINE_STATIC_LOCAL(AtomicString, firstPage, ("first"));
       
   464     DEFINE_STATIC_LOCAL(AtomicString, leftPage, ("left"));
       
   465     DEFINE_STATIC_LOCAL(AtomicString, rightPage, ("right"));
       
   466 
       
   467     static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0;
       
   468     if (!nameToPseudoType) {
       
   469         nameToPseudoType = new HashMap<AtomicStringImpl*, CSSSelector::PseudoType>;
       
   470         nameToPseudoType->set(active.impl(), CSSSelector::PseudoActive);
       
   471         nameToPseudoType->set(after.impl(), CSSSelector::PseudoAfter);
       
   472         nameToPseudoType->set(anyLink.impl(), CSSSelector::PseudoAnyLink);
       
   473         nameToPseudoType->set(autofill.impl(), CSSSelector::PseudoAutofill);
       
   474         nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore);
       
   475         nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked);
       
   476         nameToPseudoType->set(fileUploadButton.impl(), CSSSelector::PseudoFileUploadButton);
       
   477 #if ENABLE(INPUT_SPEECH)
       
   478         nameToPseudoType->set(inputSpeechButton.impl(), CSSSelector::PseudoInputSpeechButton);
       
   479 #endif
       
   480         nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault);
       
   481         nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled);
       
   482         nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly);
       
   483         nameToPseudoType->set(readWrite.impl(), CSSSelector::PseudoReadWrite);
       
   484         nameToPseudoType->set(valid.impl(), CSSSelector::PseudoValid);
       
   485         nameToPseudoType->set(invalid.impl(), CSSSelector::PseudoInvalid);
       
   486         nameToPseudoType->set(drag.impl(), CSSSelector::PseudoDrag);
       
   487         nameToPseudoType->set(dragAlias.impl(), CSSSelector::PseudoDrag);
       
   488         nameToPseudoType->set(enabled.impl(), CSSSelector::PseudoEnabled);
       
   489         nameToPseudoType->set(empty.impl(), CSSSelector::PseudoEmpty);
       
   490         nameToPseudoType->set(firstChild.impl(), CSSSelector::PseudoFirstChild);
       
   491         nameToPseudoType->set(fullPageMedia.impl(), CSSSelector::PseudoFullPageMedia);
       
   492 #if ENABLE(DATALIST)
       
   493         nameToPseudoType->set(inputListButton.impl(), CSSSelector::PseudoInputListButton);
       
   494 #endif
       
   495         nameToPseudoType->set(inputPlaceholder.impl(), CSSSelector::PseudoInputPlaceholder);
       
   496         nameToPseudoType->set(lastChild.impl(), CSSSelector::PseudoLastChild);
       
   497         nameToPseudoType->set(lastOfType.impl(), CSSSelector::PseudoLastOfType);
       
   498         nameToPseudoType->set(onlyChild.impl(), CSSSelector::PseudoOnlyChild);
       
   499         nameToPseudoType->set(onlyOfType.impl(), CSSSelector::PseudoOnlyOfType);
       
   500         nameToPseudoType->set(firstLetter.impl(), CSSSelector::PseudoFirstLetter);
       
   501         nameToPseudoType->set(firstLine.impl(), CSSSelector::PseudoFirstLine);
       
   502         nameToPseudoType->set(firstOfType.impl(), CSSSelector::PseudoFirstOfType);
       
   503         nameToPseudoType->set(focus.impl(), CSSSelector::PseudoFocus);
       
   504         nameToPseudoType->set(hover.impl(), CSSSelector::PseudoHover);
       
   505         nameToPseudoType->set(indeterminate.impl(), CSSSelector::PseudoIndeterminate);
       
   506         nameToPseudoType->set(innerSpinButton.impl(), CSSSelector::PseudoInnerSpinButton);
       
   507         nameToPseudoType->set(link.impl(), CSSSelector::PseudoLink);
       
   508         nameToPseudoType->set(lang.impl(), CSSSelector::PseudoLang);
       
   509         nameToPseudoType->set(mediaControlsPanel.impl(), CSSSelector::PseudoMediaControlsPanel);
       
   510         nameToPseudoType->set(mediaControlsMuteButton.impl(), CSSSelector::PseudoMediaControlsMuteButton);
       
   511         nameToPseudoType->set(mediaControlsPlayButton.impl(), CSSSelector::PseudoMediaControlsPlayButton);
       
   512         nameToPseudoType->set(mediaControlsCurrentTimeDisplay.impl(), CSSSelector::PseudoMediaControlsCurrentTimeDisplay);
       
   513         nameToPseudoType->set(mediaControlsTimeRemainingDisplay.impl(), CSSSelector::PseudoMediaControlsTimeRemainingDisplay);
       
   514         nameToPseudoType->set(mediaControlsTimeline.impl(), CSSSelector::PseudoMediaControlsTimeline);
       
   515         nameToPseudoType->set(mediaControlsVolumeSlider.impl(), CSSSelector::PseudoMediaControlsVolumeSlider);
       
   516         nameToPseudoType->set(mediaControlsVolumeSliderMuteButton.impl(), CSSSelector::PseudoMediaControlsVolumeSliderMuteButton);
       
   517         nameToPseudoType->set(mediaControlsSeekBackButton.impl(), CSSSelector::PseudoMediaControlsSeekBackButton);
       
   518         nameToPseudoType->set(mediaControlsSeekForwardButton.impl(), CSSSelector::PseudoMediaControlsSeekForwardButton);
       
   519         nameToPseudoType->set(mediaControlsRewindButton.impl(), CSSSelector::PseudoMediaControlsRewindButton);
       
   520         nameToPseudoType->set(mediaControlsReturnToRealtimeButton.impl(), CSSSelector::PseudoMediaControlsReturnToRealtimeButton);
       
   521         nameToPseudoType->set(mediaControlsToggleClosedCaptionsButton.impl(), CSSSelector::PseudoMediaControlsToggleClosedCaptions);
       
   522         nameToPseudoType->set(mediaControlsStatusDisplay.impl(), CSSSelector::PseudoMediaControlsStatusDisplay);
       
   523         nameToPseudoType->set(mediaControlsFullscreenButton.impl(), CSSSelector::PseudoMediaControlsFullscreenButton);
       
   524         nameToPseudoType->set(mediaControlsTimelineContainer.impl(), CSSSelector::PseudoMediaControlsTimelineContainer);
       
   525         nameToPseudoType->set(mediaControlsVolumeSliderContainer.impl(), CSSSelector::PseudoMediaControlsVolumeSliderContainer);
       
   526         nameToPseudoType->set(notStr.impl(), CSSSelector::PseudoNot);
       
   527         nameToPseudoType->set(nthChild.impl(), CSSSelector::PseudoNthChild);
       
   528         nameToPseudoType->set(nthOfType.impl(), CSSSelector::PseudoNthOfType);
       
   529         nameToPseudoType->set(nthLastChild.impl(), CSSSelector::PseudoNthLastChild);
       
   530         nameToPseudoType->set(nthLastOfType.impl(), CSSSelector::PseudoNthLastOfType);
       
   531         nameToPseudoType->set(outerSpinButton.impl(), CSSSelector::PseudoOuterSpinButton);
       
   532 #if ENABLE(PROGRESS_TAG)
       
   533         nameToPseudoType->set(progressBarValue.impl(), CSSSelector::PseudoProgressBarValue);
       
   534 #endif
       
   535 #if ENABLE(METER_TAG)
       
   536         nameToPseudoType->set(meterHorizontalBar.impl(), CSSSelector::PseudoMeterHorizontalBar);
       
   537         nameToPseudoType->set(meterHorizontalOptimumValue.impl(), CSSSelector::PseudoMeterHorizontalOptimum);
       
   538         nameToPseudoType->set(meterHorizontalSuboptimalValue.impl(), CSSSelector::PseudoMeterHorizontalSuboptimal);
       
   539         nameToPseudoType->set(meterHorizontalEvenLessGoodValue.impl(), CSSSelector::PseudoMeterHorizontalEvenLessGood);
       
   540         nameToPseudoType->set(meterVerticalBar.impl(), CSSSelector::PseudoMeterVerticalBar);
       
   541         nameToPseudoType->set(meterVerticalOptimumValue.impl(), CSSSelector::PseudoMeterVerticalOptimum);
       
   542         nameToPseudoType->set(meterVerticalSuboptimalValue.impl(), CSSSelector::PseudoMeterVerticalSuboptimal);
       
   543         nameToPseudoType->set(meterVerticalEvenLessGoodValue.impl(), CSSSelector::PseudoMeterVerticalEvenLessGood);
       
   544 #endif
       
   545         nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot);
       
   546         nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive);
       
   547         nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement);
       
   548         nameToPseudoType->set(increment.impl(), CSSSelector::PseudoIncrement);
       
   549         nameToPseudoType->set(start.impl(), CSSSelector::PseudoStart);
       
   550         nameToPseudoType->set(end.impl(), CSSSelector::PseudoEnd);
       
   551         nameToPseudoType->set(horizontal.impl(), CSSSelector::PseudoHorizontal);
       
   552         nameToPseudoType->set(vertical.impl(), CSSSelector::PseudoVertical);
       
   553         nameToPseudoType->set(doubleButton.impl(), CSSSelector::PseudoDoubleButton);
       
   554         nameToPseudoType->set(singleButton.impl(), CSSSelector::PseudoSingleButton);
       
   555         nameToPseudoType->set(noButton.impl(), CSSSelector::PseudoNoButton);
       
   556         nameToPseudoType->set(optional.impl(), CSSSelector::PseudoOptional);
       
   557         nameToPseudoType->set(required.impl(), CSSSelector::PseudoRequired);
       
   558         nameToPseudoType->set(resizer.impl(), CSSSelector::PseudoResizer);
       
   559         nameToPseudoType->set(scrollbar.impl(), CSSSelector::PseudoScrollbar);
       
   560         nameToPseudoType->set(scrollbarButton.impl(), CSSSelector::PseudoScrollbarButton);
       
   561         nameToPseudoType->set(scrollbarCorner.impl(), CSSSelector::PseudoScrollbarCorner);
       
   562         nameToPseudoType->set(scrollbarThumb.impl(), CSSSelector::PseudoScrollbarThumb);
       
   563         nameToPseudoType->set(scrollbarTrack.impl(), CSSSelector::PseudoScrollbarTrack);
       
   564         nameToPseudoType->set(scrollbarTrackPiece.impl(), CSSSelector::PseudoScrollbarTrackPiece);
       
   565         nameToPseudoType->set(cornerPresent.impl(), CSSSelector::PseudoCornerPresent);
       
   566         nameToPseudoType->set(searchCancelButton.impl(), CSSSelector::PseudoSearchCancelButton);
       
   567         nameToPseudoType->set(searchDecoration.impl(), CSSSelector::PseudoSearchDecoration);
       
   568         nameToPseudoType->set(searchResultsDecoration.impl(), CSSSelector::PseudoSearchResultsDecoration);
       
   569         nameToPseudoType->set(searchResultsButton.impl(), CSSSelector::PseudoSearchResultsButton);
       
   570         nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection);
       
   571         nameToPseudoType->set(sliderThumb.impl(), CSSSelector::PseudoSliderThumb);
       
   572         nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget);
       
   573         nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited);
       
   574         nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage);
       
   575         nameToPseudoType->set(leftPage.impl(), CSSSelector::PseudoLeftPage);
       
   576         nameToPseudoType->set(rightPage.impl(), CSSSelector::PseudoRightPage);
       
   577     }
       
   578     return nameToPseudoType;
       
   579 }
       
   580 
       
   581 CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name)
       
   582 {
       
   583     if (name.isNull())
       
   584         return PseudoUnknown;
       
   585     HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap();
       
   586     HashMap<AtomicStringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl());
       
   587     return slot == nameToPseudoType->end() ? PseudoUnknown : slot->second;
       
   588 }
       
   589 
       
   590 void CSSSelector::extractPseudoType() const
       
   591 {
       
   592     if (m_match != PseudoClass && m_match != PseudoElement && m_match != PagePseudoClass)
       
   593         return;
       
   594 
       
   595     m_pseudoType = parsePseudoType(m_value);
       
   596 
       
   597     bool element = false; // pseudo-element
       
   598     bool compat = false; // single colon compatbility mode
       
   599     bool isPagePseudoClass = false; // Page pseudo-class
       
   600 
       
   601     switch (m_pseudoType) {
       
   602     case PseudoAfter:
       
   603     case PseudoBefore:
       
   604     case PseudoFirstLetter:
       
   605     case PseudoFirstLine:
       
   606         compat = true;
       
   607     case PseudoFileUploadButton:
       
   608     case PseudoInputListButton:
       
   609     case PseudoInputPlaceholder:
       
   610 #if ENABLE(INPUT_SPEECH)
       
   611     case PseudoInputSpeechButton:
       
   612 #endif
       
   613     case PseudoInnerSpinButton:
       
   614     case PseudoMediaControlsPanel:
       
   615     case PseudoMediaControlsMuteButton:
       
   616     case PseudoMediaControlsPlayButton:
       
   617     case PseudoMediaControlsCurrentTimeDisplay:
       
   618     case PseudoMediaControlsTimeRemainingDisplay:
       
   619     case PseudoMediaControlsTimeline:
       
   620     case PseudoMediaControlsVolumeSlider:
       
   621     case PseudoMediaControlsVolumeSliderMuteButton:
       
   622     case PseudoMediaControlsSeekBackButton:
       
   623     case PseudoMediaControlsSeekForwardButton:
       
   624     case PseudoMediaControlsRewindButton:
       
   625     case PseudoMediaControlsReturnToRealtimeButton:
       
   626     case PseudoMediaControlsToggleClosedCaptions:
       
   627     case PseudoMediaControlsStatusDisplay:
       
   628     case PseudoMediaControlsFullscreenButton:
       
   629     case PseudoMediaControlsTimelineContainer:
       
   630     case PseudoMediaControlsVolumeSliderContainer:
       
   631     case PseudoMeterHorizontalBar:
       
   632     case PseudoMeterHorizontalOptimum:
       
   633     case PseudoMeterHorizontalSuboptimal:
       
   634     case PseudoMeterHorizontalEvenLessGood:
       
   635     case PseudoMeterVerticalBar:
       
   636     case PseudoMeterVerticalOptimum:
       
   637     case PseudoMeterVerticalSuboptimal:
       
   638     case PseudoMeterVerticalEvenLessGood:
       
   639     case PseudoOuterSpinButton:
       
   640     case PseudoProgressBarValue:
       
   641     case PseudoResizer:
       
   642     case PseudoScrollbar:
       
   643     case PseudoScrollbarCorner:
       
   644     case PseudoScrollbarButton:
       
   645     case PseudoScrollbarThumb:
       
   646     case PseudoScrollbarTrack:
       
   647     case PseudoScrollbarTrackPiece:
       
   648     case PseudoSearchCancelButton:
       
   649     case PseudoSearchDecoration:
       
   650     case PseudoSearchResultsDecoration:
       
   651     case PseudoSearchResultsButton:
       
   652     case PseudoSelection:
       
   653     case PseudoSliderThumb:
       
   654         element = true;
       
   655         break;
       
   656     case PseudoUnknown:
       
   657     case PseudoEmpty:
       
   658     case PseudoFirstChild:
       
   659     case PseudoFirstOfType:
       
   660     case PseudoLastChild:
       
   661     case PseudoLastOfType:
       
   662     case PseudoOnlyChild:
       
   663     case PseudoOnlyOfType:
       
   664     case PseudoNthChild:
       
   665     case PseudoNthOfType:
       
   666     case PseudoNthLastChild:
       
   667     case PseudoNthLastOfType:
       
   668     case PseudoLink:
       
   669     case PseudoVisited:
       
   670     case PseudoAnyLink:
       
   671     case PseudoAutofill:
       
   672     case PseudoHover:
       
   673     case PseudoDrag:
       
   674     case PseudoFocus:
       
   675     case PseudoActive:
       
   676     case PseudoChecked:
       
   677     case PseudoEnabled:
       
   678     case PseudoFullPageMedia:
       
   679     case PseudoDefault:
       
   680     case PseudoDisabled:
       
   681     case PseudoOptional:
       
   682     case PseudoRequired:
       
   683     case PseudoReadOnly:
       
   684     case PseudoReadWrite:
       
   685     case PseudoValid:
       
   686     case PseudoInvalid:
       
   687     case PseudoIndeterminate:
       
   688     case PseudoTarget:
       
   689     case PseudoLang:
       
   690     case PseudoNot:
       
   691     case PseudoRoot:
       
   692     case PseudoScrollbarBack:
       
   693     case PseudoScrollbarForward:
       
   694     case PseudoWindowInactive:
       
   695     case PseudoCornerPresent:
       
   696     case PseudoDecrement:
       
   697     case PseudoIncrement:
       
   698     case PseudoHorizontal:
       
   699     case PseudoVertical:
       
   700     case PseudoStart:
       
   701     case PseudoEnd:
       
   702     case PseudoDoubleButton:
       
   703     case PseudoSingleButton:
       
   704     case PseudoNoButton:
       
   705     case PseudoNotParsed:
       
   706         break;
       
   707     case PseudoFirstPage:
       
   708     case PseudoLeftPage:
       
   709     case PseudoRightPage:
       
   710         isPagePseudoClass = true;
       
   711         break;
       
   712     }
       
   713 
       
   714     bool matchPagePseudoClass = (m_match == PagePseudoClass);
       
   715     if (matchPagePseudoClass != isPagePseudoClass)
       
   716         m_pseudoType = PseudoUnknown;
       
   717     else if (m_match == PseudoClass && element) {
       
   718         if (!compat)
       
   719             m_pseudoType = PseudoUnknown;
       
   720         else
       
   721            m_match = PseudoElement;
       
   722     } else if (m_match == PseudoElement && !element)
       
   723         m_pseudoType = PseudoUnknown;
       
   724 }
       
   725 
       
   726 bool CSSSelector::operator==(const CSSSelector& other)
       
   727 {
       
   728     const CSSSelector* sel1 = this;
       
   729     const CSSSelector* sel2 = &other;
       
   730 
       
   731     while (sel1 && sel2) {
       
   732         if (sel1->m_tag != sel2->m_tag || sel1->attribute() != sel2->attribute() ||
       
   733              sel1->relation() != sel2->relation() || sel1->m_match != sel2->m_match ||
       
   734              sel1->m_value != sel2->m_value ||
       
   735              sel1->pseudoType() != sel2->pseudoType() ||
       
   736              sel1->argument() != sel2->argument())
       
   737             return false;
       
   738         sel1 = sel1->tagHistory();
       
   739         sel2 = sel2->tagHistory();
       
   740     }
       
   741 
       
   742     if (sel1 || sel2)
       
   743         return false;
       
   744 
       
   745     return true;
       
   746 }
       
   747 
       
   748 String CSSSelector::selectorText() const
       
   749 {
       
   750     String str = "";
       
   751 
       
   752     const AtomicString& prefix = m_tag.prefix();
       
   753     const AtomicString& localName = m_tag.localName();
       
   754     if (m_match == CSSSelector::None || !prefix.isNull() || localName != starAtom) {
       
   755         if (prefix.isNull())
       
   756             str = localName;
       
   757         else
       
   758             str = prefix + "|" + localName;
       
   759     }
       
   760 
       
   761     const CSSSelector* cs = this;
       
   762     while (true) {
       
   763         if (cs->m_match == CSSSelector::Id) {
       
   764             str += "#";
       
   765             serializeIdentifier(cs->m_value, str);
       
   766         } else if (cs->m_match == CSSSelector::Class) {
       
   767             str += ".";
       
   768             serializeIdentifier(cs->m_value, str);
       
   769         } else if (cs->m_match == CSSSelector::PseudoClass || cs->m_match == CSSSelector::PagePseudoClass) {
       
   770             str += ":";
       
   771             str += cs->m_value;
       
   772             if (cs->pseudoType() == PseudoNot) {
       
   773                 if (CSSSelector* subSel = cs->simpleSelector())
       
   774                     str += subSel->selectorText();
       
   775                 str += ")";
       
   776             } else if (cs->pseudoType() == PseudoLang
       
   777                     || cs->pseudoType() == PseudoNthChild
       
   778                     || cs->pseudoType() == PseudoNthLastChild
       
   779                     || cs->pseudoType() == PseudoNthOfType
       
   780                     || cs->pseudoType() == PseudoNthLastOfType) {
       
   781                 str += cs->argument();
       
   782                 str += ")";
       
   783             }
       
   784         } else if (cs->m_match == CSSSelector::PseudoElement) {
       
   785             str += "::";
       
   786             str += cs->m_value;
       
   787         } else if (cs->hasAttribute()) {
       
   788             str += "[";
       
   789             const AtomicString& prefix = cs->attribute().prefix();
       
   790             if (!prefix.isNull())
       
   791                 str += prefix + "|";
       
   792             str += cs->attribute().localName();
       
   793             switch (cs->m_match) {
       
   794                 case CSSSelector::Exact:
       
   795                     str += "=";
       
   796                     break;
       
   797                 case CSSSelector::Set:
       
   798                     // set has no operator or value, just the attrName
       
   799                     str += "]";
       
   800                     break;
       
   801                 case CSSSelector::List:
       
   802                     str += "~=";
       
   803                     break;
       
   804                 case CSSSelector::Hyphen:
       
   805                     str += "|=";
       
   806                     break;
       
   807                 case CSSSelector::Begin:
       
   808                     str += "^=";
       
   809                     break;
       
   810                 case CSSSelector::End:
       
   811                     str += "$=";
       
   812                     break;
       
   813                 case CSSSelector::Contain:
       
   814                     str += "*=";
       
   815                     break;
       
   816                 default:
       
   817                     break;
       
   818             }
       
   819             if (cs->m_match != CSSSelector::Set) {
       
   820                 serializeString(cs->m_value, str);
       
   821                 str += "]";
       
   822             }
       
   823         }
       
   824         if (cs->relation() != CSSSelector::SubSelector || !cs->tagHistory())
       
   825             break;
       
   826         cs = cs->tagHistory();
       
   827     }
       
   828 
       
   829     if (CSSSelector* tagHistory = cs->tagHistory()) {
       
   830         String tagHistoryText = tagHistory->selectorText();
       
   831         if (cs->relation() == CSSSelector::DirectAdjacent)
       
   832             str = tagHistoryText + " + " + str;
       
   833         else if (cs->relation() == CSSSelector::IndirectAdjacent)
       
   834             str = tagHistoryText + " ~ " + str;
       
   835         else if (cs->relation() == CSSSelector::Child)
       
   836             str = tagHistoryText + " > " + str;
       
   837         else
       
   838             // Descendant
       
   839             str = tagHistoryText + " " + str;
       
   840     }
       
   841 
       
   842     return str;
       
   843 }
       
   844     
       
   845 void CSSSelector::setTagHistory(CSSSelector* tagHistory) 
       
   846 { 
       
   847     if (m_hasRareData) 
       
   848         m_data.m_rareData->m_tagHistory.set(tagHistory); 
       
   849     else 
       
   850         m_data.m_tagHistory = tagHistory; 
       
   851 }
       
   852 
       
   853 const QualifiedName& CSSSelector::attribute() const
       
   854 { 
       
   855     switch (m_match) {
       
   856     case Id:
       
   857         return idAttr;
       
   858     case Class:
       
   859         return classAttr;
       
   860     default:
       
   861         return m_hasRareData ? m_data.m_rareData->m_attribute : anyQName();
       
   862     }
       
   863 }
       
   864 
       
   865 void CSSSelector::setAttribute(const QualifiedName& value) 
       
   866 { 
       
   867     createRareData(); 
       
   868     m_data.m_rareData->m_attribute = value; 
       
   869 }
       
   870     
       
   871 void CSSSelector::setArgument(const AtomicString& value) 
       
   872 { 
       
   873     createRareData(); 
       
   874     m_data.m_rareData->m_argument = value; 
       
   875 }
       
   876 
       
   877 void CSSSelector::setSimpleSelector(CSSSelector* value)
       
   878 {
       
   879     createRareData(); 
       
   880     m_data.m_rareData->m_simpleSelector.set(value); 
       
   881 }
       
   882 
       
   883 bool CSSSelector::parseNth()
       
   884 {
       
   885     if (!m_hasRareData)
       
   886         return false;
       
   887     if (m_parsedNth)
       
   888         return true;
       
   889     m_parsedNth = m_data.m_rareData->parseNth();
       
   890     return m_parsedNth;
       
   891 }
       
   892 
       
   893 bool CSSSelector::matchNth(int count)
       
   894 {
       
   895     ASSERT(m_hasRareData);
       
   896     return m_data.m_rareData->matchNth(count);
       
   897 }
       
   898 
       
   899 bool CSSSelector::isSimple() const
       
   900 {
       
   901     if (simpleSelector() || tagHistory() || matchesPseudoElement())
       
   902         return false;
       
   903 
       
   904     int numConditions = 0;
       
   905 
       
   906     // hasTag() cannot be be used here because namespace may not be nullAtom.
       
   907     // Example:
       
   908     //     @namespace "http://www.w3.org/2000/svg";
       
   909     //     svg:not(:root) { ...
       
   910     if (m_tag != starAtom)
       
   911         numConditions++;
       
   912 
       
   913     if (m_match == Id || m_match == Class || m_match == PseudoClass)
       
   914         numConditions++;
       
   915 
       
   916     if (m_hasRareData && m_data.m_rareData->m_attribute != anyQName())
       
   917         numConditions++;
       
   918 
       
   919     // numConditions is 0 for a universal selector.
       
   920     // numConditions is 1 for other simple selectors.
       
   921     return numConditions <= 1;
       
   922 }
       
   923 
       
   924 // a helper function for parsing nth-arguments
       
   925 bool CSSSelector::RareData::parseNth()
       
   926 {
       
   927     String argument = m_argument.lower();
       
   928     
       
   929     if (argument.isEmpty())
       
   930         return false;
       
   931     
       
   932     m_a = 0;
       
   933     m_b = 0;
       
   934     if (argument == "odd") {
       
   935         m_a = 2;
       
   936         m_b = 1;
       
   937     } else if (argument == "even") {
       
   938         m_a = 2;
       
   939         m_b = 0;
       
   940     } else {
       
   941         int n = argument.find('n');
       
   942         if (n != -1) {
       
   943             if (argument[0] == '-') {
       
   944                 if (n == 1)
       
   945                     m_a = -1; // -n == -1n
       
   946                 else
       
   947                     m_a = argument.substring(0, n).toInt();
       
   948             } else if (!n)
       
   949                 m_a = 1; // n == 1n
       
   950             else
       
   951                 m_a = argument.substring(0, n).toInt();
       
   952             
       
   953             int p = argument.find('+', n);
       
   954             if (p != -1)
       
   955                 m_b = argument.substring(p + 1, argument.length() - p - 1).toInt();
       
   956             else {
       
   957                 p = argument.find('-', n);
       
   958                 if (p != -1)
       
   959                     m_b = -argument.substring(p + 1, argument.length() - p - 1).toInt();
       
   960             }
       
   961         } else
       
   962             m_b = argument.toInt();
       
   963     }
       
   964     return true;
       
   965 }
       
   966 
       
   967 // a helper function for checking nth-arguments
       
   968 bool CSSSelector::RareData::matchNth(int count)
       
   969 {
       
   970     if (!m_a)
       
   971         return count == m_b;
       
   972     else if (m_a > 0) {
       
   973         if (count < m_b)
       
   974             return false;
       
   975         return (count - m_b) % m_a == 0;
       
   976     } else {
       
   977         if (count > m_b)
       
   978             return false;
       
   979         return (m_b - count) % (-m_a) == 0;
       
   980     }
       
   981 }
       
   982 
       
   983 } // namespace WebCore