CLOSED TREE: TraceMonkey merge head. (a=blockers)
[mozilla-central.git] / layout / style / nsCSSRules.cpp
blobbbff869d4ae034ab3d46a0eb52acf32d7c2e6d51
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) 1999
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Boris Zbarsky <bzbarsky@mit.edu>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
41 #include "nsCSSRules.h"
42 #include "nsCSSValue.h"
43 #include "nsICSSImportRule.h"
44 #include "nsICSSNameSpaceRule.h"
46 #include "nsString.h"
47 #include "nsIAtom.h"
48 #include "nsIURL.h"
50 #include "nsCSSRule.h"
51 #include "nsCSSProps.h"
52 #include "nsCSSStyleSheet.h"
54 #include "nsCOMPtr.h"
55 #include "nsIDOMCSSStyleSheet.h"
56 #include "nsIDOMCSSRule.h"
57 #include "nsIDOMCSSImportRule.h"
58 #include "nsIDOMCSSMediaRule.h"
59 #include "nsIDOMCSSMozDocumentRule.h"
60 #include "nsIDOMCSSCharsetRule.h"
61 #include "nsIDOMCSSStyleDeclaration.h"
62 #include "nsIMediaList.h"
63 #include "nsIDOMMediaList.h"
64 #include "nsICSSRuleList.h"
65 #include "nsIDOMStyleSheet.h"
66 #include "nsIDocument.h"
67 #include "nsPresContext.h"
69 #include "nsContentUtils.h"
70 #include "nsStyleConsts.h"
71 #include "nsDOMError.h"
72 #include "nsStyleUtil.h"
73 #include "mozilla/css/Declaration.h"
74 #include "nsPrintfCString.h"
76 #define IMPL_STYLE_RULE_INHERIT(_class, super) \
77 /* virtual */ already_AddRefed<nsIStyleSheet> _class::GetStyleSheet() const { return super::GetStyleSheet(); } \
78 /* virtual */ void _class::SetStyleSheet(nsCSSStyleSheet* aSheet) { super::SetStyleSheet(aSheet); } \
79 /* virtual */ void _class::SetParentRule(nsICSSGroupRule* aRule) { super::SetParentRule(aRule); } \
80 nsIDOMCSSRule* _class::GetDOMRuleWeak(nsresult *aResult) { *aResult = NS_OK; return this; } \
81 /* virtual */ void _class::MapRuleInfoInto(nsRuleData* aRuleData) { }
83 #define IMPL_STYLE_RULE_INHERIT2(_class, super) \
84 /* virtual */ already_AddRefed<nsIStyleSheet> _class::GetStyleSheet() const { return super::GetStyleSheet(); } \
85 /* virtual */ void _class::SetParentRule(nsICSSGroupRule* aRule) { super::SetParentRule(aRule); } \
86 /* virtual */ void _class::MapRuleInfoInto(nsRuleData* aRuleData) { }
88 // -------------------------------
89 // Style Rule List for group rules
91 class CSSGroupRuleRuleListImpl : public nsICSSRuleList
93 public:
94 CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule);
96 NS_DECL_ISUPPORTS
98 NS_DECL_NSIDOMCSSRULELIST
100 virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult);
102 void DropReference() { mGroupRule = nsnull; }
104 protected:
105 virtual ~CSSGroupRuleRuleListImpl(void);
107 private:
108 nsICSSGroupRule* mGroupRule;
111 CSSGroupRuleRuleListImpl::CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule)
113 // Not reference counted to avoid circular references.
114 // The rule will tell us when its going away.
115 mGroupRule = aGroupRule;
118 CSSGroupRuleRuleListImpl::~CSSGroupRuleRuleListImpl()
122 DOMCI_DATA(CSSGroupRuleRuleList, CSSGroupRuleRuleListImpl)
124 // QueryInterface implementation for CSSGroupRuleRuleList
125 NS_INTERFACE_MAP_BEGIN(CSSGroupRuleRuleListImpl)
126 NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
127 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
128 NS_INTERFACE_MAP_ENTRY(nsISupports)
129 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSGroupRuleRuleList)
130 NS_INTERFACE_MAP_END
133 NS_IMPL_ADDREF(CSSGroupRuleRuleListImpl)
134 NS_IMPL_RELEASE(CSSGroupRuleRuleListImpl)
136 NS_IMETHODIMP
137 CSSGroupRuleRuleListImpl::GetLength(PRUint32* aLength)
139 if (mGroupRule) {
140 PRInt32 count;
141 mGroupRule->StyleRuleCount(count);
142 *aLength = (PRUint32)count;
143 } else {
144 *aLength = 0;
147 return NS_OK;
150 nsIDOMCSSRule*
151 CSSGroupRuleRuleListImpl::GetItemAt(PRUint32 aIndex, nsresult* aResult)
153 nsresult result = NS_OK;
155 if (mGroupRule) {
156 nsCOMPtr<nsICSSRule> rule;
158 result = mGroupRule->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
159 if (rule) {
160 return rule->GetDOMRuleWeak(aResult);
162 if (result == NS_ERROR_ILLEGAL_VALUE) {
163 result = NS_OK; // per spec: "Return Value ... null if ... not a valid index."
167 *aResult = result;
169 return nsnull;
172 NS_IMETHODIMP
173 CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
175 nsresult rv;
176 nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
177 if (!rule) {
178 *aReturn = nsnull;
179 return rv;
182 NS_ADDREF(*aReturn = rule);
183 return NS_OK;
186 // -------------------------------------------
187 // CharsetRule
189 class NS_FINAL_CLASS CSSCharsetRuleImpl : public nsCSSRule,
190 public nsICSSRule,
191 public nsIDOMCSSCharsetRule
193 public:
194 CSSCharsetRuleImpl(const nsAString& aEncoding);
195 CSSCharsetRuleImpl(const CSSCharsetRuleImpl& aCopy);
196 private:
197 ~CSSCharsetRuleImpl() {}
198 public:
199 NS_DECL_ISUPPORTS
201 DECL_STYLE_RULE_INHERIT
203 // nsIStyleRule methods
204 #ifdef DEBUG
205 virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
206 #endif
208 // nsICSSRule methods
209 virtual PRInt32 GetType() const;
210 virtual already_AddRefed<nsICSSRule> Clone() const;
212 // nsIDOMCSSRule interface
213 NS_DECL_NSIDOMCSSRULE
215 // nsIDOMCSSCharsetRule methods
216 NS_IMETHOD GetEncoding(nsAString& aEncoding);
217 NS_IMETHOD SetEncoding(const nsAString& aEncoding);
219 protected:
220 nsString mEncoding;
223 CSSCharsetRuleImpl::CSSCharsetRuleImpl(const nsAString& aEncoding)
224 : nsCSSRule(),
225 mEncoding(aEncoding)
229 CSSCharsetRuleImpl::CSSCharsetRuleImpl(const CSSCharsetRuleImpl& aCopy)
230 : nsCSSRule(aCopy),
231 mEncoding(aCopy.mEncoding)
235 NS_IMPL_ADDREF(CSSCharsetRuleImpl)
236 NS_IMPL_RELEASE(CSSCharsetRuleImpl)
238 DOMCI_DATA(CSSCharsetRule, CSSCharsetRuleImpl)
240 // QueryInterface implementation for CSSCharsetRuleImpl
241 NS_INTERFACE_MAP_BEGIN(CSSCharsetRuleImpl)
242 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
243 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
244 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
245 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule)
246 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule)
247 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCharsetRule)
248 NS_INTERFACE_MAP_END
250 IMPL_STYLE_RULE_INHERIT(CSSCharsetRuleImpl, nsCSSRule)
252 #ifdef DEBUG
253 /* virtual */ void
254 CSSCharsetRuleImpl::List(FILE* out, PRInt32 aIndent) const
256 // Indent
257 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
259 fputs("@charset \"", out);
260 fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out);
261 fputs("\"\n", out);
263 #endif
265 /* virtual */ PRInt32
266 CSSCharsetRuleImpl::GetType() const
268 return nsICSSRule::CHARSET_RULE;
271 /* virtual */ already_AddRefed<nsICSSRule>
272 CSSCharsetRuleImpl::Clone() const
274 nsCOMPtr<nsICSSRule> clone = new CSSCharsetRuleImpl(*this);
275 return clone.forget();
278 NS_IMETHODIMP
279 CSSCharsetRuleImpl::GetEncoding(nsAString& aEncoding)
281 aEncoding = mEncoding;
282 return NS_OK;
285 NS_IMETHODIMP
286 CSSCharsetRuleImpl::SetEncoding(const nsAString& aEncoding)
288 mEncoding = aEncoding;
289 return NS_OK;
293 nsresult
294 NS_NewCSSCharsetRule(nsICSSRule** aInstancePtrResult, const nsAString& aEncoding)
296 if (! aInstancePtrResult) {
297 return NS_ERROR_NULL_POINTER;
300 CSSCharsetRuleImpl* it = new CSSCharsetRuleImpl(aEncoding);
302 if (!it) {
303 return NS_ERROR_OUT_OF_MEMORY;
306 NS_ADDREF(*aInstancePtrResult = it);
307 return NS_OK;
310 NS_IMETHODIMP
311 CSSCharsetRuleImpl::GetType(PRUint16* aType)
313 *aType = nsIDOMCSSRule::CHARSET_RULE;
314 return NS_OK;
317 NS_IMETHODIMP
318 CSSCharsetRuleImpl::GetCssText(nsAString& aCssText)
320 aCssText.AssignLiteral("@charset \"");
321 aCssText.Append(mEncoding);
322 aCssText.AppendLiteral("\";");
323 return NS_OK;
326 NS_IMETHODIMP
327 CSSCharsetRuleImpl::SetCssText(const nsAString& aCssText)
329 return NS_ERROR_NOT_IMPLEMENTED;
332 NS_IMETHODIMP
333 CSSCharsetRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
335 NS_ENSURE_ARG_POINTER(aSheet);
337 NS_IF_ADDREF(*aSheet = mSheet);
338 return NS_OK;
341 NS_IMETHODIMP
342 CSSCharsetRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
344 if (mParentRule) {
345 return mParentRule->GetDOMRule(aParentRule);
347 *aParentRule = nsnull;
348 return NS_OK;
353 // -------------------------------------------
354 // nsICSSImportRule
356 class NS_FINAL_CLASS CSSImportRuleImpl : public nsCSSRule,
357 public nsICSSImportRule,
358 public nsIDOMCSSImportRule
360 public:
361 CSSImportRuleImpl(nsMediaList* aMedia);
362 CSSImportRuleImpl(const CSSImportRuleImpl& aCopy);
363 private:
364 ~CSSImportRuleImpl();
365 public:
367 NS_DECL_ISUPPORTS
369 DECL_STYLE_RULE_INHERIT
371 // nsIStyleRule methods
372 #ifdef DEBUG
373 virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
374 #endif
376 // nsICSSRule methods
377 virtual PRInt32 GetType() const;
378 virtual already_AddRefed<nsICSSRule> Clone() const;
380 // nsICSSImportRule methods
381 NS_IMETHOD SetURLSpec(const nsString& aURLSpec);
382 NS_IMETHOD GetURLSpec(nsString& aURLSpec) const;
384 NS_IMETHOD SetMedia(const nsString& aMedia);
385 NS_IMETHOD GetMedia(nsString& aMedia) const;
387 NS_IMETHOD SetSheet(nsCSSStyleSheet*);
389 // nsIDOMCSSRule interface
390 NS_DECL_NSIDOMCSSRULE
392 // nsIDOMCSSImportRule interface
393 NS_DECL_NSIDOMCSSIMPORTRULE
395 protected:
396 nsString mURLSpec;
397 nsRefPtr<nsMediaList> mMedia;
398 nsRefPtr<nsCSSStyleSheet> mChildSheet;
401 CSSImportRuleImpl::CSSImportRuleImpl(nsMediaList* aMedia)
402 : nsCSSRule()
403 , mURLSpec()
404 , mMedia(aMedia)
406 // XXXbz This is really silly.... the mMedia here will be replaced
407 // with itself if we manage to load a sheet. Which should really
408 // never fail nowadays, in sane cases.
411 CSSImportRuleImpl::CSSImportRuleImpl(const CSSImportRuleImpl& aCopy)
412 : nsCSSRule(aCopy),
413 mURLSpec(aCopy.mURLSpec)
415 nsRefPtr<nsCSSStyleSheet> sheet;
416 if (aCopy.mChildSheet) {
417 sheet = aCopy.mChildSheet->Clone(nsnull, this, nsnull, nsnull);
419 SetSheet(sheet);
420 // SetSheet sets mMedia appropriately
423 CSSImportRuleImpl::~CSSImportRuleImpl()
425 if (mChildSheet) {
426 mChildSheet->SetOwnerRule(nsnull);
430 NS_IMPL_ADDREF(CSSImportRuleImpl)
431 NS_IMPL_RELEASE(CSSImportRuleImpl)
433 DOMCI_DATA(CSSImportRule, CSSImportRuleImpl)
435 // QueryInterface implementation for CSSImportRuleImpl
436 NS_INTERFACE_MAP_BEGIN(CSSImportRuleImpl)
437 NS_INTERFACE_MAP_ENTRY(nsICSSImportRule)
438 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
439 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
440 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
441 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
442 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSImportRule)
443 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
444 NS_INTERFACE_MAP_END
446 IMPL_STYLE_RULE_INHERIT(CSSImportRuleImpl, nsCSSRule)
448 #ifdef DEBUG
449 /* virtual */ void
450 CSSImportRuleImpl::List(FILE* out, PRInt32 aIndent) const
452 // Indent
453 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
455 fputs("@import \"", out);
456 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
457 fputs("\" ", out);
459 nsAutoString mediaText;
460 mMedia->GetText(mediaText);
461 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
462 fputs("\n", out);
464 #endif
466 /* virtual */ PRInt32
467 CSSImportRuleImpl::GetType() const
469 return nsICSSRule::IMPORT_RULE;
472 /* virtual */ already_AddRefed<nsICSSRule>
473 CSSImportRuleImpl::Clone() const
475 nsCOMPtr<nsICSSRule> clone = new CSSImportRuleImpl(*this);
476 return clone.forget();
479 NS_IMETHODIMP
480 CSSImportRuleImpl::SetURLSpec(const nsString& aURLSpec)
482 mURLSpec = aURLSpec;
483 return NS_OK;
486 NS_IMETHODIMP
487 CSSImportRuleImpl::GetURLSpec(nsString& aURLSpec) const
489 aURLSpec = mURLSpec;
490 return NS_OK;
493 NS_IMETHODIMP
494 CSSImportRuleImpl::SetMedia(const nsString& aMedia)
496 if (mMedia) {
497 return mMedia->SetText(aMedia);
498 } else {
499 return NS_OK;
503 NS_IMETHODIMP
504 CSSImportRuleImpl::GetMedia(nsString& aMedia) const
506 if (mMedia) {
507 return mMedia->GetText(aMedia);
508 } else {
509 aMedia.Truncate();
510 return NS_OK;
514 NS_IMETHODIMP
515 CSSImportRuleImpl::SetSheet(nsCSSStyleSheet* aSheet)
517 nsresult rv;
518 NS_ENSURE_ARG_POINTER(aSheet);
520 // set the new sheet
521 mChildSheet = aSheet;
522 aSheet->SetOwnerRule(this);
524 // set our medialist to be the same as the sheet's medialist
525 nsCOMPtr<nsIDOMMediaList> mediaList;
526 rv = mChildSheet->GetMedia(getter_AddRefs(mediaList));
527 NS_ENSURE_SUCCESS(rv, rv);
528 mMedia = static_cast<nsMediaList*>(mediaList.get());
530 return NS_OK;
533 nsresult
534 NS_NewCSSImportRule(nsICSSImportRule** aInstancePtrResult,
535 const nsString& aURLSpec,
536 nsMediaList* aMedia)
538 NS_ENSURE_ARG_POINTER(aInstancePtrResult);
540 CSSImportRuleImpl* it = new CSSImportRuleImpl(aMedia);
542 if (!it) {
543 return NS_ERROR_OUT_OF_MEMORY;
546 it->SetURLSpec(aURLSpec);
547 NS_ADDREF(*aInstancePtrResult = it);
548 return NS_OK;
551 NS_IMETHODIMP
552 CSSImportRuleImpl::GetType(PRUint16* aType)
554 NS_ENSURE_ARG_POINTER(aType);
555 *aType = nsIDOMCSSRule::IMPORT_RULE;
556 return NS_OK;
559 NS_IMETHODIMP
560 CSSImportRuleImpl::GetCssText(nsAString& aCssText)
562 aCssText.AssignLiteral("@import url(");
563 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
564 aCssText.Append(NS_LITERAL_STRING(")"));
565 if (mMedia) {
566 nsAutoString mediaText;
567 mMedia->GetText(mediaText);
568 if (!mediaText.IsEmpty()) {
569 aCssText.AppendLiteral(" ");
570 aCssText.Append(mediaText);
573 aCssText.AppendLiteral(";");
574 return NS_OK;
577 NS_IMETHODIMP
578 CSSImportRuleImpl::SetCssText(const nsAString& aCssText)
580 return NS_ERROR_NOT_IMPLEMENTED;
583 NS_IMETHODIMP
584 CSSImportRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
586 NS_ENSURE_ARG_POINTER(aSheet);
588 NS_IF_ADDREF(*aSheet = mSheet);
589 return NS_OK;
592 NS_IMETHODIMP
593 CSSImportRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
595 if (mParentRule) {
596 return mParentRule->GetDOMRule(aParentRule);
598 *aParentRule = nsnull;
599 return NS_OK;
602 NS_IMETHODIMP
603 CSSImportRuleImpl::GetHref(nsAString & aHref)
605 aHref = mURLSpec;
606 return NS_OK;
609 NS_IMETHODIMP
610 CSSImportRuleImpl::GetMedia(nsIDOMMediaList * *aMedia)
612 NS_ENSURE_ARG_POINTER(aMedia);
614 NS_IF_ADDREF(*aMedia = mMedia);
615 return NS_OK;
618 NS_IMETHODIMP
619 CSSImportRuleImpl::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
621 NS_ENSURE_ARG_POINTER(aStyleSheet);
623 NS_IF_ADDREF(*aStyleSheet = mChildSheet);
624 return NS_OK;
627 nsCSSGroupRule::nsCSSGroupRule()
628 : nsCSSRule()
629 , mRuleCollection(nsnull)
633 static PRBool
634 CloneRuleInto(nsICSSRule* aRule, void* aArray)
636 nsCOMPtr<nsICSSRule> clone = aRule->Clone();
637 static_cast<nsCOMArray<nsICSSRule>*>(aArray)->AppendObject(clone);
638 return PR_TRUE;
641 static PRBool
642 SetParentRuleReference(nsICSSRule* aRule, void* aParentRule)
644 nsCSSGroupRule* parentRule = static_cast<nsCSSGroupRule*>(aParentRule);
645 aRule->SetParentRule(parentRule);
646 return PR_TRUE;
649 nsCSSGroupRule::nsCSSGroupRule(const nsCSSGroupRule& aCopy)
650 : nsCSSRule(aCopy)
651 , mRuleCollection(nsnull) // lazily constructed
653 const_cast<nsCSSGroupRule&>(aCopy).mRules.EnumerateForwards(CloneRuleInto, &mRules);
654 mRules.EnumerateForwards(SetParentRuleReference, this);
657 nsCSSGroupRule::~nsCSSGroupRule()
659 mRules.EnumerateForwards(SetParentRuleReference, nsnull);
660 if (mRuleCollection) {
661 mRuleCollection->DropReference();
662 NS_RELEASE(mRuleCollection);
666 NS_IMPL_ADDREF(nsCSSGroupRule)
667 NS_IMPL_RELEASE(nsCSSGroupRule)
669 IMPL_STYLE_RULE_INHERIT2(nsCSSGroupRule, nsCSSRule)
671 static PRBool
672 SetStyleSheetReference(nsICSSRule* aRule, void* aSheet)
674 nsCSSStyleSheet* sheet = (nsCSSStyleSheet*)aSheet;
675 aRule->SetStyleSheet(sheet);
676 return PR_TRUE;
679 /* virtual */ void
680 nsCSSGroupRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
682 mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
683 nsCSSRule::SetStyleSheet(aSheet);
686 #ifdef DEBUG
687 /* virtual */ void
688 nsCSSGroupRule::List(FILE* out, PRInt32 aIndent) const
690 fputs(" {\n", out);
692 for (PRInt32 index = 0, count = mRules.Count(); index < count; ++index) {
693 mRules.ObjectAt(index)->List(out, aIndent + 1);
695 fputs("}\n", out);
697 #endif
699 NS_IMETHODIMP
700 nsCSSGroupRule::AppendStyleRule(nsICSSRule* aRule)
702 mRules.AppendObject(aRule);
703 aRule->SetStyleSheet(mSheet);
704 aRule->SetParentRule(this);
705 if (mSheet) {
706 // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and
707 // shouldn't |SetModified| be removed?
708 mSheet->SetModified(PR_TRUE);
710 return NS_OK;
713 NS_IMETHODIMP
714 nsCSSGroupRule::StyleRuleCount(PRInt32& aCount) const
716 aCount = mRules.Count();
717 return NS_OK;
720 NS_IMETHODIMP
721 nsCSSGroupRule::GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const
723 if (aIndex < 0 || aIndex >= mRules.Count()) {
724 aRule = nsnull;
725 return NS_ERROR_ILLEGAL_VALUE;
728 NS_ADDREF(aRule = mRules.ObjectAt(aIndex));
729 return NS_OK;
732 NS_IMETHODIMP_(PRBool)
733 nsCSSGroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
735 return
736 const_cast<nsCSSGroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
740 * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt)
741 * should never be called unless you have first called WillDirty() on
742 * the parents tylesheet. After they are called, DidDirty() needs to
743 * be called on the sheet
745 NS_IMETHODIMP
746 nsCSSGroupRule::DeleteStyleRuleAt(PRUint32 aIndex)
748 nsICSSRule* rule = mRules.SafeObjectAt(aIndex);
749 if (rule) {
750 rule->SetStyleSheet(nsnull);
751 rule->SetParentRule(nsnull);
753 return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
756 NS_IMETHODIMP
757 nsCSSGroupRule::InsertStyleRulesAt(PRUint32 aIndex,
758 nsCOMArray<nsICSSRule>& aRules)
760 aRules.EnumerateForwards(SetStyleSheetReference, mSheet);
761 aRules.EnumerateForwards(SetParentRuleReference, this);
762 if (! mRules.InsertObjectsAt(aRules, aIndex)) {
763 return NS_ERROR_FAILURE;
765 return NS_OK;
768 NS_IMETHODIMP
769 nsCSSGroupRule::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew)
771 PRInt32 index = mRules.IndexOf(aOld);
772 NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED);
773 mRules.ReplaceObjectAt(aNew, index);
774 aNew->SetStyleSheet(mSheet);
775 aNew->SetParentRule(this);
776 aOld->SetStyleSheet(nsnull);
777 aOld->SetParentRule(nsnull);
778 return NS_OK;
781 nsresult
782 nsCSSGroupRule::AppendRulesToCssText(nsAString& aCssText)
784 aCssText.AppendLiteral(" {\n");
786 // get all the rules
787 for (PRInt32 index = 0, count = mRules.Count(); index < count; ++index) {
788 nsICSSRule* rule = mRules.ObjectAt(index);
789 nsCOMPtr<nsIDOMCSSRule> domRule;
790 rule->GetDOMRule(getter_AddRefs(domRule));
791 if (domRule) {
792 nsAutoString cssText;
793 domRule->GetCssText(cssText);
794 aCssText.Append(NS_LITERAL_STRING(" ") +
795 cssText +
796 NS_LITERAL_STRING("\n"));
800 aCssText.AppendLiteral("}");
802 return NS_OK;
805 nsresult
806 nsCSSGroupRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
808 NS_IF_ADDREF(*aSheet = mSheet);
809 return NS_OK;
812 nsresult
813 nsCSSGroupRule::GetParentRule(nsIDOMCSSRule** aParentRule)
815 if (mParentRule) {
816 return mParentRule->GetDOMRule(aParentRule);
818 *aParentRule = nsnull;
819 return NS_OK;
822 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
823 nsresult
824 nsCSSGroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
826 if (!mRuleCollection) {
827 mRuleCollection = new CSSGroupRuleRuleListImpl(this);
828 if (!mRuleCollection) {
829 return NS_ERROR_OUT_OF_MEMORY;
831 NS_ADDREF(mRuleCollection);
834 NS_ADDREF(*aRuleList = mRuleCollection);
835 return NS_OK;
838 nsresult
839 nsCSSGroupRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
841 NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE);
843 if (aIndex > PRUint32(mRules.Count()))
844 return NS_ERROR_DOM_INDEX_SIZE_ERR;
846 NS_ASSERTION(PRUint32(mRules.Count()) <= PR_INT32_MAX,
847 "Too many style rules!");
849 return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
852 nsresult
853 nsCSSGroupRule::DeleteRule(PRUint32 aIndex)
855 NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE);
857 if (aIndex >= PRUint32(mRules.Count()))
858 return NS_ERROR_DOM_INDEX_SIZE_ERR;
860 NS_ASSERTION(PRUint32(mRules.Count()) <= PR_INT32_MAX,
861 "Too many style rules!");
863 return mSheet->DeleteRuleFromGroup(this, aIndex);
866 // -------------------------------------------
867 // nsICSSMediaRule
869 nsCSSMediaRule::nsCSSMediaRule()
873 nsCSSMediaRule::nsCSSMediaRule(const nsCSSMediaRule& aCopy)
874 : nsCSSGroupRule(aCopy)
876 if (aCopy.mMedia) {
877 aCopy.mMedia->Clone(getter_AddRefs(mMedia));
878 if (mMedia) {
879 // XXXldb This doesn't really make sense.
880 mMedia->SetStyleSheet(aCopy.mSheet);
885 nsCSSMediaRule::~nsCSSMediaRule()
887 if (mMedia) {
888 mMedia->SetStyleSheet(nsnull);
892 NS_IMPL_ADDREF_INHERITED(nsCSSMediaRule, nsCSSGroupRule)
893 NS_IMPL_RELEASE_INHERITED(nsCSSMediaRule, nsCSSGroupRule)
895 DOMCI_DATA(CSSMediaRule, nsCSSMediaRule)
897 // QueryInterface implementation for nsCSSMediaRule
898 NS_INTERFACE_MAP_BEGIN(nsCSSMediaRule)
899 NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule)
900 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
901 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
902 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
903 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
904 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule)
905 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
906 NS_INTERFACE_MAP_END
908 /* virtual */ void
909 nsCSSMediaRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
911 if (mMedia) {
912 // Set to null so it knows it's leaving one sheet and joining another.
913 mMedia->SetStyleSheet(nsnull);
914 mMedia->SetStyleSheet(aSheet);
917 nsCSSGroupRule::SetStyleSheet(aSheet);
920 #ifdef DEBUG
921 /* virtual */ void
922 nsCSSMediaRule::List(FILE* out, PRInt32 aIndent) const
924 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
926 nsAutoString buffer;
928 fputs("@media ", out);
930 if (mMedia) {
931 nsAutoString mediaText;
932 mMedia->GetText(mediaText);
933 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
936 nsCSSGroupRule::List(out, aIndent);
938 #endif
940 /* virtual */ PRInt32
941 nsCSSMediaRule::GetType() const
943 return nsICSSRule::MEDIA_RULE;
946 /* virtual */ already_AddRefed<nsICSSRule>
947 nsCSSMediaRule::Clone() const
949 nsCOMPtr<nsICSSRule> clone = new nsCSSMediaRule(*this);
950 return clone.forget();
953 nsresult
954 nsCSSMediaRule::SetMedia(nsMediaList* aMedia)
956 mMedia = aMedia;
957 if (aMedia)
958 mMedia->SetStyleSheet(mSheet);
959 return NS_OK;
962 // nsIDOMCSSRule methods
963 NS_IMETHODIMP
964 nsCSSMediaRule::GetType(PRUint16* aType)
966 *aType = nsIDOMCSSRule::MEDIA_RULE;
967 return NS_OK;
970 NS_IMETHODIMP
971 nsCSSMediaRule::GetCssText(nsAString& aCssText)
973 aCssText.AssignLiteral("@media ");
974 // get all the media
975 if (mMedia) {
976 nsAutoString mediaText;
977 mMedia->GetText(mediaText);
978 aCssText.Append(mediaText);
981 return nsCSSGroupRule::AppendRulesToCssText(aCssText);
984 NS_IMETHODIMP
985 nsCSSMediaRule::SetCssText(const nsAString& aCssText)
987 return NS_ERROR_NOT_IMPLEMENTED;
990 NS_IMETHODIMP
991 nsCSSMediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
993 return nsCSSGroupRule::GetParentStyleSheet(aSheet);
996 NS_IMETHODIMP
997 nsCSSMediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
999 return nsCSSGroupRule::GetParentRule(aParentRule);
1002 // nsIDOMCSSMediaRule methods
1003 NS_IMETHODIMP
1004 nsCSSMediaRule::GetMedia(nsIDOMMediaList* *aMedia)
1006 NS_ENSURE_ARG_POINTER(aMedia);
1007 NS_IF_ADDREF(*aMedia = mMedia);
1008 return NS_OK;
1011 NS_IMETHODIMP
1012 nsCSSMediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1014 return nsCSSGroupRule::GetCssRules(aRuleList);
1017 NS_IMETHODIMP
1018 nsCSSMediaRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
1020 return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval);
1023 NS_IMETHODIMP
1024 nsCSSMediaRule::DeleteRule(PRUint32 aIndex)
1026 return nsCSSGroupRule::DeleteRule(aIndex);
1029 // nsICSSGroupRule interface
1030 NS_IMETHODIMP_(PRBool)
1031 nsCSSMediaRule::UseForPresentation(nsPresContext* aPresContext,
1032 nsMediaQueryResultCacheKey& aKey)
1034 if (mMedia) {
1035 return mMedia->Matches(aPresContext, aKey);
1037 return PR_TRUE;
1041 nsCSSDocumentRule::nsCSSDocumentRule(void)
1045 nsCSSDocumentRule::nsCSSDocumentRule(const nsCSSDocumentRule& aCopy)
1046 : nsCSSGroupRule(aCopy)
1047 , mURLs(new URL(*aCopy.mURLs))
1051 nsCSSDocumentRule::~nsCSSDocumentRule(void)
1055 NS_IMPL_ADDREF_INHERITED(nsCSSDocumentRule, nsCSSGroupRule)
1056 NS_IMPL_RELEASE_INHERITED(nsCSSDocumentRule, nsCSSGroupRule)
1058 DOMCI_DATA(CSSMozDocumentRule, nsCSSDocumentRule)
1060 // QueryInterface implementation for nsCSSDocumentRule
1061 NS_INTERFACE_MAP_BEGIN(nsCSSDocumentRule)
1062 NS_INTERFACE_MAP_ENTRY(nsICSSGroupRule)
1063 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1064 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1065 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1066 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
1067 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsCSSGroupRule)
1068 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
1069 NS_INTERFACE_MAP_END
1071 #ifdef DEBUG
1072 /* virtual */ void
1073 nsCSSDocumentRule::List(FILE* out, PRInt32 aIndent) const
1075 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
1077 nsCAutoString str;
1078 str.AssignLiteral("@-moz-document ");
1079 for (URL *url = mURLs; url; url = url->next) {
1080 switch (url->func) {
1081 case eURL:
1082 str.AppendLiteral("url(\"");
1083 break;
1084 case eURLPrefix:
1085 str.AppendLiteral("url-prefix(\"");
1086 break;
1087 case eDomain:
1088 str.AppendLiteral("domain(\"");
1089 break;
1091 nsCAutoString escapedURL(url->url);
1092 escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
1093 str.Append(escapedURL);
1094 str.AppendLiteral("\"), ");
1096 str.Cut(str.Length() - 2, 1); // remove last ,
1097 fputs(str.get(), out);
1099 nsCSSGroupRule::List(out, aIndent);
1101 #endif
1103 /* virtual */ PRInt32
1104 nsCSSDocumentRule::GetType() const
1106 return nsICSSRule::DOCUMENT_RULE;
1109 /* virtual */ already_AddRefed<nsICSSRule>
1110 nsCSSDocumentRule::Clone() const
1112 nsCOMPtr<nsICSSRule> clone = new nsCSSDocumentRule(*this);
1113 return clone.forget();
1116 // nsIDOMCSSRule methods
1117 NS_IMETHODIMP
1118 nsCSSDocumentRule::GetType(PRUint16* aType)
1120 // XXX What should really happen here?
1121 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1122 return NS_OK;
1125 NS_IMETHODIMP
1126 nsCSSDocumentRule::GetCssText(nsAString& aCssText)
1128 aCssText.AssignLiteral("@-moz-document ");
1129 for (URL *url = mURLs; url; url = url->next) {
1130 switch (url->func) {
1131 case eURL:
1132 aCssText.AppendLiteral("url(");
1133 break;
1134 case eURLPrefix:
1135 aCssText.AppendLiteral("url-prefix(");
1136 break;
1137 case eDomain:
1138 aCssText.AppendLiteral("domain(");
1139 break;
1141 nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
1142 aCssText);
1143 aCssText.AppendLiteral("), ");
1145 aCssText.Cut(aCssText.Length() - 2, 1); // remove last ,
1147 return nsCSSGroupRule::AppendRulesToCssText(aCssText);
1150 NS_IMETHODIMP
1151 nsCSSDocumentRule::SetCssText(const nsAString& aCssText)
1153 return NS_ERROR_NOT_IMPLEMENTED;
1156 NS_IMETHODIMP
1157 nsCSSDocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1159 return nsCSSGroupRule::GetParentStyleSheet(aSheet);
1162 NS_IMETHODIMP
1163 nsCSSDocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1165 return nsCSSGroupRule::GetParentRule(aParentRule);
1168 NS_IMETHODIMP
1169 nsCSSDocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1171 return nsCSSGroupRule::GetCssRules(aRuleList);
1174 NS_IMETHODIMP
1175 nsCSSDocumentRule::InsertRule(const nsAString & aRule, PRUint32 aIndex, PRUint32* _retval)
1177 return nsCSSGroupRule::InsertRule(aRule, aIndex, _retval);
1180 NS_IMETHODIMP
1181 nsCSSDocumentRule::DeleteRule(PRUint32 aIndex)
1183 return nsCSSGroupRule::DeleteRule(aIndex);
1186 // nsICSSGroupRule interface
1187 NS_IMETHODIMP_(PRBool)
1188 nsCSSDocumentRule::UseForPresentation(nsPresContext* aPresContext,
1189 nsMediaQueryResultCacheKey& aKey)
1191 nsIURI *docURI = aPresContext->Document()->GetDocumentURI();
1192 nsCAutoString docURISpec;
1193 if (docURI)
1194 docURI->GetSpec(docURISpec);
1196 for (URL *url = mURLs; url; url = url->next) {
1197 switch (url->func) {
1198 case eURL: {
1199 if (docURISpec == url->url)
1200 return PR_TRUE;
1201 } break;
1202 case eURLPrefix: {
1203 if (StringBeginsWith(docURISpec, url->url))
1204 return PR_TRUE;
1205 } break;
1206 case eDomain: {
1207 nsCAutoString host;
1208 if (docURI)
1209 docURI->GetHost(host);
1210 PRInt32 lenDiff = host.Length() - url->url.Length();
1211 if (lenDiff == 0) {
1212 if (host == url->url)
1213 return PR_TRUE;
1214 } else {
1215 if (StringEndsWith(host, url->url) &&
1216 host.CharAt(lenDiff - 1) == '.')
1217 return PR_TRUE;
1219 } break;
1223 return PR_FALSE;
1226 nsCSSDocumentRule::URL::~URL()
1228 NS_CSS_DELETE_LIST_MEMBER(nsCSSDocumentRule::URL, this, next);
1231 // -------------------------------------------
1232 // nsICSSNameSpaceRule
1234 class NS_FINAL_CLASS CSSNameSpaceRuleImpl : public nsCSSRule,
1235 public nsICSSNameSpaceRule,
1236 public nsIDOMCSSRule
1238 public:
1239 CSSNameSpaceRuleImpl(void);
1240 CSSNameSpaceRuleImpl(const CSSNameSpaceRuleImpl& aCopy);
1241 private:
1242 ~CSSNameSpaceRuleImpl();
1243 public:
1244 NS_DECL_ISUPPORTS
1246 DECL_STYLE_RULE_INHERIT
1248 // nsIStyleRule methods
1249 #ifdef DEBUG
1250 virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
1251 #endif
1253 // nsICSSRule methods
1254 virtual PRInt32 GetType() const;
1255 virtual already_AddRefed<nsICSSRule> Clone() const;
1257 // nsICSSNameSpaceRule methods
1258 NS_IMETHOD GetPrefix(nsIAtom*& aPrefix) const;
1259 NS_IMETHOD SetPrefix(nsIAtom* aPrefix);
1261 NS_IMETHOD GetURLSpec(nsString& aURLSpec) const;
1262 NS_IMETHOD SetURLSpec(const nsString& aURLSpec);
1264 // nsIDOMCSSRule interface
1265 NS_DECL_NSIDOMCSSRULE
1267 protected:
1268 nsIAtom* mPrefix;
1269 nsString mURLSpec;
1272 CSSNameSpaceRuleImpl::CSSNameSpaceRuleImpl(void)
1273 : nsCSSRule(),
1274 mPrefix(nsnull),
1275 mURLSpec()
1279 CSSNameSpaceRuleImpl::CSSNameSpaceRuleImpl(const CSSNameSpaceRuleImpl& aCopy)
1280 : nsCSSRule(aCopy),
1281 mPrefix(aCopy.mPrefix),
1282 mURLSpec(aCopy.mURLSpec)
1284 NS_IF_ADDREF(mPrefix);
1287 CSSNameSpaceRuleImpl::~CSSNameSpaceRuleImpl()
1289 NS_IF_RELEASE(mPrefix);
1292 NS_IMPL_ADDREF(CSSNameSpaceRuleImpl)
1293 NS_IMPL_RELEASE(CSSNameSpaceRuleImpl)
1295 DOMCI_DATA(CSSNameSpaceRule, CSSNameSpaceRuleImpl)
1297 // QueryInterface implementation for CSSNameSpaceRuleImpl
1298 NS_INTERFACE_MAP_BEGIN(CSSNameSpaceRuleImpl)
1299 NS_INTERFACE_MAP_ENTRY(nsICSSNameSpaceRule)
1300 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1301 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1302 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1303 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSNameSpaceRule)
1304 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule)
1305 NS_INTERFACE_MAP_END
1307 IMPL_STYLE_RULE_INHERIT(CSSNameSpaceRuleImpl, nsCSSRule)
1309 #ifdef DEBUG
1310 /* virtual */ void
1311 CSSNameSpaceRuleImpl::List(FILE* out, PRInt32 aIndent) const
1313 for (PRInt32 indent = aIndent; --indent >= 0; ) fputs(" ", out);
1315 nsAutoString buffer;
1317 fputs("@namespace ", out);
1319 if (mPrefix) {
1320 mPrefix->ToString(buffer);
1321 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
1322 fputs(" ", out);
1325 fputs("url(", out);
1326 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
1327 fputs(")\n", out);
1329 #endif
1331 /* virtual */ PRInt32
1332 CSSNameSpaceRuleImpl::GetType() const
1334 return nsICSSRule::NAMESPACE_RULE;
1337 /* virtual */ already_AddRefed<nsICSSRule>
1338 CSSNameSpaceRuleImpl::Clone() const
1340 nsCOMPtr<nsICSSRule> clone = new CSSNameSpaceRuleImpl(*this);
1341 return clone.forget();
1344 NS_IMETHODIMP
1345 CSSNameSpaceRuleImpl::GetPrefix(nsIAtom*& aPrefix) const
1347 aPrefix = mPrefix;
1348 NS_IF_ADDREF(aPrefix);
1349 return NS_OK;
1352 NS_IMETHODIMP
1353 CSSNameSpaceRuleImpl::SetPrefix(nsIAtom* aPrefix)
1355 NS_IF_RELEASE(mPrefix);
1356 mPrefix = aPrefix;
1357 NS_IF_ADDREF(mPrefix);
1358 return NS_OK;
1361 NS_IMETHODIMP
1362 CSSNameSpaceRuleImpl::GetURLSpec(nsString& aURLSpec) const
1364 aURLSpec = mURLSpec;
1365 return NS_OK;
1368 NS_IMETHODIMP
1369 CSSNameSpaceRuleImpl::SetURLSpec(const nsString& aURLSpec)
1371 mURLSpec = aURLSpec;
1372 return NS_OK;
1375 nsresult
1376 NS_NewCSSNameSpaceRule(nsICSSNameSpaceRule** aInstancePtrResult,
1377 nsIAtom* aPrefix, const nsString& aURLSpec)
1379 if (! aInstancePtrResult) {
1380 return NS_ERROR_NULL_POINTER;
1383 CSSNameSpaceRuleImpl* it = new CSSNameSpaceRuleImpl();
1385 if (!it) {
1386 return NS_ERROR_OUT_OF_MEMORY;
1389 it->SetPrefix(aPrefix);
1390 it->SetURLSpec(aURLSpec);
1391 NS_ADDREF(*aInstancePtrResult = it);
1392 return NS_OK;
1395 NS_IMETHODIMP
1396 CSSNameSpaceRuleImpl::GetType(PRUint16* aType)
1398 // XXX What should really happen here?
1399 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1400 return NS_OK;
1403 NS_IMETHODIMP
1404 CSSNameSpaceRuleImpl::GetCssText(nsAString& aCssText)
1406 aCssText.AssignLiteral("@namespace ");
1407 if (mPrefix) {
1408 aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
1410 aCssText.AppendLiteral("url(");
1411 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
1412 aCssText.Append(NS_LITERAL_STRING(");"));
1413 return NS_OK;
1416 NS_IMETHODIMP
1417 CSSNameSpaceRuleImpl::SetCssText(const nsAString& aCssText)
1419 return NS_ERROR_NOT_IMPLEMENTED;
1422 NS_IMETHODIMP
1423 CSSNameSpaceRuleImpl::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1425 NS_IF_ADDREF(*aSheet = mSheet);
1426 return NS_OK;
1429 NS_IMETHODIMP
1430 CSSNameSpaceRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
1432 if (mParentRule) {
1433 return mParentRule->GetDOMRule(aParentRule);
1435 *aParentRule = nsnull;
1436 return NS_OK;
1439 // -------------------------------------------
1440 // nsCSSFontFaceStyleDecl and related routines
1443 // A src: descriptor is represented as an array value; each entry in
1444 // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
1445 // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear
1446 // only after one of the first two. (css3-fonts only contemplates
1447 // annotating URLs with formats, but we handle the general case.)
1448 static void
1449 AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult NS_OUTPARAM)
1451 NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array,
1452 "improper value unit for src:");
1454 const nsCSSValue::Array& sources = *src.GetArrayValue();
1455 size_t i = 0;
1457 while (i < sources.Count()) {
1458 nsAutoString formats;
1460 if (sources[i].GetUnit() == eCSSUnit_URL) {
1461 aResult.AppendLiteral("url(");
1462 nsDependentString url(sources[i].GetOriginalURLValue());
1463 nsStyleUtil::AppendEscapedCSSString(url, aResult);
1464 aResult.AppendLiteral(")");
1465 } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
1466 aResult.AppendLiteral("local(");
1467 nsDependentString local(sources[i].GetStringBufferValue());
1468 nsStyleUtil::AppendEscapedCSSString(local, aResult);
1469 aResult.AppendLiteral(")");
1470 } else {
1471 NS_NOTREACHED("entry in src: descriptor with improper unit");
1472 i++;
1473 continue;
1476 i++;
1477 formats.Truncate();
1478 while (i < sources.Count() &&
1479 sources[i].GetUnit() == eCSSUnit_Font_Format) {
1480 formats.Append('"');
1481 formats.Append(sources[i].GetStringBufferValue());
1482 formats.AppendLiteral("\", ");
1483 i++;
1485 if (formats.Length() > 0) {
1486 formats.Truncate(formats.Length() - 2); // remove the last comma
1487 aResult.AppendLiteral(" format(");
1488 aResult.Append(formats);
1489 aResult.Append(')');
1491 aResult.AppendLiteral(", ");
1493 aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
1496 // print all characters with at least four hex digits
1497 static void
1498 AppendSerializedUnicodePoint(PRUint32 aCode, nsACString &aBuf NS_OUTPARAM)
1500 aBuf.Append(nsPrintfCString("%04X", aCode));
1503 // A unicode-range: descriptor is represented as an array of integers,
1504 // to be interpreted as a sequence of pairs: min max min max ...
1505 // It is in source order. (Possibly it should be sorted and overlaps
1506 // consolidated, but right now we don't do that.)
1507 static void
1508 AppendSerializedUnicodeRange(nsCSSValue const & aValue,
1509 nsAString & aResult NS_OUTPARAM)
1511 NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null ||
1512 aValue.GetUnit() == eCSSUnit_Array,
1513 "improper value unit for unicode-range:");
1514 aResult.Truncate();
1515 if (aValue.GetUnit() != eCSSUnit_Array)
1516 return;
1518 nsCSSValue::Array const & sources = *aValue.GetArrayValue();
1519 nsCAutoString buf;
1521 NS_ABORT_IF_FALSE(sources.Count() % 2 == 0,
1522 "odd number of entries in a unicode-range: array");
1524 for (PRUint32 i = 0; i < sources.Count(); i += 2) {
1525 PRUint32 min = sources[i].GetIntValue();
1526 PRUint32 max = sources[i+1].GetIntValue();
1528 // We don't try to replicate the U+XX?? notation.
1529 buf.AppendLiteral("U+");
1530 AppendSerializedUnicodePoint(min, buf);
1532 if (min != max) {
1533 buf.Append('-');
1534 AppendSerializedUnicodePoint(max, buf);
1536 buf.AppendLiteral(", ");
1538 buf.Truncate(buf.Length() - 2); // remove the last comma-space
1539 CopyASCIItoUTF16(buf, aResult);
1542 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
1543 // Keep this in sync with enum nsCSSFontDesc in nsCSSProperty.h.
1544 nsCSSValue nsCSSFontFaceStyleDecl::* const
1545 nsCSSFontFaceStyleDecl::Fields[] = {
1546 &nsCSSFontFaceStyleDecl::mFamily,
1547 &nsCSSFontFaceStyleDecl::mStyle,
1548 &nsCSSFontFaceStyleDecl::mWeight,
1549 &nsCSSFontFaceStyleDecl::mStretch,
1550 &nsCSSFontFaceStyleDecl::mSrc,
1551 &nsCSSFontFaceStyleDecl::mUnicodeRange,
1552 &nsCSSFontFaceStyleDecl::mFontFeatureSettings,
1553 &nsCSSFontFaceStyleDecl::mFontLanguageOverride
1556 DOMCI_DATA(CSSFontFaceStyleDecl, nsCSSFontFaceStyleDecl)
1558 // QueryInterface implementation for nsCSSFontFaceStyleDecl
1559 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
1560 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
1561 NS_INTERFACE_MAP_ENTRY(nsISupports)
1562 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceStyleDecl)
1563 NS_INTERFACE_MAP_END
1565 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1566 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1568 // helper for string GetPropertyValue and RemovePropertyValue
1569 nsresult
1570 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
1571 nsAString & aResult NS_OUTPARAM) const
1573 NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
1574 eCSSFontDesc_COUNT - 1);
1576 aResult.Truncate();
1577 if (aFontDescID == eCSSFontDesc_UNKNOWN)
1578 return NS_OK;
1580 const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID];
1582 if (val.GetUnit() == eCSSUnit_Null) {
1583 // Avoid having to check no-value in the Family and Src cases below.
1584 return NS_OK;
1587 switch (aFontDescID) {
1588 case eCSSFontDesc_Family: {
1589 // we don't use nsCSSValue::AppendToString here because it doesn't
1590 // canonicalize the way we want, and anyway it's overkill when
1591 // we know we have eCSSUnit_String
1592 NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
1593 nsDependentString family(val.GetStringBufferValue());
1594 nsStyleUtil::AppendEscapedCSSString(family, aResult);
1595 return NS_OK;
1598 case eCSSFontDesc_Style:
1599 val.AppendToString(eCSSProperty_font_style, aResult);
1600 return NS_OK;
1602 case eCSSFontDesc_Weight:
1603 val.AppendToString(eCSSProperty_font_weight, aResult);
1604 return NS_OK;
1606 case eCSSFontDesc_Stretch:
1607 val.AppendToString(eCSSProperty_font_stretch, aResult);
1608 return NS_OK;
1610 case eCSSFontDesc_FontFeatureSettings:
1611 val.AppendToString(eCSSProperty_font_feature_settings, aResult);
1612 return NS_OK;
1614 case eCSSFontDesc_FontLanguageOverride:
1615 val.AppendToString(eCSSProperty_font_language_override, aResult);
1616 return NS_OK;
1618 case eCSSFontDesc_Src:
1619 AppendSerializedFontSrc(val, aResult);
1620 return NS_OK;
1622 case eCSSFontDesc_UnicodeRange:
1623 AppendSerializedUnicodeRange(val, aResult);
1624 return NS_OK;
1626 case eCSSFontDesc_UNKNOWN:
1627 case eCSSFontDesc_COUNT:
1630 NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
1631 "out-of-range value got to the switch");
1632 return NS_ERROR_INVALID_ARG;
1636 // attribute DOMString cssText;
1637 NS_IMETHODIMP
1638 nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
1640 nsAutoString descStr;
1642 aCssText.Truncate();
1643 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1644 id < eCSSFontDesc_COUNT;
1645 id = nsCSSFontDesc(id + 1)) {
1646 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1647 != eCSSUnit_Null &&
1648 NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
1649 NS_ASSERTION(descStr.Length() > 0,
1650 "GetCssText: non-null unit, empty property value");
1651 aCssText.AppendLiteral(" ");
1652 aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
1653 aCssText.AppendLiteral(": ");
1654 aCssText.Append(descStr);
1655 aCssText.AppendLiteral(";\n");
1658 return NS_OK;
1661 NS_IMETHODIMP
1662 nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
1664 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1667 // DOMString getPropertyValue (in DOMString propertyName);
1668 NS_IMETHODIMP
1669 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
1670 nsAString & aResult NS_OUTPARAM)
1672 return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
1675 // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
1676 NS_IMETHODIMP
1677 nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
1678 nsIDOMCSSValue **aResult NS_OUTPARAM)
1680 // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
1681 return NS_ERROR_NOT_IMPLEMENTED;
1684 // DOMString removeProperty (in DOMString propertyName) raises (DOMException);
1685 NS_IMETHODIMP
1686 nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
1687 nsAString & aResult NS_OUTPARAM)
1689 nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
1690 NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
1691 descID < eCSSFontDesc_COUNT,
1692 "LookupFontDesc returned value out of range");
1694 if (descID == eCSSFontDesc_UNKNOWN) {
1695 aResult.Truncate();
1696 } else {
1697 nsresult rv = GetPropertyValue(descID, aResult);
1698 NS_ENSURE_SUCCESS(rv, rv);
1699 (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset();
1701 return NS_OK;
1704 // DOMString getPropertyPriority (in DOMString propertyName);
1705 NS_IMETHODIMP
1706 nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
1707 nsAString & aResult NS_OUTPARAM)
1709 // font descriptors do not have priorities at present
1710 aResult.Truncate();
1711 return NS_OK;
1714 // void setProperty (in DOMString propertyName, in DOMString value,
1715 // in DOMString priority) raises (DOMException);
1716 NS_IMETHODIMP
1717 nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
1718 const nsAString & value,
1719 const nsAString & priority)
1721 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1724 // readonly attribute unsigned long length;
1725 NS_IMETHODIMP
1726 nsCSSFontFaceStyleDecl::GetLength(PRUint32 *aLength)
1728 PRUint32 len = 0;
1729 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1730 id < eCSSFontDesc_COUNT;
1731 id = nsCSSFontDesc(id + 1))
1732 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null)
1733 len++;
1735 *aLength = len;
1736 return NS_OK;
1739 // DOMString item (in unsigned long index);
1740 NS_IMETHODIMP
1741 nsCSSFontFaceStyleDecl::Item(PRUint32 index, nsAString & aResult NS_OUTPARAM)
1743 PRInt32 nset = -1;
1744 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1745 id < eCSSFontDesc_COUNT;
1746 id = nsCSSFontDesc(id + 1)) {
1747 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1748 != eCSSUnit_Null) {
1749 nset++;
1750 if (nset == PRInt32(index)) {
1751 aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
1752 return NS_OK;
1756 aResult.Truncate();
1757 return NS_OK;
1760 // readonly attribute nsIDOMCSSRule parentRule;
1761 NS_IMETHODIMP
1762 nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
1764 return ContainingRule()->GetDOMRule(aParentRule);
1768 // -------------------------------------------
1769 // nsCSSFontFaceRule
1772 /* virtual */ already_AddRefed<nsICSSRule>
1773 nsCSSFontFaceRule::Clone() const
1775 nsCOMPtr<nsICSSRule> clone = new nsCSSFontFaceRule(*this);
1776 return clone.forget();
1779 NS_IMPL_ADDREF(nsCSSFontFaceRule)
1780 NS_IMPL_RELEASE(nsCSSFontFaceRule)
1782 DOMCI_DATA(CSSFontFaceRule, nsCSSFontFaceRule)
1784 // QueryInterface implementation for nsCSSFontFaceRule
1785 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceRule)
1786 NS_INTERFACE_MAP_ENTRY(nsICSSRule)
1787 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1788 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
1789 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1790 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICSSRule)
1791 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule)
1792 NS_INTERFACE_MAP_END
1794 IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, nsCSSRule)
1796 #ifdef DEBUG
1797 void
1798 nsCSSFontFaceRule::List(FILE* out, PRInt32 aIndent) const
1800 nsCString baseInd, descInd;
1801 for (PRInt32 indent = aIndent; --indent >= 0; ) {
1802 baseInd.AppendLiteral(" ");
1803 descInd.AppendLiteral(" ");
1805 descInd.AppendLiteral(" ");
1807 nsString descStr;
1809 fprintf(out, "%s@font-face {\n", baseInd.get());
1810 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1811 id < eCSSFontDesc_COUNT;
1812 id = nsCSSFontDesc(id + 1))
1813 if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1814 != eCSSUnit_Null) {
1815 if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
1816 descStr.AssignLiteral("#<serialization error>");
1817 else if (descStr.Length() == 0)
1818 descStr.AssignLiteral("#<serialization missing>");
1819 fprintf(out, "%s%s: %s\n",
1820 descInd.get(), nsCSSProps::GetStringValue(id).get(),
1821 NS_ConvertUTF16toUTF8(descStr).get());
1823 fprintf(out, "%s}\n", baseInd.get());
1825 #endif
1827 /* virtual */ PRInt32
1828 nsCSSFontFaceRule::GetType() const
1830 return nsICSSRule::FONT_FACE_RULE;
1833 NS_IMETHODIMP
1834 nsCSSFontFaceRule::GetType(PRUint16* aType)
1836 *aType = nsIDOMCSSRule::FONT_FACE_RULE;
1837 return NS_OK;
1840 NS_IMETHODIMP
1841 nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
1843 nsAutoString propText;
1844 mDecl.GetCssText(propText);
1846 aCssText.AssignLiteral("@font-face {\n");
1847 aCssText.Append(propText);
1848 aCssText.Append('}');
1849 return NS_OK;
1852 NS_IMETHODIMP
1853 nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
1855 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1858 NS_IMETHODIMP
1859 nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1861 NS_IF_ADDREF(*aSheet = mSheet);
1862 return NS_OK;
1865 NS_IMETHODIMP
1866 nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1868 if (mParentRule) {
1869 return mParentRule->GetDOMRule(aParentRule);
1871 *aParentRule = nsnull;
1872 return NS_OK;
1875 NS_IMETHODIMP
1876 nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1878 NS_IF_ADDREF(*aStyle = &mDecl);
1879 return NS_OK;
1882 // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
1883 void
1884 nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
1886 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1887 aDescID < eCSSFontDesc_COUNT,
1888 "aDescID out of range in nsCSSFontFaceRule::SetDesc");
1890 mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue;
1893 void
1894 nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
1896 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1897 aDescID < eCSSFontDesc_COUNT,
1898 "aDescID out of range in nsCSSFontFaceRule::GetDesc");
1900 aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];