Back to index

lightning-sunbird  0.9+nobinonly
nsPresContext.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.org 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  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsCOMPtr.h"
00038 #include "nsPresContext.h"
00039 #include "nsIPresShell.h"
00040 #include "nsILinkHandler.h"
00041 #include "nsIDocShellTreeItem.h"
00042 #include "nsIDocShell.h"
00043 #include "nsIContentViewer.h"
00044 #include "nsIDocumentViewer.h"
00045 #include "nsPIDOMWindow.h"
00046 #include "nsIFocusController.h"
00047 #include "nsStyleSet.h"
00048 #include "nsImageLoader.h"
00049 #include "nsIContent.h"
00050 #include "nsIFrame.h"
00051 #include "nsIRenderingContext.h"
00052 #include "nsIURL.h"
00053 #include "nsIDocument.h"
00054 #include "nsStyleContext.h"
00055 #include "nsLayoutAtoms.h"
00056 #include "nsILookAndFeel.h"
00057 #include "nsWidgetsCID.h"
00058 #include "nsIComponentManager.h"
00059 #include "nsIURIContentListener.h"
00060 #include "nsIInterfaceRequestor.h"
00061 #include "nsIInterfaceRequestorUtils.h"
00062 #include "nsIServiceManager.h"
00063 #include "nsIDOMElement.h"
00064 #include "nsContentPolicyUtils.h"
00065 #include "nsIScriptGlobalObject.h"
00066 #include "nsIDOMWindow.h"
00067 #include "nsXPIDLString.h"
00068 #include "nsIWeakReferenceUtils.h"
00069 #include "nsCSSRendering.h"
00070 #include "prprf.h"
00071 #include "nsContentPolicyUtils.h"
00072 #include "nsIScriptGlobalObject.h"
00073 #include "nsIDOMDocument.h"
00074 #include "nsAutoPtr.h"
00075 #include "nsEventStateManager.h"
00076 #ifdef IBMBIDI
00077 #include "nsBidiPresUtils.h"
00078 #endif // IBMBIDI
00079 
00080 #include "nsContentUtils.h"
00081 
00082 // Needed for Start/Stop of Image Animation
00083 #include "imgIContainer.h"
00084 #include "nsIImageLoadingContent.h"
00085 
00086 //needed for resetting of image service color
00087 #include "nsLayoutCID.h"
00088 #include "nsISelectionImageService.h"
00089 
00090 static nscolor
00091 MakeColorPref(const char *colstr)
00092 {
00093   PRUint32 red, green, blue;
00094   nscolor colorref;
00095 
00096   // 4.x stored RGB color values as a string rather than as an int,
00097   // thus we need to do this conversion
00098   PR_sscanf(colstr, "#%02x%02x%02x", &red, &green, &blue);
00099   colorref = NS_RGB(red, green, blue);
00100   return colorref;
00101 }
00102 
00103 int PR_CALLBACK
00104 nsPresContext::PrefChangedCallback(const char* aPrefName, void* instance_data)
00105 {
00106   nsPresContext*  presContext = (nsPresContext*)instance_data;
00107 
00108   NS_ASSERTION(nsnull != presContext, "bad instance data");
00109   if (nsnull != presContext) {
00110     presContext->PreferenceChanged(aPrefName);
00111   }
00112   return 0;  // PREF_OK
00113 }
00114 
00115 
00116 void
00117 nsPresContext::PrefChangedUpdateTimerCallback(nsITimer *aTimer, void *aClosure)
00118 {
00119   nsPresContext*  presContext = (nsPresContext*)aClosure;
00120   NS_ASSERTION(presContext != nsnull, "bad instance data");
00121   if (presContext)
00122     presContext->UpdateAfterPreferencesChanged();
00123 }
00124 
00125 #ifdef IBMBIDI
00126 static PRBool
00127 IsVisualCharset(const nsCString& aCharset)
00128 {
00129   if (aCharset.LowerCaseEqualsLiteral("ibm864")             // Arabic//ahmed
00130       || aCharset.LowerCaseEqualsLiteral("ibm862")          // Hebrew
00131       || aCharset.LowerCaseEqualsLiteral("iso-8859-8") ) {  // Hebrew
00132     return PR_TRUE; // visual text type
00133   }
00134   else {
00135     return PR_FALSE; // logical text type
00136   }
00137 }
00138 #endif // IBMBIDI
00139 
00140 
00141 PR_STATIC_CALLBACK(PRBool) destroy_loads(nsHashKey *aKey, void *aData, void* closure)
00142 {
00143   nsISupports *sup = NS_REINTERPRET_CAST(nsISupports*, aData);
00144   nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, sup);
00145   loader->Destroy();
00146   return PR_TRUE;
00147 }
00148 
00149 static NS_DEFINE_CID(kLookAndFeelCID,  NS_LOOKANDFEEL_CID);
00150 #include "nsContentCID.h"
00151 static NS_DEFINE_CID(kSelectionImageService, NS_SELECTIONIMAGESERVICE_CID);
00152 
00153   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
00154   // bother initializing members to 0.
00155 
00156 nsPresContext::nsPresContext(nsPresContextType aType)
00157   : mType(aType),
00158     mTextZoom(1.0),
00159     mViewportStyleOverflow(NS_STYLE_OVERFLOW_AUTO, NS_STYLE_OVERFLOW_AUTO),
00160     mCompatibilityMode(eCompatibility_FullStandards),
00161     mImageAnimationModePref(imgIContainer::kNormalAnimMode),
00162     mDefaultVariableFont("serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00163                          NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(12)),
00164     mDefaultFixedFont("monospace", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00165                       NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(10)),
00166     mDefaultSerifFont("serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00167                       NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(12)),
00168     mDefaultSansSerifFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00169                           NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(12)),
00170     mDefaultMonospaceFont("monospace", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00171                           NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(10)),
00172     mDefaultCursiveFont("cursive", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00173                         NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(12)),
00174     mDefaultFantasyFont("fantasy", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00175                         NS_FONT_WEIGHT_NORMAL, 0, NSIntPointsToTwips(12))
00176 {
00177   // NOTE! nsPresContext::operator new() zeroes out all members, so don't
00178   // bother initializing members to 0.
00179 
00180   mDoScaledTwips = PR_TRUE;
00181 
00182   SetBackgroundImageDraw(PR_TRUE);        // always draw the background
00183   SetBackgroundColorDraw(PR_TRUE);
00184 
00185   mBackgroundColor = NS_RGB(0xFF, 0xFF, 0xFF);
00186   
00187   mUseDocumentColors = PR_TRUE;
00188   mUseDocumentFonts = PR_TRUE;
00189 
00190   // the minimum font-size is unconstrained by default
00191 
00192   mLinkColor = NS_RGB(0x00, 0x00, 0xEE);
00193   mActiveLinkColor = NS_RGB(0xEE, 0x00, 0x00);
00194   mVisitedLinkColor = NS_RGB(0x55, 0x1A, 0x8B);
00195   mUnderlineLinks = PR_TRUE;
00196 
00197   mFocusTextColor = mDefaultColor;
00198   mFocusBackgroundColor = mBackgroundColor;
00199   mFocusRingWidth = 1;
00200 
00201   mLanguageSpecificTransformType = eLanguageSpecificTransformType_Unknown;
00202   if (aType == eContext_Galley) {
00203     mMedium = nsLayoutAtoms::screen;
00204     mImageAnimationMode = imgIContainer::kNormalAnimMode;
00205   } else {
00206     SetBackgroundImageDraw(PR_FALSE);
00207     SetBackgroundColorDraw(PR_FALSE);
00208     mImageAnimationMode = imgIContainer::kDontAnimMode;
00209     mNeverAnimate = PR_TRUE;
00210     mMedium = nsLayoutAtoms::print;
00211     mPaginated = PR_TRUE;
00212     if (aType == eContext_PrintPreview) {
00213       mCanPaginatedScroll = PR_TRUE;
00214       mPageDim.SetRect(-1, -1, -1, -1);
00215     } else {
00216       mPageDim.SetRect(0, 0, 0, 0);
00217     }
00218   }
00219 }
00220 
00221 nsPresContext::~nsPresContext()
00222 {
00223   mImageLoaders.Enumerate(destroy_loads);
00224 
00225   NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
00226   SetShell(nsnull);
00227 
00228   if (mEventManager) {
00229     mEventManager->SetPresContext(nsnull);   // unclear if this is needed, but can't hurt
00230     NS_RELEASE(mEventManager);
00231   }
00232 
00233   if (mPrefChangedTimer)
00234   {
00235     mPrefChangedTimer->Cancel();
00236     mPrefChangedTimer = nsnull;
00237   }
00238 
00239   // Unregister preference callbacks
00240   nsContentUtils::UnregisterPrefCallback("font.",
00241                                          nsPresContext::PrefChangedCallback,
00242                                          this);
00243   nsContentUtils::UnregisterPrefCallback("browser.display.",
00244                                          nsPresContext::PrefChangedCallback,
00245                                          this);
00246   nsContentUtils::UnregisterPrefCallback("browser.underline_anchors",
00247                                          nsPresContext::PrefChangedCallback,
00248                                          this);
00249   nsContentUtils::UnregisterPrefCallback("browser.anchor_color",
00250                                          nsPresContext::PrefChangedCallback,
00251                                          this);
00252   nsContentUtils::UnregisterPrefCallback("browser.active_color",
00253                                          nsPresContext::PrefChangedCallback,
00254                                          this);
00255   nsContentUtils::UnregisterPrefCallback("browser.visited_color",
00256                                          nsPresContext::PrefChangedCallback,
00257                                          this);
00258   nsContentUtils::UnregisterPrefCallback("image.animation_mode",
00259                                          nsPresContext::PrefChangedCallback,
00260                                          this);
00261 #ifdef IBMBIDI
00262   nsContentUtils::UnregisterPrefCallback("bidi.", PrefChangedCallback, this);
00263 
00264   delete mBidiUtils;
00265 #endif // IBMBIDI
00266 
00267   NS_IF_RELEASE(mDeviceContext);
00268   NS_IF_RELEASE(mLookAndFeel);
00269   NS_IF_RELEASE(mLangGroup);
00270 }
00271 
00272 NS_IMPL_ISUPPORTS2(nsPresContext, nsPresContext, nsIObserver)
00273 
00274 #define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
00275  _pref.Assign(_s0); \
00276  _pref.Append(_s1);
00277 
00278 static const char* const kGenericFont[] = {
00279   ".variable.",
00280   ".fixed.",
00281   ".serif.", 
00282   ".sans-serif.", 
00283   ".monospace.",
00284   ".cursive.",
00285   ".fantasy."
00286 };
00287 
00288 void
00289 nsPresContext::GetFontPreferences()
00290 {
00291   if (!mLangGroup)
00292     return;
00293 
00294   /* Fetch the font prefs to be used -- see bug 61883 for details.
00295      Not all prefs are needed upfront. Some are fallback prefs intended
00296      for the GFX font sub-system...
00297 
00298   1) unit : assumed to be the same for all language groups -------------
00299   font.size.unit = px | pt    XXX could be folded in the size... bug 90440
00300 
00301   2) attributes for generic fonts --------------------------------------
00302   font.default = serif | sans-serif - fallback generic font
00303   font.name.[generic].[langGroup] = current user' selected font on the pref dialog
00304   font.name-list.[generic].[langGroup] = fontname1, fontname2, ... [factory pre-built list]
00305   font.size.[generic].[langGroup] = integer - settable by the user
00306   font.size-adjust.[generic].[langGroup] = "float" - settable by the user
00307   font.minimum-size.[langGroup] = integer - settable by the user
00308   */
00309 
00310   float p2t = ScaledPixelsToTwips();
00311   mDefaultVariableFont.size = NSFloatPixelsToTwips((float)16, p2t);
00312   mDefaultFixedFont.size = NSFloatPixelsToTwips((float)13, p2t);
00313 
00314   const char *langGroup;
00315   mLangGroup->GetUTF8String(&langGroup);
00316 
00317   nsCAutoString pref;
00318 
00319   // get the current applicable font-size unit
00320   enum {eUnit_unknown = -1, eUnit_px, eUnit_pt};
00321   PRInt32 unit = eUnit_px;
00322 
00323   nsAdoptingCString cvalue =
00324     nsContentUtils::GetCharPref("font.size.unit");
00325 
00326   if (!cvalue.IsEmpty()) {
00327     if (cvalue.Equals("px")) {
00328       unit = eUnit_px;
00329     }
00330     else if (cvalue.Equals("pt")) {
00331       unit = eUnit_pt;
00332     }
00333     else {
00334       NS_WARNING("unexpected font-size unit -- expected: 'px' or 'pt'");
00335       unit = eUnit_unknown;
00336     }
00337   }
00338 
00339   // get font.minimum-size.[langGroup]
00340 
00341   pref.Assign("font.minimum-size.");
00342   pref.Append(langGroup);
00343 
00344   PRInt32 size = nsContentUtils::GetIntPref(pref.get());
00345   if (size > 0) {
00346     if (unit == eUnit_px) {
00347       mMinimumFontSize = NSFloatPixelsToTwips((float)size, p2t);
00348     }
00349     else if (unit == eUnit_pt) {
00350       mMinimumFontSize = NSIntPointsToTwips(size);
00351     }
00352   }
00353 
00354   // get attributes specific to each generic font
00355   nsCAutoString generic_dot_langGroup;
00356   for (PRInt32 eType = eDefaultFont_Variable; eType < eDefaultFont_COUNT; ++eType) {
00357     generic_dot_langGroup.Assign(kGenericFont[eType]);
00358     generic_dot_langGroup.Append(langGroup);
00359 
00360     nsFont* font;
00361     switch (eType) {
00362       case eDefaultFont_Variable:  font = &mDefaultVariableFont;  break;
00363       case eDefaultFont_Fixed:     font = &mDefaultFixedFont;     break;
00364       case eDefaultFont_Serif:     font = &mDefaultSerifFont;     break;
00365       case eDefaultFont_SansSerif: font = &mDefaultSansSerifFont; break;
00366       case eDefaultFont_Monospace: font = &mDefaultMonospaceFont; break;
00367       case eDefaultFont_Cursive:   font = &mDefaultCursiveFont;   break;
00368       case eDefaultFont_Fantasy:   font = &mDefaultFantasyFont;   break;
00369     }
00370 
00371     // set the default variable font (the other fonts are seen as 'generic' fonts
00372     // in GFX and will be queried there when hunting for alternative fonts)
00373     if (eType == eDefaultFont_Variable) {
00374       MAKE_FONT_PREF_KEY(pref, "font.name", generic_dot_langGroup);
00375 
00376       nsAdoptingString value =
00377         nsContentUtils::GetStringPref(pref.get());
00378       if (!value.IsEmpty()) {
00379         font->name.Assign(value);
00380       }
00381       else {
00382         MAKE_FONT_PREF_KEY(pref, "font.default.", langGroup);
00383         value = nsContentUtils::GetStringPref(pref.get());
00384         if (!value.IsEmpty()) {
00385           mDefaultVariableFont.name.Assign(value);
00386         }
00387       } 
00388     }
00389     else {
00390       if (eType == eDefaultFont_Monospace) {
00391         // This takes care of the confusion whereby people often expect "monospace" 
00392         // to have the same default font-size as "-moz-fixed" (this tentative
00393         // size may be overwritten with the specific value for "monospace" when
00394         // "font.size.monospace.[langGroup]" is read -- see below)
00395         font->size = mDefaultFixedFont.size;
00396       }
00397       else if (eType != eDefaultFont_Fixed) {
00398         // all the other generic fonts are initialized with the size of the
00399         // variable font, but their specific size can supersede later -- see below
00400         font->size = mDefaultVariableFont.size;
00401       }
00402     }
00403 
00404     // Bug 84398: for spec purists, a different font-size only applies to the
00405     // .variable. and .fixed. fonts and the other fonts should get |font-size-adjust|.
00406     // The problem is that only GfxWin has the support for |font-size-adjust|. So for
00407     // parity, we enable the ability to set a different font-size on all platforms.
00408 
00409     // get font.size.[generic].[langGroup]
00410     // size=0 means 'Auto', i.e., generic fonts retain the size of the variable font
00411     MAKE_FONT_PREF_KEY(pref, "font.size", generic_dot_langGroup);
00412     size = nsContentUtils::GetIntPref(pref.get());
00413     if (size > 0) {
00414       if (unit == eUnit_px) {
00415         font->size = NSFloatPixelsToTwips((float)size, p2t);
00416       }
00417       else if (unit == eUnit_pt) {
00418         font->size = NSIntPointsToTwips(size);
00419       }
00420     }
00421 
00422     // get font.size-adjust.[generic].[langGroup]
00423     // XXX only applicable on GFX ports that handle |font-size-adjust|
00424     MAKE_FONT_PREF_KEY(pref, "font.size-adjust", generic_dot_langGroup);
00425     cvalue = nsContentUtils::GetCharPref(pref.get());
00426     if (!cvalue.IsEmpty()) {
00427       font->sizeAdjust = (float)atof(cvalue.get());
00428     }
00429 
00430 #ifdef DEBUG_rbs
00431     printf("%s Family-list:%s size:%d sizeAdjust:%.2f\n",
00432            generic_dot_langGroup.get(),
00433            NS_ConvertUCS2toUTF8(font->name).get(), font->size,
00434            font->sizeAdjust);
00435 #endif
00436   }
00437 }
00438 
00439 void
00440 nsPresContext::GetDocumentColorPreferences()
00441 {
00442   PRInt32 useAccessibilityTheme = 0;
00443   PRBool usePrefColors = PR_TRUE;
00444   nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
00445   if (docShell) {
00446     PRInt32 docShellType;
00447     docShell->GetItemType(&docShellType);
00448     if (nsIDocShellTreeItem::typeChrome == docShellType) {
00449       usePrefColors = PR_FALSE;
00450     }
00451     else {
00452       mLookAndFeel->GetMetric(nsILookAndFeel::eMetric_UseAccessibilityTheme, useAccessibilityTheme);
00453       usePrefColors = !useAccessibilityTheme;
00454     }
00455 
00456   }
00457   if (usePrefColors) {
00458     usePrefColors =
00459       !nsContentUtils::GetBoolPref("browser.display.use_system_colors",
00460                                    PR_FALSE);
00461   }
00462 
00463   if (usePrefColors) {
00464     nsAdoptingCString colorStr =
00465       nsContentUtils::GetCharPref("browser.display.foreground_color");
00466 
00467     if (!colorStr.IsEmpty()) {
00468       mDefaultColor = MakeColorPref(colorStr);
00469     }
00470 
00471     colorStr =
00472       nsContentUtils::GetCharPref("browser.display.background_color");
00473 
00474     if (!colorStr.IsEmpty()) {
00475       mBackgroundColor = MakeColorPref(colorStr);
00476     }
00477   }
00478   else {
00479     mDefaultColor = NS_RGB(0x00, 0x00, 0x00);
00480     mBackgroundColor = NS_RGB(0xFF, 0xFF, 0xFF);
00481     mLookAndFeel->GetColor(nsILookAndFeel::eColor_WindowForeground,
00482                            mDefaultColor);
00483     mLookAndFeel->GetColor(nsILookAndFeel::eColor_WindowBackground,
00484                            mBackgroundColor);
00485   }
00486 
00487   mUseDocumentColors = !useAccessibilityTheme &&
00488     nsContentUtils::GetBoolPref("browser.display.use_document_colors",
00489                                 mUseDocumentColors);
00490 }
00491 
00492 void
00493 nsPresContext::GetUserPreferences()
00494 {
00495   mFontScaler =
00496     nsContentUtils::GetIntPref("browser.display.base_font_scaler",
00497                                mFontScaler);
00498 
00499   // * document colors
00500   GetDocumentColorPreferences();
00501 
00502   // * link colors
00503   mUnderlineLinks =
00504     nsContentUtils::GetBoolPref("browser.underline_anchors", mUnderlineLinks);
00505 
00506   nsAdoptingCString colorStr =
00507     nsContentUtils::GetCharPref("browser.anchor_color");
00508 
00509   if (!colorStr.IsEmpty()) {
00510     mLinkColor = MakeColorPref(colorStr);
00511   }
00512 
00513   colorStr =
00514     nsContentUtils::GetCharPref("browser.active_color");
00515 
00516   if (!colorStr.IsEmpty()) {
00517     mActiveLinkColor = MakeColorPref(colorStr);
00518   }
00519 
00520   colorStr = nsContentUtils::GetCharPref("browser.visited_color");
00521 
00522   if (!colorStr.IsEmpty()) {
00523     mVisitedLinkColor = MakeColorPref(colorStr);
00524   }
00525 
00526   mUseFocusColors =
00527     nsContentUtils::GetBoolPref("browser.display.use_focus_colors",
00528                                 mUseFocusColors);
00529 
00530   mFocusTextColor = mDefaultColor;
00531   mFocusBackgroundColor = mBackgroundColor;
00532 
00533   colorStr = nsContentUtils::GetCharPref("browser.display.focus_text_color");
00534 
00535   if (!colorStr.IsEmpty()) {
00536     mFocusTextColor = MakeColorPref(colorStr);
00537   }
00538 
00539   colorStr =
00540     nsContentUtils::GetCharPref("browser.display.focus_background_color");
00541 
00542   if (!colorStr.IsEmpty()) {
00543     mFocusBackgroundColor = MakeColorPref(colorStr);
00544   }
00545 
00546   mFocusRingWidth =
00547     nsContentUtils::GetIntPref("browser.display.focus_ring_width",
00548                                mFocusRingWidth);
00549 
00550   mFocusRingOnAnything =
00551     nsContentUtils::GetBoolPref("browser.display.focus_ring_on_anything",
00552                                 mFocusRingOnAnything);
00553 
00554   // * use fonts?
00555   mUseDocumentFonts =
00556     nsContentUtils::GetIntPref("browser.display.use_document_fonts") != 0;
00557 
00558   // * replace backslashes with Yen signs? (bug 245770)
00559   mEnableJapaneseTransform =
00560     nsContentUtils::GetBoolPref("layout.enable_japanese_specific_transform");
00561 
00562   GetFontPreferences();
00563 
00564   // * image animation
00565   const nsAdoptingCString& animatePref =
00566     nsContentUtils::GetCharPref("image.animation_mode");
00567   if (animatePref.Equals("normal"))
00568     mImageAnimationModePref = imgIContainer::kNormalAnimMode;
00569   else if (animatePref.Equals("none"))
00570     mImageAnimationModePref = imgIContainer::kDontAnimMode;
00571   else if (animatePref.Equals("once"))
00572     mImageAnimationModePref = imgIContainer::kLoopOnceAnimMode;
00573 
00574 #ifdef IBMBIDI
00575   PRUint32 bidiOptions = mBidi;
00576 
00577   PRInt32 prefInt =
00578     nsContentUtils::GetIntPref("bidi.direction",
00579                                GET_BIDI_OPTION_DIRECTION(bidiOptions));
00580   SET_BIDI_OPTION_DIRECTION(bidiOptions, prefInt);
00581 
00582   prefInt =
00583     nsContentUtils::GetIntPref("bidi.texttype",
00584                                GET_BIDI_OPTION_TEXTTYPE(bidiOptions));
00585   SET_BIDI_OPTION_TEXTTYPE(bidiOptions, prefInt);
00586 
00587   prefInt =
00588     nsContentUtils::GetIntPref("bidi.controlstextmode",
00589                                GET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions));
00590   SET_BIDI_OPTION_CONTROLSTEXTMODE(bidiOptions, prefInt);
00591 
00592   prefInt =
00593     nsContentUtils::GetIntPref("bidi.numeral",
00594                                GET_BIDI_OPTION_NUMERAL(bidiOptions));
00595   SET_BIDI_OPTION_NUMERAL(bidiOptions, prefInt);
00596 
00597   prefInt =
00598     nsContentUtils::GetIntPref("bidi.support",
00599                                GET_BIDI_OPTION_SUPPORT(bidiOptions));
00600   SET_BIDI_OPTION_SUPPORT(bidiOptions, prefInt);
00601 
00602   prefInt =
00603     nsContentUtils::GetIntPref("bidi.characterset",
00604                                GET_BIDI_OPTION_CHARACTERSET(bidiOptions));
00605   SET_BIDI_OPTION_CHARACTERSET(bidiOptions, prefInt);
00606 
00607   // We don't need to force reflow: either we are initializing a new
00608   // prescontext or we are being called from UpdateAfterPreferencesChanged()
00609   // which triggers a reflow anyway.
00610   SetBidi(bidiOptions, PR_FALSE);
00611 #endif
00612 }
00613 
00614 void
00615 nsPresContext::ClearStyleDataAndReflow()
00616 {
00617   if (mShell) {
00618     // Clear out all our style data.
00619     mShell->StyleSet()->ClearStyleData(this);
00620 
00621     // Force a reflow of the root frame
00622     // XXX We really should only do a reflow if a preference that affects
00623     // formatting changed, e.g., a font change. If it's just a color change
00624     // then we only need to repaint...
00625     mShell->StyleChangeReflow();
00626   }
00627 }
00628 
00629 void
00630 nsPresContext::PreferenceChanged(const char* aPrefName)
00631 {
00632   // we use a zero-delay timer to coalesce multiple pref updates
00633   if (!mPrefChangedTimer)
00634   {
00635     mPrefChangedTimer = do_CreateInstance("@mozilla.org/timer;1");
00636     if (!mPrefChangedTimer)
00637       return;
00638     mPrefChangedTimer->InitWithFuncCallback(nsPresContext::PrefChangedUpdateTimerCallback, (void*)this, 0, nsITimer::TYPE_ONE_SHOT);
00639   }
00640 }
00641 
00642 void
00643 nsPresContext::UpdateAfterPreferencesChanged()
00644 {
00645   mPrefChangedTimer = nsnull;
00646 
00647   nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
00648   if (docShell) {
00649     PRInt32 docShellType;
00650     docShell->GetItemType(&docShellType);
00651     if (nsIDocShellTreeItem::typeChrome == docShellType)
00652       return;
00653   }
00654 
00655   // Initialize our state from the user preferences
00656   GetUserPreferences();
00657 
00658   // update the presShell: tell it to set the preference style rules up
00659   if (mShell) {
00660     mShell->SetPreferenceStyleRules(PR_TRUE);
00661   }
00662 
00663   mDeviceContext->FlushFontCache();
00664   ClearStyleDataAndReflow();
00665 }
00666 
00667 nsresult
00668 nsPresContext::Init(nsIDeviceContext* aDeviceContext)
00669 {
00670   NS_ASSERTION(!(mInitialized == PR_TRUE), "attempt to reinit pres context");
00671   NS_ENSURE_ARG(aDeviceContext);
00672 
00673   mDeviceContext = aDeviceContext;
00674   NS_ADDREF(mDeviceContext);
00675 
00676   // Get the look and feel service here; default colors will be initialized
00677   // from calling GetUserPreferences() below.
00678   nsresult rv = CallGetService(kLookAndFeelCID, &mLookAndFeel);
00679   if (NS_FAILED(rv)) {
00680     NS_ERROR("LookAndFeel service must be implemented for this toolkit");
00681     return rv;
00682   }
00683 
00684   mEventManager = new nsEventStateManager();
00685   if (!mEventManager)
00686     return NS_ERROR_OUT_OF_MEMORY;
00687 
00688   NS_ADDREF(mEventManager);
00689 
00690   mLangService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
00691 
00692   // Register callbacks so we're notified when the preferences change
00693   nsContentUtils::RegisterPrefCallback("font.",
00694                                        nsPresContext::PrefChangedCallback,
00695                                        this);
00696   nsContentUtils::RegisterPrefCallback("browser.display.",
00697                                        nsPresContext::PrefChangedCallback,
00698                                        this);
00699   nsContentUtils::RegisterPrefCallback("browser.underline_anchors",
00700                                        nsPresContext::PrefChangedCallback,
00701                                        this);
00702   nsContentUtils::RegisterPrefCallback("browser.anchor_color",
00703                                        nsPresContext::PrefChangedCallback,
00704                                        this);
00705   nsContentUtils::RegisterPrefCallback("browser.active_color",
00706                                        nsPresContext::PrefChangedCallback,
00707                                        this);
00708   nsContentUtils::RegisterPrefCallback("browser.visited_color",
00709                                        nsPresContext::PrefChangedCallback,
00710                                        this);
00711   nsContentUtils::RegisterPrefCallback("image.animation_mode",
00712                                        nsPresContext::PrefChangedCallback,
00713                                        this);
00714 #ifdef IBMBIDI
00715   nsContentUtils::RegisterPrefCallback("bidi.", PrefChangedCallback,
00716                                        this);
00717 #endif
00718 
00719   // Initialize our state from the user preferences
00720   GetUserPreferences();
00721 
00722   rv = mEventManager->Init();
00723   NS_ENSURE_SUCCESS(rv, rv);
00724 
00725   mEventManager->SetPresContext(this);
00726 
00727 #ifdef DEBUG
00728   mInitialized = PR_TRUE;
00729 #endif
00730 
00731   float pixelsToTwips = PixelsToTwips();
00732   mBorderWidthTable[NS_STYLE_BORDER_WIDTH_THIN] = NSIntPixelsToTwips(1, pixelsToTwips);
00733   mBorderWidthTable[NS_STYLE_BORDER_WIDTH_MEDIUM] = NSIntPixelsToTwips(3, pixelsToTwips);
00734   mBorderWidthTable[NS_STYLE_BORDER_WIDTH_THICK] = NSIntPixelsToTwips(5, pixelsToTwips);
00735 
00736   return NS_OK;
00737 }
00738 
00739 // Note: We don't hold a reference on the shell; it has a reference to
00740 // us
00741 void
00742 nsPresContext::SetShell(nsIPresShell* aShell)
00743 {
00744   if (mShell) {
00745     // Remove ourselves as the charset observer from the shell's doc, because
00746     // this shell may be going away for good.
00747     nsIDocument *doc = mShell->GetDocument();
00748     if (doc) {
00749       doc->RemoveCharSetObserver(this);
00750     }
00751   }    
00752 
00753   mShell = aShell;
00754 
00755   if (mShell) {
00756     nsIDocument *doc = mShell->GetDocument();
00757     NS_ASSERTION(doc, "expect document here");
00758     if (doc) {
00759       nsIURI *docURI = doc->GetDocumentURI();
00760 
00761       if (mMedium != nsLayoutAtoms::print && docURI) {
00762         PRBool isChrome = PR_FALSE;
00763         PRBool isRes = PR_FALSE;
00764         docURI->SchemeIs("chrome", &isChrome);
00765         docURI->SchemeIs("resource", &isRes);
00766 
00767         if (!isChrome && !isRes)
00768           mImageAnimationMode = mImageAnimationModePref;
00769         else
00770           mImageAnimationMode = imgIContainer::kNormalAnimMode;
00771       }
00772 
00773       if (mLangService) {
00774         doc->AddCharSetObserver(this);
00775         UpdateCharSet(doc->GetDocumentCharacterSet());
00776       }
00777     }
00778   }
00779 }
00780 
00781 void
00782 nsPresContext::UpdateCharSet(const nsAFlatCString& aCharSet)
00783 {
00784   if (mLangService) {
00785     NS_IF_RELEASE(mLangGroup);
00786     mLangGroup = mLangService->LookupCharSet(aCharSet.get()).get();  // addrefs
00787 
00788     if (mLangGroup == nsLayoutAtoms::Japanese && mEnableJapaneseTransform) {
00789       mLanguageSpecificTransformType =
00790         eLanguageSpecificTransformType_Japanese;
00791     }
00792     else {
00793       mLanguageSpecificTransformType =
00794         eLanguageSpecificTransformType_None;
00795     }
00796     // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
00797 #if !defined(XP_BEOS) 
00798     if (mLangGroup == nsLayoutAtoms::Unicode) {
00799       NS_RELEASE(mLangGroup);
00800       NS_IF_ADDREF(mLangGroup = mLangService->GetLocaleLanguageGroup()); 
00801     }
00802 #endif
00803     GetFontPreferences();
00804   }
00805 #ifdef IBMBIDI
00806   //ahmed
00807 
00808   switch (GET_BIDI_OPTION_TEXTTYPE(mBidi)) {
00809 
00810     case IBMBIDI_TEXTTYPE_LOGICAL:
00811       SetVisualMode(PR_FALSE);
00812       break;
00813 
00814     case IBMBIDI_TEXTTYPE_VISUAL:
00815       SetVisualMode(PR_TRUE);
00816       break;
00817 
00818     case IBMBIDI_TEXTTYPE_CHARSET:
00819     default:
00820       SetVisualMode(IsVisualCharset(aCharSet));
00821   }
00822 #endif // IBMBIDI
00823 }
00824 
00825 NS_IMETHODIMP
00826 nsPresContext::Observe(nsISupports* aSubject, 
00827                         const char* aTopic,
00828                         const PRUnichar* aData)
00829 {
00830   if (!nsCRT::strcmp(aTopic, "charset")) {
00831     UpdateCharSet(NS_LossyConvertUCS2toASCII(aData));
00832     mDeviceContext->FlushFontCache();
00833     ClearStyleDataAndReflow();
00834 
00835     return NS_OK;
00836   }
00837 
00838   NS_WARNING("unrecognized topic in nsPresContext::Observe");
00839   return NS_ERROR_FAILURE;
00840 }
00841 
00842 void
00843 nsPresContext::SetCompatibilityMode(nsCompatibility aMode)
00844 {
00845   mCompatibilityMode = aMode;
00846 
00847   if (!mShell)
00848     return;
00849 
00850   // enable/disable the QuirkSheet
00851   mShell->StyleSet()->
00852     EnableQuirkStyleSheet(mCompatibilityMode == eCompatibility_NavQuirks);
00853 }
00854 
00855 // Helper function for setting Anim Mode on image
00856 static void SetImgAnimModeOnImgReq(imgIRequest* aImgReq, PRUint16 aMode)
00857 {
00858   if (aImgReq) {
00859     nsCOMPtr<imgIContainer> imgCon;
00860     aImgReq->GetImage(getter_AddRefs(imgCon));
00861     if (imgCon) {
00862       imgCon->SetAnimationMode(aMode);
00863     }
00864   }
00865 }
00866 
00867  // Enumeration call back for HashTable
00868 PR_STATIC_CALLBACK(PRBool) set_animation_mode(nsHashKey *aKey, void *aData, void* closure)
00869 {
00870   nsISupports *sup = NS_REINTERPRET_CAST(nsISupports*, aData);
00871   nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, sup);
00872   imgIRequest* imgReq = loader->GetRequest();
00873   SetImgAnimModeOnImgReq(imgReq, (PRUint16)NS_PTR_TO_INT32(closure));
00874   return PR_TRUE;
00875 }
00876 
00877 // IMPORTANT: Assumption is that all images for a Presentation 
00878 // have the same Animation Mode (pavlov said this was OK)
00879 //
00880 // Walks content and set the animation mode
00881 // this is a way to turn on/off image animations
00882 void nsPresContext::SetImgAnimations(nsIContent *aParent, PRUint16 aMode)
00883 {
00884   nsCOMPtr<nsIImageLoadingContent> imgContent(do_QueryInterface(aParent));
00885   if (imgContent) {
00886     nsCOMPtr<imgIRequest> imgReq;
00887     imgContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
00888                            getter_AddRefs(imgReq));
00889     SetImgAnimModeOnImgReq(imgReq, aMode);
00890   }
00891   
00892   PRUint32 count = aParent->GetChildCount();
00893   for (PRUint32 i = 0; i < count; ++i) {
00894     SetImgAnimations(aParent->GetChildAt(i), aMode);
00895   }
00896 }
00897 
00898 void
00899 nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode)
00900 {
00901   NS_ASSERTION(aMode == imgIContainer::kNormalAnimMode ||
00902                aMode == imgIContainer::kDontAnimMode ||
00903                aMode == imgIContainer::kLoopOnceAnimMode, "Wrong Animation Mode is being set!");
00904 
00905   // Image animation mode cannot be changed when rendering to a printer.
00906   if (mMedium == nsLayoutAtoms::print)
00907     return;
00908 
00909   // This hash table contains a list of background images
00910   // so iterate over it and set the mode
00911   mImageLoaders.Enumerate(set_animation_mode, NS_INT32_TO_PTR(aMode));
00912 
00913   // Now walk the content tree and set the animation mode 
00914   // on all the images
00915   if (mShell != nsnull) {
00916     nsIDocument *doc = mShell->GetDocument();
00917     if (doc) {
00918       nsIContent *rootContent = doc->GetRootContent();
00919       if (rootContent) {
00920         SetImgAnimations(rootContent, aMode);
00921       }
00922     }
00923   }
00924 
00925   mImageAnimationMode = aMode;
00926 }
00927 
00928 void
00929 nsPresContext::SetImageAnimationModeExternal(PRUint16 aMode)
00930 {
00931   SetImageAnimationModeInternal(aMode);
00932 }
00933 
00934 already_AddRefed<nsIFontMetrics>
00935 nsPresContext::GetMetricsForInternal(const nsFont& aFont)
00936 {
00937   nsIFontMetrics* metrics = nsnull;
00938   mDeviceContext->GetMetricsFor(aFont, mLangGroup, metrics);
00939   return metrics;
00940 }
00941 
00942 already_AddRefed<nsIFontMetrics>
00943 nsPresContext::GetMetricsForExternal(const nsFont& aFont)
00944 {
00945   return GetMetricsForInternal(aFont);
00946 }
00947 
00948 const nsFont*
00949 nsPresContext::GetDefaultFontInternal(PRUint8 aFontID) const
00950 {
00951   const nsFont *font;
00952   switch (aFontID) {
00953     // Special (our default variable width font and fixed width font)
00954     case kPresContext_DefaultVariableFont_ID:
00955       font = &mDefaultVariableFont;
00956       break;
00957     case kPresContext_DefaultFixedFont_ID:
00958       font = &mDefaultFixedFont;
00959       break;
00960     // CSS
00961     case kGenericFont_serif:
00962       font = &mDefaultSerifFont;
00963       break;
00964     case kGenericFont_sans_serif:
00965       font = &mDefaultSansSerifFont;
00966       break;
00967     case kGenericFont_monospace:
00968       font = &mDefaultMonospaceFont;
00969       break;
00970     case kGenericFont_cursive:
00971       font = &mDefaultCursiveFont;
00972       break;
00973     case kGenericFont_fantasy: 
00974       font = &mDefaultFantasyFont;
00975       break;
00976     default:
00977       font = nsnull;
00978       NS_ERROR("invalid arg");
00979       break;
00980   }
00981   return font;
00982 }
00983 
00984 const nsFont*
00985 nsPresContext::GetDefaultFontExternal(PRUint8 aFontID) const
00986 {
00987   return GetDefaultFontInternal(aFontID);
00988 }
00989 
00990 float
00991 nsPresContext::TwipsToPixelsForFonts() const
00992 {
00993   float app2dev;
00994 #ifdef NS_PRINT_PREVIEW
00995   // If an alternative DC is available we want to use
00996   // it to get the scaling factor for fonts. Usually, the AltDC
00997   // is a printing DC so therefore we need to get the printers
00998   // scaling values for calculating the font heights
00999   nsCOMPtr<nsIDeviceContext> altDC;
01000   mDeviceContext->GetAltDevice(getter_AddRefs(altDC));
01001   if (altDC) {
01002     app2dev = altDC->AppUnitsToDevUnits();
01003   } else {
01004     app2dev = mDeviceContext->AppUnitsToDevUnits();
01005   }
01006 #else
01007   app2dev = mDeviceContext->AppUnitsToDevUnits();
01008 #endif
01009   return app2dev;
01010 }
01011 
01012 
01013 
01014 float
01015 nsPresContext::ScaledPixelsToTwips() const
01016 {
01017   float scale;
01018   float p2t;
01019 
01020   p2t = mDeviceContext->DevUnitsToAppUnits();
01021   if (mDoScaledTwips) {
01022     mDeviceContext->GetCanonicalPixelScale(scale);
01023     scale = p2t * scale;
01024   } else {
01025     scale = p2t;
01026   }
01027 
01028   return scale;
01029 }
01030 
01031 void
01032 nsPresContext::SetTextZoomExternal(float aZoom)
01033 {
01034   SetTextZoomInternal(aZoom);
01035 }
01036 
01037 imgIRequest*
01038 nsPresContext::LoadImage(imgIRequest* aImage, nsIFrame* aTargetFrame)
01039 {
01040   // look and see if we have a loader for the target frame.
01041 
01042   nsVoidKey key(aTargetFrame);
01043   nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, mImageLoaders.Get(&key)); // addrefs
01044 
01045   if (!loader) {
01046     loader = new nsImageLoader();
01047     if (!loader)
01048       return nsnull;
01049 
01050     NS_ADDREF(loader); // new
01051 
01052     loader->Init(aTargetFrame, this);
01053     mImageLoaders.Put(&key, loader);
01054   }
01055 
01056   loader->Load(aImage);
01057 
01058   imgIRequest *request = loader->GetRequest();
01059   NS_RELEASE(loader);
01060 
01061   return request;
01062 }
01063 
01064 
01065 void
01066 nsPresContext::StopImagesFor(nsIFrame* aTargetFrame)
01067 {
01068   nsVoidKey key(aTargetFrame);
01069   nsImageLoader *loader = NS_REINTERPRET_CAST(nsImageLoader*, mImageLoaders.Get(&key)); // addrefs
01070 
01071   if (loader) {
01072     loader->Destroy();
01073     NS_RELEASE(loader);
01074 
01075     mImageLoaders.Remove(&key);
01076   }
01077 }
01078 
01079 
01080 void
01081 nsPresContext::SetContainer(nsISupports* aHandler)
01082 {
01083   mContainer = do_GetWeakReference(aHandler);
01084   if (mContainer) {
01085     GetDocumentColorPreferences();
01086   }
01087 }
01088 
01089 already_AddRefed<nsISupports>
01090 nsPresContext::GetContainerInternal()
01091 {
01092   nsISupports *result;
01093   if (mContainer)
01094     CallQueryReferent(mContainer.get(), &result);
01095   else
01096     result = nsnull;
01097 
01098   return result;
01099 }
01100 
01101 already_AddRefed<nsISupports>
01102 nsPresContext::GetContainerExternal()
01103 {
01104   return GetContainerInternal();
01105 }
01106 
01107 #ifdef IBMBIDI
01108 PRBool
01109 nsPresContext::BidiEnabledInternal() const
01110 {
01111   PRBool bidiEnabled = PR_FALSE;
01112   NS_ASSERTION(mShell, "PresShell must be set on PresContext before calling nsPresContext::GetBidiEnabled");
01113   if (mShell) {
01114     nsIDocument *doc = mShell->GetDocument();
01115     NS_ASSERTION(doc, "PresShell has no document in nsPresContext::GetBidiEnabled");
01116     if (doc) {
01117       bidiEnabled = doc->GetBidiEnabled();
01118     }
01119   }
01120   return bidiEnabled;
01121 }
01122 
01123 PRBool
01124 nsPresContext::BidiEnabledExternal() const
01125 {
01126   return BidiEnabledInternal();
01127 }
01128 
01129 void
01130 nsPresContext::SetBidiEnabled(PRBool aBidiEnabled) const
01131 {
01132   if (mShell) {
01133     nsIDocument *doc = mShell->GetDocument();
01134     if (doc) {
01135       doc->SetBidiEnabled(aBidiEnabled);
01136     }
01137   }
01138 }
01139 
01140 nsBidiPresUtils*
01141 nsPresContext::GetBidiUtils()
01142 {
01143   if (!mBidiUtils)
01144     mBidiUtils = new nsBidiPresUtils;
01145 
01146   return mBidiUtils;
01147 }
01148 
01149 void
01150 nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceReflow)
01151 {
01152   // Don't do all this stuff if the options haven't changed
01153   if (aSource == mBidi) {
01154     return;
01155   }
01156 
01157   NS_ASSERTION(!(aForceReflow && (mBidi == 0)), 
01158                "ForceReflow on new prescontext");
01159 
01160   mBidi = aSource;
01161   if (IBMBIDI_TEXTDIRECTION_RTL == GET_BIDI_OPTION_DIRECTION(mBidi)
01162       || IBMBIDI_NUMERAL_HINDI == GET_BIDI_OPTION_NUMERAL(mBidi)) {
01163     SetBidiEnabled(PR_TRUE);
01164   }
01165   if (IBMBIDI_TEXTTYPE_VISUAL == GET_BIDI_OPTION_TEXTTYPE(mBidi)) {
01166     SetVisualMode(PR_TRUE);
01167   }
01168   else if (IBMBIDI_TEXTTYPE_LOGICAL == GET_BIDI_OPTION_TEXTTYPE(mBidi)) {
01169     SetVisualMode(PR_FALSE);
01170   }
01171   else {
01172     if (mShell) {
01173       nsIDocument* doc = mShell->GetDocument();
01174       if (doc) {
01175         SetVisualMode(IsVisualCharset(doc->GetDocumentCharacterSet()));
01176       }
01177     }
01178   }
01179   if (aForceReflow) {
01180     ClearStyleDataAndReflow();
01181   }
01182 }
01183 #endif //IBMBIDI
01184 
01185 nsITheme*
01186 nsPresContext::GetTheme()
01187 {
01188   if (!mNoTheme && !mTheme) {
01189     mTheme = do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
01190     if (!mTheme)
01191       mNoTheme = PR_TRUE;
01192   }
01193 
01194   return mTheme;
01195 }
01196 
01197 void
01198 nsPresContext::ThemeChanged()
01199 {
01200   // Tell the theme that it changed, so it can flush any handles to stale theme
01201   // data.
01202   if (mTheme)
01203     mTheme->ThemeChanged();
01204 
01205   // Clear all cached nsILookAndFeel colors.
01206   if (mLookAndFeel)
01207     mLookAndFeel->LookAndFeelChanged();
01208 
01209   // We have to clear style data because the assumption of style rule
01210   // immutability has been violated since any style rule that uses
01211   // system colors or fonts (and probably -moz-appearance as well) has
01212   // changed.
01213   nsPresContext::ClearStyleDataAndReflow();
01214 }
01215 
01216 void
01217 nsPresContext::SysColorChanged()
01218 {
01219   if (mLookAndFeel) {
01220      // Don't use the cached values for the system colors
01221     mLookAndFeel->LookAndFeelChanged();
01222   }
01223    
01224   // Reset default background and foreground colors for the document since
01225   // they may be using system colors
01226   GetDocumentColorPreferences();
01227 
01228   // Clear out all of the style data since it may contain RGB values
01229   // which originated from system colors.
01230   nsCOMPtr<nsISelectionImageService> imageService;
01231   nsresult result;
01232   imageService = do_GetService(kSelectionImageService, &result);
01233   if (NS_SUCCEEDED(result) && imageService)
01234   {
01235     imageService->Reset();
01236   }
01237 
01238   // We need to do a full reflow (and view update) here. Clearing the style
01239   // data without reflowing/updating views will lead to incorrect change hints
01240   // later, because when generating change hints, any style structs which have
01241   // been cleared and not reread are assumed to not be used at all.
01242   ClearStyleDataAndReflow();
01243 }
01244 
01245 void
01246 nsPresContext::GetPageDim(nsRect* aActualRect, nsRect* aAdjRect)
01247 {
01248   if (mMedium == nsLayoutAtoms::print) {
01249     if (aActualRect) {
01250       PRInt32 width, height;
01251       nsresult rv = mDeviceContext->GetDeviceSurfaceDimensions(width, height);
01252       if (NS_SUCCEEDED(rv))
01253         aActualRect->SetRect(0, 0, width, height);
01254     }
01255     if (aAdjRect)
01256       *aAdjRect = mPageDim;
01257   } else {
01258     if (aActualRect)
01259       aActualRect->SetRect(0, 0, 0, 0);
01260     if (aAdjRect)
01261       aAdjRect->SetRect(0, 0, 0, 0);
01262   }
01263 }
01264 
01265 void
01266 nsPresContext::SetPageDim(const nsRect& aPageDim)
01267 {
01268   if (mMedium == nsLayoutAtoms::print)
01269     mPageDim = aPageDim;
01270 }
01271 
01272 void
01273 nsPresContext::SetPaginatedScrolling(PRBool aPaginated)
01274 {
01275   if (mType == eContext_PrintPreview)
01276     mCanPaginatedScroll = aPaginated;
01277 }
01278 
01279 void
01280 nsPresContext::SetPrintSettings(nsIPrintSettings *aPrintSettings)
01281 {
01282   if (mMedium == nsLayoutAtoms::print)
01283     mPrintSettings = aPrintSettings;
01284 }
01285 
01286 PRBool
01287 nsPresContext::EnsureVisible(PRBool aUnsuppressFocus)
01288 {
01289   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
01290   if (docShell) {
01291     nsCOMPtr<nsIContentViewer> cv;
01292     docShell->GetContentViewer(getter_AddRefs(cv));
01293     // Make sure this is the content viewer we belong with
01294     nsCOMPtr<nsIDocumentViewer> docV(do_QueryInterface(cv));
01295     if (docV) {
01296       nsCOMPtr<nsPresContext> currentPresContext;
01297       docV->GetPresContext(getter_AddRefs(currentPresContext));
01298       if (currentPresContext == this) {
01299         // OK, this is us.  We want to call Show() on the content viewer.  But
01300         // first, we need to suppress focus changes; otherwise the focus will
01301         // get sent to the wrong place (toplevel window).
01302         nsCOMPtr<nsPIDOMWindow> privWindow = do_GetInterface(docShell);
01303         // XXXbz privWindow should never really be null!
01304         nsIFocusController* fc =
01305           privWindow ? privWindow->GetRootFocusController() : nsnull;
01306         if (fc) {
01307           fc->SetSuppressFocus(PR_TRUE,
01308                                "nsPresContext::EnsureVisible Suppression");
01309         }
01310         cv->Show();
01311         if (fc && aUnsuppressFocus) {
01312           fc->SetSuppressFocus(PR_FALSE,
01313                                "nsPresContext::EnsureVisible Suppression");
01314         }
01315         return PR_TRUE;
01316       }
01317     }
01318   }
01319   return PR_FALSE;
01320 }
01321 
01322 nsresult
01323 NS_NewPresContext(nsPresContext::nsPresContextType aType,
01324                   nsPresContext** aInstancePtrResult)
01325 {
01326   nsPresContext *context = new nsPresContext(aType);
01327   if (!context)
01328     return NS_ERROR_OUT_OF_MEMORY;
01329 
01330   NS_ADDREF(*aInstancePtrResult = context);
01331   return NS_OK;
01332 }
01333 
01334 #ifdef MOZ_REFLOW_PERF
01335 void
01336 nsPresContext::CountReflows(const char * aName,
01337                              PRUint32 aType, nsIFrame * aFrame)
01338 {
01339   if (mShell) {
01340     mShell->CountReflows(aName, aType, aFrame);
01341   }
01342 }
01343 
01344 void
01345 nsPresContext::PaintCount(const char * aName,
01346                            nsIRenderingContext* aRenderingContext,
01347                            nsIFrame * aFrame, PRUint32 aColor)
01348 {
01349   if (mShell) {
01350     mShell->PaintCount(aName, aRenderingContext, this, aFrame, aColor);
01351   }
01352 }
01353 #endif