1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Daniel Glazman <glazman@netscape.com>
24 : * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /*
41 : * representation of CSS style rules (selectors+declaration) and CSS
42 : * selectors
43 : */
44 :
45 : #ifndef mozilla_css_StyleRule_h__
46 : #define mozilla_css_StyleRule_h__
47 :
48 : #include "mozilla/Attributes.h"
49 :
50 : #include "mozilla/Attributes.h"
51 : #include "mozilla/css/Rule.h"
52 :
53 : #include "nsString.h"
54 : #include "nsCOMPtr.h"
55 : #include "nsCSSPseudoElements.h"
56 : #include "nsCSSPseudoClasses.h"
57 : #include "nsAutoPtr.h"
58 :
59 : class nsIAtom;
60 : class nsCSSStyleSheet;
61 : struct nsCSSSelectorList;
62 : class nsCSSCompressedDataBlock;
63 :
64 : struct nsAtomList {
65 : public:
66 : nsAtomList(nsIAtom* aAtom);
67 : nsAtomList(const nsString& aAtomValue);
68 : ~nsAtomList(void);
69 :
70 : /** Do a deep clone. Should be used only on the first in the linked list. */
71 0 : nsAtomList* Clone() const { return Clone(true); }
72 :
73 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
74 :
75 : nsCOMPtr<nsIAtom> mAtom;
76 : nsAtomList* mNext;
77 : private:
78 : nsAtomList* Clone(bool aDeep) const;
79 :
80 : nsAtomList(const nsAtomList& aCopy) MOZ_DELETE;
81 : nsAtomList& operator=(const nsAtomList& aCopy) MOZ_DELETE;
82 : };
83 :
84 : struct nsPseudoClassList {
85 : public:
86 : nsPseudoClassList(nsCSSPseudoClasses::Type aType);
87 : nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRUnichar *aString);
88 : nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRInt32 *aIntPair);
89 : nsPseudoClassList(nsCSSPseudoClasses::Type aType,
90 : nsCSSSelectorList *aSelectorList /* takes ownership */);
91 : ~nsPseudoClassList(void);
92 :
93 : /** Do a deep clone. Should be used only on the first in the linked list. */
94 0 : nsPseudoClassList* Clone() const { return Clone(true); }
95 :
96 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
97 :
98 : union {
99 : // For a given value of mType, we have either:
100 : // a. no value, which means mMemory is always null
101 : // (if none of the conditions for (b), (c), or (d) is true)
102 : // b. a string value, which means mString/mMemory is non-null
103 : // (if nsCSSPseudoClasses::HasStringArg(mType))
104 : // c. an integer pair value, which means mNumbers/mMemory is non-null
105 : // (if nsCSSPseudoClasses::HasNthPairArg(mType))
106 : // d. a selector list, which means mSelectors is non-null
107 : // (if nsCSSPseudoClasses::HasSelectorListArg(mType))
108 : void* mMemory; // mString and mNumbers use NS_Alloc/NS_Free
109 : PRUnichar* mString;
110 : PRInt32* mNumbers;
111 : nsCSSSelectorList* mSelectors;
112 : } u;
113 : nsCSSPseudoClasses::Type mType;
114 : nsPseudoClassList* mNext;
115 : private:
116 : nsPseudoClassList* Clone(bool aDeep) const;
117 :
118 : nsPseudoClassList(const nsPseudoClassList& aCopy) MOZ_DELETE;
119 : nsPseudoClassList& operator=(const nsPseudoClassList& aCopy) MOZ_DELETE;
120 : };
121 :
122 : #define NS_ATTR_FUNC_SET 0 // [attr]
123 : #define NS_ATTR_FUNC_EQUALS 1 // [attr=value]
124 : #define NS_ATTR_FUNC_INCLUDES 2 // [attr~=value] (space separated)
125 : #define NS_ATTR_FUNC_DASHMATCH 3 // [attr|=value] ('-' truncated)
126 : #define NS_ATTR_FUNC_BEGINSMATCH 4 // [attr^=value] (begins with)
127 : #define NS_ATTR_FUNC_ENDSMATCH 5 // [attr$=value] (ends with)
128 : #define NS_ATTR_FUNC_CONTAINSMATCH 6 // [attr*=value] (contains substring)
129 :
130 : struct nsAttrSelector {
131 : public:
132 : nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr);
133 : nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
134 : const nsString& aValue, bool aCaseSensitive);
135 : nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aLowercaseAttr,
136 : nsIAtom* aCasedAttr, PRUint8 aFunction,
137 : const nsString& aValue, bool aCaseSensitive);
138 : ~nsAttrSelector(void);
139 :
140 : /** Do a deep clone. Should be used only on the first in the linked list. */
141 0 : nsAttrSelector* Clone() const { return Clone(true); }
142 :
143 : nsString mValue;
144 : nsAttrSelector* mNext;
145 : nsCOMPtr<nsIAtom> mLowercaseAttr;
146 : nsCOMPtr<nsIAtom> mCasedAttr;
147 : PRInt32 mNameSpace;
148 : PRUint8 mFunction;
149 : bool mCaseSensitive; // If we are in an HTML document,
150 : // is the value case sensitive?
151 : private:
152 : nsAttrSelector* Clone(bool aDeep) const;
153 :
154 : nsAttrSelector(const nsAttrSelector& aCopy) MOZ_DELETE;
155 : nsAttrSelector& operator=(const nsAttrSelector& aCopy) MOZ_DELETE;
156 : };
157 :
158 : struct nsCSSSelector {
159 : public:
160 : nsCSSSelector(void);
161 : ~nsCSSSelector(void);
162 :
163 : /** Do a deep clone. Should be used only on the first in the linked list. */
164 0 : nsCSSSelector* Clone() const { return Clone(true, true); }
165 :
166 : void Reset(void);
167 : void SetNameSpace(PRInt32 aNameSpace);
168 : void SetTag(const nsString& aTag);
169 : void AddID(const nsString& aID);
170 : void AddClass(const nsString& aClass);
171 : void AddPseudoClass(nsCSSPseudoClasses::Type aType);
172 : void AddPseudoClass(nsCSSPseudoClasses::Type aType, const PRUnichar* aString);
173 : void AddPseudoClass(nsCSSPseudoClasses::Type aType, const PRInt32* aIntPair);
174 : // takes ownership of aSelectorList
175 : void AddPseudoClass(nsCSSPseudoClasses::Type aType,
176 : nsCSSSelectorList* aSelectorList);
177 : void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr);
178 : void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunc,
179 : const nsString& aValue, bool aCaseSensitive);
180 : void SetOperator(PRUnichar aOperator);
181 :
182 : inline bool HasTagSelector() const {
183 : return !!mCasedTag;
184 : }
185 :
186 3538 : inline bool IsPseudoElement() const {
187 3538 : return mLowercaseTag && !mCasedTag;
188 : }
189 :
190 : // Calculate the specificity of this selector (not including its mNext!).
191 : PRInt32 CalcWeight() const;
192 :
193 : void ToString(nsAString& aString, nsCSSStyleSheet* aSheet,
194 : bool aAppend = false) const;
195 :
196 : private:
197 : void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass);
198 : nsCSSSelector* Clone(bool aDeepNext, bool aDeepNegations) const;
199 :
200 : void AppendToStringWithoutCombinators(nsAString& aString,
201 : nsCSSStyleSheet* aSheet) const;
202 : void AppendToStringWithoutCombinatorsOrNegations(nsAString& aString,
203 : nsCSSStyleSheet* aSheet,
204 : bool aIsNegated)
205 : const;
206 : // Returns true if this selector can have a namespace specified (which
207 : // happens if and only if the default namespace would apply to this
208 : // selector).
209 : bool CanBeNamespaced(bool aIsNegated) const;
210 : // Calculate the specificity of this selector (not including its mNext
211 : // or its mNegations).
212 : PRInt32 CalcWeightWithoutNegations() const;
213 :
214 : public:
215 : // Get and set the selector's pseudo type
216 : nsCSSPseudoElements::Type PseudoType() const {
217 : return static_cast<nsCSSPseudoElements::Type>(mPseudoType);
218 : }
219 0 : void SetPseudoType(nsCSSPseudoElements::Type aType) {
220 0 : NS_ASSERTION(aType > PR_INT16_MIN && aType < PR_INT16_MAX, "Out of bounds");
221 0 : mPseudoType = static_cast<PRInt16>(aType);
222 0 : }
223 :
224 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
225 :
226 : // For case-sensitive documents, mLowercaseTag is the same as mCasedTag,
227 : // but in case-insensitive documents (HTML) mLowercaseTag is lowercase.
228 : // Also, for pseudo-elements mCasedTag will be null but mLowercaseTag
229 : // contains their name.
230 : nsCOMPtr<nsIAtom> mLowercaseTag;
231 : nsCOMPtr<nsIAtom> mCasedTag;
232 : nsAtomList* mIDList;
233 : nsAtomList* mClassList;
234 : nsPseudoClassList* mPseudoClassList; // atom for the pseudo, string for
235 : // the argument to functional pseudos
236 : nsAttrSelector* mAttrList;
237 : nsCSSSelector* mNegations;
238 : nsCSSSelector* mNext;
239 : PRInt32 mNameSpace;
240 : PRUnichar mOperator;
241 : private:
242 : // PRInt16 to make sure it packs well with mOperator
243 : PRInt16 mPseudoType;
244 :
245 : nsCSSSelector(const nsCSSSelector& aCopy) MOZ_DELETE;
246 : nsCSSSelector& operator=(const nsCSSSelector& aCopy) MOZ_DELETE;
247 : };
248 :
249 : /**
250 : * A selector list is the unit of selectors that each style rule has.
251 : * For example, "P B, H1 B { ... }" would be a selector list with two
252 : * items (where each |nsCSSSelectorList| object's |mSelectors| has
253 : * an |mNext| for the P or H1). We represent them as linked lists.
254 : */
255 : struct nsCSSSelectorList {
256 : nsCSSSelectorList(void);
257 : ~nsCSSSelectorList(void);
258 :
259 : /**
260 : * Create a new selector and push it onto the beginning of |mSelectors|,
261 : * setting its |mNext| to the current value of |mSelectors|. If there is an
262 : * earlier selector, set its |mOperator| to |aOperator|; else |aOperator|
263 : * must be PRUnichar(0).
264 : * Returns the new selector.
265 : * The list owns the new selector.
266 : * The caller is responsible for updating |mWeight|.
267 : */
268 : nsCSSSelector* AddSelector(PRUnichar aOperator);
269 :
270 : /**
271 : * Should be used only on the first in the list
272 : */
273 : void ToString(nsAString& aResult, nsCSSStyleSheet* aSheet);
274 :
275 : /**
276 : * Do a deep clone. Should be used only on the first in the list.
277 : */
278 0 : nsCSSSelectorList* Clone() const { return Clone(true); }
279 :
280 : size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
281 :
282 : nsCSSSelector* mSelectors;
283 : PRInt32 mWeight;
284 : nsCSSSelectorList* mNext;
285 : private:
286 : nsCSSSelectorList* Clone(bool aDeep) const;
287 :
288 : nsCSSSelectorList(const nsCSSSelectorList& aCopy) MOZ_DELETE;
289 : nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy) MOZ_DELETE;
290 : };
291 :
292 : // 464bab7a-2fce-4f30-ab44-b7a5f3aae57d
293 : #define NS_CSS_STYLE_RULE_IMPL_CID \
294 : { 0x464bab7a, 0x2fce, 0x4f30, \
295 : { 0xab, 0x44, 0xb7, 0xa5, 0xf3, 0xaa, 0xe5, 0x7d } }
296 :
297 : namespace mozilla {
298 : namespace css {
299 :
300 : class Declaration;
301 : class DOMCSSStyleRule;
302 :
303 : class StyleRule;
304 :
305 : class ImportantRule : public nsIStyleRule {
306 : public:
307 : ImportantRule(Declaration *aDeclaration);
308 :
309 : NS_DECL_ISUPPORTS
310 :
311 : // nsIStyleRule interface
312 : virtual void MapRuleInfoInto(nsRuleData* aRuleData);
313 : #ifdef DEBUG
314 : virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
315 : #endif
316 :
317 : protected:
318 : virtual ~ImportantRule();
319 :
320 : // Not an owning reference; the StyleRule that owns this
321 : // ImportantRule also owns the mDeclaration, and any rule node
322 : // pointing to this rule keeps that StyleRule alive as well.
323 : Declaration* mDeclaration;
324 :
325 : friend class StyleRule;
326 : };
327 :
328 : class StyleRule MOZ_FINAL : public Rule
329 : {
330 : public:
331 : StyleRule(nsCSSSelectorList* aSelector,
332 : Declaration *aDeclaration);
333 : private:
334 : // for |Clone|
335 : StyleRule(const StyleRule& aCopy);
336 : // for |DeclarationChanged|
337 : StyleRule(StyleRule& aCopy,
338 : Declaration *aDeclaration);
339 : public:
340 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_STYLE_RULE_IMPL_CID)
341 :
342 : NS_DECL_ISUPPORTS_INHERITED
343 :
344 : // null for style attribute
345 : nsCSSSelectorList* Selector() { return mSelector; }
346 :
347 0 : PRUint32 GetLineNumber() const { return mLineNumber; }
348 0 : void SetLineNumber(PRUint32 aLineNumber) { mLineNumber = aLineNumber; }
349 :
350 0 : Declaration* GetDeclaration() const { return mDeclaration; }
351 :
352 : /**
353 : * Return a new |nsIStyleRule| instance that replaces the current
354 : * one, with |aDecl| replacing the previous declaration. Due to the
355 : * |nsIStyleRule| contract of immutability, this must be called if
356 : * the declaration is modified.
357 : *
358 : * |DeclarationChanged| handles replacing the object in the container
359 : * sheet or group rule if |aHandleContainer| is true.
360 : */
361 : already_AddRefed<StyleRule>
362 : DeclarationChanged(Declaration* aDecl, bool aHandleContainer);
363 :
364 0 : nsIStyleRule* GetImportantRule() const { return mImportantRule; }
365 :
366 : /**
367 : * The rule processor must call this method before calling
368 : * nsRuleWalker::Forward on this rule during rule matching.
369 : */
370 : void RuleMatched();
371 :
372 : // hooks for DOM rule
373 : void GetCssText(nsAString& aCssText);
374 : void SetCssText(const nsAString& aCssText);
375 : void GetSelectorText(nsAString& aSelectorText);
376 : void SetSelectorText(const nsAString& aSelectorText);
377 :
378 : virtual PRInt32 GetType() const;
379 :
380 : virtual already_AddRefed<Rule> Clone() const;
381 :
382 : virtual nsIDOMCSSRule* GetDOMRule();
383 :
384 : // The new mapping function.
385 : virtual void MapRuleInfoInto(nsRuleData* aRuleData);
386 :
387 : #ifdef DEBUG
388 : virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
389 : #endif
390 :
391 : virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
392 :
393 : private:
394 : ~StyleRule();
395 :
396 : private:
397 : nsCSSSelectorList* mSelector; // null for style attribute
398 : Declaration* mDeclaration;
399 : ImportantRule* mImportantRule; // initialized by RuleMatched
400 : DOMCSSStyleRule* mDOMRule;
401 : // Keep the same type so that MSVC packs them.
402 : PRUint32 mLineNumber : 31;
403 : PRUint32 mWasMatched : 1;
404 :
405 : private:
406 : StyleRule& operator=(const StyleRule& aCopy) MOZ_DELETE;
407 : };
408 :
409 : } // namespace css
410 : } // namespace mozilla
411 :
412 : NS_DEFINE_STATIC_IID_ACCESSOR(mozilla::css::StyleRule, NS_CSS_STYLE_RULE_IMPL_CID)
413 :
414 : #endif /* mozilla_css_StyleRule_h__ */
|