Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / style / nsCSSStyleRule.cpp
blob9dc7de4eefee5551718576ce8ed2ee89ca584462
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
23 * David Hyatt <hyatt@netscape.com>
24 * Daniel Glazman <glazman@netscape.com>
25 * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * representation of CSS style rules (selectors+declaration), CSS
43 * selectors, and DOM objects for style rules, selectors, and
44 * declarations
47 #include "nsCOMPtr.h"
48 #include "nsCSSRule.h"
49 #include "nsICSSStyleRule.h"
50 #include "nsICSSGroupRule.h"
51 #include "nsCSSDeclaration.h"
52 #include "nsICSSStyleSheet.h"
53 #include "nsICSSParser.h"
54 #include "nsICSSLoader.h"
55 #include "nsIURL.h"
56 #include "nsPresContext.h"
57 #include "nsIDocument.h"
58 #include "nsIDeviceContext.h"
59 #include "nsIAtom.h"
60 #include "nsCRT.h"
61 #include "nsString.h"
62 #include "nsStyleConsts.h"
63 #include "nsStyleUtil.h"
64 #include "nsIFontMetrics.h"
65 #include "nsIDOMCSSStyleSheet.h"
66 #include "nsICSSStyleRuleDOMWrapper.h"
67 #include "nsIDOMCSSStyleDeclaration.h"
68 #include "nsDOMCSSDeclaration.h"
69 #include "nsINameSpaceManager.h"
70 #include "nsXMLNameSpaceMap.h"
71 #include "nsILookAndFeel.h"
72 #include "nsRuleNode.h"
73 #include "nsUnicharUtils.h"
74 #include "nsCSSPseudoElements.h"
75 #include "nsIPrincipal.h"
76 #include "nsComponentManagerUtils.h"
77 #include "nsCSSPseudoClasses.h"
79 #include "nsContentUtils.h"
80 #include "nsContentErrors.h"
81 #include "mozAutoDocUpdate.h"
83 #define NS_IF_CLONE(member_) \
84 PR_BEGIN_MACRO \
85 if (member_) { \
86 result->member_ = member_->Clone(); \
87 if (!result->member_) { \
88 delete result; \
89 return nsnull; \
90 } \
91 } \
92 PR_END_MACRO
94 #define NS_IF_DELETE(ptr) \
95 PR_BEGIN_MACRO \
96 delete ptr; \
97 ptr = nsnull; \
98 PR_END_MACRO
100 /* ************************************************************************** */
102 nsAtomList::nsAtomList(nsIAtom* aAtom)
103 : mAtom(aAtom),
104 mNext(nsnull)
106 MOZ_COUNT_CTOR(nsAtomList);
109 nsAtomList::nsAtomList(const nsString& aAtomValue)
110 : mAtom(nsnull),
111 mNext(nsnull)
113 MOZ_COUNT_CTOR(nsAtomList);
114 mAtom = do_GetAtom(aAtomValue);
117 nsAtomList*
118 nsAtomList::Clone(PRBool aDeep) const
120 nsAtomList *result = new nsAtomList(mAtom);
121 if (!result)
122 return nsnull;
124 if (aDeep)
125 NS_CSS_CLONE_LIST_MEMBER(nsAtomList, this, mNext, result, (PR_FALSE));
126 return result;
129 nsAtomList::~nsAtomList(void)
131 MOZ_COUNT_DTOR(nsAtomList);
132 NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
135 nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom)
136 : mAtom(aAtom),
137 mNext(nsnull)
139 NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aAtom) &&
140 !nsCSSPseudoClasses::HasNthPairArg(aAtom),
141 "unexpected pseudo-class");
142 MOZ_COUNT_CTOR(nsPseudoClassList);
143 u.mMemory = nsnull;
146 nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRUnichar* aString)
147 : mAtom(aAtom),
148 mNext(nsnull)
150 NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aAtom),
151 "unexpected pseudo-class");
152 NS_ASSERTION(aString, "string expected");
153 MOZ_COUNT_CTOR(nsPseudoClassList);
154 u.mString = NS_strdup(aString);
157 nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRInt32* aIntPair)
158 : mAtom(aAtom),
159 mNext(nsnull)
161 NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aAtom),
162 "unexpected pseudo-class");
163 NS_ASSERTION(aIntPair, "integer pair expected");
164 MOZ_COUNT_CTOR(nsPseudoClassList);
165 u.mNumbers =
166 static_cast<PRInt32*>(nsMemory::Clone(aIntPair, sizeof(PRInt32) * 2));
169 nsPseudoClassList*
170 nsPseudoClassList::Clone(PRBool aDeep) const
172 nsPseudoClassList *result;
173 if (!u.mMemory) {
174 result = new nsPseudoClassList(mAtom);
175 } else if (nsCSSPseudoClasses::HasStringArg(mAtom)) {
176 result = new nsPseudoClassList(mAtom, u.mString);
177 } else {
178 NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(mAtom),
179 "unexpected pseudo-class");
180 result = new nsPseudoClassList(mAtom, u.mNumbers);
183 if (aDeep)
184 NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
185 (PR_FALSE));
187 return result;
190 nsPseudoClassList::~nsPseudoClassList(void)
192 MOZ_COUNT_DTOR(nsPseudoClassList);
193 if (u.mMemory)
194 NS_Free(u.mMemory);
195 NS_CSS_DELETE_LIST_MEMBER(nsPseudoClassList, this, mNext);
198 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr)
199 : mNameSpace(aNameSpace),
200 mAttr(nsnull),
201 mFunction(NS_ATTR_FUNC_SET),
202 mCaseSensitive(1),
203 mValue(),
204 mNext(nsnull)
206 MOZ_COUNT_CTOR(nsAttrSelector);
208 mAttr = do_GetAtom(aAttr);
211 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
212 const nsString& aValue, PRBool aCaseSensitive)
213 : mNameSpace(aNameSpace),
214 mAttr(nsnull),
215 mFunction(aFunction),
216 mCaseSensitive(aCaseSensitive),
217 mValue(aValue),
218 mNext(nsnull)
220 MOZ_COUNT_CTOR(nsAttrSelector);
222 mAttr = do_GetAtom(aAttr);
225 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aAttr,
226 PRUint8 aFunction, const nsString& aValue,
227 PRBool aCaseSensitive)
228 : mNameSpace(aNameSpace),
229 mAttr(aAttr),
230 mFunction(aFunction),
231 mCaseSensitive(aCaseSensitive),
232 mValue(aValue),
233 mNext(nsnull)
235 MOZ_COUNT_CTOR(nsAttrSelector);
238 nsAttrSelector*
239 nsAttrSelector::Clone(PRBool aDeep) const
241 nsAttrSelector *result =
242 new nsAttrSelector(mNameSpace, mAttr, mFunction, mValue, mCaseSensitive);
244 if (aDeep)
245 NS_CSS_CLONE_LIST_MEMBER(nsAttrSelector, this, mNext, result, (PR_FALSE));
247 return result;
250 nsAttrSelector::~nsAttrSelector(void)
252 MOZ_COUNT_DTOR(nsAttrSelector);
254 NS_CSS_DELETE_LIST_MEMBER(nsAttrSelector, this, mNext);
257 // -- nsCSSSelector -------------------------------
259 nsCSSSelector::nsCSSSelector(void)
260 : mNameSpace(kNameSpaceID_Unknown), mTag(nsnull),
261 mIDList(nsnull),
262 mClassList(nsnull),
263 mPseudoClassList(nsnull),
264 mAttrList(nsnull),
265 mOperator(0),
266 mNegations(nsnull),
267 mNext(nsnull)
269 MOZ_COUNT_CTOR(nsCSSSelector);
272 nsCSSSelector*
273 nsCSSSelector::Clone(PRBool aDeepNext, PRBool aDeepNegations) const
275 nsCSSSelector *result = new nsCSSSelector();
276 if (!result)
277 return nsnull;
279 result->mNameSpace = mNameSpace;
280 result->mTag = mTag;
282 NS_IF_CLONE(mIDList);
283 NS_IF_CLONE(mClassList);
284 NS_IF_CLONE(mPseudoClassList);
285 NS_IF_CLONE(mAttrList);
287 // No need to worry about multiple levels of recursion since an
288 // mNegations can't have an mNext.
289 NS_ASSERTION(!mNegations || !mNegations->mNext,
290 "mNegations can't have non-null mNext");
291 if (aDeepNegations) {
292 NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNegations, result,
293 (PR_TRUE, PR_FALSE));
296 if (aDeepNext) {
297 NS_CSS_CLONE_LIST_MEMBER(nsCSSSelector, this, mNext, result,
298 (PR_FALSE, PR_TRUE));
301 return result;
304 nsCSSSelector::~nsCSSSelector(void)
306 MOZ_COUNT_DTOR(nsCSSSelector);
307 Reset();
308 // No need to worry about multiple levels of recursion since an
309 // mNegations can't have an mNext.
310 NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNext);
313 void nsCSSSelector::Reset(void)
315 mNameSpace = kNameSpaceID_Unknown;
316 mTag = nsnull;
317 NS_IF_DELETE(mIDList);
318 NS_IF_DELETE(mClassList);
319 NS_IF_DELETE(mPseudoClassList);
320 NS_IF_DELETE(mAttrList);
321 // No need to worry about multiple levels of recursion since an
322 // mNegations can't have an mNext.
323 NS_ASSERTION(!mNegations || !mNegations->mNext,
324 "mNegations can't have non-null mNext");
325 NS_CSS_DELETE_LIST_MEMBER(nsCSSSelector, this, mNegations);
326 mOperator = PRUnichar(0);
329 void nsCSSSelector::SetNameSpace(PRInt32 aNameSpace)
331 mNameSpace = aNameSpace;
334 void nsCSSSelector::SetTag(const nsString& aTag)
336 if (aTag.IsEmpty())
337 mTag = nsnull;
338 else
339 mTag = do_GetAtom(aTag);
342 void nsCSSSelector::AddID(const nsString& aID)
344 if (!aID.IsEmpty()) {
345 nsAtomList** list = &mIDList;
346 while (nsnull != *list) {
347 list = &((*list)->mNext);
349 *list = new nsAtomList(aID);
353 void nsCSSSelector::AddClass(const nsString& aClass)
355 if (!aClass.IsEmpty()) {
356 nsAtomList** list = &mClassList;
357 while (nsnull != *list) {
358 list = &((*list)->mNext);
360 *list = new nsAtomList(aClass);
364 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass)
366 AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass));
369 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
370 const PRUnichar* aString)
372 AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aString));
375 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
376 const PRInt32* aIntPair)
378 AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aIntPair));
381 void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
383 nsPseudoClassList** list = &mPseudoClassList;
384 while (nsnull != *list) {
385 list = &((*list)->mNext);
387 *list = aPseudoClass;
390 void nsCSSSelector::AddAttribute(PRInt32 aNameSpace, const nsString& aAttr)
392 if (!aAttr.IsEmpty()) {
393 nsAttrSelector** list = &mAttrList;
394 while (nsnull != *list) {
395 list = &((*list)->mNext);
397 *list = new nsAttrSelector(aNameSpace, aAttr);
401 void nsCSSSelector::AddAttribute(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunc,
402 const nsString& aValue, PRBool aCaseSensitive)
404 if (!aAttr.IsEmpty()) {
405 nsAttrSelector** list = &mAttrList;
406 while (nsnull != *list) {
407 list = &((*list)->mNext);
409 *list = new nsAttrSelector(aNameSpace, aAttr, aFunc, aValue, aCaseSensitive);
413 void nsCSSSelector::SetOperator(PRUnichar aOperator)
415 mOperator = aOperator;
418 PRInt32 nsCSSSelector::CalcWeight(void) const
420 PRInt32 weight = 0;
422 if (nsnull != mTag) {
423 weight += 0x000001;
425 nsAtomList* list = mIDList;
426 while (nsnull != list) {
427 weight += 0x010000;
428 list = list->mNext;
430 list = mClassList;
431 while (nsnull != list) {
432 weight += 0x000100;
433 list = list->mNext;
435 nsPseudoClassList *plist = mPseudoClassList;
436 while (nsnull != plist) {
437 weight += 0x000100;
438 plist = plist->mNext;
440 nsAttrSelector* attr = mAttrList;
441 while (nsnull != attr) {
442 weight += 0x000100;
443 attr = attr->mNext;
445 if (nsnull != mNegations) {
446 weight += mNegations->CalcWeight();
448 return weight;
451 // pseudo-elements are stored in the selectors' chain using fictional elements;
452 // these fictional elements have mTag starting with a colon
453 static PRBool IsPseudoElement(nsIAtom* aAtom)
455 if (aAtom) {
456 const char* str;
457 aAtom->GetUTF8String(&str);
458 return str && (*str == ':');
461 return PR_FALSE;
464 void nsCSSSelector::AppendNegationToString(nsAString& aString)
466 aString.AppendLiteral(":not(");
470 // Builds the textual representation of a selector. Called by DOM 2 CSS
471 // StyleRule:selectorText
473 void
474 nsCSSSelector::ToString(nsAString& aString, nsICSSStyleSheet* aSheet,
475 PRBool aAppend) const
477 if (!aAppend)
478 aString.Truncate();
480 ToStringInternal(aString, aSheet, IsPseudoElement(mTag), PR_FALSE);
483 void nsCSSSelector::ToStringInternal(nsAString& aString,
484 nsICSSStyleSheet* aSheet,
485 PRBool aIsPseudoElem,
486 PRBool aIsNegated) const
488 nsAutoString temp;
489 PRBool isPseudoElement = IsPseudoElement(mTag);
491 // selectors are linked from right-to-left, so the next selector in the linked list
492 // actually precedes this one in the resulting string
493 if (mNext) {
494 mNext->ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
495 if (!aIsNegated && !isPseudoElement) {
496 // don't add a leading whitespace if we have a pseudo-element
497 // or a negated simple selector
498 aString.Append(PRUnichar(' '));
502 // For non-pseudo-element selectors or for lone pseudo-elements, deal with
503 // namespace prefixes.
504 PRBool wroteNamespace = PR_FALSE;
505 if (!isPseudoElement || !mNext) {
506 // append the namespace prefix if needed
507 nsXMLNameSpaceMap *sheetNS = aSheet ? aSheet->GetNameSpaceMap() : nsnull;
509 // sheetNS is non-null if and only if we had an @namespace rule. If it's
510 // null, that means that the only namespaces we could have are the
511 // wildcard namespace (which can be implicit in this case) and the "none"
512 // namespace, which then needs to be explicitly specified.
513 if (!sheetNS) {
514 NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
515 mNameSpace == kNameSpaceID_None,
516 "How did we get this namespace?");
517 if (mNameSpace == kNameSpaceID_None) {
518 aString.Append(PRUnichar('|'));
519 wroteNamespace = PR_TRUE;
521 } else if (sheetNS->FindNameSpaceID(nsnull) == mNameSpace) {
522 // We have the default namespace (possibly including the wildcard
523 // namespace). Do nothing.
524 NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
525 CanBeNamespaced(aIsNegated),
526 "How did we end up with this namespace?");
527 } else if (mNameSpace != kNameSpaceID_Unknown) {
528 NS_ASSERTION(CanBeNamespaced(aIsNegated),
529 "How did we end up with this namespace?");
530 nsIAtom *prefixAtom = sheetNS->FindPrefix(mNameSpace);
531 NS_ASSERTION(prefixAtom, "how'd we get a non-default namespace "
532 "without a prefix?");
533 nsAutoString prefix;
534 prefixAtom->ToString(prefix);
535 aString.Append(prefix);
536 aString.Append(PRUnichar('|'));
537 wroteNamespace = PR_TRUE;
538 } else {
539 // A selector for an element in any namespace, while the default
540 // namespace is something else. :not() is special in that the default
541 // namespace is not implied for non-type selectors, so if this is a
542 // negated non-type selector we don't need to output an explicit wildcard
543 // namespace here, since those default to a wildcard namespace.
544 if (CanBeNamespaced(aIsNegated)) {
545 aString.AppendLiteral("*|");
546 wroteNamespace = PR_TRUE;
551 if (!mTag) {
552 // Universal selector: avoid writing the universal selector when we
553 // can avoid it, especially since we're required to avoid it for the
554 // inside of :not()
555 if (wroteNamespace ||
556 (!mIDList && !mClassList && !mPseudoClassList && !mAttrList &&
557 (aIsNegated || !mNegations))) {
558 aString.Append(PRUnichar('*'));
560 } else {
561 // Append the tag name
562 if (isPseudoElement) {
563 if (!mNext) {
564 // Lone pseudo-element selector -- toss in a wildcard type selector
565 // XXXldb Why?
566 aString.Append(PRUnichar('*'));
568 if (!nsCSSPseudoElements::IsCSS2PseudoElement(mTag)) {
569 aString.Append(PRUnichar(':'));
572 nsAutoString prefix;
573 mTag->ToString(prefix);
574 aString.Append(prefix);
577 // Append the id, if there is one
578 if (mIDList) {
579 nsAtomList* list = mIDList;
580 while (list != nsnull) {
581 list->mAtom->ToString(temp);
582 aString.Append(PRUnichar('#'));
583 aString.Append(temp);
584 list = list->mNext;
588 // Append each class in the linked list
589 if (mClassList) {
590 nsAtomList* list = mClassList;
591 while (list != nsnull) {
592 list->mAtom->ToString(temp);
593 aString.Append(PRUnichar('.'));
594 aString.Append(temp);
595 list = list->mNext;
599 // Append each attribute selector in the linked list
600 if (mAttrList) {
601 nsAttrSelector* list = mAttrList;
602 while (list != nsnull) {
603 aString.Append(PRUnichar('['));
604 // Append the namespace prefix
605 if (list->mNameSpace > 0) {
606 if (aSheet) {
607 nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap();
608 // will return null if namespace was the default
609 nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace);
610 if (prefixAtom) {
611 nsAutoString prefix;
612 prefixAtom->ToString(prefix);
613 aString.Append(prefix);
614 aString.Append(PRUnichar('|'));
618 // Append the attribute name
619 list->mAttr->ToString(temp);
620 aString.Append(temp);
622 if (list->mFunction != NS_ATTR_FUNC_SET) {
623 // Append the function
624 if (list->mFunction == NS_ATTR_FUNC_INCLUDES)
625 aString.Append(PRUnichar('~'));
626 else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH)
627 aString.Append(PRUnichar('|'));
628 else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH)
629 aString.Append(PRUnichar('^'));
630 else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH)
631 aString.Append(PRUnichar('$'));
632 else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH)
633 aString.Append(PRUnichar('*'));
635 aString.Append(PRUnichar('='));
637 // Append the value
638 nsAutoString escaped;
639 nsStyleUtil::EscapeCSSString(list->mValue, escaped);
641 aString.Append(PRUnichar('\"'));
642 aString.Append(escaped);
643 aString.Append(PRUnichar('\"'));
646 aString.Append(PRUnichar(']'));
648 list = list->mNext;
652 // Append each pseudo-class in the linked list
653 if (mPseudoClassList) {
654 nsPseudoClassList* list = mPseudoClassList;
655 while (list != nsnull) {
656 list->mAtom->ToString(temp);
657 aString.Append(temp);
658 if (list->u.mMemory) {
659 aString.Append(PRUnichar('('));
660 if (nsCSSPseudoClasses::HasStringArg(list->mAtom)) {
661 aString.Append(list->u.mString);
662 } else {
663 NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(list->mAtom),
664 "unexpected pseudo-class");
665 PRInt32 a = list->u.mNumbers[0],
666 b = list->u.mNumbers[1];
667 temp.Truncate();
668 if (a != 0) {
669 if (a == -1) {
670 temp.Append(PRUnichar('-'));
671 } else if (a != 1) {
672 temp.AppendInt(a);
674 temp.Append(PRUnichar('n'));
676 if (b != 0 || a == 0) {
677 if (b >= 0 && a != 0) // check a != 0 for whether we printed above
678 temp.Append(PRUnichar('+'));
679 temp.AppendInt(b);
681 aString.Append(temp);
683 aString.Append(PRUnichar(')'));
685 list = list->mNext;
689 if (!aIsNegated) {
690 for (nsCSSSelector* negation = mNegations; negation;
691 negation = negation->mNegations) {
692 aString.AppendLiteral(":not(");
693 negation->ToStringInternal(aString, aSheet, PR_FALSE, PR_TRUE);
694 aString.Append(PRUnichar(')'));
698 // Append the operator only if the selector is not negated and is not
699 // a pseudo-element
700 if (!aIsNegated && mOperator && !aIsPseudoElem) {
701 aString.Append(PRUnichar(' '));
702 aString.Append(mOperator);
706 PRBool
707 nsCSSSelector::CanBeNamespaced(PRBool aIsNegated) const
709 return !aIsNegated ||
710 (!mIDList && !mClassList && !mPseudoClassList && !mAttrList);
713 // -- nsCSSSelectorList -------------------------------
715 nsCSSSelectorList::nsCSSSelectorList(void)
716 : mSelectors(nsnull),
717 mWeight(0),
718 mNext(nsnull)
720 MOZ_COUNT_CTOR(nsCSSSelectorList);
723 nsCSSSelectorList::~nsCSSSelectorList()
725 MOZ_COUNT_DTOR(nsCSSSelectorList);
726 delete mSelectors;
727 NS_CSS_DELETE_LIST_MEMBER(nsCSSSelectorList, this, mNext);
730 void nsCSSSelectorList::AddSelector(nsAutoPtr<nsCSSSelector>& aSelector)
731 { // prepend to list
732 nsCSSSelector* newSel = aSelector.forget();
733 if (newSel) {
734 newSel->mNext = mSelectors;
735 mSelectors = newSel;
739 void
740 nsCSSSelectorList::ToString(nsAString& aResult, nsICSSStyleSheet* aSheet)
742 aResult.Truncate();
743 nsCSSSelectorList *p = this;
744 for (;;) {
745 p->mSelectors->ToString(aResult, aSheet, PR_TRUE);
746 p = p->mNext;
747 if (!p)
748 break;
749 aResult.AppendLiteral(", ");
753 nsCSSSelectorList*
754 nsCSSSelectorList::Clone(PRBool aDeep) const
756 nsCSSSelectorList *result = new nsCSSSelectorList();
757 result->mWeight = mWeight;
758 NS_IF_CLONE(mSelectors);
760 if (aDeep) {
761 NS_CSS_CLONE_LIST_MEMBER(nsCSSSelectorList, this, mNext, result,
762 (PR_FALSE));
764 return result;
767 // -- CSSImportantRule -------------------------------
769 class CSSStyleRuleImpl;
771 class CSSImportantRule : public nsIStyleRule {
772 public:
773 CSSImportantRule(nsCSSDeclaration* aDeclaration);
775 NS_DECL_ISUPPORTS
777 // nsIStyleRule interface
778 NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
779 #ifdef DEBUG
780 NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
781 #endif
783 protected:
784 virtual ~CSSImportantRule(void);
786 nsCSSDeclaration* mDeclaration;
788 friend class CSSStyleRuleImpl;
791 CSSImportantRule::CSSImportantRule(nsCSSDeclaration* aDeclaration)
792 : mDeclaration(aDeclaration)
796 CSSImportantRule::~CSSImportantRule(void)
798 mDeclaration = nsnull;
801 NS_IMPL_ISUPPORTS1(CSSImportantRule, nsIStyleRule)
803 NS_IMETHODIMP
804 CSSImportantRule::MapRuleInfoInto(nsRuleData* aRuleData)
806 // Check this at runtime because it might be hit in some out-of-memory cases.
807 NS_ENSURE_TRUE(mDeclaration->HasImportantData(), NS_ERROR_UNEXPECTED);
809 return mDeclaration->MapImportantRuleInfoInto(aRuleData);
812 #ifdef DEBUG
813 NS_IMETHODIMP
814 CSSImportantRule::List(FILE* out, PRInt32 aIndent) const
816 // Indent
817 for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
819 fputs("! Important rule ", out);
820 if (nsnull != mDeclaration) {
821 mDeclaration->List(out);
823 else {
824 fputs("{ null declaration }", out);
826 fputs("\n", out);
828 return NS_OK;
830 #endif
832 // --------------------------------------------------------
834 class DOMCSSStyleRuleImpl;
836 class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration
838 public:
839 DOMCSSDeclarationImpl(nsICSSStyleRule *aRule);
840 virtual ~DOMCSSDeclarationImpl(void);
842 NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent);
843 virtual void DropReference(void);
844 virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl,
845 PRBool aAllocate);
846 virtual nsresult GetCSSParsingEnvironment(nsIURI** aSheetURI,
847 nsIURI** aBaseURI,
848 nsIPrincipal** aSheetPrincipal,
849 nsICSSLoader** aCSSLoader,
850 nsICSSParser** aCSSParser);
851 virtual nsresult DeclarationChanged();
853 // Override |AddRef| and |Release| for being a member of
854 // |DOMCSSStyleRuleImpl|.
855 NS_IMETHOD_(nsrefcnt) AddRef(void);
856 NS_IMETHOD_(nsrefcnt) Release(void);
858 friend class DOMCSSStyleRuleImpl;
860 protected:
861 // This reference is not reference-counted. The rule object tells us
862 // when it's about to go away.
863 nsICSSStyleRule *mRule;
865 inline DOMCSSStyleRuleImpl* DomRule();
867 private:
868 // NOT TO BE IMPLEMENTED
869 // This object cannot be allocated on its own. It must be a member of
870 // DOMCSSStyleRuleImpl.
871 void* operator new(size_t size) CPP_THROW_NEW;
874 class DOMCSSStyleRuleImpl : public nsICSSStyleRuleDOMWrapper
876 public:
877 DOMCSSStyleRuleImpl(nsICSSStyleRule *aRule);
878 virtual ~DOMCSSStyleRuleImpl();
880 NS_DECL_ISUPPORTS
881 NS_DECL_NSIDOMCSSRULE
882 NS_DECL_NSIDOMCSSSTYLERULE
884 // nsICSSStyleRuleDOMWrapper
885 NS_IMETHOD GetCSSStyleRule(nsICSSStyleRule **aResult);
887 DOMCSSDeclarationImpl* DOMDeclaration() { return &mDOMDeclaration; }
889 friend class DOMCSSDeclarationImpl;
891 protected:
892 DOMCSSDeclarationImpl mDOMDeclaration;
894 nsICSSStyleRule* Rule() {
895 return mDOMDeclaration.mRule;
899 DOMCSSDeclarationImpl::DOMCSSDeclarationImpl(nsICSSStyleRule *aRule)
900 : mRule(aRule)
902 MOZ_COUNT_CTOR(DOMCSSDeclarationImpl);
905 DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void)
907 NS_ASSERTION(!mRule, "DropReference not called.");
909 MOZ_COUNT_DTOR(DOMCSSDeclarationImpl);
912 inline DOMCSSStyleRuleImpl* DOMCSSDeclarationImpl::DomRule()
914 return reinterpret_cast<DOMCSSStyleRuleImpl*>
915 (reinterpret_cast<char*>(this) -
916 offsetof(DOMCSSStyleRuleImpl, mDOMDeclaration));
919 NS_IMPL_ADDREF_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule())
920 NS_IMPL_RELEASE_USING_AGGREGATOR(DOMCSSDeclarationImpl, DomRule())
922 void
923 DOMCSSDeclarationImpl::DropReference(void)
925 mRule = nsnull;
928 nsresult
929 DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl,
930 PRBool aAllocate)
932 if (mRule) {
933 *aDecl = mRule->GetDeclaration();
935 else {
936 *aDecl = nsnull;
939 return NS_OK;
943 * This is a utility function. It will only fail if it can't get a
944 * parser. This means it can return NS_OK without aURI or aCSSLoader
945 * being initialized.
947 nsresult
948 DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aSheetURI,
949 nsIURI** aBaseURI,
950 nsIPrincipal** aSheetPrincipal,
951 nsICSSLoader** aCSSLoader,
952 nsICSSParser** aCSSParser)
954 // null out the out params since some of them may not get initialized below
955 *aSheetURI = nsnull;
956 *aBaseURI = nsnull;
957 *aSheetPrincipal = nsnull;
958 *aCSSLoader = nsnull;
959 *aCSSParser = nsnull;
960 nsresult result;
961 nsCOMPtr<nsIStyleSheet> sheet;
962 if (mRule) {
963 mRule->GetStyleSheet(*getter_AddRefs(sheet));
964 if (sheet) {
965 sheet->GetSheetURI(aSheetURI);
966 sheet->GetBaseURI(aBaseURI);
968 nsCOMPtr<nsICSSStyleSheet> cssSheet(do_QueryInterface(sheet));
969 if (cssSheet) {
970 NS_ADDREF(*aSheetPrincipal = cssSheet->Principal());
973 nsCOMPtr<nsIDocument> document;
974 sheet->GetOwningDocument(*getter_AddRefs(document));
975 if (document) {
976 NS_ADDREF(*aCSSLoader = document->CSSLoader());
980 // XXXldb Why bother if |mRule| is null?
981 if (*aCSSLoader) {
982 result = (*aCSSLoader)->GetParserFor(nsnull, aCSSParser);
983 } else {
984 result = NS_NewCSSParser(aCSSParser);
987 if (NS_SUCCEEDED(result) && !*aSheetPrincipal) {
988 result = CallCreateInstance("@mozilla.org/nullprincipal;1",
989 aSheetPrincipal);
992 return result;
995 NS_IMETHODIMP
996 DOMCSSDeclarationImpl::GetParentRule(nsIDOMCSSRule **aParent)
998 NS_ENSURE_ARG_POINTER(aParent);
1000 if (!mRule) {
1001 *aParent = nsnull;
1002 return NS_OK;
1005 return mRule->GetDOMRule(aParent);
1008 nsresult
1009 DOMCSSDeclarationImpl::DeclarationChanged()
1011 NS_PRECONDITION(mRule,
1012 "can only be called when |GetCSSDeclaration| returned a declaration");
1014 nsCOMPtr<nsIDocument> owningDoc;
1015 nsCOMPtr<nsIStyleSheet> sheet;
1016 mRule->GetStyleSheet(*getter_AddRefs(sheet));
1017 if (sheet) {
1018 sheet->GetOwningDocument(*getter_AddRefs(owningDoc));
1021 mozAutoDocUpdate updateBatch(owningDoc, UPDATE_STYLE, PR_TRUE);
1023 nsCOMPtr<nsICSSStyleRule> oldRule = mRule;
1024 mRule = oldRule->DeclarationChanged(PR_TRUE).get();
1025 if (!mRule)
1026 return NS_ERROR_OUT_OF_MEMORY;
1027 nsrefcnt cnt = mRule->Release();
1028 if (cnt == 0) {
1029 NS_NOTREACHED("container didn't take ownership");
1030 mRule = nsnull;
1031 return NS_ERROR_UNEXPECTED;
1034 if (owningDoc) {
1035 owningDoc->StyleRuleChanged(sheet, oldRule, mRule);
1037 return NS_OK;
1040 DOMCSSStyleRuleImpl::DOMCSSStyleRuleImpl(nsICSSStyleRule* aRule)
1041 : mDOMDeclaration(aRule)
1045 DOMCSSStyleRuleImpl::~DOMCSSStyleRuleImpl()
1049 NS_INTERFACE_MAP_BEGIN(DOMCSSStyleRuleImpl)
1050 NS_INTERFACE_MAP_ENTRY(nsICSSStyleRuleDOMWrapper)
1051 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleRule)
1052 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1053 NS_INTERFACE_MAP_ENTRY(nsISupports)
1054 NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSStyleRule)
1055 NS_INTERFACE_MAP_END
1057 NS_IMPL_ADDREF(DOMCSSStyleRuleImpl)
1058 NS_IMPL_RELEASE(DOMCSSStyleRuleImpl)
1060 NS_IMETHODIMP
1061 DOMCSSStyleRuleImpl::GetType(PRUint16* aType)
1063 *aType = nsIDOMCSSRule::STYLE_RULE;
1065 return NS_OK;
1068 NS_IMETHODIMP
1069 DOMCSSStyleRuleImpl::GetCssText(nsAString& aCssText)
1071 if (!Rule()) {
1072 aCssText.Truncate();
1073 return NS_OK;
1075 return Rule()->GetCssText(aCssText);
1078 NS_IMETHODIMP
1079 DOMCSSStyleRuleImpl::SetCssText(const nsAString& aCssText)
1081 if (!Rule()) {
1082 return NS_OK;
1084 return Rule()->SetCssText(aCssText);
1087 NS_IMETHODIMP
1088 DOMCSSStyleRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1090 if (!Rule()) {
1091 *aSheet = nsnull;
1092 return NS_OK;
1094 nsCOMPtr<nsICSSStyleSheet> sheet;
1095 Rule()->GetParentStyleSheet(getter_AddRefs(sheet));
1096 if (!sheet) {
1097 *aSheet = nsnull;
1098 return NS_OK;
1100 return CallQueryInterface(sheet, aSheet);
1103 NS_IMETHODIMP
1104 DOMCSSStyleRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
1106 if (!Rule()) {
1107 *aParentRule = nsnull;
1108 return NS_OK;
1110 nsCOMPtr<nsICSSGroupRule> rule;
1111 Rule()->GetParentRule(getter_AddRefs(rule));
1112 if (!rule) {
1113 *aParentRule = nsnull;
1114 return NS_OK;
1116 return rule->GetDOMRule(aParentRule);
1119 NS_IMETHODIMP
1120 DOMCSSStyleRuleImpl::GetSelectorText(nsAString& aSelectorText)
1122 if (!Rule()) {
1123 aSelectorText.Truncate();
1124 return NS_OK;
1126 return Rule()->GetSelectorText(aSelectorText);
1129 NS_IMETHODIMP
1130 DOMCSSStyleRuleImpl::SetSelectorText(const nsAString& aSelectorText)
1132 if (!Rule()) {
1133 return NS_OK;
1135 return Rule()->SetSelectorText(aSelectorText);
1138 NS_IMETHODIMP
1139 DOMCSSStyleRuleImpl::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1141 *aStyle = &mDOMDeclaration;
1142 NS_ADDREF(*aStyle);
1143 return NS_OK;
1146 NS_IMETHODIMP
1147 DOMCSSStyleRuleImpl::GetCSSStyleRule(nsICSSStyleRule **aResult)
1149 *aResult = Rule();
1150 NS_IF_ADDREF(*aResult);
1151 return NS_OK;
1154 // -- nsCSSStyleRule -------------------------------
1156 class CSSStyleRuleImpl : public nsCSSRule,
1157 public nsICSSStyleRule
1159 public:
1160 CSSStyleRuleImpl(nsCSSSelectorList* aSelector,
1161 nsCSSDeclaration *aDeclaration);
1162 private:
1163 // for |Clone|
1164 CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy);
1165 // for |DeclarationChanged|
1166 CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy,
1167 nsCSSDeclaration *aDeclaration);
1168 public:
1170 NS_DECL_ISUPPORTS_INHERITED
1172 virtual nsCSSSelectorList* Selector(void);
1174 virtual PRUint32 GetLineNumber(void) const;
1175 virtual void SetLineNumber(PRUint32 aLineNumber);
1177 virtual nsCSSDeclaration* GetDeclaration(void) const;
1179 virtual already_AddRefed<nsIStyleRule> GetImportantRule(void);
1181 NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const;
1182 NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet);
1184 NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule);
1186 virtual nsresult GetCssText(nsAString& aCssText);
1187 virtual nsresult SetCssText(const nsAString& aCssText);
1188 virtual nsresult GetParentStyleSheet(nsICSSStyleSheet** aSheet);
1189 virtual nsresult GetParentRule(nsICSSGroupRule** aParentRule);
1190 virtual nsresult GetSelectorText(nsAString& aSelectorText);
1191 virtual nsresult SetSelectorText(const nsAString& aSelectorText);
1193 NS_IMETHOD GetType(PRInt32& aType) const;
1194 NS_IMETHOD Clone(nsICSSRule*& aClone) const;
1196 nsIDOMCSSRule* GetDOMRuleWeak(nsresult* aResult);
1198 virtual already_AddRefed<nsICSSStyleRule>
1199 DeclarationChanged(PRBool aHandleContainer);
1201 // The new mapping function.
1202 NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
1204 #ifdef DEBUG
1205 NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
1206 #endif
1208 private:
1209 // These are not supported and are not implemented!
1210 CSSStyleRuleImpl& operator=(const CSSStyleRuleImpl& aCopy);
1212 protected:
1213 virtual ~CSSStyleRuleImpl(void);
1215 protected:
1216 nsCSSSelectorList* mSelector; // null for style attribute
1217 nsCSSDeclaration* mDeclaration;
1218 CSSImportantRule* mImportantRule;
1219 DOMCSSStyleRuleImpl* mDOMRule;
1220 PRUint32 mLineNumber;
1223 CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector,
1224 nsCSSDeclaration* aDeclaration)
1225 : nsCSSRule(),
1226 mSelector(aSelector),
1227 mDeclaration(aDeclaration),
1228 mImportantRule(nsnull),
1229 mDOMRule(nsnull),
1230 mLineNumber(0)
1232 mDeclaration->AddRef();
1235 // for |Clone|
1236 CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy)
1237 : nsCSSRule(aCopy),
1238 mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nsnull),
1239 mDeclaration(aCopy.mDeclaration->Clone()),
1240 mImportantRule(nsnull),
1241 mDOMRule(nsnull),
1242 mLineNumber(aCopy.mLineNumber)
1244 if (mDeclaration)
1245 mDeclaration->AddRef();
1246 // rest is constructed lazily on existing data
1249 // for |DeclarationChanged|
1250 CSSStyleRuleImpl::CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy,
1251 nsCSSDeclaration* aDeclaration)
1252 : nsCSSRule(aCopy),
1253 mSelector(aCopy.mSelector),
1254 mDeclaration(aDeclaration),
1255 mImportantRule(nsnull),
1256 mDOMRule(aCopy.mDOMRule),
1257 mLineNumber(aCopy.mLineNumber)
1259 // The DOM rule is replacing |aCopy| with |this|, so transfer
1260 // the reverse pointer as well (and transfer ownership).
1261 aCopy.mDOMRule = nsnull;
1263 NS_ASSERTION(aDeclaration == aCopy.mDeclaration, "declaration mismatch");
1264 // Transfer ownership of selector and declaration:
1265 aCopy.mSelector = nsnull;
1266 #if 0
1267 aCopy.mDeclaration = nsnull;
1268 #else
1269 // We ought to be able to transfer ownership of the selector and the
1270 // declaration since this rule should now be unused, but unfortunately
1271 // SetInlineStyleRule might use it before setting the new rule (see
1272 // stack in bug 209575). So leave the declaration pointer on the old
1273 // rule.
1274 mDeclaration->AddRef();
1275 #endif
1279 CSSStyleRuleImpl::~CSSStyleRuleImpl(void)
1281 if (mSelector) {
1282 delete mSelector;
1283 mSelector = nsnull;
1285 if (nsnull != mDeclaration) {
1286 mDeclaration->Release();
1287 mDeclaration = nsnull;
1289 if (nsnull != mImportantRule) {
1290 NS_RELEASE(mImportantRule);
1291 mImportantRule = nsnull;
1293 if (mDOMRule) {
1294 mDOMRule->DOMDeclaration()->DropReference();
1295 NS_RELEASE(mDOMRule);
1299 // QueryInterface implementation for CSSStyleRuleImpl
1300 NS_INTERFACE_MAP_BEGIN(CSSStyleRuleImpl)
1301 NS_INTERFACE_MAP_ENTRY(nsICSSStyleRule)
1302 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1303 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1304 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSStyleRule)
1305 NS_INTERFACE_MAP_END
1307 NS_IMPL_ADDREF_INHERITED(CSSStyleRuleImpl, nsCSSRule)
1308 NS_IMPL_RELEASE_INHERITED(CSSStyleRuleImpl, nsCSSRule)
1310 nsCSSSelectorList* CSSStyleRuleImpl::Selector(void)
1312 return mSelector;
1315 PRUint32 CSSStyleRuleImpl::GetLineNumber(void) const
1317 return mLineNumber;
1320 void CSSStyleRuleImpl::SetLineNumber(PRUint32 aLineNumber)
1322 mLineNumber = aLineNumber;
1325 nsCSSDeclaration* CSSStyleRuleImpl::GetDeclaration(void) const
1327 return mDeclaration;
1330 already_AddRefed<nsIStyleRule> CSSStyleRuleImpl::GetImportantRule(void)
1332 if (!mDeclaration->HasImportantData()) {
1333 NS_ASSERTION(!mImportantRule, "immutable, so should be no important rule");
1334 return nsnull;
1337 if (!mImportantRule) {
1338 mImportantRule = new CSSImportantRule(mDeclaration);
1339 if (!mImportantRule)
1340 return nsnull;
1341 NS_ADDREF(mImportantRule);
1343 NS_ADDREF(mImportantRule);
1344 return mImportantRule;
1347 NS_IMETHODIMP
1348 CSSStyleRuleImpl::GetStyleSheet(nsIStyleSheet*& aSheet) const
1350 // XXX What about inner, etc.
1351 return nsCSSRule::GetStyleSheet(aSheet);
1354 NS_IMETHODIMP
1355 CSSStyleRuleImpl::SetStyleSheet(nsICSSStyleSheet* aSheet)
1357 return nsCSSRule::SetStyleSheet(aSheet);
1360 NS_IMETHODIMP
1361 CSSStyleRuleImpl::SetParentRule(nsICSSGroupRule* aRule)
1363 return nsCSSRule::SetParentRule(aRule);
1366 NS_IMETHODIMP
1367 CSSStyleRuleImpl::GetType(PRInt32& aType) const
1369 aType = nsICSSRule::STYLE_RULE;
1370 return NS_OK;
1373 NS_IMETHODIMP
1374 CSSStyleRuleImpl::Clone(nsICSSRule*& aClone) const
1376 CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this);
1377 if (!clone || !clone->mDeclaration || (!clone->mSelector != !mSelector)) {
1378 delete clone;
1379 aClone = nsnull;
1380 return NS_ERROR_OUT_OF_MEMORY;
1382 return CallQueryInterface(clone, &aClone);
1385 nsIDOMCSSRule*
1386 CSSStyleRuleImpl::GetDOMRuleWeak(nsresult *aResult)
1388 *aResult = NS_OK;
1389 if (!mSheet) {
1390 // inline style rules aren't supposed to have a DOM rule object, only
1391 // a declaration.
1392 return nsnull;
1394 if (!mDOMRule) {
1395 mDOMRule = new DOMCSSStyleRuleImpl(this);
1396 if (!mDOMRule) {
1397 *aResult = NS_ERROR_OUT_OF_MEMORY;
1398 return nsnull;
1400 NS_ADDREF(mDOMRule);
1402 return mDOMRule;
1405 /* virtual */ already_AddRefed<nsICSSStyleRule>
1406 CSSStyleRuleImpl::DeclarationChanged(PRBool aHandleContainer)
1408 CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this, mDeclaration);
1409 if (!clone) {
1410 return nsnull;
1413 NS_ADDREF(clone); // for return
1415 if (aHandleContainer) {
1416 NS_ASSERTION(mSheet, "rule must be in a sheet");
1417 if (mParentRule) {
1418 mSheet->ReplaceRuleInGroup(mParentRule, this, clone);
1419 } else {
1420 mSheet->ReplaceStyleRule(this, clone);
1424 return clone;
1427 NS_IMETHODIMP
1428 CSSStyleRuleImpl::MapRuleInfoInto(nsRuleData* aRuleData)
1430 return mDeclaration->MapRuleInfoInto(aRuleData);
1433 #ifdef DEBUG
1434 NS_IMETHODIMP
1435 CSSStyleRuleImpl::List(FILE* out, PRInt32 aIndent) const
1437 // Indent
1438 for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
1440 nsAutoString buffer;
1441 if (mSelector)
1442 mSelector->ToString(buffer, mSheet);
1444 buffer.AppendLiteral(" ");
1445 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
1446 if (nsnull != mDeclaration) {
1447 mDeclaration->List(out);
1449 else {
1450 fputs("{ null declaration }", out);
1452 fputs("\n", out);
1454 return NS_OK;
1456 #endif
1458 /* virtual */ nsresult
1459 CSSStyleRuleImpl::GetCssText(nsAString& aCssText)
1461 if (mSelector) {
1462 mSelector->ToString(aCssText, mSheet);
1463 aCssText.Append(PRUnichar(' '));
1465 aCssText.Append(PRUnichar('{'));
1466 aCssText.Append(PRUnichar(' '));
1467 if (mDeclaration)
1469 nsAutoString tempString;
1470 mDeclaration->ToString( tempString );
1471 aCssText.Append( tempString );
1473 aCssText.Append(PRUnichar(' '));
1474 aCssText.Append(PRUnichar('}'));
1475 return NS_OK;
1478 /* virtual */ nsresult
1479 CSSStyleRuleImpl::SetCssText(const nsAString& aCssText)
1481 // XXX TBI - need to re-parse rule & declaration
1482 return NS_OK;
1485 /* virtual */ nsresult
1486 CSSStyleRuleImpl::GetParentStyleSheet(nsICSSStyleSheet** aSheet)
1488 *aSheet = mSheet;
1489 NS_IF_ADDREF(*aSheet);
1490 return NS_OK;
1493 /* virtual */ nsresult
1494 CSSStyleRuleImpl::GetParentRule(nsICSSGroupRule** aParentRule)
1496 *aParentRule = mParentRule;
1497 NS_IF_ADDREF(*aParentRule);
1498 return NS_OK;
1501 /* virtual */ nsresult
1502 CSSStyleRuleImpl::GetSelectorText(nsAString& aSelectorText)
1504 if (mSelector)
1505 mSelector->ToString(aSelectorText, mSheet);
1506 else
1507 aSelectorText.Truncate();
1508 return NS_OK;
1511 /* virtual */ nsresult
1512 CSSStyleRuleImpl::SetSelectorText(const nsAString& aSelectorText)
1514 // XXX TBI - get a parser and re-parse the selectors,
1515 // XXX then need to re-compute the cascade
1516 // XXX and dirty sheet
1517 return NS_OK;
1520 nsresult
1521 NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult,
1522 nsCSSSelectorList* aSelector,
1523 nsCSSDeclaration* aDeclaration)
1525 NS_PRECONDITION(aDeclaration, "must have a declaration");
1526 CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector, aDeclaration);
1527 if (!it) {
1528 return NS_ERROR_OUT_OF_MEMORY;
1531 return CallQueryInterface(it, aInstancePtrResult);