Bug 473680. Stop crashtest 458637-1.html early (returning success) if it's running...
[mozilla-central.git] / layout / style / nsHTMLStyleSheet.cpp
blobad1303809f7725e8545e94a22d058b2f21570a2f
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
14 * License.
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.
23 * Contributor(s):
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
49 * HTML attributes
52 #include "nsHTMLStyleSheet.h"
53 #include "nsINameSpaceManager.h"
54 #include "nsIAtom.h"
55 #include "nsIURL.h"
56 #include "nsMappedAttributes.h"
57 #include "nsILink.h"
58 #include "nsIFrame.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)
75 NS_IMETHODIMP
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);
83 return NS_OK;
86 #ifdef DEBUG
87 NS_IMETHODIMP
88 nsHTMLStyleSheet::HTMLColorRule::List(FILE* out, PRInt32 aIndent) const
90 return NS_OK;
92 #endif
95 NS_IMPL_ISUPPORTS1(nsHTMLStyleSheet::GenericTableRule, nsIStyleRule)
97 NS_IMETHODIMP
98 nsHTMLStyleSheet::GenericTableRule::MapRuleInfoInto(nsRuleData* aRuleData)
100 // Nothing to do.
101 return NS_OK;
104 #ifdef DEBUG
105 NS_IMETHODIMP
106 nsHTMLStyleSheet::GenericTableRule::List(FILE* out, PRInt32 aIndent) const
108 return NS_OK;
110 #endif
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();
118 if (parentContext) {
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;
127 NS_IMETHODIMP
128 nsHTMLStyleSheet::TableTHRule::MapRuleInfoInto(nsRuleData* aRuleData)
130 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
131 aRuleData->mCanStoreInRuleTree = PR_FALSE;
132 aRuleData->mPostResolveCallback = &PostResolveCallback;
134 return NS_OK;
137 static void
138 ProcessTableRulesAttribute(void* aStyleStruct,
139 nsRuleData* aRuleData,
140 PRUint8 aSide,
141 PRBool aGroup,
142 PRUint8 aRulesArg1,
143 PRUint8 aRulesArg2,
144 PRUint8 aRulesArg3)
146 if (!aStyleStruct || !aRuleData || !aRuleData->mPresContext) return;
148 nsStyleContext* tableContext = aRuleData->mStyleContext->GetParent();
149 if (!tableContext)
150 return;
151 if (!aGroup) {
152 tableContext = tableContext->GetParent();
153 if (!tableContext)
154 return;
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;
165 if (!borderData)
166 return;
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);
189 nscolor borderColor;
190 PRBool foreground;
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);
214 NS_IMETHODIMP
215 nsHTMLStyleSheet::TableTbodyRule::MapRuleInfoInto(nsRuleData* aRuleData)
217 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
218 aRuleData->mCanStoreInRuleTree = PR_FALSE;
219 aRuleData->mPostResolveCallback = &TbodyPostResolveCallback;
221 return NS_OK;
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);
233 NS_IMETHODIMP
234 nsHTMLStyleSheet::TableRowRule::MapRuleInfoInto(nsRuleData* aRuleData)
236 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
237 aRuleData->mCanStoreInRuleTree = PR_FALSE;
238 aRuleData->mPostResolveCallback = &RowPostResolveCallback;
240 return NS_OK;
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);
251 NS_IMETHODIMP
252 nsHTMLStyleSheet::TableColgroupRule::MapRuleInfoInto(nsRuleData* aRuleData)
254 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
255 aRuleData->mCanStoreInRuleTree = PR_FALSE;
256 aRuleData->mPostResolveCallback = &ColgroupPostResolveCallback;
258 return NS_OK;
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);
280 NS_IMETHODIMP
281 nsHTMLStyleSheet::TableColRule::MapRuleInfoInto(nsRuleData* aRuleData)
283 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
284 aRuleData->mCanStoreInRuleTree = PR_FALSE;
285 aRuleData->mPostResolveCallback = &ColPostResolveCallback;
287 return NS_OK;
290 NS_IMETHODIMP
291 nsHTMLStyleSheet::TableUngroupedColRule::MapRuleInfoInto(nsRuleData* aRuleData)
293 if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
294 aRuleData->mCanStoreInRuleTree = PR_FALSE;
295 aRuleData->mPostResolveCallback = &UngroupedColPostResolveCallback;
297 return NS_OK;
299 // -----------------------------------------------------------
301 struct MappedAttrTableEntry : public PLDHashEntryHdr {
302 nsMappedAttributes *mAttributes;
305 static 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 static 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 static PRBool
324 MappedAttrTable_MatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
325 const void *key)
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 = {
336 PL_DHashAllocTable,
337 PL_DHashFreeTable,
338 MappedAttrTable_HashKey,
339 MappedAttrTable_MatchEntry,
340 PL_DHashMoveEntryStub,
341 MappedAttrTable_ClearEntry,
342 PL_DHashFinalizeStub,
343 NULL
346 // -----------------------------------------------------------
348 nsHTMLStyleSheet::nsHTMLStyleSheet(void)
349 : mURL(nsnull),
350 mDocument(nsnull),
351 mLinkRule(nsnull),
352 mVisitedRule(nsnull),
353 mActiveRule(nsnull),
354 mDocumentColorRule(nsnull)
356 mMappedAttrTable.ops = nsnull;
359 nsresult
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();
368 if (!mTableRowRule)
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();
378 if (!mTableColRule)
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();
388 if (!mTableTHRule)
389 return NS_ERROR_OUT_OF_MEMORY;
390 NS_ADDREF(mTableTHRule);
391 return NS_OK;
394 nsHTMLStyleSheet::~nsHTMLStyleSheet()
396 NS_IF_RELEASE(mURL);
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());
419 if (!domdoc)
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);
425 if (!bodyFrame)
426 return NS_ERROR_FAILURE;
427 *aColor = bodyFrame->GetStyleColor()->mColor;
428 return NS_OK;
431 NS_IMETHODIMP
432 nsHTMLStyleSheet::RulesMatching(ElementRuleProcessorData* aData)
434 nsIContent *content = aData->mContent;
436 if (content) {
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:
447 if (mLinkRule)
448 ruleWalker->Forward(mLinkRule);
449 break;
450 case eLinkState_Visited:
451 if (mVisitedRule)
452 ruleWalker->Forward(mVisitedRule);
453 break;
454 default:
455 break;
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
463 } // end A tag
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);
479 } else {
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) {
488 nscolor bodyColor;
489 nsresult rv =
490 GetBodyColor(ruleWalker->GetCurrentNode()->GetPresContext(),
491 &bodyColor);
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);
511 return NS_OK;
514 // Test if style is dependent on content state
515 NS_IMETHODIMP
516 nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData,
517 nsReStyleHint* aResult)
519 if (aData->mContent &&
520 aData->mIsHTMLContent &&
521 aData->mIsLink &&
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;
528 else
529 *aResult = nsReStyleHint(0);
531 return NS_OK;
534 NS_IMETHODIMP
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
540 // needed.
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) &&
546 content &&
547 content->IsNodeOfType(nsINode::eHTML) &&
548 aData->mContentTag == nsGkAtoms::a) {
549 *aResult = eReStyle_Self;
550 return NS_OK;
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;
559 return NS_OK;
562 *aResult = nsReStyleHint(0);
563 return NS_OK;
566 NS_IMETHODIMP
567 nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext,
568 PRBool* aRulesChanged)
570 *aRulesChanged = PR_FALSE;
571 return NS_OK;
575 NS_IMETHODIMP
576 nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
578 nsIAtom* pseudoTag = aData->mPseudoTag;
579 if (pseudoTag == nsCSSAnonBoxes::tableCol) {
580 nsRuleWalker *ruleWalker = aData->mRuleWalker;
581 if (ruleWalker) {
582 ruleWalker->Forward(mTableColRule);
585 return NS_OK;
589 // nsIStyleSheet api
590 NS_IMETHODIMP
591 nsHTMLStyleSheet::GetSheetURI(nsIURI** aSheetURI) const
593 *aSheetURI = mURL;
594 NS_IF_ADDREF(*aSheetURI);
595 return NS_OK;
598 NS_IMETHODIMP
599 nsHTMLStyleSheet::GetBaseURI(nsIURI** aBaseURI) const
601 *aBaseURI = mURL;
602 NS_IF_ADDREF(*aBaseURI);
603 return NS_OK;
606 NS_IMETHODIMP
607 nsHTMLStyleSheet::GetTitle(nsString& aTitle) const
609 aTitle.Truncate();
610 return NS_OK;
613 NS_IMETHODIMP
614 nsHTMLStyleSheet::GetType(nsString& aType) const
616 aType.AssignLiteral("text/html");
617 return NS_OK;
620 NS_IMETHODIMP_(PRBool)
621 nsHTMLStyleSheet::HasRules() const
623 return PR_TRUE; // We have rules at all reasonable times
626 NS_IMETHODIMP
627 nsHTMLStyleSheet::GetApplicable(PRBool& aApplicable) const
629 aApplicable = PR_TRUE;
630 return NS_OK;
633 NS_IMETHODIMP
634 nsHTMLStyleSheet::SetEnabled(PRBool aEnabled)
635 { // these can't be disabled
636 return NS_OK;
639 NS_IMETHODIMP
640 nsHTMLStyleSheet::GetComplete(PRBool& aComplete) const
642 aComplete = PR_TRUE;
643 return NS_OK;
646 NS_IMETHODIMP
647 nsHTMLStyleSheet::SetComplete()
649 return NS_OK;
652 NS_IMETHODIMP
653 nsHTMLStyleSheet::GetParentSheet(nsIStyleSheet*& aParent) const
655 aParent = nsnull;
656 return NS_OK;
659 NS_IMETHODIMP
660 nsHTMLStyleSheet::GetOwningDocument(nsIDocument*& aDocument) const
662 aDocument = mDocument;
663 NS_IF_ADDREF(aDocument);
664 return NS_OK;
667 NS_IMETHODIMP
668 nsHTMLStyleSheet::SetOwningDocument(nsIDocument* aDocument)
670 mDocument = aDocument; // not refcounted
671 return NS_OK;
674 nsresult
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!
685 mURL = aURL;
686 NS_ADDREF(mURL);
687 return NS_OK;
690 nsresult
691 nsHTMLStyleSheet::Reset(nsIURI* aURL)
693 NS_IF_RELEASE(mURL);
694 mURL = aURL;
695 NS_ADDREF(mURL);
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;
707 return NS_OK;
710 nsresult
711 nsHTMLStyleSheet::GetLinkColor(nscolor& aColor)
713 if (!mLinkRule) {
714 return NS_HTML_STYLE_PROPERTY_NOT_THERE;
716 else {
717 aColor = mLinkRule->mColor;
718 return NS_OK;
722 nsresult
723 nsHTMLStyleSheet::GetActiveLinkColor(nscolor& aColor)
725 if (!mActiveRule) {
726 return NS_HTML_STYLE_PROPERTY_NOT_THERE;
728 else {
729 aColor = mActiveRule->mColor;
730 return NS_OK;
734 nsresult
735 nsHTMLStyleSheet::GetVisitedLinkColor(nscolor& aColor)
737 if (!mVisitedRule) {
738 return NS_HTML_STYLE_PROPERTY_NOT_THERE;
740 else {
741 aColor = mVisitedRule->mColor;
742 return NS_OK;
746 nsresult
747 nsHTMLStyleSheet::SetLinkColor(nscolor aColor)
749 if (mLinkRule) {
750 if (mLinkRule->mColor == aColor)
751 return NS_OK;
752 NS_RELEASE(mLinkRule);
755 mLinkRule = new HTMLColorRule();
756 if (!mLinkRule)
757 return NS_ERROR_OUT_OF_MEMORY;
758 NS_ADDREF(mLinkRule);
760 mLinkRule->mColor = aColor;
761 return NS_OK;
765 nsresult
766 nsHTMLStyleSheet::SetActiveLinkColor(nscolor aColor)
768 if (mActiveRule) {
769 if (mActiveRule->mColor == aColor)
770 return NS_OK;
771 NS_RELEASE(mActiveRule);
774 mActiveRule = new HTMLColorRule();
775 if (!mActiveRule)
776 return NS_ERROR_OUT_OF_MEMORY;
777 NS_ADDREF(mActiveRule);
779 mActiveRule->mColor = aColor;
780 return NS_OK;
783 nsresult
784 nsHTMLStyleSheet::SetVisitedLinkColor(nscolor aColor)
786 if (mVisitedRule) {
787 if (mVisitedRule->mColor == aColor)
788 return NS_OK;
789 NS_RELEASE(mVisitedRule);
792 mVisitedRule = new HTMLColorRule();
793 if (!mVisitedRule)
794 return NS_ERROR_OUT_OF_MEMORY;
795 NS_ADDREF(mVisitedRule);
797 mVisitedRule->mColor = aColor;
798 return NS_OK;
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);
807 if (!res) {
808 mMappedAttrTable.ops = nsnull;
809 return nsnull;
812 MappedAttrTableEntry *entry = static_cast<MappedAttrTableEntry*>
813 (PL_DHashTableOperate(&mMappedAttrTable, aMapped, PL_DHASH_ADD));
814 if (!entry)
815 return nsnull;
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;
824 void
825 nsHTMLStyleSheet::DropMappedAttributes(nsMappedAttributes* aMapped)
827 NS_ENSURE_TRUE(aMapped, /**/);
829 NS_ASSERTION(mMappedAttrTable.ops, "table uninitialized");
830 #ifdef DEBUG
831 PRUint32 entryCount = mMappedAttrTable.entryCount - 1;
832 #endif
834 PL_DHashTableOperate(&mMappedAttrTable, aMapped, PL_DHASH_REMOVE);
836 NS_ASSERTION(entryCount == mMappedAttrTable.entryCount, "not removed");
839 #ifdef DEBUG
840 void nsHTMLStyleSheet::List(FILE* out, PRInt32 aIndent) const
842 // Indent
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);
851 fputs("\n", out);
853 #endif
855 // XXX For convenience and backwards compatibility
856 nsresult
857 NS_NewHTMLStyleSheet(nsHTMLStyleSheet** aInstancePtrResult, nsIURI* aURL,
858 nsIDocument* aDocument)
860 nsresult rv;
861 nsHTMLStyleSheet* sheet;
862 if (NS_FAILED(rv = NS_NewHTMLStyleSheet(&sheet)))
863 return rv;
865 if (NS_FAILED(rv = sheet->Init(aURL, aDocument))) {
866 NS_RELEASE(sheet);
867 return rv;
870 *aInstancePtrResult = sheet;
871 return NS_OK;
875 nsresult
876 NS_NewHTMLStyleSheet(nsHTMLStyleSheet** aInstancePtrResult)
878 NS_ASSERTION(aInstancePtrResult, "null out param");
880 nsHTMLStyleSheet *it = new nsHTMLStyleSheet();
881 if (!it) {
882 *aInstancePtrResult = nsnull;
883 return NS_ERROR_OUT_OF_MEMORY;
886 NS_ADDREF(it);
887 nsresult rv = it->Init();
888 if (NS_FAILED(rv))
889 NS_RELEASE(it);
891 *aInstancePtrResult = it; // NS_ADDREF above, or set to null by NS_RELEASE
892 return rv;