Back to index

lightning-sunbird  0.9+nobinonly
nsCSSFrameConstructor.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 // vim:cindent:ts=2:et:sw=2:
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Dan Rosen <dr@netscape.com>
00025  *   Mats Palmgren <mats.palmgren@bredband.net>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsCSSFrameConstructor.h"
00042 #include "nsCRT.h"
00043 #include "nsIAtom.h"
00044 #include "nsIURL.h"
00045 #include "nsISupportsArray.h"
00046 #include "nsHashtable.h"
00047 #include "nsIStyledContent.h"
00048 #include "nsIHTMLDocument.h"
00049 #include "nsIStyleRule.h"
00050 #include "nsIFrame.h"
00051 #include "nsHTMLAtoms.h"
00052 #include "nsPresContext.h"
00053 #include "nsILinkHandler.h"
00054 #include "nsIDocument.h"
00055 #include "nsTableFrame.h"
00056 #include "nsTableColGroupFrame.h"
00057 #include "nsTableColFrame.h"
00058 #include "nsIDOMHTMLDocument.h"
00059 #include "nsIDOMHTMLTableColElement.h"
00060 #include "nsIDOMHTMLTableCaptionElem.h"
00061 #include "nsTableCellFrame.h" // to get IS_CELL_FRAME
00062 #include "nsHTMLParts.h"
00063 #include "nsIPresShell.h"
00064 #include "nsStyleSet.h"
00065 #include "nsIViewManager.h"
00066 #include "nsIScrollableView.h"
00067 #include "nsStyleConsts.h"
00068 #include "nsTableOuterFrame.h"
00069 #include "nsIDOMXULElement.h"
00070 #include "nsHTMLContainerFrame.h"
00071 #include "nsINameSpaceManager.h"
00072 #include "nsLayoutAtoms.h"
00073 #include "nsIDOMHTMLSelectElement.h"
00074 #include "nsIDOMHTMLLegendElement.h"
00075 #include "nsIComboboxControlFrame.h"
00076 #include "nsIListControlFrame.h"
00077 #include "nsISelectControlFrame.h"
00078 #include "nsIRadioControlFrame.h"
00079 #include "nsICheckboxControlFrame.h"
00080 #include "nsIDOMCharacterData.h"
00081 #include "nsIDOMHTMLImageElement.h"
00082 #include "nsITextContent.h"
00083 #include "nsPlaceholderFrame.h"
00084 #include "nsTableRowGroupFrame.h"
00085 #include "nsStyleChangeList.h"
00086 #include "nsIFormControl.h"
00087 #include "nsCSSAnonBoxes.h"
00088 #include "nsCSSPseudoElements.h"
00089 #include "nsIDeviceContext.h"
00090 #include "nsTextFragment.h"
00091 #include "nsISupportsArray.h"
00092 #include "nsIAnonymousContentCreator.h"
00093 #include "nsFrameManager.h"
00094 #include "nsLegendFrame.h"
00095 #include "nsIContentIterator.h"
00096 #include "nsBoxLayoutState.h"
00097 #include "nsIBindingManager.h"
00098 #include "nsXBLBinding.h"
00099 #include "nsITheme.h"
00100 #include "nsContentCID.h"
00101 #include "nsContentUtils.h"
00102 #include "nsIDocShell.h"
00103 #include "nsIDocShellTreeItem.h"
00104 #include "nsObjectFrame.h"
00105 #include "nsRuleNode.h"
00106 #include "nsIDOMMutationEvent.h"
00107 #include "nsChildIterator.h"
00108 #include "nsCSSRendering.h"
00109 #include "nsISelectElement.h"
00110 #include "nsLayoutErrors.h"
00111 #include "nsLayoutUtils.h"
00112 #include "nsAutoPtr.h"
00113 #include "nsXULAtoms.h"
00114 #include "nsBoxFrame.h"
00115 #include "nsIBoxLayout.h"
00116 
00117 static NS_DEFINE_CID(kEventQueueServiceCID,   NS_EVENTQUEUESERVICE_CID);
00118 
00119 #include "nsIDOMWindowInternal.h"
00120 #include "nsIMenuFrame.h"
00121 
00122 #include "nsBox.h"
00123 
00124 #ifdef MOZ_XUL
00125 #include "nsIRootBox.h"
00126 #include "nsIDOMXULCommandDispatcher.h"
00127 #include "nsIDOMXULDocument.h"
00128 #include "nsIXULDocument.h"
00129 #endif
00130 #ifdef ACCESSIBILITY
00131 #include "nsIAccessibilityService.h"
00132 #include "nsIAccessibleEvent.h"
00133 #endif
00134 
00135 #include "nsInlineFrame.h"
00136 #include "nsBlockFrame.h"
00137 
00138 #include "nsIScrollableFrame.h"
00139 
00140 #include "nsIXBLService.h"
00141 #include "nsIStyleRuleSupplier.h"
00142 
00143 #undef NOISY_FIRST_LETTER
00144 
00145 #ifdef MOZ_MATHML
00146 #include "nsMathMLAtoms.h"
00147 #include "nsMathMLParts.h"
00148 #endif
00149 
00150 #ifdef MOZ_XTF
00151 #include "nsIXTFElement.h"
00152 #include "nsIXTFElementWrapperPrivate.h"
00153 #include "nsIXTFVisualWrapperPrivate.h"
00154 nsresult
00155 NS_NewXTFXULDisplayFrame(nsIPresShell*, nsIFrame**);
00156 nsresult
00157 NS_NewXTFXMLDisplayFrame(nsIPresShell*, PRBool isBlock, nsIFrame**);
00158 #ifdef MOZ_SVG
00159 nsresult
00160 NS_NewXTFSVGDisplayFrame(nsIPresShell*, nsIContent*, nsIFrame**);
00161 #endif
00162 #endif
00163 
00164 nsresult
00165 NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00166 
00167 #ifdef MOZ_SVG
00168 #include "nsSVGAtoms.h"
00169 #include "nsISVGTextContainerFrame.h"
00170 #include "nsISVGContainerFrame.h"
00171 #include "nsStyleUtil.h"
00172 #include "nsSVGUtils.h"
00173 
00174 nsresult
00175 NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00176 nsresult
00177 NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00178 nsresult
00179 NS_NewSVGPolylineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00180 nsresult
00181 NS_NewSVGPolygonFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00182 nsresult
00183 NS_NewSVGCircleFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00184 nsresult
00185 NS_NewSVGEllipseFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00186 nsresult
00187 NS_NewSVGLineFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00188 nsresult
00189 NS_NewSVGRectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00190 nsresult
00191 NS_NewSVGGFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00192 nsresult
00193 NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00194 #ifdef MOZ_SVG_FOREIGNOBJECT
00195 nsresult
00196 NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00197 #endif
00198 nsresult
00199 NS_NewSVGPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00200 nsresult
00201 NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parent, nsIFrame** aNewFrame);
00202 nsresult
00203 NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00204 nsresult
00205 NS_NewSVGTSpanFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parent, nsIFrame** aNewFrame);
00206 nsresult
00207 NS_NewSVGDefsFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00208 nsresult
00209 NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00210 PRBool 
00211 NS_SVG_TestFeatures (const nsAString& value);
00212 extern nsresult
00213 NS_NewSVGLinearGradientFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame** newFrame);
00214 extern nsresult
00215 NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame** newFrame);
00216 extern nsresult
00217 NS_NewSVGStopFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame *aParentFrame, nsIFrame** newFrame);
00218 nsresult
00219 NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00220 extern nsresult
00221 NS_NewSVGImageFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame** newFrame);
00222 nsresult
00223 NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame** aNewFrame);
00224 nsresult
00225 NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* parent, nsIFrame** aNewFrame);
00226 #endif
00227 
00228 #include "nsIDocument.h"
00229 #include "nsIDOMElement.h"
00230 #include "nsIDOMNodeList.h"
00231 #include "nsIDOMDocument.h"
00232 #include "nsIDOMDocumentXBL.h"
00233 #include "nsIScrollable.h"
00234 #include "nsINodeInfo.h"
00235 #include "prenv.h"
00236 #include "nsWidgetsCID.h"
00237 #include "nsNodeInfoManager.h"
00238 #include "nsContentCreatorFunctions.h"
00239 
00240 // Global object maintenance
00241 nsIXBLService * nsCSSFrameConstructor::gXBLService = nsnull;
00242 
00243 // Global prefs
00244 static PRBool gGotXBLFormPrefs = PR_FALSE;
00245 static PRBool gUseXBLForms = PR_FALSE;
00246 
00247 #ifdef DEBUG
00248 // Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
00249 // more of the following flags (comma separated) for handy debug
00250 // output.
00251 static PRBool gNoisyContentUpdates = PR_FALSE;
00252 static PRBool gReallyNoisyContentUpdates = PR_FALSE;
00253 static PRBool gNoisyInlineConstruction = PR_FALSE;
00254 static PRBool gVerifyFastFindFrame = PR_FALSE;
00255 static PRBool gTablePseudoFrame = PR_FALSE;
00256 
00257 struct FrameCtorDebugFlags {
00258   const char* name;
00259   PRBool* on;
00260 };
00261 
00262 static FrameCtorDebugFlags gFlags[] = {
00263   { "content-updates",              &gNoisyContentUpdates },
00264   { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
00265   { "noisy-inline",                 &gNoisyInlineConstruction },
00266   { "fast-find-frame",              &gVerifyFastFindFrame },
00267   { "table-pseudo",                 &gTablePseudoFrame },
00268 };
00269 
00270 #define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
00271 #endif
00272 
00273 
00274 #ifdef MOZ_XUL
00275 #include "nsMenuFrame.h"
00276 #include "nsPopupSetFrame.h"
00277 #include "nsTreeColFrame.h"
00278 #include "nsIBoxObject.h"
00279 #include "nsPIListBoxObject.h"
00280 #include "nsListBoxBodyFrame.h"
00281 #include "nsListItemFrame.h"
00282 
00283 //------------------------------------------------------------------
00284 
00285 nsresult
00286 NS_NewAutoRepeatBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00287 
00288 nsresult
00289 NS_NewRootBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00290 
00291 nsresult
00292 NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00293 
00294 nsresult
00295 NS_NewThumbFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00296 
00297 nsresult
00298 NS_NewDeckFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIBoxLayout* aLayoutManager = nsnull);
00299 
00300 nsresult
00301 NS_NewLeafBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00302 
00303 nsresult
00304 NS_NewStackFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, nsIBoxLayout* aLayoutManager = nsnull);
00305 
00306 nsresult
00307 NS_NewProgressMeterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00308 
00309 nsresult
00310 NS_NewImageBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00311 
00312 nsresult
00313 NS_NewTextBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00314 
00315 nsresult
00316 NS_NewGroupBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00317 
00318 nsresult
00319 NS_NewButtonBoxFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00320 
00321 nsresult
00322 NS_NewGrippyFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00323 
00324 nsresult
00325 NS_NewSplitterFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00326 
00327 nsresult
00328 NS_NewMenuPopupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00329 
00330 nsresult
00331 NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00332 
00333 nsresult
00334 NS_NewMenuFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags );
00335 
00336 nsresult
00337 NS_NewMenuBarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00338 
00339 nsresult
00340 NS_NewTreeBodyFrame (nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00341 
00342 // grid
00343 nsresult
00344 NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsIBoxLayout** aNewLayout );
00345 nsresult
00346 NS_NewGridRowLeafLayout ( nsIPresShell* aPresShell, nsIBoxLayout** aNewLayout );
00347 nsresult
00348 NS_NewGridRowLeafFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayout);
00349 nsresult
00350 NS_NewGridRowGroupLayout ( nsIPresShell* aPresShell, nsIBoxLayout** aNewLayout );
00351 nsresult
00352 NS_NewGridRowGroupFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayout);
00353 
00354 nsresult
00355 NS_NewListBoxLayout ( nsIPresShell* aPresShell, nsCOMPtr<nsIBoxLayout>& aNewLayout );
00356 
00357 // end grid
00358 
00359 nsresult
00360 NS_NewTitleBarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00361 
00362 nsresult
00363 NS_NewResizerFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame);
00364 
00365 
00366 #endif
00367 
00368 nsresult
00369 NS_NewHTMLScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot);
00370 
00371 nsresult
00372 NS_NewXULScrollFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot);
00373 
00374 nsresult
00375 NS_NewSliderFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00376 
00377 nsresult
00378 NS_NewScrollbarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00379 
00380 nsresult
00381 NS_NewScrollbarButtonFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00382 
00383 nsresult
00384 NS_NewNativeScrollbarFrame ( nsIPresShell* aPresShell, nsIFrame** aNewFrame );
00385 
00386 
00387 #ifdef NOISY_FINDFRAME
00388 static PRInt32 FFWC_totalCount=0;
00389 static PRInt32 FFWC_doLoop=0;
00390 static PRInt32 FFWC_doSibling=0;
00391 static PRInt32 FFWC_recursions=0;
00392 static PRInt32 FFWC_nextInFlows=0;
00393 static PRInt32 FFWC_slowSearchForText=0;
00394 #endif
00395 
00396 static nsresult
00397 DeletingFrameSubtree(nsPresContext*  aPresContext,
00398                      nsFrameManager* aFrameManager,
00399                      nsIFrame*       aFrame);
00400 
00401 #ifdef  MOZ_SVG
00402 
00403 // Test to see if this language is supported
00404 static PRBool
00405 SVG_TestLanguage(const nsSubstring& lstr, const nsSubstring& prefs) 
00406 {
00407   // Compare list to attribute value, which may be a list
00408   // According to the SVG 1.1 Spec (at least as I read it), we should take
00409   // the first attribute value and check it for any matches in the users
00410   // preferences, including any prefix matches.
00411   // This algorithm is O(M*N)
00412   PRInt32 vbegin = 0;
00413   PRInt32 vlen = lstr.Length();
00414   while (vbegin < vlen) {
00415     PRInt32 vend = lstr.FindChar(PRUnichar(','), vbegin);
00416     if (vend == kNotFound) {
00417       vend = vlen;
00418     }
00419     PRInt32 gbegin = 0;
00420     PRInt32 glen = prefs.Length();
00421     while (gbegin < glen) {
00422       PRInt32 gend = prefs.FindChar(PRUnichar(','), gbegin);
00423       if (gend == kNotFound) {
00424         gend = glen;
00425       }
00426       const nsDefaultStringComparator defaultComparator;
00427       const nsStringComparator& comparator = 
00428                   NS_STATIC_CAST(const nsStringComparator&, defaultComparator);
00429       if (nsStyleUtil::DashMatchCompare(Substring(lstr, vbegin, vend-vbegin),
00430                                         Substring(prefs, gbegin, gend-gbegin),
00431                                         comparator)) {
00432         return PR_TRUE;
00433       }
00434       gbegin = gend + 1;
00435     }
00436     vbegin = vend + 1;
00437   }
00438   return PR_FALSE;
00439 }
00440 #endif
00441 
00442 static inline nsIFrame*
00443 GetFieldSetAreaFrame(nsIFrame* aFieldsetFrame)
00444 {
00445   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
00446   nsIFrame* firstChild = aFieldsetFrame->GetFirstChild(nsnull);
00447   return firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
00448 }
00449 
00450 //----------------------------------------------------------------------
00451 //
00452 // When inline frames get weird and have block frames in them, we
00453 // annotate them to help us respond to incremental content changes
00454 // more easily.
00455 
00456 static inline PRBool
00457 IsFrameSpecial(nsIFrame* aFrame)
00458 {
00459 
00460   return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) != 0;
00461 }
00462 
00463 static void
00464 GetSpecialSibling(nsFrameManager* aFrameManager, nsIFrame* aFrame, nsIFrame** aResult)
00465 {
00466   // We only store the "special sibling" annotation with the first
00467   // frame in the flow. Walk back to find that frame now.
00468   aFrame = aFrame->GetFirstInFlow();
00469 
00470   void* value = aFrame->GetProperty(nsLayoutAtoms::IBSplitSpecialSibling);
00471 
00472   *aResult = NS_STATIC_CAST(nsIFrame*, value);
00473 }
00474 
00475 static nsIFrame*
00476 GetLastSpecialSibling(nsFrameManager* aFrameManager, nsIFrame* aFrame)
00477 {
00478   for (nsIFrame *frame = aFrame, *next; ; frame = next) {
00479     GetSpecialSibling(aFrameManager, frame, &next);
00480     if (!next)
00481       return frame;
00482   }
00483   NS_NOTREACHED("unreachable code");
00484   return nsnull;
00485 }
00486 
00487 // Get the frame's next-in-flow, or, if it doesn't have one,
00488 // its special sibling.
00489 static nsIFrame*
00490 GetNifOrSpecialSibling(nsFrameManager *aFrameManager, nsIFrame *aFrame)
00491 {
00492   nsIFrame *result = aFrame->GetNextInFlow();
00493   if (result)
00494     return result;
00495 
00496   if (IsFrameSpecial(aFrame))
00497     GetSpecialSibling(aFrameManager, aFrame, &result);
00498   return result;
00499 }
00500 
00501 static void
00502 SetFrameIsSpecial(nsIFrame* aFrame, nsIFrame* aSpecialSibling)
00503 {
00504   NS_PRECONDITION(aFrame, "bad args!");
00505 
00506   // Mark the frame and all of its siblings as "special".
00507   for (nsIFrame* frame = aFrame; frame != nsnull; frame = frame->GetNextInFlow()) {
00508     frame->AddStateBits(NS_FRAME_IS_SPECIAL);
00509   }
00510 
00511   if (aSpecialSibling) {
00512     // We should be the first-in-flow
00513     NS_ASSERTION(!aFrame->GetPrevInFlow(),
00514                  "assigning special sibling to other than first-in-flow!");
00515 
00516     // Store the "special sibling" (if we were given one) with the
00517     // first frame in the flow.
00518     aFrame->SetProperty(nsLayoutAtoms::IBSplitSpecialSibling, aSpecialSibling);
00519   }
00520 }
00521 
00522 static nsIFrame*
00523 GetIBContainingBlockFor(nsIFrame* aFrame)
00524 {
00525   NS_PRECONDITION(IsFrameSpecial(aFrame),
00526                   "GetIBContainingBlockFor() should only be called on known IB frames");
00527 
00528   // Get the first "normal" ancestor of the target frame.
00529   nsIFrame* parentFrame;
00530   do {
00531     parentFrame = aFrame->GetParent();
00532 
00533     if (! parentFrame) {
00534       NS_ERROR("no unsplit block frame in IB hierarchy");
00535       return aFrame;
00536     }
00537 
00538     // Note that we ignore non-special frames which have a pseudo on their
00539     // style context -- they're not the frames we're looking for!  In
00540     // particular, they may be hiding a real parent that _is_ special.
00541     if (!IsFrameSpecial(parentFrame) &&
00542         !parentFrame->GetStyleContext()->GetPseudoType())
00543       break;
00544 
00545     aFrame = parentFrame;
00546   } while (1);
00547  
00548   // post-conditions
00549   NS_ASSERTION(parentFrame, "no normal ancestor found for special frame in GetIBContainingBlockFor");
00550   NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
00551 
00552   return parentFrame;
00553 }
00554 
00555 //----------------------------------------------------------------------
00556 
00557 // XXX this predicate and its cousins need to migrated to a single
00558 // place in layout - something in nsStyleDisplay maybe?
00559 static PRBool
00560 IsInlineFrame(nsIFrame* aFrame)
00561 {
00562   // XXXwaterson why don't we use |! display->IsBlockLevel()| here?
00563   switch (aFrame->GetStyleDisplay()->mDisplay) {
00564     case NS_STYLE_DISPLAY_INLINE:
00565     case NS_STYLE_DISPLAY_INLINE_BLOCK:
00566     case NS_STYLE_DISPLAY_INLINE_TABLE:
00567     case NS_STYLE_DISPLAY_INLINE_BOX:
00568     case NS_STYLE_DISPLAY_INLINE_GRID:
00569     case NS_STYLE_DISPLAY_INLINE_STACK:
00570     case NS_STYLE_DISPLAY_DECK:
00571     case NS_STYLE_DISPLAY_POPUP:
00572     case NS_STYLE_DISPLAY_GROUPBOX:
00573       return PR_TRUE;
00574     default:
00575       break;
00576   }
00577   return PR_FALSE;
00578 }
00579 
00580 // NeedSpecialFrameReframe uses this until we decide what to do about IsInlineFrame() above
00581 static PRBool
00582 IsInlineFrame2(nsIFrame* aFrame)
00583 {
00584   return !aFrame->GetStyleDisplay()->IsBlockLevel();
00585 }
00586 
00587 //----------------------------------------------------------------------
00588 
00589 // Block/inline frame construction logic. We maintain a few invariants here:
00590 //
00591 // 1. Block frames contain block and inline frames.
00592 //
00593 // 2. Inline frames only contain inline frames. If an inline parent has a block
00594 // child then the block child is migrated upward until it lands in a block
00595 // parent (the inline frames containing block is where it will end up).
00596 
00597 // XXX consolidate these things
00598 static PRBool
00599 IsBlockFrame(nsIFrame* aFrame)
00600 {
00601   // XXXwaterson this seems wrong; see IsInlineFrame() immediately
00602   // above, which will treat inline-block (e.g.) as an inline. Why
00603   // don't we use display->IsBlockLevel() here?
00604   const nsStyleDisplay* display = aFrame->GetStyleDisplay();
00605   return NS_STYLE_DISPLAY_INLINE != display->mDisplay;
00606 }
00607 
00608 static nsIFrame*
00609 FindFirstBlock(nsIFrame* aKid, nsIFrame** aPrevKid)
00610 {
00611   nsIFrame* prevKid = nsnull;
00612   while (aKid) {
00613     if (IsBlockFrame(aKid)) {
00614       *aPrevKid = prevKid;
00615       return aKid;
00616     }
00617     prevKid = aKid;
00618     aKid = aKid->GetNextSibling();
00619   }
00620   *aPrevKid = nsnull;
00621   return nsnull;
00622 }
00623 
00624 static nsIFrame*
00625 FindLastBlock(nsIFrame* aKid)
00626 {
00627   nsIFrame* lastBlock = nsnull;
00628   while (aKid) {
00629     if (IsBlockFrame(aKid)) {
00630       lastBlock = aKid;
00631     }
00632     aKid = aKid->GetNextSibling();
00633   }
00634   return lastBlock;
00635 }
00636 
00637 /*
00638  * Unlike the special (next) sibling, the special previous sibling
00639  * property points only from the anonymous block to the original
00640  * inline that preceded it.  DO NOT CHANGE THAT -- the
00641  * GetParentStyleContextFrame code depends on it!  It is useful for
00642  * finding the "special parent" of a frame (i.e., a frame from which a
00643  * good parent style context can be obtained), one looks at the
00644  * special previous sibling annotation of the real parent of the frame
00645  * (if the real parent has NS_FRAME_IS_SPECIAL).
00646  */
00647 inline void
00648 MarkIBSpecialPrevSibling(nsPresContext* aPresContext,
00649                          nsIFrame *aAnonymousFrame,
00650                          nsIFrame *aSpecialParent)
00651 {
00652   aPresContext->PropertyTable()->SetProperty(aAnonymousFrame,
00653                                       nsLayoutAtoms::IBSplitSpecialPrevSibling,
00654                                              aSpecialParent, nsnull, nsnull);
00655 }
00656 
00657 // -----------------------------------------------------------
00658 
00659 // Helper function that recursively removes content to frame mappings and
00660 // undisplayed content mappings.
00661 // This differs from DeletingFrameSubtree() because the frames have not yet been
00662 // added to the frame hierarchy
00663 static void
00664 DoCleanupFrameReferences(nsPresContext*  aPresContext,
00665                          nsFrameManager*  aFrameManager,
00666                          nsIFrame*        aFrameIn)
00667 {
00668   nsIContent* content = aFrameIn->GetContent();
00669 
00670   // if the frame is a placeholder use the out of flow frame
00671   nsIFrame* frame = nsPlaceholderFrame::GetRealFrameFor(aFrameIn);
00672 
00673   // Remove the mapping from the content object to its frame
00674   aFrameManager->RemoveAsPrimaryFrame(content, frame);
00675   aFrameManager->ClearAllUndisplayedContentIn(content);
00676 
00677   // Recursively walk the child frames.
00678   // Note: we only need to look at the principal child list
00679   nsIFrame* childFrame = frame->GetFirstChild(nsnull);
00680   while (childFrame) {
00681     DoCleanupFrameReferences(aPresContext, aFrameManager, childFrame);
00682     
00683     // Get the next sibling child frame
00684     childFrame = childFrame->GetNextSibling();
00685   }
00686 }
00687 
00688 // Helper function that walks a frame list and calls DoCleanupFrameReference()
00689 static void
00690 CleanupFrameReferences(nsPresContext*  aPresContext,
00691                        nsFrameManager*  aFrameManager,
00692                        nsIFrame*        aFrameList)
00693 {
00694   while (aFrameList) {
00695     DoCleanupFrameReferences(aPresContext, aFrameManager, aFrameList);
00696 
00697     // Get the sibling frame
00698     aFrameList = aFrameList->GetNextSibling();
00699   }
00700 }
00701 
00702 // -----------------------------------------------------------
00703 
00704 // Structure used when constructing formatting object trees.
00705 struct nsFrameItems {
00706   nsIFrame* childList;
00707   nsIFrame* lastChild;
00708   
00709   nsFrameItems(nsIFrame* aFrame = nsnull);
00710 
00711   // Appends the frame to the end of the list
00712   void AddChild(nsIFrame* aChild);
00713   // Remove the frame from the list, return PR_FALSE if not found.
00714   PRBool RemoveChild(nsIFrame* aChild);
00715 };
00716 
00717 nsFrameItems::nsFrameItems(nsIFrame* aFrame)
00718   : childList(aFrame), lastChild(aFrame)
00719 {
00720 }
00721 
00722 void 
00723 nsFrameItems::AddChild(nsIFrame* aChild)
00724 {
00725 #ifdef DEBUG
00726   nsIFrame* oldLastChild = lastChild;
00727 #endif
00728   
00729   if (childList == nsnull) {
00730     childList = lastChild = aChild;
00731   }
00732   else
00733   {
00734     NS_ASSERTION(aChild != lastChild,
00735                  "Same frame being added to frame list twice?");
00736     lastChild->SetNextSibling(aChild);
00737     lastChild = aChild;
00738   }
00739   // if aChild has siblings, lastChild needs to be the last one
00740   for (nsIFrame* sib = lastChild->GetNextSibling(); sib;
00741        sib = sib->GetNextSibling()) {
00742     NS_ASSERTION(oldLastChild != sib, "Loop in frame list");
00743     lastChild = sib;
00744   }
00745 }
00746 
00747 PRBool
00748 nsFrameItems::RemoveChild(nsIFrame* aFrame)
00749 {
00750   NS_PRECONDITION(aFrame, "null ptr");
00751   nsIFrame* prev = nsnull;
00752   nsIFrame* sib = childList;
00753   for (; sib && sib != aFrame; sib = sib->GetNextSibling()) {
00754     prev = sib;
00755   }
00756   if (!sib) {
00757     return PR_FALSE;
00758   }
00759   if (sib == childList) {
00760     childList = sib->GetNextSibling();
00761   } else {
00762     prev->SetNextSibling(sib->GetNextSibling());
00763   }
00764   if (sib == lastChild) {
00765     lastChild = prev;
00766   }
00767   sib->SetNextSibling(nsnull);
00768   return PR_TRUE;
00769 }
00770 
00771 // -----------------------------------------------------------
00772 
00773 // Structure used when constructing formatting object trees. Contains
00774 // state information needed for absolutely positioned elements
00775 struct nsAbsoluteItems : nsFrameItems {
00776   // containing block for absolutely positioned elements
00777   nsIFrame* containingBlock;
00778   
00779   nsAbsoluteItems(nsIFrame* aContainingBlock);
00780 #ifdef DEBUG
00781   // XXXbz Does this need a debug-only assignment operator that nulls out the
00782   // childList in the nsAbsoluteItems we're copying?  Introducing a difference
00783   // between debug and non-debug behavior seems bad, so I guess not...
00784   ~nsAbsoluteItems() {
00785     NS_ASSERTION(!childList,
00786                  "Dangling child list.  Someone forgot to insert it?");
00787   }
00788 #endif
00789   
00790   // Appends the frame to the end of the list
00791   void AddChild(nsIFrame* aChild);
00792 };
00793 
00794 nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock)
00795   : containingBlock(aContainingBlock)
00796 {
00797 }
00798 
00799 // Additional behavior is that it sets the frame's NS_FRAME_OUT_OF_FLOW flag
00800 void
00801 nsAbsoluteItems::AddChild(nsIFrame* aChild)
00802 {
00803   aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
00804   nsFrameItems::AddChild(aChild);
00805 }
00806 
00807 // Structures used to record the creation of pseudo table frames where 
00808 // the content belongs to some ancestor. 
00809 // PseudoFrames are necessary when the childframe cannot be the direct
00810 // ancestor of the content based parent frame. The amount of necessary pseudo
00811 // frames is limited as the worst case would be table frame nested directly
00812 // into another table frame. So the member structures of nsPseudoFrames can be
00813 // viewed as a ring buffer where you start with the necessary frame type and
00814 // add higher frames as long as necessary to fit into the initial parent frame.
00815 // mLowestType is some sort of stack pointer which shows the start of the
00816 // ringbuffer. The insertion of pseudo frames can happen between every
00817 // two frames so we need to push and pop the pseudo frame data when children
00818 // of a frame are created.
00819 // The colgroup frame is special as it can harbour only col children.
00820 // Once all children of given frame are known, the pseudo frames can be
00821 // processed that means attached to the corresponding parent frames.
00822 // The behaviour is in general described at
00823 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
00824 // however there are implementation details that extend the CSS 2.1
00825 // specification:
00826 // 1. every table frame is wrapped in an outer table frame, which is always a
00827 //    pseudo frame.
00828 // 2. the outer table frame will be also created to hold a caption.
00829 // 3. each table cell will have a pseudo inner table cell frame.
00830 // 4. a colgroup frame is created between a column and a table
00831 // 5. a rowgroup frame is created between a row and a table
00832 // A table frame can only have rowgroups or column groups as children.
00833 // A outer table frame can only have one caption and one table frame
00834 // as children.
00835 // Every table even if all table frames are specified will require the
00836 // creation of two types of pseudo frames: the outer table frame and the inner
00837 // table cell frames.
00838 
00839 struct nsPseudoFrameData {
00840   nsIFrame*    mFrame; // created pseudo frame
00841   nsFrameItems mChildList;  // child frames pending to be added to the pseudo
00842   nsFrameItems mChildList2; // child frames pending to be added to the pseudo
00843 
00844   nsPseudoFrameData();
00845   nsPseudoFrameData(nsPseudoFrameData& aOther);
00846   void Reset();
00847 #ifdef DEBUG
00848   void Dump();
00849 #endif
00850 };
00851 
00852 struct nsPseudoFrames {
00853   nsPseudoFrameData mTableOuter; 
00854   nsPseudoFrameData mTableInner;  
00855   nsPseudoFrameData mRowGroup;   
00856   nsPseudoFrameData mColGroup;
00857   nsPseudoFrameData mRow;   
00858   nsPseudoFrameData mCellOuter;
00859   nsPseudoFrameData mCellInner;
00860 
00861   // the frame type of the most descendant pseudo frame, no AddRef
00862   nsIAtom*          mLowestType;
00863 
00864   nsPseudoFrames();
00865   nsPseudoFrames& operator=(const nsPseudoFrames& aOther);
00866   void Reset(nsPseudoFrames* aSave = nsnull);
00867   PRBool IsEmpty() { return (!mLowestType && !mColGroup.mFrame); }
00868 #ifdef DEBUG
00869   void Dump();
00870 #endif
00871 };
00872 
00873 nsPseudoFrameData::nsPseudoFrameData()
00874 : mFrame(nsnull), mChildList(), mChildList2()
00875 {}
00876 
00877 nsPseudoFrameData::nsPseudoFrameData(nsPseudoFrameData& aOther)
00878 : mFrame(aOther.mFrame), mChildList(aOther.mChildList), 
00879   mChildList2(aOther.mChildList2)
00880 {}
00881 
00882 void
00883 nsPseudoFrameData::Reset()
00884 {
00885   mFrame = nsnull;
00886   mChildList.childList  = mChildList.lastChild  = nsnull;
00887   mChildList2.childList = mChildList2.lastChild = nsnull;
00888 }
00889 
00890 #ifdef DEBUG
00891 void
00892 nsPseudoFrameData::Dump()
00893 {
00894   nsIFrame* main = nsnull;
00895   nsIFrame* second = nsnull;
00896   printf("        %p\n", NS_STATIC_CAST(void*, mFrame));
00897   main = mChildList.childList;
00898 
00899  
00900   second = mChildList2.childList;
00901   while (main || second) {
00902     printf("          %p   %p\n", NS_STATIC_CAST(void*, main),
00903            NS_STATIC_CAST(void*, second));
00904     if (main)
00905       main = main->GetNextSibling();
00906     if (second)
00907       second = second->GetNextSibling();
00908   }
00909 }
00910 #endif
00911 nsPseudoFrames::nsPseudoFrames() 
00912 : mTableOuter(), mTableInner(), mRowGroup(), mColGroup(), 
00913   mRow(), mCellOuter(), mCellInner(), mLowestType(nsnull)
00914 {}
00915 
00916 nsPseudoFrames& nsPseudoFrames::operator=(const nsPseudoFrames& aOther)
00917 {
00918   mTableOuter = aOther.mTableOuter;
00919   mTableInner = aOther.mTableInner;
00920   mColGroup   = aOther.mColGroup;
00921   mRowGroup   = aOther.mRowGroup;
00922   mRow        = aOther.mRow;
00923   mCellOuter  = aOther.mCellOuter;
00924   mCellInner  = aOther.mCellInner;
00925   mLowestType = aOther.mLowestType;
00926 
00927   return *this;
00928 }
00929 void
00930 nsPseudoFrames::Reset(nsPseudoFrames* aSave) 
00931 {
00932   if (aSave) {
00933     *aSave = *this;
00934   }
00935 
00936   mTableOuter.Reset();
00937   mTableInner.Reset();
00938   mColGroup.Reset();
00939   mRowGroup.Reset();
00940   mRow.Reset();
00941   mCellOuter.Reset();
00942   mCellInner.Reset();
00943   mLowestType = nsnull;
00944 }
00945 
00946 #ifdef DEBUG
00947 void
00948 nsPseudoFrames::Dump()
00949 {
00950   if (IsEmpty()) {
00951     // check that it is really empty, warn otherwise
00952     NS_ASSERTION(!mTableOuter.mFrame,    "Pseudo Outer Table Frame not empty");
00953     NS_ASSERTION(!mTableOuter.mChildList.childList, "Pseudo Outer Table Frame has primary children");
00954     NS_ASSERTION(!mTableOuter.mChildList2.childList,"Pseudo Outer Table Frame has secondary children");
00955     NS_ASSERTION(!mTableInner.mFrame,    "Pseudo Inner Table Frame not empty");
00956     NS_ASSERTION(!mTableInner.mChildList.childList, "Pseudo Inner Table Frame has primary children");
00957     NS_ASSERTION(!mTableInner.mChildList2.childList,"Pseudo Inner Table Frame has secondary children");
00958     NS_ASSERTION(!mColGroup.mFrame,      "Pseudo Colgroup Frame not empty");
00959     NS_ASSERTION(!mColGroup.mChildList.childList,   "Pseudo Colgroup Table Frame has primary children");
00960     NS_ASSERTION(!mColGroup.mChildList2.childList,  "Pseudo Colgroup Table Frame has secondary children");
00961     NS_ASSERTION(!mRowGroup.mFrame,      "Pseudo Rowgroup Frame not empty");
00962     NS_ASSERTION(!mRowGroup.mChildList.childList,   "Pseudo Rowgroup Frame has primary children");
00963     NS_ASSERTION(!mRowGroup.mChildList2.childList,  "Pseudo Rowgroup Frame has secondary children");
00964     NS_ASSERTION(!mRow.mFrame,           "Pseudo Row Frame not empty");
00965     NS_ASSERTION(!mRow.mChildList.childList,        "Pseudo Row Frame has primary children");
00966     NS_ASSERTION(!mRow.mChildList2.childList,       "Pseudo Row Frame has secondary children");
00967     NS_ASSERTION(!mCellOuter.mFrame,     "Pseudo Outer Cell Frame not empty");
00968     NS_ASSERTION(!mCellOuter.mChildList.childList,  "Pseudo Outer Cell Frame has primary children");
00969     NS_ASSERTION(!mCellOuter.mChildList2.childList, "Pseudo Outer Cell Frame has secondary children");
00970     NS_ASSERTION(!mCellInner.mFrame,     "Pseudo Inner Cell Frame not empty");
00971     NS_ASSERTION(!mCellInner.mChildList.childList,  "Pseudo Inner Cell Frame has primary children");
00972     NS_ASSERTION(!mCellInner.mChildList2.childList, "Pseudo inner Cell Frame has secondary children");
00973   }
00974   else {
00975     if (mTableOuter.mFrame || mTableOuter.mChildList.childList || mTableOuter.mChildList2.childList) {
00976       if (nsLayoutAtoms::tableOuterFrame == mLowestType) {
00977         printf("LOW OuterTable\n");
00978       }
00979       else {
00980         printf("    OuterTable\n");
00981       }
00982       mTableOuter.Dump();
00983     }
00984     if (mTableInner.mFrame || mTableInner.mChildList.childList || mTableInner.mChildList2.childList) {
00985       if (nsLayoutAtoms::tableFrame == mLowestType) {
00986         printf("LOW InnerTable\n");
00987       }
00988       else {
00989         printf("    InnerTable\n");
00990       }
00991       mTableInner.Dump();
00992     }
00993     if (mColGroup.mFrame || mColGroup.mChildList.childList || mColGroup.mChildList2.childList) {
00994       if (nsLayoutAtoms::tableColGroupFrame == mLowestType) {
00995         printf("LOW ColGroup\n");
00996       }
00997       else {
00998         printf("    ColGroup\n");
00999       }
01000       mColGroup.Dump();
01001     }
01002     if (mRowGroup.mFrame || mRowGroup.mChildList.childList || mRowGroup.mChildList2.childList) {
01003       if (nsLayoutAtoms::tableRowGroupFrame == mLowestType) {
01004         printf("LOW RowGroup\n");
01005       }
01006       else {
01007         printf("    RowGroup\n");
01008       }
01009       mRowGroup.Dump();
01010     }
01011     if (mRow.mFrame || mRow.mChildList.childList || mRow.mChildList2.childList) {
01012       if (nsLayoutAtoms::tableRowFrame == mLowestType) {
01013         printf("LOW Row\n");
01014       }
01015       else {
01016         printf("    Row\n");
01017       }
01018       mRow.Dump();
01019     }
01020     
01021     if (mCellOuter.mFrame || mCellOuter.mChildList.childList || mCellOuter.mChildList2.childList) {
01022       if (IS_TABLE_CELL(mLowestType)) {
01023         printf("LOW OuterCell\n");
01024       }
01025       else {
01026         printf("    OuterCell\n");
01027       }
01028       mCellOuter.Dump();
01029     }
01030     if (mCellInner.mFrame || mCellInner.mChildList.childList || mCellInner.mChildList2.childList) {
01031       printf("    InnerCell\n");
01032       mCellInner.Dump();
01033     }
01034   }
01035 }
01036 #endif
01037 // -----------------------------------------------------------
01038 
01039 // Structure for saving the existing state when pushing/poping containing
01040 // blocks. The destructor restores the state to its previous state
01041 class nsFrameConstructorSaveState {
01042 public:
01043   nsFrameConstructorSaveState();
01044   ~nsFrameConstructorSaveState();
01045 
01046 private:
01047   nsAbsoluteItems* mItems;                // pointer to struct whose data we save/restore
01048   PRBool*          mFirstLetterStyle;
01049   PRBool*          mFirstLineStyle;
01050 
01051   nsAbsoluteItems  mSavedItems;           // copy of original data
01052   PRBool           mSavedFirstLetterStyle;
01053   PRBool           mSavedFirstLineStyle;
01054 
01055   // The name of the child list in which our frames would belong
01056   nsIAtom* mChildListName;
01057   nsFrameConstructorState* mState;
01058 
01059   friend class nsFrameConstructorState;
01060 };
01061 
01062 // Structure for saving the existing state when pushing/popping insertion
01063 // points for nsIAnonymousContentCreator.  The destructor restores the state
01064 // to its previous state.  See documentation of these members in
01065 // nsFrameConstructorState.
01066 class nsFrameConstructorInsertionState {
01067 public:
01068   nsFrameConstructorInsertionState();
01069   ~nsFrameConstructorInsertionState();
01070 
01071 private:
01072   nsIFrame*   mAnonymousCreator;
01073   nsIContent* mInsertionContent;
01074   PRBool      mCreatorIsBlock;
01075 
01076   nsFrameConstructorState* mState;
01077 
01078   friend class nsFrameConstructorState;
01079 };
01080 
01081 // Structure used for maintaining state information during the
01082 // frame construction process
01083 class nsFrameConstructorState {
01084 public:
01085   nsPresContext            *mPresContext;
01086   nsIPresShell             *mPresShell;
01087   nsFrameManager           *mFrameManager;
01088 
01089   // Containing block information for out-of-flow frammes
01090   nsAbsoluteItems           mFixedItems;
01091   nsAbsoluteItems           mAbsoluteItems;
01092   nsAbsoluteItems           mFloatedItems;
01093   PRBool                    mFirstLetterStyle;
01094   PRBool                    mFirstLineStyle;
01095   nsCOMPtr<nsILayoutHistoryState> mFrameState;
01096   nsPseudoFrames            mPseudoFrames;
01097 
01098   // The nsIAnonymousContentCreator we're currently constructing children for.
01099   nsIFrame                 *mAnonymousCreator;
01100   // The insertion point node for mAnonymousCreator.
01101   nsIContent               *mInsertionContent;
01102   // Whether the parent is a block (see ProcessChildren's aParentIsBlock)
01103   PRBool                    mCreatorIsBlock;
01104 
01105   // Constructor
01106   // Use the passed-in history state.
01107   nsFrameConstructorState(nsIPresShell*          aPresShell,
01108                           nsIFrame*              aFixedContainingBlock,
01109                           nsIFrame*              aAbsoluteContainingBlock,
01110                           nsIFrame*              aFloatContainingBlock,
01111                           nsILayoutHistoryState* aHistoryState);
01112   // Get the history state from the pres context's pres shell.
01113   nsFrameConstructorState(nsIPresShell*          aPresShell,
01114                           nsIFrame*              aFixedContainingBlock,
01115                           nsIFrame*              aAbsoluteContainingBlock,
01116                           nsIFrame*              aFloatContainingBlock);
01117 
01118   ~nsFrameConstructorState();
01119   
01120   // Function to push the existing absolute containing block state and
01121   // create a new scope. Code that uses this function should get matching
01122   // logic in GetAbsoluteContainingBlock.
01123   void PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
01124                                    nsFrameConstructorSaveState& aSaveState);
01125 
01126   // Function to push the existing float containing block state and
01127   // create a new scope. Code that uses this function should get matching
01128   // logic in GetFloatContainingBlock.
01129   // Pushing a null float containing block forbids any frames from being
01130   // floated until a new float containing block is pushed.
01131   // XXX we should get rid of null float containing blocks and teach the
01132   // various frame classes to deal with floats instead.
01133   void PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
01134                                 nsFrameConstructorSaveState& aSaveState,
01135                                 PRBool aFirstLetterStyle,
01136                                 PRBool aFirstLineStyle);
01137 
01138   // Function to return the proper geometric parent for a frame with display
01139   // struct given by aStyleDisplay and parent's frame given by
01140   // aContentParentFrame.  If the frame is not allowed to be positioned, pass
01141   // false for aCanBePositioned.
01142   nsIFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
01143                                nsIFrame* aContentParentFrame);
01144 
01167   nsresult AddChild(nsIFrame* aNewFrame,
01168                     nsFrameItems& aFrameItems,
01169                     const nsStyleDisplay* aStyleDisplay,
01170                     nsIContent* aContent,
01171                     nsStyleContext* aStyleContext,
01172                     nsIFrame* aParentFrame,
01173                     PRBool aCanBePositioned = PR_TRUE,
01174                     PRBool aCanBeFloated = PR_TRUE);
01175 
01176   // Push an nsIAnonymousContentCreator and its insertion node
01177   void PushAnonymousContentCreator(nsIFrame *aCreator,
01178                                    nsIContent *aContent,
01179                                    PRBool aIsBlock,
01180                                    nsFrameConstructorInsertionState &aSaveState);
01181 
01182 protected:
01183   friend class nsFrameConstructorSaveState;
01184   friend class nsFrameConstructorInsertionState;
01185 
01190   void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
01191                               nsIAtom* aChildListName);
01192 };
01193 
01194 nsFrameConstructorState::nsFrameConstructorState(nsIPresShell*          aPresShell,
01195                                                  nsIFrame*              aFixedContainingBlock,
01196                                                  nsIFrame*              aAbsoluteContainingBlock,
01197                                                  nsIFrame*              aFloatContainingBlock,
01198                                                  nsILayoutHistoryState* aHistoryState)
01199   : mPresContext(aPresShell->GetPresContext()),
01200     mPresShell(aPresShell),
01201     mFrameManager(aPresShell->FrameManager()),
01202     mFixedItems(aFixedContainingBlock),
01203     mAbsoluteItems(aAbsoluteContainingBlock),
01204     mFloatedItems(aFloatContainingBlock),
01205     mFirstLetterStyle(PR_FALSE),
01206     mFirstLineStyle(PR_FALSE),
01207     mFrameState(aHistoryState),
01208     mPseudoFrames(),
01209     mAnonymousCreator(nsnull),
01210     mInsertionContent(nsnull),
01211     mCreatorIsBlock(PR_FALSE)
01212 {
01213 }
01214 
01215 nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
01216                                                  nsIFrame*     aFixedContainingBlock,
01217                                                  nsIFrame*     aAbsoluteContainingBlock,
01218                                                  nsIFrame*     aFloatContainingBlock)
01219   : mPresContext(aPresShell->GetPresContext()),
01220     mPresShell(aPresShell),
01221     mFrameManager(aPresShell->FrameManager()),
01222     mFixedItems(aFixedContainingBlock),
01223     mAbsoluteItems(aAbsoluteContainingBlock),
01224     mFloatedItems(aFloatContainingBlock),
01225     mFirstLetterStyle(PR_FALSE),
01226     mFirstLineStyle(PR_FALSE),
01227     mPseudoFrames(),
01228     mAnonymousCreator(nsnull),
01229     mInsertionContent(nsnull),
01230     mCreatorIsBlock(PR_FALSE)
01231 {
01232   mFrameState = aPresShell->GetDocument()->GetLayoutHistoryState();
01233 }
01234 
01235 nsFrameConstructorState::~nsFrameConstructorState()
01236 {
01237   ProcessFrameInsertions(mAbsoluteItems, nsLayoutAtoms::absoluteList);
01238   ProcessFrameInsertions(mFixedItems, nsLayoutAtoms::fixedList);
01239   ProcessFrameInsertions(mFloatedItems, nsLayoutAtoms::floatList);
01240 }
01241 
01242 static nsIFrame*
01243 AdjustAbsoluteContainingBlock(nsPresContext* aPresContext,
01244                               nsIFrame*       aContainingBlockIn)
01245 {
01246   if (!aContainingBlockIn) {
01247     return nsnull;
01248   }
01249 
01250   // Always use the container's first in flow.
01251   return aContainingBlockIn->GetFirstInFlow();
01252 }
01253 
01254 void
01255 nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
01256                                                      nsFrameConstructorSaveState& aSaveState)
01257 {
01258   aSaveState.mItems = &mAbsoluteItems;
01259   aSaveState.mSavedItems = mAbsoluteItems;
01260   aSaveState.mChildListName = nsLayoutAtoms::absoluteList;
01261   aSaveState.mState = this;
01262   mAbsoluteItems = 
01263     nsAbsoluteItems(AdjustAbsoluteContainingBlock(mPresContext,
01264                                                   aNewAbsoluteContainingBlock));
01265 }
01266 
01267 void
01268 nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
01269                                                   nsFrameConstructorSaveState& aSaveState,
01270                                                   PRBool aFirstLetterStyle,
01271                                                   PRBool aFirstLineStyle)
01272 {
01273   // XXXbz we should probably just be able to assert that
01274   // aNewFloatContainingBlock is a float containing block... see XXX comment at
01275   // the top of ProcessChildren.
01276   NS_PRECONDITION(!aNewFloatContainingBlock ||
01277                   aNewFloatContainingBlock->GetContentInsertionFrame()->
01278                     IsFloatContainingBlock(),
01279                   "Please push a real float containing block!");
01280   aSaveState.mItems = &mFloatedItems;
01281   aSaveState.mFirstLetterStyle = &mFirstLetterStyle;
01282   aSaveState.mFirstLineStyle = &mFirstLineStyle;
01283   aSaveState.mSavedItems = mFloatedItems;
01284   aSaveState.mSavedFirstLetterStyle = mFirstLetterStyle;
01285   aSaveState.mSavedFirstLineStyle = mFirstLineStyle;
01286   aSaveState.mChildListName = nsLayoutAtoms::floatList;
01287   aSaveState.mState = this;
01288   mFloatedItems = nsAbsoluteItems(aNewFloatContainingBlock);
01289   mFirstLetterStyle = aFirstLetterStyle;
01290   mFirstLineStyle = aFirstLineStyle;
01291 }
01292 
01293 nsIFrame*
01294 nsFrameConstructorState::GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
01295                                             nsIFrame* aContentParentFrame)
01296 {
01297   NS_PRECONDITION(aStyleDisplay, "Must have display struct!");
01298 
01299   // If there is no container for a fixed, absolute, or floating root
01300   // frame, we will ignore the positioning.  This hack is originally
01301   // brought to you by the letter T: tables, since other roots don't
01302   // even call into this code.  See bug 178855.
01303   //
01304   // XXX Disabling positioning in this case is a hack.  If one was so inclined,
01305   // one could support this either by (1) inserting a dummy block between the
01306   // table and the canvas or (2) teaching the canvas how to reflow positioned
01307   // elements. (1) has the usual problems when multiple frames share the same
01308   // content (notice all the special cases in this file dealing with inner
01309   // tables and outer tables which share the same content). (2) requires some
01310   // work and possible factoring.
01311   //
01312   // XXXbz couldn't we just force position to "static" on roots and
01313   // float to "none"?  That's OK per CSS 2.1, as far as I can tell.
01314   
01315   if (aStyleDisplay->IsFloating() && mFloatedItems.containingBlock) {
01316     NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositioned(),
01317                  "Absolutely positioned _and_ floating?");
01318     return mFloatedItems.containingBlock;
01319   }
01320 
01321   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
01322       mAbsoluteItems.containingBlock) {
01323     return mAbsoluteItems.containingBlock;
01324   }
01325 
01326   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
01327       mFixedItems.containingBlock) {
01328     return mFixedItems.containingBlock;
01329   }
01330 
01331   return aContentParentFrame;
01332 }
01333 
01334 nsresult
01335 nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
01336                                   nsFrameItems& aFrameItems,
01337                                   const nsStyleDisplay* aStyleDisplay,
01338                                   nsIContent* aContent,
01339                                   nsStyleContext* aStyleContext,
01340                                   nsIFrame* aParentFrame,
01341                                   PRBool aCanBePositioned,
01342                                   PRBool aCanBeFloated)
01343 {
01344   // The comments in GetGeometricParent regarding root table frames
01345   // all apply here, unfortunately.
01346 
01347   PRBool needPlaceholder = PR_FALSE;
01348   nsFrameItems* frameItems = &aFrameItems;
01349   if (aCanBeFloated && aStyleDisplay->IsFloating() &&
01350       mFloatedItems.containingBlock) {
01351     NS_ASSERTION(aNewFrame->GetParent() == mFloatedItems.containingBlock,
01352                  "Float whose parent is not the float containing block?");
01353     needPlaceholder = PR_TRUE;
01354     frameItems = &mFloatedItems;
01355   } else if (aCanBePositioned) {
01356     if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
01357         mAbsoluteItems.containingBlock) {
01358       NS_ASSERTION(aNewFrame->GetParent() == mAbsoluteItems.containingBlock,
01359                    "Abs pos whose parent is not the abs pos containing block?");
01360       needPlaceholder = PR_TRUE;
01361       frameItems = &mAbsoluteItems;
01362     }
01363     if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
01364         mFixedItems.containingBlock) {
01365       NS_ASSERTION(aNewFrame->GetParent() == mFixedItems.containingBlock,
01366                    "Fixed pos whose parent is not the fixed pos containing block?");
01367       needPlaceholder = PR_TRUE;
01368       frameItems = &mFixedItems;
01369     }
01370   }
01371 
01372   if (needPlaceholder) {
01373     NS_ASSERTION(frameItems != &aFrameItems,
01374                  "Putting frame in-flow _and_ want a placeholder?");
01375     nsIFrame* placeholderFrame;
01376     nsresult rv =
01377       nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
01378                                                        mPresContext,
01379                                                        mFrameManager,
01380                                                        aContent,
01381                                                        aNewFrame,
01382                                                        aStyleContext,
01383                                                        aParentFrame,
01384                                                        &placeholderFrame);
01385     if (NS_FAILED(rv)) {
01386       // Note that aNewFrame could be the top frame for a scrollframe setup,
01387       // hence already set as the primary frame.  So we have to clean up here.
01388       // But it shouldn't have any out-of-flow kids.
01389       // XXXbz Maybe add a utility function to assert that?
01390       CleanupFrameReferences(mPresContext, mFrameManager,
01391                              aNewFrame);
01392       aNewFrame->Destroy(mPresContext);
01393       return rv;
01394     }
01395 
01396     // Add the placeholder frame to the flow
01397     aFrameItems.AddChild(placeholderFrame);
01398   }
01399 #ifdef DEBUG
01400   else {
01401     NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
01402                  "In-flow frame has wrong parent");
01403   }
01404 #endif
01405 
01406   frameItems->AddChild(aNewFrame);
01407 
01408   // Now add the special siblings too.
01409   nsIFrame* specialSibling = aNewFrame;
01410   while (specialSibling && IsFrameSpecial(specialSibling)) {
01411     GetSpecialSibling(mFrameManager, specialSibling, &specialSibling);
01412     if (specialSibling) {
01413       NS_ASSERTION(frameItems == &aFrameItems,
01414                    "IB split ending up in an out-of-flow childlist?");
01415       frameItems->AddChild(specialSibling);
01416     }
01417   }
01418   
01419   return NS_OK;
01420 }
01421 
01422 void
01423 nsFrameConstructorState::PushAnonymousContentCreator(nsIFrame *aCreator,
01424                                                      nsIContent *aContent,
01425                                                      PRBool aIsBlock,
01426                                                      nsFrameConstructorInsertionState &aSaveState)
01427 {
01428   NS_ASSERTION(aCreator || !aContent, "Must have a frame if there is an insertion node");
01429   aSaveState.mAnonymousCreator = mAnonymousCreator;
01430   aSaveState.mInsertionContent = mInsertionContent;
01431   aSaveState.mCreatorIsBlock = mCreatorIsBlock;
01432   aSaveState.mState = this;
01433 
01434   mAnonymousCreator = aCreator;
01435   mInsertionContent = aContent;
01436   mCreatorIsBlock = aIsBlock;
01437 }
01438 
01439 void
01440 nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
01441                                                 nsIAtom* aChildListName)
01442 {
01443   NS_PRECONDITION((&aFrameItems == &mFloatedItems &&
01444                    aChildListName == nsLayoutAtoms::floatList) ||
01445                   (&aFrameItems == &mAbsoluteItems &&
01446                    aChildListName == nsLayoutAtoms::absoluteList) ||
01447                   (&aFrameItems == &mFixedItems &&
01448                    aChildListName == nsLayoutAtoms::fixedList),
01449                   "Unexpected aFrameItems/aChildListName combination");
01450 
01451   nsIFrame* firstNewFrame = aFrameItems.childList;
01452   
01453   if (!firstNewFrame) {
01454     return;
01455   }
01456   
01457   nsIFrame* containingBlock = aFrameItems.containingBlock;
01458 
01459   NS_ASSERTION(containingBlock,
01460                "Child list without containing block?");
01461   
01462   // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
01463   // if the containing block hasn't been reflown yet (so NS_FRAME_FIRST_REFLOW
01464   // is set) and doesn't have any frames in the aChildListName child list yet.
01465   nsIFrame* firstChild = containingBlock->GetFirstChild(aChildListName);
01466   nsresult rv = NS_OK;
01467   if (!firstChild && (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
01468     rv = containingBlock->SetInitialChildList(mPresContext,
01469                                               aChildListName,
01470                                               firstNewFrame);
01471   } else {
01472     // Note that whether the frame construction context is doing an append or
01473     // not is not helpful here, since it could be appending to some frame in
01474     // the middle of the document, which means we're not necessarily
01475     // appending to the children of the containing block.
01476     //
01477     // We need to make sure the 'append to the end of document' case is fast.
01478     // So first test the last child of the containing block
01479     nsIFrame* lastChild = nsLayoutUtils::GetLastSibling(firstChild);
01480 
01481     if (!lastChild ||
01482         nsLayoutUtils::CompareTreePosition(lastChild->GetContent(),
01483                                            firstNewFrame->GetContent(),
01484                                            containingBlock->GetContent()) < 0) {
01485       // no lastChild, or lastChild comes before the new children, so just append
01486       rv = containingBlock->AppendFrames(aChildListName, firstNewFrame);
01487     } else {
01488       nsIFrame* insertionPoint = nsnull;
01489       // try the other children
01490       for (nsIFrame* f = firstChild; f != lastChild; f = f->GetNextSibling()) {
01491         if (nsLayoutUtils::CompareTreePosition(f->GetContent(),
01492                                                firstNewFrame->GetContent(),
01493                                                containingBlock->GetContent()) > 0) {
01494           // f comes after the new children, so stop here and insert after
01495           // the previous frame
01496           break;
01497         }
01498         insertionPoint = f;
01499       }
01500 
01501       rv = containingBlock->InsertFrames(aChildListName, insertionPoint,
01502                                          firstNewFrame);
01503     }
01504   }
01505   aFrameItems.childList = nsnull;
01506   // XXXbz And if NS_FAILED(rv), what?  I guess we need to clean up the list
01507   // and deal with all the placeholders... but what if the placeholders aren't
01508   // in the document yet?  Could that happen?
01509   NS_ASSERTION(NS_SUCCEEDED(rv), "Frames getting lost!");
01510 }
01511 
01512 
01513 nsFrameConstructorSaveState::nsFrameConstructorSaveState()
01514   : mItems(nsnull),
01515     mFirstLetterStyle(nsnull),
01516     mFirstLineStyle(nsnull),
01517     mSavedItems(nsnull),
01518     mSavedFirstLetterStyle(PR_FALSE),
01519     mSavedFirstLineStyle(PR_FALSE),
01520     mChildListName(nsnull),
01521     mState(nsnull)
01522 {
01523 }
01524 
01525 nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
01526 {
01527   // Restore the state
01528   if (mItems) {
01529     NS_ASSERTION(mState, "Can't have mItems set without having a state!");
01530     mState->ProcessFrameInsertions(*mItems, mChildListName);
01531     *mItems = mSavedItems;
01532 #ifdef DEBUG
01533     // We've transferred the child list, so drop the pointer we held to it.
01534     // Note that this only matters for the assert in ~nsAbsoluteItems.
01535     mSavedItems.childList = nsnull;
01536 #endif
01537   }
01538   if (mFirstLetterStyle) {
01539     *mFirstLetterStyle = mSavedFirstLetterStyle;
01540   }
01541   if (mFirstLineStyle) {
01542     *mFirstLineStyle = mSavedFirstLineStyle;
01543   }
01544 }
01545 
01546 nsFrameConstructorInsertionState::nsFrameConstructorInsertionState()
01547   : mAnonymousCreator(nsnull),
01548     mInsertionContent(nsnull),
01549     mCreatorIsBlock(PR_FALSE),
01550     mState(nsnull)
01551 {
01552 }
01553 
01554 nsFrameConstructorInsertionState::~nsFrameConstructorInsertionState()
01555 {
01556   // Restore the state
01557   if (mState) {
01558     mState->mAnonymousCreator = mAnonymousCreator;
01559     mState->mInsertionContent = mInsertionContent;
01560     mState->mCreatorIsBlock = mCreatorIsBlock;
01561   }
01562 }
01563 
01564 // Putting this up here to help inlining work on compilers that won't inline
01565 // definitions that are after the call site.
01566 inline nsresult
01567 nsCSSFrameConstructor::CreateInsertionPointChildren(nsFrameConstructorState &aState,
01568                                                     nsIFrame *aNewFrame,
01569                                                     nsIContent *aContent,
01570                                                     PRBool aUseInsertionFrame)
01571 {
01572   if (aState.mInsertionContent == aContent)
01573     return CreateInsertionPointChildren(aState, aNewFrame, aUseInsertionFrame);
01574 
01575   return NS_OK;
01576 }
01577 
01578 static 
01579 PRBool IsBorderCollapse(nsIFrame* aFrame)
01580 {
01581   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
01582     if (nsLayoutAtoms::tableFrame == frame->GetType()) {
01583       return ((nsTableFrame*)frame)->IsBorderCollapse();
01584     }
01585   }
01586   NS_ASSERTION(PR_FALSE, "program error");
01587   return PR_FALSE;
01588 }
01589 
01597 static void
01598 AdjustFloatParentPtrs(nsIFrame*                aFrame,
01599                       nsFrameConstructorState& aState,
01600                       nsFrameConstructorState& aOuterState)
01601 {
01602   NS_PRECONDITION(aFrame, "must have frame to work with");
01603 
01604   nsIFrame *outOfFlowFrame = nsPlaceholderFrame::GetRealFrameFor(aFrame);
01605   if (outOfFlowFrame != aFrame) {
01606     if (outOfFlowFrame->GetStyleDisplay()->IsFloating()) {
01607       // Update the parent pointer for outOfFlowFrame since its
01608       // containing block has changed as the result of reparenting
01609       // and move it from the outer state to the inner, bug 307277.
01610       
01611       nsIFrame *parent = aState.mFloatedItems.containingBlock;
01612       NS_ASSERTION(parent, "Should have float containing block here!");
01613       NS_ASSERTION(outOfFlowFrame->GetParent() == aOuterState.mFloatedItems.containingBlock,
01614                    "expected the float to be a child of the outer CB");
01615 
01616       if (aOuterState.mFloatedItems.RemoveChild(outOfFlowFrame)) {
01617         aState.mFloatedItems.AddChild(outOfFlowFrame);
01618       } else {
01619         NS_NOTREACHED("float wasn't in the outer state float list");
01620       }
01621 
01622       outOfFlowFrame->SetParent(parent);
01623       if (outOfFlowFrame->GetStateBits() &
01624           (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW)) {
01625         // We don't need to walk up the tree, since each level of
01626         // recursion of the SplitToContainingBlock will propagate the bit.
01627         parent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
01628       }
01629     }
01630 
01631     // All out-of-flows are automatically float containing blocks, so we're
01632     // done here.
01633     return;
01634   }
01635 
01636   if (aFrame->IsFloatContainingBlock()) {
01637     // No need to recurse further; floats whose placeholders are
01638     // inside a block already have the right parent.
01639     return;
01640   }
01641 
01642   // Dive down into children to see if any of their
01643   // placeholders need adjusting.
01644   nsIFrame *childFrame = aFrame->GetFirstChild(nsnull);
01645   while (childFrame) {
01646     // XXX_kin: Do we need to prevent descent into anonymous content here?
01647 
01648     AdjustFloatParentPtrs(childFrame, aState, aOuterState);
01649     childFrame = childFrame->GetNextSibling();
01650   }
01651 }
01652 
01660 static void
01661 MoveChildrenTo(nsFrameManager*          aFrameManager,
01662                nsStyleContext*          aNewParentSC,
01663                nsIFrame*                aNewParent,
01664                nsIFrame*                aFrameList,
01665                nsFrameConstructorState* aState,
01666                nsFrameConstructorState* aOuterState)
01667 {
01668   PRBool setHasChildWithView = PR_FALSE;
01669 
01670   while (aFrameList) {
01671     if (!setHasChildWithView
01672         && (aFrameList->GetStateBits() & (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW))) {
01673       setHasChildWithView = PR_TRUE;
01674     }
01675 
01676     aFrameList->SetParent(aNewParent);
01677 
01678     // If aState is not null, the caller expects us to make adjustments so that
01679     // floats whose placeholders are descendants of frames in aFrameList point
01680     // to the correct parent.
01681     if (aState) {
01682       NS_ASSERTION(aOuterState, "need an outer state too");
01683       AdjustFloatParentPtrs(aFrameList, *aState, *aOuterState);
01684     }
01685 
01686 #if 0
01687     // XXX When this is used with {ib} frame hierarchies, it seems
01688     // fine to leave the style contexts of the children of the
01689     // anonymous block frame parented by the original inline
01690     // frame. (In fact, one would expect some inheritance
01691     // relationships to be broken if we reparented them to the
01692     // anonymous block frame, but oddly they aren't -- need to
01693     // investigate that...)
01694     if (aNewParentSC)
01695       aPresContext->FrameManager()->ReParentStyleContext(aFrameList);
01696 #endif
01697 
01698     aFrameList = aFrameList->GetNextSibling();
01699   }
01700 
01701   if (setHasChildWithView) {
01702     aNewParent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
01703   }
01704 }
01705 
01706 // -----------------------------------------------------------
01707 
01708 // Structure used when creating table frames.
01709 struct nsTableCreator {
01710   virtual nsresult CreateTableOuterFrame(nsIFrame** aNewFrame);
01711   virtual nsresult CreateTableFrame(nsIFrame** aNewFrame);
01712   virtual nsresult CreateTableCaptionFrame(nsIFrame** aNewFrame);
01713   virtual nsresult CreateTableRowGroupFrame(nsIFrame** aNewFrame);
01714   virtual nsresult CreateTableColFrame(nsIFrame** aNewFrame);
01715   virtual nsresult CreateTableColGroupFrame(nsIFrame** aNewFrame);
01716   virtual nsresult CreateTableRowFrame(nsIFrame** aNewFrame);
01717   virtual nsresult CreateTableCellFrame(nsIFrame* aParentFrame, nsIFrame** aNewFrame);
01718   virtual nsresult CreateTableCellInnerFrame(nsIFrame** aNewFrame);
01719 
01720   nsTableCreator(nsIPresShell* aPresShell)
01721   {
01722     mPresShell = aPresShell;
01723   }
01724 
01725   virtual ~nsTableCreator() {};
01726 
01727   nsIPresShell* mPresShell;
01728 };
01729 
01730 nsresult
01731 nsTableCreator::CreateTableOuterFrame(nsIFrame** aNewFrame) {
01732   return NS_NewTableOuterFrame(mPresShell, aNewFrame);
01733 }
01734 
01735 nsresult
01736 nsTableCreator::CreateTableFrame(nsIFrame** aNewFrame) {
01737   return NS_NewTableFrame(mPresShell, aNewFrame);
01738 }
01739 
01740 nsresult
01741 nsTableCreator::CreateTableCaptionFrame(nsIFrame** aNewFrame) {
01742   return NS_NewTableCaptionFrame(mPresShell, aNewFrame);
01743 }
01744 
01745 nsresult
01746 nsTableCreator::CreateTableRowGroupFrame(nsIFrame** aNewFrame) {
01747   return NS_NewTableRowGroupFrame(mPresShell, aNewFrame);
01748 }
01749 
01750 nsresult
01751 nsTableCreator::CreateTableColFrame(nsIFrame** aNewFrame) {
01752   return NS_NewTableColFrame(mPresShell, aNewFrame);
01753 }
01754 
01755 nsresult
01756 nsTableCreator::CreateTableColGroupFrame(nsIFrame** aNewFrame) {
01757   return NS_NewTableColGroupFrame(mPresShell, aNewFrame);
01758 }
01759 
01760 nsresult
01761 nsTableCreator::CreateTableRowFrame(nsIFrame** aNewFrame) {
01762   return NS_NewTableRowFrame(mPresShell, aNewFrame);
01763 }
01764 
01765 nsresult
01766 nsTableCreator::CreateTableCellFrame(nsIFrame*  aParentFrame,
01767                                      nsIFrame** aNewFrame) {
01768   return NS_NewTableCellFrame(mPresShell, IsBorderCollapse(aParentFrame), aNewFrame);
01769 }
01770 
01771 nsresult
01772 nsTableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame) {
01773   return NS_NewTableCellInnerFrame(mPresShell, aNewFrame);
01774 }
01775 
01776 //MathML Mod - RBS
01777 #ifdef MOZ_MATHML
01778 
01779 // Structure used when creating MathML mtable frames
01780 struct nsMathMLmtableCreator: public nsTableCreator {
01781   virtual nsresult CreateTableOuterFrame(nsIFrame** aNewFrame);
01782   virtual nsresult CreateTableFrame(nsIFrame** aNewFrame);
01783   virtual nsresult CreateTableRowFrame(nsIFrame** aNewFrame);
01784   virtual nsresult CreateTableCellFrame(nsIFrame* aParentFrame, nsIFrame** aNewFrame);
01785   virtual nsresult CreateTableCellInnerFrame(nsIFrame** aNewFrame);
01786 
01787   nsMathMLmtableCreator(nsIPresShell* aPresShell)
01788     :nsTableCreator(aPresShell) {};
01789 };
01790 
01791 nsresult
01792 nsMathMLmtableCreator::CreateTableOuterFrame(nsIFrame** aNewFrame)
01793 {
01794   return NS_NewMathMLmtableOuterFrame(mPresShell, aNewFrame);
01795 }
01796 
01797 nsresult
01798 nsMathMLmtableCreator::CreateTableFrame(nsIFrame** aNewFrame)
01799 {
01800   return NS_NewMathMLmtableFrame(mPresShell, aNewFrame);
01801 }
01802 
01803 nsresult
01804 nsMathMLmtableCreator::CreateTableRowFrame(nsIFrame** aNewFrame)
01805 {
01806   return NS_NewMathMLmtrFrame(mPresShell, aNewFrame);
01807 }
01808 
01809 nsresult
01810 nsMathMLmtableCreator::CreateTableCellFrame(nsIFrame*  aParentFrame,
01811                                             nsIFrame** aNewFrame)
01812 {
01813   if (IsBorderCollapse(aParentFrame))
01814     return NS_NewTableCellFrame(mPresShell, PR_TRUE, aNewFrame);
01815 
01816   return NS_NewMathMLmtdFrame(mPresShell, aNewFrame);
01817 }
01818 
01819 nsresult
01820 nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame)
01821 {
01822   // only works if aNewFrame can take care of the lineLayout logic
01823   return NS_NewMathMLmtdInnerFrame(mPresShell, aNewFrame);
01824 }
01825 #endif // MOZ_MATHML
01826 
01827 // Structure used to ensure that bindings are properly enqueued in the
01828 // binding manager's attached queue.
01829 struct nsAutoEnqueueBinding
01830 {
01831   nsAutoEnqueueBinding(nsIDocument* aDocument) :
01832     mDocument(aDocument)
01833   {}
01834 
01835   ~nsAutoEnqueueBinding();
01836 
01837   nsRefPtr<nsXBLBinding> mBinding;
01838 private:
01839   nsIDocument* mDocument;
01840 };
01841 
01842 nsAutoEnqueueBinding::~nsAutoEnqueueBinding()
01843 {
01844   if (mBinding) {
01845     mDocument->BindingManager()->AddToAttachedQueue(mBinding);
01846   }
01847 }
01848 
01855 static PRBool
01856 GetCaptionAdjustedParent(nsIFrame*        aParentFrame,
01857                          const nsIFrame*  aChildFrame,
01858                          nsIFrame**       aAdjParentFrame)
01859 {
01860   *aAdjParentFrame = aParentFrame;
01861   PRBool haveCaption = PR_FALSE;
01862 
01863   if (nsLayoutAtoms::tableCaptionFrame == aChildFrame->GetType()) {
01864     haveCaption = PR_TRUE;
01865     if (nsLayoutAtoms::tableFrame == aParentFrame->GetType()) {
01866       *aAdjParentFrame = aParentFrame->GetParent();
01867     }
01868   }
01869   return haveCaption;
01870 }
01871 
01872 // Helper function that determines the child list name that aChildFrame
01873 // is contained in
01874 static void
01875 GetChildListNameFor(nsIFrame*       aParentFrame,
01876                     nsIFrame*       aChildFrame,
01877                     nsIAtom**       aListName)
01878 {
01879   nsIAtom*      listName;
01880   
01881   // See if the frame is moved out of the flow
01882   if (aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
01883     // Look at the style information to tell
01884     const nsStyleDisplay* disp = aChildFrame->GetStyleDisplay();
01885     
01886     if (NS_STYLE_POSITION_ABSOLUTE == disp->mPosition) {
01887       listName = nsLayoutAtoms::absoluteList;
01888     } else if (NS_STYLE_POSITION_FIXED == disp->mPosition) {
01889       listName = nsLayoutAtoms::fixedList;
01890     } else {
01891       NS_ASSERTION(aChildFrame->GetStyleDisplay()->IsFloating(),
01892                    "not a floated frame");
01893       listName = nsLayoutAtoms::floatList;
01894     }
01895 
01896   } else {
01897     listName = nsnull;
01898   }
01899 
01900   // Verify that the frame is actually in that child list
01901   NS_ASSERTION(nsFrameList(aParentFrame->GetFirstChild(listName))
01902                .ContainsFrame(aChildFrame), "not in child list");
01903 
01904   NS_IF_ADDREF(listName);
01905   *aListName = listName;
01906 }
01907 
01908 //----------------------------------------------------------------------
01909 
01910 nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
01911                                              nsIPresShell *aPresShell)
01912   : mDocument(aDocument)
01913   , mPresShell(aPresShell)
01914   , mInitialContainingBlock(nsnull)
01915   , mFixedContainingBlock(nsnull)
01916   , mDocElementContainingBlock(nsnull)
01917   , mGfxScrollFrame(nsnull)
01918   , mPageSequenceFrame(nsnull)
01919   , mUpdateCount(0)
01920   , mQuotesDirty(PR_FALSE)
01921   , mCountersDirty(PR_FALSE)
01922   , mInitialContainingBlockIsAbsPosContainer(PR_FALSE)
01923   , mIsDestroyingFrameTree(PR_FALSE)
01924 {
01925   if (!gGotXBLFormPrefs) {
01926     gGotXBLFormPrefs = PR_TRUE;
01927 
01928     gUseXBLForms =
01929       nsContentUtils::GetBoolPref("nglayout.debug.enable_xbl_forms");
01930   }
01931 
01932   // XXXbz this should be in Init() or something!
01933   if (!mPendingRestyles.Init()) {
01934     // now what?
01935   }
01936 
01937   // XXXbz this should be in Init() or something!
01938   mEventQueueService = do_GetService(kEventQueueServiceCID);
01939   
01940 #ifdef DEBUG
01941   static PRBool gFirstTime = PR_TRUE;
01942   if (gFirstTime) {
01943     gFirstTime = PR_FALSE;
01944     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
01945     if (flags) {
01946       PRBool error = PR_FALSE;
01947       for (;;) {
01948         char* comma = PL_strchr(flags, ',');
01949         if (comma)
01950           *comma = '\0';
01951 
01952         PRBool found = PR_FALSE;
01953         FrameCtorDebugFlags* flag = gFlags;
01954         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
01955         while (flag < limit) {
01956           if (PL_strcasecmp(flag->name, flags) == 0) {
01957             *(flag->on) = PR_TRUE;
01958             printf("nsCSSFrameConstructor: setting %s debug flag on\n", flag->name);
01959             found = PR_TRUE;
01960             break;
01961           }
01962           ++flag;
01963         }
01964 
01965         if (! found)
01966           error = PR_TRUE;
01967 
01968         if (! comma)
01969           break;
01970 
01971         *comma = ',';
01972         flags = comma + 1;
01973       }
01974 
01975       if (error) {
01976         printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
01977         FrameCtorDebugFlags* flag = gFlags;
01978         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
01979         while (flag < limit) {
01980           printf("  %s\n", flag->name);
01981           ++flag;
01982         }
01983         printf("Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of flag\n");
01984         printf("names (no whitespace)\n");
01985       }
01986     }
01987   }
01988 #endif
01989 }
01990 
01991 nsIXBLService * nsCSSFrameConstructor::GetXBLService()
01992 {
01993   if (!gXBLService) {
01994     nsresult rv = CallGetService("@mozilla.org/xbl;1", &gXBLService);
01995     if (NS_FAILED(rv))
01996       gXBLService = nsnull;
01997   }
01998   
01999   return gXBLService;
02000 }
02001 
02002 void
02003 nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame)
02004 {
02005   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
02006     if (mQuoteList.DestroyNodesFor(aFrame))
02007       QuotesDirty();
02008   }
02009 
02010   if (mCounterManager.DestroyNodesFor(aFrame)) {
02011     // Technically we don't need to update anything if we destroyed only
02012     // USE nodes.  However, this is unlikely to happen in the real world
02013     // since USE nodes generally go along with INCREMENT nodes.
02014     CountersDirty();
02015   }
02016 }
02017 
02018 nsresult
02019 nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame*             aParentFrame,
02020                                                nsIContent*           aContent,
02021                                                nsStyleContext*       aStyleContext,
02022                                                const nsStyleContent* aStyleContent,
02023                                                PRUint32              aContentIndex,
02024                                                nsIFrame**            aFrame)
02025 {
02026   *aFrame = nsnull;  // initialize OUT parameter
02027 
02028   // The QuoteList needs the content attached to the frame.
02029   nsCOMPtr<nsIDOMCharacterData>* textPtr = nsnull;
02030 
02031   // Get the content value
02032   const nsStyleContentData &data = aStyleContent->ContentAt(aContentIndex);
02033   nsStyleContentType  type = data.mType;
02034 
02035   nsCOMPtr<nsIContent> content;
02036   nsPresContext* presContext = mPresShell->GetPresContext();
02037 
02038   if (eStyleContentType_Image == type) {
02039     if (!data.mContent.mImage) {
02040       // CSS had something specified that couldn't be converted to an
02041       // image object
02042       *aFrame = nsnull;
02043       return NS_ERROR_FAILURE;
02044     }
02045     
02046     // Create an image content object and pass it the image request.
02047     // XXX Check if it's an image type we can handle...
02048 
02049     nsCOMPtr<nsINodeInfo> nodeInfo;
02050     mDocument->NodeInfoManager()->GetNodeInfo(nsHTMLAtoms::img, nsnull,
02051                                               kNameSpaceID_None,
02052                                               getter_AddRefs(nodeInfo));
02053 
02054     nsresult rv = NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo,
02055                                            data.mContent.mImage);
02056     NS_ENSURE_SUCCESS(rv, rv);
02057 
02058     // Set aContent as the parent content and set the document object. This
02059     // way event handling works
02060     // Hack the binding parent to make document rules not match (not
02061     // like it matters, since we already have a non-element style
02062     // context... which is totally wacky, but anyway).
02063     rv = content->BindToTree(mDocument, aContent, content, PR_TRUE);
02064     if (NS_FAILED(rv)) {
02065       content->UnbindFromTree();
02066       return rv;
02067     }
02068     
02069     content->SetNativeAnonymous(PR_TRUE);
02070   
02071     // Create an image frame and initialize it
02072     nsIFrame* imageFrame = nsnull;
02073     rv = NS_NewImageFrame(mPresShell, &imageFrame);
02074     if (!imageFrame) {
02075       return rv;
02076     }
02077 
02078     rv = imageFrame->Init(presContext, content, aParentFrame, aStyleContext,
02079                           nsnull);
02080     if (NS_FAILED(rv)) {
02081       imageFrame->Destroy(presContext);
02082       return rv == NS_ERROR_FRAME_REPLACED ? NS_OK : rv;
02083     }
02084 
02085     // Return the image frame
02086     *aFrame = imageFrame;
02087 
02088   } else {
02089 
02090     nsAutoString contentString;
02091 
02092     switch (type) {
02093     case eStyleContentType_String:
02094       contentString = data.mContent.mString;
02095       break;
02096   
02097     case eStyleContentType_Attr:
02098       {
02099         nsCOMPtr<nsIAtom> attrName;
02100         PRInt32 attrNameSpace = kNameSpaceID_None;
02101         contentString = data.mContent.mString;
02102         PRInt32 barIndex = contentString.FindChar('|'); // CSS namespace delimiter
02103         if (-1 != barIndex) {
02104           nsAutoString  nameSpaceVal;
02105           contentString.Left(nameSpaceVal, barIndex);
02106           PRInt32 error;
02107           attrNameSpace = nameSpaceVal.ToInteger(&error, 10);
02108           contentString.Cut(0, barIndex + 1);
02109           if (contentString.Length()) {
02110             attrName = do_GetAtom(contentString);
02111           }
02112         }
02113         else {
02114           attrName = do_GetAtom(contentString);
02115         }
02116 
02117         if (!attrName) {
02118           return NS_ERROR_OUT_OF_MEMORY;
02119         }
02120 
02121         // Creates the content and frame and return if successful
02122         nsresult rv = NS_ERROR_FAILURE;
02123         if (attrName) {
02124           nsIFrame*   textFrame = nsnull;
02125           rv = NS_NewAttributeContent(mDocument->NodeInfoManager(),
02126                                       attrNameSpace, attrName,
02127                                       getter_AddRefs(content));
02128           NS_ENSURE_SUCCESS(rv, rv);
02129 
02130           // Set aContent as the parent content so that event handling works.
02131           rv = content->BindToTree(mDocument, aContent, content, PR_TRUE);
02132           if (NS_FAILED(rv)) {
02133             content->UnbindFromTree();
02134             return rv;
02135           }
02136 
02137           content->SetNativeAnonymous(PR_TRUE);
02138 
02139           // Create a text frame and initialize it
02140           NS_NewTextFrame(mPresShell, &textFrame);
02141           textFrame->Init(presContext, content, aParentFrame, aStyleContext,
02142                           nsnull);
02143 
02144           // Return the text frame
02145           *aFrame = textFrame;
02146           rv = NS_OK;
02147         }
02148       }
02149       break;
02150   
02151     case eStyleContentType_Counter:
02152     case eStyleContentType_Counters:
02153       {
02154         nsCSSValue::Array *counters = data.mContent.mCounters;
02155         nsCounterList *counterList = mCounterManager.CounterListFor(
02156             nsDependentString(counters->Item(0).GetStringBufferValue()));
02157         if (!counterList)
02158             return NS_ERROR_OUT_OF_MEMORY;
02159 
02160         nsCounterUseNode* node =
02161           new nsCounterUseNode(counters, aParentFrame, aContentIndex,
02162                                type == eStyleContentType_Counters);
02163         if (!node)
02164           return NS_ERROR_OUT_OF_MEMORY;
02165 
02166         counterList->Insert(node);
02167         PRBool dirty = counterList->IsDirty();
02168         if (!dirty) {
02169           if (counterList->IsLast(node)) {
02170             node->Calc(counterList);
02171             node->GetText(contentString);
02172           }
02173           // In all other cases (list already dirty or node not at the end),
02174           // just start with an empty string for now and when we recalculate
02175           // the list we'll change the value to the right one.
02176           else {
02177             counterList->SetDirty();
02178             CountersDirty();
02179           }
02180         }
02181 
02182         textPtr = &node->mText; // text node assigned below
02183       }
02184       break;
02185 
02186     case eStyleContentType_Image:
02187       NS_NOTREACHED("handled by if above");
02188       return NS_ERROR_UNEXPECTED;
02189   
02190     case eStyleContentType_OpenQuote:
02191     case eStyleContentType_CloseQuote:
02192     case eStyleContentType_NoOpenQuote:
02193     case eStyleContentType_NoCloseQuote:
02194       {
02195         nsQuoteNode* node = new nsQuoteNode(type, aParentFrame, aContentIndex);
02196         if (!node)
02197           return NS_ERROR_OUT_OF_MEMORY;
02198         mQuoteList.Insert(node);
02199         if (mQuoteList.IsLast(node))
02200           mQuoteList.Calc(node);
02201         else
02202           QuotesDirty();
02203 
02204         // Don't generate a text node or any text for 'no-open-quote' and
02205         // 'no-close-quote'.
02206         if (node->IsHiddenQuote())
02207           return NS_OK;
02208 
02209         textPtr = &node->mText; // text node assigned below
02210         contentString = *node->Text();
02211       }
02212       break;
02213   
02214     } // switch
02215   
02216 
02217     if (!content) {
02218       // Create a text content node
02219       nsIFrame* textFrame = nsnull;
02220       nsCOMPtr<nsITextContent> textContent;
02221       NS_NewTextNode(getter_AddRefs(textContent),
02222                      mDocument->NodeInfoManager());
02223       if (textContent) {
02224         // Set the text
02225         textContent->SetText(contentString, PR_TRUE);
02226 
02227         if (textPtr) {
02228           *textPtr = do_QueryInterface(textContent);
02229           NS_ASSERTION(*textPtr, "must implement nsIDOMCharacterData");
02230         }
02231 
02232         // Set aContent as the parent content so that event handling works.
02233         nsresult rv = textContent->BindToTree(mDocument, aContent, textContent,
02234                                               PR_TRUE);
02235         if (NS_FAILED(rv)) {
02236           textContent->UnbindFromTree();
02237           return rv;
02238         }
02239 
02240         textContent->SetNativeAnonymous(PR_TRUE);
02241 
02242         // Create a text frame and initialize it
02243         NS_NewTextFrame(mPresShell, &textFrame);
02244         if (!textFrame) {
02245           // XXX The quotes/counters code doesn't like the text pointer
02246           // being null in case of dynamic changes!
02247           NS_NOTREACHED("this OOM case isn't handled very well");
02248           return NS_ERROR_OUT_OF_MEMORY;
02249         }
02250 
02251         textFrame->Init(presContext, textContent, aParentFrame, aStyleContext,
02252                         nsnull);
02253 
02254         content = textContent;
02255       } else {
02256         // XXX The quotes/counters code doesn't like the text pointer
02257         // being null in case of dynamic changes!
02258         NS_NOTREACHED("this OOM case isn't handled very well");
02259       }
02260 
02261       // Return the text frame
02262       *aFrame = textFrame;
02263     }
02264   }
02265 
02266   if (content) {
02267     nsCOMPtr<nsISupportsArray> anonymousItems;
02268     nsresult rv = NS_NewISupportsArray(getter_AddRefs(anonymousItems));
02269     NS_ENSURE_SUCCESS(rv, rv);
02270 
02271     anonymousItems->AppendElement(content);
02272 
02273     mPresShell->SetAnonymousContentFor(aContent, anonymousItems);
02274   }
02275 
02276   return NS_OK;
02277 }
02278 
02279 /*
02280  *
02281  * aFrame - the frame that should be the parent of the generated
02282  *   content.  This is the frame for the corresponding content node,
02283  *   which must not be a leaf frame.
02284  */
02285 PRBool
02286 nsCSSFrameConstructor::CreateGeneratedContentFrame(nsFrameConstructorState& aState,
02287                                                    nsIFrame*        aFrame,
02288                                                    nsIContent*      aContent,
02289                                                    nsStyleContext*  aStyleContext,
02290                                                    nsIAtom*         aPseudoElement,
02291                                                    nsIFrame**       aResult)
02292 {
02293   *aResult = nsnull; // initialize OUT parameter
02294 
02295   if (!aContent->IsContentOfType(nsIContent::eELEMENT))
02296     return PR_FALSE;
02297 
02298   nsStyleSet *styleSet = mPresShell->StyleSet();
02299 
02300   // Probe for the existence of the pseudo-element
02301   nsRefPtr<nsStyleContext> pseudoStyleContext;
02302   pseudoStyleContext = styleSet->ProbePseudoStyleFor(aContent,
02303                                                      aPseudoElement,
02304                                                      aStyleContext);
02305 
02306   if (pseudoStyleContext) {
02307     // |ProbePseudoStyleContext| checks the 'display' property and the
02308     // |ContentCount()| of the 'content' property for us.
02309 
02310     // Create a block box or an inline box depending on the value of
02311     // the 'display' property
02312     nsIFrame*     containerFrame;
02313     nsFrameItems  childFrames;
02314 
02315     if (NS_STYLE_DISPLAY_BLOCK ==
02316         pseudoStyleContext->GetStyleDisplay()->mDisplay) {
02317       NS_NewBlockFrame(mPresShell, &containerFrame);
02318     } else {
02319       NS_NewInlineFrame(mPresShell, &containerFrame);
02320     }        
02321     InitAndRestoreFrame(aState, aContent, aFrame, pseudoStyleContext, nsnull,
02322                         containerFrame);
02323     // XXXbz should we be passing in a non-null aContentParentFrame?
02324     nsHTMLContainerFrame::CreateViewForFrame(containerFrame, nsnull, PR_FALSE);
02325 
02326     // Mark the frame as being associated with generated content
02327     containerFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
02328 
02329     // Create another pseudo style context to use for all the generated child
02330     // frames
02331     nsRefPtr<nsStyleContext> textStyleContext;
02332     textStyleContext = styleSet->ResolveStyleForNonElement(pseudoStyleContext);
02333 
02334     // Now create content objects (and child frames) for each value of the
02335     // 'content' property
02336 
02337     const nsStyleContent* styleContent = pseudoStyleContext->GetStyleContent();
02338     PRUint32 contentCount = styleContent->ContentCount();
02339     for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) {
02340       nsIFrame* frame;
02341 
02342       // Create a frame
02343       nsresult result;
02344       result = CreateGeneratedFrameFor(containerFrame,
02345                                        aContent, textStyleContext,
02346                                        styleContent, contentIndex, &frame);
02347       // Non-elements can't possibly have a view, so don't bother checking
02348       if (NS_SUCCEEDED(result) && frame) {
02349         // Add it to the list of child frames
02350         childFrames.AddChild(frame);
02351       }
02352     }
02353 
02354     if (childFrames.childList) {
02355       containerFrame->SetInitialChildList(aState.mPresContext, nsnull, childFrames.childList);
02356     }
02357     *aResult = containerFrame;
02358     return PR_TRUE;
02359   }
02360 
02361   return PR_FALSE;
02362 }
02363 
02364 nsresult
02365 nsCSSFrameConstructor::CreateInputFrame(nsIContent      *aContent,
02366                                         nsIFrame        **aFrame,
02367                                         nsStyleContext  *aStyleContext)
02368 {
02369   nsCOMPtr<nsIFormControl> control = do_QueryInterface(aContent);
02370   NS_ASSERTION(control, "input is not an nsIFormControl!");
02371   
02372   switch (control->GetType()) {
02373     case NS_FORM_INPUT_SUBMIT:
02374     case NS_FORM_INPUT_RESET:
02375     case NS_FORM_INPUT_BUTTON:
02376       if (gUseXBLForms)
02377         return NS_OK; // upddate IsSpecialContent if this becomes functional
02378       return NS_NewGfxButtonControlFrame(mPresShell, aFrame);
02379 
02380     case NS_FORM_INPUT_CHECKBOX:
02381       if (gUseXBLForms)
02382         return NS_OK; // see comment above
02383       return ConstructCheckboxControlFrame(aFrame, aContent, aStyleContext);
02384 
02385     case NS_FORM_INPUT_RADIO:
02386       if (gUseXBLForms)
02387         return NS_OK; // see comment above
02388       return ConstructRadioControlFrame(aFrame, aContent, aStyleContext);
02389 
02390     case NS_FORM_INPUT_FILE:
02391     {
02392       nsresult rv = NS_NewFileControlFrame(mPresShell, aFrame);
02393       if (NS_SUCCEEDED(rv)) {
02394         // The (block-like) file control frame should have a space manager
02395         (*aFrame)->AddStateBits(NS_BLOCK_SPACE_MGR);
02396       }
02397       return rv;
02398     }
02399 
02400     case NS_FORM_INPUT_HIDDEN:
02401       return NS_OK; // this does not create a frame so it needs special handling
02402                     // in IsSpecialContent
02403 
02404     case NS_FORM_INPUT_IMAGE:
02405       return NS_NewImageControlFrame(mPresShell, aFrame);
02406 
02407     case NS_FORM_INPUT_TEXT:
02408     case NS_FORM_INPUT_PASSWORD:
02409       return NS_NewTextControlFrame(mPresShell, aFrame);
02410 
02411     default:
02412       NS_ASSERTION(0, "Unknown input type!");
02413       return NS_ERROR_INVALID_ARG;
02414   }
02415 }
02416 
02417 static PRBool
02418 IsOnlyWhitespace(nsIContent* aContent)
02419 {
02420   PRBool onlyWhiteSpace = PR_FALSE;
02421   if (aContent->IsContentOfType(nsIContent::eTEXT)) {
02422     nsCOMPtr<nsITextContent> textContent = do_QueryInterface(aContent);
02423 
02424     onlyWhiteSpace = textContent->IsOnlyWhitespace();
02425   }
02426 
02427   return onlyWhiteSpace;
02428 }
02429     
02430 /****************************************************
02431  **  BEGIN TABLE SECTION
02432  ****************************************************/
02433 
02434 // The term pseudo frame is being used instead of anonymous frame, since anonymous
02435 // frame has been used elsewhere to refer to frames that have generated content
02436 
02437 // aIncludeSpecial applies to captions, col groups, cols and cells.
02438 // These do not generate pseudo frame wrappers for foreign children. 
02439 
02440 static PRBool
02441 IsTableRelated(PRUint8 aDisplay,
02442                PRBool  aIncludeSpecial) 
02443 {
02444   if ((aDisplay == NS_STYLE_DISPLAY_TABLE)              ||
02445       (aDisplay == NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) ||
02446       (aDisplay == NS_STYLE_DISPLAY_TABLE_ROW_GROUP)    ||
02447       (aDisplay == NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) ||
02448       (aDisplay == NS_STYLE_DISPLAY_TABLE_ROW)) {
02449     return PR_TRUE;
02450   }
02451   else if (aIncludeSpecial && 
02452            ((aDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION)      ||
02453             (aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) ||
02454             (aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN)       ||
02455             (aDisplay == NS_STYLE_DISPLAY_TABLE_CELL))) {
02456     return PR_TRUE;
02457   }
02458   else return PR_FALSE;
02459 }
02460 
02461 static PRBool
02462 IsTableRelated(nsIAtom* aParentType,
02463                PRBool   aIncludeSpecial)
02464 {
02465   if ((nsLayoutAtoms::tableFrame         == aParentType)  ||
02466       (nsLayoutAtoms::tableRowGroupFrame == aParentType)  ||
02467       (nsLayoutAtoms::tableRowFrame      == aParentType)) {
02468     return PR_TRUE;
02469   }
02470   else if (aIncludeSpecial && 
02471            ((nsLayoutAtoms::tableCaptionFrame  == aParentType)  ||
02472             (nsLayoutAtoms::tableColGroupFrame == aParentType)  ||
02473             (nsLayoutAtoms::tableColFrame      == aParentType)  ||
02474             IS_TABLE_CELL(aParentType))) {
02475     return PR_TRUE;
02476   }
02477   else return PR_FALSE;
02478 }
02479            
02480 static nsIFrame*
02481 AdjustCaptionParentFrame(nsIFrame* aParentFrame) 
02482 {
02483   if (nsLayoutAtoms::tableFrame == aParentFrame->GetType()) {
02484     return aParentFrame->GetParent();;
02485   }
02486   return aParentFrame;
02487 }
02488     
02489 static nsresult 
02490 ProcessPseudoFrame(nsPresContext*    aPresContext,
02491                    nsPseudoFrameData& aPseudoData,
02492                    nsIFrame*&         aParent)
02493 {
02494   nsresult rv = NS_OK;
02495   if (!aPresContext) return rv;
02496 
02497   aParent = aPseudoData.mFrame;
02498   nsFrameItems* items = &aPseudoData.mChildList;
02499   if (items && items->childList) {
02500     rv = aParent->SetInitialChildList(aPresContext, nsnull, items->childList);
02501     if (NS_FAILED(rv)) return rv;
02502   }
02503   aPseudoData.Reset();
02504   return rv;
02505 }
02506 
02507 static nsresult 
02508 ProcessPseudoRowGroupFrame(nsPresContext*     aPresContext,
02509                            nsPseudoFrameData& aPseudoData,
02510                            nsIFrame*&         aParent)
02511 {
02512   nsresult rv = NS_OK;
02513   if (!aPresContext) return rv;
02514 
02515   aParent = aPseudoData.mFrame;
02516   nsFrameItems* items = &aPseudoData.mChildList;
02517   if (items && items->childList) {
02518     nsTableRowGroupFrame* rgFrame = nsTableFrame::GetRowGroupFrame(aParent);
02519     rv = rgFrame->SetInitialChildList(aPresContext, nsnull, items->childList);
02520     if (NS_FAILED(rv)) return rv;
02521   }
02522   aPseudoData.Reset();
02523   return rv;
02524 }
02525 
02526 static nsresult 
02527 ProcessPseudoTableFrame(nsPresContext* aPresContext,
02528                         nsPseudoFrames& aPseudoFrames,
02529                         nsIFrame*&      aParent)
02530 {
02531   nsresult rv = NS_OK;
02532   if (!aPresContext) return rv;
02533 
02534   // process the col group frame, if it exists
02535   if (aPseudoFrames.mColGroup.mFrame) {
02536     rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mColGroup, aParent);
02537   }
02538 
02539   // process the inner table frame
02540   rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mTableInner, aParent);
02541 
02542   // process the outer table frame
02543   aParent = aPseudoFrames.mTableOuter.mFrame;
02544   nsFrameItems* items = &aPseudoFrames.mTableOuter.mChildList;
02545   if (items && items->childList) {
02546     rv = aParent->SetInitialChildList(aPresContext, nsnull, items->childList);
02547     if (NS_FAILED(rv)) return rv;
02548   }
02549   nsFrameItems* captions = &aPseudoFrames.mTableOuter.mChildList2;
02550   if (captions && captions->childList) {
02551     rv = aParent->SetInitialChildList(aPresContext, nsLayoutAtoms::captionList, captions->childList);
02552   }
02553   aPseudoFrames.mTableOuter.Reset();
02554   return rv;
02555 }
02556 
02557 static nsresult 
02558 ProcessPseudoCellFrame(nsPresContext* aPresContext,
02559                        nsPseudoFrames& aPseudoFrames,
02560                        nsIFrame*&      aParent)
02561 {
02562   nsresult rv = NS_OK;
02563   if (!aPresContext) return rv;
02564 
02565   rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mCellInner, aParent);
02566   if (NS_FAILED(rv)) return rv;
02567   rv = ProcessPseudoFrame(aPresContext, aPseudoFrames.mCellOuter, aParent);
02568   return rv;
02569 }
02570 
02571 // limit the processing up to the frame type indicated by aHighestType.
02572 // make a complete processing when aHighestType is null
02573 static nsresult 
02574 ProcessPseudoFrames(nsFrameConstructorState& aState,
02575                     nsIAtom*        aHighestType,
02576                     nsIFrame*&      aHighestFrame)
02577 {
02578   nsresult rv = NS_OK;
02579 
02580   aHighestFrame = nsnull;
02581 
02582 #ifdef DEBUG
02583   if (gTablePseudoFrame) {
02584     printf("*** ProcessPseudoFrames enter***\n");
02585     aState.mPseudoFrames.Dump();
02586   }
02587 #endif
02588 
02589   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
02590   nsPresContext* presContext = aState.mPresContext;
02591 
02592   if (nsLayoutAtoms::tableFrame == pseudoFrames.mLowestType) {
02593     if (pseudoFrames.mColGroup.mFrame) {
02594        rv = ProcessPseudoFrame(presContext, pseudoFrames.mColGroup,
02595                               aHighestFrame);
02596       if (nsLayoutAtoms::tableColGroupFrame == aHighestType) return rv;
02597     }
02598     rv = ProcessPseudoTableFrame(presContext, pseudoFrames, aHighestFrame);
02599     if (nsLayoutAtoms::tableOuterFrame == aHighestType) return rv;
02600     
02601     if (pseudoFrames.mCellOuter.mFrame) {
02602       rv = ProcessPseudoCellFrame(presContext, pseudoFrames, aHighestFrame);
02603       if (IS_TABLE_CELL(aHighestType)) return rv;
02604     }
02605     if (pseudoFrames.mRow.mFrame) {
02606       rv = ProcessPseudoFrame(presContext, pseudoFrames.mRow, aHighestFrame);
02607       if (nsLayoutAtoms::tableRowFrame == aHighestType) return rv;
02608     }
02609     if (pseudoFrames.mRowGroup.mFrame) {
02610       rv = ProcessPseudoRowGroupFrame(presContext, pseudoFrames.mRowGroup, aHighestFrame);
02611       if (nsLayoutAtoms::tableRowGroupFrame == aHighestType) return rv;
02612     }
02613   }
02614   else if (nsLayoutAtoms::tableRowGroupFrame == pseudoFrames.mLowestType) {
02615     rv = ProcessPseudoRowGroupFrame(presContext, pseudoFrames.mRowGroup, aHighestFrame);
02616     if (nsLayoutAtoms::tableRowGroupFrame == aHighestType) return rv;
02617     if (pseudoFrames.mColGroup.mFrame) {
02618       nsIFrame* colGroupHigh;
02619       rv = ProcessPseudoFrame(presContext, pseudoFrames.mColGroup,
02620                               colGroupHigh);
02621       if (aHighestFrame &&
02622           nsLayoutAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
02623           !pseudoFrames.mTableInner.mFrame) {
02624         // table frames are special they can have two types of pseudo frames
02625         // that need to be processed in one pass, we only need to link them if
02626         // the parent is not a pseudo where the link is already done
02627         // We sort this later out inside nsTableFrame.
02628          colGroupHigh->SetNextSibling(aHighestFrame); 
02629       }
02630       aHighestFrame = colGroupHigh;
02631       if (nsLayoutAtoms::tableColGroupFrame == aHighestType) return rv;
02632     }
02633     if (pseudoFrames.mTableOuter.mFrame) {
02634       rv = ProcessPseudoTableFrame(presContext, pseudoFrames, aHighestFrame);
02635       if (nsLayoutAtoms::tableOuterFrame == aHighestType) return rv;
02636     }
02637     if (pseudoFrames.mCellOuter.mFrame) {
02638       rv = ProcessPseudoCellFrame(presContext, pseudoFrames, aHighestFrame);
02639       if (IS_TABLE_CELL(aHighestType)) return rv;
02640     }
02641     if (pseudoFrames.mRow.mFrame) {
02642       rv = ProcessPseudoFrame(presContext, pseudoFrames.mRow, aHighestFrame);
02643       if (nsLayoutAtoms::tableRowFrame == aHighestType) return rv;
02644     }
02645   }
02646   else if (nsLayoutAtoms::tableRowFrame == pseudoFrames.mLowestType) {
02647     rv = ProcessPseudoFrame(presContext, pseudoFrames.mRow, aHighestFrame);
02648     if (nsLayoutAtoms::tableRowFrame == aHighestType) return rv;
02649 
02650     if (pseudoFrames.mRowGroup.mFrame) {
02651       rv = ProcessPseudoRowGroupFrame(presContext, pseudoFrames.mRowGroup, aHighestFrame);
02652       if (nsLayoutAtoms::tableRowGroupFrame == aHighestType) return rv;
02653     }
02654     if (pseudoFrames.mColGroup.mFrame) {
02655       nsIFrame* colGroupHigh;
02656       rv = ProcessPseudoFrame(presContext, pseudoFrames.mColGroup,
02657                               colGroupHigh);
02658       if (aHighestFrame &&
02659           nsLayoutAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
02660           !pseudoFrames.mTableInner.mFrame) {
02661         // table frames are special they can have two types of pseudo frames
02662         // that need to be processed in one pass, we only need to link them if
02663         // the parent is not a pseudo where the link is already done
02664         // We sort this later out inside nsTableFrame.
02665          colGroupHigh->SetNextSibling(aHighestFrame); 
02666       }
02667       aHighestFrame = colGroupHigh;
02668       if (nsLayoutAtoms::tableColGroupFrame == aHighestType) return rv;
02669     }
02670     if (pseudoFrames.mTableOuter.mFrame) {
02671       rv = ProcessPseudoTableFrame(presContext, pseudoFrames, aHighestFrame);
02672       if (nsLayoutAtoms::tableOuterFrame == aHighestType) return rv;
02673     }
02674     if (pseudoFrames.mCellOuter.mFrame) {
02675       rv = ProcessPseudoCellFrame(presContext, pseudoFrames, aHighestFrame);
02676       if (IS_TABLE_CELL(aHighestType)) return rv;
02677     }
02678   }
02679   else if (IS_TABLE_CELL(pseudoFrames.mLowestType)) {
02680     rv = ProcessPseudoCellFrame(presContext, pseudoFrames, aHighestFrame);
02681     if (IS_TABLE_CELL(aHighestType)) return rv;
02682 
02683     if (pseudoFrames.mRow.mFrame) {
02684       rv = ProcessPseudoFrame(presContext, pseudoFrames.mRow, aHighestFrame);
02685       if (nsLayoutAtoms::tableRowFrame == aHighestType) return rv;
02686     }
02687     if (pseudoFrames.mRowGroup.mFrame) {
02688       rv = ProcessPseudoRowGroupFrame(presContext, pseudoFrames.mRowGroup, aHighestFrame);
02689       if (nsLayoutAtoms::tableRowGroupFrame == aHighestType) return rv;
02690     }
02691     if (pseudoFrames.mColGroup.mFrame) {
02692       nsIFrame* colGroupHigh;
02693       rv = ProcessPseudoFrame(presContext, pseudoFrames.mColGroup,
02694                               colGroupHigh);
02695       if (aHighestFrame &&
02696           nsLayoutAtoms::tableRowGroupFrame == aHighestFrame->GetType() &&
02697           !pseudoFrames.mTableInner.mFrame) {
02698         // table frames are special they can have two types of pseudo frames
02699         // that need to be processed in one pass, we only need to link them if
02700         // the parent is not a pseudo where the link is already done
02701         // We sort this later out inside nsTableFrame.
02702          colGroupHigh->SetNextSibling(aHighestFrame); 
02703       }
02704       aHighestFrame = colGroupHigh;
02705       if (nsLayoutAtoms::tableColGroupFrame == aHighestType) return rv;
02706     }
02707     if (pseudoFrames.mTableOuter.mFrame) {
02708       rv = ProcessPseudoTableFrame(presContext, pseudoFrames, aHighestFrame);
02709     }
02710   }
02711   else if (pseudoFrames.mColGroup.mFrame) { 
02712     // process the col group frame
02713     rv = ProcessPseudoFrame(presContext, pseudoFrames.mColGroup, aHighestFrame);
02714   }
02715 
02716   return rv;
02717 }
02718 
02719 static nsresult 
02720 ProcessPseudoFrames(nsFrameConstructorState& aState,
02721                     nsFrameItems&   aItems)
02722 {
02723 
02724 #ifdef DEBUG
02725   if (gTablePseudoFrame) {
02726     printf("*** ProcessPseudoFrames complete enter***\n");
02727     aState.mPseudoFrames.Dump();
02728   }
02729 #endif
02730  
02731   nsIFrame* highestFrame;
02732   nsresult rv = ProcessPseudoFrames(aState, nsnull, highestFrame);
02733   if (highestFrame) {
02734     aItems.AddChild(highestFrame);
02735   }
02736  
02737 #ifdef DEBUG
02738   if (gTablePseudoFrame) {
02739     printf("*** ProcessPseudoFrames complete leave, highestframe:%p***\n",
02740            NS_STATIC_CAST(void*, highestFrame));
02741     aState.mPseudoFrames.Dump();
02742   }
02743 #endif
02744   aState.mPseudoFrames.Reset();
02745   return rv;
02746 }
02747 
02748 static nsresult 
02749 ProcessPseudoFrames(nsFrameConstructorState& aState,
02750                     nsIAtom*        aHighestType)
02751 {
02752 #ifdef DEBUG
02753   if (gTablePseudoFrame) {
02754     printf("*** ProcessPseudoFrames limited enter highest:");
02755     if (nsLayoutAtoms::tableOuterFrame == aHighestType) 
02756       printf("OuterTable");
02757     else if (nsLayoutAtoms::tableFrame == aHighestType) 
02758       printf("InnerTable");
02759     else if (nsLayoutAtoms::tableColGroupFrame == aHighestType) 
02760       printf("ColGroup");
02761     else if (nsLayoutAtoms::tableRowGroupFrame == aHighestType) 
02762       printf("RowGroup");
02763     else if (nsLayoutAtoms::tableRowFrame == aHighestType) 
02764       printf("Row");
02765     else if (IS_TABLE_CELL(aHighestType)) 
02766       printf("Cell");
02767     else 
02768       NS_ASSERTION(PR_FALSE, "invalid call to ProcessPseudoFrames ");
02769     printf("***\n");
02770     aState.mPseudoFrames.Dump();
02771   }
02772 #endif
02773  
02774   nsIFrame* highestFrame;
02775   nsresult rv = ProcessPseudoFrames(aState, aHighestType, highestFrame);
02776 
02777 #ifdef DEBUG
02778   if (gTablePseudoFrame) {
02779     printf("*** ProcessPseudoFrames limited leave:%p***\n",
02780            NS_STATIC_CAST(void*, highestFrame));
02781     aState.mPseudoFrames.Dump();
02782   }
02783 #endif
02784   return rv;
02785 }
02786 
02787 nsresult
02788 nsCSSFrameConstructor::CreatePseudoTableFrame(nsTableCreator&          aTableCreator,
02789                                               nsFrameConstructorState& aState, 
02790                                               nsIFrame*                aParentFrameIn)
02791 {
02792   nsresult rv = NS_OK;
02793 
02794   nsIFrame* parentFrame = (aState.mPseudoFrames.mCellInner.mFrame) 
02795                           ? aState.mPseudoFrames.mCellInner.mFrame : aParentFrameIn;
02796   if (!parentFrame) return rv;
02797 
02798   nsStyleContext *parentStyle;
02799   nsRefPtr<nsStyleContext> childStyle;
02800 
02801   parentStyle = parentFrame->GetStyleContext(); 
02802   nsIContent* parentContent = parentFrame->GetContent();   
02803 
02804   // create the SC for the inner table which will be the parent of the outer table's SC
02805   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
02806                                                              nsCSSAnonBoxes::table,
02807                                                              parentStyle);
02808 
02809   nsPseudoFrameData& pseudoOuter = aState.mPseudoFrames.mTableOuter;
02810   nsPseudoFrameData& pseudoInner = aState.mPseudoFrames.mTableInner;
02811 
02812   // construct the pseudo outer and inner as part of the pseudo frames
02813   nsFrameItems items;
02814   rv = ConstructTableFrame(aState, parentContent,
02815                            parentFrame, childStyle, aTableCreator,
02816                            PR_TRUE, items, PR_TRUE, pseudoOuter.mFrame, 
02817                            pseudoInner.mFrame);
02818 
02819   if (NS_FAILED(rv)) return rv;
02820 
02821   // set pseudo data for the newly created frames
02822   pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
02823   aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableFrame;
02824 
02825   // set pseudo data for the parent
02826   if (aState.mPseudoFrames.mCellInner.mFrame) {
02827     aState.mPseudoFrames.mCellInner.mChildList.AddChild(pseudoOuter.mFrame);
02828   }
02829 #ifdef DEBUG
02830   if (gTablePseudoFrame) {
02831      printf("*** CreatePseudoTableFrame ***\n");
02832     aState.mPseudoFrames.Dump();
02833   }
02834 #endif
02835   return rv;
02836 }
02837 
02838 nsresult
02839 nsCSSFrameConstructor::CreatePseudoRowGroupFrame(nsTableCreator&          aTableCreator,
02840                                                  nsFrameConstructorState& aState, 
02841                                                  nsIFrame*                aParentFrameIn)
02842 {
02843   nsresult rv = NS_OK;
02844 
02845   nsIFrame* parentFrame = (aState.mPseudoFrames.mTableInner.mFrame) 
02846                           ? aState.mPseudoFrames.mTableInner.mFrame : aParentFrameIn;
02847   if (!parentFrame) return rv;
02848 
02849   nsStyleContext *parentStyle;
02850   nsRefPtr<nsStyleContext> childStyle;
02851 
02852   parentStyle = parentFrame->GetStyleContext();
02853   nsIContent* parentContent = parentFrame->GetContent();
02854 
02855   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
02856                                                              nsCSSAnonBoxes::tableRowGroup, 
02857                                                              parentStyle);
02858 
02859   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRowGroup;
02860 
02861   // construct the pseudo row group as part of the pseudo frames
02862   PRBool pseudoParent;
02863   nsFrameItems items;
02864   rv = ConstructTableRowGroupFrame(aState, parentContent,
02865                                    parentFrame, childStyle, aTableCreator,
02866                                    PR_TRUE, items, pseudo.mFrame, pseudoParent);
02867   if (NS_FAILED(rv)) return rv;
02868 
02869   // set pseudo data for the newly created frames
02870   aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableRowGroupFrame;
02871 
02872   // set pseudo data for the parent
02873   if (aState.mPseudoFrames.mTableInner.mFrame) {
02874     aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
02875   }
02876 #ifdef DEBUG
02877   if (gTablePseudoFrame) {
02878      printf("*** CreatePseudoRowGroupFrame ***\n");
02879     aState.mPseudoFrames.Dump();
02880   }
02881 #endif
02882   return rv;
02883 }
02884 
02885 nsresult 
02886 nsCSSFrameConstructor::CreatePseudoColGroupFrame(nsTableCreator&          aTableCreator,
02887                                                  nsFrameConstructorState& aState, 
02888                                                  nsIFrame*                aParentFrameIn)
02889 {
02890   nsresult rv = NS_OK;
02891 
02892   nsIFrame* parentFrame = (aState.mPseudoFrames.mTableInner.mFrame) 
02893                           ? aState.mPseudoFrames.mTableInner.mFrame : aParentFrameIn;
02894   if (!parentFrame) return rv;
02895 
02896   nsStyleContext *parentStyle;
02897   nsRefPtr<nsStyleContext> childStyle;
02898 
02899   parentStyle = parentFrame->GetStyleContext();
02900   nsIContent* parentContent = parentFrame->GetContent();
02901 
02902   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
02903                                                              nsCSSAnonBoxes::tableColGroup, 
02904                                                              parentStyle);
02905 
02906   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mColGroup;
02907 
02908   // construct the pseudo col group as part of the pseudo frames
02909   PRBool pseudoParent;
02910   nsFrameItems items;
02911   rv = ConstructTableColGroupFrame(aState, parentContent,
02912                                    parentFrame, childStyle, aTableCreator,
02913                                    PR_TRUE, items, pseudo.mFrame, pseudoParent);
02914   if (NS_FAILED(rv)) return rv;
02915   ((nsTableColGroupFrame*)pseudo.mFrame)->SetColType(eColGroupAnonymousCol);
02916 
02917   // Do not set  aState.mPseudoFrames.mLowestType here as colgroup frame will
02918   // be always below a table frame but we can not descent any further as col
02919   // frames can not have children and will not wrap table foreign frames.
02920 
02921   // set pseudo data for the parent
02922   if (aState.mPseudoFrames.mTableInner.mFrame) {
02923     aState.mPseudoFrames.mTableInner.mChildList.AddChild(pseudo.mFrame);
02924   }
02925 #ifdef DEBUG
02926   if (gTablePseudoFrame) {
02927      printf("*** CreatePseudoColGroupFrame ***\n");
02928     aState.mPseudoFrames.Dump();
02929   }
02930 #endif
02931   return rv;
02932 }
02933 
02934 nsresult
02935 nsCSSFrameConstructor::CreatePseudoRowFrame(nsTableCreator&          aTableCreator,
02936                                             nsFrameConstructorState& aState, 
02937                                             nsIFrame*                aParentFrameIn)
02938 {
02939   nsresult rv = NS_OK;
02940 
02941   nsIFrame* parentFrame = aParentFrameIn;
02942   if (aState.mPseudoFrames.mRowGroup.mFrame) {
02943     parentFrame = (nsIFrame*) nsTableFrame::GetRowGroupFrame(aState.mPseudoFrames.mRowGroup.mFrame);
02944   }
02945   if (!parentFrame) return rv;
02946 
02947   nsStyleContext *parentStyle;
02948   nsRefPtr<nsStyleContext> childStyle;
02949 
02950   parentStyle = parentFrame->GetStyleContext();
02951   nsIContent* parentContent = parentFrame->GetContent();
02952 
02953   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
02954                                                              nsCSSAnonBoxes::tableRow, 
02955                                                              parentStyle);
02956 
02957   nsPseudoFrameData& pseudo = aState.mPseudoFrames.mRow;
02958 
02959   // construct the pseudo row as part of the pseudo frames
02960   PRBool pseudoParent;
02961   nsFrameItems items;
02962   rv = ConstructTableRowFrame(aState, parentContent,
02963                               parentFrame, childStyle, aTableCreator,
02964                               PR_TRUE, items, pseudo.mFrame, pseudoParent);
02965   if (NS_FAILED(rv)) return rv;
02966 
02967   aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableRowFrame;
02968 
02969   // set pseudo data for the parent
02970   if (aState.mPseudoFrames.mRowGroup.mFrame) {
02971     aState.mPseudoFrames.mRowGroup.mChildList.AddChild(pseudo.mFrame);
02972   }
02973 #ifdef DEBUG
02974   if (gTablePseudoFrame) {
02975      printf("*** CreatePseudoRowFrame ***\n");
02976     aState.mPseudoFrames.Dump();
02977   }
02978 #endif
02979   return rv;
02980 }
02981 
02982 nsresult
02983 nsCSSFrameConstructor::CreatePseudoCellFrame(nsTableCreator&          aTableCreator,
02984                                              nsFrameConstructorState& aState, 
02985                                              nsIFrame*                aParentFrameIn)
02986 {
02987   nsresult rv = NS_OK;
02988 
02989   nsIFrame* parentFrame = (aState.mPseudoFrames.mRow.mFrame) 
02990                           ? aState.mPseudoFrames.mRow.mFrame : aParentFrameIn;
02991   if (!parentFrame) return rv;
02992 
02993   nsStyleContext *parentStyle;
02994   nsRefPtr<nsStyleContext> childStyle;
02995 
02996   parentStyle = parentFrame->GetStyleContext();
02997   nsIContent* parentContent = parentFrame->GetContent();
02998 
02999   childStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
03000                                                              nsCSSAnonBoxes::tableCell, 
03001                                                              parentStyle);
03002 
03003   nsPseudoFrameData& pseudoOuter = aState.mPseudoFrames.mCellOuter;
03004   nsPseudoFrameData& pseudoInner = aState.mPseudoFrames.mCellInner;
03005 
03006   // construct the pseudo outer and inner as part of the pseudo frames
03007   PRBool pseudoParent;
03008   nsFrameItems items;
03009   rv = ConstructTableCellFrame(aState, parentContent, parentFrame, childStyle,
03010                                aTableCreator, PR_TRUE, items,
03011                                pseudoOuter.mFrame, pseudoInner.mFrame,
03012                                pseudoParent);
03013   if (NS_FAILED(rv)) return rv;
03014 
03015   // set pseudo data for the newly created frames
03016   pseudoOuter.mChildList.AddChild(pseudoInner.mFrame);
03017   // give it nsLayoutAtoms::tableCellFrame, if it is really nsLayoutAtoms::bcTableCellFrame, it will match later
03018   aState.mPseudoFrames.mLowestType = nsLayoutAtoms::tableCellFrame;
03019 
03020   // set pseudo data for the parent
03021   if (aState.mPseudoFrames.mRow.mFrame) {
03022     aState.mPseudoFrames.mRow.mChildList.AddChild(pseudoOuter.mFrame);
03023   }
03024 #ifdef DEBUG
03025   if (gTablePseudoFrame) {
03026      printf("*** CreatePseudoCellFrame ***\n");
03027     aState.mPseudoFrames.Dump();
03028   }
03029 #endif
03030   return rv;
03031 }
03032 
03033 // called if the parent is not a table
03034 nsresult 
03035 nsCSSFrameConstructor::GetPseudoTableFrame(nsTableCreator&          aTableCreator,
03036                                            nsFrameConstructorState& aState, 
03037                                            nsIFrame&                aParentFrameIn)
03038 {
03039   nsresult rv = NS_OK;
03040 
03041   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03042   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03043 
03044   if (pseudoFrames.IsEmpty()) {
03045     PRBool created = PR_FALSE;
03046     if (nsLayoutAtoms::tableRowGroupFrame == parentFrameType) { // row group parent
03047       rv = CreatePseudoRowFrame(aTableCreator, aState, &aParentFrameIn);
03048       if (NS_FAILED(rv)) return rv;
03049       created = PR_TRUE;
03050     }
03051     if (created || (nsLayoutAtoms::tableRowFrame == parentFrameType)) { // row parent
03052       rv = CreatePseudoCellFrame(aTableCreator, aState, &aParentFrameIn);
03053       if (NS_FAILED(rv)) return rv;
03054     }
03055     rv = CreatePseudoTableFrame(aTableCreator, aState, &aParentFrameIn);
03056   }
03057   else {
03058     if (!pseudoFrames.mTableInner.mFrame) { 
03059       if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
03060         rv = CreatePseudoRowFrame(aTableCreator, aState);
03061         if (NS_FAILED(rv)) return rv;
03062       }
03063       if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
03064         rv = CreatePseudoCellFrame(aTableCreator, aState);
03065         if (NS_FAILED(rv)) return rv;
03066       }
03067       CreatePseudoTableFrame(aTableCreator, aState);
03068     }
03069   }
03070   return rv;
03071 }
03072 
03073 // called if the parent is not a col group
03074 nsresult 
03075 nsCSSFrameConstructor::GetPseudoColGroupFrame(nsTableCreator&          aTableCreator,
03076                                               nsFrameConstructorState& aState, 
03077                                               nsIFrame&                aParentFrameIn)
03078 {
03079   nsresult rv = NS_OK;
03080 
03081   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03082   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03083 
03084   if (pseudoFrames.IsEmpty()) {
03085     PRBool created = PR_FALSE;
03086     if (nsLayoutAtoms::tableRowGroupFrame == parentFrameType) {  // row group parent
03087       rv = CreatePseudoRowFrame(aTableCreator, aState, &aParentFrameIn);
03088       created = PR_TRUE;
03089     }
03090     if (created || (nsLayoutAtoms::tableRowFrame == parentFrameType)) { // row parent
03091       rv = CreatePseudoCellFrame(aTableCreator, aState, &aParentFrameIn);
03092       created = PR_TRUE;
03093     }
03094     if (created || IS_TABLE_CELL(parentFrameType) || // cell parent
03095         (nsLayoutAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
03096         !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
03097       rv = CreatePseudoTableFrame(aTableCreator, aState, &aParentFrameIn);
03098     }
03099     rv = CreatePseudoColGroupFrame(aTableCreator, aState, &aParentFrameIn);
03100   }
03101   else {
03102     if (!pseudoFrames.mColGroup.mFrame) {
03103       if (!pseudoFrames.mTableInner.mFrame) {
03104         if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
03105           rv = CreatePseudoRowFrame(aTableCreator, aState);
03106         }
03107         if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
03108           rv = CreatePseudoCellFrame(aTableCreator, aState);
03109         }
03110         if (pseudoFrames.mCellOuter.mFrame && !(pseudoFrames.mTableOuter.mFrame)) {
03111           rv = CreatePseudoTableFrame(aTableCreator, aState);
03112         }
03113       }
03114       rv = CreatePseudoColGroupFrame(aTableCreator, aState);
03115     }
03116   }
03117   return rv;
03118 }
03119 
03120 // called if the parent is not a row group
03121 nsresult 
03122 nsCSSFrameConstructor::GetPseudoRowGroupFrame(nsTableCreator&          aTableCreator,
03123                                               nsFrameConstructorState& aState, 
03124                                               nsIFrame&                aParentFrameIn)
03125 {
03126   nsresult rv = NS_OK;
03127 
03128   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03129   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03130 
03131   if (!pseudoFrames.mLowestType) {
03132     PRBool created = PR_FALSE;
03133     if (nsLayoutAtoms::tableRowFrame == parentFrameType) {  // row parent
03134       rv = CreatePseudoCellFrame(aTableCreator, aState, &aParentFrameIn);
03135       created = PR_TRUE;
03136     }
03137     if (created || IS_TABLE_CELL(parentFrameType) || // cell parent
03138         (nsLayoutAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
03139         !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
03140       rv = CreatePseudoTableFrame(aTableCreator, aState, &aParentFrameIn);
03141     }
03142     rv = CreatePseudoRowGroupFrame(aTableCreator, aState, &aParentFrameIn);
03143   }
03144   else {
03145     if (!pseudoFrames.mRowGroup.mFrame) { 
03146       if (pseudoFrames.mRow.mFrame && !(pseudoFrames.mCellOuter.mFrame)) {
03147         rv = CreatePseudoCellFrame(aTableCreator, aState);
03148       }
03149       if (pseudoFrames.mCellOuter.mFrame && !(pseudoFrames.mTableOuter.mFrame)) {
03150         rv = CreatePseudoTableFrame(aTableCreator, aState);
03151       }
03152       rv = CreatePseudoRowGroupFrame(aTableCreator, aState);
03153     }
03154   }
03155   return rv;
03156 }
03157 
03158 // called if the parent is not a row
03159 nsresult
03160 nsCSSFrameConstructor::GetPseudoRowFrame(nsTableCreator&          aTableCreator,
03161                                          nsFrameConstructorState& aState, 
03162                                          nsIFrame&                aParentFrameIn)
03163 {
03164   nsresult rv = NS_OK;
03165 
03166   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03167   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03168 
03169   if (!pseudoFrames.mLowestType) {
03170     PRBool created = PR_FALSE;
03171     if (IS_TABLE_CELL(parentFrameType) || // cell parent
03172        (nsLayoutAtoms::tableCaptionFrame == parentFrameType)  || // caption parent
03173         !IsTableRelated(parentFrameType, PR_TRUE)) { // block parent
03174       rv = CreatePseudoTableFrame(aTableCreator, aState, &aParentFrameIn);
03175       created = PR_TRUE;
03176     }
03177     if (created || (nsLayoutAtoms::tableFrame == parentFrameType)) { // table parent
03178       rv = CreatePseudoRowGroupFrame(aTableCreator, aState, &aParentFrameIn);
03179     }
03180     rv = CreatePseudoRowFrame(aTableCreator, aState, &aParentFrameIn);
03181   }
03182   else {
03183     if (!pseudoFrames.mRow.mFrame) { 
03184       if (pseudoFrames.mCellOuter.mFrame && !pseudoFrames.mTableOuter.mFrame) {
03185         rv = CreatePseudoTableFrame(aTableCreator, aState);
03186       }
03187       if (pseudoFrames.mTableInner.mFrame && !(pseudoFrames.mRowGroup.mFrame)) {
03188         rv = CreatePseudoRowGroupFrame(aTableCreator, aState);
03189       }
03190       rv = CreatePseudoRowFrame(aTableCreator, aState);
03191     }
03192   }
03193   return rv;
03194 }
03195 
03196 // called if the parent is not a cell or block
03197 nsresult 
03198 nsCSSFrameConstructor::GetPseudoCellFrame(nsTableCreator&          aTableCreator,
03199                                           nsFrameConstructorState& aState, 
03200                                           nsIFrame&                aParentFrameIn)
03201 {
03202   nsresult rv = NS_OK;
03203 
03204   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03205   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03206 
03207   if (!pseudoFrames.mLowestType) {
03208     PRBool created = PR_FALSE;
03209     if (nsLayoutAtoms::tableFrame == parentFrameType) { // table parent
03210       rv = CreatePseudoRowGroupFrame(aTableCreator, aState, &aParentFrameIn);
03211       created = PR_TRUE;
03212     }
03213     if (created || (nsLayoutAtoms::tableRowGroupFrame == parentFrameType)) { // row group parent
03214       rv = CreatePseudoRowFrame(aTableCreator, aState, &aParentFrameIn);
03215       created = PR_TRUE;
03216     }
03217     rv = CreatePseudoCellFrame(aTableCreator, aState, &aParentFrameIn);
03218   }
03219   else if (!pseudoFrames.mCellOuter.mFrame) { 
03220     if (pseudoFrames.mTableInner.mFrame && !(pseudoFrames.mRowGroup.mFrame)) {
03221       rv = CreatePseudoRowGroupFrame(aTableCreator, aState);
03222     }
03223     if (pseudoFrames.mRowGroup.mFrame && !(pseudoFrames.mRow.mFrame)) {
03224       rv = CreatePseudoRowFrame(aTableCreator, aState);
03225     }
03226     rv = CreatePseudoCellFrame(aTableCreator, aState);
03227   }
03228   return rv;
03229 }
03230 
03231 nsresult 
03232 nsCSSFrameConstructor::GetParentFrame(nsTableCreator&          aTableCreator,
03233                                       nsIFrame&                aParentFrameIn, 
03234                                       nsIAtom*                 aChildFrameType, 
03235                                       nsFrameConstructorState& aState, 
03236                                       nsIFrame*&               aParentFrame,
03237                                       PRBool&                  aIsPseudoParent)
03238 {
03239   nsresult rv = NS_OK;
03240 
03241   nsIAtom* parentFrameType = aParentFrameIn.GetType();
03242   nsIFrame* pseudoParentFrame = nsnull;
03243   nsPseudoFrames& pseudoFrames = aState.mPseudoFrames;
03244   aParentFrame = &aParentFrameIn;
03245   aIsPseudoParent = PR_FALSE;
03246 
03247   if (nsLayoutAtoms::tableOuterFrame == aChildFrameType) { // table child
03248     if (IsTableRelated(parentFrameType, PR_TRUE) &&
03249         (nsLayoutAtoms::tableCaptionFrame != parentFrameType) ) { // need pseudo cell parent
03250       rv = GetPseudoCellFrame(aTableCreator, aState, aParentFrameIn);
03251       if (NS_FAILED(rv)) return rv;
03252       pseudoParentFrame = pseudoFrames.mCellInner.mFrame;
03253     }
03254   } 
03255   else if (nsLayoutAtoms::tableCaptionFrame == aChildFrameType) { // caption child
03256     if (nsLayoutAtoms::tableOuterFrame != parentFrameType) { // need pseudo table parent
03257       rv = GetPseudoTableFrame(aTableCreator, aState, aParentFrameIn);
03258       if (NS_FAILED(rv)) return rv;
03259       pseudoParentFrame = pseudoFrames.mTableOuter.mFrame;
03260     }
03261   }
03262   else if (nsLayoutAtoms::tableColGroupFrame == aChildFrameType) { // col group child
03263     if (nsLayoutAtoms::tableFrame != parentFrameType) { // need pseudo table parent
03264       rv = GetPseudoTableFrame(aTableCreator, aState, aParentFrameIn);
03265       if (NS_FAILED(rv)) return rv;
03266       pseudoParentFrame = pseudoFrames.mTableInner.mFrame;
03267     }
03268   }
03269   else if (nsLayoutAtoms::tableColFrame == aChildFrameType) { // col child
03270     if (nsLayoutAtoms::tableColGroupFrame != parentFrameType) { // need pseudo col group parent
03271       rv = GetPseudoColGroupFrame(aTableCreator, aState, aParentFrameIn);
03272       if (NS_FAILED(rv)) return rv;
03273       pseudoParentFrame = pseudoFrames.mColGroup.mFrame;
03274     }
03275   }
03276   else if (nsLayoutAtoms::tableRowGroupFrame == aChildFrameType) { // row group child
03277     // XXX can this go away?
03278     if (nsLayoutAtoms::tableFrame != parentFrameType) {
03279       // trees allow row groups to contain row groups, so don't create pseudo frames
03280         rv = GetPseudoTableFrame(aTableCreator, aState, aParentFrameIn);
03281         if (NS_FAILED(rv)) return rv;
03282         pseudoParentFrame = pseudoFrames.mTableInner.mFrame;
03283      }
03284   }
03285   else if (nsLayoutAtoms::tableRowFrame == aChildFrameType) { // row child
03286     if (nsLayoutAtoms::tableRowGroupFrame != parentFrameType) { // need pseudo row group parent
03287       rv = GetPseudoRowGroupFrame(aTableCreator, aState, aParentFrameIn);
03288       if (NS_FAILED(rv)) return rv;
03289       pseudoParentFrame = pseudoFrames.mRowGroup.mFrame;
03290     }
03291   }
03292   else if (IS_TABLE_CELL(aChildFrameType)) { // cell child
03293     if (nsLayoutAtoms::tableRowFrame != parentFrameType) { // need pseudo row parent
03294       rv = GetPseudoRowFrame(aTableCreator, aState, aParentFrameIn);
03295       if (NS_FAILED(rv)) return rv;
03296       pseudoParentFrame = pseudoFrames.mRow.mFrame;
03297     }
03298   }
03299   else if (nsLayoutAtoms::tableFrame == aChildFrameType) { // invalid
03300     NS_ASSERTION(PR_FALSE, "GetParentFrame called on nsLayoutAtoms::tableFrame child");
03301   }
03302   else { // foreign frame
03303     if (IsTableRelated(parentFrameType, PR_FALSE)) { // need pseudo cell parent
03304       rv = GetPseudoCellFrame(aTableCreator, aState, aParentFrameIn);
03305       if (NS_FAILED(rv)) return rv;
03306       pseudoParentFrame = pseudoFrames.mCellInner.mFrame;
03307     }
03308   }
03309   
03310   if (pseudoParentFrame) {
03311     aParentFrame = pseudoParentFrame;
03312     aIsPseudoParent = PR_TRUE;
03313   }
03314 
03315   return rv;
03316 }
03317 
03318 static PRBool
03319 IsSpecialContent(nsIContent* aContent,
03320                  nsIAtom*    aTag,
03321                  PRInt32     aNameSpaceID,
03322                  nsStyleContext* aStyleContext)
03323 {
03324   // Gross hack. Return true if this is a content node that we'd create a
03325   // frame for based on something other than display -- in other words if this
03326   // is a node that could never have a nsTableCellFrame, for example.
03327   if (aContent->IsContentOfType(nsIContent::eHTML) ||
03328       aNameSpaceID == kNameSpaceID_XHTML) {
03329     // XXXbz this is duplicating some logic from ConstructHTMLFrame....
03330     // Would be nice to avoid that.  :(
03331   
03332     if (aTag == nsHTMLAtoms::input) {
03333       nsCOMPtr<nsIFormControl> control = do_QueryInterface(aContent);
03334       if (control && NS_FORM_INPUT_HIDDEN == control->GetType())
03335         return PR_FALSE; // input hidden does not create a special frame
03336     }
03337 
03338     return
03339       aTag == nsHTMLAtoms::img ||
03340       aTag == nsHTMLAtoms::br ||
03341       aTag == nsHTMLAtoms::wbr ||
03342       aTag == nsHTMLAtoms::input ||
03343       aTag == nsHTMLAtoms::textarea ||
03344       aTag == nsHTMLAtoms::select ||
03345       aTag == nsHTMLAtoms::object ||
03346       aTag == nsHTMLAtoms::applet ||
03347       aTag == nsHTMLAtoms::embed ||
03348       aTag == nsHTMLAtoms::fieldset ||
03349       aTag == nsHTMLAtoms::legend ||
03350       aTag == nsHTMLAtoms::frameset ||
03351       aTag == nsHTMLAtoms::iframe ||
03352       aTag == nsHTMLAtoms::spacer ||
03353       aTag == nsHTMLAtoms::button ||
03354       aTag == nsHTMLAtoms::isindex ||
03355       aTag == nsHTMLAtoms::canvas; 
03356   }
03357   if (aNameSpaceID == kNameSpaceID_XUL)
03358     return
03359 #ifdef MOZ_XUL
03360       aTag == nsXULAtoms::button ||
03361       aTag == nsXULAtoms::checkbox ||
03362       aTag == nsXULAtoms::radio ||
03363       aTag == nsXULAtoms::autorepeatbutton ||
03364       aTag == nsXULAtoms::titlebar ||
03365       aTag == nsXULAtoms::resizer ||
03366       aTag == nsXULAtoms::image ||
03367       aTag == nsXULAtoms::spring ||
03368       aTag == nsHTMLAtoms::spacer ||
03369       aTag == nsXULAtoms::treechildren ||
03370       aTag == nsXULAtoms::treecol ||
03371       aTag == nsXULAtoms::text ||
03372       aTag == nsXULAtoms::description ||
03373       aTag == nsHTMLAtoms::label ||
03374       aTag == nsXULAtoms::menu ||
03375       aTag == nsXULAtoms::menuitem ||
03376       aTag == nsXULAtoms::menubutton ||
03377       aTag == nsXULAtoms::menubar ||
03378       aTag == nsXULAtoms::popupgroup ||
03379       aTag == nsXULAtoms::iframe ||
03380       aTag == nsXULAtoms::editor ||
03381       aTag == nsXULAtoms::browser ||
03382       aTag == nsXULAtoms::progressmeter ||
03383 #endif
03384       aTag == nsXULAtoms::slider ||
03385       aTag == nsXULAtoms::scrollbar ||
03386       aTag == nsXULAtoms::nativescrollbar ||
03387       aTag == nsXULAtoms::scrollbarbutton ||
03388 #ifdef MOZ_XUL
03389       aTag == nsXULAtoms::splitter ||
03390       aTag == nsXULAtoms::grippy ||
03391 #endif
03392       PR_FALSE;
03393 
03394 #ifdef MOZ_SVG
03395   if (aNameSpaceID == kNameSpaceID_SVG &&
03396       nsSVGUtils::SVGEnabled())
03397     return
03398       aTag == nsSVGAtoms::svg ||
03399       aTag == nsSVGAtoms::g ||
03400       aTag == nsSVGAtoms::polygon ||
03401       aTag == nsSVGAtoms::polyline ||
03402       aTag == nsSVGAtoms::circle ||
03403       aTag == nsSVGAtoms::defs ||
03404       aTag == nsSVGAtoms::ellipse ||
03405       aTag == nsSVGAtoms::line ||
03406       aTag == nsSVGAtoms::rect ||
03407 #ifdef MOZ_SVG_FOREIGNOBJECT
03408       aTag == nsSVGAtoms::foreignObject ||
03409 #endif
03410       aTag == nsSVGAtoms::path ||
03411       aTag == nsSVGAtoms::text ||
03412       aTag == nsSVGAtoms::tspan ||
03413       aTag == nsSVGAtoms::linearGradient ||
03414       aTag == nsSVGAtoms::radialGradient ||
03415       aTag == nsSVGAtoms::stop ||
03416       aTag == nsSVGAtoms::use ||
03417       aTag == nsSVGAtoms::marker ||
03418       aTag == nsSVGAtoms::image  ||
03419       aTag == nsSVGAtoms::clipPath;
03420 #endif
03421 
03422 #ifdef MOZ_MATHML
03423   if (aNameSpaceID == kNameSpaceID_MathML)
03424     return
03425       aTag == nsMathMLAtoms::mi_ ||
03426       aTag == nsMathMLAtoms::mn_ ||
03427       aTag == nsMathMLAtoms::ms_ ||
03428       aTag == nsMathMLAtoms::mtext_ ||
03429       aTag == nsMathMLAtoms::mo_ ||
03430       aTag == nsMathMLAtoms::mfrac_ ||
03431       aTag == nsMathMLAtoms::msup_ ||
03432       aTag == nsMathMLAtoms::msub_ ||
03433       aTag == nsMathMLAtoms::msubsup_ ||
03434       aTag == nsMathMLAtoms::munder_ ||
03435       aTag == nsMathMLAtoms::mover_ ||
03436       aTag == nsMathMLAtoms::munderover_ ||
03437       aTag == nsMathMLAtoms::mphantom_ ||
03438       aTag == nsMathMLAtoms::mpadded_ ||
03439       aTag == nsMathMLAtoms::mspace_ ||
03440       aTag == nsMathMLAtoms::mfenced_ ||
03441       aTag == nsMathMLAtoms::mmultiscripts_ ||
03442       aTag == nsMathMLAtoms::mstyle_ ||
03443       aTag == nsMathMLAtoms::msqrt_ ||
03444       aTag == nsMathMLAtoms::mroot_ ||
03445       aTag == nsMathMLAtoms::maction_ ||
03446       aTag == nsMathMLAtoms::mrow_   ||
03447       aTag == nsMathMLAtoms::merror_ ||
03448       aTag == nsMathMLAtoms::none_   ||
03449       aTag == nsMathMLAtoms::mprescripts_ ||
03450       (aTag == nsMathMLAtoms::mtable_ &&
03451        aStyleContext->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_TABLE) ||
03452       aTag == nsMathMLAtoms::math;
03453 #endif
03454   return PR_FALSE;
03455 }
03456 
03457 
03458 nsresult
03459 nsCSSFrameConstructor::AdjustParentFrame(nsIContent* aChildContent,
03460                                          const nsStyleDisplay* aChildDisplay,
03461                                          nsIAtom* aTag,
03462                                          PRInt32 aNameSpaceID,
03463                                          nsStyleContext* aChildStyle,
03464                                          nsIFrame* & aParentFrame,
03465                                          nsFrameItems* & aFrameItems,
03466                                          nsFrameConstructorState& aState,
03467                                          nsFrameConstructorSaveState& aSaveState,
03468                                          PRBool& aCreatedPseudo)
03469 {
03470   NS_PRECONDITION(aChildDisplay, "Must have child's display struct");
03471   NS_PRECONDITION(aFrameItems, "Must have frame items to work with");
03472 
03473   aCreatedPseudo = PR_FALSE;
03474   if (!aParentFrame) {
03475     // Nothing to do here
03476     return NS_OK;
03477   }
03478 
03479   PRBool childIsSpecialContent = PR_FALSE; // lazy lookup
03480   // Only use the outer table frame as parent if the child is going to use a
03481   // tableCaptionFrame, otherwise the inner table frame is the parent
03482   // (bug 341858).
03483   if (aParentFrame->GetType() == nsLayoutAtoms::tableOuterFrame) {
03484     childIsSpecialContent = IsSpecialContent(aChildContent, aTag, aNameSpaceID,
03485                                              aChildStyle);
03486     if (childIsSpecialContent ||
03487        (aChildStyle->GetStyleDisplay()->mDisplay !=
03488        NS_STYLE_DISPLAY_TABLE_CAPTION)) {
03489       aParentFrame = aParentFrame->GetContentInsertionFrame();
03490     }
03491   }
03492 
03493   // If our parent is a table, table-row-group, or table-row, and
03494   // we're not table-related in any way, we have to create table
03495   // pseudo-frames so that we have a table cell to live in.
03496   if (IsTableRelated(aParentFrame->GetType(), PR_FALSE) &&
03497       (!IsTableRelated(aChildDisplay->mDisplay, PR_TRUE) ||
03498        // Also need to create a pseudo-parent if the child is going to end up
03499        // with a frame based on something other than display.
03500        childIsSpecialContent || // looked it up before
03501        IsSpecialContent(aChildContent, aTag, aNameSpaceID, aChildStyle))) {
03502     nsTableCreator tableCreator(aState.mPresShell);
03503     nsresult rv = GetPseudoCellFrame(tableCreator, aState, *aParentFrame);
03504     if (NS_FAILED(rv)) {
03505       return rv;
03506     }
03507 
03508     NS_ASSERTION(aState.mPseudoFrames.mCellInner.mFrame,
03509                  "Must have inner cell frame now!");
03510 
03511     aParentFrame = aState.mPseudoFrames.mCellInner.mFrame;
03512     aFrameItems = &aState.mPseudoFrames.mCellInner.mChildList;
03513     // We pushed an anonymous table cell.  The inner block of this
03514     // needs to become the float containing block.
03515     aState.PushFloatContainingBlock(aParentFrame, aSaveState, PR_FALSE,
03516                                     PR_FALSE);
03517     aCreatedPseudo = PR_TRUE;
03518   }
03519   return NS_OK;
03520 }
03521 
03522 // Construct the outer, inner table frames and the children frames for the table. 
03523 // XXX Page break frames for pseudo table frames are not constructed to avoid the risk
03524 // associated with revising the pseudo frame mechanism. The long term solution
03525 // of having frames handle page-break-before/after will solve the problem. 
03526 nsresult
03527 nsCSSFrameConstructor::ConstructTableFrame(nsFrameConstructorState& aState,
03528                                            nsIContent*              aContent,
03529                                            nsIFrame*                aContentParent,
03530                                            nsStyleContext*          aStyleContext,
03531                                            nsTableCreator&          aTableCreator,
03532                                            PRBool                   aIsPseudo,
03533                                            nsFrameItems&            aChildItems,
03534                                            PRBool                   aAllowOutOfFlow,
03535                                            nsIFrame*&               aNewOuterFrame,
03536                                            nsIFrame*&               aNewInnerFrame)
03537 {
03538   nsresult rv = NS_OK;
03539 
03540   // Create the outer table frame which holds the caption and inner table frame
03541   aTableCreator.CreateTableOuterFrame(&aNewOuterFrame);
03542 
03543   nsIFrame* parentFrame = aContentParent;
03544   nsFrameItems* frameItems = &aChildItems;
03545   // We may need to push a float containing block
03546   nsFrameConstructorSaveState floatSaveState;
03547   if (!aIsPseudo) {
03548     // this frame may have a pseudo parent
03549     PRBool hasPseudoParent = PR_FALSE;
03550     GetParentFrame(aTableCreator, *parentFrame, nsLayoutAtoms::tableOuterFrame,
03551                    aState, parentFrame, hasPseudoParent);
03552     if (!hasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03553       ProcessPseudoFrames(aState, aChildItems);
03554     }
03555     if (hasPseudoParent) {
03556       aState.PushFloatContainingBlock(parentFrame, floatSaveState,
03557                                       PR_FALSE, PR_FALSE);
03558       frameItems = &aState.mPseudoFrames.mCellInner.mChildList;
03559       if (aState.mPseudoFrames.mTableOuter.mFrame) {
03560         ProcessPseudoFrames(aState, nsLayoutAtoms::tableOuterFrame);
03561       }
03562     }
03563   }
03564 
03565   // create the pseudo SC for the outer table as a child of the inner SC
03566   nsRefPtr<nsStyleContext> outerStyleContext;
03567   outerStyleContext = mPresShell->StyleSet()->
03568     ResolvePseudoStyleFor(aContent, nsCSSAnonBoxes::tableOuter, aStyleContext);
03569 
03570   const nsStyleDisplay* disp = outerStyleContext->GetStyleDisplay();
03571   nsIFrame* geometricParent =
03572     aAllowOutOfFlow ? aState.GetGeometricParent(disp, parentFrame) :
03573                       parentFrame;
03574 
03575   // Init the table outer frame and see if we need to create a view, e.g.
03576   // the frame is absolutely positioned  
03577   InitAndRestoreFrame(aState, aContent, geometricParent, outerStyleContext,
03578                       nsnull, aNewOuterFrame);  
03579   nsHTMLContainerFrame::CreateViewForFrame(aNewOuterFrame, aContentParent,
03580                                            PR_FALSE);
03581 
03582   // Create the inner table frame
03583   aTableCreator.CreateTableFrame(&aNewInnerFrame);
03584 
03585   InitAndRestoreFrame(aState, aContent, aNewOuterFrame, aStyleContext, nsnull,
03586                       aNewInnerFrame);
03587 
03588   if (!aIsPseudo) {
03589     // Put the newly created frames into the right child list
03590     aNewOuterFrame->SetInitialChildList(aState.mPresContext, nsnull,
03591                                         aNewInnerFrame);
03592 
03593     rv = aState.AddChild(aNewOuterFrame, *frameItems, disp, aContent,
03594                          outerStyleContext, parentFrame, aAllowOutOfFlow,
03595                          aAllowOutOfFlow);
03596     if (NS_FAILED(rv)) {
03597       return rv;
03598     }
03599 
03600     nsFrameItems childItems;
03601     nsIFrame* captionFrame;
03602 
03603     rv = TableProcessChildren(aState, aContent, aNewInnerFrame,
03604                               aTableCreator, childItems, captionFrame);
03605     // XXXbz what about cleaning up?
03606     if (NS_FAILED(rv)) return rv;
03607 
03608     // if there are any anonymous children for the table, create frames for them
03609     CreateAnonymousFrames(nsnull, aState, aContent, aNewInnerFrame,
03610                           PR_FALSE, childItems);
03611 
03612     // Set the inner table frame's initial primary list 
03613     aNewInnerFrame->SetInitialChildList(aState.mPresContext, nsnull,
03614                                         childItems.childList);
03615 
03616     // Set the outer table frame's primary and option lists
03617     if (captionFrame) {
03618       aNewOuterFrame->SetInitialChildList(aState.mPresContext,
03619                                           nsLayoutAtoms::captionList,
03620                                           captionFrame);
03621     }
03622   }
03623 
03624   return rv;
03625 }
03626 
03627 nsresult
03628 nsCSSFrameConstructor::ConstructTableCaptionFrame(nsFrameConstructorState& aState,
03629                                                   nsIContent*              aContent,
03630                                                   nsIFrame*                aParentFrameIn,
03631                                                   nsStyleContext*          aStyleContext,
03632                                                   nsTableCreator&          aTableCreator,
03633                                                   nsFrameItems&            aChildItems,
03634                                                   nsIFrame*&               aNewFrame,
03635                                                   PRBool&                  aIsPseudoParent)
03636 
03637 {
03638   nsresult rv = NS_OK;
03639   if (!aParentFrameIn) return rv;
03640 
03641   nsIFrame* parentFrame = aParentFrameIn;
03642   aIsPseudoParent = PR_FALSE;
03643   // this frame may have a pseudo parent
03644   GetParentFrame(aTableCreator, *aParentFrameIn, 
03645                  nsLayoutAtoms::tableCaptionFrame, aState, parentFrame,
03646                  aIsPseudoParent);
03647   if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03648     ProcessPseudoFrames(aState, aChildItems);
03649   }
03650 
03651   rv = aTableCreator.CreateTableCaptionFrame(&aNewFrame);
03652   if (NS_FAILED(rv)) return rv;
03653   InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03654                       aNewFrame);
03655   // XXXbz should we be passing in a non-null aContentParentFrame?
03656   nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, nsnull, PR_FALSE);
03657 
03658   PRBool haveFirstLetterStyle, haveFirstLineStyle;
03659   HaveSpecialBlockStyle(aContent, aStyleContext,
03660                         &haveFirstLetterStyle, &haveFirstLineStyle);
03661 
03662   // The caption frame is a float container
03663   nsFrameConstructorSaveState floatSaveState;
03664   aState.PushFloatContainingBlock(aNewFrame, floatSaveState,
03665                                   haveFirstLetterStyle, haveFirstLineStyle);
03666   nsFrameItems childItems;
03667   // pass in aTableCreator so ProcessChildren will call TableProcessChildren
03668   rv = ProcessChildren(aState, aContent, aNewFrame,
03669                        PR_TRUE, childItems, PR_TRUE, &aTableCreator);
03670   if (NS_FAILED(rv)) return rv;
03671   aNewFrame->SetInitialChildList(aState.mPresContext, nsnull,
03672                                  childItems.childList);
03673   if (aIsPseudoParent) {
03674     aState.mPseudoFrames.mTableOuter.mChildList2.AddChild(aNewFrame);
03675   }
03676   
03677   return rv;
03678 }
03679 
03680 
03681 nsresult
03682 nsCSSFrameConstructor::ConstructTableRowGroupFrame(nsFrameConstructorState& aState,
03683                                                    nsIContent*              aContent,
03684                                                    nsIFrame*                aParentFrameIn,
03685                                                    nsStyleContext*          aStyleContext,
03686                                                    nsTableCreator&          aTableCreator,
03687                                                    PRBool                   aIsPseudo,
03688                                                    nsFrameItems&            aChildItems,
03689                                                    nsIFrame*&               aNewFrame, 
03690                                                    PRBool&                  aIsPseudoParent)
03691 {
03692   nsresult rv = NS_OK;
03693   if (!aParentFrameIn) return rv;
03694 
03695   nsIFrame* parentFrame = aParentFrameIn;
03696   aIsPseudoParent = PR_FALSE;
03697   if (!aIsPseudo) {
03698     // this frame may have a pseudo parent
03699     GetParentFrame(aTableCreator, *aParentFrameIn, 
03700                    nsLayoutAtoms::tableRowGroupFrame, aState, parentFrame,
03701                    aIsPseudoParent);
03702     if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03703       ProcessPseudoFrames(aState, aChildItems);
03704     }
03705     if (!aIsPseudo && aIsPseudoParent && aState.mPseudoFrames.mRowGroup.mFrame) {
03706       ProcessPseudoFrames(aState, nsLayoutAtoms::tableRowGroupFrame);
03707     }
03708   }
03709 
03710   const nsStyleDisplay* styleDisplay = aStyleContext->GetStyleDisplay();
03711 
03712   rv = aTableCreator.CreateTableRowGroupFrame(&aNewFrame);
03713 
03714   nsIFrame* scrollFrame = nsnull;
03715   if (styleDisplay->IsScrollableOverflow()) {
03716     // Create an area container for the frame
03717     BuildScrollFrame(aState, aContent, aStyleContext, aNewFrame, parentFrame,
03718                      nsnull, scrollFrame, aStyleContext);
03719 
03720   } 
03721   else {
03722     if (NS_FAILED(rv)) return rv;
03723     InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03724                         aNewFrame);
03725     // XXXbz should we be passing in a non-null aContentParentFrame?
03726     nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, nsnull, PR_FALSE);
03727   }
03728 
03729   if (!aIsPseudo) {
03730     nsFrameItems childItems;
03731     nsIFrame* captionFrame;
03732     rv = TableProcessChildren(aState, aContent, aNewFrame, aTableCreator,
03733                               childItems, captionFrame);
03734     if (NS_FAILED(rv)) return rv;
03735     // if there are any anonymous children for the table, create frames for them
03736     CreateAnonymousFrames(nsnull, aState, aContent, aNewFrame,
03737                           PR_FALSE, childItems);
03738 
03739     aNewFrame->SetInitialChildList(aState.mPresContext, nsnull,
03740                                    childItems.childList);
03741     if (aIsPseudoParent) {
03742       nsIFrame* child = (scrollFrame) ? scrollFrame : aNewFrame;
03743       aState.mPseudoFrames.mTableInner.mChildList.AddChild(child);
03744     }
03745   } 
03746 
03747   // if there is a scroll frame, use it as the one constructed
03748   if (scrollFrame) {
03749     aNewFrame = scrollFrame;
03750   }
03751   
03752   return rv;
03753 }
03754 
03755 nsresult
03756 nsCSSFrameConstructor::ConstructTableColGroupFrame(nsFrameConstructorState& aState,
03757                                                    nsIContent*              aContent,
03758                                                    nsIFrame*                aParentFrameIn,
03759                                                    nsStyleContext*          aStyleContext,
03760                                                    nsTableCreator&          aTableCreator,
03761                                                    PRBool                   aIsPseudo,
03762                                                    nsFrameItems&            aChildItems,
03763                                                    nsIFrame*&               aNewFrame, 
03764                                                    PRBool&                  aIsPseudoParent)
03765 {
03766   nsresult rv = NS_OK;
03767   if (!aParentFrameIn) return rv;
03768 
03769   nsIFrame* parentFrame = aParentFrameIn;
03770   aIsPseudoParent = PR_FALSE;
03771   if (!aIsPseudo) {
03772     // this frame may have a pseudo parent
03773     GetParentFrame(aTableCreator, *aParentFrameIn, 
03774                    nsLayoutAtoms::tableColGroupFrame, aState, parentFrame,
03775                    aIsPseudoParent);
03776     if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03777       ProcessPseudoFrames(aState, aChildItems);
03778     }
03779     if (!aIsPseudo && aIsPseudoParent && aState.mPseudoFrames.mColGroup.mFrame) {
03780       ProcessPseudoFrames(aState, nsLayoutAtoms::tableColGroupFrame);
03781     }
03782   }
03783 
03784   rv = aTableCreator.CreateTableColGroupFrame(&aNewFrame);
03785   if (NS_FAILED(rv)) return rv;
03786   InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03787                       aNewFrame);
03788 
03789   if (!aIsPseudo) {
03790     nsFrameItems childItems;
03791     nsIFrame* captionFrame;
03792     rv = TableProcessChildren(aState, aContent, aNewFrame, aTableCreator,
03793                               childItems, captionFrame);
03794     if (NS_FAILED(rv)) return rv;
03795     aNewFrame->SetInitialChildList(aState.mPresContext, nsnull,
03796                                    childItems.childList);
03797     if (aIsPseudoParent) {
03798       aState.mPseudoFrames.mTableInner.mChildList.AddChild(aNewFrame);
03799     }
03800   }
03801 
03802   return rv;
03803 }
03804 
03805 nsresult
03806 nsCSSFrameConstructor::ConstructTableRowFrame(nsFrameConstructorState& aState,
03807                                               nsIContent*              aContent,
03808                                               nsIFrame*                aParentFrameIn,
03809                                               nsStyleContext*          aStyleContext,
03810                                               nsTableCreator&          aTableCreator,
03811                                               PRBool                   aIsPseudo,
03812                                               nsFrameItems&            aChildItems,
03813                                               nsIFrame*&               aNewFrame,
03814                                               PRBool&                  aIsPseudoParent)
03815 {
03816   nsresult rv = NS_OK;
03817   if (!aParentFrameIn) return rv;
03818 
03819   nsIFrame* parentFrame = aParentFrameIn;
03820   aIsPseudoParent = PR_FALSE;
03821   if (!aIsPseudo) {
03822     // this frame may have a pseudo parent
03823     GetParentFrame(aTableCreator, *aParentFrameIn,
03824                    nsLayoutAtoms::tableRowFrame, aState, parentFrame,
03825                    aIsPseudoParent);
03826     if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03827       ProcessPseudoFrames(aState, aChildItems);
03828     }
03829     if (!aIsPseudo && aIsPseudoParent && aState.mPseudoFrames.mRow.mFrame) {
03830       ProcessPseudoFrames(aState, nsLayoutAtoms::tableRowFrame);
03831     }
03832   }
03833 
03834   rv = aTableCreator.CreateTableRowFrame(&aNewFrame);
03835   if (NS_FAILED(rv)) return rv;
03836   InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03837                       aNewFrame);
03838   // XXXbz should we be passing in a non-null aContentParentFrame?
03839   nsHTMLContainerFrame::CreateViewForFrame(aNewFrame, nsnull, PR_FALSE);
03840   if (!aIsPseudo) {
03841     nsFrameItems childItems;
03842     nsIFrame* captionFrame;
03843     rv = TableProcessChildren(aState, aContent, aNewFrame, aTableCreator,
03844                               childItems, captionFrame);
03845     if (NS_FAILED(rv)) return rv;
03846     // if there are any anonymous children for the table, create frames for them
03847     CreateAnonymousFrames(nsnull, aState, aContent, aNewFrame,
03848                           PR_FALSE, childItems);
03849 
03850     aNewFrame->SetInitialChildList(aState.mPresContext, nsnull,
03851                                    childItems.childList);
03852     if (aIsPseudoParent) {
03853       aState.mPseudoFrames.mRowGroup.mChildList.AddChild(aNewFrame);
03854     }
03855   }
03856 
03857   return rv;
03858 }
03859       
03860 nsresult
03861 nsCSSFrameConstructor::ConstructTableColFrame(nsFrameConstructorState& aState,
03862                                               nsIContent*              aContent,
03863                                               nsIFrame*                aParentFrameIn,
03864                                               nsStyleContext*          aStyleContext,
03865                                               nsTableCreator&          aTableCreator,
03866                                               PRBool                   aIsPseudo,
03867                                               nsFrameItems&            aChildItems,
03868                                               nsIFrame*&               aNewFrame,
03869                                               PRBool&                  aIsPseudoParent)
03870 {
03871   nsresult rv = NS_OK;
03872   if (!aParentFrameIn || !aStyleContext) return rv;
03873 
03874   nsIFrame* parentFrame = aParentFrameIn;
03875   aIsPseudoParent = PR_FALSE;
03876   if (!aIsPseudo) {
03877     // this frame may have a pseudo parent
03878     GetParentFrame(aTableCreator, *aParentFrameIn, 
03879                    nsLayoutAtoms::tableColFrame, aState, parentFrame,
03880                    aIsPseudoParent);
03881     if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03882       ProcessPseudoFrames(aState, aChildItems);
03883     }
03884   }
03885 
03886   rv = aTableCreator.CreateTableColFrame(&aNewFrame);
03887   if (NS_FAILED(rv)) return rv;
03888   InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03889                       aNewFrame);
03890   // if the parent frame was anonymous then reparent the style context
03891   if (aIsPseudoParent) {
03892     aState.mFrameManager->ReParentStyleContext(aNewFrame);
03893   }
03894 
03895   // construct additional col frames if the col frame has a span > 1
03896   PRInt32 span = 1;
03897   nsCOMPtr<nsIDOMHTMLTableColElement> cgContent(do_QueryInterface(aContent));
03898   if (cgContent) { 
03899     cgContent->GetSpan(&span);
03900     nsIFrame* lastCol = aNewFrame;
03901     nsStyleContext* styleContext = nsnull;
03902     for (PRInt32 spanX = 1; spanX < span; spanX++) {
03903       // The same content node should always resolve to the same style context.
03904       if (1 == spanX)
03905         styleContext = aNewFrame->GetStyleContext();
03906       nsIFrame* newCol;
03907       rv = aTableCreator.CreateTableColFrame(&newCol);
03908       if (NS_FAILED(rv)) return rv;
03909       InitAndRestoreFrame(aState, aContent, parentFrame, styleContext, nsnull,
03910                           newCol, PR_FALSE);
03911       ((nsTableColFrame*)newCol)->SetColType(eColAnonymousCol);
03912       lastCol->SetNextSibling(newCol);
03913       lastCol = newCol;
03914     }
03915   }
03916 
03917   if (!aIsPseudo && aIsPseudoParent) {
03918       aState.mPseudoFrames.mColGroup.mChildList.AddChild(aNewFrame);
03919   }
03920   
03921   return rv;
03922 }
03923 
03924 nsresult
03925 nsCSSFrameConstructor::ConstructTableCellFrame(nsFrameConstructorState& aState,
03926                                                nsIContent*              aContent,
03927                                                nsIFrame*                aParentFrameIn,
03928                                                nsStyleContext*          aStyleContext,
03929                                                nsTableCreator&          aTableCreator,
03930                                                PRBool                   aIsPseudo,
03931                                                nsFrameItems&            aChildItems,
03932                                                nsIFrame*&               aNewCellOuterFrame,
03933                                                nsIFrame*&               aNewCellInnerFrame,
03934                                                PRBool&                  aIsPseudoParent)
03935 {
03936   nsresult rv = NS_OK;
03937   if (!aParentFrameIn) return rv;
03938 
03939   nsIFrame* parentFrame = aParentFrameIn;
03940   aIsPseudoParent = PR_FALSE;
03941   if (!aIsPseudo) {
03942     // this frame may have a pseudo parent
03943     // use nsLayoutAtoms::tableCellFrame which will match if it is really nsLayoutAtoms::bcTableCellFrame
03944     GetParentFrame(aTableCreator, *aParentFrameIn, 
03945                    nsLayoutAtoms::tableCellFrame, aState, parentFrame,
03946                    aIsPseudoParent);
03947     if (!aIsPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
03948       ProcessPseudoFrames(aState, aChildItems);
03949     }
03950     if (!aIsPseudo && aIsPseudoParent && aState.mPseudoFrames.mCellOuter.mFrame) {
03951       ProcessPseudoFrames(aState, nsLayoutAtoms::tableCellFrame);
03952     }
03953   }
03954 
03955   rv = aTableCreator.CreateTableCellFrame(parentFrame, &aNewCellOuterFrame);
03956   if (NS_FAILED(rv)) return rv;
03957  
03958   // Initialize the table cell frame
03959   InitAndRestoreFrame(aState, aContent, parentFrame, aStyleContext, nsnull,
03960                       aNewCellOuterFrame);
03961   // XXXbz should we be passing in a non-null aContentParentFrame?
03962   nsHTMLContainerFrame::CreateViewForFrame(aNewCellOuterFrame, nsnull, PR_FALSE);
03963 
03964   // Create a block frame that will format the cell's content
03965   rv = aTableCreator.CreateTableCellInnerFrame(&aNewCellInnerFrame);
03966 
03967   if (NS_FAILED(rv)) {
03968     aNewCellOuterFrame->Destroy(aState.mPresContext);
03969     aNewCellOuterFrame = nsnull;
03970     return rv;
03971   }
03972   
03973   // Resolve pseudo style and initialize the body cell frame
03974   nsRefPtr<nsStyleContext> innerPseudoStyle;
03975   innerPseudoStyle = mPresShell->StyleSet()->
03976     ResolvePseudoStyleFor(aContent,
03977                           nsCSSAnonBoxes::cellContent, aStyleContext);
03978 
03979   InitAndRestoreFrame(aState, aContent, aNewCellOuterFrame, innerPseudoStyle,
03980                       nsnull, aNewCellInnerFrame);
03981 
03982   if (!aIsPseudo) {
03983     PRBool haveFirstLetterStyle, haveFirstLineStyle;
03984     HaveSpecialBlockStyle(aContent, aStyleContext,
03985                           &haveFirstLetterStyle, &haveFirstLineStyle);
03986 
03987     // The block frame is a float container
03988     nsFrameConstructorSaveState floatSaveState;
03989     aState.PushFloatContainingBlock(aNewCellInnerFrame, floatSaveState,
03990                                     haveFirstLetterStyle, haveFirstLineStyle);
03991 
03992     // Process the child content
03993     nsFrameItems childItems;
03994     // pass in null tableCreator so ProcessChildren will not call TableProcessChildren
03995     rv = ProcessChildren(aState, aContent, aNewCellInnerFrame, 
03996                          PR_TRUE, childItems, PR_TRUE, nsnull);
03997     if (NS_FAILED(rv)) {
03998       // Clean up
03999       // XXXbz kids of this stuff need to be cleaned up too!
04000       aNewCellInnerFrame->Destroy(aState.mPresContext);
04001       aNewCellInnerFrame = nsnull;
04002       aNewCellOuterFrame->Destroy(aState.mPresContext);
04003       aNewCellOuterFrame = nsnull;
04004       return rv;
04005     }
04006 
04007     aNewCellInnerFrame->SetInitialChildList(aState.mPresContext, nsnull,
04008                                             childItems.childList);
04009 
04010     aNewCellOuterFrame->SetInitialChildList(aState.mPresContext, nsnull,
04011                                             aNewCellInnerFrame);
04012     if (aIsPseudoParent) {
04013       aState.mPseudoFrames.mRow.mChildList.AddChild(aNewCellOuterFrame);
04014     }
04015   }
04016 
04017   return rv;
04018 }
04019 
04020 static PRBool 
04021 MustGeneratePseudoParent(nsIContent* aContent, nsStyleContext*  aStyleContext)
04022 {
04023   if (!aStyleContext ||
04024       NS_STYLE_DISPLAY_NONE == aStyleContext->GetStyleDisplay()->mDisplay) {
04025     return PR_FALSE;
04026   }
04027     
04028   if (aContent->IsContentOfType(nsIContent::eTEXT)) {
04029     return !IsOnlyWhitespace(aContent);
04030   }
04031 
04032   return !aContent->IsContentOfType(nsIContent::eCOMMENT);
04033 }
04034 
04035 // this is called when a non table related element is a child of a table, row group, 
04036 // or row, but not a cell.
04037 nsresult
04038 nsCSSFrameConstructor::ConstructTableForeignFrame(nsFrameConstructorState& aState,
04039                                                   nsIContent*              aContent,
04040                                                   nsIFrame*                aParentFrameIn,
04041                                                   nsStyleContext*          aStyleContext,
04042                                                   nsTableCreator&          aTableCreator,
04043                                                   nsFrameItems&            aChildItems)
04044 {
04045   nsresult rv = NS_OK;
04046   if (!aParentFrameIn) return rv;
04047 
04048   nsIFrame* parentFrame = nsnull;
04049   PRBool hasPseudoParent = PR_FALSE;
04050 
04051   if (MustGeneratePseudoParent(aContent, aStyleContext)) {
04052     // this frame may have a pseudo parent, use block frame type to
04053     // trigger foreign
04054     rv = GetParentFrame(aTableCreator,
04055                         *aParentFrameIn, nsLayoutAtoms::blockFrame,
04056                         aState, parentFrame, hasPseudoParent);
04057     NS_ASSERTION(NS_SUCCEEDED(rv), "GetParentFrame failed!");
04058     if (!hasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
04059       ProcessPseudoFrames(aState, aChildItems);
04060     }
04061   }
04062 
04063   if (!parentFrame) return rv; // if pseudo frame wasn't created
04064  
04065   // there are two situations where table related frames will wrap around
04066   // foreign frames
04067   // a) inner table cell, which is a pseudo frame
04068   // b) caption frame which will be always a real frame.
04069   NS_ASSERTION(nsLayoutAtoms::tableCaptionFrame == parentFrame->GetType() ||
04070                parentFrame == aState.mPseudoFrames.mCellInner.mFrame,
04071                "Weird parent in ConstructTableForeignFrame");
04072 
04073   // Push the parent as the floater containing block
04074   nsFrameConstructorSaveState saveState;
04075   aState.PushFloatContainingBlock(parentFrame, saveState, PR_FALSE, PR_FALSE);
04076   
04077   // save the pseudo frame state now, as descendants of the child frame may require
04078   // other pseudo frame creations
04079   nsPseudoFrames prevPseudoFrames; 
04080   aState.mPseudoFrames.Reset(&prevPseudoFrames);
04081 
04082   // Put the frames as kids of either the anonymous block (if we
04083   // created one), or just of our parent.
04084   nsFrameItems& childItems =
04085     hasPseudoParent ? prevPseudoFrames.mCellInner.mChildList : aChildItems;
04086 
04087   ConstructFrame(aState, aContent, parentFrame, childItems);
04088   // dont care about return value as ConstructFrame will not append a child if it fails.
04089 
04090   if (!aState.mPseudoFrames.IsEmpty()) {
04091     ProcessPseudoFrames(aState, childItems);
04092   }
04093   // restore the pseudo frame state
04094   aState.mPseudoFrames = prevPseudoFrames;
04095 
04096   return rv;
04097 }
04098 
04099 static PRBool 
04100 NeedFrameFor(nsIFrame*   aParentFrame,
04101              nsIContent* aChildContent) 
04102 {
04103   // don't create a whitespace frame if aParentFrame doesn't want it
04104   if ((NS_FRAME_EXCLUDE_IGNORABLE_WHITESPACE & aParentFrame->GetStateBits())
04105       && IsOnlyWhitespace(aChildContent)) {
04106     return PR_FALSE;
04107   }
04108   return PR_TRUE;
04109 }
04110 
04111 
04112 nsresult
04113 nsCSSFrameConstructor::TableProcessChildren(nsFrameConstructorState& aState,
04114                                             nsIContent*              aContent,
04115                                             nsIFrame*                aParentFrame,
04116                                             nsTableCreator&          aTableCreator,
04117                                             nsFrameItems&            aChildItems,
04118                                             nsIFrame*&               aCaption)
04119 {
04120   nsresult rv = NS_OK;
04121   if (!aContent || !aParentFrame) return rv;
04122 
04123   aCaption = nsnull;
04124 
04125   // save the incoming pseudo frame state 
04126   nsPseudoFrames priorPseudoFrames; 
04127   aState.mPseudoFrames.Reset(&priorPseudoFrames);
04128 
04129   nsIAtom* parentFrameType = aParentFrame->GetType();
04130   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
04131 
04132   ChildIterator iter, last;
04133   for (ChildIterator::Init(aContent, &iter, &last);
04134        iter != last;
04135        ++iter) {
04136     nsCOMPtr<nsIContent> childContent = *iter;
04137     if (childContent &&
04138         (childContent->IsContentOfType(nsIContent::eELEMENT) ||
04139          childContent->IsContentOfType(nsIContent::eTEXT)) &&
04140         NeedFrameFor(aParentFrame, childContent)) {
04141       rv = TableProcessChild(aState, childContent,
04142                              aContent, aParentFrame,
04143                              parentFrameType, parentStyleContext,
04144                              aTableCreator, aChildItems, aCaption);
04145     }
04146     if (NS_FAILED(rv)) return rv;
04147   }
04148   // process the current pseudo frame state
04149   if (!aState.mPseudoFrames.IsEmpty()) {
04150     ProcessPseudoFrames(aState, aChildItems);
04151   }
04152 
04153   // restore the incoming pseudo frame state 
04154   aState.mPseudoFrames = priorPseudoFrames;
04155   return rv;
04156 }
04157 
04158 nsresult
04159 nsCSSFrameConstructor::TableProcessChild(nsFrameConstructorState& aState,
04160                                          nsIContent*              aChildContent,
04161                                          nsIContent*              aParentContent,
04162                                          nsIFrame*                aParentFrame,
04163                                          nsIAtom*                 aParentFrameType,
04164                                          nsStyleContext*          aParentStyleContext,
04165                                          nsTableCreator&          aTableCreator,
04166                                          nsFrameItems&            aChildItems,
04167                                          nsIFrame*&               aCaption)
04168 {
04169   nsresult rv = NS_OK;
04170   
04171   PRBool childIsCaption = PR_FALSE;
04172   PRBool isPseudoParent = PR_FALSE;
04173     
04174   nsIFrame* childFrame = nsnull;
04175   nsRefPtr<nsStyleContext> childStyleContext;
04176 
04177 
04178   // Resolve the style context and get its display
04179   childStyleContext = ResolveStyleContext(aParentFrame, aChildContent);
04180   const nsStyleDisplay* childDisplay = childStyleContext->GetStyleDisplay();
04181   if (nsLayoutAtoms::tableColGroupFrame == aParentFrameType &&
04182       NS_STYLE_DISPLAY_TABLE_COLUMN != childDisplay->mDisplay)
04183       return rv; // construct only table columns below colgroups
04184   
04185   switch (childDisplay->mDisplay) {
04186   case NS_STYLE_DISPLAY_TABLE:
04187     {
04188       PRBool pageBreakAfter = PR_FALSE;
04189 
04190       if (aState.mPresContext->IsPaginated()) {
04191         // See if there is a page break before, if so construct one. Also see if there is one after
04192         pageBreakAfter = PageBreakBefore(aState, aChildContent, aParentFrame,
04193                                          childStyleContext, aChildItems);
04194       }
04195       // construct the table frame
04196       nsIFrame* innerTableFrame;
04197       rv = ConstructTableFrame(aState, aChildContent,
04198                                aParentFrame, childStyleContext,
04199                                aTableCreator, PR_FALSE, aChildItems,
04200                                PR_TRUE, childFrame, innerTableFrame);
04201       if (NS_SUCCEEDED(rv) && pageBreakAfter) {
04202         // Construct the page break after
04203         ConstructPageBreakFrame(aState, aChildContent, aParentFrame,
04204                                 childStyleContext, aChildItems);
04205       }
04206     }
04207     // All done here
04208     return rv;
04209 
04210   case NS_STYLE_DISPLAY_TABLE_CAPTION:
04211     if (!aCaption) {  // only allow one caption
04212       nsIFrame* parentFrame = AdjustCaptionParentFrame(aParentFrame);
04213       rv = ConstructTableCaptionFrame(aState, aChildContent, parentFrame,
04214                                       childStyleContext, aTableCreator, 
04215                                       aChildItems, aCaption, isPseudoParent);
04216     }
04217     childIsCaption = PR_TRUE;
04218     break;
04219 
04220   case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
04221     rv = ConstructTableColGroupFrame(aState, aChildContent, aParentFrame,
04222                                      childStyleContext, aTableCreator,
04223                                      PR_FALSE, aChildItems, childFrame,
04224                                      isPseudoParent);
04225     break;
04226 
04227   case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
04228   case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
04229   case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
04230     rv = ConstructTableRowGroupFrame(aState, aChildContent, aParentFrame,
04231                                      childStyleContext, aTableCreator, 
04232                                      PR_FALSE, aChildItems, childFrame,
04233                                      isPseudoParent);
04234     break;
04235 
04236   case NS_STYLE_DISPLAY_TABLE_ROW:
04237     rv = ConstructTableRowFrame(aState, aChildContent, aParentFrame,
04238                                 childStyleContext, aTableCreator, 
04239                                 PR_FALSE, aChildItems, childFrame,
04240                                 isPseudoParent);
04241     break;
04242 
04243   case NS_STYLE_DISPLAY_TABLE_COLUMN:
04244     rv = ConstructTableColFrame(aState, aChildContent, aParentFrame,
04245                                 childStyleContext, aTableCreator, 
04246                                 PR_FALSE, aChildItems, childFrame,
04247                                 isPseudoParent);
04248     break;
04249 
04250 
04251   case NS_STYLE_DISPLAY_TABLE_CELL:
04252     nsIFrame* innerCell;
04253     rv = ConstructTableCellFrame(aState, aChildContent, aParentFrame,
04254                                  childStyleContext, aTableCreator, PR_FALSE, 
04255                                  aChildItems, childFrame, innerCell,
04256                                  isPseudoParent);
04257     break;
04258 
04259   case NS_STYLE_DISPLAY_NONE:
04260     aState.mFrameManager->SetUndisplayedContent(aChildContent,
04261                                                 childStyleContext);
04262     break;
04263 
04264   default:
04265     {
04266       // ConstructTableForeignFrame puts the frame in the right child list and
04267       // all that
04268       return ConstructTableForeignFrame(aState, aChildContent, aParentFrame,
04269                                         childStyleContext, aTableCreator, 
04270                                         aChildItems);
04271     }
04272   }
04273 
04274   // for every table related frame except captions and ones with pseudo parents, 
04275   // link into the child list
04276   if (childFrame && !childIsCaption && !isPseudoParent) {
04277     aChildItems.AddChild(childFrame);
04278   }
04279   return rv;
04280 }
04281 
04282 const nsStyleDisplay* 
04283 nsCSSFrameConstructor::GetDisplay(nsIFrame* aFrame)
04284 {
04285   if (nsnull == aFrame) {
04286     return nsnull;
04287   }
04288   return aFrame->GetStyleContext()->GetStyleDisplay();
04289 }
04290 
04291 /***********************************************
04292  * END TABLE SECTION
04293  ***********************************************/
04294 
04295 nsresult
04296 nsCSSFrameConstructor::ConstructDocElementTableFrame(nsIContent*     aDocElement,
04297                                                      nsIFrame*       aParentFrame,
04298                                                      nsIFrame**      aNewTableFrame,
04299                                                      nsFrameConstructorState& aState)
04300 {
04301   nsFrameItems    frameItems;
04302 
04303   // XXXbz this is wrong.  We should at least be setting the fixed container in
04304   // the framestate here.  Better yet, we should pass through aState
04305   // unmodified.  Can't do that, though, because then a fixed or absolute
04306   // positioned root table with auto offsets would look for a block to compute
04307   // its hypothetical box and crash.  So we just disable fixed positioning
04308   // altogether in documents where the root is a table.  Oh, well.
04309   nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull,
04310                                 aState.mFrameState);
04311   ConstructFrame(state, aDocElement, aParentFrame, frameItems);
04312   *aNewTableFrame = frameItems.childList;
04313   if (!*aNewTableFrame) {
04314     NS_WARNING("cannot get table contentFrame");
04315     // XXXbz maybe better to return the error from ConstructFrame?
04316     return NS_ERROR_FAILURE;
04317   }
04318   return NS_OK;
04319 }
04320 
04321 static PRBool CheckOverflow(nsPresContext* aPresContext,
04322                             const nsStyleDisplay* aDisplay)
04323 {
04324   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
04325     return PR_FALSE;
04326 
04327   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
04328     aPresContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_HIDDEN,
04329                                               NS_STYLE_OVERFLOW_HIDDEN);
04330   else
04331     aPresContext->SetViewportOverflowOverride(aDisplay->mOverflowX,
04332                                               aDisplay->mOverflowY);
04333   return PR_TRUE;
04334 }
04335 
04344 nsIContent*
04345 nsCSSFrameConstructor::PropagateScrollToViewport()
04346 {
04347   // Set default
04348   nsPresContext* presContext = mPresShell->GetPresContext();
04349   presContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_AUTO,
04350                                            NS_STYLE_OVERFLOW_AUTO);
04351 
04352   // We never mess with the viewport scroll state
04353   // when printing or in print preview
04354   if (presContext->IsPaginated()) {
04355     return nsnull;
04356   }
04357 
04358   nsIContent* docElement = mDocument->GetRootContent();
04359 
04360   // Check the style on the document root element
04361   nsStyleSet *styleSet = mPresShell->StyleSet();
04362   nsRefPtr<nsStyleContext> rootStyle;
04363   rootStyle = styleSet->ResolveStyleFor(docElement, nsnull);
04364   if (!rootStyle) {
04365     return nsnull;
04366   }
04367   if (CheckOverflow(presContext, rootStyle->GetStyleDisplay())) {
04368     // tell caller we stole the overflow style from the root element
04369     return docElement;
04370   }
04371   
04372   // Don't look in the BODY for non-HTML documents or HTML documents
04373   // with non-HTML roots
04374   // XXX this should be earlier; we shouldn't even look at the document root
04375   // for non-HTML documents. Fix this once we support explicit CSS styling
04376   // of the viewport
04377   // XXX what about XHTML?
04378   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
04379   if (!htmlDoc || !docElement->IsContentOfType(nsIContent::eHTML)) {
04380     return nsnull;
04381   }
04382   
04383   nsCOMPtr<nsIDOMHTMLElement> body;
04384   htmlDoc->GetBody(getter_AddRefs(body));
04385   nsCOMPtr<nsIContent> bodyElement = do_QueryInterface(body);
04386   
04387   if (!bodyElement ||
04388       !bodyElement->GetNodeInfo()->Equals(nsHTMLAtoms::body)) {
04389     // The body is not a <body> tag, it's a <frameset>.
04390     return nsnull;
04391   }
04392 
04393   nsRefPtr<nsStyleContext> bodyStyle;
04394   bodyStyle = styleSet->ResolveStyleFor(bodyElement, rootStyle);
04395   if (!bodyStyle) {
04396     return nsnull;
04397   }
04398 
04399   if (CheckOverflow(presContext, bodyStyle->GetStyleDisplay())) {
04400     // tell caller we stole the overflow style from the body element
04401     return bodyElement;
04402   }
04403 
04404   return nsnull;
04405 }
04406 
04410 nsresult
04411 nsCSSFrameConstructor::ConstructDocElementFrame(nsFrameConstructorState& aState,
04412                                                 nsIContent*              aDocElement,
04413                                                 nsIFrame*                aParentFrame,
04414                                                 nsIFrame**               aNewFrame)
04415 {
04416     // how the root frame hierarchy should look
04417 
04418     /*
04419 
04420 ---------------No Scrollbars------
04421 
04422 
04423      AreaFrame or BoxFrame (InitialContainingBlock)
04424   
04425 
04426 
04427 ---------------Gfx Scrollbars ------
04428 
04429 
04430      ScrollFrame
04431 
04432          ^
04433          |
04434          |
04435      AreaFrame or BoxFrame (InitialContainingBlock)
04436           
04437 */    
04438 
04439   *aNewFrame = nsnull;
04440 
04441   if (!mTempFrameTreeState)
04442     aState.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
04443 
04444   // ----- reattach gfx scrollbars ------
04445   // Gfx scrollframes were created in the root frame but the primary frame map may have been destroyed if a 
04446   // new style sheet was loaded so lets reattach the frames to their content.
04447   // XXX this seems truly bogus, we wipe out mGfxScrollFrame below
04448   if (mGfxScrollFrame) {
04449     nsIFrame* gfxScrollbarFrame1 = mGfxScrollFrame->GetFirstChild(nsnull);
04450     if (gfxScrollbarFrame1) {
04451       // XXX This works, but why?
04452       aState.mFrameManager->
04453         SetPrimaryFrameFor(gfxScrollbarFrame1->GetContent(), gfxScrollbarFrame1);
04454 
04455       nsIFrame* gfxScrollbarFrame2 = gfxScrollbarFrame1->GetNextSibling();
04456       if (gfxScrollbarFrame2) {
04457         // XXX This works, but why?
04458         aState.mFrameManager->
04459           SetPrimaryFrameFor(gfxScrollbarFrame2->GetContent(), gfxScrollbarFrame2);
04460       }
04461     }
04462   }
04463 
04464   // --------- CREATE AREA OR BOX FRAME -------
04465   nsRefPtr<nsStyleContext> styleContext;
04466   styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
04467                                                          nsnull);
04468 
04469   const nsStyleDisplay* display = styleContext->GetStyleDisplay();
04470 
04471   // Ensure that our XBL bindings are installed.
04472   if (display->mBinding) {
04473     // Get the XBL loader.
04474     nsresult rv;
04475     PRBool resolveStyle;
04476     
04477     nsIXBLService * xblService = GetXBLService();
04478     if (!xblService)
04479       return NS_ERROR_FAILURE;
04480 
04481     nsRefPtr<nsXBLBinding> binding;
04482     rv = xblService->LoadBindings(aDocElement, display->mBinding, PR_FALSE,
04483                                   getter_AddRefs(binding), &resolveStyle);
04484     if (NS_FAILED(rv))
04485       return NS_OK; // Binding will load asynchronously.
04486 
04487     if (binding) {
04488       mDocument->BindingManager()->AddToAttachedQueue(binding);
04489     }
04490 
04491     if (resolveStyle) {
04492       styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
04493                                                              nsnull);
04494       display = styleContext->GetStyleDisplay();
04495     }
04496   }
04497 
04498   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
04499 
04500   PRBool propagatedScrollToViewport =
04501     PropagateScrollToViewport() == aDocElement;
04502 
04503   // The document root should not be scrollable in any paginated context,
04504   // even in print preview.
04505   PRBool isScrollable = display->IsScrollableOverflow()
04506     && !aState.mPresContext->IsPaginated()
04507     && !propagatedScrollToViewport;
04508 
04509   nsIFrame* scrollFrame = nsnull;
04510 
04511   // build a scrollframe
04512   if (isScrollable) {
04513     nsRefPtr<nsStyleContext> newContext;
04514 
04515     newContext = BeginBuildingScrollFrame( aState,
04516                                            aDocElement,
04517                                            styleContext,
04518                                            aParentFrame,
04519                                            nsnull,
04520                                            nsCSSAnonBoxes::scrolledContent,
04521                                            PR_FALSE,
04522                                            scrollFrame);
04523 
04524     styleContext = newContext;
04525     aParentFrame = scrollFrame;
04526   }
04527 
04528   nsIFrame* contentFrame = nsnull;
04529   PRBool isBlockFrame = PR_FALSE;
04530   nsresult rv;
04531 
04532   // The rules from CSS 2.1, section 9.2.4, have already been applied
04533   // by the style system, so we can assume that display->mDisplay is
04534   // either NONE, BLOCK, or TABLE.
04535 
04536   PRBool docElemIsTable = display->mDisplay == NS_STYLE_DISPLAY_TABLE;
04537 
04538   if (docElemIsTable) {
04539     // if the document is a table then just populate it.
04540     rv = ConstructDocElementTableFrame(aDocElement, aParentFrame, &contentFrame,
04541                                        aState);
04542     if (NS_FAILED(rv)) {
04543       return rv;
04544     }
04545     styleContext = contentFrame->GetStyleContext();
04546   } else {
04547     // otherwise build a box or a block
04548 #ifdef MOZ_XUL
04549     if (aDocElement->IsContentOfType(nsIContent::eXUL)) {
04550       rv = NS_NewDocElementBoxFrame(mPresShell, &contentFrame);
04551       if (NS_FAILED(rv)) {
04552         return rv;
04553       }
04554     }
04555     else
04556 #endif 
04557 #ifdef MOZ_SVG
04558     if (aDocElement->GetNameSpaceID() == kNameSpaceID_SVG &&
04559         nsSVGUtils::SVGEnabled()) {
04560       rv = NS_NewSVGOuterSVGFrame(mPresShell, aDocElement, &contentFrame);
04561       if (NS_FAILED(rv)) {
04562         return rv;
04563       }
04564     }
04565     else 
04566 #endif
04567     {
04568       rv = NS_NewDocumentElementFrame(mPresShell, &contentFrame);
04569       if (NS_FAILED(rv)) {
04570         return rv;
04571       }
04572       isBlockFrame = PR_TRUE;
04573     }
04574 
04575     // initialize the child
04576     InitAndRestoreFrame(aState, aDocElement, aParentFrame, styleContext,
04577                         nsnull, contentFrame);
04578   }
04579 
04580   // set the primary frame
04581   aState.mFrameManager->SetPrimaryFrameFor(aDocElement, contentFrame);
04582 
04583   // Finish building the scrollframe
04584   if (isScrollable) {
04585     FinishBuildingScrollFrame(aParentFrame, contentFrame);
04586     // primary is set above (to the contentFrame)
04587     
04588     *aNewFrame = scrollFrame;
04589   } else {
04590     // if not scrollable the new frame is the content frame.
04591     *aNewFrame = contentFrame;
04592   }
04593 
04594   mInitialContainingBlock = contentFrame;
04595   mInitialContainingBlockIsAbsPosContainer = PR_FALSE;
04596 
04597   // if it was a table then we don't need to process our children.
04598   if (!docElemIsTable) {
04599     // Process the child content
04600     nsFrameConstructorSaveState absoluteSaveState;
04601     nsFrameConstructorSaveState floatSaveState;
04602     nsFrameItems                childItems;
04603 
04604     if (isBlockFrame) {
04605       PRBool haveFirstLetterStyle, haveFirstLineStyle;
04606       HaveSpecialBlockStyle(aDocElement, styleContext,
04607                             &haveFirstLetterStyle, &haveFirstLineStyle);
04608       mInitialContainingBlockIsAbsPosContainer = PR_TRUE;
04609       aState.PushAbsoluteContainingBlock(contentFrame, absoluteSaveState);
04610       aState.PushFloatContainingBlock(contentFrame, floatSaveState,
04611                                       haveFirstLetterStyle,
04612                                       haveFirstLineStyle);
04613     }
04614 
04615     // Create any anonymous frames the doc element frame requires
04616     // This must happen before ProcessChildren to ensure that popups are
04617     // never constructed before the popupset.
04618     CreateAnonymousFrames(nsnull, aState, aDocElement, contentFrame,
04619                           PR_FALSE, childItems, PR_TRUE);
04620     ProcessChildren(aState, aDocElement, contentFrame, PR_TRUE, childItems,
04621                     isBlockFrame);
04622 
04623     // Set the initial child lists
04624     contentFrame->SetInitialChildList(aState.mPresContext, nsnull,
04625                                       childItems.childList);
04626   }
04627 
04628   return NS_OK;
04629 }
04630 
04631 
04632 nsresult
04633 nsCSSFrameConstructor::ConstructRootFrame(nsIContent*     aDocElement,
04634                                           nsIFrame**      aNewFrame)
04635 {
04636   NS_PRECONDITION(aNewFrame, "null out param");
04637   
04638   // how the root frame hierarchy should look
04639 
04640     /*
04641 
04642 ---------------No Scrollbars------
04643 
04644 
04645 
04646      ViewPortFrame (FixedContainingBlock) <---- RootView
04647 
04648          ^
04649          |
04650      RootFrame(DocElementContainingBlock)
04651   
04652 
04653 
04654 ---------------Gfx Scrollbars ------
04655 
04656 
04657      ViewPortFrame (FixedContainingBlock) <---- RootView
04658 
04659          ^
04660          |
04661      ScrollFrame
04662 
04663          ^
04664          |
04665      RootFrame(DocElementContainingBlock)
04666           
04667 */    
04668 
04669   // Set up our style rule observer.
04670   {
04671     nsCOMPtr<nsIStyleRuleSupplier> ruleSupplier =
04672       do_QueryInterface(mDocument->BindingManager());
04673     mPresShell->StyleSet()->SetStyleRuleSupplier(ruleSupplier);
04674   }
04675 
04676   // --------- BUILD VIEWPORT -----------
04677   nsIFrame*                 viewportFrame = nsnull;
04678   nsRefPtr<nsStyleContext> viewportPseudoStyle;
04679   nsStyleSet *styleSet = mPresShell->StyleSet();
04680 
04681   viewportPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
04682                                                         nsCSSAnonBoxes::viewport,
04683                                                         nsnull);
04684 
04685   NS_NewViewportFrame(mPresShell, &viewportFrame);
04686 
04687   nsPresContext* presContext = mPresShell->GetPresContext();
04688 
04689   // XXXbz do we _have_ to pass a null content pointer to that frame?
04690   // Would it really kill us to pass in the root element or something?
04691   // What would that break?
04692   viewportFrame->Init(presContext, nsnull, nsnull,
04693                       viewportPseudoStyle, nsnull);
04694 
04695   // Bind the viewport frame to the root view
04696   nsIViewManager* viewManager = mPresShell->GetViewManager();
04697   nsIView*        rootView;
04698 
04699   viewManager->GetRootView(rootView);
04700   viewportFrame->SetView(rootView);
04701 
04702   nsContainerFrame::SyncFrameViewProperties(presContext, viewportFrame,
04703                                             viewportPseudoStyle, rootView);
04704 
04705   // The viewport is the containing block for 'fixed' elements
04706   mFixedContainingBlock = viewportFrame;
04707 
04708   // --------- CREATE ROOT FRAME -------
04709 
04710 
04711     // Create the root frame. The document element's frame is a child of the
04712     // root frame.
04713     //
04714     // The root frame serves two purposes:
04715     // - reserves space for any margins needed for the document element's frame
04716     // - renders the document element's background. This ensures the background covers
04717     //   the entire canvas as specified by the CSS2 spec
04718 
04719     PRBool isPaginated = presContext->IsPaginated();
04720     PRBool isPrintPreview =
04721       presContext->Type() == nsPresContext::eContext_PrintPreview;
04722 
04723     nsIFrame* rootFrame = nsnull;
04724     nsIAtom* rootPseudo;
04725         
04726     if (!isPaginated) {
04727 #ifdef MOZ_XUL
04728         if (aDocElement->IsContentOfType(nsIContent::eXUL)) 
04729         {
04730           NS_NewRootBoxFrame(mPresShell, &rootFrame);
04731         } else 
04732 #endif
04733         {
04734           NS_NewCanvasFrame(mPresShell, &rootFrame);
04735         }
04736 
04737         rootPseudo = nsCSSAnonBoxes::canvas;
04738         mDocElementContainingBlock = rootFrame;
04739     } else {
04740         // Create a page sequence frame
04741         NS_NewSimplePageSequenceFrame(mPresShell, &rootFrame);
04742         mPageSequenceFrame = rootFrame;
04743         rootPseudo = nsCSSAnonBoxes::pageSequence;
04744     }
04745 
04746 
04747   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
04748 
04749   // If the device supports scrolling (e.g., in galley mode on the screen and
04750   // for print-preview, but not when printing), then create a scroll frame that
04751   // will act as the scrolling mechanism for the viewport. 
04752   // XXX Do we even need a viewport when printing to a printer?
04753 
04754   // As long as the webshell doesn't prohibit it, and the device supports
04755   // it, create a scroll frame that will act as the scolling mechanism for
04756   // the viewport.
04757   //
04758   // Threre are three possible values stored in the docshell:
04759   //  1) nsIScrollable::Scrollbar_Never = no scrollbars
04760   //  2) nsIScrollable::Scrollbar_Auto = scrollbars appear if needed
04761   //  3) nsIScrollable::Scrollbar_Always = scrollbars always
04762   // Only need to create a scroll frame/view for cases 2 and 3.
04763 
04764   PRBool isHTML = aDocElement->IsContentOfType(nsIContent::eHTML);
04765   PRBool isXUL = PR_FALSE;
04766 
04767   if (!isHTML) {
04768     isXUL = aDocElement->IsContentOfType(nsIContent::eXUL);
04769   }
04770 
04771   // Never create scrollbars for XUL documents
04772   PRBool isScrollable = !isXUL;
04773 
04774   // Never create scrollbars for frameset documents.
04775   if (isHTML) {
04776     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
04777     if (htmlDoc && htmlDoc->GetIsFrameset())
04778       isScrollable = PR_FALSE;
04779   }
04780 
04781   if (isPaginated) {
04782     if (isPrintPreview) {
04783       isScrollable = presContext->HasPaginatedScrolling();
04784     } else {
04785       isScrollable = PR_FALSE; // we are printing
04786     }
04787   }
04788 
04789   // We no longer need to do overflow propagation here. It's taken care of
04790   // when we construct frames for the element whose overflow might be
04791   // propagated
04792   NS_ASSERTION(!isScrollable || !isXUL,
04793                "XUL documents should never be scrollable - see above");
04794 
04795   nsIFrame* newFrame = rootFrame;
04796   nsRefPtr<nsStyleContext> rootPseudoStyle;
04797   // we must create a state because if the scrollbars are GFX it needs the 
04798   // state to build the scrollbar frames.
04799   nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
04800 
04801   nsIFrame* parentFrame = viewportFrame;
04802 
04803   // If paginated, make sure we don't put scrollbars in
04804   if (!isScrollable) {
04805     rootPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
04806                                                       rootPseudo,
04807                                                       viewportPseudoStyle);
04808   } else {
04809       if (rootPseudo == nsCSSAnonBoxes::canvas) {
04810         rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
04811       } else {
04812         NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
04813                      "Unknown root pseudo");
04814         rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
04815       }
04816 
04817       // Build the frame. We give it the content we are wrapping which is the document,
04818       // the root frame, the parent view port frame, and we should get back the new
04819       // frame and the scrollable view if one was created.
04820 
04821       // resolve a context for the scrollframe
04822       nsRefPtr<nsStyleContext>  styleContext;
04823       styleContext = styleSet->ResolvePseudoStyleFor(nsnull,
04824                                                      nsCSSAnonBoxes::viewportScroll,
04825                                                      viewportPseudoStyle);
04826 
04827       // Note that the viewport scrollframe is always built with
04828       // overflow:auto style. This forces the scroll frame to create
04829       // anonymous content for both scrollbars. This is necessary even
04830       // if the HTML or BODY elements are overriding the viewport
04831       // scroll style to 'hidden' --- dynamic style changes might put
04832       // scrollbars back on the viewport and we don't want to have to
04833       // reframe the viewport to create the scrollbar content.
04834       newFrame = nsnull;
04835       rootPseudoStyle = BeginBuildingScrollFrame( state,
04836                                                   aDocElement,
04837                                                   styleContext,
04838                                                   viewportFrame,
04839                                                   nsnull,
04840                                                   rootPseudo,
04841                                                   PR_TRUE,
04842                                                   newFrame);
04843 
04844       nsIScrollableFrame* scrollable;
04845       CallQueryInterface(newFrame, &scrollable);
04846       NS_ENSURE_TRUE(scrollable, NS_ERROR_FAILURE);
04847 
04848       nsIScrollableView* scrollableView = scrollable->GetScrollableView();
04849       NS_ENSURE_TRUE(scrollableView, NS_ERROR_FAILURE);
04850 
04851       viewManager->SetRootScrollableView(scrollableView);
04852       parentFrame = newFrame;
04853 
04854       mGfxScrollFrame = newFrame;
04855   }
04856   
04857 
04858   rootFrame->Init(presContext, aDocElement, parentFrame,
04859                   rootPseudoStyle, nsnull);
04860   
04861   if (isScrollable) {
04862     FinishBuildingScrollFrame(parentFrame, rootFrame);
04863   }
04864   
04865   if (isPaginated) { // paginated
04866     // Create the first page
04867     // Set the initial child lists
04868     nsIFrame *pageFrame, *pageContentFrame;
04869     ConstructPageFrame(mPresShell, presContext, rootFrame, nsnull,
04870                        pageFrame, pageContentFrame);
04871     rootFrame->SetInitialChildList(presContext, nsnull, pageFrame);
04872 
04873     // The eventual parent of the document element frame.
04874     // XXX should this be set for every new page (in ConstructPageFrame)?
04875     mDocElementContainingBlock = pageContentFrame;
04876   }
04877 
04878   viewportFrame->SetInitialChildList(presContext, nsnull, newFrame);
04879   
04880   *aNewFrame = viewportFrame;
04881 
04882   return NS_OK;
04883 }
04884 
04885 nsresult
04886 nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*   aPresShell,
04887                                           nsPresContext* aPresContext,
04888                                           nsIFrame*       aParentFrame,
04889                                           nsIFrame*       aPrevPageFrame,
04890                                           nsIFrame*&      aPageFrame,
04891                                           nsIFrame*&      aPageContentFrame)
04892 {
04893   nsresult rv = NS_OK;
04894   rv = NS_NewPageFrame(aPresShell, &aPageFrame);
04895   if (NS_FAILED(rv))
04896     return rv;
04897 
04898   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
04899   nsStyleSet *styleSet = aPresShell->StyleSet();
04900 
04901   nsRefPtr<nsStyleContext> pagePseudoStyle;
04902   pagePseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
04903                                                     nsCSSAnonBoxes::page,
04904                                                     parentStyleContext);
04905 
04906   // Initialize the page frame and force it to have a view. This makes printing of
04907   // the pages easier and faster.
04908   aPageFrame->Init(aPresContext, nsnull, aParentFrame, pagePseudoStyle, aPrevPageFrame);
04909   // XXXbz should we be passing in a non-null aContentParentFrame?
04910   rv = nsHTMLContainerFrame::CreateViewForFrame(aPageFrame, nsnull, PR_TRUE);
04911   if (NS_FAILED(rv))
04912     return NS_ERROR_NULL_POINTER;
04913 
04914   NS_NewPageContentFrame(aPresShell, &aPageContentFrame);
04915 
04916   nsRefPtr<nsStyleContext> pageContentPseudoStyle;
04917   pageContentPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
04918                                                            nsCSSAnonBoxes::pageContent,
04919                                                            pagePseudoStyle);
04920 
04921   // Initialize the page content frame and force it to have a view. Also make it the
04922   // containing block for fixed elements which are repeated on every page.
04923   aPageContentFrame->Init(aPresContext, nsnull, aPageFrame, pageContentPseudoStyle, nsnull);
04924   // XXXbz should we be passing in a non-null aContentParentFrame?
04925   nsHTMLContainerFrame::CreateViewForFrame(aPageContentFrame, nsnull, PR_TRUE);
04926   if (NS_FAILED(rv))
04927     return NS_ERROR_NULL_POINTER;
04928   mFixedContainingBlock = aPageContentFrame;
04929 
04930   aPageFrame->SetInitialChildList(aPresContext, nsnull, aPageContentFrame);
04931 
04932   // Fixed pos kids are taken care of directly in CreateContinuingFrame()
04933   
04934   return rv;
04935 }
04936 
04937 /* static */
04938 nsresult
04939 nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*    aPresShell, 
04940                                                  nsPresContext*  aPresContext,
04941                                                  nsFrameManager*  aFrameManager,
04942                                                  nsIContent*      aContent,
04943                                                  nsIFrame*        aFrame,
04944                                                  nsStyleContext*  aStyleContext,
04945                                                  nsIFrame*        aParentFrame,
04946                                                  nsIFrame**       aPlaceholderFrame)
04947 {
04948   nsPlaceholderFrame* placeholderFrame;
04949   nsresult            rv = NS_NewPlaceholderFrame(aPresShell, (nsIFrame**)&placeholderFrame);
04950 
04951   if (NS_SUCCEEDED(rv)) {
04952     // The placeholder frame gets a pseudo style context
04953     nsRefPtr<nsStyleContext> placeholderStyle;
04954     nsStyleContext* parentContext = aStyleContext->GetParent();
04955     placeholderStyle = aPresShell->StyleSet()->
04956       ResolveStyleForNonElement(parentContext);
04957     placeholderFrame->Init(aPresContext, aContent, aParentFrame,
04958                            placeholderStyle, nsnull);
04959   
04960     // The placeholder frame has a pointer back to the out-of-flow frame
04961     placeholderFrame->SetOutOfFlowFrame(aFrame);
04962   
04963     aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
04964 
04965     // Add mapping from absolutely positioned frame to its placeholder frame
04966     aFrameManager->RegisterPlaceholderFrame(placeholderFrame);
04967 
04968     *aPlaceholderFrame = NS_STATIC_CAST(nsIFrame*, placeholderFrame);
04969   }
04970 
04971   return rv;
04972 }
04973 
04974 nsresult
04975 nsCSSFrameConstructor::ConstructRadioControlFrame(nsIFrame**      aNewFrame,
04976                                                   nsIContent*     aContent,
04977                                                   nsStyleContext* aStyleContext)
04978 {
04979   nsresult rv = NS_NewGfxRadioControlFrame(mPresShell, aNewFrame);
04980   if (NS_FAILED(rv)) {
04981     *aNewFrame = nsnull;
04982     return rv;
04983   }
04984 
04985   nsRefPtr<nsStyleContext> radioStyle;
04986   radioStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(aContent,
04987                                                              nsCSSAnonBoxes::radio,
04988                                                              aStyleContext);
04989   nsIRadioControlFrame* radio = nsnull;
04990   if (*aNewFrame && NS_SUCCEEDED(CallQueryInterface(*aNewFrame, &radio))) {
04991     radio->SetRadioButtonFaceStyleContext(radioStyle);
04992   }
04993   return rv;
04994 }
04995 
04996 nsresult
04997 nsCSSFrameConstructor::ConstructCheckboxControlFrame(nsIFrame**      aNewFrame,
04998                                                      nsIContent*     aContent,
04999                                                      nsStyleContext* aStyleContext)
05000 {
05001   nsresult rv = NS_NewGfxCheckboxControlFrame(mPresShell, aNewFrame);
05002   if (NS_FAILED(rv)) {
05003     *aNewFrame = nsnull;
05004     return rv;
05005   }
05006 
05007   nsRefPtr<nsStyleContext> checkboxStyle;
05008   checkboxStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(aContent,
05009                                                                 nsCSSAnonBoxes::check, 
05010                                                                 aStyleContext);
05011   nsICheckboxControlFrame* checkbox = nsnull;
05012   if (*aNewFrame && NS_SUCCEEDED(CallQueryInterface(*aNewFrame, &checkbox))) {
05013     checkbox->SetCheckboxFaceStyleContext(checkboxStyle);
05014   }
05015   return rv;
05016 }
05017 
05018 nsresult
05019 nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
05020                                             nsIContent*              aContent,
05021                                             nsIFrame*                aParentFrame,
05022                                             nsIAtom*                 aTag,
05023                                             nsStyleContext*          aStyleContext,
05024                                             nsIFrame*&               aNewFrame,
05025                                             const nsStyleDisplay*    aStyleDisplay,
05026                                             PRBool&                  aFrameHasBeenInitialized,
05027                                             nsFrameItems&            aFrameItems)
05028 {
05029   nsresult rv = NS_OK;
05030   const PRInt32 kNoSizeSpecified = -1;
05031 
05032   // Construct a frame-based listbox or combobox
05033   nsCOMPtr<nsIDOMHTMLSelectElement> sel(do_QueryInterface(aContent));
05034   PRInt32 size = 1;
05035   if (sel) {
05036     sel->GetSize(&size); 
05037     PRBool multipleSelect = PR_FALSE;
05038     sel->GetMultiple(&multipleSelect);
05039      // Construct a combobox if size=1 or no size is specified and its multiple select
05040     if (((1 == size || 0 == size) || (kNoSizeSpecified  == size)) && (PR_FALSE == multipleSelect)) {
05041         // Construct a frame-based combo box.
05042         // The frame-based combo box is built out of three parts. A display area, a button and
05043         // a dropdown list. The display area and button are created through anonymous content.
05044         // The drop-down list's frame is created explicitly. The combobox frame shares it's content
05045         // with the drop-down list.
05046       PRUint32 flags = NS_BLOCK_SHRINK_WRAP | NS_BLOCK_SPACE_MGR;
05047       nsIFrame * comboboxFrame;
05048       rv = NS_NewComboboxControlFrame(mPresShell, &comboboxFrame, flags);
05049 
05050       // Save the history state so we don't restore during construction
05051       // since the complete tree is required before we restore.
05052       nsILayoutHistoryState *historyState = aState.mFrameState;
05053       aState.mFrameState = nsnull;
05054       // Initialize the combobox frame
05055       InitAndRestoreFrame(aState, aContent,
05056                           aState.GetGeometricParent(aStyleDisplay, aParentFrame),
05057                           aStyleContext, nsnull, comboboxFrame);
05058 
05059       nsHTMLContainerFrame::CreateViewForFrame(comboboxFrame, aParentFrame, PR_FALSE);
05060 
05061       rv = aState.AddChild(comboboxFrame, aFrameItems, aStyleDisplay,
05062                            aContent, aStyleContext, aParentFrame);
05063       if (NS_FAILED(rv)) {
05064         return rv;
05065       }
05066       
05068       // Combobox - Old Native Implementation
05070       nsIComboboxControlFrame* comboBox = nsnull;
05071       CallQueryInterface(comboboxFrame, &comboBox);
05072       NS_ASSERTION(comboBox, "NS_NewComboboxControlFrame returned frame that "
05073                              "doesn't implement nsIComboboxControlFrame");
05074 
05075         // Create a listbox
05076       nsIFrame * listFrame;
05077       rv = NS_NewListControlFrame(mPresShell, &listFrame);
05078 
05079         // Notify the listbox that it is being used as a dropdown list.
05080       nsIListControlFrame * listControlFrame;
05081       rv = CallQueryInterface(listFrame, &listControlFrame);
05082       if (NS_SUCCEEDED(rv)) {
05083         listControlFrame->SetComboboxFrame(comboboxFrame);
05084       }
05085          // Notify combobox that it should use the listbox as it's popup
05086       comboBox->SetDropDown(listFrame);
05087 
05088         // Resolve pseudo element style for the dropdown list 
05089       nsRefPtr<nsStyleContext> listStyle;
05090       listStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(aContent, 
05091                                                                 nsCSSAnonBoxes::dropDownList, 
05092                                                                 aStyleContext);
05093 
05094       NS_ASSERTION(!listStyle->GetStyleDisplay()->IsPositioned(),
05095                    "Ended up with positioned dropdown list somehow.");
05096       NS_ASSERTION(!listStyle->GetStyleDisplay()->IsFloating(),
05097                    "Ended up with floating dropdown list somehow.");
05098       
05099       // Initialize the scroll frame positioned. Note that it is NOT
05100       // initialized as absolutely positioned.
05101       nsIFrame* newFrame = nsnull;
05102       nsIFrame* scrolledFrame = nsnull;
05103       NS_NewSelectsAreaFrame(mPresShell, &scrolledFrame, flags);
05104 
05105       // make sure any existing anonymous content is cleared out. Gfx scroll frame construction
05106       // should reset it to just be the anonymous scrollbars, but we don't want to depend
05107       // on that.
05108       mPresShell->SetAnonymousContentFor(aContent, nsnull);
05109 
05110       InitializeSelectFrame(aState, listFrame,
05111                             scrolledFrame, aContent, comboboxFrame,
05112                             listStyle, PR_TRUE, aFrameItems);
05113       newFrame = listFrame;
05114 
05115         // Set flag so the events go to the listFrame not child frames.
05116         // XXX: We should replace this with a real widget manager similar
05117         // to how the nsFormControlFrame works. Re-directing events is a temporary Kludge.
05118       NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nsnull");
05119       //listFrame->GetView()->SetViewFlags(NS_VIEW_PUBLIC_FLAG_DONT_CHECK_CHILDREN);
05120 
05121       // Create display and button frames from the combobox's anonymous content.
05122       // The anonymous content is appended to existing anonymous content for this
05123       // element (the scrollbars).
05124 
05125       nsFrameItems childItems;
05126       CreateAnonymousFrames(nsHTMLAtoms::combobox, aState, aContent,
05127                             comboboxFrame, PR_TRUE, childItems);
05128   
05129       comboboxFrame->SetInitialChildList(aState.mPresContext, nsnull,
05130                                          childItems.childList);
05131 
05132       // Initialize the additional popup child list which contains the
05133       // dropdown list frame.
05134       nsFrameItems popupItems;
05135       popupItems.AddChild(listFrame);
05136       comboboxFrame->SetInitialChildList(aState.mPresContext,
05137                                          nsLayoutAtoms::popupList,
05138                                          popupItems.childList);
05139 
05140       aNewFrame = comboboxFrame;
05141       aFrameHasBeenInitialized = PR_TRUE;
05142       aState.mFrameState = historyState;
05143       if (aState.mFrameState && aState.mFrameManager) {
05144         // Restore frame state for the entire subtree of |comboboxFrame|.
05145         aState.mFrameManager->RestoreFrameState(comboboxFrame,
05146                                                 aState.mFrameState);
05147       }
05148     } else {
05150       // ListBox - Old Native Implementation
05152       nsIFrame * listFrame;
05153       rv = NS_NewListControlFrame(mPresShell, &listFrame);
05154 
05155       PRUint32 flags = NS_BLOCK_SHRINK_WRAP | NS_BLOCK_SPACE_MGR;
05156       nsIFrame* scrolledFrame = nsnull;
05157       NS_NewSelectsAreaFrame(mPresShell, &scrolledFrame, flags);
05158 
05159       // ******* this code stolen from Initialze ScrollFrame ********
05160       // please adjust this code to use BuildScrollFrame.
05161 
05162       InitializeSelectFrame(aState, listFrame,
05163                             scrolledFrame, aContent, aParentFrame,
05164                             aStyleContext, PR_FALSE, aFrameItems);
05165 
05166       aNewFrame = listFrame;
05167 
05168       aFrameHasBeenInitialized = PR_TRUE;
05169     }
05170   }
05171   return rv;
05172 
05173 }
05174 
05180 nsresult
05181 nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
05182                                              nsIFrame*                scrollFrame,
05183                                              nsIFrame*                scrolledFrame,
05184                                              nsIContent*              aContent,
05185                                              nsIFrame*                aParentFrame,
05186                                              nsStyleContext*          aStyleContext,
05187                                              PRBool                   aBuildCombobox,
05188                                              nsFrameItems&            aFrameItems)
05189 {
05190   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
05191 
05192   // Initialize it
05193   nsIFrame* geometricParent = aState.GetGeometricParent(display, aParentFrame);
05194     
05195   // We don't call InitAndRestoreFrame for scrollFrame because we can only
05196   // restore the frame state after its parts have been created (in particular,
05197   // the scrollable view). So we have to split Init and Restore.
05198 
05199   // Initialize the frame
05200   scrollFrame->Init(aState.mPresContext, aContent, geometricParent,
05201                     aStyleContext, nsnull);
05202 
05203   if (!aBuildCombobox) {
05204     nsresult rv = aState.AddChild(scrollFrame, aFrameItems, display,
05205                                   aContent, aStyleContext, aParentFrame);
05206     if (NS_FAILED(rv)) {
05207       return rv;
05208     }
05209   }
05210       
05211   nsHTMLContainerFrame::CreateViewForFrame(scrollFrame, aParentFrame,
05212                                            aBuildCombobox);
05213   if (aBuildCombobox) {
05214     // Give the drop-down list a popup widget
05215     nsIView* view = scrollFrame->GetView();
05216     NS_ASSERTION(view, "We asked for a view but didn't get one");
05217     if (view) {
05218       view->GetViewManager()->SetViewFloating(view, PR_TRUE);
05219 
05220       nsWidgetInitData widgetData;
05221       widgetData.mWindowType  = eWindowType_popup;
05222       widgetData.mBorderStyle = eBorderStyle_default;
05223 
05224 #ifdef XP_MACOSX
05225       static NS_DEFINE_IID(kCPopUpCID,  NS_POPUP_CID);
05226       view->CreateWidget(kCPopUpCID, &widgetData, nsnull);
05227 #else
05228       static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
05229       view->CreateWidget(kCChildCID, &widgetData, nsnull);
05230 #endif
05231     }
05232   }
05233 
05234   nsStyleContext* scrolledPseudoStyle;
05235   BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame,
05236                    geometricParent, aParentFrame, scrollFrame,
05237                    scrolledPseudoStyle);
05238 
05239   if (aState.mFrameState && aState.mFrameManager) {
05240     // Restore frame state for the scroll frame
05241     aState.mFrameManager->RestoreFrameStateFor(scrollFrame, aState.mFrameState);
05242   }
05243 
05244   // The area frame is a float container
05245   PRBool haveFirstLetterStyle, haveFirstLineStyle;
05246   HaveSpecialBlockStyle(aContent, aStyleContext,
05247                         &haveFirstLetterStyle, &haveFirstLineStyle);
05248   nsFrameConstructorSaveState floatSaveState;
05249   aState.PushFloatContainingBlock(scrolledFrame, floatSaveState,
05250                                   haveFirstLetterStyle, haveFirstLineStyle);
05251 
05252   // Process children
05253   nsFrameConstructorSaveState absoluteSaveState;
05254   nsFrameItems                childItems;
05255 
05256   if (display->IsPositioned()) {
05257     // The area frame becomes a container for child frames that are
05258     // absolutely positioned
05259     aState.PushAbsoluteContainingBlock(scrolledFrame, absoluteSaveState);
05260   }
05261 
05262   ProcessChildren(aState, aContent, scrolledFrame, PR_FALSE,
05263                   childItems, PR_TRUE);
05264 
05265   // if a select is being created with zero options we need to create
05266   // a special pseudo frame so it can be sized as best it can
05267   nsCOMPtr<nsIDOMHTMLSelectElement> selectElement(do_QueryInterface(aContent));
05268   if (selectElement) {
05269     AddDummyFrameToSelect(aState, scrollFrame, scrolledFrame, &childItems,
05270                           aContent, selectElement);
05271   }
05274 
05275   // Set the scrolled frame's initial child lists
05276   scrolledFrame->SetInitialChildList(aState.mPresContext, nsnull,
05277                                      childItems.childList);
05278   return NS_OK;
05279 }
05280 
05281 nsresult
05282 nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
05283                                               nsIContent*              aContent,
05284                                               nsIFrame*                aParentFrame,
05285                                               nsIAtom*                 aTag,
05286                                               nsStyleContext*          aStyleContext,
05287                                               nsIFrame*&               aNewFrame,
05288                                               nsFrameItems&            aFrameItems,
05289                                               const nsStyleDisplay*    aStyleDisplay,
05290                                               PRBool&                  aFrameHasBeenInitialized)
05291 {
05292   nsIFrame * newFrame;
05293   nsresult rv = NS_NewFieldSetFrame(mPresShell, &newFrame, NS_BLOCK_SPACE_MGR);
05294   if (NS_FAILED(rv)) {
05295     return rv;
05296   }
05297 
05298   // Initialize it
05299   InitAndRestoreFrame(aState, aContent, 
05300                       aState.GetGeometricParent(aStyleDisplay, aParentFrame),
05301                       aStyleContext, nsnull, newFrame);
05302 
05303   // See if we need to create a view, e.g. the frame is absolutely
05304   // positioned
05305   nsHTMLContainerFrame::CreateViewForFrame(newFrame, aParentFrame, PR_FALSE);
05306 
05307   nsIFrame* areaFrame;
05308   NS_NewAreaFrame(mPresShell, &areaFrame,
05309                   NS_BLOCK_SPACE_MGR | NS_BLOCK_SHRINK_WRAP | NS_BLOCK_MARGIN_ROOT);
05310 
05311   // Resolve style and initialize the frame
05312   nsRefPtr<nsStyleContext> styleContext;
05313   styleContext = mPresShell->StyleSet()->ResolvePseudoStyleFor(aContent,
05314                                                                nsCSSAnonBoxes::fieldsetContent,
05315                                                                aStyleContext);
05316   InitAndRestoreFrame(aState, aContent, newFrame, styleContext, nsnull,
05317                       areaFrame);
05318 
05319   rv = aState.AddChild(newFrame, aFrameItems, aStyleDisplay, aContent,
05320                        aStyleContext, aParentFrame);
05321   if (NS_FAILED(rv)) {
05322     return rv;
05323   }
05324   
05325 
05326   // The area frame is a float container
05327   PRBool haveFirstLetterStyle, haveFirstLineStyle;
05328   HaveSpecialBlockStyle(aContent, aStyleContext,
05329                         &haveFirstLetterStyle, &haveFirstLineStyle);
05330   nsFrameConstructorSaveState floatSaveState;
05331   aState.PushFloatContainingBlock(areaFrame, floatSaveState,
05332                                   haveFirstLetterStyle,
05333                                   haveFirstLineStyle);
05334 
05335   // Process children
05336   nsFrameConstructorSaveState absoluteSaveState;
05337   nsFrameItems                childItems;
05338 
05339   if (aStyleDisplay->IsPositioned()) {
05340     // The area frame becomes a container for child frames that are
05341     // absolutely positioned
05342     aState.PushAbsoluteContainingBlock(areaFrame, absoluteSaveState);
05343   }
05344 
05345   ProcessChildren(aState, aContent, areaFrame, PR_FALSE,
05346                   childItems, PR_TRUE);
05347 
05348   static NS_DEFINE_IID(kLegendFrameCID, NS_LEGEND_FRAME_CID);
05349   nsIFrame * child      = childItems.childList;
05350   nsIFrame * previous   = nsnull;
05351   nsIFrame* legendFrame = nsnull;
05352   while (nsnull != child) {
05353     nsresult result = child->QueryInterface(kLegendFrameCID, (void**)&legendFrame);
05354     if (NS_SUCCEEDED(result) && legendFrame) {
05355       // We want the legend to be the first frame in the fieldset child list.
05356       // That way the EventStateManager will do the right thing when tabbing
05357       // from a selection point within the legend (bug 236071), which is
05358       // used for implementing legend access keys (bug 81481).
05359       // GetAdjustedParentFrame() below depends on this frame order.
05360       if (nsnull != previous) {
05361         previous->SetNextSibling(legendFrame->GetNextSibling());
05362       } else {
05363         childItems.childList = legendFrame->GetNextSibling();
05364       }
05365       legendFrame->SetNextSibling(areaFrame);
05366       legendFrame->SetParent(newFrame);
05367       break;
05368     }
05369     previous = child;
05370     child = child->GetNextSibling();
05371   }
05372 
05373   // Set the scrolled frame's initial child lists
05374   areaFrame->SetInitialChildList(aState.mPresContext, nsnull,
05375                                  childItems.childList);
05376 
05377   // Set the scroll frame's initial child list
05378   newFrame->SetInitialChildList(aState.mPresContext, nsnull,
05379                                 legendFrame ? legendFrame : areaFrame);
05380 
05381   // our new frame retured is the top frame which is the list frame. 
05382   aNewFrame = newFrame; 
05383 
05384   // yes we have already initialized our frame 
05385   aFrameHasBeenInitialized = PR_TRUE; 
05386 
05387   return NS_OK;
05388 }
05389 
05390 nsresult
05391 nsCSSFrameConstructor::ConstructTextFrame(nsFrameConstructorState& aState,
05392                                           nsIContent*              aContent,
05393                                           nsIFrame*                aParentFrame,
05394                                           nsStyleContext*          aStyleContext,
05395                                           nsFrameItems&            aFrameItems,
05396                                           PRBool                   aPseudoParent)
05397 {
05398   // process pending pseudo frames. whitespace doesn't have an effect.
05399   if (!aPseudoParent && !aState.mPseudoFrames.IsEmpty() &&
05400       !IsOnlyWhitespace(aContent))
05401     ProcessPseudoFrames(aState, aFrameItems);
05402 
05403   nsIFrame* newFrame = nsnull;
05404 
05405 #ifdef MOZ_SVG
05406   nsresult rv;
05407 
05408   if (aParentFrame->IsFrameOfType(nsIFrame::eSVG)) {
05409     nsCOMPtr<nsISVGTextContainerFrame> svg_parent = do_QueryInterface(aParentFrame);
05410     if (!svg_parent) {
05411       return NS_OK;
05412     }
05413     rv = NS_NewSVGGlyphFrame(mPresShell, aContent, aParentFrame, &newFrame);
05414   }
05415   else
05416     rv = NS_NewTextFrame(mPresShell, &newFrame);
05417 #else
05418   nsresult rv = NS_NewTextFrame(mPresShell, &newFrame);
05419 #endif
05420   if (NS_FAILED(rv) || !newFrame)
05421     return rv;
05422 
05423   // Set the frame state bit for text frames to mark them as replaced.
05424   // XXX kipp: temporary
05425   newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
05426 
05427   rv = InitAndRestoreFrame(aState, aContent, aParentFrame, aStyleContext,
05428                            nsnull, newFrame);
05429 
05430   if (NS_FAILED(rv)) {
05431     newFrame->Destroy(aState.mPresContext);
05432     return rv;
05433   }
05434 
05435   // We never need to create a view for a text frame.
05436 
05437   // Set the frame's initial child list to null.
05438   newFrame->SetInitialChildList(aState.mPresContext, nsnull, nsnull);
05439 
05440   // Add the newly constructed frame to the flow
05441   aFrameItems.AddChild(newFrame);
05442 
05443   // Text frames don't go in the content->frame hash table, because
05444   // they're anonymous. This keeps the hash table smaller
05445 
05446   return rv;
05447 }
05448 
05449 nsresult
05450 nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
05451                                           nsIContent*              aContent,
05452                                           nsIFrame*                aParentFrame,
05453                                           nsIAtom*                 aTag,
05454                                           PRInt32                  aNameSpaceID,
05455                                           nsStyleContext*          aStyleContext,
05456                                           nsFrameItems&            aFrameItems,
05457                                           PRBool                   aHasPseudoParent)
05458 {
05459   // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL)
05460   // a valid HTML namespace.
05461   if (!aContent->IsContentOfType(nsIContent::eHTML) &&
05462       aNameSpaceID != kNameSpaceID_XHTML) {
05463     return NS_OK;
05464   }
05465 
05466   PRBool    frameHasBeenInitialized = PR_FALSE;
05467   nsIFrame* newFrame = nsnull;  // the frame we construct
05468   PRBool    isReplaced = PR_FALSE;
05469   PRBool    addToHashTable = PR_TRUE;
05470   PRBool    isFloatContainer = PR_FALSE;
05471   PRBool    addedToFrameList = PR_FALSE;
05472   nsresult  rv = NS_OK;
05473 
05474   // See if the element is absolute or fixed positioned
05475   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
05476 
05477   // Create a frame based on the tag
05478   if (nsHTMLAtoms::img == aTag) {
05479     isReplaced = PR_TRUE;
05480     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05481       ProcessPseudoFrames(aState, aFrameItems); 
05482     }
05483     // XXX If image display is turned off, then use ConstructAlternateFrame()
05484     // instead...
05485     rv = NS_NewImageFrame(mPresShell, &newFrame);
05486   }
05487   else if (nsHTMLAtoms::br == aTag) {
05488     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05489       ProcessPseudoFrames(aState, aFrameItems); 
05490     }
05491     rv = NS_NewBRFrame(mPresShell, &newFrame);
05492     isReplaced = PR_TRUE;
05493     // BR frames don't go in the content->frame hash table: typically
05494     // there are many BR content objects and this would increase the size
05495     // of the hash table, and it's doubtful we need the mapping anyway
05496     addToHashTable = PR_FALSE;
05497   }
05498   else if (nsHTMLAtoms::wbr == aTag) {
05499     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05500       ProcessPseudoFrames(aState, aFrameItems); 
05501     }
05502     rv = NS_NewWBRFrame(mPresShell, &newFrame);
05503   }
05504   else if (nsHTMLAtoms::input == aTag) {
05505     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05506       ProcessPseudoFrames(aState, aFrameItems); 
05507     }
05508     isReplaced = PR_TRUE;
05509     rv = CreateInputFrame(aContent, &newFrame, aStyleContext);
05510   }
05511   else if (nsHTMLAtoms::textarea == aTag) {
05512     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05513       ProcessPseudoFrames(aState, aFrameItems); 
05514     }
05515     isReplaced = PR_TRUE;
05516     rv = NS_NewTextControlFrame(mPresShell, &newFrame);
05517   }
05518   else if (nsHTMLAtoms::select == aTag) {
05519     if (!gUseXBLForms) {
05520       if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05521         ProcessPseudoFrames(aState, aFrameItems); 
05522       }
05523       isReplaced = PR_TRUE;
05524       rv = ConstructSelectFrame(aState, aContent, aParentFrame,
05525                                 aTag, aStyleContext, newFrame,
05526                                 display, frameHasBeenInitialized,
05527                                 aFrameItems);
05528       NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) ==
05529                    newFrame,
05530                    "Frame didn't get added to aFrameItems?");
05531       addedToFrameList = PR_TRUE;
05532     }
05533   }
05534   else if (nsHTMLAtoms::object == aTag ||
05535            nsHTMLAtoms::applet == aTag ||
05536            nsHTMLAtoms::embed == aTag) {
05537     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05538       ProcessPseudoFrames(aState, aFrameItems); 
05539     }
05540     isReplaced = PR_TRUE;
05541     rv = NS_NewObjectFrame(mPresShell, &newFrame);
05542   }
05543   else if (nsHTMLAtoms::fieldset == aTag) {
05544     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05545       ProcessPseudoFrames(aState, aFrameItems); 
05546     }
05547     rv = ConstructFieldSetFrame(aState, aContent, aParentFrame,
05548                                 aTag, aStyleContext, newFrame,
05549                                 aFrameItems, display, frameHasBeenInitialized);
05550     NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) ==
05551                  newFrame,
05552                  "Frame didn't get added to aFrameItems?");
05553     addedToFrameList = PR_TRUE;
05554   }
05555   else if (nsHTMLAtoms::legend == aTag) {
05556     NS_ASSERTION(!display->IsAbsolutelyPositioned() && !display->IsFloating(),
05557                  "Legends should not be positioned and should not float");
05558     
05559     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05560       ProcessPseudoFrames(aState, aFrameItems); 
05561     }
05562     rv = NS_NewLegendFrame(mPresShell, &newFrame);
05563     isFloatContainer = PR_TRUE;
05564   }
05565   else if (nsHTMLAtoms::frameset == aTag) {
05566     NS_ASSERTION(!display->IsAbsolutelyPositioned() && !display->IsFloating(),
05567                  "Framesets should not be positioned and should not float");
05568     
05569     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05570       ProcessPseudoFrames(aState, aFrameItems); 
05571     }
05572    
05573     rv = NS_NewHTMLFramesetFrame(mPresShell, &newFrame);
05574   }
05575   else if (nsHTMLAtoms::iframe == aTag) {
05576     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05577       ProcessPseudoFrames(aState, aFrameItems); 
05578     }
05579     
05580     isReplaced = PR_TRUE;
05581     rv = NS_NewSubDocumentFrame(mPresShell, &newFrame);
05582     if (newFrame) {
05583       // the nsSubDocumentFrame needs to know about its content parent during ::Init.
05584       // there is no reasonable way to get the value there.
05585       // so we store it as a frame property.
05586       nsCOMPtr<nsIAtom> contentParentAtom = do_GetAtom("contentParent");
05587       aState.mPresContext->PropertyTable()->
05588         SetProperty(newFrame, contentParentAtom,
05589                     aParentFrame, nsnull, nsnull);
05590     }
05591   }
05592   else if (nsHTMLAtoms::spacer == aTag) {
05593     NS_ASSERTION(!display->IsAbsolutelyPositioned() && !display->IsFloating(),
05594                  "Spacers should not be positioned and should not float");
05595     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05596       ProcessPseudoFrames(aState, aFrameItems); 
05597     }
05598     rv = NS_NewSpacerFrame(mPresShell, &newFrame);
05599   }
05600   else if (nsHTMLAtoms::button == aTag) {
05601     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05602       ProcessPseudoFrames(aState, aFrameItems); 
05603     }
05604     rv = NS_NewHTMLButtonControlFrame(mPresShell, &newFrame);
05605     // the html4 button needs to act just like a 
05606     // regular button except contain html content
05607     // so it must be replaced or html outside it will
05608     // draw into its borders. -EDV
05609     isReplaced = PR_TRUE;
05610     isFloatContainer = PR_TRUE;
05611   }
05612   else if (nsHTMLAtoms::isindex == aTag) {
05613     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05614       ProcessPseudoFrames(aState, aFrameItems);
05615     }
05616     isReplaced = PR_TRUE;
05617     rv = NS_NewIsIndexFrame(mPresShell, &newFrame);
05618   }
05619   else if (nsHTMLAtoms::canvas == aTag) {
05620     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
05621       ProcessPseudoFrames(aState, aFrameItems); 
05622     }
05623     isReplaced = PR_TRUE;
05624     rv = NS_NewHTMLCanvasFrame(mPresShell, &newFrame);
05625   }
05626 
05627   if (NS_FAILED(rv) || !newFrame)
05628     return rv;
05629 
05630   // If we succeeded in creating a frame then initialize it, process its
05631   // children (if requested), and set the initial child list
05632 
05633   // If the frame is a replaced element, then set the frame state bit
05634   if (isReplaced) {
05635     newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
05636   }
05637 
05638   // Note: at this point we should construct kids for newFrame only if
05639   // it's not a leaf and hasn't been initialized yet.
05640   
05641   if (!frameHasBeenInitialized) {
05642     NS_ASSERTION(!addedToFrameList,
05643                  "Frames that were already added to the frame list should be "
05644                  "initialized by now!");
05645     nsIFrame* geometricParent = aState.GetGeometricParent(display,
05646                                                           aParentFrame);
05647      
05648     rv = InitAndRestoreFrame(aState, aContent, geometricParent, aStyleContext,
05649                              nsnull, newFrame);
05650     if (rv == NS_ERROR_FRAME_REPLACED) {
05651       // The frame called CantRenderReplacedElement from inside Init().  That
05652       // failed to do anything useful, since the frame was not in the frame
05653       // tree yet... Create an alternate frame ourselves
05654       newFrame->Destroy(aState.mPresContext);
05655 
05656       if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) {
05657         // XXXbz This should really be made to work for <object> too...
05658         return NS_OK;
05659       }
05660 
05661       // Try to construct the alternate frame
05662       newFrame = nsnull;
05663       rv = ConstructAlternateFrame(aContent, aStyleContext, geometricParent,
05664                                    aParentFrame, newFrame);
05665       NS_ENSURE_SUCCESS(rv, rv);
05666       NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking");
05667     } else {
05668       NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed");
05669       // See if we need to create a view, e.g. the frame is absolutely
05670       // positioned
05671       nsHTMLContainerFrame::CreateViewForFrame(newFrame, aParentFrame, PR_FALSE);
05672 
05673       rv = aState.AddChild(newFrame, aFrameItems, display, aContent,
05674                            aStyleContext, aParentFrame);
05675       if (NS_FAILED(rv)) {
05676         return rv;
05677       }
05678       addedToFrameList = PR_TRUE;
05679       
05680       // Process the child content if requested
05681       nsFrameItems childItems;
05682       nsFrameConstructorSaveState absoluteSaveState;
05683       nsFrameConstructorSaveState floatSaveState;
05684       if (!newFrame->IsLeaf()) {
05685         if (display->IsPositioned()) {
05686           aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
05687         }
05688         if (isFloatContainer) {
05689           PRBool haveFirstLetterStyle, haveFirstLineStyle;
05690           HaveSpecialBlockStyle(aContent, aStyleContext,
05691                                 &haveFirstLetterStyle, &haveFirstLineStyle);
05692           aState.PushFloatContainingBlock(newFrame, floatSaveState,
05693                                           PR_FALSE, PR_FALSE);
05694         }
05695 
05696         // Process the child frames
05697         rv = ProcessChildren(aState, aContent, newFrame,
05698                              PR_TRUE, childItems, PR_FALSE);
05699       }
05700 
05701       // if there are any anonymous children create frames for them
05702       CreateAnonymousFrames(aTag, aState, aContent, newFrame,
05703                             PR_FALSE, childItems);
05704 
05705       // Set the frame's initial child list
05706       if (childItems.childList) {
05707         newFrame->SetInitialChildList(aState.mPresContext, nsnull,
05708                                       childItems.childList);
05709       }
05710     }
05711   }
05712 
05713   if (!addedToFrameList) {
05714     // Gotta do it here.  Note that things like absolutely positioned replaced
05715     // elements and the like will end up in this code.   So use the AddChild
05716     // on the state.
05717     rv = aState.AddChild(newFrame, aFrameItems, display, aContent,
05718                          aStyleContext, aParentFrame);
05719     if (NS_FAILED(rv)) {
05720       return rv;
05721     }
05722   }
05723 
05724   if (newFrame && !newFrame->IsLeaf()) {
05725     rv = CreateInsertionPointChildren(aState, newFrame, aContent);
05726     NS_ENSURE_SUCCESS(rv, rv);
05727   }
05728 
05729   if (addToHashTable) {
05730     // Add a mapping from content object to primary frame. Note that for
05731     // floated and positioned frames this is the out-of-flow frame and not
05732     // the placeholder frame
05733     aState.mFrameManager->SetPrimaryFrameFor(aContent, newFrame);
05734   }
05735 
05736   return rv;
05737 }
05738 
05739 nsresult
05740 nsCSSFrameConstructor::CreateAnonymousFrames(nsIAtom*                 aTag,
05741                                              nsFrameConstructorState& aState,
05742                                              nsIContent*              aParent,
05743                                              nsIFrame*                aNewFrame,
05744                                              PRBool                   aAppendToExisting,
05745                                              nsFrameItems&            aChildItems,
05746                                              PRBool                   aIsRoot)
05747 {
05748   // See if we might have anonymous content
05749   // by looking at the tag rather than doing a QueryInterface on
05750   // the frame.  Only these tags' frames can have anonymous content
05751   // through nsIAnonymousContentCreator.  We do this check for
05752   // performance reasons. If we did a QueryInterface on every tag it
05753   // would be inefficient.
05754 
05755   // nsGenericElement::SetDocument ought to keep a list like this one,
05756   // but it can't because scroll frames get around this.
05757   if (!aIsRoot &&
05758       aTag != nsHTMLAtoms::input &&
05759       aTag != nsHTMLAtoms::textarea &&
05760       aTag != nsHTMLAtoms::combobox &&
05761       aTag != nsHTMLAtoms::isindex &&
05762       aTag != nsXULAtoms::scrollbar
05763 #ifdef MOZ_SVG
05764       && aTag != nsSVGAtoms::use
05765 #endif
05766       )
05767     return NS_OK;
05768 
05769   return CreateAnonymousFrames(aState, aParent, mDocument, aNewFrame, PR_FALSE,
05770                                aAppendToExisting, aChildItems,
05771                                nsnull, nsnull, PR_FALSE);
05772 }
05773 
05774 // after the node has been constructed and initialized create any
05775 // anonymous content a node needs.
05776 nsresult
05777 nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
05778                                              nsIContent*              aParent,
05779                                              nsIDocument*             aDocument,
05780                                              nsIFrame*                aParentFrame,
05781                                              PRBool                   aForceBindingParent,
05782                                              PRBool                   aAppendToExisting,
05783                                              nsFrameItems&            aChildItems,
05784                                              nsIFrame*                aAnonymousCreator,
05785                                              nsIContent*              aInsertionNode,
05786                                              PRBool                   aAnonymousParentIsBlock)
05787 {
05788   nsCOMPtr<nsIAnonymousContentCreator> creator(do_QueryInterface(aParentFrame));
05789 
05790   if (!creator)
05791     return NS_OK;
05792 
05793   nsFrameConstructorInsertionState saveState;
05794   aState.PushAnonymousContentCreator(aAnonymousCreator,
05795                                      aInsertionNode,
05796                                      aAnonymousParentIsBlock,
05797                                      saveState);
05798 
05799   nsCOMPtr<nsISupportsArray> anonymousItems;
05800   NS_NewISupportsArray(getter_AddRefs(anonymousItems));
05801 
05802   creator->CreateAnonymousContent(aState.mPresContext, *anonymousItems);
05803   
05804   PRUint32 count = 0;
05805   anonymousItems->Count(&count);
05806 
05807   if (count) {
05808     // save the incoming pseudo frame state, so that we don't end up
05809     // with those pseudoframes in aChildItems
05810     nsPseudoFrames priorPseudoFrames; 
05811     aState.mPseudoFrames.Reset(&priorPseudoFrames);
05812 
05813     // A content element can have multiple sources of anonymous content. For example,
05814     // SELECTs have a combobox dropdown button and also scrollbars in the list view.
05815     // nsPresShell doesn't handle this very well. It's a problem because a reframe could
05816     // cause anonymous content from one source to be destroyed and recreated while
05817     // (in theory) leaving the rest intact, but the presshell doesn't have a way of tracking
05818     // the anonymous content at that granularity.
05819 
05820     // So what we're doing right now is wiping out existing content whenever we get new
05821     // anonymous content, except for the one case we care about where there are multiple
05822     // sources (SELECTs). This case is handled by having SELECT initialization tell us
05823     // explicitly not to wipe out the scrollbars when the combobox anonymous content is
05824     // added.
05825     // Note that we only wipe out existing content when there is actual new content.
05826     // Otherwise we wipe out scrollbars and other anonymous content when we check sources
05827     // that never provide anonymous content (e.g. the call to CreateAnonymousFrames
05828     // from ConstructBlock).
05829 
05830     // What we SHOULD do is get rid of the presshell's need to track anonymous
05831     // content. It's only used for cleanup as far as I can tell.
05832     if (!aAppendToExisting) {
05833       mPresShell->SetAnonymousContentFor(aParent, nsnull);
05834     }
05835 
05836     // Inform the pres shell about the anonymous content
05837     mPresShell->SetAnonymousContentFor(aParent, anonymousItems);
05838 
05839     for (PRUint32 i=0; i < count; i++) {
05840       // get our child's content and set its parent to our content
05841       nsCOMPtr<nsIContent> content;
05842       if (NS_FAILED(anonymousItems->QueryElementAt(i, NS_GET_IID(nsIContent), getter_AddRefs(content))))
05843         continue;
05844 
05845       content->SetNativeAnonymous(PR_TRUE);
05846 
05847       nsresult rv;
05848       nsIContent* bindingParent = content;
05849 #ifdef MOZ_XUL
05850       // Only cut XUL scrollbars off if they're not in a XUL document.
05851       // This allows scrollbars to be styled from XUL (although not
05852       // from XML or HTML).
05853       nsINodeInfo *ni = content->GetNodeInfo();
05854 
05855       if (ni && (ni->Equals(nsXULAtoms::scrollbar, kNameSpaceID_XUL) ||
05856                  ni->Equals(nsXULAtoms::scrollcorner, kNameSpaceID_XUL))) {
05857         nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(aDocument));
05858         if (xulDoc)
05859           bindingParent = aParent;
05860       }
05861       else
05862 #endif
05863 #ifdef MOZ_XTF
05864       if (aForceBindingParent)
05865         bindingParent = aParent;
05866       else
05867 #endif
05868 #ifdef MOZ_SVG
05869       // least-surprise CSS binding until we do the SVG specified
05870       // cascading rules for <svg:use> - bug 265894
05871       if (aParent &&
05872           aParent->GetNodeInfo() &&
05873           aParent->GetNodeInfo()->Equals(nsSVGAtoms::use, kNameSpaceID_SVG))
05874         bindingParent = aParent;
05875       else
05876 #endif
05877       // Empty block to serve as the else clause to keep the
05878       // following statement from accidentally falling into the
05879       // |else| when the #defines are changed.
05880       {}
05881       
05882       rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE);
05883       if (NS_FAILED(rv)) {
05884         content->UnbindFromTree();
05885         return rv;
05886       }
05887 
05888       nsIFrame * newFrame = nsnull;
05889       rv = creator->CreateFrameFor(aState.mPresContext, content, &newFrame);
05890       if (NS_SUCCEEDED(rv) && newFrame != nsnull) {
05891         aChildItems.AddChild(newFrame);
05892       }
05893       else {
05894         // create the frame and attach it to our frame
05895         ConstructFrame(aState, content, aParentFrame, aChildItems);
05896       }
05897 
05898       creator->PostCreateFrames();
05899     }
05900 
05901     // process the current pseudo frame state
05902     if (!aState.mPseudoFrames.IsEmpty()) {
05903       ProcessPseudoFrames(aState, aChildItems);
05904     }
05905 
05906     // restore the incoming pseudo frame state 
05907     aState.mPseudoFrames = priorPseudoFrames;
05908   }
05909 
05910   return NS_OK;
05911 }
05912 
05913 static
05914 PRBool IsXULDisplayType(const nsStyleDisplay* aDisplay)
05915 {
05916   return (aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX || 
05917           aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_GRID || 
05918           aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK ||
05919           aDisplay->mDisplay == NS_STYLE_DISPLAY_BOX ||
05920           aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID ||
05921           aDisplay->mDisplay == NS_STYLE_DISPLAY_STACK ||
05922           aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID_GROUP ||
05923           aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID_LINE ||
05924           aDisplay->mDisplay == NS_STYLE_DISPLAY_DECK ||
05925           aDisplay->mDisplay == NS_STYLE_DISPLAY_POPUP ||
05926           aDisplay->mDisplay == NS_STYLE_DISPLAY_GROUPBOX
05927           );
05928 }
05929 
05930 nsresult
05931 nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
05932                                          nsIContent*              aContent,
05933                                          nsIFrame*                aParentFrame,
05934                                          nsIAtom*                 aTag,
05935                                          PRInt32                  aNameSpaceID,
05936                                          nsStyleContext*          aStyleContext,
05937                                          nsFrameItems&            aFrameItems,
05938                                          PRBool                   aXBLBaseTag,
05939                                          PRBool                   aHasPseudoParent,
05940                                          PRBool*                  aHaltProcessing)
05941 {
05942   *aHaltProcessing = PR_FALSE;
05943 
05944   PRBool    primaryFrameSet = PR_FALSE;
05945   nsresult  rv = NS_OK;
05946   PRBool    isPopup = PR_FALSE;
05947   PRBool    isReplaced = PR_FALSE;
05948   PRBool    frameHasBeenInitialized = PR_FALSE;
05949 
05950   // XXXbz somewhere here we should process pseudo frames if !aHasPseudoParent
05951   
05952   // this is the new frame that will be created
05953   nsIFrame* newFrame = nsnull;
05954   
05955   // this is the also the new frame that is created. But if a scroll frame is needed
05956   // the content will be mapped to the scrollframe and topFrame will point to it.
05957   // newFrame will still point to the child that we created like a "div" for example.
05958   nsIFrame* topFrame = nsnull;
05959 
05960   // Store aParentFrame away, since we plan to stomp on it later
05961   nsIFrame* origParentFrame = aParentFrame;
05962 
05963   NS_ASSERTION(aTag != nsnull, "null XUL tag");
05964   if (aTag == nsnull)
05965     return NS_OK;
05966 
05967   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
05968   
05969   PRBool isXULNS = (aNameSpaceID == kNameSpaceID_XUL);
05970   PRBool isXULDisplay = IsXULDisplayType(display);
05971 
05972   // don't apply xul display types to tag based frames
05973   if (isXULDisplay && !isXULNS) {
05974     isXULDisplay = !IsSpecialContent(aContent, aTag, aNameSpaceID,
05975                                      aStyleContext);
05976   }
05977 
05978   if (isXULNS || isXULDisplay) {
05979     PRBool mayBeScrollable = PR_FALSE;
05980 
05981     if (isXULNS) {
05982       // First try creating a frame based on the tag
05983       // Make sure to keep IsSpecialContent in synch with this code
05984 #ifdef MOZ_XUL
05985       // BUTTON CONSTRUCTION
05986       if (aTag == nsXULAtoms::button || aTag == nsXULAtoms::checkbox || aTag == nsXULAtoms::radio) {
05987         isReplaced = PR_TRUE;
05988         rv = NS_NewButtonBoxFrame(mPresShell, &newFrame);
05989 
05990         // Boxes can scroll.
05991         mayBeScrollable = PR_TRUE;
05992       } // End of BUTTON CONSTRUCTION logic
05993       // AUTOREPEATBUTTON CONSTRUCTION
05994       else if (aTag == nsXULAtoms::autorepeatbutton) {
05995         isReplaced = PR_TRUE;
05996         rv = NS_NewAutoRepeatBoxFrame(mPresShell, &newFrame);
05997 
05998         // Boxes can scroll.
05999         mayBeScrollable = PR_TRUE;
06000       } // End of AUTOREPEATBUTTON CONSTRUCTION logic
06001 
06002 
06003       // TITLEBAR CONSTRUCTION
06004       else if (aTag == nsXULAtoms::titlebar) {
06005         isReplaced = PR_TRUE;
06006         rv = NS_NewTitleBarFrame(mPresShell, &newFrame);
06007 
06008         // Boxes can scroll.
06009         mayBeScrollable = PR_TRUE;
06010       } // End of TITLEBAR CONSTRUCTION logic
06011 
06012       // RESIZER CONSTRUCTION
06013       else if (aTag == nsXULAtoms::resizer) {
06014         isReplaced = PR_TRUE;
06015         rv = NS_NewResizerFrame(mPresShell, &newFrame);
06016 
06017         // Boxes can scroll.
06018         mayBeScrollable = PR_TRUE;
06019       } // End of RESIZER CONSTRUCTION logic
06020 
06021       else if (aTag == nsXULAtoms::image) {
06022         isReplaced = PR_TRUE;
06023         rv = NS_NewImageBoxFrame(mPresShell, &newFrame);
06024       }
06025       else if (aTag == nsXULAtoms::spring ||
06026                aTag == nsHTMLAtoms::spacer) {
06027         isReplaced = PR_TRUE;
06028         rv = NS_NewLeafBoxFrame(mPresShell, &newFrame);
06029       }
06030        else if (aTag == nsXULAtoms::treechildren) {
06031         isReplaced = PR_TRUE;
06032         rv = NS_NewTreeBodyFrame(mPresShell, &newFrame);
06033       }
06034       else if (aTag == nsXULAtoms::treecol) {
06035         isReplaced = PR_TRUE;
06036         rv = NS_NewTreeColFrame(mPresShell, &newFrame);
06037       }
06038       // TEXT CONSTRUCTION
06039       else if (aTag == nsXULAtoms::text || aTag == nsHTMLAtoms::label ||
06040                aTag == nsXULAtoms::description) {
06041         if ((aTag == nsHTMLAtoms::label || aTag == nsXULAtoms::description) && 
06042             (! aContent->HasAttr(kNameSpaceID_None, nsHTMLAtoms::value))) {
06043           // XXX we should probably be calling ConstructBlock here to handle
06044           // things like columns etc
06045           rv = NS_NewAreaFrame(mPresShell, &newFrame,
06046                                NS_BLOCK_SPACE_MGR | NS_BLOCK_SHRINK_WRAP | NS_BLOCK_MARGIN_ROOT);
06047         }
06048         else {
06049           isReplaced = PR_TRUE;
06050           rv = NS_NewTextBoxFrame(mPresShell, &newFrame);
06051         }
06052       }
06053       // End of TEXT CONSTRUCTION logic
06054 
06055        // Menu Construction    
06056       else if (aTag == nsXULAtoms::menu ||
06057                aTag == nsXULAtoms::menuitem || 
06058                aTag == nsXULAtoms::menubutton) {
06059         // A derived class box frame
06060         // that has custom reflow to prevent menu children
06061         // from becoming part of the flow.
06062         isReplaced = PR_TRUE;
06063         rv = NS_NewMenuFrame(mPresShell, &newFrame, (aTag != nsXULAtoms::menuitem));
06064       }
06065       else if (aTag == nsXULAtoms::menubar) {
06066   #ifdef XP_MACOSX
06067         // On Mac OS X, we use the system menubar for any root chrome shell
06068         // XUL menubars.
06069         PRBool isRootChromeShell = PR_FALSE;
06070         nsCOMPtr<nsISupports> container = aState.mPresContext->GetContainer();
06071         if (container) {
06072           nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
06073           if (treeItem) {
06074             PRInt32 type;
06075             treeItem->GetItemType(&type);
06076             if (nsIDocShellTreeItem::typeChrome == type) {
06077               nsCOMPtr<nsIDocShellTreeItem> parent;
06078               treeItem->GetParent(getter_AddRefs(parent));
06079               isRootChromeShell = !parent;
06080             }
06081           }
06082         }
06083 
06084         if (isRootChromeShell) {
06085           *aHaltProcessing = PR_TRUE;
06086           return NS_OK;
06087         }
06088   #endif
06089 
06090         rv = NS_NewMenuBarFrame(mPresShell, &newFrame);
06091       }
06092       else if (aTag == nsXULAtoms::popupgroup) {
06093         // This frame contains child popups
06094         isReplaced = PR_TRUE;
06095         rv = NS_NewPopupSetFrame(mPresShell, &newFrame);
06096       }
06097       else if (aTag == nsXULAtoms::iframe || aTag == nsXULAtoms::editor ||
06098                aTag == nsXULAtoms::browser) {
06099         isReplaced = PR_TRUE;
06100         
06101         rv = NS_NewSubDocumentFrame(mPresShell, &newFrame);
06102       }
06103       // PROGRESS METER CONSTRUCTION
06104       else if (aTag == nsXULAtoms::progressmeter) {
06105         isReplaced = PR_TRUE;
06106         rv = NS_NewProgressMeterFrame(mPresShell, &newFrame);
06107       }
06108       // End of PROGRESS METER CONSTRUCTION logic
06109       else
06110 #endif
06111       // SLIDER CONSTRUCTION
06112       if (aTag == nsXULAtoms::slider) {
06113         isReplaced = PR_TRUE;
06114         rv = NS_NewSliderFrame(mPresShell, &newFrame);
06115       }
06116       // End of SLIDER CONSTRUCTION logic
06117 
06118       // SCROLLBAR CONSTRUCTION
06119       else if (aTag == nsXULAtoms::scrollbar) {
06120         isReplaced = PR_TRUE;
06121         rv = NS_NewScrollbarFrame(mPresShell, &newFrame);
06122       }
06123       else if (aTag == nsXULAtoms::nativescrollbar) {
06124         isReplaced = PR_TRUE;
06125         rv = NS_NewNativeScrollbarFrame(mPresShell, &newFrame);
06126       }
06127       // End of SCROLLBAR CONSTRUCTION logic
06128 
06129       // SCROLLBUTTON CONSTRUCTION
06130       else if (aTag == nsXULAtoms::scrollbarbutton) {
06131         isReplaced = PR_TRUE;
06132         rv = NS_NewScrollbarButtonFrame(mPresShell, &newFrame);
06133       }
06134       // End of SCROLLBUTTON CONSTRUCTION logic
06135 
06136 #ifdef MOZ_XUL
06137       // SPLITTER CONSTRUCTION
06138       else if (aTag == nsXULAtoms::splitter) {
06139         isReplaced = PR_TRUE;
06140         rv = NS_NewSplitterFrame(mPresShell, &newFrame);
06141       }
06142       // End of SPLITTER CONSTRUCTION logic
06143 
06144       // GRIPPY CONSTRUCTION
06145       else if (aTag == nsXULAtoms::grippy) {
06146         isReplaced = PR_TRUE;
06147         rv = NS_NewGrippyFrame(mPresShell, &newFrame);
06148       }
06149       // End of GRIPPY CONSTRUCTION logic
06150 #endif
06151     }
06152 
06153     // Display types for XUL start here
06154     // First is BOX
06155     if (!newFrame && isXULDisplay) {
06156       if (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX ||
06157                display->mDisplay == NS_STYLE_DISPLAY_BOX) {
06158         isReplaced = PR_TRUE;
06159 
06160         rv = NS_NewBoxFrame(mPresShell, &newFrame, PR_FALSE, nsnull);
06161 
06162         // Boxes can scroll.
06163         mayBeScrollable = PR_TRUE;
06164       } // End of BOX CONSTRUCTION logic
06165 #ifdef MOZ_XUL
06166       // ------- Begin Grid ---------
06167       else if (display->mDisplay == NS_STYLE_DISPLAY_INLINE_GRID ||
06168                display->mDisplay == NS_STYLE_DISPLAY_GRID) {
06169         isReplaced = PR_TRUE;
06170         nsCOMPtr<nsIBoxLayout> layout;
06171         NS_NewGridLayout2(mPresShell, getter_AddRefs(layout));
06172         rv = NS_NewBoxFrame(mPresShell, &newFrame, PR_FALSE, layout);
06173 
06174         // Boxes can scroll.
06175         mayBeScrollable = PR_TRUE;
06176       } //------- End Grid ------
06177 
06178       // ------- Begin Rows/Columns ---------
06179       else if (display->mDisplay == NS_STYLE_DISPLAY_GRID_GROUP) {
06180         isReplaced = PR_TRUE;
06181 
06182         nsCOMPtr<nsIBoxLayout> layout;
06183       
06184         if (aTag == nsXULAtoms::listboxbody) {
06185           NS_NewListBoxLayout(mPresShell, layout);
06186 
06187           rv = NS_NewListBoxBodyFrame(mPresShell, &newFrame, PR_FALSE, layout);
06188           ((nsListBoxBodyFrame*)newFrame)->InitGroup(this,
06189                                                      aState.mPresContext);
06190         }
06191         else
06192         {
06193           NS_NewGridRowGroupLayout(mPresShell, getter_AddRefs(layout));
06194           rv = NS_NewGridRowGroupFrame(mPresShell, &newFrame, PR_FALSE, layout);
06195         }
06196 
06197         // Boxes can scroll.
06198         if (display->IsScrollableOverflow()) {
06199           // set the top to be the newly created scrollframe
06200           BuildScrollFrame(aState, aContent, aStyleContext, newFrame,
06201                            aParentFrame, nsnull, topFrame, aStyleContext);
06202 
06203           // we have a scrollframe so the parent becomes the scroll frame.
06204           aParentFrame = newFrame->GetParent();
06205 
06206           primaryFrameSet = PR_TRUE;
06207 
06208           frameHasBeenInitialized = PR_TRUE;
06209         }
06210       } //------- End Grid ------
06211 
06212       // ------- Begin Row/Column ---------
06213       else if (display->mDisplay == NS_STYLE_DISPLAY_GRID_LINE) {
06214         isReplaced = PR_TRUE;
06215       
06216         nsCOMPtr<nsIBoxLayout> layout;
06217 
06218 
06219         NS_NewGridRowLeafLayout(mPresShell, getter_AddRefs(layout));
06220 
06221         if (aTag == nsXULAtoms::listitem)
06222           rv = NS_NewListItemFrame(mPresShell, &newFrame, PR_FALSE, layout);
06223         else
06224           rv = NS_NewGridRowLeafFrame(mPresShell, &newFrame, PR_FALSE, layout);
06225 
06226         // Boxes can scroll.
06227         mayBeScrollable = PR_TRUE;
06228       } //------- End Grid ------
06229       // End of STACK CONSTRUCTION logic
06230        // DECK CONSTRUCTION
06231       else if (display->mDisplay == NS_STYLE_DISPLAY_DECK) {
06232         isReplaced = PR_TRUE;
06233         rv = NS_NewDeckFrame(mPresShell, &newFrame);
06234       }
06235       // End of DECK CONSTRUCTION logic
06236       else if (display->mDisplay == NS_STYLE_DISPLAY_GROUPBOX) {
06237         rv = NS_NewGroupBoxFrame(mPresShell, &newFrame);
06238         isReplaced = PR_TRUE;
06239 
06240         // Boxes can scroll.
06241         mayBeScrollable = PR_TRUE;
06242       } 
06243       // STACK CONSTRUCTION
06244       else if (display->mDisplay == NS_STYLE_DISPLAY_STACK ||
06245                display->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK) {
06246         isReplaced = PR_TRUE;
06247 
06248         rv = NS_NewStackFrame(mPresShell, &newFrame);
06249 
06250         mayBeScrollable = PR_TRUE;
06251       }
06252       else if (display->mDisplay == NS_STYLE_DISPLAY_POPUP) {
06253         // This is its own frame that derives from
06254         // box.
06255         isReplaced = PR_TRUE;
06256         rv = NS_NewMenuPopupFrame(mPresShell, &newFrame);
06257 
06258         if (aTag == nsXULAtoms::tooltip) {
06259           nsAutoString defaultTooltip;
06260           aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::defaultz, defaultTooltip);
06261           if (defaultTooltip.LowerCaseEqualsLiteral("true")) {
06262             // Locate the root frame and tell it about the tooltip.
06263             nsIFrame* rootFrame = aState.mFrameManager->GetRootFrame();
06264             if (rootFrame)
06265               rootFrame = rootFrame->GetFirstChild(nsnull);
06266             nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
06267             if (rootBox)
06268               rootBox->SetDefaultTooltip(aContent);
06269           }
06270         }
06271 
06272         // If a popup is inside a menu, then the menu understands the complex
06273         // rules/behavior governing the cascade of multiple menu popups and can handle
06274         // having the real popup frame placed under it as a child.  
06275         // If, however, the parent is *not* a menu frame, then we need to create
06276         // a placeholder frame for the popup, and then we add the popup frame to the
06277         // root popup set (that manages all such "detached" popups).
06278         nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(aParentFrame));
06279         if (!menuFrame)
06280           isPopup = PR_TRUE;
06281       } 
06282 #endif
06283     }
06284 
06285     if (mayBeScrollable && display->IsScrollableOverflow()) {
06286       // set the top to be the newly created scrollframe
06287       BuildScrollFrame(aState, aContent, aStyleContext, newFrame,
06288                        aParentFrame, nsnull, topFrame, aStyleContext);
06289 
06290       // we have a scrollframe so the parent becomes the scroll frame.
06291       // XXXldb Do we really want to do this?  The one case where it
06292       // matters when |frameHasBeenInitialized| is true is one where
06293       // I think we'd be better off the other way around.
06294       aParentFrame = newFrame->GetParent();
06295       primaryFrameSet = PR_TRUE;
06296       frameHasBeenInitialized = PR_TRUE;
06297     }
06298   }
06299 
06300   // If we succeeded in creating a frame then initialize it, process its
06301   // children (if requested), and set the initial child list
06302   if (NS_SUCCEEDED(rv) && newFrame != nsnull) {
06303 
06304     // if no top frame was created then the top is the new frame
06305     if (topFrame == nsnull)
06306         topFrame = newFrame;
06307 
06308     // If the frame is a replaced element, then set the frame state bit
06309     if (isReplaced) {
06310       newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
06311     }
06312 
06313     // xul does not support absolute positioning
06314     nsIFrame* geometricParent = aParentFrame;
06315 
06316     /*
06317       nsIFrame* geometricParent = aState.GetGeometricParent(display, aParentFrame);
06318     */
06319     // if the new frame was already initialized to initialize it again.
06320     if (!frameHasBeenInitialized) {
06321 
06322       rv = InitAndRestoreFrame(aState, aContent, geometricParent,
06323                                aStyleContext, nsnull, newFrame);
06324 
06325       if (NS_FAILED(rv)) {
06326         newFrame->Destroy(aState.mPresContext);
06327         return rv;
06328       }
06329       
06330       /*
06331       // if our parent is a block frame then do things the way html likes it
06332       // if not then we are in a box so do what boxes like. On example is boxes
06333       // do not support the absolute positioning of their children. While html blocks
06334       // thats why we call different things here.
06335       nsIAtom* frameType = geometricParent->GetType();
06336       if ((frameType == nsLayoutAtoms::blockFrame) ||
06337           (frameType == nsLayoutAtoms::areaFrame)) {
06338       */
06339         // See if we need to create a view, e.g. the frame is absolutely positioned
06340         nsHTMLContainerFrame::CreateViewForFrame(newFrame, aParentFrame, PR_FALSE);
06341 
06342       /*
06343       } else {
06344           // we are in a box so do the box thing.
06345         nsBoxFrame::CreateViewForFrame(aState.mPresContext, newFrame,
06346                                                  aStyleContext, PR_FALSE);
06347       }
06348       */
06349       
06350     }
06351 
06352     // If the frame is a popup, then create a placeholder frame
06353 #ifdef MOZ_XUL
06354     if (isPopup) {
06355       nsIFrame* placeholderFrame;
06356 
06357       CreatePlaceholderFrameFor(mPresShell, aState.mPresContext,
06358                                 aState.mFrameManager, aContent,
06359                                 newFrame, aStyleContext, aParentFrame,
06360                                 &placeholderFrame);
06361 
06362       // Locate the root popup set and add ourselves to the popup set's list
06363       // of popup frames.
06364       nsIFrame* rootFrame = aState.mFrameManager->GetRootFrame();
06365       if (rootFrame)
06366         rootFrame = rootFrame->GetFirstChild(nsnull);
06367       nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
06368       PRBool added = PR_FALSE;
06369       if (rootBox) {
06370         nsIFrame* popupSetFrame;
06371         rootBox->GetPopupSetFrame(&popupSetFrame);
06372         NS_ASSERTION(popupSetFrame, "unexpected null pointer");
06373         if (popupSetFrame) {
06374           nsCOMPtr<nsIPopupSetFrame> popupSet(do_QueryInterface(popupSetFrame));
06375           NS_ASSERTION(popupSet, "unexpected null pointer");
06376           if (popupSet) {
06377             added = PR_TRUE;
06378             popupSet->AddPopupFrame(newFrame);
06379           }
06380         }
06381       }
06382 
06383       if (added) {
06384         // Add the placeholder frame to the flow
06385         aFrameItems.AddChild(placeholderFrame);
06386       } else {
06387         // Didn't add the popup set frame...  Need to clean up and
06388         // just not construct a frame here.
06389         aState.mFrameManager->UnregisterPlaceholderFrame(NS_STATIC_CAST(nsPlaceholderFrame*, placeholderFrame));
06390         newFrame->Destroy(aState.mPresContext);
06391         placeholderFrame->Destroy(aState.mPresContext);
06392         *aHaltProcessing = PR_TRUE;
06393         return NS_OK;
06394       }
06395     } else {
06396 #endif
06397       // Add the new frame to our list of frame items.  Note that we
06398       // don't support floating or positioning of XUL frames.
06399       rv = aState.AddChild(topFrame, aFrameItems, display, aContent,
06400                            aStyleContext, origParentFrame, PR_FALSE, PR_FALSE);
06401       if (NS_FAILED(rv)) {
06402         return rv;
06403       }
06404 #ifdef MOZ_XUL
06405     }
06406 #endif
06407 
06408     // If the new frame isn't a float containing block, then push a null
06409     // float containing block to disable floats. This is needed to disable
06410     // floats within XUL frames.
06411     nsFrameConstructorSaveState floatSaveState;
06412     PRBool isFloatContainingBlock =
06413       newFrame->GetContentInsertionFrame()->IsFloatContainingBlock();
06414     aState.PushFloatContainingBlock(isFloatContainingBlock ? newFrame : nsnull,
06415                                     floatSaveState, PR_FALSE, PR_FALSE);
06416 
06417     // Process the child content if requested
06418     nsFrameItems childItems;
06419     if (!newFrame->IsLeaf()) {
06420       // XXXbz don't we need calls to ShouldBuildChildFrames
06421       // elsewhere too?  Why only for XUL?
06422       PRBool processChildren = PR_TRUE;
06423       mDocument->BindingManager()->ShouldBuildChildFrames(aContent,
06424                                                           &processChildren);
06425       if (processChildren)
06426         rv = ProcessChildren(aState, aContent, newFrame, PR_FALSE,
06427                              childItems, PR_FALSE);
06428     }
06429       
06430     CreateAnonymousFrames(aTag, aState, aContent, newFrame, PR_FALSE,
06431                           childItems);
06432 
06433     // Set the frame's initial child list
06434     newFrame->SetInitialChildList(aState.mPresContext, nsnull,
06435                                   childItems.childList);
06436   }
06437 
06438 #ifdef MOZ_XUL
06439   // register tooltip support if needed
06440   nsAutoString value;
06441   if (aTag == nsXULAtoms::treechildren || // trees always need titletips
06442       aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltiptext, value) !=
06443         NS_CONTENT_ATTR_NOT_THERE ||
06444       aContent->GetAttr(kNameSpaceID_None, nsXULAtoms::tooltip, value) !=
06445         NS_CONTENT_ATTR_NOT_THERE)
06446   {
06447     nsIFrame* rootFrame = aState.mFrameManager->GetRootFrame();
06448     if (rootFrame)
06449       rootFrame = rootFrame->GetFirstChild(nsnull);
06450     nsCOMPtr<nsIRootBox> rootBox(do_QueryInterface(rootFrame));
06451     if (rootBox)
06452       rootBox->AddTooltipSupport(aContent);
06453   }
06454 #endif
06455 
06456 // addToHashTable:
06457 
06458   if (newFrame && !newFrame->IsLeaf()) {
06459     rv = CreateInsertionPointChildren(aState, newFrame, aContent);
06460     NS_ENSURE_SUCCESS(rv, rv);
06461   }
06462 
06463   if (topFrame) {
06464     // the top frame is always what we map the content to. This is the frame that contains a pointer
06465     // to the content node.
06466 
06467     // Add a mapping from content object to primary frame. Note that for
06468     // floated and positioned frames this is the out-of-flow frame and not
06469     // the placeholder frame
06470     if (!primaryFrameSet)
06471         aState.mFrameManager->SetPrimaryFrameFor(aContent, topFrame);
06472   }
06473 
06474   return rv;
06475 }
06476 
06477 already_AddRefed<nsStyleContext>
06478 nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
06479                                                 nsIContent*              aContent,
06480                                                 nsStyleContext*          aContentStyle,
06481                                                 nsIFrame*                aParentFrame,
06482                                                 nsIFrame*                aContentParentFrame,
06483                                                 nsIAtom*                 aScrolledPseudo,
06484                                                 PRBool                   aIsRoot,
06485                                                 nsIFrame*&               aNewFrame)
06486 {
06487   // Check to see the type of parent frame so we know whether we need to 
06488   // turn off/on scaling for the scrollbars
06489   //
06490   // If the parent is a viewportFrame then we are the scrollbars for the UI
06491   // if not then we are scrollbars inside the document.
06492   PRBool noScalingOfTwips = PR_FALSE;
06493   PRBool isPrintPreview =
06494     aState.mPresContext->Type() == nsPresContext::eContext_PrintPreview;
06495 
06496   if (isPrintPreview) {
06497     noScalingOfTwips = aParentFrame->GetType() == nsLayoutAtoms::viewportFrame;
06498     if (noScalingOfTwips) {
06499       aState.mPresContext->SetScalingOfTwips(PR_FALSE);
06500     }
06501   }
06502 
06503   nsIFrame* parentFrame = nsnull;
06504   nsIFrame* gfxScrollFrame = aNewFrame;
06505 
06506   nsFrameItems anonymousItems;
06507 
06508   nsRefPtr<nsStyleContext> contentStyle = aContentStyle;
06509 
06510   if (!gfxScrollFrame) {
06511     // Build a XULScrollFrame when the child is a box, otherwise an
06512     // HTMLScrollFrame
06513     if (IsXULDisplayType(aContentStyle->GetStyleDisplay())) {
06514       NS_NewXULScrollFrame(mPresShell, &gfxScrollFrame, aIsRoot);
06515     } else {
06516       NS_NewHTMLScrollFrame(mPresShell, &gfxScrollFrame, aIsRoot);
06517     }
06518 
06519     InitAndRestoreFrame(aState, aContent, aParentFrame, contentStyle, nsnull,
06520                         gfxScrollFrame);
06521 
06522     // Create a view
06523     nsHTMLContainerFrame::CreateViewForFrame(gfxScrollFrame,
06524                                              aContentParentFrame, PR_FALSE);
06525   }
06526 
06527   // if there are any anonymous children for the scroll frame, create
06528   // frames for them.
06529   CreateAnonymousFrames(aState, aContent, mDocument, gfxScrollFrame, PR_FALSE,
06530                         PR_FALSE, anonymousItems, nsnull, nsnull, PR_FALSE);
06531 
06532   parentFrame = gfxScrollFrame;
06533   aNewFrame = gfxScrollFrame;
06534 
06535   // we used the style that was passed in. So resolve another one.
06536   nsStyleSet *styleSet = mPresShell->StyleSet();
06537   nsStyleContext* aScrolledChildStyle = styleSet->ResolvePseudoStyleFor(aContent,
06538                                                                         aScrolledPseudo,
06539                                                                         contentStyle).get();
06540 
06541   if (gfxScrollFrame) {
06542      gfxScrollFrame->SetInitialChildList(aState.mPresContext, nsnull,
06543                                          anonymousItems.childList);
06544   }
06545 
06546   if (isPrintPreview && noScalingOfTwips) {
06547     aState.mPresContext->SetScalingOfTwips(PR_TRUE);
06548   }
06549 
06550   return aScrolledChildStyle;;
06551 }
06552 
06553 void
06554 nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
06555                                                  nsIFrame* aScrolledFrame)
06556 {
06557   aScrollFrame->AppendFrames(nsnull, aScrolledFrame);
06558 
06559   // force the scrolled frame to have a view. The view will be parented to
06560   // the correct anonymous inner view because the scrollframes override
06561   // nsIFrame::GetParentViewForChildFrame.
06562   nsHTMLContainerFrame::CreateViewForFrame(aScrolledFrame, nsnull, PR_TRUE);
06563   nsIView* view = aScrolledFrame->GetView();
06564   if (!view)
06565     return;
06566 }
06567 
06568 
06600 nsresult
06601 nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
06602                                         nsIContent*              aContent,
06603                                         nsStyleContext*          aContentStyle,
06604                                         nsIFrame*                aScrolledFrame,
06605                                         nsIFrame*                aParentFrame,
06606                                         nsIFrame*                aContentParentFrame,
06607                                         nsIFrame*&               aNewFrame, 
06608                                         nsStyleContext*&         aScrolledContentStyle)
06609 {
06610     nsRefPtr<nsStyleContext> scrolledContentStyle =
06611       BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame,
06612                                aContentParentFrame, nsCSSAnonBoxes::scrolledContent,
06613                                PR_FALSE, aNewFrame);
06614     
06615     InitAndRestoreFrame(aState, aContent, aNewFrame, scrolledContentStyle,
06616                         nsnull, aScrolledFrame);
06617 
06618     FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
06619 
06620     aScrolledContentStyle = scrolledContentStyle;
06621 
06622     // now set the primary frame to the ScrollFrame
06623     aState.mFrameManager->SetPrimaryFrameFor( aContent, aNewFrame );
06624     return NS_OK;
06625 
06626 }
06627 
06628 nsresult
06629 nsCSSFrameConstructor::ConstructFrameByDisplayType(nsFrameConstructorState& aState,
06630                                                    const nsStyleDisplay*    aDisplay,
06631                                                    nsIContent*              aContent,
06632                                                    PRInt32                  aNameSpaceID,
06633                                                    nsIAtom*                 aTag,
06634                                                    nsIFrame*                aParentFrame,
06635                                                    nsStyleContext*          aStyleContext,
06636                                                    nsFrameItems&            aFrameItems,
06637                                                    PRBool                   aHasPseudoParent)
06638 {
06639   PRBool    primaryFrameSet = PR_FALSE;
06640   nsIFrame* newFrame = nsnull;  // the frame we construct
06641   nsTableCreator tableCreator(mPresShell); // Used to make table frames.
06642   PRBool    addToHashTable = PR_TRUE;
06643   PRBool    addedToFrameList = PR_FALSE;
06644   nsresult  rv = NS_OK;
06645 
06646   // The style system ensures that floated and positioned frames are
06647   // block-level.
06648   NS_ASSERTION(!(aDisplay->IsFloating() ||
06649                  aDisplay->IsAbsolutelyPositioned()) ||
06650                aDisplay->IsBlockLevel(),
06651                "Style system did not apply CSS2.1 section 9.7 fixups");
06652 
06653   // If this is "body", try propagating its scroll style to the viewport
06654   // Note that we need to do this even if the body is NOT scrollable;
06655   // it might have dynamically changed from scrollable to not scrollable,
06656   // and that might need to be propagated.
06657   PRBool propagatedScrollToViewport = PR_FALSE;
06658   if (aContent->GetNodeInfo()->Equals(nsHTMLAtoms::body) &&
06659       aContent->IsContentOfType(nsIContent::eHTML)) {
06660     propagatedScrollToViewport =
06661       PropagateScrollToViewport() == aContent;
06662   }
06663 
06664   // If the frame is a block-level frame and is scrollable, then wrap it
06665   // in a scroll frame.
06666   // XXX Ignore tables for the time being
06667   if (aDisplay->IsBlockLevel() &&
06668       aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE &&
06669       aDisplay->IsScrollableOverflow() &&
06670       !propagatedScrollToViewport) {
06671 
06672     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06673       ProcessPseudoFrames(aState, aFrameItems); 
06674     }
06675 
06676     nsRefPtr<nsStyleContext> scrolledContentStyle
06677       = BeginBuildingScrollFrame(aState, aContent, aStyleContext,
06678                                  aState.GetGeometricParent(aDisplay, aParentFrame),
06679                                  aParentFrame,
06680                                  nsCSSAnonBoxes::scrolledContent,
06681                                  PR_FALSE, newFrame);
06682     
06683     // Initialize it
06684     nsIFrame* scrolledFrame = nsnull;
06685     NS_NewAreaFrame(mPresShell, &scrolledFrame, NS_BLOCK_SPACE_MGR |
06686                     NS_BLOCK_SHRINK_WRAP | NS_BLOCK_MARGIN_ROOT);
06687     nsFrameItems blockItem;
06688     rv = ConstructBlock(aState,
06689                         scrolledContentStyle->GetStyleDisplay(), aContent,
06690                         newFrame, newFrame, scrolledContentStyle,
06691                         &scrolledFrame, blockItem, aDisplay->IsPositioned());
06692     NS_ASSERTION(blockItem.childList == scrolledFrame,
06693                  "Scrollframe's frameItems should be exactly the scrolled frame");
06694     FinishBuildingScrollFrame(newFrame, scrolledFrame);
06695 
06696     rv = aState.AddChild(newFrame, aFrameItems, aDisplay, aContent,
06697                          aStyleContext, aParentFrame);
06698     if (NS_FAILED(rv)) {
06699       return rv;
06700     }
06701 
06702     addedToFrameList = PR_TRUE;
06703   }
06704   // See if the frame is absolute or fixed positioned
06705   else if (aDisplay->IsAbsolutelyPositioned() &&
06706            (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay ||
06707             NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay)) {
06708 
06709     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06710       ProcessPseudoFrames(aState, aFrameItems); 
06711     }
06712 
06713     // Create a frame to wrap up the absolute positioned item
06714     NS_NewAbsoluteItemWrapperFrame(mPresShell, &newFrame);
06715 
06716     rv = ConstructBlock(aState, aDisplay, aContent,
06717                         aState.GetGeometricParent(aDisplay, aParentFrame), aParentFrame,
06718                         aStyleContext, &newFrame, aFrameItems, PR_TRUE);
06719     if (NS_FAILED(rv)) {
06720       return rv;
06721     }
06722 
06723     addedToFrameList = PR_TRUE;
06724   }
06725   // See if the frame is floated and it's a block frame
06726   else if (aDisplay->IsFloating() &&
06727            (NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay ||
06728             NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay)) {
06729     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06730       ProcessPseudoFrames(aState, aFrameItems); 
06731     }
06732     // Create an area frame
06733     NS_NewFloatingItemWrapperFrame(mPresShell, &newFrame);
06734 
06735     rv = ConstructBlock(aState, aDisplay, aContent, 
06736                         aState.GetGeometricParent(aDisplay, aParentFrame),
06737                         aParentFrame, aStyleContext, &newFrame, aFrameItems,
06738                         aDisplay->mPosition == NS_STYLE_POSITION_RELATIVE);
06739     if (NS_FAILED(rv)) {
06740       return rv;
06741     }
06742 
06743     addedToFrameList = PR_TRUE;
06744   }
06745   // See if it's relatively positioned
06746   else if ((NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition) &&
06747            ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) ||
06748             (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) ||
06749             (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) {
06750     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06751       ProcessPseudoFrames(aState, aFrameItems); 
06752     }
06753     // Is it block-level or inline-level?
06754     if ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) ||
06755         (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay)) {
06756       // Create a wrapper frame. No space manager, though
06757       NS_NewRelativeItemWrapperFrame(mPresShell, &newFrame);
06758       // XXXbz should we be passing in a non-null aContentParentFrame?
06759       ConstructBlock(aState, aDisplay, aContent,
06760                      aParentFrame, nsnull, aStyleContext, &newFrame,
06761                      aFrameItems, PR_TRUE);
06762       addedToFrameList = PR_TRUE;
06763     } else {
06764       // Create a positioned inline frame
06765       NS_NewPositionedInlineFrame(mPresShell, &newFrame);
06766       // Note that we want to insert the inline after processing kids, since
06767       // processing of kids may split the inline.
06768       ConstructInline(aState, aDisplay, aContent,
06769                       aParentFrame, aStyleContext, PR_TRUE, newFrame);
06770     }
06771   }
06772   // See if it's a block frame of some sort
06773   else if ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) ||
06774            (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay) ||
06775            (NS_STYLE_DISPLAY_RUN_IN == aDisplay->mDisplay) ||
06776            (NS_STYLE_DISPLAY_COMPACT == aDisplay->mDisplay) ||
06777            (NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay)) {
06778     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06779       ProcessPseudoFrames(aState, aFrameItems); 
06780     }
06781     PRUint32 flags = 0;
06782     if (NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay) {
06783       flags = NS_BLOCK_SPACE_MGR | NS_BLOCK_MARGIN_ROOT;
06784     }
06785     // Create the block frame
06786     rv = NS_NewBlockFrame(mPresShell, &newFrame, flags);
06787     if (NS_SUCCEEDED(rv)) { // That worked so construct the block and its children
06788       // XXXbz should we be passing in a non-null aContentParentFrame?
06789       rv = ConstructBlock(aState, aDisplay, aContent,
06790                           aParentFrame, nsnull, aStyleContext, &newFrame,
06791                           aFrameItems, PR_FALSE);
06792       addedToFrameList = PR_TRUE;
06793     }
06794   }
06795   // See if it's an inline frame of some sort
06796   else if ((NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) ||
06797            (NS_STYLE_DISPLAY_MARKER == aDisplay->mDisplay)) {
06798     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
06799       ProcessPseudoFrames(aState, aFrameItems); 
06800     }
06801     // Create the inline frame
06802     rv = NS_NewInlineFrame(mPresShell, &newFrame);
06803     if (NS_SUCCEEDED(rv)) { // That worked so construct the inline and its children
06804       // Note that we want to insert the inline after processing kids, since
06805       // processing of kids may split the inline.
06806       rv = ConstructInline(aState, aDisplay, aContent,
06807                            aParentFrame, aStyleContext, PR_FALSE, newFrame);
06808     }
06809 
06810     // To keep the hash table small don't add inline frames (they're
06811     // typically things like FONT and B), because we can quickly
06812     // find them if we need to
06813     addToHashTable = PR_FALSE;
06814   }
06815   // otherwise let the display property influence the frame type to create
06816   else {
06817     // XXX This section now only handles table frames; should be
06818     // factored out probably
06819 
06820     // Use the 'display' property to choose a frame type
06821     switch (aDisplay->mDisplay) {
06822     case NS_STYLE_DISPLAY_TABLE:
06823     {
06824       // XXXbz this isn't quite right, but checking for aHasPseudoParent here
06825       // would just lead us to ProcessPseudoFrames inside ConstructTableFrame.
06826       if (!aState.mPseudoFrames.IsEmpty()) {
06827         ProcessPseudoFrames(aState, aFrameItems); 
06828       }
06829       nsIFrame* innerTable;
06830       rv = ConstructTableFrame(aState, aContent, 
06831                                aParentFrame, aStyleContext,
06832                                tableCreator, PR_FALSE, aFrameItems, PR_TRUE,
06833                                newFrame, innerTable);
06834       addedToFrameList = PR_TRUE;
06835       // Note: table construction function takes care of initializing
06836       // the frame, processing children, and setting the initial child
06837       // list
06838       break;
06839     }
06840   
06841     // the next 5 cases are only relevant if the parent is not a table, ConstructTableFrame handles children
06842     case NS_STYLE_DISPLAY_TABLE_CAPTION:
06843     {
06844       // aParentFrame may be an inner table frame rather than an outer frame 
06845       // In this case we need to get the outer frame.
06846       nsIFrame* parentFrame = aParentFrame;
06847       nsIFrame* outerFrame = aParentFrame->GetParent();
06848       if (outerFrame) {
06849         if ((nsLayoutAtoms::tableOuterFrame == outerFrame->GetType()) &&
06850             (nsLayoutAtoms::tableFrame == parentFrame->GetType())) {
06851           parentFrame = outerFrame;
06852         }
06853       }
06854       rv = ConstructTableCaptionFrame(aState, aContent, parentFrame,
06855                                       aStyleContext, tableCreator, aFrameItems,
06856                                       newFrame, aHasPseudoParent);
06857       if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06858         aFrameItems.AddChild(newFrame);
06859       }
06860       return rv;
06861     }
06862 
06863     case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
06864     case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
06865     case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
06866       rv = ConstructTableRowGroupFrame(aState, aContent, 
06867                                        aParentFrame, aStyleContext, tableCreator, 
06868                                        PR_FALSE, aFrameItems, newFrame, aHasPseudoParent);
06869       if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06870         aFrameItems.AddChild(newFrame);
06871       }
06872       return rv;
06873 
06874     case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
06875       rv = ConstructTableColGroupFrame(aState, aContent, aParentFrame,
06876                                        aStyleContext, tableCreator, 
06877                                        PR_FALSE, aFrameItems, newFrame,
06878                                        aHasPseudoParent);
06879       if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06880         aFrameItems.AddChild(newFrame);
06881       }
06882       return rv;
06883    
06884     case NS_STYLE_DISPLAY_TABLE_COLUMN:
06885       rv = ConstructTableColFrame(aState, aContent, aParentFrame,
06886                                   aStyleContext, tableCreator, PR_FALSE,
06887                                   aFrameItems, newFrame, aHasPseudoParent);
06888       if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06889         aFrameItems.AddChild(newFrame);
06890       }
06891       return rv;
06892   
06893     case NS_STYLE_DISPLAY_TABLE_ROW:
06894       rv = ConstructTableRowFrame(aState, aContent, aParentFrame,
06895                                   aStyleContext, tableCreator, PR_FALSE,
06896                                   aFrameItems, newFrame, aHasPseudoParent);
06897       if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06898         aFrameItems.AddChild(newFrame);
06899       }
06900       return rv;
06901   
06902     case NS_STYLE_DISPLAY_TABLE_CELL:
06903       {
06904         nsIFrame* innerTable;
06905         rv = ConstructTableCellFrame(aState, aContent, aParentFrame,
06906                                      aStyleContext, tableCreator, 
06907                                      PR_FALSE, aFrameItems, newFrame,
06908                                      innerTable, aHasPseudoParent);
06909         if (NS_SUCCEEDED(rv) && !aHasPseudoParent) {
06910           aFrameItems.AddChild(newFrame);
06911         }
06912         return rv;
06913       }
06914   
06915     default:
06916       NS_NOTREACHED("How did we get here? (ok if from CantRenderReplacedElement)");
06917       return NS_ERROR_FAILURE;
06918     }
06919   }
06920 
06921   if (!addedToFrameList) {
06922     // Gotta do it here
06923     NS_ASSERTION(!aDisplay->IsAbsolutelyPositioned() &&
06924                  !aDisplay->IsFloating(),
06925                  "Things that could be out-of-flow need to handle adding "
06926                  "to the frame list themselves");
06927     
06928     rv = aState.AddChild(newFrame, aFrameItems, aDisplay, aContent,
06929                          aStyleContext, aParentFrame);
06930     NS_ASSERTION(NS_SUCCEEDED(rv),
06931                  "Cases where AddChild() can fail must handle it themselves");
06932   }
06933 
06934   if (newFrame) {
06935     rv = CreateInsertionPointChildren(aState, newFrame, aContent);
06936     NS_ENSURE_SUCCESS(rv, rv);
06937 
06938     if (addToHashTable) {
06939       // Add a mapping from content object to primary frame. Note that for
06940       // floated and positioned frames this is the out-of-flow frame and not
06941       // the placeholder frame
06942       if (!primaryFrameSet)
06943         aState.mFrameManager->SetPrimaryFrameFor(aContent, newFrame);
06944     }
06945   }
06946 
06947   return rv;
06948 }
06949 
06950 nsresult 
06951 nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
06952                                            nsIContent*              aContent,
06953                                            nsIFrame*                aParentFrame,
06954                                            nsStyleContext*          aStyleContext,
06955                                            nsIFrame*                aPrevInFlow,
06956                                            nsIFrame*                aNewFrame,
06957                                            PRBool                   aAllowCounters)
06958 {
06959   nsresult rv = NS_OK;
06960   
06961   NS_ASSERTION(aNewFrame, "Null frame cannot be initialized");
06962   if (!aNewFrame)
06963     return NS_ERROR_NULL_POINTER;
06964 
06965   // Initialize the frame
06966   rv = aNewFrame->Init(aState.mPresContext, aContent, aParentFrame, 
06967                        aStyleContext, aPrevInFlow);
06968 
06969   if (aState.mFrameState && aState.mFrameManager) {
06970     // Restore frame state for just the newly created frame.
06971     aState.mFrameManager->RestoreFrameStateFor(aNewFrame, aState.mFrameState);
06972   }
06973 
06974   if (aAllowCounters && !aPrevInFlow &&
06975       mCounterManager.AddCounterResetsAndIncrements(aNewFrame)) {
06976     CountersDirty();
06977   }
06978 
06979   return rv;
06980 }
06981 
06982 already_AddRefed<nsStyleContext>
06983 nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*         aParentFrame,
06984                                            nsIContent*       aContent)
06985 {
06986   aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nsnull);
06987   
06988   // Resolve the style context based on the content object and the parent
06989   // style context
06990   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
06991 
06992   nsStyleSet *styleSet = mPresShell->StyleSet();
06993 
06994   if (aContent->IsContentOfType(nsIContent::eELEMENT)) {
06995     return styleSet->ResolveStyleFor(aContent, parentStyleContext);
06996   } else {
06997 
06998     NS_ASSERTION(aContent->IsContentOfType(nsIContent::eTEXT),
06999                  "shouldn't waste time creating style contexts for "
07000                  "comments and processing instructions");
07001 
07002     return styleSet->ResolveStyleForNonElement(parentStyleContext);
07003   }
07004 }
07005 
07006 // MathML Mod - RBS
07007 #ifdef MOZ_MATHML
07008 nsresult
07009 nsCSSFrameConstructor::ConstructMathMLFrame(nsFrameConstructorState& aState,
07010                                             nsIContent*              aContent,
07011                                             nsIFrame*                aParentFrame,
07012                                             nsIAtom*                 aTag,
07013                                             PRInt32                  aNameSpaceID,
07014                                             nsStyleContext*          aStyleContext,
07015                                             nsFrameItems&            aFrameItems,
07016                                             PRBool                   aHasPseudoParent)
07017 {
07018   // Make sure that we remain confined in the MathML world
07019   if (aNameSpaceID != kNameSpaceID_MathML) 
07020     return NS_OK;
07021 
07022   nsresult  rv = NS_OK;
07023   PRBool    isReplaced = PR_FALSE;
07024   PRBool    ignoreInterTagWhitespace = PR_TRUE;
07025 
07026   NS_ASSERTION(aTag != nsnull, "null MathML tag");
07027   if (aTag == nsnull)
07028     return NS_OK;
07029 
07030   // Initialize the new frame
07031   nsIFrame* newFrame = nsnull;
07032 
07033   // Make sure to keep IsSpecialContent in synch with this code
07034   const nsStyleDisplay* disp = aStyleContext->GetStyleDisplay();
07035 
07036   // Leverage IsSpecialContent to check if one of the |if aTag| below will
07037   // surely match (knowing that aNameSpaceID == kNameSpaceID_MathML here)
07038   if (IsSpecialContent(aContent, aTag, aNameSpaceID, aStyleContext)) {
07039     // process pending pseudo frames
07040     if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
07041       ProcessPseudoFrames(aState, aFrameItems); 
07042     }
07043   }
07044 
07045   if (aTag == nsMathMLAtoms::mi_ ||
07046       aTag == nsMathMLAtoms::mn_ ||
07047       aTag == nsMathMLAtoms::ms_ ||
07048       aTag == nsMathMLAtoms::mtext_)
07049     rv = NS_NewMathMLTokenFrame(mPresShell, &newFrame);
07050   else if (aTag == nsMathMLAtoms::mo_)
07051     rv = NS_NewMathMLmoFrame(mPresShell, &newFrame);
07052   else if (aTag == nsMathMLAtoms::mfrac_)
07053     rv = NS_NewMathMLmfracFrame(mPresShell, &newFrame);
07054   else if (aTag == nsMathMLAtoms::msup_)
07055     rv = NS_NewMathMLmsupFrame(mPresShell, &newFrame);
07056   else if (aTag == nsMathMLAtoms::msub_)
07057     rv = NS_NewMathMLmsubFrame(mPresShell, &newFrame);
07058   else if (aTag == nsMathMLAtoms::msubsup_)
07059     rv = NS_NewMathMLmsubsupFrame(mPresShell, &newFrame);
07060   else if (aTag == nsMathMLAtoms::munder_)
07061     rv = NS_NewMathMLmunderFrame(mPresShell, &newFrame);
07062   else if (aTag == nsMathMLAtoms::mover_)
07063     rv = NS_NewMathMLmoverFrame(mPresShell, &newFrame);
07064   else if (aTag == nsMathMLAtoms::munderover_)
07065     rv = NS_NewMathMLmunderoverFrame(mPresShell, &newFrame);
07066   else if (aTag == nsMathMLAtoms::mphantom_)
07067     rv = NS_NewMathMLmphantomFrame(mPresShell, &newFrame);
07068   else if (aTag == nsMathMLAtoms::mpadded_)
07069     rv = NS_NewMathMLmpaddedFrame(mPresShell, &newFrame);
07070   else if (aTag == nsMathMLAtoms::mspace_ ||
07071            aTag == nsMathMLAtoms::none_   ||
07072            aTag == nsMathMLAtoms::mprescripts_ )
07073     rv = NS_NewMathMLmspaceFrame(mPresShell, &newFrame);
07074   else if (aTag == nsMathMLAtoms::mfenced_)
07075     rv = NS_NewMathMLmfencedFrame(mPresShell, &newFrame);
07076   else if (aTag == nsMathMLAtoms::mmultiscripts_)
07077     rv = NS_NewMathMLmmultiscriptsFrame(mPresShell, &newFrame);
07078   else if (aTag == nsMathMLAtoms::mstyle_)
07079     rv = NS_NewMathMLmstyleFrame(mPresShell, &newFrame);
07080   else if (aTag == nsMathMLAtoms::msqrt_)
07081     rv = NS_NewMathMLmsqrtFrame(mPresShell, &newFrame);
07082   else if (aTag == nsMathMLAtoms::mroot_)
07083     rv = NS_NewMathMLmrootFrame(mPresShell, &newFrame);
07084   else if (aTag == nsMathMLAtoms::maction_)
07085     rv = NS_NewMathMLmactionFrame(mPresShell, &newFrame);
07086   else if (aTag == nsMathMLAtoms::mrow_   ||
07087            aTag == nsMathMLAtoms::merror_)
07088     rv = NS_NewMathMLmrowFrame(mPresShell, &newFrame);
07089   // CONSTRUCTION of MTABLE elements
07090   else if (aTag == nsMathMLAtoms::mtable_ &&
07091            disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
07092     // <mtable> is an inline-table -- but this isn't yet supported.
07093     // What we do here is to wrap the table in an anonymous containing
07094     // block so that it can mix better with other surrounding MathML markups
07095     // XXXbz this is wrong if the <mtable> is positioned or floated.
07096 
07097     nsStyleContext* parentContext = aParentFrame->GetStyleContext();
07098     nsStyleSet *styleSet = mPresShell->StyleSet();
07099 
07100     // first, create a MathML mrow frame that will wrap the block frame
07101     rv = NS_NewMathMLmrowFrame(mPresShell, &newFrame);
07102     if (NS_FAILED(rv)) return rv;
07103     nsRefPtr<nsStyleContext> mrowContext;
07104     mrowContext = styleSet->ResolvePseudoStyleFor(aContent,
07105                                                   nsCSSAnonBoxes::mozMathInline,
07106                                                   parentContext);
07107     InitAndRestoreFrame(aState, aContent, aParentFr