1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
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 * This Original Code has been modified by IBM Corporation. Modifications made by IBM
40 * described herein are Copyright (c) International Business Machines Corporation, 2000.
41 * Modifications to Mozilla code or documentation identified per MPL Section 3.3
43 * Date Modified by Description of modification
44 * 04/20/2000 IBM Corp. OS/2 VisualAge build.
48 * style sheet and style rule processor representing data from presentational
52 #include "nsHTMLStyleSheet.h"
53 #include "nsINameSpaceManager.h"
56 #include "nsMappedAttributes.h"
59 #include "nsStyleContext.h"
60 #include "nsGkAtoms.h"
61 #include "nsPresContext.h"
62 #include "nsIEventStateManager.h"
63 #include "nsIDocument.h"
64 #include "nsIPresShell.h"
65 #include "nsStyleConsts.h"
66 #include "nsIDOMHTMLDocument.h"
67 #include "nsIDOMHTMLElement.h"
68 #include "nsCSSAnonBoxes.h"
69 #include "nsRuleWalker.h"
70 #include "nsRuleData.h"
71 #include "nsContentErrors.h"
73 NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet::HTMLColorRule
, nsIStyleRule
)
76 nsHTMLStyleSheet::HTMLColorRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
78 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Color
)) {
79 if (aRuleData
->mColorData
->mColor
.GetUnit() == eCSSUnit_Null
&&
80 aRuleData
->mPresContext
->UseDocumentColors())
81 aRuleData
->mColorData
->mColor
.SetColorValue(mColor
);
88 nsHTMLStyleSheet::HTMLColorRule::List(FILE* out
, PRInt32 aIndent
) const
95 NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet::GenericTableRule
, nsIStyleRule
)
98 nsHTMLStyleSheet::GenericTableRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
106 nsHTMLStyleSheet::GenericTableRule::List(FILE* out
, PRInt32 aIndent
) const
112 static void PostResolveCallback(void* aStyleStruct
, nsRuleData
* aRuleData
)
114 nsStyleText
* text
= (nsStyleText
*)aStyleStruct
;
115 if (text
->mTextAlign
== NS_STYLE_TEXT_ALIGN_DEFAULT
) {
116 nsStyleContext
* parentContext
= aRuleData
->mStyleContext
->GetParent();
119 const nsStyleText
* parentStyleText
= parentContext
->GetStyleText();
120 PRUint8 parentAlign
= parentStyleText
->mTextAlign
;
121 text
->mTextAlign
= (NS_STYLE_TEXT_ALIGN_DEFAULT
== parentAlign
)
122 ? NS_STYLE_TEXT_ALIGN_CENTER
: parentAlign
;
128 nsHTMLStyleSheet::TableTHRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
130 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Text
)) {
131 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
132 aRuleData
->mPostResolveCallback
= &PostResolveCallback
;
138 ProcessTableRulesAttribute(void* aStyleStruct
,
139 nsRuleData
* aRuleData
,
146 if (!aStyleStruct
|| !aRuleData
|| !aRuleData
->mPresContext
) return;
148 nsStyleContext
* tableContext
= aRuleData
->mStyleContext
->GetParent();
152 tableContext
= tableContext
->GetParent();
157 const nsStyleTable
* tableData
= tableContext
->GetStyleTable();
158 if (aRulesArg1
== tableData
->mRules
||
159 aRulesArg2
== tableData
->mRules
||
160 aRulesArg3
== tableData
->mRules
) {
161 const nsStyleBorder
* tableBorderData
= tableContext
->GetStyleBorder();
162 PRUint8 tableBorderStyle
= tableBorderData
->GetBorderStyle(aSide
);
164 nsStyleBorder
* borderData
= (nsStyleBorder
*)aStyleStruct
;
167 PRUint8 borderStyle
= borderData
->GetBorderStyle(aSide
);
168 // XXX It appears that the style system erronously applies the custom style rule after css style,
169 // consequently it does not properly fit into the casade. For now, assume that a border style of none
170 // implies that the style has not been set.
171 // XXXldb No, there's nothing wrong with the style system. The problem
172 // is that the author of all these table rules made them work as
173 // post-resolve callbacks, which is an override mechanism that was meant
174 // to be used for other things. They should instead map their rule data
175 // normally (see nsIStyleRule.h).
176 if (NS_STYLE_BORDER_STYLE_NONE
== borderStyle
) {
177 // use the table's border style if it is dashed or dotted, otherwise use solid
178 PRUint8 bStyle
= ((NS_STYLE_BORDER_STYLE_NONE
!= tableBorderStyle
) &&
179 (NS_STYLE_BORDER_STYLE_HIDDEN
!= tableBorderStyle
))
180 ? tableBorderStyle
: NS_STYLE_BORDER_STYLE_SOLID
;
181 if ((NS_STYLE_BORDER_STYLE_DASHED
!= bStyle
) &&
182 (NS_STYLE_BORDER_STYLE_DOTTED
!= bStyle
) &&
183 (NS_STYLE_BORDER_STYLE_SOLID
!= bStyle
)) {
184 bStyle
= NS_STYLE_BORDER_STYLE_SOLID
;
186 bStyle
|= NS_STYLE_BORDER_STYLE_RULES_MARKER
;
187 borderData
->SetBorderStyle(aSide
, bStyle
);
191 borderData
->GetBorderColor(aSide
, borderColor
, foreground
);
192 if (foreground
|| NS_GET_A(borderColor
) == 0) {
193 // use the table's border color if it is set, otherwise use black
194 nscolor tableBorderColor
;
195 tableBorderData
->GetBorderColor(aSide
, tableBorderColor
, foreground
);
196 borderColor
= (foreground
|| NS_GET_A(tableBorderColor
) == 0)
197 ? NS_RGB(0,0,0) : tableBorderColor
;
198 borderData
->SetBorderColor(aSide
, borderColor
);
200 // set the border width to be 1 pixel
201 borderData
->SetBorderWidth(aSide
, nsPresContext::CSSPixelsToAppUnits(1));
206 static void TbodyPostResolveCallback(void* aStyleStruct
, nsRuleData
* aRuleData
)
208 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_TOP
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
209 NS_STYLE_TABLE_RULES_GROUPS
, NS_STYLE_TABLE_RULES_ROWS
);
210 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_BOTTOM
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
211 NS_STYLE_TABLE_RULES_GROUPS
, NS_STYLE_TABLE_RULES_ROWS
);
215 nsHTMLStyleSheet::TableTbodyRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
217 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Border
)) {
218 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
219 aRuleData
->mPostResolveCallback
= &TbodyPostResolveCallback
;
223 // -----------------------------------------------------------
225 static void RowPostResolveCallback(void* aStyleStruct
, nsRuleData
* aRuleData
)
227 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_TOP
, PR_FALSE
, NS_STYLE_TABLE_RULES_ALL
,
228 NS_STYLE_TABLE_RULES_ROWS
, NS_STYLE_TABLE_RULES_ROWS
);
229 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_BOTTOM
, PR_FALSE
, NS_STYLE_TABLE_RULES_ALL
,
230 NS_STYLE_TABLE_RULES_ROWS
, NS_STYLE_TABLE_RULES_ROWS
);
234 nsHTMLStyleSheet::TableRowRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
236 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Border
)) {
237 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
238 aRuleData
->mPostResolveCallback
= &RowPostResolveCallback
;
243 static void ColgroupPostResolveCallback(void* aStyleStruct
, nsRuleData
* aRuleData
)
245 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_LEFT
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
246 NS_STYLE_TABLE_RULES_GROUPS
, NS_STYLE_TABLE_RULES_COLS
);
247 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_RIGHT
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
248 NS_STYLE_TABLE_RULES_GROUPS
, NS_STYLE_TABLE_RULES_COLS
);
252 nsHTMLStyleSheet::TableColgroupRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
254 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Border
)) {
255 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
256 aRuleData
->mPostResolveCallback
= &ColgroupPostResolveCallback
;
261 static void ColPostResolveCallback(void* aStyleStruct
, nsRuleData
* aRuleData
)
263 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_LEFT
, PR_FALSE
, NS_STYLE_TABLE_RULES_ALL
,
264 NS_STYLE_TABLE_RULES_COLS
, NS_STYLE_TABLE_RULES_COLS
);
265 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_RIGHT
, PR_FALSE
, NS_STYLE_TABLE_RULES_ALL
,
266 NS_STYLE_TABLE_RULES_COLS
, NS_STYLE_TABLE_RULES_COLS
);
269 static void UngroupedColPostResolveCallback(void* aStyleStruct
,
270 nsRuleData
* aRuleData
)
272 // Pass PR_TRUE for aGroup, so that we find the table's style
273 // context correctly.
274 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_LEFT
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
275 NS_STYLE_TABLE_RULES_COLS
, NS_STYLE_TABLE_RULES_COLS
);
276 ::ProcessTableRulesAttribute(aStyleStruct
, aRuleData
, NS_SIDE_RIGHT
, PR_TRUE
, NS_STYLE_TABLE_RULES_ALL
,
277 NS_STYLE_TABLE_RULES_COLS
, NS_STYLE_TABLE_RULES_COLS
);
281 nsHTMLStyleSheet::TableColRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
283 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Border
)) {
284 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
285 aRuleData
->mPostResolveCallback
= &ColPostResolveCallback
;
291 nsHTMLStyleSheet::TableUngroupedColRule::MapRuleInfoInto(nsRuleData
* aRuleData
)
293 if (aRuleData
->mSIDs
& NS_STYLE_INHERIT_BIT(Border
)) {
294 aRuleData
->mCanStoreInRuleTree
= PR_FALSE
;
295 aRuleData
->mPostResolveCallback
= &UngroupedColPostResolveCallback
;
299 // -----------------------------------------------------------
301 struct MappedAttrTableEntry
: public PLDHashEntryHdr
{
302 nsMappedAttributes
*mAttributes
;
305 PR_STATIC_CALLBACK(PLDHashNumber
)
306 MappedAttrTable_HashKey(PLDHashTable
*table
, const void *key
)
308 nsMappedAttributes
*attributes
=
309 static_cast<nsMappedAttributes
*>(const_cast<void*>(key
));
311 return attributes
->HashValue();
314 PR_STATIC_CALLBACK(void)
315 MappedAttrTable_ClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
)
317 MappedAttrTableEntry
*entry
= static_cast<MappedAttrTableEntry
*>(hdr
);
319 entry
->mAttributes
->DropStyleSheetReference();
320 memset(entry
, 0, sizeof(MappedAttrTableEntry
));
323 PR_STATIC_CALLBACK(PRBool
)
324 MappedAttrTable_MatchEntry(PLDHashTable
*table
, const PLDHashEntryHdr
*hdr
,
327 nsMappedAttributes
*attributes
=
328 static_cast<nsMappedAttributes
*>(const_cast<void*>(key
));
329 const MappedAttrTableEntry
*entry
=
330 static_cast<const MappedAttrTableEntry
*>(hdr
);
332 return attributes
->Equals(entry
->mAttributes
);
335 static PLDHashTableOps MappedAttrTable_Ops
= {
338 MappedAttrTable_HashKey
,
339 MappedAttrTable_MatchEntry
,
340 PL_DHashMoveEntryStub
,
341 MappedAttrTable_ClearEntry
,
342 PL_DHashFinalizeStub
,
346 // -----------------------------------------------------------
348 nsHTMLStyleSheet::nsHTMLStyleSheet(void)
352 mVisitedRule(nsnull
),
354 mDocumentColorRule(nsnull
)
356 mMappedAttrTable
.ops
= nsnull
;
360 nsHTMLStyleSheet::Init()
362 mTableTbodyRule
= new TableTbodyRule();
363 if (!mTableTbodyRule
)
364 return NS_ERROR_OUT_OF_MEMORY
;
365 NS_ADDREF(mTableTbodyRule
);
367 mTableRowRule
= new TableRowRule();
369 return NS_ERROR_OUT_OF_MEMORY
;
370 NS_ADDREF(mTableRowRule
);
372 mTableColgroupRule
= new TableColgroupRule();
373 if (!mTableColgroupRule
)
374 return NS_ERROR_OUT_OF_MEMORY
;
375 NS_ADDREF(mTableColgroupRule
);
377 mTableColRule
= new TableColRule();
379 return NS_ERROR_OUT_OF_MEMORY
;
380 NS_ADDREF(mTableColRule
);
382 mTableUngroupedColRule
= new TableUngroupedColRule();
383 if (!mTableUngroupedColRule
)
384 return NS_ERROR_OUT_OF_MEMORY
;
385 NS_ADDREF(mTableUngroupedColRule
);
387 mTableTHRule
= new TableTHRule();
389 return NS_ERROR_OUT_OF_MEMORY
;
390 NS_ADDREF(mTableTHRule
);
394 nsHTMLStyleSheet::~nsHTMLStyleSheet()
398 NS_IF_RELEASE(mLinkRule
);
399 NS_IF_RELEASE(mVisitedRule
);
400 NS_IF_RELEASE(mActiveRule
);
401 NS_IF_RELEASE(mDocumentColorRule
);
402 NS_IF_RELEASE(mTableTbodyRule
);
403 NS_IF_RELEASE(mTableRowRule
);
404 NS_IF_RELEASE(mTableColgroupRule
);
405 NS_IF_RELEASE(mTableColRule
);
406 NS_IF_RELEASE(mTableUngroupedColRule
);
407 NS_IF_RELEASE(mTableTHRule
);
409 if (mMappedAttrTable
.ops
)
410 PL_DHashTableFinish(&mMappedAttrTable
);
413 NS_IMPL_ISUPPORTS2(nsHTMLStyleSheet
, nsIStyleSheet
, nsIStyleRuleProcessor
)
415 static nsresult
GetBodyColor(nsPresContext
* aPresContext
, nscolor
* aColor
)
417 nsIPresShell
*shell
= aPresContext
->PresShell();
418 nsCOMPtr
<nsIDOMHTMLDocument
> domdoc
= do_QueryInterface(shell
->GetDocument());
420 return NS_ERROR_FAILURE
;
421 nsCOMPtr
<nsIDOMHTMLElement
> body
;
422 domdoc
->GetBody(getter_AddRefs(body
));
423 nsCOMPtr
<nsIContent
> bodyContent
= do_QueryInterface(body
);
424 nsIFrame
*bodyFrame
= shell
->GetPrimaryFrameFor(bodyContent
);
426 return NS_ERROR_FAILURE
;
427 *aColor
= bodyFrame
->GetStyleColor()->mColor
;
432 nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData
* aData
)
434 nsIContent
*content
= aData
->mContent
;
437 nsRuleWalker
*ruleWalker
= aData
->mRuleWalker
;
438 if (aData
->mIsHTMLContent
) {
439 nsIAtom
* tag
= aData
->mContentTag
;
441 // if we have anchor colors, check if this is an anchor with an href
442 if (tag
== nsGkAtoms::a
) {
443 if (mLinkRule
|| mVisitedRule
|| mActiveRule
) {
444 if (aData
->mIsLink
) {
445 switch (aData
->mLinkState
) {
446 case eLinkState_Unvisited
:
448 ruleWalker
->Forward(mLinkRule
);
450 case eLinkState_Visited
:
452 ruleWalker
->Forward(mVisitedRule
);
458 // No need to add to the active rule if it's not a link
459 if (mActiveRule
&& (aData
->mEventState
& NS_EVENT_STATE_ACTIVE
))
460 ruleWalker
->Forward(mActiveRule
);
462 } // end link/visited/active rules
464 // add the rule to handle text-align for a <th>
465 else if (tag
== nsGkAtoms::th
) {
466 ruleWalker
->Forward(mTableTHRule
);
468 else if (tag
== nsGkAtoms::tr
) {
469 ruleWalker
->Forward(mTableRowRule
);
471 else if ((tag
== nsGkAtoms::thead
) || (tag
== nsGkAtoms::tbody
) || (tag
== nsGkAtoms::tfoot
)) {
472 ruleWalker
->Forward(mTableTbodyRule
);
474 else if (tag
== nsGkAtoms::col
) {
475 nsIContent
* parent
= aData
->mParentContent
;
476 if (parent
&& parent
->IsNodeOfType(nsIContent::eHTML
) &&
477 parent
->Tag() == nsGkAtoms::colgroup
) {
478 ruleWalker
->Forward(mTableColRule
);
480 ruleWalker
->Forward(mTableUngroupedColRule
);
483 else if (tag
== nsGkAtoms::colgroup
) {
484 ruleWalker
->Forward(mTableColgroupRule
);
486 else if (tag
== nsGkAtoms::table
) {
487 if (aData
->mCompatMode
== eCompatibility_NavQuirks
) {
490 GetBodyColor(ruleWalker
->GetCurrentNode()->GetPresContext(),
492 if (NS_SUCCEEDED(rv
) &&
493 (!mDocumentColorRule
|| bodyColor
!= mDocumentColorRule
->mColor
)) {
494 NS_IF_RELEASE(mDocumentColorRule
);
495 mDocumentColorRule
= new HTMLColorRule();
496 if (mDocumentColorRule
) {
497 NS_ADDREF(mDocumentColorRule
);
498 mDocumentColorRule
->mColor
= bodyColor
;
501 if (mDocumentColorRule
)
502 ruleWalker
->Forward(mDocumentColorRule
);
505 } // end html element
507 // just get the style rules from the content
508 content
->WalkContentStyleRules(ruleWalker
);
514 // Test if style is dependent on content state
516 nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData
* aData
,
517 nsReStyleHint
* aResult
)
519 if (aData
->mContent
&&
520 aData
->mIsHTMLContent
&&
522 aData
->mContentTag
== nsGkAtoms::a
&&
523 ((mActiveRule
&& (aData
->mStateMask
& NS_EVENT_STATE_ACTIVE
)) ||
524 (mLinkRule
&& (aData
->mStateMask
& NS_EVENT_STATE_VISITED
)) ||
525 (mVisitedRule
&& (aData
->mStateMask
& NS_EVENT_STATE_VISITED
)))) {
526 *aResult
= eReStyle_Self
;
529 *aResult
= nsReStyleHint(0);
535 nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData
* aData
,
536 nsReStyleHint
* aResult
)
538 // Note: no need to worry about whether some states changed with this
539 // attribute here, because we handle that under HasStateDependentStyle() as
542 // Result is true for |href| changes on HTML links if we have link rules.
543 nsIContent
*content
= aData
->mContent
;
544 if (aData
->mAttribute
== nsGkAtoms::href
&&
545 (mLinkRule
|| mVisitedRule
|| mActiveRule
) &&
547 content
->IsNodeOfType(nsINode::eHTML
) &&
548 aData
->mContentTag
== nsGkAtoms::a
) {
549 *aResult
= eReStyle_Self
;
553 // Don't worry about the mDocumentColorRule since it only applies
554 // to descendants of body, when we're already reresolving.
556 // Handle the content style rules.
557 if (content
&& content
->IsAttributeMapped(aData
->mAttribute
)) {
558 *aResult
= eReStyle_Self
;
562 *aResult
= nsReStyleHint(0);
567 nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext
* aPresContext
,
568 PRBool
* aRulesChanged
)
570 *aRulesChanged
= PR_FALSE
;
576 nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData
* aData
)
578 nsIAtom
* pseudoTag
= aData
->mPseudoTag
;
579 if (pseudoTag
== nsCSSAnonBoxes::tableCol
) {
580 nsRuleWalker
*ruleWalker
= aData
->mRuleWalker
;
582 ruleWalker
->Forward(mTableColRule
);
591 nsHTMLStyleSheet::GetSheetURI(nsIURI
** aSheetURI
) const
594 NS_IF_ADDREF(*aSheetURI
);
599 nsHTMLStyleSheet::GetBaseURI(nsIURI
** aBaseURI
) const
602 NS_IF_ADDREF(*aBaseURI
);
607 nsHTMLStyleSheet::GetTitle(nsString
& aTitle
) const
614 nsHTMLStyleSheet::GetType(nsString
& aType
) const
616 aType
.AssignLiteral("text/html");
620 NS_IMETHODIMP_(PRBool
)
621 nsHTMLStyleSheet::HasRules() const
623 return PR_TRUE
; // We have rules at all reasonable times
627 nsHTMLStyleSheet::GetApplicable(PRBool
& aApplicable
) const
629 aApplicable
= PR_TRUE
;
634 nsHTMLStyleSheet::SetEnabled(PRBool aEnabled
)
635 { // these can't be disabled
640 nsHTMLStyleSheet::GetComplete(PRBool
& aComplete
) const
647 nsHTMLStyleSheet::SetComplete()
653 nsHTMLStyleSheet::GetParentSheet(nsIStyleSheet
*& aParent
) const
660 nsHTMLStyleSheet::GetOwningDocument(nsIDocument
*& aDocument
) const
662 aDocument
= mDocument
;
663 NS_IF_ADDREF(aDocument
);
668 nsHTMLStyleSheet::SetOwningDocument(nsIDocument
* aDocument
)
670 mDocument
= aDocument
; // not refcounted
675 nsHTMLStyleSheet::Init(nsIURI
* aURL
, nsIDocument
* aDocument
)
677 NS_PRECONDITION(aURL
&& aDocument
, "null ptr");
678 if (! aURL
|| ! aDocument
)
679 return NS_ERROR_NULL_POINTER
;
681 if (mURL
|| mDocument
)
682 return NS_ERROR_ALREADY_INITIALIZED
;
684 mDocument
= aDocument
; // not refcounted!
691 nsHTMLStyleSheet::Reset(nsIURI
* aURL
)
697 NS_IF_RELEASE(mLinkRule
);
698 NS_IF_RELEASE(mVisitedRule
);
699 NS_IF_RELEASE(mActiveRule
);
700 NS_IF_RELEASE(mDocumentColorRule
);
702 if (mMappedAttrTable
.ops
) {
703 PL_DHashTableFinish(&mMappedAttrTable
);
704 mMappedAttrTable
.ops
= nsnull
;
711 nsHTMLStyleSheet::GetLinkColor(nscolor
& aColor
)
714 return NS_HTML_STYLE_PROPERTY_NOT_THERE
;
717 aColor
= mLinkRule
->mColor
;
723 nsHTMLStyleSheet::GetActiveLinkColor(nscolor
& aColor
)
726 return NS_HTML_STYLE_PROPERTY_NOT_THERE
;
729 aColor
= mActiveRule
->mColor
;
735 nsHTMLStyleSheet::GetVisitedLinkColor(nscolor
& aColor
)
738 return NS_HTML_STYLE_PROPERTY_NOT_THERE
;
741 aColor
= mVisitedRule
->mColor
;
747 nsHTMLStyleSheet::SetLinkColor(nscolor aColor
)
750 if (mLinkRule
->mColor
== aColor
)
752 NS_RELEASE(mLinkRule
);
755 mLinkRule
= new HTMLColorRule();
757 return NS_ERROR_OUT_OF_MEMORY
;
758 NS_ADDREF(mLinkRule
);
760 mLinkRule
->mColor
= aColor
;
766 nsHTMLStyleSheet::SetActiveLinkColor(nscolor aColor
)
769 if (mActiveRule
->mColor
== aColor
)
771 NS_RELEASE(mActiveRule
);
774 mActiveRule
= new HTMLColorRule();
776 return NS_ERROR_OUT_OF_MEMORY
;
777 NS_ADDREF(mActiveRule
);
779 mActiveRule
->mColor
= aColor
;
784 nsHTMLStyleSheet::SetVisitedLinkColor(nscolor aColor
)
787 if (mVisitedRule
->mColor
== aColor
)
789 NS_RELEASE(mVisitedRule
);
792 mVisitedRule
= new HTMLColorRule();
794 return NS_ERROR_OUT_OF_MEMORY
;
795 NS_ADDREF(mVisitedRule
);
797 mVisitedRule
->mColor
= aColor
;
801 already_AddRefed
<nsMappedAttributes
>
802 nsHTMLStyleSheet::UniqueMappedAttributes(nsMappedAttributes
* aMapped
)
804 if (!mMappedAttrTable
.ops
) {
805 PRBool res
= PL_DHashTableInit(&mMappedAttrTable
, &MappedAttrTable_Ops
,
806 nsnull
, sizeof(MappedAttrTableEntry
), 16);
808 mMappedAttrTable
.ops
= nsnull
;
812 MappedAttrTableEntry
*entry
= static_cast<MappedAttrTableEntry
*>
813 (PL_DHashTableOperate(&mMappedAttrTable
, aMapped
, PL_DHASH_ADD
));
816 if (!entry
->mAttributes
) {
817 // We added a new entry to the hashtable, so we have a new unique set.
818 entry
->mAttributes
= aMapped
;
820 NS_ADDREF(entry
->mAttributes
); // for caller
821 return entry
->mAttributes
;
825 nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes
* aMapped
)
827 NS_ENSURE_TRUE(aMapped
, /**/);
829 NS_ASSERTION(mMappedAttrTable
.ops
, "table uninitialized");
831 PRUint32 entryCount
= mMappedAttrTable
.entryCount
- 1;
834 PL_DHashTableOperate(&mMappedAttrTable
, aMapped
, PL_DHASH_REMOVE
);
836 NS_ASSERTION(entryCount
== mMappedAttrTable
.entryCount
, "not removed");
840 void nsHTMLStyleSheet::List(FILE* out
, PRInt32 aIndent
) const
843 for (PRInt32 index
= aIndent
; --index
>= 0; ) fputs(" ", out
);
845 fputs("HTML Style Sheet: ", out
);
846 nsCAutoString urlSpec
;
847 mURL
->GetSpec(urlSpec
);
848 if (!urlSpec
.IsEmpty()) {
849 fputs(urlSpec
.get(), out
);
855 // XXX For convenience and backwards compatibility
857 NS_NewHTMLStyleSheet(nsHTMLStyleSheet
** aInstancePtrResult
, nsIURI
* aURL
,
858 nsIDocument
* aDocument
)
861 nsHTMLStyleSheet
* sheet
;
862 if (NS_FAILED(rv
= NS_NewHTMLStyleSheet(&sheet
)))
865 if (NS_FAILED(rv
= sheet
->Init(aURL
, aDocument
))) {
870 *aInstancePtrResult
= sheet
;
876 NS_NewHTMLStyleSheet(nsHTMLStyleSheet
** aInstancePtrResult
)
878 NS_ASSERTION(aInstancePtrResult
, "null out param");
880 nsHTMLStyleSheet
*it
= new nsHTMLStyleSheet();
882 *aInstancePtrResult
= nsnull
;
883 return NS_ERROR_OUT_OF_MEMORY
;
887 nsresult rv
= it
->Init();
891 *aInstancePtrResult
= it
; // NS_ADDREF above, or set to null by NS_RELEASE