1 /*
2  * This file is part of the CSS implementation for KDE.
3  *
4  * Copyright 1999-2003 Lars Knoll (knoll@kde.org)
5  * Copyright 1999 Waldo Bastian (bastian@kde.org)
6  * Copyright 2002 Apple Computer, Inc.
7  * Copyright 2004 Allan Sandfeld Jensen (kde@carewolf.com)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25 #ifndef _CSS_BASE_H
26 #define _CSS_BASE_H
27 
28 #include "misc/AtomicString.h"
29 #include "dom/dom_misc.h"
30 #include "xml/dom_nodeimpl.h"
31 #include "misc/shared.h"
32 #include "misc/enum.h"
33 
34 #include <QDate>
35 
36 namespace DOM
37 {
38 
39 class StyleSheetImpl;
40 class MediaList;
41 
42 class CSSSelector;
43 class CSSProperty;
44 class CSSValueImpl;
45 
46 // this class represents a selector for a StyleRule
47 class CSSSelector
48 {
49 public:
CSSSelector()50     CSSSelector()
51         : tagHistory(nullptr), simpleSelector(nullptr), relation(Descendant),
52           match(None), pseudoId(0), _pseudoType(PseudoNotParsed)
53     {
54         tagLocalName = LocalName::fromId(anyLocalName);
55         tagNamespace = NamespaceName::fromId(anyNamespace);
56         attrLocalName = LocalName::fromId(0);
57         attrNamespace = NamespaceName::fromId(0);
58     }
59 
~CSSSelector()60     ~CSSSelector()
61     {
62         delete tagHistory;
63         delete simpleSelector;
64     }
65 
66     /**
67      * Print debug output for this selector
68      */
69     void print();
70 
71     /**
72      * Re-create selector text from selector's data
73      */
74     DOMString selectorText() const;
75 
76     // checks if the 2 selectors (including sub selectors) agree.
77     bool operator == (const CSSSelector &other) const;
78 
79     // tag == -1 means apply to all elements (Selector = *)
80 
81     unsigned int specificity() const;
82 
83     /* how the attribute value has to match.... Default is Exact */
84     enum Match {
85         None = 0,
86         Id,
87         Exact,
88         Set,
89         Class,
90         List,
91         Hyphen,
92         PseudoClass,
93         PseudoElement,
94         Contain,   // css3: E[foo*="bar"]
95         Begin,     // css3: E[foo^="bar"]
96         End        // css3: E[foo$="bar"]
97     };
98 
99     enum Relation {
100         Descendant = 0,
101         Child,
102         DirectAdjacent,
103         IndirectAdjacent,
104         SubSelector
105     };
106 
107     enum PseudoType {
108         PseudoNotParsed = 0,
109         PseudoOther,
110         PseudoEmpty,
111         PseudoFirstChild,
112         PseudoLastChild,
113         PseudoNthChild,
114         PseudoNthLastChild,
115         PseudoOnlyChild,
116         PseudoFirstOfType,
117         PseudoLastOfType,
118         PseudoNthOfType,
119         PseudoNthLastOfType,
120         PseudoOnlyOfType,
121         PseudoLink,
122         PseudoVisited,
123         PseudoHover,
124         PseudoFocus,
125         PseudoActive,
126         PseudoTarget,
127         PseudoLang,
128         PseudoNot,
129         PseudoContains,
130         PseudoRoot,
131         PseudoEnabled,
132         PseudoDisabled,
133         PseudoDefault,
134         PseudoReadOnly,
135         PseudoReadWrite,
136         PseudoChecked,
137         PseudoIndeterminate,
138 // pseudo-elements:
139         // inherited:
140         PseudoFirstLine,
141         PseudoFirstLetter,
142         PseudoSelection,
143         // generated:
144         PseudoBefore,
145         PseudoAfter,
146         PseudoMarker,
147         PseudoReplaced
148     };
149 
pseudoType()150     PseudoType pseudoType() const
151     {
152         if (_pseudoType == PseudoNotParsed) {
153             extractPseudoType();
154         }
155         return KDE_CAST_BF_ENUM(PseudoType, _pseudoType);
156     }
157 
158     mutable khtml::AtomicString value;
159     CSSSelector *tagHistory;
160     CSSSelector *simpleSelector; // Used by :not
161     DOM::DOMString string_arg; // Used by :contains, :lang and :nth-*
162     LocalName attrLocalName;
163     NamespaceName attrNamespace;
164     LocalName tagLocalName;
165     NamespaceName tagNamespace;
166 
167     KDE_BF_ENUM(Relation) relation     : 3;
168     mutable KDE_BF_ENUM(Match)   match         : 4;
169     unsigned int pseudoId : 4;
170     mutable KDE_BF_ENUM(PseudoType) _pseudoType : 6;
171 
172 private:
173     void extractPseudoType() const;
174 };
175 
176 // a style class which has a parent (almost all have)
177 class StyleBaseImpl : public khtml::TreeShared<StyleBaseImpl>
178 {
179 public:
StyleBaseImpl()180     StyleBaseImpl()
181     {
182         m_parent = nullptr;
183         hasInlinedDecl = false;
184         strictParsing = true;
185         multiLength = false;
186     }
StyleBaseImpl(StyleBaseImpl * p)187     StyleBaseImpl(StyleBaseImpl *p)
188     {
189         m_parent = p; hasInlinedDecl = false;
190         strictParsing = (m_parent ? m_parent->useStrictParsing() : true);
191         multiLength = false;
192     }
193 
~StyleBaseImpl()194     virtual ~StyleBaseImpl() {}
195 
196     // returns the url of the style sheet this object belongs to
197     // not const
198     QUrl baseURL();
199 
isStyleSheet()200     virtual bool isStyleSheet() const
201     {
202         return false;
203     }
isCSSStyleSheet()204     virtual bool isCSSStyleSheet() const
205     {
206         return false;
207     }
isStyleSheetList()208     virtual bool isStyleSheetList() const
209     {
210         return false;
211     }
isMediaList()212     virtual bool isMediaList() const
213     {
214         return false;
215     }
isRuleList()216     virtual bool isRuleList() const
217     {
218         return false;
219     }
isRule()220     virtual bool isRule() const
221     {
222         return false;
223     }
isStyleRule()224     virtual bool isStyleRule() const
225     {
226         return false;
227     }
isCharsetRule()228     virtual bool isCharsetRule() const
229     {
230         return false;
231     }
isImportRule()232     virtual bool isImportRule() const
233     {
234         return false;
235     }
isMediaRule()236     virtual bool isMediaRule() const
237     {
238         return false;
239     }
isFontFaceRule()240     virtual bool isFontFaceRule() const
241     {
242         return false;
243     }
isPageRule()244     virtual bool isPageRule() const
245     {
246         return false;
247     }
isUnknownRule()248     virtual bool isUnknownRule() const
249     {
250         return false;
251     }
isStyleDeclaration()252     virtual bool isStyleDeclaration() const
253     {
254         return false;
255     }
isValue()256     virtual bool isValue() const
257     {
258         return false;
259     }
isPrimitiveValue()260     virtual bool isPrimitiveValue() const
261     {
262         return false;
263     }
isValueList()264     virtual bool isValueList() const
265     {
266         return false;
267     }
isValueCustom()268     virtual bool isValueCustom() const
269     {
270         return false;
271     }
272 
setParent(StyleBaseImpl * parent)273     void setParent(StyleBaseImpl *parent)
274     {
275         m_parent = parent;
276     }
277 
278     static void setParsedValue(int propId, const CSSValueImpl *parsedValue,
279                                bool important, QList<CSSProperty *> *propList);
280 
281     virtual bool parseString(const DOMString &/*cssString*/, bool = false)
282     {
283         return false;
284     }
285 
286     // verifies if the resource chain is fully loaded,
287     // and in the affirmative, notifies the owner document
288     virtual void checkLoaded() const;
289     // makes sure the resource chain is considered 'Pending' by the owner document
290     virtual void checkPending() const;
291 
setStrictParsing(bool b)292     void setStrictParsing(bool b)
293     {
294         strictParsing = b;
295     }
useStrictParsing()296     bool useStrictParsing() const
297     {
298         return strictParsing;
299     }
300 
301     // not const
302     StyleSheetImpl *stylesheet();
303 
304 protected:
305     bool hasInlinedDecl : 1;
306     bool strictParsing : 1;
307     bool multiLength : 1;
308 };
309 
310 // a style class which has a list of children (StyleSheets for example)
311 class StyleListImpl : public StyleBaseImpl
312 {
313 public:
StyleListImpl()314     StyleListImpl() : StyleBaseImpl()
315     {
316         m_lstChildren = nullptr;
317     }
StyleListImpl(StyleBaseImpl * parent)318     StyleListImpl(StyleBaseImpl *parent) : StyleBaseImpl(parent)
319     {
320         m_lstChildren = nullptr;
321     }
322     virtual ~StyleListImpl();
323 
length()324     unsigned long length() const
325     {
326         return m_lstChildren->count();
327     }
item(unsigned long num)328     StyleBaseImpl *item(unsigned long num) const
329     {
330         return num < length() ? m_lstChildren->at(num) : nullptr;
331     }
332 
append(StyleBaseImpl * item)333     void append(StyleBaseImpl *item)
334     {
335         m_lstChildren->append(item);
336     }
337 
338 protected:
339     QList<StyleBaseImpl *> *m_lstChildren;
340 };
341 
342 KHTML_NO_EXPORT int getPropertyID(const char *tagStr, int len);
343 KHTML_NO_EXPORT int getValueID(const char *tagStr, int len);
344 
345 struct SelectorHash {
hashSelectorHash346     static unsigned hash(CSSSelector *selector)
347     {
348         unsigned result = 0;
349         while (selector) {
350             result ^= (quintptr)selector->value.impl();
351             result ^= (selector->attrLocalName.id() << 3);
352             result ^= (selector->attrNamespace.id() << 7);
353             result ^= (selector->tagLocalName.id() << 10);
354             result ^= (selector->tagNamespace.id() << 13);
355             result ^= (selector->relation << 17);
356             result ^= (selector->match << 20);
357             result ^= result << 5;
358             selector = selector->tagHistory;
359         }
360         return result;
361     }
equalSelectorHash362     static bool equal(CSSSelector *a, CSSSelector *b)
363     {
364         return a == b || *a == *b;
365     }
366     static const bool safeToCompareToEmptyOrDeleted = false;
367 };
368 
369 }
370 
371 namespace WTF
372 {
373 template<typename T> struct DefaultHash;
374 template<> struct DefaultHash<DOM::CSSSelector *> {
375     typedef DOM::SelectorHash Hash;
376 };
377 }
378 
379 #endif
380