Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLBodyElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Daniel Glazman <glazman@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 #include "nscore.h"
00039 #include "nsCOMPtr.h"
00040 #include "nsIDOMHTMLBodyElement.h"
00041 #include "nsIDOMEventReceiver.h"
00042 #include "nsGenericHTMLElement.h"
00043 #include "nsHTMLAtoms.h"
00044 #include "nsStyleConsts.h"
00045 #include "nsPresContext.h"
00046 #include "nsIPresShell.h"
00047 #include "nsIDocument.h"
00048 #include "nsIHTMLDocument.h"
00049 #include "nsHTMLStyleSheet.h"
00050 #include "nsIHTMLCSSStyleSheet.h"
00051 #include "nsICSSStyleRule.h"
00052 #include "nsIContentViewer.h"
00053 #include "nsIMarkupDocumentViewer.h"
00054 #include "nsMappedAttributes.h"
00055 #include "nsISupportsArray.h"
00056 #include "nsRuleData.h"
00057 #include "nsIFrame.h"
00058 #include "nsIDocShell.h"
00059 #include "nsIEditorDocShell.h"
00060 #include "nsCOMPtr.h"
00061 #include "nsIView.h"
00062 #include "nsLayoutAtoms.h"
00063 #include "nsRuleWalker.h"
00064 #include "nsIViewManager.h"
00065 
00066 //----------------------------------------------------------------------
00067 
00068 class nsHTMLBodyElement;
00069 
00070 class BodyRule: public nsIStyleRule {
00071 public:
00072   BodyRule(nsHTMLBodyElement* aPart);
00073   virtual ~BodyRule();
00074 
00075   NS_DECL_ISUPPORTS
00076 
00077   // nsIStyleRule interface
00078   NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
00079 #ifdef DEBUG
00080   NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
00081 #endif
00082 
00083   nsHTMLBodyElement*  mPart;  // not ref-counted, cleared by content 
00084 };
00085 
00086 //----------------------------------------------------------------------
00087 
00088 class nsHTMLBodyElement : public nsGenericHTMLElement,
00089                           public nsIDOMHTMLBodyElement
00090 {
00091 public:
00092   nsHTMLBodyElement(nsINodeInfo *aNodeInfo);
00093   virtual ~nsHTMLBodyElement();
00094 
00095   // nsISupports
00096   NS_DECL_ISUPPORTS_INHERITED
00097 
00098   // nsIDOMNode
00099   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
00100 
00101   // nsIDOMElement
00102   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
00103 
00104   // nsIDOMHTMLElement
00105   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
00106 
00107   // nsIDOMHTMLBodyElement
00108   NS_DECL_NSIDOMHTMLBODYELEMENT
00109 
00110   virtual PRBool ParseAttribute(nsIAtom* aAttribute,
00111                                 const nsAString& aValue,
00112                                 nsAttrValue& aResult);
00113   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
00114                               PRBool aNullParent = PR_TRUE);
00115   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
00116   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
00117   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
00118   virtual already_AddRefed<nsIEditor> GetAssociatedEditor();
00119 
00120 protected:
00121   BodyRule* mContentStyleRule;
00122 };
00123 
00124 //----------------------------------------------------------------------
00125 
00126 BodyRule::BodyRule(nsHTMLBodyElement* aPart)
00127 {
00128   mPart = aPart;
00129 }
00130 
00131 BodyRule::~BodyRule()
00132 {
00133 }
00134 
00135 NS_IMPL_ISUPPORTS1(BodyRule, nsIStyleRule)
00136 
00137 NS_IMETHODIMP
00138 BodyRule::MapRuleInfoInto(nsRuleData* aData)
00139 {
00140   if (!aData || (aData->mSID != eStyleStruct_Margin) || !aData->mMarginData || !mPart)
00141     return NS_OK; // We only care about margins.
00142 
00143   PRInt32 bodyMarginWidth  = -1;
00144   PRInt32 bodyMarginHeight = -1;
00145   PRInt32 bodyTopMargin = -1;
00146   PRInt32 bodyBottomMargin = -1;
00147   PRInt32 bodyLeftMargin = -1;
00148   PRInt32 bodyRightMargin = -1;
00149 
00150   // check the mode (fortunately, the ruleData has a presContext for us to use!)
00151   NS_ASSERTION(aData->mPresContext, "null presContext in ruleNode was unexpected");
00152   nsCompatibility mode = aData->mPresContext->CompatibilityMode();
00153 
00154 
00155   const nsAttrValue* value;
00156   if (mPart->GetAttrCount() > 0) {
00157     // if marginwidth/marginheight are set, reflect them as 'margin'
00158     value = mPart->GetParsedAttr(nsHTMLAtoms::marginwidth);
00159     if (value && value->Type() == nsAttrValue::eInteger) {
00160       bodyMarginWidth = value->GetIntegerValue();
00161       if (bodyMarginWidth < 0) bodyMarginWidth = 0;
00162       nsCSSRect& margin = aData->mMarginData->mMargin;
00163       if (margin.mLeft.GetUnit() == eCSSUnit_Null)
00164         margin.mLeft.SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
00165       if (margin.mRight.GetUnit() == eCSSUnit_Null)
00166         margin.mRight.SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
00167     }
00168 
00169     value = mPart->GetParsedAttr(nsHTMLAtoms::marginheight);
00170     if (value && value->Type() == nsAttrValue::eInteger) {
00171       bodyMarginHeight = value->GetIntegerValue();
00172       if (bodyMarginHeight < 0) bodyMarginHeight = 0;
00173       nsCSSRect& margin = aData->mMarginData->mMargin;
00174       if (margin.mTop.GetUnit() == eCSSUnit_Null)
00175         margin.mTop.SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
00176       if (margin.mBottom.GetUnit() == eCSSUnit_Null)
00177         margin.mBottom.SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
00178     }
00179 
00180     if (eCompatibility_NavQuirks == mode){
00181       // topmargin (IE-attribute)
00182       value = mPart->GetParsedAttr(nsHTMLAtoms::topmargin);
00183       if (value && value->Type() == nsAttrValue::eInteger) {
00184         bodyTopMargin = value->GetIntegerValue();
00185         if (bodyTopMargin < 0) bodyTopMargin = 0;
00186         nsCSSRect& margin = aData->mMarginData->mMargin;
00187         if (margin.mTop.GetUnit() == eCSSUnit_Null)
00188           margin.mTop.SetFloatValue((float)bodyTopMargin, eCSSUnit_Pixel);
00189       }
00190 
00191       // bottommargin (IE-attribute)
00192       value = mPart->GetParsedAttr(nsHTMLAtoms::bottommargin);
00193       if (value && value->Type() == nsAttrValue::eInteger) {
00194         bodyBottomMargin = value->GetIntegerValue();
00195         if (bodyBottomMargin < 0) bodyBottomMargin = 0;
00196         nsCSSRect& margin = aData->mMarginData->mMargin;
00197         if (margin.mBottom.GetUnit() == eCSSUnit_Null)
00198           margin.mBottom.SetFloatValue((float)bodyBottomMargin, eCSSUnit_Pixel);
00199       }
00200 
00201       // leftmargin (IE-attribute)
00202       value = mPart->GetParsedAttr(nsHTMLAtoms::leftmargin);
00203       if (value && value->Type() == nsAttrValue::eInteger) {
00204         bodyLeftMargin = value->GetIntegerValue();
00205         if (bodyLeftMargin < 0) bodyLeftMargin = 0;
00206         nsCSSRect& margin = aData->mMarginData->mMargin;
00207         if (margin.mLeft.GetUnit() == eCSSUnit_Null)
00208           margin.mLeft.SetFloatValue((float)bodyLeftMargin, eCSSUnit_Pixel);
00209       }
00210 
00211       // rightmargin (IE-attribute)
00212       value = mPart->GetParsedAttr(nsHTMLAtoms::rightmargin);
00213       if (value && value->Type() == nsAttrValue::eInteger) {
00214         bodyRightMargin = value->GetIntegerValue();
00215         if (bodyRightMargin < 0) bodyRightMargin = 0;
00216         nsCSSRect& margin = aData->mMarginData->mMargin;
00217         if (margin.mRight.GetUnit() == eCSSUnit_Null)
00218           margin.mRight.SetFloatValue((float)bodyRightMargin, eCSSUnit_Pixel);
00219       }
00220     }
00221 
00222   }
00223 
00224   // if marginwidth or marginheight is set in the <frame> and not set in the <body>
00225   // reflect them as margin in the <body>
00226   if (bodyMarginWidth == -1 || bodyMarginHeight == -1) {
00227     nsCOMPtr<nsISupports> container = aData->mPresContext->GetContainer();
00228     if (container) {
00229       nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
00230       if (docShell) {
00231         nscoord frameMarginWidth=-1;  // default value
00232         nscoord frameMarginHeight=-1; // default value
00233         docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set   
00234         docShell->GetMarginHeight(&frameMarginHeight); 
00235         if ((frameMarginWidth >= 0) && (bodyMarginWidth == -1)) { // set in <frame> & not in <body> 
00236           if (eCompatibility_NavQuirks == mode) {
00237             if ((bodyMarginHeight == -1) && (0 > frameMarginHeight)) // nav quirk 
00238               frameMarginHeight = 0;
00239           }
00240         }
00241         if ((frameMarginHeight >= 0) && (bodyMarginHeight == -1)) { // set in <frame> & not in <body> 
00242           if (eCompatibility_NavQuirks == mode) {
00243             if ((bodyMarginWidth == -1) && (0 > frameMarginWidth)) // nav quirk
00244               frameMarginWidth = 0;
00245           }
00246         }
00247 
00248         if ((bodyMarginWidth == -1) && (frameMarginWidth >= 0)) {
00249           nsCSSRect& margin = aData->mMarginData->mMargin;
00250           if (margin.mLeft.GetUnit() == eCSSUnit_Null)
00251             margin.mLeft.SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
00252           if (margin.mRight.GetUnit() == eCSSUnit_Null)
00253             margin.mRight.SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
00254         }
00255 
00256         if ((bodyMarginHeight == -1) && (frameMarginHeight >= 0)) {
00257           nsCSSRect& margin = aData->mMarginData->mMargin;
00258           if (margin.mTop.GetUnit() == eCSSUnit_Null)
00259             margin.mTop.SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
00260           if (margin.mBottom.GetUnit() == eCSSUnit_Null)
00261             margin.mBottom.SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
00262         }
00263       }
00264     }
00265   }
00266   return NS_OK;
00267 }
00268 
00269 #ifdef DEBUG
00270 NS_IMETHODIMP
00271 BodyRule::List(FILE* out, PRInt32 aIndent) const
00272 {
00273   return NS_OK;
00274 }
00275 #endif
00276 
00277 //----------------------------------------------------------------------
00278 
00279 
00280 NS_IMPL_NS_NEW_HTML_ELEMENT(Body)
00281 
00282 
00283 nsHTMLBodyElement::nsHTMLBodyElement(nsINodeInfo *aNodeInfo)
00284   : nsGenericHTMLElement(aNodeInfo),
00285     mContentStyleRule(nsnull)
00286 {
00287 }
00288 
00289 nsHTMLBodyElement::~nsHTMLBodyElement()
00290 {
00291   if (mContentStyleRule) {
00292     mContentStyleRule->mPart = nsnull;
00293     NS_RELEASE(mContentStyleRule);
00294   }
00295 }
00296 
00297 
00298 NS_IMPL_ADDREF_INHERITED(nsHTMLBodyElement, nsGenericElement) 
00299 NS_IMPL_RELEASE_INHERITED(nsHTMLBodyElement, nsGenericElement) 
00300 
00301 // QueryInterface implementation for nsHTMLBodyElement
00302 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLBodyElement, nsGenericHTMLElement)
00303   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLBodyElement)
00304   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLBodyElement)
00305 NS_HTML_CONTENT_INTERFACE_MAP_END
00306 
00307 
00308 NS_IMPL_DOM_CLONENODE(nsHTMLBodyElement)
00309 
00310 
00311 NS_IMPL_URI_ATTR(nsHTMLBodyElement, Background, background)
00312 
00313 #define NS_IMPL_HTMLBODY_COLOR_ATTR(attr_, func_, default_)         \
00314 NS_IMETHODIMP                                                       \
00315 nsHTMLBodyElement::Get##func_(nsAString& aColor)                    \
00316 {                                                                   \
00317   aColor.Truncate();                                                \
00318   nsAutoString color;                                               \
00319   nscolor attrColor;                                                \
00320   if (NS_CONTENT_ATTR_NOT_THERE ==                                  \
00321       GetAttr(kNameSpaceID_None, nsHTMLAtoms::attr_, color)) {      \
00322                                                                     \
00323     nsPresContext *presContext = GetPresContext();                  \
00324     if (presContext) {                                              \
00325       attrColor = presContext->Default##default_();                 \
00326       NS_RGBToHex(attrColor, aColor);                               \
00327     }                                                               \
00328   } else if (NS_ColorNameToRGB(color, &attrColor)) {                \
00329     NS_RGBToHex(attrColor, aColor);                                 \
00330   } else {                                                          \
00331     aColor.Assign(color);                                           \
00332   }                                                                 \
00333   return NS_OK;                                                     \
00334 }                                                                   \
00335 NS_IMETHODIMP                                                       \
00336 nsHTMLBodyElement::Set##func_(const nsAString& aColor)              \
00337 {                                                                   \
00338   return SetAttr(kNameSpaceID_None, nsHTMLAtoms::attr_, aColor,     \
00339                  PR_TRUE);                                          \
00340 }
00341 
00342 NS_IMPL_HTMLBODY_COLOR_ATTR(vlink, VLink, VisitedLinkColor)
00343 NS_IMPL_HTMLBODY_COLOR_ATTR(alink, ALink, ActiveLinkColor)
00344 NS_IMPL_HTMLBODY_COLOR_ATTR(link, Link, LinkColor)
00345 // XXX Should text check the body frame's style struct for color,
00346 // like we do for bgColor?
00347 NS_IMPL_HTMLBODY_COLOR_ATTR(text, Text, Color)
00348 
00349 NS_IMETHODIMP 
00350 nsHTMLBodyElement::GetBgColor(nsAString& aBgColor)
00351 {
00352   aBgColor.Truncate();
00353 
00354   nsAutoString attr;
00355   nscolor bgcolor;
00356   nsresult rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::bgcolor, attr);
00357 
00358   // If we don't have an attribute, find the actual color used for
00359   // (generally from the user agent style sheet) for compatibility
00360   if (rv == NS_CONTENT_ATTR_NOT_THERE) {
00361     nsIDocument *document = GetCurrentDoc();
00362     if (document) {
00363       // Make sure the style is up-to-date, since we need it
00364       document->FlushPendingNotifications(Flush_Style);
00365 
00366       nsIFrame* frame = GetPrimaryFrameFor(this, document, PR_FALSE);
00367     
00368       if (frame) {
00369         bgcolor = frame->GetStyleBackground()->mBackgroundColor;
00370         NS_RGBToHex(bgcolor, aBgColor);
00371       }
00372     }
00373   }
00374   else if (NS_ColorNameToRGB(attr, &bgcolor)) {
00375     // If we have a color name which we can convert to an nscolor,
00376     // then we should use the hex value instead of the color name.
00377     NS_RGBToHex(bgcolor, aBgColor);
00378   }
00379   else {
00380     // Otherwise, just assign whatever the attribute value is.
00381     aBgColor.Assign(attr);
00382   }
00383 
00384   return NS_OK;
00385 }
00386 
00387 NS_IMETHODIMP 
00388 nsHTMLBodyElement::SetBgColor(const nsAString& aBgColor)
00389 {
00390   return SetAttr(kNameSpaceID_None, nsHTMLAtoms::bgcolor, aBgColor, PR_TRUE); 
00391 }
00392 
00393 PRBool
00394 nsHTMLBodyElement::ParseAttribute(nsIAtom* aAttribute,
00395                                   const nsAString& aValue,
00396                                   nsAttrValue& aResult)
00397 {
00398   if (aAttribute == nsHTMLAtoms::bgcolor ||
00399       aAttribute == nsHTMLAtoms::text ||
00400       aAttribute == nsHTMLAtoms::link ||
00401       aAttribute == nsHTMLAtoms::alink ||
00402       aAttribute == nsHTMLAtoms::vlink) {
00403     return aResult.ParseColor(aValue, GetOwnerDoc());
00404   }
00405   if (aAttribute == nsHTMLAtoms::marginwidth ||
00406       aAttribute == nsHTMLAtoms::marginheight ||
00407       aAttribute == nsHTMLAtoms::topmargin ||
00408       aAttribute == nsHTMLAtoms::bottommargin ||
00409       aAttribute == nsHTMLAtoms::leftmargin ||
00410       aAttribute == nsHTMLAtoms::rightmargin) {
00411     return aResult.ParseIntWithBounds(aValue, 0);
00412   }
00413 
00414   return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
00415 }
00416 
00417 void
00418 nsHTMLBodyElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
00419 {
00420   if (mContentStyleRule) {
00421     mContentStyleRule->mPart = nsnull;
00422 
00423     // destroy old style rule
00424     NS_RELEASE(mContentStyleRule);
00425   }
00426 
00427   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);  
00428 }
00429 
00430 static 
00431 void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
00432 {
00433   if (aData->mSID == eStyleStruct_Display) {
00434     // When display if first asked for, go ahead and get our colors set up.
00435     nsIPresShell *presShell = aData->mPresContext->GetPresShell();
00436     if (presShell) {
00437       nsIDocument *doc = presShell->GetDocument();
00438       if (doc) {
00439         nsHTMLStyleSheet* styleSheet = doc->GetAttributeStyleSheet();
00440         if (styleSheet) {
00441           const nsAttrValue* value;
00442           nscolor color;
00443           value = aAttributes->GetAttr(nsHTMLAtoms::link);
00444           if (value && value->GetColorValue(color)) {
00445             styleSheet->SetLinkColor(color);
00446           }
00447 
00448           value = aAttributes->GetAttr(nsHTMLAtoms::alink);
00449           if (value && value->GetColorValue(color)) {
00450             styleSheet->SetActiveLinkColor(color);
00451           }
00452 
00453           value = aAttributes->GetAttr(nsHTMLAtoms::vlink);
00454           if (value && value->GetColorValue(color)) {
00455             styleSheet->SetVisitedLinkColor(color);
00456           }
00457         }
00458       }
00459     }
00460   }
00461 
00462   if (aData->mSID == eStyleStruct_Color) {
00463     if (aData->mColorData->mColor.GetUnit() == eCSSUnit_Null) {
00464       // color: color
00465       nscolor color;
00466       const nsAttrValue* value = aAttributes->GetAttr(nsHTMLAtoms::text);
00467       if (value && value->GetColorValue(color))
00468         aData->mColorData->mColor.SetColorValue(color);
00469     }
00470   }
00471 
00472   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
00473   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
00474 }
00475 
00476 nsMapRuleToAttributesFunc
00477 nsHTMLBodyElement::GetAttributeMappingFunction() const
00478 {
00479   return &MapAttributesIntoRule;
00480 }
00481 
00482 NS_IMETHODIMP
00483 nsHTMLBodyElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
00484 {
00485   nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
00486 
00487   if (!mContentStyleRule && IsInDoc()) {
00488     // XXXbz should this use GetOwnerDoc() or GetCurrentDoc()?
00489     // sXBL/XBL2 issue!
00490     mContentStyleRule = new BodyRule(this);
00491     NS_IF_ADDREF(mContentStyleRule);
00492   }
00493   if (aRuleWalker && mContentStyleRule) {
00494     aRuleWalker->Forward(mContentStyleRule);
00495   }
00496   return NS_OK;
00497 }
00498 
00499 NS_IMETHODIMP_(PRBool)
00500 nsHTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
00501 {
00502   static const MappedAttributeEntry attributes[] = {
00503     { &nsHTMLAtoms::link },
00504     { &nsHTMLAtoms::vlink },
00505     { &nsHTMLAtoms::alink },
00506     { &nsHTMLAtoms::text },
00507     // These aren't mapped through attribute mapping, but they are
00508     // mapped through a style rule, so it is attribute dependent style.
00509     // XXXldb But we don't actually replace the body rule when we have
00510     // dynamic changes...
00511     { &nsHTMLAtoms::marginwidth },
00512     { &nsHTMLAtoms::marginheight },
00513     { nsnull },
00514   };
00515 
00516   static const MappedAttributeEntry* const map[] = {
00517     attributes,
00518     sCommonAttributeMap,
00519     sBackgroundAttributeMap,
00520   };
00521 
00522   return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
00523 }
00524 
00525 already_AddRefed<nsIEditor>
00526 nsHTMLBodyElement::GetAssociatedEditor()
00527 {
00528   nsIEditor* editor = nsnull;
00529   if (NS_SUCCEEDED(GetEditorInternal(&editor)) && editor) {
00530     return editor;
00531   }
00532 
00533   // Make sure this is the actual body of the document
00534   if (!IsCurrentBodyElement()) {
00535     return nsnull;
00536   }
00537 
00538   // For designmode, try to get document's editor
00539   nsPresContext* presContext = GetPresContext();
00540   if (!presContext) {
00541     return nsnull;
00542   }
00543 
00544   nsCOMPtr<nsISupports> container = presContext->GetContainer();
00545   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(container);
00546   if (!editorDocShell) {
00547     return nsnull;
00548   }
00549 
00550   editorDocShell->GetEditor(&editor);
00551   return editor;
00552 }