Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999-2003 Lars Knoll (knoll (at) kde.org)
      3  *               1999 Waldo Bastian (bastian (at) kde.org)
      4  * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  */
     21 
     22 #ifndef CSSSelector_h
     23 #define CSSSelector_h
     24 
     25 #include "QualifiedName.h"
     26 #include <wtf/Noncopyable.h>
     27 #include <wtf/OwnPtr.h>
     28 
     29 namespace WebCore {
     30 
     31     // this class represents a selector for a StyleRule
     32     class CSSSelector : public Noncopyable {
     33     public:
     34         CSSSelector()
     35             : m_tag(anyQName())
     36             , m_relation(Descendant)
     37             , m_match(None)
     38             , m_pseudoType(PseudoNotParsed)
     39             , m_parsedNth(false)
     40             , m_isLastInSelectorList(false)
     41             , m_hasRareData(false)
     42         {
     43         }
     44 
     45         CSSSelector(const QualifiedName& qName)
     46             : m_tag(qName)
     47             , m_relation(Descendant)
     48             , m_match(None)
     49             , m_pseudoType(PseudoNotParsed)
     50             , m_parsedNth(false)
     51             , m_isLastInSelectorList(false)
     52             , m_hasRareData(false)
     53         {
     54         }
     55 
     56         ~CSSSelector()
     57         {
     58             if (m_hasRareData)
     59                 delete m_data.m_rareData;
     60             else
     61                 delete m_data.m_tagHistory;
     62         }
     63 
     64         /**
     65          * Re-create selector text from selector's data
     66          */
     67         String selectorText() const;
     68 
     69         // checks if the 2 selectors (including sub selectors) agree.
     70         bool operator==(const CSSSelector&);
     71 
     72         // tag == -1 means apply to all elements (Selector = *)
     73 
     74         unsigned specificity();
     75 
     76         /* how the attribute value has to match.... Default is Exact */
     77         enum Match {
     78             None = 0,
     79             Id,
     80             Class,
     81             Exact,
     82             Set,
     83             List,
     84             Hyphen,
     85             PseudoClass,
     86             PseudoElement,
     87             Contain,   // css3: E[foo*="bar"]
     88             Begin,     // css3: E[foo^="bar"]
     89             End        // css3: E[foo$="bar"]
     90         };
     91 
     92         enum Relation {
     93             Descendant = 0,
     94             Child,
     95             DirectAdjacent,
     96             IndirectAdjacent,
     97             SubSelector
     98         };
     99 
    100         enum PseudoType {
    101             PseudoNotParsed = 0,
    102             PseudoUnknown,
    103             PseudoEmpty,
    104             PseudoFirstChild,
    105             PseudoFirstOfType,
    106             PseudoLastChild,
    107             PseudoLastOfType,
    108             PseudoOnlyChild,
    109             PseudoOnlyOfType,
    110             PseudoFirstLine,
    111             PseudoFirstLetter,
    112             PseudoNthChild,
    113             PseudoNthOfType,
    114             PseudoNthLastChild,
    115             PseudoNthLastOfType,
    116             PseudoLink,
    117             PseudoVisited,
    118             PseudoAnyLink,
    119             PseudoAutofill,
    120             PseudoHover,
    121             PseudoDrag,
    122             PseudoFocus,
    123             PseudoActive,
    124             PseudoChecked,
    125             PseudoEnabled,
    126             PseudoFullPageMedia,
    127             PseudoDefault,
    128             PseudoDisabled,
    129             PseudoInputPlaceholder,
    130             PseudoOptional,
    131             PseudoRequired,
    132             PseudoReadOnly,
    133             PseudoReadWrite,
    134             PseudoValid,
    135             PseudoInvalid,
    136             PseudoIndeterminate,
    137             PseudoTarget,
    138             PseudoBefore,
    139             PseudoAfter,
    140             PseudoLang,
    141             PseudoNot,
    142             PseudoResizer,
    143             PseudoRoot,
    144             PseudoScrollbar,
    145             PseudoScrollbarBack,
    146             PseudoScrollbarButton,
    147             PseudoScrollbarCorner,
    148             PseudoScrollbarForward,
    149             PseudoScrollbarThumb,
    150             PseudoScrollbarTrack,
    151             PseudoScrollbarTrackPiece,
    152             PseudoWindowInactive,
    153             PseudoCornerPresent,
    154             PseudoDecrement,
    155             PseudoIncrement,
    156             PseudoHorizontal,
    157             PseudoVertical,
    158             PseudoStart,
    159             PseudoEnd,
    160             PseudoDoubleButton,
    161             PseudoSingleButton,
    162             PseudoNoButton,
    163             PseudoSelection,
    164             PseudoFileUploadButton,
    165             PseudoSliderThumb,
    166             PseudoSearchCancelButton,
    167             PseudoSearchDecoration,
    168             PseudoSearchResultsDecoration,
    169             PseudoSearchResultsButton,
    170             PseudoMediaControlsPanel,
    171             PseudoMediaControlsMuteButton,
    172             PseudoMediaControlsPlayButton,
    173             PseudoMediaControlsTimelineContainer,
    174             PseudoMediaControlsVolumeSliderContainer,
    175             PseudoMediaControlsCurrentTimeDisplay,
    176             PseudoMediaControlsTimeRemainingDisplay,
    177             PseudoMediaControlsToggleClosedCaptions,
    178             PseudoMediaControlsTimeline,
    179             PseudoMediaControlsVolumeSlider,
    180             PseudoMediaControlsSeekBackButton,
    181             PseudoMediaControlsSeekForwardButton,
    182             PseudoMediaControlsRewindButton,
    183             PseudoMediaControlsReturnToRealtimeButton,
    184             PseudoMediaControlsStatusDisplay,
    185             PseudoMediaControlsFullscreenButton,
    186             PseudoInputListButton,
    187             PseudoInnerSpinButton,
    188             PseudoOuterSpinButton,
    189         };
    190 
    191         PseudoType pseudoType() const
    192         {
    193             if (m_pseudoType == PseudoNotParsed)
    194                 extractPseudoType();
    195             return static_cast<PseudoType>(m_pseudoType);
    196         }
    197 
    198         CSSSelector* tagHistory() const { return m_hasRareData ? m_data.m_rareData->m_tagHistory.get() : m_data.m_tagHistory; }
    199         void setTagHistory(CSSSelector* tagHistory);
    200 
    201         bool hasTag() const { return m_tag != anyQName(); }
    202         bool hasAttribute() const { return m_match == Id || m_match == Class || (m_hasRareData && m_data.m_rareData->m_attribute != anyQName()); }
    203 
    204         const QualifiedName& attribute() const;
    205         const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; }
    206         CSSSelector* simpleSelector() const { return m_hasRareData ? m_data.m_rareData->m_simpleSelector.get() : 0; }
    207 
    208         void setAttribute(const QualifiedName& value);
    209         void setArgument(const AtomicString& value);
    210         void setSimpleSelector(CSSSelector* value);
    211 
    212         bool parseNth();
    213         bool matchNth(int count);
    214 
    215         Relation relation() const { return static_cast<Relation>(m_relation); }
    216 
    217         bool isLastInSelectorList() const { return m_isLastInSelectorList; }
    218         void setLastInSelectorList() { m_isLastInSelectorList = true; }
    219 
    220         mutable AtomicString m_value;
    221         QualifiedName m_tag;
    222 
    223         unsigned m_relation           : 3; // enum Relation
    224         mutable unsigned m_match      : 4; // enum Match
    225         mutable unsigned m_pseudoType : 8; // PseudoType
    226 
    227     private:
    228         bool m_parsedNth              : 1; // Used for :nth-*
    229         bool m_isLastInSelectorList   : 1;
    230         bool m_hasRareData            : 1;
    231 
    232         void extractPseudoType() const;
    233 
    234         struct RareData : Noncopyable {
    235             RareData(CSSSelector* tagHistory)
    236                 : m_tagHistory(tagHistory)
    237                 , m_simpleSelector(0)
    238                 , m_attribute(anyQName())
    239                 , m_argument(nullAtom)
    240                 , m_a(0)
    241                 , m_b(0)
    242             {
    243             }
    244 
    245             bool parseNth();
    246             bool matchNth(int count);
    247 
    248             OwnPtr<CSSSelector> m_tagHistory;
    249             OwnPtr<CSSSelector> m_simpleSelector; // Used for :not.
    250             QualifiedName m_attribute; // used for attribute selector
    251             AtomicString m_argument; // Used for :contains, :lang and :nth-*
    252             int m_a; // Used for :nth-*
    253             int m_b; // Used for :nth-*
    254         };
    255 
    256         void createRareData()
    257         {
    258             if (m_hasRareData)
    259                 return;
    260             m_data.m_rareData = new RareData(m_data.m_tagHistory);
    261             m_hasRareData = true;
    262         }
    263 
    264         union DataUnion {
    265             DataUnion() : m_tagHistory(0) { }
    266             CSSSelector* m_tagHistory;
    267             RareData* m_rareData;
    268         } m_data;
    269     };
    270 
    271 } // namespace WebCore
    272 
    273 #endif // CSSSelector_h
    274