LCOV - code coverage report
Current view: directory - layout/base - nsCSSFrameConstructor.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 4061 0 0.0 %
Date: 2012-06-02 Functions: 229 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : // vim:cindent:ts=2:et:sw=2:
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Dan Rosen <dr@netscape.com>
      25                 :  *   Mats Palmgren <matspal@gmail.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : /*
      42                 :  * construction of a frame tree that is nearly isomorphic to the content
      43                 :  * tree and updating of that tree in response to dynamic changes
      44                 :  */
      45                 : 
      46                 : #include "mozilla/Util.h"
      47                 : 
      48                 : #include "nsCSSFrameConstructor.h"
      49                 : #include "nsCRT.h"
      50                 : #include "nsIAtom.h"
      51                 : #include "nsIURL.h"
      52                 : #include "nsHashtable.h"
      53                 : #include "nsIHTMLDocument.h"
      54                 : #include "nsIStyleRule.h"
      55                 : #include "nsIFrame.h"
      56                 : #include "nsGkAtoms.h"
      57                 : #include "nsPresContext.h"
      58                 : #include "nsILinkHandler.h"
      59                 : #include "nsIDocument.h"
      60                 : #include "nsTableFrame.h"
      61                 : #include "nsTableColGroupFrame.h"
      62                 : #include "nsTableColFrame.h"
      63                 : #include "nsIDOMHTMLDocument.h"
      64                 : #include "nsIDOMHTMLTableColElement.h"
      65                 : #include "nsIDOMHTMLTableCaptionElem.h"
      66                 : #include "nsHTMLParts.h"
      67                 : #include "nsIPresShell.h"
      68                 : #include "nsUnicharUtils.h"
      69                 : #include "nsStyleSet.h"
      70                 : #include "nsIViewManager.h"
      71                 : #include "nsEventStates.h"
      72                 : #include "nsStyleConsts.h"
      73                 : #include "nsTableOuterFrame.h"
      74                 : #include "nsIDOMXULElement.h"
      75                 : #include "nsContainerFrame.h"
      76                 : #include "nsINameSpaceManager.h"
      77                 : #include "nsIDOMHTMLSelectElement.h"
      78                 : #include "nsIDOMHTMLLegendElement.h"
      79                 : #include "nsIComboboxControlFrame.h"
      80                 : #include "nsIListControlFrame.h"
      81                 : #include "nsISelectControlFrame.h"
      82                 : #include "nsIDOMCharacterData.h"
      83                 : #include "nsIDOMHTMLImageElement.h"
      84                 : #include "nsPlaceholderFrame.h"
      85                 : #include "nsTableRowGroupFrame.h"
      86                 : #include "nsStyleChangeList.h"
      87                 : #include "nsIFormControl.h"
      88                 : #include "nsCSSAnonBoxes.h"
      89                 : #include "nsTextFragment.h"
      90                 : #include "nsIAnonymousContentCreator.h"
      91                 : #include "nsLegendFrame.h"
      92                 : #include "nsIContentIterator.h"
      93                 : #include "nsBoxLayoutState.h"
      94                 : #include "nsBindingManager.h"
      95                 : #include "nsXBLBinding.h"
      96                 : #include "nsITheme.h"
      97                 : #include "nsContentCID.h"
      98                 : #include "nsContentUtils.h"
      99                 : #include "nsIScriptError.h"
     100                 : #include "nsIDocShell.h"
     101                 : #include "nsIDocShellTreeItem.h"
     102                 : #include "nsObjectFrame.h"
     103                 : #include "nsRuleNode.h"
     104                 : #include "nsIDOMMutationEvent.h"
     105                 : #include "nsChildIterator.h"
     106                 : #include "nsCSSRendering.h"
     107                 : #include "nsLayoutErrors.h"
     108                 : #include "nsLayoutUtils.h"
     109                 : #include "nsAutoPtr.h"
     110                 : #include "nsBoxFrame.h"
     111                 : #include "nsBoxLayout.h"
     112                 : #include "nsImageFrame.h"
     113                 : #include "nsIObjectLoadingContent.h"
     114                 : #include "nsContentErrors.h"
     115                 : #include "nsIPrincipal.h"
     116                 : #include "nsStyleUtil.h"
     117                 : #include "nsBox.h"
     118                 : #include "nsTArray.h"
     119                 : #include "nsGenericDOMDataNode.h"
     120                 : #include "mozilla/dom/Element.h"
     121                 : #include "FrameLayerBuilder.h"
     122                 : #include "nsAutoLayoutPhase.h"
     123                 : 
     124                 : #ifdef MOZ_XUL
     125                 : #include "nsIRootBox.h"
     126                 : #include "nsIDOMXULCommandDispatcher.h"
     127                 : #include "nsIDOMXULDocument.h"
     128                 : #include "nsIXULDocument.h"
     129                 : #endif
     130                 : #ifdef ACCESSIBILITY
     131                 : #include "nsAccessibilityService.h"
     132                 : #endif
     133                 : 
     134                 : #include "nsInlineFrame.h"
     135                 : #include "nsBlockFrame.h"
     136                 : 
     137                 : #include "nsIScrollableFrame.h"
     138                 : 
     139                 : #include "nsIXBLService.h"
     140                 : 
     141                 : #undef NOISY_FIRST_LETTER
     142                 : 
     143                 : #include "nsMathMLParts.h"
     144                 : #include "nsIDOMSVGFilters.h"
     145                 : #include "DOMSVGTests.h"
     146                 : #include "nsSVGEffects.h"
     147                 : #include "nsSVGUtils.h"
     148                 : 
     149                 : #include "nsRefreshDriver.h"
     150                 : #include "nsRuleProcessorData.h"
     151                 : 
     152                 : using namespace mozilla;
     153                 : using namespace mozilla::dom;
     154                 : 
     155                 : // An alias for convenience.
     156                 : static const nsIFrame::ChildListID kPrincipalList = nsIFrame::kPrincipalList;
     157                 : 
     158                 : nsIFrame*
     159                 : NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     160                 : 
     161                 : #if defined(MOZ_MEDIA)
     162                 : nsIFrame*
     163                 : NS_NewHTMLVideoFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     164                 : #endif
     165                 : 
     166                 : #include "nsSVGTextContainerFrame.h"
     167                 : 
     168                 : nsIFrame*
     169                 : NS_NewSVGOuterSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     170                 : nsIFrame*
     171                 : NS_NewSVGInnerSVGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     172                 : nsIFrame*
     173                 : NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     174                 : nsIFrame*
     175                 : NS_NewSVGGFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     176                 : nsIFrame*
     177                 : NS_NewSVGGenericContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     178                 : nsIFrame*
     179                 : NS_NewSVGForeignObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     180                 : nsIFrame*
     181                 : NS_NewSVGAFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     182                 : nsIFrame*
     183                 : NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     184                 : nsIFrame*
     185                 : NS_NewSVGSwitchFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     186                 : nsIFrame*
     187                 : NS_NewSVGTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     188                 : nsIFrame*
     189                 : NS_NewSVGTSpanFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     190                 : nsIFrame*
     191                 : NS_NewSVGContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     192                 : nsIFrame*
     193                 : NS_NewSVGUseFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     194                 : extern nsIFrame*
     195                 : NS_NewSVGLinearGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     196                 : extern nsIFrame*
     197                 : NS_NewSVGRadialGradientFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     198                 : extern nsIFrame*
     199                 : NS_NewSVGStopFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     200                 : nsIFrame*
     201                 : NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     202                 : extern nsIFrame*
     203                 : NS_NewSVGImageFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     204                 : nsIFrame*
     205                 : NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     206                 : nsIFrame*
     207                 : NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     208                 : nsIFrame*
     209                 : NS_NewSVGFilterFrame(nsIPresShell *aPresShell, nsStyleContext* aContext);
     210                 : nsIFrame*
     211                 : NS_NewSVGPatternFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     212                 : nsIFrame*
     213                 : NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     214                 : nsIFrame*
     215                 : NS_NewSVGFEContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     216                 : nsIFrame*
     217                 : NS_NewSVGFELeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     218                 : nsIFrame*
     219                 : NS_NewSVGFEImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     220                 : nsIFrame*
     221                 : NS_NewSVGFEUnstyledLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     222                 : 
     223                 : #include "nsIScrollable.h"
     224                 : #include "nsINodeInfo.h"
     225                 : #include "prenv.h"
     226                 : #include "nsWidgetsCID.h"
     227                 : #include "nsNodeInfoManager.h"
     228                 : #include "nsContentCreatorFunctions.h"
     229                 : #include "nsIServiceManager.h"
     230                 : 
     231                 : // Global object maintenance
     232                 : nsIXBLService * nsCSSFrameConstructor::gXBLService = nsnull;
     233                 : 
     234                 : #ifdef DEBUG
     235                 : // Set the environment variable GECKO_FRAMECTOR_DEBUG_FLAGS to one or
     236                 : // more of the following flags (comma separated) for handy debug
     237                 : // output.
     238                 : static bool gNoisyContentUpdates = false;
     239                 : static bool gReallyNoisyContentUpdates = false;
     240                 : static bool gNoisyInlineConstruction = false;
     241                 : 
     242                 : struct FrameCtorDebugFlags {
     243                 :   const char* name;
     244                 :   bool* on;
     245                 : };
     246                 : 
     247                 : static FrameCtorDebugFlags gFlags[] = {
     248                 :   { "content-updates",              &gNoisyContentUpdates },
     249                 :   { "really-noisy-content-updates", &gReallyNoisyContentUpdates },
     250                 :   { "noisy-inline",                 &gNoisyInlineConstruction }
     251                 : };
     252                 : 
     253                 : #define NUM_DEBUG_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
     254                 : #endif
     255                 : 
     256                 : 
     257                 : #ifdef MOZ_XUL
     258                 : #include "nsMenuFrame.h"
     259                 : #include "nsMenuPopupFrame.h"
     260                 : #include "nsPopupSetFrame.h"
     261                 : #include "nsTreeColFrame.h"
     262                 : #include "nsIBoxObject.h"
     263                 : #include "nsPIListBoxObject.h"
     264                 : #include "nsListBoxBodyFrame.h"
     265                 : #include "nsListItemFrame.h"
     266                 : #include "nsXULLabelFrame.h"
     267                 : 
     268                 : //------------------------------------------------------------------
     269                 : 
     270                 : nsIFrame*
     271                 : NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     272                 : 
     273                 : nsIFrame*
     274                 : NS_NewRootBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     275                 : 
     276                 : nsIFrame*
     277                 : NS_NewDocElementBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     278                 : 
     279                 : nsIFrame*
     280                 : NS_NewThumbFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     281                 : 
     282                 : nsIFrame*
     283                 : NS_NewDeckFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     284                 : 
     285                 : nsIFrame*
     286                 : NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     287                 : 
     288                 : nsIFrame*
     289                 : NS_NewStackFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     290                 : 
     291                 : nsIFrame*
     292                 : NS_NewProgressMeterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     293                 : 
     294                 : nsIFrame*
     295                 : NS_NewImageBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     296                 : 
     297                 : nsIFrame*
     298                 : NS_NewTextBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     299                 : 
     300                 : nsIFrame*
     301                 : NS_NewGroupBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     302                 : 
     303                 : nsIFrame*
     304                 : NS_NewButtonBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     305                 : 
     306                 : nsIFrame*
     307                 : NS_NewSplitterFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     308                 : 
     309                 : nsIFrame*
     310                 : NS_NewMenuPopupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     311                 : 
     312                 : nsIFrame*
     313                 : NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
     314                 : 
     315                 : nsIFrame*
     316                 : NS_NewMenuFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
     317                 : 
     318                 : nsIFrame*
     319                 : NS_NewMenuBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     320                 : 
     321                 : nsIFrame*
     322                 : NS_NewTreeBodyFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     323                 : 
     324                 : // grid
     325                 : nsresult
     326                 : NS_NewGridLayout2 ( nsIPresShell* aPresShell, nsBoxLayout** aNewLayout );
     327                 : nsIFrame*
     328                 : NS_NewGridRowLeafFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     329                 : nsIFrame*
     330                 : NS_NewGridRowGroupFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     331                 : 
     332                 : // end grid
     333                 : 
     334                 : nsIFrame*
     335                 : NS_NewTitleBarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     336                 : 
     337                 : nsIFrame*
     338                 : NS_NewResizerFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     339                 : 
     340                 : 
     341                 : #endif
     342                 : 
     343                 : nsIFrame*
     344                 : NS_NewHTMLScrollFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot);
     345                 : 
     346                 : nsIFrame*
     347                 : NS_NewXULScrollFrame (nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot);
     348                 : 
     349                 : nsIFrame*
     350                 : NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     351                 : 
     352                 : nsIFrame*
     353                 : NS_NewScrollbarFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     354                 : 
     355                 : nsIFrame*
     356                 : NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
     357                 : 
     358                 : 
     359                 : #ifdef NOISY_FINDFRAME
     360                 : static PRInt32 FFWC_totalCount=0;
     361                 : static PRInt32 FFWC_doLoop=0;
     362                 : static PRInt32 FFWC_doSibling=0;
     363                 : static PRInt32 FFWC_recursions=0;
     364                 : static PRInt32 FFWC_nextInFlows=0;
     365                 : #endif
     366                 : 
     367                 : static inline nsIFrame*
     368               0 : GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
     369                 : {
     370                 :   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
     371               0 :   nsIFrame* firstChild = aFieldsetFrame->GetFirstPrincipalChild();
     372               0 :   return firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
     373                 : }
     374                 : 
     375                 : #define FCDATA_DECL(_flags, _func)                          \
     376                 :   { _flags, { (FrameCreationFunc)_func }, nsnull, nsnull }
     377                 : #define FCDATA_WITH_WRAPPING_BLOCK(_flags, _func, _anon_box)  \
     378                 :   { _flags | FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS,        \
     379                 :       { (FrameCreationFunc)_func }, nsnull, &_anon_box }
     380                 : 
     381                 : //----------------------------------------------------------------------
     382                 : 
     383                 : static bool
     384               0 : IsInlineOutside(nsIFrame* aFrame)
     385                 : {
     386               0 :   return aFrame->GetStyleDisplay()->IsInlineOutside();
     387                 : }
     388                 : 
     389                 : /**
     390                 :  * True if aFrame is an actual inline frame in the sense of non-replaced
     391                 :  * display:inline CSS boxes.  In other words, it can be affected by {ib}
     392                 :  * splitting and can contain first-letter frames.  Basically, this is either an
     393                 :  * inline frame (positioned or otherwise) or an line frame (this last because
     394                 :  * it can contain first-letter and because inserting blocks in the middle of it
     395                 :  * needs to terminate it).
     396                 :  */
     397                 : static bool
     398               0 : IsInlineFrame(const nsIFrame* aFrame)
     399                 : {
     400               0 :   return aFrame->IsFrameOfType(nsIFrame::eLineParticipant);
     401                 : }
     402                 : 
     403                 : /**
     404                 :  * If any children require a block parent, return the first such child.
     405                 :  * Otherwise return null.
     406                 :  */
     407                 : static nsIContent*
     408               0 : AnyKidsNeedBlockParent(nsIFrame *aFrameList)
     409                 : {
     410               0 :   for (nsIFrame *k = aFrameList; k; k = k->GetNextSibling()) {
     411                 :     // Line participants, such as text and inline frames, can't be
     412                 :     // directly inside a XUL box; they must be wrapped in an
     413                 :     // intermediate block.
     414               0 :     if (k->IsFrameOfType(nsIFrame::eLineParticipant)) {
     415               0 :       return k->GetContent();
     416                 :     }
     417                 :   }
     418               0 :   return nsnull;
     419                 : }
     420                 : 
     421                 : // Reparent a frame into a wrapper frame that is a child of its old parent.
     422                 : static void
     423               0 : ReparentFrame(nsFrameManager* aFrameManager,
     424                 :               nsIFrame* aNewParentFrame,
     425                 :               nsIFrame* aFrame)
     426                 : {
     427               0 :   aFrame->SetParent(aNewParentFrame);
     428               0 :   aFrameManager->ReparentStyleContext(aFrame);
     429               0 : }
     430                 : 
     431                 : static void
     432               0 : ReparentFrames(nsFrameManager* aFrameManager,
     433                 :                nsIFrame* aNewParentFrame,
     434                 :                const nsFrameList& aFrameList)
     435                 : {
     436               0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
     437               0 :     ReparentFrame(aFrameManager, aNewParentFrame, e.get());
     438                 :   }
     439               0 : }
     440                 : 
     441                 : //----------------------------------------------------------------------
     442                 : //
     443                 : // When inline frames get weird and have block frames in them, we
     444                 : // annotate them to help us respond to incremental content changes
     445                 : // more easily.
     446                 : 
     447                 : static inline bool
     448               0 : IsFrameSpecial(nsIFrame* aFrame)
     449                 : {
     450               0 :   return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) != 0;
     451                 : }
     452                 : 
     453               0 : static nsIFrame* GetSpecialSibling(nsIFrame* aFrame)
     454                 : {
     455               0 :   NS_PRECONDITION(IsFrameSpecial(aFrame), "Shouldn't call this");
     456                 : 
     457                 :   // We only store the "special sibling" annotation with the first
     458                 :   // frame in the continuation chain. Walk back to find that frame now.
     459                 :   return static_cast<nsIFrame*>
     460               0 :     (aFrame->GetFirstContinuation()->
     461               0 :        Properties().Get(nsIFrame::IBSplitSpecialSibling()));
     462                 : }
     463                 : 
     464               0 : static nsIFrame* GetSpecialPrevSibling(nsIFrame* aFrame)
     465                 : {
     466               0 :   NS_PRECONDITION(IsFrameSpecial(aFrame), "Shouldn't call this");
     467                 :   
     468                 :   // We only store the "special sibling" annotation with the first
     469                 :   // frame in the continuation chain. Walk back to find that frame now.  
     470                 :   return static_cast<nsIFrame*>
     471               0 :     (aFrame->GetFirstContinuation()->
     472               0 :        Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()));
     473                 : }
     474                 : 
     475                 : static nsIFrame*
     476               0 : GetLastSpecialSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
     477                 : {
     478               0 :   for (nsIFrame *frame = aFrame, *next; ; frame = next) {
     479               0 :     next = GetSpecialSibling(frame);
     480               0 :     if (!next ||
     481               0 :         (!aReturnEmptyTrailingInline && !next->GetFirstPrincipalChild() &&
     482               0 :          !GetSpecialSibling(next))) {
     483               0 :       NS_ASSERTION(!next || !IsInlineOutside(frame),
     484                 :                    "Should have a block here!");
     485               0 :       return frame;
     486                 :     }
     487                 :   }
     488                 :   NS_NOTREACHED("unreachable code");
     489                 :   return nsnull;
     490                 : }
     491                 : 
     492                 : static void
     493               0 : SetFrameIsSpecial(nsIFrame* aFrame, nsIFrame* aSpecialSibling)
     494                 : {
     495               0 :   NS_PRECONDITION(aFrame, "bad args!");
     496                 : 
     497                 :   // We should be the only continuation
     498               0 :   NS_ASSERTION(!aFrame->GetPrevContinuation(),
     499                 :                "assigning special sibling to other than first continuation!");
     500               0 :   NS_ASSERTION(!aFrame->GetNextContinuation() ||
     501                 :                IsFrameSpecial(aFrame->GetNextContinuation()),
     502                 :                "should have no non-special continuations here");
     503                 : 
     504                 :   // Mark the frame as "special".
     505               0 :   aFrame->AddStateBits(NS_FRAME_IS_SPECIAL);
     506                 : 
     507               0 :   if (aSpecialSibling) {
     508               0 :     NS_ASSERTION(!aSpecialSibling->GetPrevContinuation(),
     509                 :                  "assigning something other than the first continuation as the "
     510                 :                  "special sibling");
     511                 : 
     512                 :     // Store the "special sibling" (if we were given one) with the
     513                 :     // first frame in the flow.
     514               0 :     FramePropertyTable* props = aFrame->PresContext()->PropertyTable();
     515               0 :     props->Set(aFrame, nsIFrame::IBSplitSpecialSibling(), aSpecialSibling);
     516               0 :     props->Set(aSpecialSibling, nsIFrame::IBSplitSpecialPrevSibling(), aFrame);
     517                 :   }
     518               0 : }
     519                 : 
     520                 : static nsIFrame*
     521               0 : GetIBContainingBlockFor(nsIFrame* aFrame)
     522                 : {
     523               0 :   NS_PRECONDITION(IsFrameSpecial(aFrame),
     524                 :                   "GetIBContainingBlockFor() should only be called on known IB frames");
     525                 : 
     526                 :   // Get the first "normal" ancestor of the target frame.
     527                 :   nsIFrame* parentFrame;
     528               0 :   do {
     529               0 :     parentFrame = aFrame->GetParent();
     530                 : 
     531               0 :     if (! parentFrame) {
     532               0 :       NS_ERROR("no unsplit block frame in IB hierarchy");
     533               0 :       return aFrame;
     534                 :     }
     535                 : 
     536                 :     // Note that we ignore non-special frames which have a pseudo on their
     537                 :     // style context -- they're not the frames we're looking for!  In
     538                 :     // particular, they may be hiding a real parent that _is_ special.
     539               0 :     if (!IsFrameSpecial(parentFrame) &&
     540               0 :         !parentFrame->GetStyleContext()->GetPseudo())
     541                 :       break;
     542                 : 
     543               0 :     aFrame = parentFrame;
     544                 :   } while (1);
     545                 :  
     546                 :   // post-conditions
     547               0 :   NS_ASSERTION(parentFrame, "no normal ancestor found for special frame in GetIBContainingBlockFor");
     548               0 :   NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
     549                 : 
     550               0 :   return parentFrame;
     551                 : }
     552                 : 
     553                 : //----------------------------------------------------------------------
     554                 : 
     555                 : // Block/inline frame construction logic. We maintain a few invariants here:
     556                 : //
     557                 : // 1. Block frames contain block and inline frames.
     558                 : //
     559                 : // 2. Inline frames only contain inline frames. If an inline parent has a block
     560                 : // child then the block child is migrated upward until it lands in a block
     561                 : // parent (the inline frames containing block is where it will end up).
     562                 : 
     563                 : // After this function returns, aLink is pointing to the first link at or
     564                 : // after its starting position for which the next frame is a block.  If there
     565                 : // is no such link, it points to the end of the list.
     566                 : static void
     567               0 : FindFirstBlock(nsFrameList::FrameLinkEnumerator& aLink)
     568                 : {
     569               0 :   for ( ; !aLink.AtEnd(); aLink.Next()) {
     570               0 :     if (!IsInlineOutside(aLink.NextFrame())) {
     571               0 :       return;
     572                 :     }
     573                 :   }
     574                 : }
     575                 : 
     576                 : // This function returns a frame link enumerator pointing to the first link in
     577                 : // the list for which the next frame is not block.  If there is no such link,
     578                 : // it points to the end of the list.
     579                 : static nsFrameList::FrameLinkEnumerator
     580               0 : FindFirstNonBlock(const nsFrameList& aList)
     581                 : {
     582               0 :   nsFrameList::FrameLinkEnumerator link(aList);
     583               0 :   for (; !link.AtEnd(); link.Next()) {
     584               0 :     if (IsInlineOutside(link.NextFrame())) {
     585               0 :       break;
     586                 :     }
     587                 :   }
     588                 :   return link;
     589                 : }
     590                 : 
     591                 : inline void
     592               0 : SetInitialSingleChild(nsIFrame* aParent, nsIFrame* aFrame)
     593                 : {
     594               0 :   NS_PRECONDITION(!aFrame->GetNextSibling(), "Should be using a frame list");
     595               0 :   nsFrameList temp(aFrame, aFrame);
     596               0 :   aParent->SetInitialChildList(kPrincipalList, temp);
     597               0 : }
     598                 : 
     599                 : // -----------------------------------------------------------
     600                 : 
     601                 : // Structure used when constructing formatting object trees.
     602                 : struct nsFrameItems : public nsFrameList
     603               0 : {
     604                 :   // Appends the frame to the end of the list
     605                 :   void AddChild(nsIFrame* aChild);
     606                 : };
     607                 : 
     608                 : void 
     609               0 : nsFrameItems::AddChild(nsIFrame* aChild)
     610                 : {
     611               0 :   NS_PRECONDITION(aChild, "nsFrameItems::AddChild");
     612                 : 
     613                 :   // It'd be really nice if we could just AppendFrames(kPrincipalList, aChild) here,
     614                 :   // but some of our callers put frames that have different
     615                 :   // parents (caption, I'm looking at you) on the same framelist, and
     616                 :   // nsFrameList asserts if you try to do that.
     617               0 :   if (IsEmpty()) {
     618               0 :     SetFrames(aChild);
     619                 :   }
     620                 :   else {
     621               0 :     NS_ASSERTION(aChild != mLastChild,
     622                 :                  "Same frame being added to frame list twice?");
     623               0 :     mLastChild->SetNextSibling(aChild);
     624               0 :     mLastChild = nsLayoutUtils::GetLastSibling(aChild);
     625                 :   }
     626               0 : }
     627                 : 
     628                 : // -----------------------------------------------------------
     629                 : 
     630                 : // Structure used when constructing formatting object trees. Contains
     631                 : // state information needed for absolutely positioned elements
     632                 : struct nsAbsoluteItems : nsFrameItems {
     633                 :   // containing block for absolutely positioned elements
     634                 :   nsIFrame* containingBlock;
     635                 :   
     636                 :   nsAbsoluteItems(nsIFrame* aContainingBlock);
     637                 : #ifdef DEBUG
     638                 :   // XXXbz Does this need a debug-only assignment operator that nulls out the
     639                 :   // childList in the nsAbsoluteItems we're copying?  Introducing a difference
     640                 :   // between debug and non-debug behavior seems bad, so I guess not...
     641               0 :   ~nsAbsoluteItems() {
     642               0 :     NS_ASSERTION(!FirstChild(),
     643                 :                  "Dangling child list.  Someone forgot to insert it?");
     644               0 :   }
     645                 : #endif
     646                 :   
     647                 :   // Appends the frame to the end of the list
     648                 :   void AddChild(nsIFrame* aChild);
     649                 : };
     650                 : 
     651               0 : nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock)
     652               0 :   : containingBlock(aContainingBlock)
     653                 : {
     654               0 : }
     655                 : 
     656                 : // Additional behavior is that it sets the frame's NS_FRAME_OUT_OF_FLOW flag
     657                 : void
     658               0 : nsAbsoluteItems::AddChild(nsIFrame* aChild)
     659                 : {
     660               0 :   NS_ASSERTION(aChild->PresContext()->FrameManager()->
     661                 :                GetPlaceholderFrameFor(aChild),
     662                 :                "Child without placeholder being added to nsAbsoluteItems?");
     663               0 :   aChild->AddStateBits(NS_FRAME_OUT_OF_FLOW);
     664               0 :   nsFrameItems::AddChild(aChild);
     665               0 : }
     666                 : 
     667                 : // -----------------------------------------------------------
     668                 : 
     669                 : // Structure for saving the existing state when pushing/poping containing
     670                 : // blocks. The destructor restores the state to its previous state
     671                 : class NS_STACK_CLASS nsFrameConstructorSaveState {
     672                 : public:
     673                 :   typedef nsIFrame::ChildListID ChildListID;
     674                 :   nsFrameConstructorSaveState();
     675                 :   ~nsFrameConstructorSaveState();
     676                 : 
     677                 : private:
     678                 :   nsAbsoluteItems* mItems;                // pointer to struct whose data we save/restore
     679                 :   bool*    mFixedPosIsAbsPos;
     680                 : 
     681                 :   nsAbsoluteItems  mSavedItems;           // copy of original data
     682                 :   bool             mSavedFixedPosIsAbsPos;
     683                 : 
     684                 :   // The name of the child list in which our frames would belong
     685                 :   ChildListID mChildListID;
     686                 :   nsFrameConstructorState* mState;
     687                 : 
     688                 :   friend class nsFrameConstructorState;
     689                 : };
     690                 : 
     691                 : // Structure used to keep track of a list of bindings we need to call
     692                 : // AddToAttachedQueue on.  These should be in post-order depth-first
     693                 : // flattened tree traversal order.
     694                 : struct PendingBinding : public PRCList
     695                 : {
     696                 : #ifdef NS_BUILD_REFCNT_LOGGING
     697               0 :   PendingBinding() {
     698               0 :     MOZ_COUNT_CTOR(PendingBinding);
     699               0 :   }
     700               0 :   ~PendingBinding() {
     701               0 :     MOZ_COUNT_DTOR(PendingBinding);
     702               0 :   }
     703                 : #endif
     704                 : 
     705                 :   nsRefPtr<nsXBLBinding> mBinding;
     706                 : };
     707                 : 
     708                 : // Structure used for maintaining state information during the
     709                 : // frame construction process
     710                 : class NS_STACK_CLASS nsFrameConstructorState {
     711                 : public:
     712                 :   typedef nsIFrame::ChildListID ChildListID;
     713                 : 
     714                 :   nsPresContext            *mPresContext;
     715                 :   nsIPresShell             *mPresShell;
     716                 :   nsFrameManager           *mFrameManager;
     717                 : 
     718                 : #ifdef MOZ_XUL
     719                 :   // Frames destined for the kPopupList.
     720                 :   nsAbsoluteItems           mPopupItems;
     721                 : #endif
     722                 : 
     723                 :   // Containing block information for out-of-flow frames.
     724                 :   nsAbsoluteItems           mFixedItems;
     725                 :   nsAbsoluteItems           mAbsoluteItems;
     726                 :   nsAbsoluteItems           mFloatedItems;
     727                 : 
     728                 :   nsCOMPtr<nsILayoutHistoryState> mFrameState;
     729                 :   // These bits will be added to the state bits of any frame we construct
     730                 :   // using this state.
     731                 :   nsFrameState              mAdditionalStateBits;
     732                 : 
     733                 :   // When working with the -moz-transform property, we want to hook
     734                 :   // the abs-pos and fixed-pos lists together, since transformed
     735                 :   // elements are fixed-pos containing blocks.  This flag determines
     736                 :   // whether or not we want to wire the fixed-pos and abs-pos lists
     737                 :   // together.
     738                 :   bool                      mFixedPosIsAbsPos;
     739                 : 
     740                 :   // A boolean to indicate whether we have a "pending" popupgroup.  That is, we
     741                 :   // have already created the FrameConstructionItem for the root popupgroup but
     742                 :   // we have not yet created the relevant frame.
     743                 :   bool                      mHavePendingPopupgroup;
     744                 : 
     745                 :   // If false (which is the default) then call SetPrimaryFrame() as needed
     746                 :   // during frame construction.  If true, don't make any SetPrimaryFrame()
     747                 :   // calls, except for generated content which doesn't have a primary frame
     748                 :   // yet.  The mCreatingExtraFrames == true mode is meant to be used for
     749                 :   // construction of random "extra" frames for elements via normal frame
     750                 :   // construction APIs (e.g. replication of things across pages in paginated
     751                 :   // mode).
     752                 :   bool                      mCreatingExtraFrames;
     753                 : 
     754                 :   nsCOMArray<nsIContent>    mGeneratedTextNodesWithInitializer;
     755                 : 
     756                 :   TreeMatchContext          mTreeMatchContext;
     757                 : 
     758                 :   // Constructor
     759                 :   // Use the passed-in history state.
     760                 :   nsFrameConstructorState(nsIPresShell*          aPresShell,
     761                 :                           nsIFrame*              aFixedContainingBlock,
     762                 :                           nsIFrame*              aAbsoluteContainingBlock,
     763                 :                           nsIFrame*              aFloatContainingBlock,
     764                 :                           nsILayoutHistoryState* aHistoryState);
     765                 :   // Get the history state from the pres context's pres shell.
     766                 :   nsFrameConstructorState(nsIPresShell*          aPresShell,
     767                 :                           nsIFrame*              aFixedContainingBlock,
     768                 :                           nsIFrame*              aAbsoluteContainingBlock,
     769                 :                           nsIFrame*              aFloatContainingBlock);
     770                 : 
     771                 :   ~nsFrameConstructorState();
     772                 :   
     773                 :   // Function to push the existing absolute containing block state and
     774                 :   // create a new scope. Code that uses this function should get matching
     775                 :   // logic in GetAbsoluteContainingBlock.
     776                 :   void PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
     777                 :                                    nsFrameConstructorSaveState& aSaveState);
     778                 : 
     779                 :   // Function to push the existing float containing block state and
     780                 :   // create a new scope. Code that uses this function should get matching
     781                 :   // logic in GetFloatContainingBlock.
     782                 :   // Pushing a null float containing block forbids any frames from being
     783                 :   // floated until a new float containing block is pushed.
     784                 :   // XXX we should get rid of null float containing blocks and teach the
     785                 :   // various frame classes to deal with floats instead.
     786                 :   void PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
     787                 :                                 nsFrameConstructorSaveState& aSaveState);
     788                 : 
     789                 :   // Function to return the proper geometric parent for a frame with display
     790                 :   // struct given by aStyleDisplay and parent's frame given by
     791                 :   // aContentParentFrame.
     792                 :   nsIFrame* GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
     793                 :                                nsIFrame* aContentParentFrame);
     794                 : 
     795                 :   /**
     796                 :    * Function to add a new frame to the right frame list.  This MUST be called
     797                 :    * on frames before their children have been processed if the frames might
     798                 :    * conceivably be out-of-flow; otherwise cleanup in error cases won't work
     799                 :    * right.  Also, this MUST be called on frames after they have been
     800                 :    * initialized.
     801                 :    * @param aNewFrame the frame to add
     802                 :    * @param aFrameItems the list to add in-flow frames to
     803                 :    * @param aContent the content pointer for aNewFrame
     804                 :    * @param aStyleContext the style context resolved for aContent
     805                 :    * @param aParentFrame the parent frame for the content if it were in-flow
     806                 :    * @param aCanBePositioned pass false if the frame isn't allowed to be
     807                 :    *        positioned
     808                 :    * @param aCanBeFloated pass false if the frame isn't allowed to be
     809                 :    *        floated
     810                 :    * @param aIsOutOfFlowPopup pass true if the frame is an out-of-flow popup
     811                 :    *        (XUL-only)
     812                 :    * @throws NS_ERROR_OUT_OF_MEMORY if it happens.
     813                 :    * @note If this method throws, that means that aNewFrame was not inserted
     814                 :    *       into any frame lists.  Furthermore, this method will handle cleanup
     815                 :    *       of aNewFrame (via calling Destroy() on it).
     816                 :    */
     817                 :   nsresult AddChild(nsIFrame* aNewFrame,
     818                 :                     nsFrameItems& aFrameItems,
     819                 :                     nsIContent* aContent,
     820                 :                     nsStyleContext* aStyleContext,
     821                 :                     nsIFrame* aParentFrame,
     822                 :                     bool aCanBePositioned = true,
     823                 :                     bool aCanBeFloated = true,
     824                 :                     bool aIsOutOfFlowPopup = false,
     825                 :                     bool aInsertAfter = false,
     826                 :                     nsIFrame* aInsertAfterFrame = nsnull);
     827                 : 
     828                 :   /**
     829                 :    * Function to return the fixed-pos element list.  Normally this will just hand back the
     830                 :    * fixed-pos element list, but in case we're dealing with a transformed element that's
     831                 :    * acting as an abs-pos and fixed-pos container, we'll hand back the abs-pos list.  Callers should
     832                 :    * use this function if they want to get the list acting as the fixed-pos item parent.
     833                 :    */
     834               0 :   nsAbsoluteItems& GetFixedItems()
     835                 :   {
     836               0 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     837                 :   }
     838                 :   const nsAbsoluteItems& GetFixedItems() const
     839                 :   {
     840                 :     return mFixedPosIsAbsPos ? mAbsoluteItems : mFixedItems;
     841                 :   }
     842                 : 
     843                 : 
     844                 :   /**
     845                 :    * class to automatically push and pop a pending binding in the frame
     846                 :    * constructor state.  See nsCSSFrameConstructor::FrameConstructionItem
     847                 :    * mPendingBinding documentation.
     848                 :    */
     849                 :   class PendingBindingAutoPusher;
     850                 :   friend class PendingBindingAutoPusher;
     851                 :   class NS_STACK_CLASS PendingBindingAutoPusher {
     852                 :   public:
     853               0 :     PendingBindingAutoPusher(nsFrameConstructorState& aState,
     854                 :                              PendingBinding* aPendingBinding) :
     855                 :       mState(aState),
     856               0 :       mPendingBinding(aState.mCurrentPendingBindingInsertionPoint)
     857                 :         {
     858               0 :           NS_PRECONDITION(mPendingBinding, "how did that happen?");
     859               0 :           if (aPendingBinding) {
     860               0 :             aState.mCurrentPendingBindingInsertionPoint = aPendingBinding;
     861                 :           }
     862               0 :         }
     863                 : 
     864               0 :     ~PendingBindingAutoPusher()
     865                 :       {
     866               0 :         mState.mCurrentPendingBindingInsertionPoint = mPendingBinding;
     867               0 :       }
     868                 : 
     869                 :   private:
     870                 :     nsFrameConstructorState& mState;
     871                 :     PRCList* mPendingBinding;
     872                 :   };
     873                 : 
     874                 :   /**
     875                 :    * Add a new pending binding to the list
     876                 :    */
     877               0 :   void AddPendingBinding(PendingBinding* aPendingBinding) {
     878               0 :     PR_INSERT_BEFORE(aPendingBinding, mCurrentPendingBindingInsertionPoint);
     879               0 :   }
     880                 : 
     881                 : protected:
     882                 :   friend class nsFrameConstructorSaveState;
     883                 : 
     884                 :   /**
     885                 :    * ProcessFrameInsertions takes the frames in aFrameItems and adds them as
     886                 :    * kids to the aChildListID child list of |aFrameItems.containingBlock|.
     887                 :    */
     888                 :   void ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
     889                 :                               ChildListID aChildListID);
     890                 : 
     891                 :   // Our list of all pending bindings.  When we're done, we need to call
     892                 :   // AddToAttachedQueue on all of them, in order.
     893                 :   PRCList mPendingBindings;
     894                 : 
     895                 :   PRCList* mCurrentPendingBindingInsertionPoint;
     896                 : };
     897                 : 
     898               0 : nsFrameConstructorState::nsFrameConstructorState(nsIPresShell*          aPresShell,
     899                 :                                                  nsIFrame*              aFixedContainingBlock,
     900                 :                                                  nsIFrame*              aAbsoluteContainingBlock,
     901                 :                                                  nsIFrame*              aFloatContainingBlock,
     902                 :                                                  nsILayoutHistoryState* aHistoryState)
     903               0 :   : mPresContext(aPresShell->GetPresContext()),
     904                 :     mPresShell(aPresShell),
     905               0 :     mFrameManager(aPresShell->FrameManager()),
     906                 : #ifdef MOZ_XUL    
     907                 :     mPopupItems(nsnull),
     908                 : #endif
     909                 :     mFixedItems(aFixedContainingBlock),
     910                 :     mAbsoluteItems(aAbsoluteContainingBlock),
     911                 :     mFloatedItems(aFloatContainingBlock),
     912                 :     // See PushAbsoluteContaningBlock below
     913                 :     mFrameState(aHistoryState),
     914                 :     mAdditionalStateBits(0),
     915                 :     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
     916                 :                       aAbsoluteContainingBlock->GetStyleDisplay()->
     917               0 :                         HasTransform()),
     918                 :     mHavePendingPopupgroup(false),
     919                 :     mCreatingExtraFrames(false),
     920                 :     mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
     921                 :                       aPresShell->GetDocument()),
     922               0 :     mCurrentPendingBindingInsertionPoint(&mPendingBindings)
     923                 : {
     924                 : #ifdef MOZ_XUL
     925               0 :   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
     926               0 :   if (rootBox) {
     927               0 :     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
     928                 :   }
     929                 : #endif
     930               0 :   MOZ_COUNT_CTOR(nsFrameConstructorState);
     931               0 :   PR_INIT_CLIST(&mPendingBindings);
     932               0 : }
     933                 : 
     934               0 : nsFrameConstructorState::nsFrameConstructorState(nsIPresShell* aPresShell,
     935                 :                                                  nsIFrame*     aFixedContainingBlock,
     936                 :                                                  nsIFrame*     aAbsoluteContainingBlock,
     937                 :                                                  nsIFrame*     aFloatContainingBlock)
     938               0 :   : mPresContext(aPresShell->GetPresContext()),
     939                 :     mPresShell(aPresShell),
     940               0 :     mFrameManager(aPresShell->FrameManager()),
     941                 : #ifdef MOZ_XUL    
     942                 :     mPopupItems(nsnull),
     943                 : #endif
     944                 :     mFixedItems(aFixedContainingBlock),
     945                 :     mAbsoluteItems(aAbsoluteContainingBlock),
     946                 :     mFloatedItems(aFloatContainingBlock),
     947                 :     // See PushAbsoluteContaningBlock below
     948                 :     mAdditionalStateBits(0),
     949                 :     mFixedPosIsAbsPos(aAbsoluteContainingBlock &&
     950                 :                       aAbsoluteContainingBlock->GetStyleDisplay()->
     951               0 :                         HasTransform()),
     952                 :     mHavePendingPopupgroup(false),
     953                 :     mCreatingExtraFrames(false),
     954                 :     mTreeMatchContext(true, nsRuleWalker::eRelevantLinkUnvisited,
     955                 :                       aPresShell->GetDocument()),
     956               0 :     mCurrentPendingBindingInsertionPoint(&mPendingBindings)
     957                 : {
     958                 : #ifdef MOZ_XUL
     959               0 :   nsIRootBox* rootBox = nsIRootBox::GetRootBox(aPresShell);
     960               0 :   if (rootBox) {
     961               0 :     mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
     962                 :   }
     963                 : #endif
     964               0 :   MOZ_COUNT_CTOR(nsFrameConstructorState);
     965               0 :   mFrameState = aPresShell->GetDocument()->GetLayoutHistoryState();
     966               0 :   PR_INIT_CLIST(&mPendingBindings);
     967               0 : }
     968                 : 
     969               0 : nsFrameConstructorState::~nsFrameConstructorState()
     970                 : {
     971                 :   // Frame order comparison functions only work properly when the placeholders
     972                 :   // have been inserted into the frame tree. So for example if we have a new float
     973                 :   // containing the placeholder for a new abs-pos frame, and we process the abs-pos
     974                 :   // insertion first, then we won't be able to find the right place to insert in
     975                 :   // in the abs-pos list. So put floats in first, because they can contain placeholders
     976                 :   // for abs-pos and fixed-pos items whose containing blocks are outside the floats.
     977                 :   // Then put abs-pos frames in, because they can contain placeholders for fixed-pos
     978                 :   // items whose containing block is outside the abs-pos frames. 
     979               0 :   MOZ_COUNT_DTOR(nsFrameConstructorState);
     980               0 :   ProcessFrameInsertions(mFloatedItems, nsIFrame::kFloatList);
     981               0 :   ProcessFrameInsertions(mAbsoluteItems, nsIFrame::kAbsoluteList);
     982               0 :   ProcessFrameInsertions(mFixedItems, nsIFrame::kFixedList);
     983                 : #ifdef MOZ_XUL
     984               0 :   ProcessFrameInsertions(mPopupItems, nsIFrame::kPopupList);
     985                 : #endif
     986               0 :   for (PRInt32 i = mGeneratedTextNodesWithInitializer.Count() - 1; i >= 0; --i) {
     987               0 :     mGeneratedTextNodesWithInitializer[i]->
     988               0 :       DeleteProperty(nsGkAtoms::genConInitializerProperty);
     989                 :   }
     990               0 :   if (!PR_CLIST_IS_EMPTY(&mPendingBindings)) {
     991               0 :     nsBindingManager* bindingManager = mPresShell->GetDocument()->BindingManager();
     992               0 :     do {
     993                 :       PendingBinding* pendingBinding =
     994               0 :         static_cast<PendingBinding*>(PR_NEXT_LINK(&mPendingBindings));
     995               0 :       PR_REMOVE_LINK(pendingBinding);
     996               0 :       bindingManager->AddToAttachedQueue(pendingBinding->mBinding);
     997               0 :       delete pendingBinding;
     998               0 :     } while (!PR_CLIST_IS_EMPTY(&mPendingBindings));
     999                 :   }
    1000               0 : }
    1001                 : 
    1002                 : static nsIFrame*
    1003               0 : AdjustAbsoluteContainingBlock(nsIFrame* aContainingBlockIn)
    1004                 : {
    1005               0 :   if (!aContainingBlockIn) {
    1006               0 :     return nsnull;
    1007                 :   }
    1008                 :   
    1009                 :   // Always use the container's first continuation. (Inline frames can have
    1010                 :   // non-fluid bidi continuations...)
    1011               0 :   return aContainingBlockIn->GetFirstContinuation();
    1012                 : }
    1013                 : 
    1014                 : void
    1015               0 : nsFrameConstructorState::PushAbsoluteContainingBlock(nsIFrame* aNewAbsoluteContainingBlock,
    1016                 :                                                      nsFrameConstructorSaveState& aSaveState)
    1017                 : {
    1018               0 :   aSaveState.mItems = &mAbsoluteItems;
    1019               0 :   aSaveState.mSavedItems = mAbsoluteItems;
    1020               0 :   aSaveState.mChildListID = nsIFrame::kAbsoluteList;
    1021               0 :   aSaveState.mState = this;
    1022                 : 
    1023                 :   /* Store whether we're wiring the abs-pos and fixed-pos lists together. */
    1024               0 :   aSaveState.mFixedPosIsAbsPos = &mFixedPosIsAbsPos;
    1025               0 :   aSaveState.mSavedFixedPosIsAbsPos = mFixedPosIsAbsPos;
    1026                 : 
    1027                 :   mAbsoluteItems = 
    1028               0 :     nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
    1029                 : 
    1030                 :   /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
    1031                 :    * we're a transformed element.
    1032                 :    */
    1033                 :   mFixedPosIsAbsPos = (aNewAbsoluteContainingBlock &&
    1034               0 :                        aNewAbsoluteContainingBlock->GetStyleDisplay()->HasTransform());
    1035                 : 
    1036               0 :   if (aNewAbsoluteContainingBlock) {
    1037               0 :     aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
    1038                 :   }
    1039               0 : }
    1040                 : 
    1041                 : void
    1042               0 : nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
    1043                 :                                                   nsFrameConstructorSaveState& aSaveState)
    1044                 : {
    1045               0 :   NS_PRECONDITION(!aNewFloatContainingBlock ||
    1046                 :                   aNewFloatContainingBlock->IsFloatContainingBlock(),
    1047                 :                   "Please push a real float containing block!");
    1048               0 :   aSaveState.mItems = &mFloatedItems;
    1049               0 :   aSaveState.mSavedItems = mFloatedItems;
    1050               0 :   aSaveState.mChildListID = nsIFrame::kFloatList;
    1051               0 :   aSaveState.mState = this;
    1052               0 :   mFloatedItems = nsAbsoluteItems(aNewFloatContainingBlock);
    1053               0 : }
    1054                 : 
    1055                 : nsIFrame*
    1056               0 : nsFrameConstructorState::GetGeometricParent(const nsStyleDisplay* aStyleDisplay,
    1057                 :                                             nsIFrame* aContentParentFrame)
    1058                 : {
    1059               0 :   NS_PRECONDITION(aStyleDisplay, "Must have display struct!");
    1060                 : 
    1061                 :   // If there is no container for a fixed, absolute, or floating root
    1062                 :   // frame, we will ignore the positioning.  This hack is originally
    1063                 :   // brought to you by the letter T: tables, since other roots don't
    1064                 :   // even call into this code.  See bug 178855.
    1065                 :   //
    1066                 :   // XXX Disabling positioning in this case is a hack.  If one was so inclined,
    1067                 :   // one could support this either by (1) inserting a dummy block between the
    1068                 :   // table and the canvas or (2) teaching the canvas how to reflow positioned
    1069                 :   // elements. (1) has the usual problems when multiple frames share the same
    1070                 :   // content (notice all the special cases in this file dealing with inner
    1071                 :   // tables and outer tables which share the same content). (2) requires some
    1072                 :   // work and possible factoring.
    1073                 :   //
    1074                 :   // XXXbz couldn't we just force position to "static" on roots and
    1075                 :   // float to "none"?  That's OK per CSS 2.1, as far as I can tell.
    1076                 :   
    1077               0 :   if (aStyleDisplay->IsFloating() && mFloatedItems.containingBlock) {
    1078               0 :     NS_ASSERTION(!aStyleDisplay->IsAbsolutelyPositioned(),
    1079                 :                  "Absolutely positioned _and_ floating?");
    1080               0 :     return mFloatedItems.containingBlock;
    1081                 :   }
    1082                 : 
    1083               0 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
    1084                 :       mAbsoluteItems.containingBlock) {
    1085               0 :     return mAbsoluteItems.containingBlock;
    1086                 :   }
    1087                 : 
    1088               0 :   if (aStyleDisplay->mPosition == NS_STYLE_POSITION_FIXED &&
    1089               0 :       GetFixedItems().containingBlock) {
    1090               0 :     return GetFixedItems().containingBlock;
    1091                 :   }
    1092                 : 
    1093               0 :   return aContentParentFrame;
    1094                 : }
    1095                 : 
    1096                 : nsresult
    1097               0 : nsFrameConstructorState::AddChild(nsIFrame* aNewFrame,
    1098                 :                                   nsFrameItems& aFrameItems,
    1099                 :                                   nsIContent* aContent,
    1100                 :                                   nsStyleContext* aStyleContext,
    1101                 :                                   nsIFrame* aParentFrame,
    1102                 :                                   bool aCanBePositioned,
    1103                 :                                   bool aCanBeFloated,
    1104                 :                                   bool aIsOutOfFlowPopup,
    1105                 :                                   bool aInsertAfter,
    1106                 :                                   nsIFrame* aInsertAfterFrame)
    1107                 : {
    1108               0 :   NS_PRECONDITION(!aNewFrame->GetNextSibling(), "Shouldn't happen");
    1109                 :   
    1110               0 :   const nsStyleDisplay* disp = aNewFrame->GetStyleDisplay();
    1111                 :   
    1112                 :   // The comments in GetGeometricParent regarding root table frames
    1113                 :   // all apply here, unfortunately.
    1114                 : 
    1115               0 :   bool needPlaceholder = false;
    1116                 :   nsFrameState placeholderType;
    1117               0 :   nsFrameItems* frameItems = &aFrameItems;
    1118                 : #ifdef MOZ_XUL
    1119               0 :   if (NS_UNLIKELY(aIsOutOfFlowPopup)) {
    1120               0 :       NS_ASSERTION(aNewFrame->GetParent() == mPopupItems.containingBlock,
    1121                 :                    "Popup whose parent is not the popup containing block?");
    1122               0 :       NS_ASSERTION(mPopupItems.containingBlock, "Must have a popup set frame!");
    1123               0 :       needPlaceholder = true;
    1124               0 :       frameItems = &mPopupItems;
    1125               0 :       placeholderType = PLACEHOLDER_FOR_POPUP;
    1126                 :   }
    1127                 :   else
    1128                 : #endif // MOZ_XUL
    1129               0 :   if (aCanBeFloated && disp->IsFloating() &&
    1130                 :       mFloatedItems.containingBlock) {
    1131               0 :     NS_ASSERTION(aNewFrame->GetParent() == mFloatedItems.containingBlock,
    1132                 :                  "Float whose parent is not the float containing block?");
    1133               0 :     needPlaceholder = true;
    1134               0 :     frameItems = &mFloatedItems;
    1135               0 :     placeholderType = PLACEHOLDER_FOR_FLOAT;
    1136                 :   }
    1137               0 :   else if (aCanBePositioned) {
    1138               0 :     if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE &&
    1139                 :         mAbsoluteItems.containingBlock) {
    1140               0 :       NS_ASSERTION(aNewFrame->GetParent() == mAbsoluteItems.containingBlock,
    1141                 :                    "Abs pos whose parent is not the abs pos containing block?");
    1142               0 :       needPlaceholder = true;
    1143               0 :       frameItems = &mAbsoluteItems;
    1144               0 :       placeholderType = PLACEHOLDER_FOR_ABSPOS;
    1145                 :     }
    1146               0 :     if (disp->mPosition == NS_STYLE_POSITION_FIXED &&
    1147               0 :         GetFixedItems().containingBlock) {
    1148               0 :       NS_ASSERTION(aNewFrame->GetParent() == GetFixedItems().containingBlock,
    1149                 :                    "Fixed pos whose parent is not the fixed pos containing block?");
    1150               0 :       needPlaceholder = true;
    1151               0 :       frameItems = &GetFixedItems();
    1152               0 :       placeholderType = PLACEHOLDER_FOR_FIXEDPOS;
    1153                 :     }
    1154                 :   }
    1155                 : 
    1156               0 :   if (needPlaceholder) {
    1157               0 :     NS_ASSERTION(frameItems != &aFrameItems,
    1158                 :                  "Putting frame in-flow _and_ want a placeholder?");
    1159                 :     nsIFrame* placeholderFrame;
    1160                 :     nsresult rv =
    1161                 :       nsCSSFrameConstructor::CreatePlaceholderFrameFor(mPresShell,
    1162                 :                                                        aContent,
    1163                 :                                                        aNewFrame,
    1164                 :                                                        aStyleContext,
    1165                 :                                                        aParentFrame,
    1166                 :                                                        nsnull,
    1167                 :                                                        placeholderType,
    1168               0 :                                                        &placeholderFrame);
    1169               0 :     if (NS_FAILED(rv)) {
    1170                 :       // Note that aNewFrame could be the top frame for a scrollframe setup,
    1171                 :       // hence already set as the primary frame.  So we have to clean up here.
    1172                 :       // But it shouldn't have any out-of-flow kids.
    1173                 :       // XXXbz Maybe add a utility function to assert that?
    1174               0 :       aNewFrame->Destroy();
    1175               0 :       return rv;
    1176                 :     }
    1177                 : 
    1178               0 :     placeholderFrame->AddStateBits(mAdditionalStateBits);
    1179                 :     // Add the placeholder frame to the flow
    1180               0 :     aFrameItems.AddChild(placeholderFrame);
    1181                 :   }
    1182                 : #ifdef DEBUG
    1183                 :   else {
    1184               0 :     NS_ASSERTION(aNewFrame->GetParent() == aParentFrame,
    1185                 :                  "In-flow frame has wrong parent");
    1186                 :   }
    1187                 : #endif
    1188                 : 
    1189               0 :   if (aInsertAfter) {
    1190               0 :     frameItems->InsertFrame(nsnull, aInsertAfterFrame, aNewFrame);
    1191                 :   } else {
    1192               0 :     frameItems->AddChild(aNewFrame);
    1193                 :   }
    1194                 :   
    1195               0 :   return NS_OK;
    1196                 : }
    1197                 : 
    1198                 : void
    1199               0 : nsFrameConstructorState::ProcessFrameInsertions(nsAbsoluteItems& aFrameItems,
    1200                 :                                                 ChildListID aChildListID)
    1201                 : {
    1202                 : #define NS_NONXUL_LIST_TEST (&aFrameItems == &mFloatedItems &&            \
    1203                 :                              aChildListID == nsIFrame::kFloatList)    ||  \
    1204                 :                             (&aFrameItems == &mAbsoluteItems &&           \
    1205                 :                              aChildListID == nsIFrame::kAbsoluteList) ||  \
    1206                 :                             (&aFrameItems == &mFixedItems &&              \
    1207                 :                              aChildListID == nsIFrame::kFixedList)
    1208                 : #ifdef MOZ_XUL
    1209               0 :   NS_PRECONDITION(NS_NONXUL_LIST_TEST ||
    1210                 :                   (&aFrameItems == &mPopupItems &&
    1211                 :                    aChildListID == nsIFrame::kPopupList), 
    1212                 :                   "Unexpected aFrameItems/aChildListID combination");
    1213                 : #else
    1214                 :   NS_PRECONDITION(NS_NONXUL_LIST_TEST,
    1215                 :                   "Unexpected aFrameItems/aChildListID combination");
    1216                 : #endif
    1217                 : 
    1218               0 :   if (aFrameItems.IsEmpty()) {
    1219               0 :     return;
    1220                 :   }
    1221                 :   
    1222               0 :   nsIFrame* containingBlock = aFrameItems.containingBlock;
    1223                 : 
    1224               0 :   NS_ASSERTION(containingBlock,
    1225                 :                "Child list without containing block?");
    1226                 :   
    1227                 :   // Insert the frames hanging out in aItems.  We can use SetInitialChildList()
    1228                 :   // if the containing block hasn't been reflowed yet (so NS_FRAME_FIRST_REFLOW
    1229                 :   // is set) and doesn't have any frames in the aChildListID child list yet.
    1230               0 :   const nsFrameList& childList = containingBlock->GetChildList(aChildListID);
    1231               0 :   nsresult rv = NS_OK;
    1232               0 :   if (childList.IsEmpty() &&
    1233               0 :       (containingBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1234                 :     // If we're injecting absolutely positioned frames, inject them on the
    1235                 :     // absolute containing block
    1236               0 :     if (aChildListID == containingBlock->GetAbsoluteListID()) {
    1237                 :       rv = containingBlock->GetAbsoluteContainingBlock()->
    1238               0 :            SetInitialChildList(containingBlock, aChildListID, aFrameItems);
    1239                 :     } else {
    1240               0 :       rv = containingBlock->SetInitialChildList(aChildListID, aFrameItems);
    1241                 :     }
    1242                 :   } else {
    1243                 :     // Note that whether the frame construction context is doing an append or
    1244                 :     // not is not helpful here, since it could be appending to some frame in
    1245                 :     // the middle of the document, which means we're not necessarily
    1246                 :     // appending to the children of the containing block.
    1247                 :     //
    1248                 :     // We need to make sure the 'append to the end of document' case is fast.
    1249                 :     // So first test the last child of the containing block
    1250               0 :     nsIFrame* lastChild = childList.LastChild();
    1251                 : 
    1252                 :     // CompareTreePosition uses placeholder hierarchy for out of flow frames,
    1253                 :     // so this will make out-of-flows respect the ordering of placeholders,
    1254                 :     // which is great because it takes care of anonymous content.
    1255               0 :     nsIFrame* firstNewFrame = aFrameItems.FirstChild();  
    1256               0 :     if (!lastChild ||
    1257               0 :         nsLayoutUtils::CompareTreePosition(lastChild, firstNewFrame, containingBlock) < 0) {
    1258                 :       // no lastChild, or lastChild comes before the new children, so just append
    1259               0 :       rv = mFrameManager->AppendFrames(containingBlock, aChildListID, aFrameItems);
    1260                 :     } else {
    1261                 :       // try the other children
    1262               0 :       nsIFrame* insertionPoint = nsnull;
    1263               0 :       for (nsIFrame* f = childList.FirstChild(); f != lastChild;
    1264                 :            f = f->GetNextSibling()) {
    1265                 :         PRInt32 compare =
    1266               0 :           nsLayoutUtils::CompareTreePosition(f, firstNewFrame, containingBlock);
    1267               0 :         if (compare > 0) {
    1268                 :           // f comes after the new children, so stop here and insert after
    1269                 :           // the previous frame
    1270               0 :           break;
    1271                 :         }
    1272               0 :         insertionPoint = f;
    1273                 :       }
    1274                 :       rv = mFrameManager->InsertFrames(containingBlock, aChildListID,
    1275               0 :                                        insertionPoint, aFrameItems);
    1276                 :     }
    1277                 :   }
    1278                 : 
    1279               0 :   NS_POSTCONDITION(aFrameItems.IsEmpty(), "How did that happen?");
    1280                 : 
    1281                 :   // XXXbz And if NS_FAILED(rv), what?  I guess we need to clean up the list
    1282                 :   // and deal with all the placeholders... but what if the placeholders aren't
    1283                 :   // in the document yet?  Could that happen?
    1284               0 :   NS_ASSERTION(NS_SUCCEEDED(rv), "Frames getting lost!");
    1285                 : }
    1286                 : 
    1287                 : 
    1288               0 : nsFrameConstructorSaveState::nsFrameConstructorSaveState()
    1289                 :   : mItems(nsnull),
    1290                 :     mFixedPosIsAbsPos(nsnull),
    1291                 :     mSavedItems(nsnull),
    1292                 :     mSavedFixedPosIsAbsPos(false),
    1293                 :     mChildListID(kPrincipalList),
    1294               0 :     mState(nsnull)
    1295                 : {
    1296               0 : }
    1297                 : 
    1298               0 : nsFrameConstructorSaveState::~nsFrameConstructorSaveState()
    1299                 : {
    1300                 :   // Restore the state
    1301               0 :   if (mItems) {
    1302               0 :     NS_ASSERTION(mState, "Can't have mItems set without having a state!");
    1303               0 :     mState->ProcessFrameInsertions(*mItems, mChildListID);
    1304               0 :     *mItems = mSavedItems;
    1305                 : #ifdef DEBUG
    1306                 :     // We've transferred the child list, so drop the pointer we held to it.
    1307                 :     // Note that this only matters for the assert in ~nsAbsoluteItems.
    1308               0 :     mSavedItems.Clear();
    1309                 : #endif
    1310                 :   }
    1311               0 :   if (mFixedPosIsAbsPos) {
    1312               0 :     *mFixedPosIsAbsPos = mSavedFixedPosIsAbsPos;
    1313                 :   }
    1314               0 : }
    1315                 : 
    1316                 : static 
    1317               0 : bool IsBorderCollapse(nsIFrame* aFrame)
    1318                 : {
    1319               0 :   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
    1320               0 :     if (nsGkAtoms::tableFrame == frame->GetType()) {
    1321               0 :       return ((nsTableFrame*)frame)->IsBorderCollapse();
    1322                 :     }
    1323                 :   }
    1324               0 :   NS_ASSERTION(false, "program error");
    1325               0 :   return false;
    1326                 : }
    1327                 : 
    1328                 : /**
    1329                 :  * Moves aFrameList from aOldParent to aNewParent.  This updates the parent
    1330                 :  * pointer of the frames in the list, and reparents their views as needed.
    1331                 :  * nsFrame::SetParent sets the NS_FRAME_HAS_VIEW bit on aNewParent and its
    1332                 :  * ancestors as needed. Then it sets the list as the initial child list
    1333                 :  * on aNewParent, unless aNewParent either already has kids or has been
    1334                 :  * reflowed; in that case it appends the new frames.  Note that this
    1335                 :  * method differs from ReparentFrames in that it doesn't change the kids'
    1336                 :  * style contexts.
    1337                 :  */
    1338                 : // XXXbz Since this is only used for {ib} splits, could we just copy the view
    1339                 : // bits from aOldParent to aNewParent and then use the
    1340                 : // nsFrameList::ApplySetParent?  That would still leave us doing two passes
    1341                 : // over the list, of course; if we really wanted to we could factor out the
    1342                 : // relevant part of ReparentFrameViewList, I suppose...  Or just get rid of
    1343                 : // views, which would make most of this function go away.
    1344                 : static void
    1345               0 : MoveChildrenTo(nsPresContext* aPresContext,
    1346                 :                nsIFrame* aOldParent,
    1347                 :                nsIFrame* aNewParent,
    1348                 :                nsFrameList& aFrameList)
    1349                 : {
    1350               0 :   bool sameGrandParent = aOldParent->GetParent() == aNewParent->GetParent();
    1351                 : 
    1352               0 :   if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) {
    1353                 :     // Move the frames into the new view
    1354                 :     nsContainerFrame::ReparentFrameViewList(aPresContext, aFrameList,
    1355               0 :                                             aOldParent, aNewParent);
    1356                 :   }
    1357                 : 
    1358               0 :   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
    1359               0 :     e.get()->SetParent(aNewParent);
    1360                 :   }
    1361                 : 
    1362               0 :   if (aNewParent->PrincipalChildList().IsEmpty() &&
    1363               0 :       (aNewParent->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    1364               0 :     aNewParent->SetInitialChildList(kPrincipalList, aFrameList);
    1365                 :   } else {
    1366               0 :     aNewParent->AppendFrames(kPrincipalList, aFrameList);
    1367                 :   }
    1368               0 : }
    1369                 : 
    1370                 : //----------------------------------------------------------------------
    1371                 : 
    1372               0 : nsCSSFrameConstructor::nsCSSFrameConstructor(nsIDocument *aDocument,
    1373                 :                                              nsIPresShell *aPresShell)
    1374                 :   : nsFrameManager(aPresShell)
    1375                 :   , mDocument(aDocument)
    1376                 :   , mRootElementFrame(nsnull)
    1377                 :   , mRootElementStyleFrame(nsnull)
    1378                 :   , mFixedContainingBlock(nsnull)
    1379                 :   , mDocElementContainingBlock(nsnull)
    1380                 :   , mGfxScrollFrame(nsnull)
    1381                 :   , mPageSequenceFrame(nsnull)
    1382                 :   , mUpdateCount(0)
    1383                 :   , mQuotesDirty(false)
    1384                 :   , mCountersDirty(false)
    1385                 :   , mIsDestroyingFrameTree(false)
    1386                 :   , mRebuildAllStyleData(false)
    1387                 :   , mHasRootAbsPosContainingBlock(false)
    1388                 :   , mObservingRefreshDriver(false)
    1389                 :   , mInStyleRefresh(false)
    1390                 :   , mHoverGeneration(0)
    1391                 :   , mRebuildAllExtraHint(nsChangeHint(0))
    1392                 :   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
    1393                 :                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT, this)
    1394                 :   , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
    1395               0 :                               ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT, this)
    1396                 : {
    1397                 :   // XXXbz this should be in Init() or something!
    1398               0 :   if (!mPendingRestyles.Init() || !mPendingAnimationRestyles.Init()) {
    1399                 :     // now what?
    1400                 :   }
    1401                 : 
    1402                 : #ifdef DEBUG
    1403                 :   static bool gFirstTime = true;
    1404               0 :   if (gFirstTime) {
    1405               0 :     gFirstTime = false;
    1406               0 :     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
    1407               0 :     if (flags) {
    1408               0 :       bool error = false;
    1409               0 :       for (;;) {
    1410               0 :         char* comma = PL_strchr(flags, ',');
    1411               0 :         if (comma)
    1412               0 :           *comma = '\0';
    1413                 : 
    1414               0 :         bool found = false;
    1415               0 :         FrameCtorDebugFlags* flag = gFlags;
    1416               0 :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1417               0 :         while (flag < limit) {
    1418               0 :           if (PL_strcasecmp(flag->name, flags) == 0) {
    1419               0 :             *(flag->on) = true;
    1420               0 :             printf("nsCSSFrameConstructor: setting %s debug flag on\n", flag->name);
    1421               0 :             found = true;
    1422               0 :             break;
    1423                 :           }
    1424               0 :           ++flag;
    1425                 :         }
    1426                 : 
    1427               0 :         if (! found)
    1428               0 :           error = true;
    1429                 : 
    1430               0 :         if (! comma)
    1431                 :           break;
    1432                 : 
    1433               0 :         *comma = ',';
    1434               0 :         flags = comma + 1;
    1435                 :       }
    1436                 : 
    1437               0 :       if (error) {
    1438               0 :         printf("Here are the available GECKO_FRAMECTOR_DEBUG_FLAGS:\n");
    1439               0 :         FrameCtorDebugFlags* flag = gFlags;
    1440               0 :         FrameCtorDebugFlags* limit = gFlags + NUM_DEBUG_FLAGS;
    1441               0 :         while (flag < limit) {
    1442               0 :           printf("  %s\n", flag->name);
    1443               0 :           ++flag;
    1444                 :         }
    1445               0 :         printf("Note: GECKO_FRAMECTOR_DEBUG_FLAGS is a comma separated list of flag\n");
    1446               0 :         printf("names (no whitespace)\n");
    1447                 :       }
    1448                 :     }
    1449                 :   }
    1450                 : #endif
    1451               0 : }
    1452                 : 
    1453               0 : nsIXBLService * nsCSSFrameConstructor::GetXBLService()
    1454                 : {
    1455               0 :   if (!gXBLService) {
    1456               0 :     nsresult rv = CallGetService("@mozilla.org/xbl;1", &gXBLService);
    1457               0 :     if (NS_FAILED(rv))
    1458               0 :       gXBLService = nsnull;
    1459                 :   }
    1460                 :   
    1461               0 :   return gXBLService;
    1462                 : }
    1463                 : 
    1464                 : void
    1465               0 : nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame)
    1466                 : {
    1467               0 :   NS_PRECONDITION(mUpdateCount != 0,
    1468                 :                   "Should be in an update while destroying frames");
    1469                 : 
    1470               0 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    1471               0 :     if (mQuoteList.DestroyNodesFor(aFrame))
    1472               0 :       QuotesDirty();
    1473                 :   }
    1474                 : 
    1475               0 :   if (mCounterManager.DestroyNodesFor(aFrame)) {
    1476                 :     // Technically we don't need to update anything if we destroyed only
    1477                 :     // USE nodes.  However, this is unlikely to happen in the real world
    1478                 :     // since USE nodes generally go along with INCREMENT nodes.
    1479               0 :     CountersDirty();
    1480                 :   }
    1481                 : 
    1482               0 :   nsFrameManager::NotifyDestroyingFrame(aFrame);
    1483               0 : }
    1484                 : 
    1485               0 : struct nsGenConInitializer {
    1486                 :   nsAutoPtr<nsGenConNode> mNode;
    1487                 :   nsGenConList*           mList;
    1488                 :   void (nsCSSFrameConstructor::*mDirtyAll)();
    1489                 :   
    1490               0 :   nsGenConInitializer(nsGenConNode* aNode, nsGenConList* aList,
    1491                 :                       void (nsCSSFrameConstructor::*aDirtyAll)())
    1492               0 :     : mNode(aNode), mList(aList), mDirtyAll(aDirtyAll) {}
    1493                 : };
    1494                 : 
    1495                 : static void
    1496               0 : DestroyGenConInitializer(void*    aFrame,
    1497                 :                          nsIAtom* aPropertyName,
    1498                 :                          void*    aPropertyValue,
    1499                 :                          void*    aDtorData)
    1500                 : {
    1501               0 :   delete static_cast<nsGenConInitializer*>(aPropertyValue);
    1502               0 : }
    1503                 : 
    1504                 : already_AddRefed<nsIContent>
    1505               0 : nsCSSFrameConstructor::CreateGenConTextNode(nsFrameConstructorState& aState,
    1506                 :                                             const nsString& aString,
    1507                 :                                             nsCOMPtr<nsIDOMCharacterData>* aText,
    1508                 :                                             nsGenConInitializer* aInitializer)
    1509                 : {
    1510               0 :   nsCOMPtr<nsIContent> content;
    1511               0 :   NS_NewTextNode(getter_AddRefs(content), mDocument->NodeInfoManager());
    1512               0 :   if (!content) {
    1513                 :     // XXX The quotes/counters code doesn't like the text pointer
    1514                 :     // being null in case of dynamic changes!
    1515               0 :     NS_ASSERTION(!aText, "this OOM case isn't handled very well");
    1516               0 :     return nsnull;
    1517                 :   }
    1518               0 :   content->SetText(aString, false);
    1519               0 :   if (aText) {
    1520               0 :     *aText = do_QueryInterface(content);
    1521                 :   }
    1522               0 :   if (aInitializer) {
    1523               0 :     content->SetProperty(nsGkAtoms::genConInitializerProperty, aInitializer,
    1524               0 :                          DestroyGenConInitializer);
    1525               0 :     aState.mGeneratedTextNodesWithInitializer.AppendObject(content);
    1526                 :   }
    1527               0 :   return content.forget();
    1528                 : }
    1529                 : 
    1530                 : already_AddRefed<nsIContent>
    1531               0 : nsCSSFrameConstructor::CreateGeneratedContent(nsFrameConstructorState& aState,
    1532                 :                                               nsIContent*     aParentContent,
    1533                 :                                               nsStyleContext* aStyleContext,
    1534                 :                                               PRUint32        aContentIndex)
    1535                 : {
    1536                 :   // Get the content value
    1537                 :   const nsStyleContentData &data =
    1538               0 :     aStyleContext->GetStyleContent()->ContentAt(aContentIndex);
    1539               0 :   nsStyleContentType type = data.mType;
    1540                 : 
    1541               0 :   if (eStyleContentType_Image == type) {
    1542               0 :     if (!data.mContent.mImage) {
    1543                 :       // CSS had something specified that couldn't be converted to an
    1544                 :       // image object
    1545               0 :       return nsnull;
    1546                 :     }
    1547                 :     
    1548                 :     // Create an image content object and pass it the image request.
    1549                 :     // XXX Check if it's an image type we can handle...
    1550                 : 
    1551               0 :     nsCOMPtr<nsINodeInfo> nodeInfo;
    1552                 :     nodeInfo = mDocument->NodeInfoManager()->
    1553                 :       GetNodeInfo(nsGkAtoms::mozgeneratedcontentimage, nsnull,
    1554               0 :                   kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
    1555                 : 
    1556               0 :     nsCOMPtr<nsIContent> content;
    1557               0 :     NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo.forget(),
    1558               0 :                              data.mContent.mImage);
    1559               0 :     return content.forget();
    1560                 :   }
    1561                 : 
    1562               0 :   switch (type) {
    1563                 :   case eStyleContentType_String:
    1564                 :     return CreateGenConTextNode(aState,
    1565               0 :                                 nsDependentString(data.mContent.mString),
    1566               0 :                                 nsnull, nsnull);
    1567                 : 
    1568                 :   case eStyleContentType_Attr:
    1569                 :     {
    1570               0 :       nsCOMPtr<nsIAtom> attrName;
    1571               0 :       PRInt32 attrNameSpace = kNameSpaceID_None;
    1572               0 :       nsAutoString contentString(data.mContent.mString);
    1573                 :       
    1574               0 :       PRInt32 barIndex = contentString.FindChar('|'); // CSS namespace delimiter
    1575               0 :       if (-1 != barIndex) {
    1576               0 :         nsAutoString  nameSpaceVal;
    1577               0 :         contentString.Left(nameSpaceVal, barIndex);
    1578                 :         PRInt32 error;
    1579               0 :         attrNameSpace = nameSpaceVal.ToInteger(&error, 10);
    1580               0 :         contentString.Cut(0, barIndex + 1);
    1581               0 :         if (contentString.Length()) {
    1582               0 :           if (mDocument->IsHTML() && aParentContent->IsHTML()) {
    1583               0 :             ToLowerCase(contentString);
    1584                 :           }
    1585               0 :           attrName = do_GetAtom(contentString);
    1586                 :         }
    1587                 :       }
    1588                 :       else {
    1589               0 :         if (mDocument->IsHTML() && aParentContent->IsHTML()) {
    1590               0 :           ToLowerCase(contentString);
    1591                 :         }
    1592               0 :         attrName = do_GetAtom(contentString);
    1593                 :       }
    1594                 : 
    1595               0 :       if (!attrName) {
    1596               0 :         return nsnull;
    1597                 :       }
    1598                 : 
    1599               0 :       nsCOMPtr<nsIContent> content;
    1600                 :       NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1601               0 :                              attrNameSpace, attrName, getter_AddRefs(content));
    1602               0 :       return content.forget();
    1603                 :     }
    1604                 : 
    1605                 :   case eStyleContentType_Counter:
    1606                 :   case eStyleContentType_Counters:
    1607                 :     {
    1608               0 :       nsCSSValue::Array* counters = data.mContent.mCounters;
    1609                 :       nsCounterList* counterList = mCounterManager.CounterListFor(
    1610               0 :           nsDependentString(counters->Item(0).GetStringBufferValue()));
    1611               0 :       if (!counterList)
    1612               0 :         return nsnull;
    1613                 : 
    1614                 :       nsCounterUseNode* node =
    1615                 :         new nsCounterUseNode(counters, aContentIndex,
    1616               0 :                              type == eStyleContentType_Counters);
    1617                 : 
    1618                 :       nsGenConInitializer* initializer =
    1619                 :         new nsGenConInitializer(node, counterList,
    1620               0 :                                 &nsCSSFrameConstructor::CountersDirty);
    1621               0 :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1622               0 :                                   initializer);
    1623                 :     }
    1624                 : 
    1625                 :   case eStyleContentType_Image:
    1626               0 :     NS_NOTREACHED("handled by if above");
    1627               0 :     return nsnull;
    1628                 : 
    1629                 :   case eStyleContentType_OpenQuote:
    1630                 :   case eStyleContentType_CloseQuote:
    1631                 :   case eStyleContentType_NoOpenQuote:
    1632                 :   case eStyleContentType_NoCloseQuote:
    1633                 :     {
    1634                 :       nsQuoteNode* node =
    1635               0 :         new nsQuoteNode(type, aContentIndex);
    1636                 : 
    1637                 :       nsGenConInitializer* initializer =
    1638                 :         new nsGenConInitializer(node, &mQuoteList,
    1639               0 :                                 &nsCSSFrameConstructor::QuotesDirty);
    1640               0 :       return CreateGenConTextNode(aState, EmptyString(), &node->mText,
    1641               0 :                                   initializer);
    1642                 :     }
    1643                 :   
    1644                 :   case eStyleContentType_AltContent:
    1645                 :     {
    1646                 :       // Use the "alt" attribute; if that fails and the node is an HTML
    1647                 :       // <input>, try the value attribute and then fall back to some default
    1648                 :       // localized text we have.
    1649                 :       // XXX what if the 'alt' attribute is added later, how will we
    1650                 :       // detect that and do the right thing here?
    1651               0 :       if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
    1652               0 :         nsCOMPtr<nsIContent> content;
    1653                 :         NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1654               0 :                                kNameSpaceID_None, nsGkAtoms::alt, getter_AddRefs(content));
    1655               0 :         return content.forget();
    1656                 :       }
    1657                 : 
    1658               0 :       if (aParentContent->IsHTML() &&
    1659               0 :           aParentContent->NodeInfo()->Equals(nsGkAtoms::input)) {
    1660               0 :         if (aParentContent->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    1661               0 :           nsCOMPtr<nsIContent> content;
    1662                 :           NS_NewAttributeContent(mDocument->NodeInfoManager(),
    1663               0 :                                  kNameSpaceID_None, nsGkAtoms::value, getter_AddRefs(content));
    1664               0 :           return content.forget();
    1665                 :         }
    1666                 : 
    1667               0 :         nsXPIDLString temp;
    1668                 :         nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    1669               0 :                                            "Submit", temp);
    1670               0 :         return CreateGenConTextNode(aState, temp, nsnull, nsnull);
    1671                 :       }
    1672                 : 
    1673               0 :       break;
    1674                 :     }
    1675                 :   } // switch
    1676                 : 
    1677               0 :   return nsnull;
    1678                 : }
    1679                 : 
    1680                 : /*
    1681                 :  * aParentFrame - the frame that should be the parent of the generated
    1682                 :  *   content.  This is the frame for the corresponding content node,
    1683                 :  *   which must not be a leaf frame.
    1684                 :  * 
    1685                 :  * Any items created are added to aItems.
    1686                 :  * 
    1687                 :  * We create an XML element (tag _moz_generated_content_before or
    1688                 :  * _moz_generated_content_after) representing the pseudoelement. We
    1689                 :  * create a DOM node for each 'content' item and make those nodes the
    1690                 :  * children of the XML element. Then we create a frame subtree for
    1691                 :  * the XML element as if it were a regular child of
    1692                 :  * aParentFrame/aParentContent, giving the XML element the ::before or
    1693                 :  * ::after style.
    1694                 :  */
    1695                 : void
    1696               0 : nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
    1697                 :                                                   nsIFrame*        aParentFrame,
    1698                 :                                                   nsIContent*      aParentContent,
    1699                 :                                                   nsStyleContext*  aStyleContext,
    1700                 :                                                   nsCSSPseudoElements::Type aPseudoElement,
    1701                 :                                                   FrameConstructionItemList& aItems)
    1702                 : {
    1703                 :   // XXXbz is this ever true?
    1704               0 :   if (!aParentContent->IsElement()) {
    1705               0 :     NS_ERROR("Bogus generated content parent");
    1706               0 :     return;
    1707                 :   }
    1708                 : 
    1709               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    1710                 : 
    1711                 :   // Probe for the existence of the pseudo-element
    1712               0 :   nsRefPtr<nsStyleContext> pseudoStyleContext;
    1713                 :   pseudoStyleContext =
    1714                 :     styleSet->ProbePseudoElementStyle(aParentContent->AsElement(),
    1715                 :                                       aPseudoElement,
    1716                 :                                       aStyleContext,
    1717               0 :                                       aState.mTreeMatchContext);
    1718               0 :   if (!pseudoStyleContext)
    1719                 :     return;
    1720                 :   // |ProbePseudoStyleFor| checked the 'display' property and the
    1721                 :   // |ContentCount()| of the 'content' property for us.
    1722               0 :   nsCOMPtr<nsINodeInfo> nodeInfo;
    1723                 :   nsIAtom* elemName = aPseudoElement == nsCSSPseudoElements::ePseudo_before ?
    1724               0 :     nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
    1725                 :   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nsnull,
    1726                 :                                                        kNameSpaceID_None,
    1727               0 :                                                        nsIDOMNode::ELEMENT_NODE);
    1728               0 :   nsCOMPtr<nsIContent> container;
    1729               0 :   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
    1730               0 :   if (NS_FAILED(rv))
    1731                 :     return;
    1732               0 :   container->SetNativeAnonymous();
    1733                 : 
    1734               0 :   rv = container->BindToTree(mDocument, aParentContent, aParentContent, true);
    1735               0 :   if (NS_FAILED(rv)) {
    1736               0 :     container->UnbindFromTree();
    1737                 :     return;
    1738                 :   }
    1739                 : 
    1740               0 :   PRUint32 contentCount = pseudoStyleContext->GetStyleContent()->ContentCount();
    1741               0 :   for (PRUint32 contentIndex = 0; contentIndex < contentCount; contentIndex++) {
    1742                 :     nsCOMPtr<nsIContent> content =
    1743                 :       CreateGeneratedContent(aState, aParentContent, pseudoStyleContext,
    1744               0 :                              contentIndex);
    1745               0 :     if (content) {
    1746               0 :       container->AppendChildTo(content, false);
    1747                 :     }
    1748                 :   }
    1749                 : 
    1750                 :   AddFrameConstructionItemsInternal(aState, container, aParentFrame, elemName,
    1751                 :                                     kNameSpaceID_None, true,
    1752                 :                                     pseudoStyleContext,
    1753               0 :                                     ITEM_IS_GENERATED_CONTENT, aItems);
    1754                 : }
    1755                 :     
    1756                 : /****************************************************
    1757                 :  **  BEGIN TABLE SECTION
    1758                 :  ****************************************************/
    1759                 : 
    1760                 : // The term pseudo frame is being used instead of anonymous frame, since anonymous
    1761                 : // frame has been used elsewhere to refer to frames that have generated content
    1762                 : 
    1763                 : // Return whether the given frame is a table pseudo-frame.  Note that
    1764                 : // cell-content and table-outer frames have pseudo-types, but are always
    1765                 : // created, even for non-anonymous cells and tables respectively.  So for those
    1766                 : // we have to examine the cell or table frame to see whether it's a pseudo
    1767                 : // frame.  In particular, a lone table caption will have an outer table as its
    1768                 : // parent, but will also trigger construction of an empty inner table, which
    1769                 : // will be the one we can examine to see whether the outer was a pseudo-frame.
    1770                 : static bool
    1771               0 : IsTablePseudo(nsIFrame* aFrame)
    1772                 : {
    1773               0 :   nsIAtom* pseudoType = aFrame->GetStyleContext()->GetPseudo();
    1774                 :   return pseudoType &&
    1775                 :     (pseudoType == nsCSSAnonBoxes::table ||
    1776                 :      pseudoType == nsCSSAnonBoxes::inlineTable ||
    1777                 :      pseudoType == nsCSSAnonBoxes::tableColGroup ||
    1778                 :      pseudoType == nsCSSAnonBoxes::tableRowGroup ||
    1779                 :      pseudoType == nsCSSAnonBoxes::tableRow ||
    1780                 :      pseudoType == nsCSSAnonBoxes::tableCell ||
    1781                 :      (pseudoType == nsCSSAnonBoxes::cellContent &&
    1782               0 :       aFrame->GetParent()->GetStyleContext()->GetPseudo() ==
    1783                 :         nsCSSAnonBoxes::tableCell) ||
    1784                 :      (pseudoType == nsCSSAnonBoxes::tableOuter &&
    1785               0 :       (aFrame->GetFirstPrincipalChild()->GetStyleContext()->GetPseudo() ==
    1786                 :          nsCSSAnonBoxes::table ||
    1787               0 :        aFrame->GetFirstPrincipalChild()->GetStyleContext()->GetPseudo() ==
    1788               0 :          nsCSSAnonBoxes::inlineTable)));
    1789                 : }
    1790                 : 
    1791                 : /* static */
    1792                 : nsCSSFrameConstructor::ParentType
    1793               0 : nsCSSFrameConstructor::GetParentType(nsIAtom* aFrameType)
    1794                 : {
    1795               0 :   if (aFrameType == nsGkAtoms::tableFrame) {
    1796               0 :     return eTypeTable;
    1797                 :   }
    1798               0 :   if (aFrameType == nsGkAtoms::tableRowGroupFrame) {
    1799               0 :     return eTypeRowGroup;
    1800                 :   }
    1801               0 :   if (aFrameType == nsGkAtoms::tableRowFrame) {
    1802               0 :     return eTypeRow;
    1803                 :   }
    1804               0 :   if (aFrameType == nsGkAtoms::tableColGroupFrame) {
    1805               0 :     return eTypeColGroup;
    1806                 :   }
    1807                 : 
    1808               0 :   return eTypeBlock;
    1809                 : }
    1810                 :            
    1811                 : static nsIFrame*
    1812               0 : AdjustCaptionParentFrame(nsIFrame* aParentFrame) 
    1813                 : {
    1814               0 :   if (nsGkAtoms::tableFrame == aParentFrame->GetType()) {
    1815               0 :     return aParentFrame->GetParent();;
    1816                 :   }
    1817               0 :   return aParentFrame;
    1818                 : }
    1819                 :  
    1820                 : /**
    1821                 :  * If the parent frame is a |tableFrame| and the child is a
    1822                 :  * |captionFrame|, then we want to insert the frames beneath the
    1823                 :  * |tableFrame|'s parent frame. Returns |true| if the parent frame
    1824                 :  * needed to be fixed up.
    1825                 :  */
    1826                 : static bool
    1827               0 : GetCaptionAdjustedParent(nsIFrame*        aParentFrame,
    1828                 :                          const nsIFrame*  aChildFrame,
    1829                 :                          nsIFrame**       aAdjParentFrame)
    1830                 : {
    1831               0 :   *aAdjParentFrame = aParentFrame;
    1832               0 :   bool haveCaption = false;
    1833                 : 
    1834               0 :   if (nsGkAtoms::tableCaptionFrame == aChildFrame->GetType()) {
    1835               0 :     haveCaption = true;
    1836               0 :     *aAdjParentFrame = AdjustCaptionParentFrame(aParentFrame);
    1837                 :   }
    1838               0 :   return haveCaption;
    1839                 : }
    1840                 : 
    1841                 : void
    1842               0 : nsCSSFrameConstructor::AdjustParentFrame(nsIFrame* &                  aParentFrame,
    1843                 :                                          const FrameConstructionData* aFCData,
    1844                 :                                          nsStyleContext*              aStyleContext)
    1845                 : {
    1846               0 :   NS_PRECONDITION(aStyleContext, "Must have child's style context");
    1847               0 :   NS_PRECONDITION(aFCData, "Must have frame construction data");
    1848                 : 
    1849               0 :   bool tablePart = ((aFCData->mBits & FCDATA_IS_TABLE_PART) != 0);
    1850                 : 
    1851               0 :   if (tablePart && aStyleContext->GetStyleDisplay()->mDisplay ==
    1852                 :       NS_STYLE_DISPLAY_TABLE_CAPTION) {
    1853               0 :     aParentFrame = AdjustCaptionParentFrame(aParentFrame);
    1854                 :   }
    1855               0 : }
    1856                 : 
    1857                 : // Pull all the captions present in aItems out  into aCaptions
    1858                 : static void
    1859               0 : PullOutCaptionFrames(nsFrameItems& aItems, nsFrameItems& aCaptions)
    1860                 : {
    1861               0 :   nsIFrame *child = aItems.FirstChild();
    1862               0 :   while (child) {
    1863               0 :     nsIFrame *nextSibling = child->GetNextSibling();
    1864               0 :     if (nsGkAtoms::tableCaptionFrame == child->GetType()) {
    1865               0 :       aItems.RemoveFrame(child);
    1866               0 :       aCaptions.AddChild(child);
    1867                 :     }
    1868               0 :     child = nextSibling;
    1869                 :   }
    1870               0 : }
    1871                 : 
    1872                 : 
    1873                 : // Construct the outer, inner table frames and the children frames for the table. 
    1874                 : // XXX Page break frames for pseudo table frames are not constructed to avoid the risk
    1875                 : // associated with revising the pseudo frame mechanism. The long term solution
    1876                 : // of having frames handle page-break-before/after will solve the problem. 
    1877                 : nsresult
    1878               0 : nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
    1879                 :                                       FrameConstructionItem&   aItem,
    1880                 :                                       nsIFrame*                aParentFrame,
    1881                 :                                       const nsStyleDisplay*    aDisplay,
    1882                 :                                       nsFrameItems&            aFrameItems,
    1883                 :                                       nsIFrame**               aNewFrame)
    1884                 : {
    1885               0 :   NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE ||
    1886                 :                   aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE,
    1887                 :                   "Unexpected call");
    1888                 : 
    1889               0 :   nsIContent* const content = aItem.mContent;
    1890               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    1891               0 :   const PRUint32 nameSpaceID = aItem.mNameSpaceID;
    1892                 : 
    1893               0 :   nsresult rv = NS_OK;
    1894                 : 
    1895                 :   // create the pseudo SC for the outer table as a child of the inner SC
    1896               0 :   nsRefPtr<nsStyleContext> outerStyleContext;
    1897                 :   outerStyleContext = mPresShell->StyleSet()->
    1898               0 :     ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableOuter, styleContext);
    1899                 : 
    1900                 :   // Create the outer table frame which holds the caption and inner table frame
    1901                 :   nsIFrame* newFrame;
    1902               0 :   if (kNameSpaceID_MathML == nameSpaceID)
    1903               0 :     newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerStyleContext);
    1904                 :   else
    1905               0 :     newFrame = NS_NewTableOuterFrame(mPresShell, outerStyleContext);
    1906                 : 
    1907                 :   nsIFrame* geometricParent =
    1908                 :     aState.GetGeometricParent(outerStyleContext->GetStyleDisplay(),
    1909               0 :                               aParentFrame);
    1910                 : 
    1911                 :   // Init the table outer frame
    1912               0 :   InitAndRestoreFrame(aState, content, geometricParent, nsnull, newFrame);  
    1913                 : 
    1914                 :   // Create the inner table frame
    1915                 :   nsIFrame* innerFrame;
    1916               0 :   if (kNameSpaceID_MathML == nameSpaceID)
    1917               0 :     innerFrame = NS_NewMathMLmtableFrame(mPresShell, styleContext);
    1918                 :   else
    1919               0 :     innerFrame = NS_NewTableFrame(mPresShell, styleContext);
    1920                 : 
    1921               0 :   if (!innerFrame) {
    1922               0 :     newFrame->Destroy();
    1923               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1924                 :   }
    1925                 : 
    1926               0 :   InitAndRestoreFrame(aState, content, newFrame, nsnull, innerFrame);
    1927                 : 
    1928                 :   // Put the newly created frames into the right child list
    1929               0 :   SetInitialSingleChild(newFrame, innerFrame);
    1930                 : 
    1931                 :   rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
    1932               0 :                        aParentFrame);
    1933               0 :   if (NS_FAILED(rv)) {
    1934               0 :     return rv;
    1935                 :   }
    1936                 : 
    1937               0 :   if (!mRootElementFrame) {
    1938                 :     // The frame we're constructing will be the root element frame.
    1939                 :     // Set mRootElementFrame before processing children.
    1940               0 :     mRootElementFrame = newFrame;
    1941                 :   }
    1942                 : 
    1943               0 :   nsFrameItems childItems;
    1944                 : 
    1945                 :   // Process children
    1946               0 :   nsFrameConstructorSaveState absoluteSaveState;
    1947               0 :   const nsStyleDisplay* display = outerStyleContext->GetStyleDisplay();
    1948                 : 
    1949                 :   // Mark the table frame as an absolute container if needed
    1950               0 :   if (display->IsPositioned()) {
    1951               0 :     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
    1952                 :   }
    1953               0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    1954                 :     rv = ConstructFramesFromItemList(aState, aItem.mChildItems,
    1955               0 :                                      innerFrame, childItems);
    1956                 :   } else {
    1957                 :     rv = ProcessChildren(aState, content, styleContext, innerFrame,
    1958               0 :                          true, childItems, false, aItem.mPendingBinding);
    1959                 :   }
    1960                 :   // XXXbz what about cleaning up?
    1961               0 :   if (NS_FAILED(rv)) return rv;
    1962                 : 
    1963               0 :   nsFrameItems captionItems;
    1964               0 :   PullOutCaptionFrames(childItems, captionItems);
    1965                 : 
    1966                 :   // Set the inner table frame's initial primary list 
    1967               0 :   innerFrame->SetInitialChildList(kPrincipalList, childItems);
    1968                 : 
    1969                 :   // Set the outer table frame's secondary childlist lists
    1970               0 :   if (captionItems.NotEmpty()) {
    1971               0 :     newFrame->SetInitialChildList(nsIFrame::kCaptionList, captionItems);
    1972                 :   }
    1973                 : 
    1974               0 :   *aNewFrame = newFrame;
    1975               0 :   return rv;
    1976                 : }
    1977                 : 
    1978                 : nsresult
    1979               0 : nsCSSFrameConstructor::ConstructTableRow(nsFrameConstructorState& aState,
    1980                 :                                          FrameConstructionItem&   aItem,
    1981                 :                                          nsIFrame*                aParentFrame,
    1982                 :                                          const nsStyleDisplay*    aDisplay,
    1983                 :                                          nsFrameItems&            aFrameItems,
    1984                 :                                          nsIFrame**               aNewFrame)
    1985                 : {
    1986               0 :   NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_ROW,
    1987                 :                   "Unexpected call");
    1988               0 :   nsIContent* const content = aItem.mContent;
    1989               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    1990               0 :   const PRUint32 nameSpaceID = aItem.mNameSpaceID;
    1991                 : 
    1992                 :   nsIFrame* newFrame;
    1993               0 :   if (kNameSpaceID_MathML == nameSpaceID)
    1994               0 :     newFrame = NS_NewMathMLmtrFrame(mPresShell, styleContext);
    1995                 :   else
    1996               0 :     newFrame = NS_NewTableRowFrame(mPresShell, styleContext);
    1997                 : 
    1998               0 :   if (NS_UNLIKELY(!newFrame)) {
    1999               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2000                 :   }
    2001               0 :   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
    2002                 : 
    2003               0 :   nsFrameItems childItems;
    2004                 :   nsresult rv;
    2005               0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2006                 :     rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
    2007               0 :                                      childItems);
    2008                 :   } else {
    2009                 :     rv = ProcessChildren(aState, content, styleContext, newFrame,
    2010               0 :                          true, childItems, false, aItem.mPendingBinding);
    2011                 :   }
    2012               0 :   if (NS_FAILED(rv)) return rv;
    2013                 : 
    2014               0 :   newFrame->SetInitialChildList(kPrincipalList, childItems);
    2015               0 :   aFrameItems.AddChild(newFrame);
    2016               0 :   *aNewFrame = newFrame;
    2017                 : 
    2018               0 :   return NS_OK;
    2019                 : }
    2020                 : 
    2021                 : nsresult
    2022               0 : nsCSSFrameConstructor::ConstructTableCol(nsFrameConstructorState& aState,
    2023                 :                                          FrameConstructionItem&   aItem,
    2024                 :                                          nsIFrame*                aParentFrame,
    2025                 :                                          const nsStyleDisplay*    aStyleDisplay,
    2026                 :                                          nsFrameItems&            aFrameItems,
    2027                 :                                          nsIFrame**               aNewFrame)
    2028                 : {
    2029               0 :   nsIContent* const content = aItem.mContent;
    2030               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2031                 : 
    2032               0 :   nsTableColFrame* colFrame = NS_NewTableColFrame(mPresShell, styleContext);
    2033               0 :   if (NS_UNLIKELY(!colFrame)) {
    2034               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2035                 :   }
    2036               0 :   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, colFrame);
    2037                 : 
    2038               0 :   NS_ASSERTION(colFrame->GetStyleContext() == styleContext,
    2039                 :                "Unexpected style context");
    2040                 : 
    2041               0 :   aFrameItems.AddChild(colFrame);
    2042               0 :   *aNewFrame = colFrame;
    2043                 : 
    2044                 :   // construct additional col frames if the col frame has a span > 1
    2045               0 :   PRInt32 span = colFrame->GetSpan();
    2046               0 :   for (PRInt32 spanX = 1; spanX < span; spanX++) {
    2047               0 :     nsTableColFrame* newCol = NS_NewTableColFrame(mPresShell, styleContext);
    2048               0 :     if (NS_UNLIKELY(!newCol)) {
    2049               0 :       return NS_ERROR_OUT_OF_MEMORY;
    2050                 :     }
    2051                 :     InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newCol,
    2052               0 :                         false);
    2053               0 :     aFrameItems.LastChild()->SetNextContinuation(newCol);
    2054               0 :     newCol->SetPrevContinuation(aFrameItems.LastChild());
    2055               0 :     aFrameItems.AddChild(newCol);
    2056               0 :     newCol->SetColType(eColAnonymousCol);
    2057                 :   }
    2058                 : 
    2059               0 :   return NS_OK;
    2060                 : }
    2061                 : 
    2062                 : nsresult
    2063               0 : nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState,
    2064                 :                                           FrameConstructionItem&   aItem,
    2065                 :                                           nsIFrame*                aParentFrame,
    2066                 :                                           const nsStyleDisplay*    aDisplay,
    2067                 :                                           nsFrameItems&            aFrameItems,
    2068                 :                                           nsIFrame**               aNewFrame)
    2069                 : {
    2070               0 :   NS_PRECONDITION(aDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL,
    2071                 :                   "Unexpected call");
    2072                 : 
    2073               0 :   nsIContent* const content = aItem.mContent;
    2074               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2075               0 :   const PRUint32 nameSpaceID = aItem.mNameSpaceID;
    2076                 : 
    2077               0 :   bool borderCollapse = IsBorderCollapse(aParentFrame);
    2078                 :   nsIFrame* newFrame;
    2079                 :   // <mtable> is border separate in mathml.css and the MathML code doesn't implement
    2080                 :   // border collapse. For those users who style <mtable> with border collapse,
    2081                 :   // give them the default non-MathML table frames that understand border collapse.
    2082                 :   // This won't break us because MathML table frames are all subclasses of the default
    2083                 :   // table code, and so we can freely mix <mtable> with <mtr> or <tr>, <mtd> or <td>.
    2084                 :   // What will happen is just that non-MathML frames won't understand MathML attributes
    2085                 :   // and will therefore miss the special handling that the MathML code does.
    2086               0 :   if (kNameSpaceID_MathML == nameSpaceID && !borderCollapse)
    2087               0 :     newFrame = NS_NewMathMLmtdFrame(mPresShell, styleContext);
    2088                 :   else
    2089                 :     // Warning: If you change this and add a wrapper frame around table cell
    2090                 :     // frames, make sure Bug 368554 doesn't regress!
    2091                 :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.    
    2092               0 :     newFrame = NS_NewTableCellFrame(mPresShell, styleContext, borderCollapse);
    2093                 : 
    2094               0 :   if (NS_UNLIKELY(!newFrame)) {
    2095               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2096                 :   }
    2097                 : 
    2098                 :   // Initialize the table cell frame
    2099               0 :   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
    2100                 :   
    2101                 :   // Resolve pseudo style and initialize the body cell frame
    2102               0 :   nsRefPtr<nsStyleContext> innerPseudoStyle;
    2103                 :   innerPseudoStyle = mPresShell->StyleSet()->
    2104               0 :     ResolveAnonymousBoxStyle(nsCSSAnonBoxes::cellContent, styleContext);
    2105                 : 
    2106                 :   // Create a block frame that will format the cell's content
    2107                 :   bool isBlock;
    2108                 :   nsIFrame* cellInnerFrame;
    2109               0 :   if (kNameSpaceID_MathML == nameSpaceID) {
    2110               0 :     cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
    2111               0 :     isBlock = false;
    2112                 :   } else {
    2113               0 :     cellInnerFrame = NS_NewBlockFormattingContext(mPresShell, innerPseudoStyle);
    2114               0 :     isBlock = true;
    2115                 :   }
    2116                 : 
    2117               0 :   if (NS_UNLIKELY(!cellInnerFrame)) {
    2118               0 :     newFrame->Destroy();
    2119               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2120                 :   }
    2121                 : 
    2122               0 :   InitAndRestoreFrame(aState, content, newFrame, nsnull, cellInnerFrame);
    2123                 : 
    2124               0 :   nsFrameItems childItems;
    2125                 :   nsresult rv;
    2126               0 :   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
    2127                 :     // Need to push ourselves as a float containing block.
    2128                 :     // XXXbz it might be nice to work on getting the parent
    2129                 :     // FrameConstructionItem down into ProcessChildren and just making use of
    2130                 :     // the push there, but that's a bit of work.
    2131               0 :     nsFrameConstructorSaveState floatSaveState;
    2132               0 :     if (!isBlock) { /* MathML case */
    2133               0 :       aState.PushFloatContainingBlock(nsnull, floatSaveState);
    2134                 :     } else {
    2135               0 :       aState.PushFloatContainingBlock(cellInnerFrame, floatSaveState);
    2136                 :     }
    2137                 : 
    2138                 :     rv = ConstructFramesFromItemList(aState, aItem.mChildItems, cellInnerFrame,
    2139               0 :                                      childItems);
    2140                 :   } else {
    2141                 :     // Process the child content
    2142                 :     rv = ProcessChildren(aState, content, styleContext, cellInnerFrame,
    2143               0 :                          true, childItems, isBlock, aItem.mPendingBinding);
    2144                 :   }
    2145                 :   
    2146               0 :   if (NS_FAILED(rv)) {
    2147                 :     // Clean up
    2148                 :     // XXXbz kids of this stuff need to be cleaned up too!
    2149               0 :     cellInnerFrame->Destroy();
    2150               0 :     newFrame->Destroy();
    2151               0 :     return rv;
    2152                 :   }
    2153                 : 
    2154               0 :   cellInnerFrame->SetInitialChildList(kPrincipalList, childItems);
    2155               0 :   SetInitialSingleChild(newFrame, cellInnerFrame);
    2156               0 :   aFrameItems.AddChild(newFrame);
    2157               0 :   *aNewFrame = newFrame;
    2158                 : 
    2159               0 :   return NS_OK;
    2160                 : }
    2161                 : 
    2162                 : static inline bool 
    2163               0 : NeedFrameFor(const nsFrameConstructorState& aState,
    2164                 :              nsIFrame*   aParentFrame,
    2165                 :              nsIContent* aChildContent) 
    2166                 : {
    2167                 :   // XXX the GetContent() != aChildContent check is needed due to bug 135040.
    2168                 :   // Remove it once that's fixed.
    2169               0 :   NS_PRECONDITION(!aChildContent->GetPrimaryFrame() ||
    2170                 :                   aState.mCreatingExtraFrames ||
    2171                 :                   aChildContent->GetPrimaryFrame()->GetContent() != aChildContent,
    2172                 :                   "Why did we get called?");
    2173                 : 
    2174                 :   // don't create a whitespace frame if aParentFrame doesn't want it.
    2175                 :   // always create frames for children in generated content. counter(),
    2176                 :   // quotes, and attr() content can easily change dynamically and we don't
    2177                 :   // want to be reconstructing frames. It's not even clear that these
    2178                 :   // should be considered ignorable just because they evaluate to
    2179                 :   // whitespace.
    2180                 : 
    2181                 :   // We could handle all this in CreateNeededTablePseudos or some other place
    2182                 :   // after we build our frame construction items, but that would involve
    2183                 :   // creating frame construction items for whitespace kids of
    2184                 :   // eExcludesIgnorableWhitespace frames, where we know we'll be dropping them
    2185                 :   // all anyway, and involve an extra walk down the frame construction item
    2186                 :   // list.
    2187               0 :   if (!aParentFrame->IsFrameOfType(nsIFrame::eExcludesIgnorableWhitespace) ||
    2188               0 :       aParentFrame->IsGeneratedContentFrame() ||
    2189               0 :       !aChildContent->IsNodeOfType(nsINode::eTEXT)) {
    2190               0 :     return true;
    2191                 :   }
    2192                 : 
    2193                 :   aChildContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
    2194               0 :                           NS_REFRAME_IF_WHITESPACE);
    2195               0 :   return !aChildContent->TextIsOnlyWhitespace();
    2196                 : }
    2197                 : 
    2198                 : /***********************************************
    2199                 :  * END TABLE SECTION
    2200                 :  ***********************************************/
    2201                 : 
    2202               0 : static bool CheckOverflow(nsPresContext* aPresContext,
    2203                 :                             const nsStyleDisplay* aDisplay)
    2204                 : {
    2205               0 :   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
    2206               0 :     return false;
    2207                 : 
    2208               0 :   if (aDisplay->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
    2209                 :     aPresContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_HIDDEN,
    2210               0 :                                               NS_STYLE_OVERFLOW_HIDDEN);
    2211                 :   else
    2212                 :     aPresContext->SetViewportOverflowOverride(aDisplay->mOverflowX,
    2213               0 :                                               aDisplay->mOverflowY);
    2214               0 :   return true;
    2215                 : }
    2216                 : 
    2217                 : /**
    2218                 :  * This checks the root element and the HTML BODY, if any, for an "overflow" property
    2219                 :  * that should be applied to the viewport. If one is found then we return the
    2220                 :  * element that we took the overflow from (which should then be treated as
    2221                 :  * "overflow:visible"), and we store the overflow style in the prescontext.
    2222                 :  * @return if scroll was propagated from some content node, the content node it
    2223                 :  *         was propagated from.
    2224                 :  */
    2225                 : nsIContent*
    2226               0 : nsCSSFrameConstructor::PropagateScrollToViewport()
    2227                 : {
    2228                 :   // Set default
    2229               0 :   nsPresContext* presContext = mPresShell->GetPresContext();
    2230                 :   presContext->SetViewportOverflowOverride(NS_STYLE_OVERFLOW_AUTO,
    2231               0 :                                            NS_STYLE_OVERFLOW_AUTO);
    2232                 : 
    2233                 :   // We never mess with the viewport scroll state
    2234                 :   // when printing or in print preview
    2235               0 :   if (presContext->IsPaginated()) {
    2236               0 :     return nsnull;
    2237                 :   }
    2238                 : 
    2239               0 :   Element* docElement = mDocument->GetRootElement();
    2240                 : 
    2241                 :   // Check the style on the document root element
    2242               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    2243               0 :   nsRefPtr<nsStyleContext> rootStyle;
    2244               0 :   rootStyle = styleSet->ResolveStyleFor(docElement, nsnull);
    2245               0 :   if (!rootStyle) {
    2246               0 :     return nsnull;
    2247                 :   }
    2248               0 :   if (CheckOverflow(presContext, rootStyle->GetStyleDisplay())) {
    2249                 :     // tell caller we stole the overflow style from the root element
    2250               0 :     return docElement;
    2251                 :   }
    2252                 :   
    2253                 :   // Don't look in the BODY for non-HTML documents or HTML documents
    2254                 :   // with non-HTML roots
    2255                 :   // XXX this should be earlier; we shouldn't even look at the document root
    2256                 :   // for non-HTML documents. Fix this once we support explicit CSS styling
    2257                 :   // of the viewport
    2258                 :   // XXX what about XHTML?
    2259               0 :   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
    2260               0 :   if (!htmlDoc || !docElement->IsHTML()) {
    2261               0 :     return nsnull;
    2262                 :   }
    2263                 :   
    2264               0 :   nsCOMPtr<nsIDOMHTMLElement> body;
    2265               0 :   htmlDoc->GetBody(getter_AddRefs(body));
    2266               0 :   nsCOMPtr<nsIContent> bodyElement = do_QueryInterface(body);
    2267                 :   
    2268               0 :   if (!bodyElement ||
    2269               0 :       !bodyElement->NodeInfo()->Equals(nsGkAtoms::body)) {
    2270                 :     // The body is not a <body> tag, it's a <frameset>.
    2271               0 :     return nsnull;
    2272                 :   }
    2273                 : 
    2274               0 :   nsRefPtr<nsStyleContext> bodyStyle;
    2275               0 :   bodyStyle = styleSet->ResolveStyleFor(bodyElement->AsElement(), rootStyle);
    2276               0 :   if (!bodyStyle) {
    2277               0 :     return nsnull;
    2278                 :   }
    2279                 : 
    2280               0 :   if (CheckOverflow(presContext, bodyStyle->GetStyleDisplay())) {
    2281                 :     // tell caller we stole the overflow style from the body element
    2282               0 :     return bodyElement;
    2283                 :   }
    2284                 : 
    2285               0 :   return nsnull;
    2286                 : }
    2287                 : 
    2288                 : nsresult
    2289               0 : nsCSSFrameConstructor::ConstructDocElementFrame(Element*                 aDocElement,
    2290                 :                                                 nsILayoutHistoryState*   aFrameState,
    2291                 :                                                 nsIFrame**               aNewFrame)
    2292                 : {
    2293               0 :   NS_PRECONDITION(mFixedContainingBlock,
    2294                 :                   "No viewport?  Someone forgot to call ConstructRootFrame!");
    2295               0 :   NS_PRECONDITION(mFixedContainingBlock == GetRootFrame(),
    2296                 :                   "Unexpected mFixedContainingBlock");
    2297               0 :   NS_PRECONDITION(!mDocElementContainingBlock,
    2298                 :                   "Shouldn't have a doc element containing block here");
    2299                 : 
    2300               0 :   *aNewFrame = nsnull;
    2301                 : 
    2302                 :   // Make sure to call PropagateScrollToViewport before
    2303                 :   // SetUpDocElementContainingBlock, since it sets up our scrollbar state
    2304                 :   // properly.
    2305                 : #ifdef DEBUG
    2306                 :   nsIContent* propagatedScrollFrom =
    2307                 : #endif
    2308               0 :     PropagateScrollToViewport();
    2309                 : 
    2310               0 :   SetUpDocElementContainingBlock(aDocElement);
    2311                 : 
    2312               0 :   NS_ASSERTION(mDocElementContainingBlock, "Should have parent by now");
    2313                 : 
    2314                 :   nsFrameConstructorState state(mPresShell, mFixedContainingBlock, nsnull,
    2315               0 :                                 nsnull, aFrameState);
    2316                 :   // Initialize the ancestor filter with null for now; we'll push
    2317                 :   // aDocElement once we finish resolving style for it.
    2318               0 :   state.mTreeMatchContext.mAncestorFilter.Init(nsnull);
    2319                 : 
    2320                 :   // XXXbz why, exactly?
    2321               0 :   if (!mTempFrameTreeState)
    2322               0 :     state.mPresShell->CaptureHistoryState(getter_AddRefs(mTempFrameTreeState));
    2323                 : 
    2324                 :   // Make sure that we'll handle restyles for this document element in
    2325                 :   // the future.  We need this, because the document element might
    2326                 :   // have stale restyle bits from a previous frame constructor for
    2327                 :   // this document.  Unlike in AddFrameConstructionItems, it's safe to
    2328                 :   // unset all element restyle flags, since we don't have any
    2329                 :   // siblings.
    2330               0 :   aDocElement->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
    2331                 : 
    2332                 :   // --------- CREATE AREA OR BOX FRAME -------
    2333               0 :   nsRefPtr<nsStyleContext> styleContext;
    2334                 :   styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
    2335               0 :                                                          nsnull);
    2336                 : 
    2337               0 :   const nsStyleDisplay* display = styleContext->GetStyleDisplay();
    2338                 : 
    2339                 :   // Ensure that our XBL bindings are installed.
    2340               0 :   if (display->mBinding) {
    2341                 :     // Get the XBL loader.
    2342                 :     nsresult rv;
    2343                 :     bool resolveStyle;
    2344                 :     
    2345               0 :     nsIXBLService * xblService = GetXBLService();
    2346               0 :     if (!xblService)
    2347               0 :       return NS_ERROR_FAILURE;
    2348                 : 
    2349               0 :     nsRefPtr<nsXBLBinding> binding;
    2350                 :     rv = xblService->LoadBindings(aDocElement, display->mBinding->GetURI(),
    2351               0 :                                   display->mBinding->mOriginPrincipal,
    2352                 :                                   false, getter_AddRefs(binding),
    2353               0 :                                   &resolveStyle);
    2354               0 :     if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
    2355               0 :       return NS_OK; // Binding will load asynchronously.
    2356                 : 
    2357               0 :     if (binding) {
    2358                 :       // For backwards compat, keep firing the root's constructor
    2359                 :       // after all of its kids' constructors.  So tell the binding
    2360                 :       // manager about it right now.
    2361               0 :       mDocument->BindingManager()->AddToAttachedQueue(binding);
    2362                 :     }
    2363                 : 
    2364               0 :     if (resolveStyle) {
    2365                 :       styleContext = mPresShell->StyleSet()->ResolveStyleFor(aDocElement,
    2366               0 :                                                              nsnull);
    2367               0 :       display = styleContext->GetStyleDisplay();
    2368                 :     }
    2369                 :   }
    2370                 : 
    2371                 :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2372                 : 
    2373                 : #ifdef DEBUG
    2374               0 :   NS_ASSERTION(!display->IsScrollableOverflow() || 
    2375                 :                state.mPresContext->IsPaginated() ||
    2376                 :                propagatedScrollFrom == aDocElement,
    2377                 :                "Scrollbars should have been propagated to the viewport");
    2378                 : #endif
    2379                 : 
    2380               0 :   if (NS_UNLIKELY(display->mDisplay == NS_STYLE_DISPLAY_NONE)) {
    2381               0 :     SetUndisplayedContent(aDocElement, styleContext);
    2382               0 :     return NS_OK;
    2383                 :   }
    2384                 : 
    2385                 :   AncestorFilter::AutoAncestorPusher
    2386               0 :     ancestorPusher(true, state.mTreeMatchContext.mAncestorFilter, aDocElement);
    2387                 : 
    2388                 :   // Make sure to start any background image loads for the root element now.
    2389               0 :   styleContext->StartBackgroundImageLoads();
    2390                 : 
    2391               0 :   nsFrameConstructorSaveState absoluteSaveState;
    2392               0 :   if (mHasRootAbsPosContainingBlock) {
    2393                 :     // Push the absolute containing block now so we can absolutely position
    2394                 :     // the root element
    2395                 :     state.PushAbsoluteContainingBlock(mDocElementContainingBlock,
    2396               0 :                                       absoluteSaveState);
    2397                 :   }
    2398                 : 
    2399                 :   nsresult rv;
    2400                 : 
    2401                 :   // The rules from CSS 2.1, section 9.2.4, have already been applied
    2402                 :   // by the style system, so we can assume that display->mDisplay is
    2403                 :   // either NONE, BLOCK, or TABLE.
    2404                 : 
    2405                 :   // contentFrame is the primary frame for the root element. *aNewFrame
    2406                 :   // is the frame that will be the child of the initial containing block.
    2407                 :   // These are usually the same frame but they can be different, in
    2408                 :   // particular if the root frame is positioned, in which case
    2409                 :   // contentFrame is the out-of-flow frame and *aNewFrame is the
    2410                 :   // placeholder.
    2411                 :   nsIFrame* contentFrame;
    2412               0 :   bool processChildren = false;
    2413                 : 
    2414                 :   // Check whether we need to build a XUL box or SVG root frame
    2415                 : #ifdef MOZ_XUL
    2416               0 :   if (aDocElement->IsXUL()) {
    2417               0 :     contentFrame = NS_NewDocElementBoxFrame(mPresShell, styleContext);
    2418               0 :     if (NS_UNLIKELY(!contentFrame)) {
    2419               0 :       return NS_ERROR_OUT_OF_MEMORY;
    2420                 :     }
    2421                 :     InitAndRestoreFrame(state, aDocElement, mDocElementContainingBlock, nsnull,
    2422               0 :                         contentFrame);
    2423               0 :     *aNewFrame = contentFrame;
    2424               0 :     processChildren = true;
    2425                 :   }
    2426                 :   else
    2427                 : #endif
    2428               0 :   if (aDocElement->IsSVG()) {
    2429               0 :     if (aDocElement->Tag() == nsGkAtoms::svg) {
    2430               0 :       contentFrame = NS_NewSVGOuterSVGFrame(mPresShell, styleContext);
    2431               0 :       if (NS_UNLIKELY(!contentFrame)) {
    2432               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2433                 :       }
    2434                 :       InitAndRestoreFrame(state, aDocElement,
    2435                 :                           state.GetGeometricParent(display,
    2436                 :                                                    mDocElementContainingBlock),
    2437               0 :                           nsnull, contentFrame);
    2438                 : 
    2439                 :       // AddChild takes care of transforming the frame tree for fixed-pos
    2440                 :       // or abs-pos situations
    2441               0 :       nsFrameItems frameItems;
    2442                 :       rv = state.AddChild(contentFrame, frameItems, aDocElement,
    2443               0 :                           styleContext, mDocElementContainingBlock);
    2444               0 :       if (NS_FAILED(rv) || frameItems.IsEmpty()) {
    2445               0 :         return rv;
    2446                 :       }
    2447               0 :       *aNewFrame = frameItems.FirstChild();
    2448               0 :       processChildren = true;
    2449                 :     } else {
    2450               0 :       return NS_ERROR_FAILURE;
    2451                 :     }
    2452                 :   } else {
    2453               0 :     bool docElemIsTable = (display->mDisplay == NS_STYLE_DISPLAY_TABLE);
    2454               0 :     if (docElemIsTable) {
    2455                 :       // We're going to call the right function ourselves, so no need to give a
    2456                 :       // function to this FrameConstructionData.
    2457                 : 
    2458                 :       // XXXbz on the other hand, if we converted this whole function to
    2459                 :       // FrameConstructionData/Item, then we'd need the right function
    2460                 :       // here... but would probably be able to get away with less code in this
    2461                 :       // function in general.
    2462                 :       // Use a null PendingBinding, since our binding is not in fact pending.
    2463                 :       static const FrameConstructionData rootTableData = FCDATA_DECL(0, nsnull);
    2464               0 :       nsRefPtr<nsStyleContext> extraRef(styleContext);
    2465                 :       FrameConstructionItem item(&rootTableData, aDocElement,
    2466                 :                                  aDocElement->Tag(), kNameSpaceID_None,
    2467               0 :                                  nsnull, extraRef.forget(), true);
    2468                 : 
    2469               0 :       nsFrameItems frameItems;
    2470                 :       // if the document is a table then just populate it.
    2471                 :       rv = ConstructTable(state, item, mDocElementContainingBlock,
    2472                 :                           styleContext->GetStyleDisplay(),
    2473               0 :                           frameItems, &contentFrame);
    2474               0 :       if (NS_FAILED(rv))
    2475               0 :         return rv;
    2476               0 :       if (!contentFrame || frameItems.IsEmpty())
    2477               0 :         return NS_ERROR_FAILURE;
    2478               0 :       *aNewFrame = frameItems.FirstChild();
    2479               0 :       NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2480                 :     } else {
    2481               0 :       contentFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
    2482               0 :       if (!contentFrame)
    2483               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2484               0 :       nsFrameItems frameItems;
    2485                 :       // Use a null PendingBinding, since our binding is not in fact pending.
    2486                 :       rv = ConstructBlock(state, display, aDocElement,
    2487                 :                           state.GetGeometricParent(display,
    2488                 :                                                    mDocElementContainingBlock),
    2489                 :                           mDocElementContainingBlock, styleContext,
    2490               0 :                           &contentFrame, frameItems, display->IsPositioned(),
    2491               0 :                           nsnull);
    2492               0 :       if (NS_FAILED(rv) || frameItems.IsEmpty())
    2493               0 :         return rv;
    2494               0 :       *aNewFrame = frameItems.FirstChild();
    2495               0 :       NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
    2496                 :     }
    2497                 :   }
    2498                 : 
    2499                 :   // set the primary frame
    2500               0 :   aDocElement->SetPrimaryFrame(contentFrame);
    2501                 : 
    2502               0 :   NS_ASSERTION(processChildren ? !mRootElementFrame :
    2503                 :                  mRootElementFrame == contentFrame,
    2504                 :                "unexpected mRootElementFrame");
    2505               0 :   mRootElementFrame = contentFrame;
    2506                 : 
    2507                 :   // Figure out which frame has the main style for the document element,
    2508                 :   // assigning it to mRootElementStyleFrame.
    2509                 :   // Backgrounds should be propagated from that frame to the viewport.
    2510               0 :   mRootElementStyleFrame = contentFrame->GetParentStyleContextFrame();
    2511                 :   bool isChild = mRootElementStyleFrame &&
    2512               0 :                  mRootElementStyleFrame->GetParent() == contentFrame;
    2513               0 :   if (!isChild) {
    2514               0 :     mRootElementStyleFrame = mRootElementFrame;
    2515                 :   }
    2516                 : 
    2517               0 :   if (processChildren) {
    2518                 :     // Still need to process the child content
    2519               0 :     nsFrameItems childItems;
    2520                 : 
    2521               0 :     NS_ASSERTION(!nsLayoutUtils::GetAsBlock(contentFrame),
    2522                 :                  "Only XUL and SVG frames should reach here");
    2523                 :     // Use a null PendingBinding, since our binding is not in fact pending.
    2524                 :     ProcessChildren(state, aDocElement, styleContext, contentFrame, true,
    2525               0 :                     childItems, false, nsnull);
    2526                 : 
    2527                 :     // Set the initial child lists
    2528               0 :     contentFrame->SetInitialChildList(kPrincipalList, childItems);
    2529                 :   }
    2530                 : 
    2531               0 :   SetInitialSingleChild(mDocElementContainingBlock, *aNewFrame);
    2532                 : 
    2533               0 :   return NS_OK;
    2534                 : }
    2535                 : 
    2536                 : 
    2537                 : nsresult
    2538               0 : nsCSSFrameConstructor::ConstructRootFrame(nsIFrame** aNewFrame)
    2539                 : {
    2540               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    2541               0 :   NS_PRECONDITION(aNewFrame, "null out param");
    2542                 : 
    2543               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    2544                 : 
    2545                 :   // Set up our style rule observer.
    2546                 :   // XXXbz wouldn't this make more sense as part of presshell init?
    2547                 :   {
    2548               0 :     styleSet->SetBindingManager(mDocument->BindingManager());
    2549                 :   }
    2550                 : 
    2551                 :   // --------- BUILD VIEWPORT -----------
    2552               0 :   nsIFrame*                 viewportFrame = nsnull;
    2553               0 :   nsRefPtr<nsStyleContext> viewportPseudoStyle;
    2554                 : 
    2555                 :   viewportPseudoStyle =
    2556               0 :     styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewport, nsnull);
    2557                 : 
    2558               0 :   viewportFrame = NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
    2559                 : 
    2560                 :   // XXXbz do we _have_ to pass a null content pointer to that frame?
    2561                 :   // Would it really kill us to pass in the root element or something?
    2562                 :   // What would that break?
    2563               0 :   viewportFrame->Init(nsnull, nsnull, nsnull);
    2564                 : 
    2565                 :   // Bind the viewport frame to the root view
    2566               0 :   nsIView* rootView = mPresShell->GetViewManager()->GetRootView();
    2567               0 :   viewportFrame->SetView(rootView);
    2568                 : 
    2569                 :   nsContainerFrame::SyncFrameViewProperties(mPresShell->GetPresContext(), viewportFrame,
    2570               0 :                                             viewportPseudoStyle, rootView);
    2571                 :   nsContainerFrame::SyncWindowProperties(mPresShell->GetPresContext(), viewportFrame,
    2572               0 :                                          rootView);
    2573                 : 
    2574                 :   // The viewport is the containing block for 'fixed' elements
    2575               0 :   mFixedContainingBlock = viewportFrame;
    2576                 :   // Make it an absolute container for fixed-pos elements
    2577               0 :   mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
    2578                 : 
    2579               0 :   *aNewFrame = viewportFrame;
    2580               0 :   return NS_OK;
    2581                 : }
    2582                 : 
    2583                 : nsresult
    2584               0 : nsCSSFrameConstructor::SetUpDocElementContainingBlock(nsIContent* aDocElement)
    2585                 : {
    2586               0 :   NS_PRECONDITION(aDocElement, "No element?");
    2587               0 :   NS_PRECONDITION(!aDocElement->GetParent(), "Not root content?");
    2588               0 :   NS_PRECONDITION(aDocElement->GetCurrentDoc(), "Not in a document?");
    2589               0 :   NS_PRECONDITION(aDocElement->GetCurrentDoc()->GetRootElement() ==
    2590                 :                   aDocElement, "Not the root of the document?");
    2591                 : 
    2592                 :   /*
    2593                 :     how the root frame hierarchy should look
    2594                 : 
    2595                 :   Galley presentation, non-XUL, with scrolling (i.e. not a frameset):
    2596                 :   
    2597                 :       ViewportFrame [fixed-cb]
    2598                 :         nsHTMLScrollFrame
    2599                 :           nsCanvasFrame [abs-cb]
    2600                 :             root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2601                 :                                 nsTableOuterFrame, nsPlaceholderFrame)
    2602                 : 
    2603                 :   Galley presentation, non-XUL, without scrolling (i.e. a frameset):
    2604                 :   
    2605                 :       ViewportFrame [fixed-cb]
    2606                 :         nsCanvasFrame [abs-cb]
    2607                 :           root element frame (nsBlockFrame)
    2608                 : 
    2609                 :   Galley presentation, XUL
    2610                 :   
    2611                 :       ViewportFrame [fixed-cb]
    2612                 :         nsRootBoxFrame
    2613                 :           root element frame (nsDocElementBoxFrame)
    2614                 : 
    2615                 :   Print presentation, non-XUL
    2616                 : 
    2617                 :       ViewportFrame
    2618                 :         nsSimplePageSequenceFrame
    2619                 :           nsPageFrame [fixed-cb]
    2620                 :             nsPageContentFrame
    2621                 :               nsCanvasFrame [abs-cb]
    2622                 :                 root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2623                 :                                     nsTableOuterFrame, nsPlaceholderFrame)
    2624                 : 
    2625                 :   Print-preview presentation, non-XUL
    2626                 : 
    2627                 :       ViewportFrame
    2628                 :         nsHTMLScrollFrame
    2629                 :           nsSimplePageSequenceFrame
    2630                 :             nsPageFrame [fixed-cb]
    2631                 :               nsPageContentFrame
    2632                 :                 nsCanvasFrame [abs-cb]
    2633                 :                   root element frame (nsBlockFrame, nsSVGOuterSVGFrame,
    2634                 :                                       nsTableOuterFrame, nsPlaceholderFrame)
    2635                 : 
    2636                 :   Print/print preview of XUL is not supported.
    2637                 :   [fixed-cb]: the default containing block for fixed-pos content
    2638                 :   [abs-cb]: the default containing block for abs-pos content
    2639                 :  
    2640                 :   Meaning of nsCSSFrameConstructor fields:
    2641                 :     mRootElementFrame is "root element frame".  This is the primary frame for
    2642                 :       the root element.
    2643                 :     mDocElementContainingBlock is the parent of mRootElementFrame
    2644                 :       (i.e. nsCanvasFrame or nsRootBoxFrame)
    2645                 :     mFixedContainingBlock is the [fixed-cb]
    2646                 :     mGfxScrollFrame is the nsHTMLScrollFrame mentioned above, or null if there isn't one
    2647                 :     mPageSequenceFrame is the nsSimplePageSequenceFrame, or null if there isn't one
    2648                 :   */
    2649                 : 
    2650                 :   // --------- CREATE ROOT FRAME -------
    2651                 : 
    2652                 : 
    2653                 :   // Create the root frame. The document element's frame is a child of the
    2654                 :   // root frame.
    2655                 :   //
    2656                 :   // The root frame serves two purposes:
    2657                 :   // - reserves space for any margins needed for the document element's frame
    2658                 :   // - renders the document element's background. This ensures the background covers
    2659                 :   //   the entire canvas as specified by the CSS2 spec
    2660                 : 
    2661               0 :   nsPresContext* presContext = mPresShell->GetPresContext();
    2662               0 :   bool isPaginated = presContext->IsRootPaginatedDocument();
    2663               0 :   nsIFrame* viewportFrame = mFixedContainingBlock;
    2664               0 :   nsStyleContext* viewportPseudoStyle = viewportFrame->GetStyleContext();
    2665                 : 
    2666               0 :   nsIFrame* rootFrame = nsnull;
    2667                 :   nsIAtom* rootPseudo;
    2668                 :         
    2669               0 :   if (!isPaginated) {
    2670                 : #ifdef MOZ_XUL
    2671               0 :     if (aDocElement->IsXUL())
    2672                 :     {
    2673                 :       // pass a temporary stylecontext, the correct one will be set later
    2674               0 :       rootFrame = NS_NewRootBoxFrame(mPresShell, viewportPseudoStyle);
    2675                 :     } else
    2676                 : #endif
    2677                 :     {
    2678                 :       // pass a temporary stylecontext, the correct one will be set later
    2679               0 :       rootFrame = NS_NewCanvasFrame(mPresShell, viewportPseudoStyle);
    2680               0 :       mHasRootAbsPosContainingBlock = true;
    2681                 :     }
    2682                 : 
    2683               0 :     rootPseudo = nsCSSAnonBoxes::canvas;
    2684               0 :     mDocElementContainingBlock = rootFrame;
    2685                 :   } else {
    2686                 :     // Create a page sequence frame
    2687               0 :     rootFrame = NS_NewSimplePageSequenceFrame(mPresShell, viewportPseudoStyle);
    2688               0 :     mPageSequenceFrame = rootFrame;
    2689               0 :     rootPseudo = nsCSSAnonBoxes::pageSequence;
    2690                 :   }
    2691                 : 
    2692                 : 
    2693                 :   // --------- IF SCROLLABLE WRAP IN SCROLLFRAME --------
    2694                 : 
    2695                 :   // If the device supports scrolling (e.g., in galley mode on the screen and
    2696                 :   // for print-preview, but not when printing), then create a scroll frame that
    2697                 :   // will act as the scrolling mechanism for the viewport. 
    2698                 :   // XXX Do we even need a viewport when printing to a printer?
    2699                 : 
    2700                 :   // As long as the docshell doesn't prohibit it, and the device supports
    2701                 :   // it, create a scroll frame that will act as the scolling mechanism for
    2702                 :   // the viewport.
    2703                 :   //
    2704                 :   // Threre are three possible values stored in the docshell:
    2705                 :   //  1) nsIScrollable::Scrollbar_Never = no scrollbars
    2706                 :   //  2) nsIScrollable::Scrollbar_Auto = scrollbars appear if needed
    2707                 :   //  3) nsIScrollable::Scrollbar_Always = scrollbars always
    2708                 :   // Only need to create a scroll frame/view for cases 2 and 3.
    2709                 : 
    2710               0 :   bool isHTML = aDocElement->IsHTML();
    2711               0 :   bool isXUL = false;
    2712                 : 
    2713               0 :   if (!isHTML) {
    2714               0 :     isXUL = aDocElement->IsXUL();
    2715                 :   }
    2716                 : 
    2717                 :   // Never create scrollbars for XUL documents
    2718               0 :   bool isScrollable = !isXUL;
    2719                 : 
    2720                 :   // Never create scrollbars for frameset documents.
    2721               0 :   if (isHTML) {
    2722               0 :     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
    2723               0 :     if (htmlDoc && htmlDoc->GetIsFrameset())
    2724               0 :       isScrollable = false;
    2725                 :   }
    2726                 : 
    2727               0 :   if (isPaginated) {
    2728               0 :     isScrollable = presContext->HasPaginatedScrolling();
    2729                 :   }
    2730                 : 
    2731                 :   // We no longer need to do overflow propagation here. It's taken care of
    2732                 :   // when we construct frames for the element whose overflow might be
    2733                 :   // propagated
    2734               0 :   NS_ASSERTION(!isScrollable || !isXUL,
    2735                 :                "XUL documents should never be scrollable - see above");
    2736                 : 
    2737               0 :   nsIFrame* newFrame = rootFrame;
    2738               0 :   nsRefPtr<nsStyleContext> rootPseudoStyle;
    2739                 :   // we must create a state because if the scrollbars are GFX it needs the 
    2740                 :   // state to build the scrollbar frames.
    2741               0 :   nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
    2742                 : 
    2743                 :   // Start off with the viewport as parent; we'll adjust it as needed.
    2744               0 :   nsIFrame* parentFrame = viewportFrame;
    2745                 : 
    2746               0 :   nsStyleSet* styleSet = mPresShell->StyleSet();
    2747                 :   // If paginated, make sure we don't put scrollbars in
    2748               0 :   if (!isScrollable) {
    2749                 :     rootPseudoStyle = styleSet->ResolveAnonymousBoxStyle(rootPseudo,
    2750               0 :                                                          viewportPseudoStyle);
    2751                 :   } else {
    2752               0 :       if (rootPseudo == nsCSSAnonBoxes::canvas) {
    2753               0 :         rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
    2754                 :       } else {
    2755               0 :         NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
    2756                 :                      "Unknown root pseudo");
    2757               0 :         rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
    2758                 :       }
    2759                 : 
    2760                 :       // Build the frame. We give it the content we are wrapping which is the
    2761                 :       // document element, the root frame, the parent view port frame, and we
    2762                 :       // should get back the new frame and the scrollable view if one was
    2763                 :       // created.
    2764                 : 
    2765                 :       // resolve a context for the scrollframe
    2766               0 :       nsRefPtr<nsStyleContext>  styleContext;
    2767                 :       styleContext = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewportScroll,
    2768               0 :                                                         viewportPseudoStyle);
    2769                 : 
    2770                 :       // Note that the viewport scrollframe is always built with
    2771                 :       // overflow:auto style. This forces the scroll frame to create
    2772                 :       // anonymous content for both scrollbars. This is necessary even
    2773                 :       // if the HTML or BODY elements are overriding the viewport
    2774                 :       // scroll style to 'hidden' --- dynamic style changes might put
    2775                 :       // scrollbars back on the viewport and we don't want to have to
    2776                 :       // reframe the viewport to create the scrollbar content.
    2777               0 :       newFrame = nsnull;
    2778                 :       rootPseudoStyle = BeginBuildingScrollFrame( state,
    2779                 :                                                   aDocElement,
    2780                 :                                                   styleContext,
    2781                 :                                                   viewportFrame,
    2782                 :                                                   rootPseudo,
    2783                 :                                                   true,
    2784               0 :                                                   newFrame);
    2785               0 :       parentFrame = newFrame;
    2786               0 :       mGfxScrollFrame = newFrame;
    2787                 :   }
    2788                 :   
    2789               0 :   rootFrame->SetStyleContextWithoutNotification(rootPseudoStyle);
    2790               0 :   rootFrame->Init(aDocElement, parentFrame, nsnull);
    2791                 :   
    2792               0 :   if (isScrollable) {
    2793               0 :     FinishBuildingScrollFrame(parentFrame, rootFrame);
    2794                 :   }
    2795                 :   
    2796               0 :   if (isPaginated) { // paginated
    2797                 :     // Create the first page
    2798                 :     // Set the initial child lists
    2799                 :     nsIFrame *pageFrame, *canvasFrame;
    2800                 :     ConstructPageFrame(mPresShell, presContext, rootFrame, nsnull,
    2801               0 :                        pageFrame, canvasFrame);
    2802               0 :     SetInitialSingleChild(rootFrame, pageFrame);
    2803                 : 
    2804                 :     // The eventual parent of the document element frame.
    2805                 :     // XXX should this be set for every new page (in ConstructPageFrame)?
    2806               0 :     mDocElementContainingBlock = canvasFrame;
    2807               0 :     mHasRootAbsPosContainingBlock = true;
    2808                 :   }
    2809                 : 
    2810               0 :   if (viewportFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
    2811               0 :     SetInitialSingleChild(viewportFrame, newFrame);
    2812                 :   } else {
    2813               0 :     nsFrameList newFrameList(newFrame, newFrame);
    2814               0 :     viewportFrame->AppendFrames(kPrincipalList, newFrameList);
    2815                 :   }
    2816                 : 
    2817               0 :   return NS_OK;
    2818                 : }
    2819                 : 
    2820                 : nsresult
    2821               0 : nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell*  aPresShell,
    2822                 :                                           nsPresContext* aPresContext,
    2823                 :                                           nsIFrame*      aParentFrame,
    2824                 :                                           nsIFrame*      aPrevPageFrame,
    2825                 :                                           nsIFrame*&     aPageFrame,
    2826                 :                                           nsIFrame*&     aCanvasFrame)
    2827                 : {
    2828               0 :   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
    2829               0 :   nsStyleSet *styleSet = aPresShell->StyleSet();
    2830                 : 
    2831               0 :   nsRefPtr<nsStyleContext> pagePseudoStyle;
    2832                 :   pagePseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::page,
    2833               0 :                                                        parentStyleContext);
    2834                 : 
    2835               0 :   aPageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
    2836               0 :   if (NS_UNLIKELY(!aPageFrame))
    2837               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2838                 : 
    2839                 :   // Initialize the page frame and force it to have a view. This makes printing of
    2840                 :   // the pages easier and faster.
    2841               0 :   aPageFrame->Init(nsnull, aParentFrame, aPrevPageFrame);
    2842                 : 
    2843               0 :   nsRefPtr<nsStyleContext> pageContentPseudoStyle;
    2844                 :   pageContentPseudoStyle =
    2845                 :     styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageContent,
    2846               0 :                                        pagePseudoStyle);
    2847                 : 
    2848               0 :   nsIFrame* pageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
    2849               0 :   if (NS_UNLIKELY(!pageContentFrame))
    2850               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2851                 : 
    2852                 :   // Initialize the page content frame and force it to have a view. Also make it the
    2853                 :   // containing block for fixed elements which are repeated on every page.
    2854               0 :   nsIFrame* prevPageContentFrame = nsnull;
    2855               0 :   if (aPrevPageFrame) {
    2856               0 :     prevPageContentFrame = aPrevPageFrame->GetFirstPrincipalChild();
    2857               0 :     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
    2858                 :   }
    2859               0 :   pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
    2860               0 :   SetInitialSingleChild(aPageFrame, pageContentFrame);
    2861               0 :   mFixedContainingBlock = pageContentFrame;
    2862                 :   // Make it an absolute container for fixed-pos elements
    2863               0 :   mFixedContainingBlock->MarkAsAbsoluteContainingBlock();
    2864                 : 
    2865               0 :   nsRefPtr<nsStyleContext> canvasPseudoStyle;
    2866                 :   canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
    2867               0 :                                                          pageContentPseudoStyle);
    2868                 : 
    2869               0 :   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
    2870               0 :   if (NS_UNLIKELY(!aCanvasFrame))
    2871               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2872                 : 
    2873               0 :   nsIFrame* prevCanvasFrame = nsnull;
    2874               0 :   if (prevPageContentFrame) {
    2875               0 :     prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
    2876               0 :     NS_ASSERTION(prevCanvasFrame, "missing canvas frame");
    2877                 :   }
    2878               0 :   aCanvasFrame->Init(nsnull, pageContentFrame, prevCanvasFrame);
    2879               0 :   SetInitialSingleChild(pageContentFrame, aCanvasFrame);
    2880                 : 
    2881               0 :   return NS_OK;
    2882                 : }
    2883                 : 
    2884                 : /* static */
    2885                 : nsresult
    2886               0 : nsCSSFrameConstructor::CreatePlaceholderFrameFor(nsIPresShell*    aPresShell, 
    2887                 :                                                  nsIContent*      aContent,
    2888                 :                                                  nsIFrame*        aFrame,
    2889                 :                                                  nsStyleContext*  aStyleContext,
    2890                 :                                                  nsIFrame*        aParentFrame,
    2891                 :                                                  nsIFrame*        aPrevInFlow,
    2892                 :                                                  nsFrameState     aTypeBit,
    2893                 :                                                  nsIFrame**       aPlaceholderFrame)
    2894                 : {
    2895                 :   nsRefPtr<nsStyleContext> placeholderStyle = aPresShell->StyleSet()->
    2896               0 :     ResolveStyleForNonElement(aStyleContext->GetParent());
    2897                 :   
    2898                 :   // The placeholder frame gets a pseudo style context
    2899                 :   nsPlaceholderFrame* placeholderFrame =
    2900                 :     (nsPlaceholderFrame*)NS_NewPlaceholderFrame(aPresShell, placeholderStyle,
    2901               0 :                                                 aTypeBit);
    2902                 : 
    2903               0 :   if (placeholderFrame) {
    2904               0 :     placeholderFrame->Init(aContent, aParentFrame, aPrevInFlow);
    2905                 :   
    2906                 :     // The placeholder frame has a pointer back to the out-of-flow frame
    2907               0 :     placeholderFrame->SetOutOfFlowFrame(aFrame);
    2908                 :   
    2909               0 :     aFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    2910                 : 
    2911                 :     // Add mapping from absolutely positioned frame to its placeholder frame
    2912               0 :     aPresShell->FrameManager()->RegisterPlaceholderFrame(placeholderFrame);
    2913                 : 
    2914               0 :     *aPlaceholderFrame = static_cast<nsIFrame*>(placeholderFrame);
    2915                 :     
    2916               0 :     return NS_OK;
    2917                 :   }
    2918                 :   else {
    2919               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2920                 :   }
    2921                 : }
    2922                 : 
    2923                 : // Clears any lazy bits set in the range [aStartContent, aEndContent).  If
    2924                 : // aEndContent is null, that means to clear bits in all siblings starting with
    2925                 : // aStartContent.  aStartContent must not be null unless aEndContent is also
    2926                 : // null.  We do this so that when new children are inserted under elements whose
    2927                 : // frame is a leaf the new children don't cause us to try to construct frames
    2928                 : // for the existing children again.
    2929                 : static inline void
    2930               0 : ClearLazyBits(nsIContent* aStartContent, nsIContent* aEndContent)
    2931                 : {
    2932               0 :   NS_PRECONDITION(aStartContent || !aEndContent,
    2933                 :                   "Must have start child if we have an end child");
    2934               0 :   for (nsIContent* cur = aStartContent; cur != aEndContent;
    2935               0 :        cur = cur->GetNextSibling()) {
    2936               0 :     cur->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    2937                 :   }
    2938               0 : }
    2939                 : 
    2940                 : nsresult
    2941               0 : nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
    2942                 :                                             FrameConstructionItem&   aItem,
    2943                 :                                             nsIFrame*                aParentFrame,
    2944                 :                                             const nsStyleDisplay*    aStyleDisplay,
    2945                 :                                             nsFrameItems&            aFrameItems,
    2946                 :                                             nsIFrame**               aNewFrame)
    2947                 : {
    2948               0 :   nsresult rv = NS_OK;
    2949               0 :   const PRInt32 kNoSizeSpecified = -1;
    2950                 : 
    2951               0 :   nsIContent* const content = aItem.mContent;
    2952               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    2953                 : 
    2954                 :   // Construct a frame-based listbox or combobox
    2955               0 :   nsCOMPtr<nsIDOMHTMLSelectElement> sel(do_QueryInterface(content));
    2956               0 :   PRInt32 size = 1;
    2957               0 :   if (sel) {
    2958               0 :     sel->GetSize(&size); 
    2959               0 :     bool multipleSelect = false;
    2960               0 :     sel->GetMultiple(&multipleSelect);
    2961                 :      // Construct a combobox if size=1 or no size is specified and its multiple select
    2962               0 :     if (((1 == size || 0 == size) || (kNoSizeSpecified  == size)) && (false == multipleSelect)) {
    2963                 :         // Construct a frame-based combo box.
    2964                 :         // The frame-based combo box is built out of three parts. A display area, a button and
    2965                 :         // a dropdown list. The display area and button are created through anonymous content.
    2966                 :         // The drop-down list's frame is created explicitly. The combobox frame shares its content
    2967                 :         // with the drop-down list.
    2968               0 :       PRUint32 flags = NS_BLOCK_FLOAT_MGR;
    2969               0 :       nsIFrame* comboboxFrame = NS_NewComboboxControlFrame(mPresShell, styleContext, flags);
    2970                 : 
    2971                 :       // Save the history state so we don't restore during construction
    2972                 :       // since the complete tree is required before we restore.
    2973               0 :       nsILayoutHistoryState *historyState = aState.mFrameState;
    2974               0 :       aState.mFrameState = nsnull;
    2975                 :       // Initialize the combobox frame
    2976                 :       InitAndRestoreFrame(aState, content,
    2977                 :                           aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    2978               0 :                           nsnull, comboboxFrame);
    2979                 : 
    2980                 :       rv = aState.AddChild(comboboxFrame, aFrameItems, content, styleContext,
    2981               0 :                            aParentFrame);
    2982               0 :       if (NS_FAILED(rv)) {
    2983               0 :         return rv;
    2984                 :       }
    2985                 :       
    2986               0 :       nsIComboboxControlFrame* comboBox = do_QueryFrame(comboboxFrame);
    2987               0 :       NS_ASSERTION(comboBox, "NS_NewComboboxControlFrame returned frame that "
    2988                 :                              "doesn't implement nsIComboboxControlFrame");
    2989                 : 
    2990                 :         // Resolve pseudo element style for the dropdown list
    2991               0 :       nsRefPtr<nsStyleContext> listStyle;
    2992                 :       listStyle = mPresShell->StyleSet()->
    2993               0 :         ResolveAnonymousBoxStyle(nsCSSAnonBoxes::dropDownList, styleContext);
    2994                 : 
    2995                 :         // Create a listbox
    2996               0 :       nsIFrame* listFrame = NS_NewListControlFrame(mPresShell, listStyle);
    2997                 : 
    2998                 :         // Notify the listbox that it is being used as a dropdown list.
    2999               0 :       nsIListControlFrame * listControlFrame = do_QueryFrame(listFrame);
    3000               0 :       if (listControlFrame) {
    3001               0 :         listControlFrame->SetComboboxFrame(comboboxFrame);
    3002                 :       }
    3003                 :          // Notify combobox that it should use the listbox as it's popup
    3004               0 :       comboBox->SetDropDown(listFrame);
    3005                 : 
    3006               0 :       NS_ASSERTION(!listStyle->GetStyleDisplay()->IsPositioned(),
    3007                 :                    "Ended up with positioned dropdown list somehow.");
    3008               0 :       NS_ASSERTION(!listStyle->GetStyleDisplay()->IsFloating(),
    3009                 :                    "Ended up with floating dropdown list somehow.");
    3010                 :       
    3011                 :       // Initialize the scroll frame positioned. Note that it is NOT
    3012                 :       // initialized as absolutely positioned.
    3013               0 :       nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(mPresShell, styleContext, flags);
    3014                 : 
    3015                 :       InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3016                 :                             comboboxFrame, listStyle, true,
    3017               0 :                             aItem.mPendingBinding, aFrameItems);
    3018                 : 
    3019               0 :       NS_ASSERTION(listFrame->GetView(), "ListFrame's view is nsnull");
    3020                 : 
    3021                 :       // Create display and button frames from the combobox's anonymous content.
    3022                 :       // The anonymous content is appended to existing anonymous content for this
    3023                 :       // element (the scrollbars).
    3024                 : 
    3025               0 :       nsFrameItems childItems;
    3026                 :       CreateAnonymousFrames(aState, content, comboboxFrame,
    3027               0 :                             aItem.mPendingBinding, childItems);
    3028                 :   
    3029               0 :       comboboxFrame->SetInitialChildList(kPrincipalList, childItems);
    3030                 : 
    3031                 :       // Initialize the additional popup child list which contains the
    3032                 :       // dropdown list frame.
    3033               0 :       nsFrameItems popupItems;
    3034               0 :       popupItems.AddChild(listFrame);
    3035                 :       comboboxFrame->SetInitialChildList(nsIFrame::kSelectPopupList,
    3036               0 :                                          popupItems);
    3037                 : 
    3038               0 :       *aNewFrame = comboboxFrame;
    3039               0 :       aState.mFrameState = historyState;
    3040               0 :       if (aState.mFrameState) {
    3041                 :         // Restore frame state for the entire subtree of |comboboxFrame|.
    3042               0 :         RestoreFrameState(comboboxFrame, aState.mFrameState);
    3043               0 :       }
    3044                 :     } else {
    3045               0 :       nsIFrame* listFrame = NS_NewListControlFrame(mPresShell, styleContext);
    3046               0 :       if (listFrame) {
    3047               0 :         rv = NS_OK;
    3048                 :       }
    3049                 :       else {
    3050               0 :         rv = NS_ERROR_OUT_OF_MEMORY;
    3051                 :       }
    3052                 : 
    3053                 :       nsIFrame* scrolledFrame = NS_NewSelectsAreaFrame(
    3054               0 :         mPresShell, styleContext, NS_BLOCK_FLOAT_MGR);
    3055                 : 
    3056                 :       // ******* this code stolen from Initialze ScrollFrame ********
    3057                 :       // please adjust this code to use BuildScrollFrame.
    3058                 : 
    3059                 :       InitializeSelectFrame(aState, listFrame, scrolledFrame, content,
    3060                 :                             aParentFrame, styleContext, false,
    3061               0 :                             aItem.mPendingBinding, aFrameItems);
    3062                 : 
    3063               0 :       *aNewFrame = listFrame;
    3064                 :     }
    3065                 :   }
    3066               0 :   return rv;
    3067                 : 
    3068                 : }
    3069                 : 
    3070                 : /**
    3071                 :  * Used to be InitializeScrollFrame but now it's only used for the select tag
    3072                 :  * But the select tag should really be fixed to use GFX scrollbars that can
    3073                 :  * be create with BuildScrollFrame.
    3074                 :  */
    3075                 : nsresult
    3076               0 : nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState,
    3077                 :                                              nsIFrame*                scrollFrame,
    3078                 :                                              nsIFrame*                scrolledFrame,
    3079                 :                                              nsIContent*              aContent,
    3080                 :                                              nsIFrame*                aParentFrame,
    3081                 :                                              nsStyleContext*          aStyleContext,
    3082                 :                                              bool                     aBuildCombobox,
    3083                 :                                              PendingBinding*          aPendingBinding,
    3084                 :                                              nsFrameItems&            aFrameItems)
    3085                 : {
    3086               0 :   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
    3087                 : 
    3088                 :   // Initialize it
    3089               0 :   nsIFrame* geometricParent = aState.GetGeometricParent(display, aParentFrame);
    3090                 :     
    3091                 :   // We don't call InitAndRestoreFrame for scrollFrame because we can only
    3092                 :   // restore the frame state after its parts have been created (in particular,
    3093                 :   // the scrollable view). So we have to split Init and Restore.
    3094                 : 
    3095                 :   // Initialize the frame
    3096               0 :   scrollFrame->Init(aContent, geometricParent, nsnull);
    3097                 : 
    3098               0 :   if (!aBuildCombobox) {
    3099                 :     nsresult rv = aState.AddChild(scrollFrame, aFrameItems, aContent,
    3100               0 :                                   aStyleContext, aParentFrame);
    3101               0 :     if (NS_FAILED(rv)) {
    3102               0 :       return rv;
    3103                 :     }
    3104                 :   }
    3105                 :       
    3106               0 :   if (aBuildCombobox) {
    3107               0 :     nsContainerFrame::CreateViewForFrame(scrollFrame, true);
    3108                 :   }
    3109                 : 
    3110                 :   BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame,
    3111               0 :                    geometricParent, scrollFrame);
    3112                 : 
    3113               0 :   if (aState.mFrameState) {
    3114                 :     // Restore frame state for the scroll frame
    3115               0 :     RestoreFrameStateFor(scrollFrame, aState.mFrameState);
    3116                 :   }
    3117                 : 
    3118                 :   // Process children
    3119               0 :   nsFrameItems                childItems;
    3120                 : 
    3121                 :   ProcessChildren(aState, aContent, aStyleContext, scrolledFrame, false,
    3122               0 :                   childItems, false, aPendingBinding);
    3123                 : 
    3124                 :   // Set the scrolled frame's initial child lists
    3125               0 :   scrolledFrame->SetInitialChildList(kPrincipalList, childItems);
    3126               0 :   return NS_OK;
    3127                 : }
    3128                 : 
    3129                 : nsresult
    3130               0 : nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState,
    3131                 :                                               FrameConstructionItem&   aItem,
    3132                 :                                               nsIFrame*                aParentFrame,
    3133                 :                                               const nsStyleDisplay*    aStyleDisplay,
    3134                 :                                               nsFrameItems&            aFrameItems,
    3135                 :                                               nsIFrame**               aNewFrame)
    3136                 : {
    3137               0 :   nsIContent* const content = aItem.mContent;
    3138               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    3139                 : 
    3140               0 :   nsIFrame* newFrame = NS_NewFieldSetFrame(mPresShell, styleContext);
    3141               0 :   if (NS_UNLIKELY(!newFrame)) {
    3142               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3143                 :   }
    3144                 : 
    3145                 :   // Initialize it
    3146                 :   InitAndRestoreFrame(aState, content,
    3147                 :                       aState.GetGeometricParent(aStyleDisplay, aParentFrame),
    3148               0 :                       nsnull, newFrame);
    3149                 : 
    3150                 :   // Resolve style and initialize the frame
    3151               0 :   nsRefPtr<nsStyleContext> fieldsetContentStyle;
    3152                 :   fieldsetContentStyle = mPresShell->StyleSet()->
    3153               0 :     ResolveAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent, styleContext);
    3154                 : 
    3155                 :   nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle,
    3156                 :                                           NS_BLOCK_FLOAT_MGR |
    3157               0 :                                           NS_BLOCK_MARGIN_ROOT);
    3158               0 :   InitAndRestoreFrame(aState, content, newFrame, nsnull, blockFrame);
    3159                 : 
    3160                 :   nsresult rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
    3161               0 :                                 aParentFrame);
    3162               0 :   if (NS_FAILED(rv)) {
    3163               0 :     return rv;
    3164                 :   }
    3165                 :   
    3166                 :   // Process children
    3167               0 :   nsFrameConstructorSaveState absoluteSaveState;
    3168               0 :   nsFrameItems                childItems;
    3169                 : 
    3170               0 :   if (aStyleDisplay->IsPositioned()) {
    3171               0 :     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
    3172                 :   }
    3173                 : 
    3174                 :   ProcessChildren(aState, content, styleContext, blockFrame, true,
    3175               0 :                   childItems, true, aItem.mPendingBinding);
    3176                 : 
    3177               0 :   nsFrameItems fieldsetKids;
    3178               0 :   fieldsetKids.AddChild(blockFrame);
    3179                 : 
    3180               0 :   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
    3181               0 :     nsLegendFrame* legendFrame = do_QueryFrame(e.get());
    3182               0 :     if (legendFrame) {
    3183                 :       // We want the legend to be the first frame in the fieldset child list.
    3184                 :       // That way the EventStateManager will do the right thing when tabbing
    3185                 :       // from a selection point within the legend (bug 236071), which is
    3186                 :       // used for implementing legend access keys (bug 81481).
    3187                 :       // GetAdjustedParentFrame() below depends on this frame order.
    3188               0 :       childItems.RemoveFrame(legendFrame);
    3189                 :       // Make sure to reparent the legend so it has the fieldset as the parent.
    3190               0 :       fieldsetKids.InsertFrame(newFrame, nsnull, legendFrame);
    3191               0 :       break;
    3192                 :     }
    3193                 :   }
    3194                 : 
    3195                 :   // Set the inner frame's initial child lists
    3196               0 :   blockFrame->SetInitialChildList(kPrincipalList, childItems);
    3197                 : 
    3198                 :   // Set the outer frame's initial child list
    3199               0 :   newFrame->SetInitialChildList(kPrincipalList, fieldsetKids);
    3200                 : 
    3201                 :   // our new frame returned is the top frame which is the list frame. 
    3202               0 :   *aNewFrame = newFrame; 
    3203                 : 
    3204               0 :   return NS_OK;
    3205                 : }
    3206                 : 
    3207                 : static nsIFrame*
    3208               0 : FindAncestorWithGeneratedContentPseudo(nsIFrame* aFrame)
    3209                 : {
    3210               0 :   for (nsIFrame* f = aFrame->GetParent(); f; f = f->GetParent()) {
    3211               0 :     NS_ASSERTION(f->IsGeneratedContentFrame(),
    3212                 :                  "should not have exited generated content");
    3213               0 :     nsIAtom* pseudo = f->GetStyleContext()->GetPseudo();
    3214               0 :     if (pseudo == nsCSSPseudoElements::before ||
    3215                 :         pseudo == nsCSSPseudoElements::after)
    3216               0 :       return f;
    3217                 :   }
    3218               0 :   return nsnull;
    3219                 : }
    3220                 : 
    3221                 : #define SIMPLE_FCDATA(_func) FCDATA_DECL(0, _func)
    3222                 : #define FULL_CTOR_FCDATA(_flags, _func)                             \
    3223                 :   { _flags | FCDATA_FUNC_IS_FULL_CTOR, { nsnull }, _func, nsnull }
    3224                 : 
    3225                 : /* static */
    3226                 : const nsCSSFrameConstructor::FrameConstructionData*
    3227               0 : nsCSSFrameConstructor::FindTextData(nsIFrame* aParentFrame)
    3228                 : {
    3229               0 :   if (aParentFrame && aParentFrame->IsFrameOfType(nsIFrame::eSVG)) {
    3230                 :     nsIFrame *ancestorFrame =
    3231               0 :       nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
    3232               0 :     if (ancestorFrame) {
    3233               0 :       nsSVGTextContainerFrame* metrics = do_QueryFrame(ancestorFrame);
    3234               0 :       if (metrics) {
    3235                 :         static const FrameConstructionData sSVGGlyphData =
    3236                 :           SIMPLE_FCDATA(NS_NewSVGGlyphFrame);
    3237               0 :         return &sSVGGlyphData;
    3238                 :       }
    3239                 :     }
    3240               0 :     return nsnull;
    3241                 :   }
    3242                 : 
    3243                 :   static const FrameConstructionData sTextData =
    3244                 :     FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT, NS_NewTextFrame);
    3245               0 :   return &sTextData;
    3246                 : }
    3247                 : 
    3248                 : nsresult
    3249               0 : nsCSSFrameConstructor::ConstructTextFrame(const FrameConstructionData* aData,
    3250                 :                                           nsFrameConstructorState& aState,
    3251                 :                                           nsIContent*              aContent,
    3252                 :                                           nsIFrame*                aParentFrame,
    3253                 :                                           nsStyleContext*          aStyleContext,
    3254                 :                                           nsFrameItems&            aFrameItems)
    3255                 : {
    3256               0 :   NS_PRECONDITION(aData, "Must have frame construction data");
    3257                 : 
    3258               0 :   nsIFrame* newFrame = (*aData->mFunc.mCreationFunc)(mPresShell, aStyleContext);
    3259                 : 
    3260               0 :   if (NS_UNLIKELY(!newFrame))
    3261               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3262                 : 
    3263                 :   nsresult rv = InitAndRestoreFrame(aState, aContent, aParentFrame,
    3264               0 :                                     nsnull, newFrame);
    3265                 : 
    3266               0 :   if (NS_FAILED(rv)) {
    3267               0 :     newFrame->Destroy();
    3268               0 :     return rv;
    3269                 :   }
    3270                 : 
    3271                 :   // We never need to create a view for a text frame.
    3272                 : 
    3273               0 :   if (newFrame->IsGeneratedContentFrame()) {
    3274               0 :     nsAutoPtr<nsGenConInitializer> initializer;
    3275                 :     initializer =
    3276                 :       static_cast<nsGenConInitializer*>(
    3277               0 :         aContent->UnsetProperty(nsGkAtoms::genConInitializerProperty));
    3278               0 :     if (initializer) {
    3279               0 :       if (initializer->mNode->InitTextFrame(initializer->mList,
    3280               0 :               FindAncestorWithGeneratedContentPseudo(newFrame), newFrame)) {
    3281               0 :         (this->*(initializer->mDirtyAll))();
    3282                 :       }
    3283               0 :       initializer->mNode.forget();
    3284                 :     }
    3285                 :   }
    3286                 :   
    3287                 :   // Add the newly constructed frame to the flow
    3288               0 :   aFrameItems.AddChild(newFrame);
    3289                 : 
    3290               0 :   if (!aState.mCreatingExtraFrames)
    3291               0 :     aContent->SetPrimaryFrame(newFrame);
    3292                 :   
    3293               0 :   return rv;
    3294                 : }
    3295                 : 
    3296                 : /* static */
    3297                 : const nsCSSFrameConstructor::FrameConstructionData*
    3298               0 : nsCSSFrameConstructor::FindDataByInt(PRInt32 aInt,
    3299                 :                                      Element* aElement,
    3300                 :                                      nsStyleContext* aStyleContext,
    3301                 :                                      const FrameConstructionDataByInt* aDataPtr,
    3302                 :                                      PRUint32 aDataLength)
    3303                 : {
    3304               0 :   for (const FrameConstructionDataByInt *curData = aDataPtr,
    3305               0 :          *endData = aDataPtr + aDataLength;
    3306                 :        curData != endData;
    3307                 :        ++curData) {
    3308               0 :     if (curData->mInt == aInt) {
    3309               0 :       const FrameConstructionData* data = &curData->mData;
    3310               0 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3311               0 :         return data->mFunc.mDataGetter(aElement, aStyleContext);
    3312                 :       }
    3313                 : 
    3314               0 :       return data;
    3315                 :     }
    3316                 :   }
    3317                 : 
    3318               0 :   return nsnull;
    3319                 : }
    3320                 : 
    3321                 : /* static */
    3322                 : const nsCSSFrameConstructor::FrameConstructionData*
    3323               0 : nsCSSFrameConstructor::FindDataByTag(nsIAtom* aTag,
    3324                 :                                      Element* aElement,
    3325                 :                                      nsStyleContext* aStyleContext,
    3326                 :                                      const FrameConstructionDataByTag* aDataPtr,
    3327                 :                                      PRUint32 aDataLength)
    3328                 : {
    3329               0 :   for (const FrameConstructionDataByTag *curData = aDataPtr,
    3330               0 :          *endData = aDataPtr + aDataLength;
    3331                 :        curData != endData;
    3332                 :        ++curData) {
    3333               0 :     if (*curData->mTag == aTag) {
    3334               0 :       const FrameConstructionData* data = &curData->mData;
    3335               0 :       if (data->mBits & FCDATA_FUNC_IS_DATA_GETTER) {
    3336               0 :         return data->mFunc.mDataGetter(aElement, aStyleContext);
    3337                 :       }
    3338                 : 
    3339               0 :       return data;
    3340                 :     }
    3341                 :   }
    3342                 : 
    3343               0 :   return nsnull;
    3344                 : }
    3345                 : 
    3346                 : #define SUPPRESS_FCDATA() FCDATA_DECL(FCDATA_SUPPRESS_FRAME, nsnull)
    3347                 : #define SIMPLE_INT_CREATE(_int, _func) { _int, SIMPLE_FCDATA(_func) }
    3348                 : #define SIMPLE_INT_CHAIN(_int, _func)                       \
    3349                 :   { _int, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER, _func) }
    3350                 : #define COMPLEX_INT_CREATE(_int, _func)         \
    3351                 :   { _int, FULL_CTOR_FCDATA(0, _func) }
    3352                 : 
    3353                 : #define SIMPLE_TAG_CREATE(_tag, _func)          \
    3354                 :   { &nsGkAtoms::_tag, SIMPLE_FCDATA(_func) }
    3355                 : #define SIMPLE_TAG_CHAIN(_tag, _func)                                   \
    3356                 :   { &nsGkAtoms::_tag, FCDATA_DECL(FCDATA_FUNC_IS_DATA_GETTER,  _func) }
    3357                 : #define COMPLEX_TAG_CREATE(_tag, _func)             \
    3358                 :   { &nsGkAtoms::_tag, FULL_CTOR_FCDATA(0, _func) }
    3359                 : 
    3360                 : /* static */
    3361                 : const nsCSSFrameConstructor::FrameConstructionData*
    3362               0 : nsCSSFrameConstructor::FindHTMLData(Element* aElement,
    3363                 :                                     nsIAtom* aTag,
    3364                 :                                     PRInt32 aNameSpaceID,
    3365                 :                                     nsIFrame* aParentFrame,
    3366                 :                                     nsStyleContext* aStyleContext)
    3367                 : {
    3368                 :   // Ignore the tag if it's not HTML content and if it doesn't extend (via XBL)
    3369                 :   // a valid HTML namespace.  This check must match the one in
    3370                 :   // ShouldHaveFirstLineStyle.
    3371               0 :   if (aNameSpaceID != kNameSpaceID_XHTML) {
    3372               0 :     return nsnull;
    3373                 :   }
    3374                 : 
    3375               0 :   NS_ASSERTION(!aParentFrame ||
    3376                 :                aParentFrame->GetStyleContext()->GetPseudo() !=
    3377                 :                  nsCSSAnonBoxes::fieldsetContent ||
    3378                 :                aParentFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame,
    3379                 :                "Unexpected parent for fieldset content anon box");
    3380               0 :   if (aTag == nsGkAtoms::legend &&
    3381                 :       (!aParentFrame ||
    3382               0 :        (aParentFrame->GetType() != nsGkAtoms::fieldSetFrame &&
    3383               0 :         aParentFrame->GetStyleContext()->GetPseudo() !=
    3384                 :           nsCSSAnonBoxes::fieldsetContent) ||
    3385               0 :        !aElement->GetParent() ||
    3386               0 :        !aElement->GetParent()->IsHTML(nsGkAtoms::fieldset) ||
    3387               0 :        aStyleContext->GetStyleDisplay()->IsFloating() ||
    3388               0 :        aStyleContext->GetStyleDisplay()->IsAbsolutelyPositioned())) {
    3389                 :     // <legend> is only special inside fieldset, check both the frame tree
    3390                 :     // parent and content tree parent due to XBL issues. For floated or
    3391                 :     // absolutely positioned legends we want to construct by display type and
    3392                 :     // not do special legend stuff.
    3393                 :     // XXXbz it would be nice if we could just decide this based on the parent
    3394                 :     // tag, and hence just use a SIMPLE_TAG_CHAIN for legend below, but the
    3395                 :     // fact that with XBL we could end up with this legend element in some
    3396                 :     // totally weird insertion point makes that chancy, I think.
    3397               0 :     return nsnull;
    3398                 :   }
    3399                 : 
    3400                 :   static const FrameConstructionDataByTag sHTMLData[] = {
    3401                 :     SIMPLE_TAG_CHAIN(img, nsCSSFrameConstructor::FindImgData),
    3402                 :     SIMPLE_TAG_CHAIN(mozgeneratedcontentimage,
    3403                 :                      nsCSSFrameConstructor::FindImgData),
    3404                 :     { &nsGkAtoms::br,
    3405                 :       FCDATA_DECL(FCDATA_IS_LINE_PARTICIPANT | FCDATA_IS_LINE_BREAK,
    3406                 :                   NS_NewBRFrame) },
    3407                 :     SIMPLE_TAG_CREATE(wbr, NS_NewWBRFrame),
    3408                 :     SIMPLE_TAG_CHAIN(input, nsCSSFrameConstructor::FindInputData),
    3409                 :     SIMPLE_TAG_CREATE(textarea, NS_NewTextControlFrame),
    3410                 :     COMPLEX_TAG_CREATE(select, &nsCSSFrameConstructor::ConstructSelectFrame),
    3411                 :     SIMPLE_TAG_CHAIN(object, nsCSSFrameConstructor::FindObjectData),
    3412                 :     SIMPLE_TAG_CHAIN(applet, nsCSSFrameConstructor::FindObjectData),
    3413                 :     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
    3414                 :     COMPLEX_TAG_CREATE(fieldset,
    3415                 :                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
    3416                 :     { &nsGkAtoms::legend,
    3417                 :       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES, NS_NewLegendFrame) },
    3418                 :     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
    3419                 :     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
    3420                 :     { &nsGkAtoms::button,
    3421                 :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES,
    3422                 :                                  NS_NewHTMLButtonControlFrame,
    3423                 :                                  nsCSSAnonBoxes::buttonContent) },
    3424                 :     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
    3425                 : #if defined(MOZ_MEDIA)
    3426                 :     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
    3427                 :     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
    3428                 : #endif
    3429                 :     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame)
    3430                 :   };
    3431                 : 
    3432                 :   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
    3433               0 :                        ArrayLength(sHTMLData));
    3434                 : }
    3435                 : 
    3436                 : /* static */
    3437                 : const nsCSSFrameConstructor::FrameConstructionData*
    3438               0 : nsCSSFrameConstructor::FindImgData(Element* aElement,
    3439                 :                                    nsStyleContext* aStyleContext)
    3440                 : {
    3441               0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
    3442               0 :     return nsnull;
    3443                 :   }
    3444                 : 
    3445                 :   static const FrameConstructionData sImgData = SIMPLE_FCDATA(NS_NewImageFrame);
    3446               0 :   return &sImgData;
    3447                 : }
    3448                 : 
    3449                 : /* static */
    3450                 : const nsCSSFrameConstructor::FrameConstructionData*
    3451               0 : nsCSSFrameConstructor::FindImgControlData(Element* aElement,
    3452                 :                                           nsStyleContext* aStyleContext)
    3453                 : {
    3454               0 :   if (!nsImageFrame::ShouldCreateImageFrameFor(aElement, aStyleContext)) {
    3455               0 :     return nsnull;
    3456                 :   }
    3457                 : 
    3458                 :   static const FrameConstructionData sImgControlData =
    3459                 :     SIMPLE_FCDATA(NS_NewImageControlFrame);
    3460               0 :   return &sImgControlData;
    3461                 : }
    3462                 : 
    3463                 : /* static */
    3464                 : const nsCSSFrameConstructor::FrameConstructionData*
    3465               0 : nsCSSFrameConstructor::FindInputData(Element* aElement,
    3466                 :                                      nsStyleContext* aStyleContext)
    3467                 : {
    3468                 :   static const FrameConstructionDataByInt sInputData[] = {
    3469                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_CHECKBOX, NS_NewGfxCheckboxControlFrame),
    3470                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_RADIO, NS_NewGfxRadioControlFrame),
    3471                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_FILE, NS_NewFileControlFrame),
    3472                 :     SIMPLE_INT_CHAIN(NS_FORM_INPUT_IMAGE,
    3473                 :                      nsCSSFrameConstructor::FindImgControlData),
    3474                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_EMAIL, NS_NewTextControlFrame),
    3475                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_SEARCH, NS_NewTextControlFrame),
    3476                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEXT, NS_NewTextControlFrame),
    3477                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_TEL, NS_NewTextControlFrame),
    3478                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_URL, NS_NewTextControlFrame),
    3479                 :     SIMPLE_INT_CREATE(NS_FORM_INPUT_PASSWORD, NS_NewTextControlFrame),
    3480                 :     { NS_FORM_INPUT_SUBMIT,
    3481                 :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3482                 :                                  nsCSSAnonBoxes::buttonContent) },
    3483                 :     { NS_FORM_INPUT_RESET,
    3484                 :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3485                 :                                  nsCSSAnonBoxes::buttonContent) },
    3486                 :     { NS_FORM_INPUT_BUTTON,
    3487                 :       FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewGfxButtonControlFrame,
    3488                 :                                  nsCSSAnonBoxes::buttonContent) }
    3489                 :     // Keeping hidden inputs out of here on purpose for so they get frames by
    3490                 :     // display (in practice, none).
    3491                 :   };
    3492                 : 
    3493               0 :   nsCOMPtr<nsIFormControl> control = do_QueryInterface(aElement);
    3494               0 :   NS_ASSERTION(control, "input doesn't implement nsIFormControl?");
    3495                 : 
    3496               0 :   return FindDataByInt(control->GetType(), aElement, aStyleContext,
    3497               0 :                        sInputData, ArrayLength(sInputData));
    3498                 : }
    3499                 : 
    3500                 : /* static */
    3501                 : const nsCSSFrameConstructor::FrameConstructionData*
    3502               0 : nsCSSFrameConstructor::FindObjectData(Element* aElement,
    3503                 :                                       nsStyleContext* aStyleContext)
    3504                 : {
    3505                 :   // GetDisplayedType isn't necessarily nsIObjectLoadingContent::TYPE_NULL for
    3506                 :   // cases when the object is broken/suppressed/etc (e.g. a broken image), but
    3507                 :   // we want to treat those cases as TYPE_NULL
    3508                 :   PRUint32 type;
    3509               0 :   if (aElement->State().HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
    3510                 :                                               NS_EVENT_STATE_USERDISABLED |
    3511               0 :                                               NS_EVENT_STATE_SUPPRESSED)) {
    3512               0 :     type = nsIObjectLoadingContent::TYPE_NULL;
    3513                 :   } else {
    3514               0 :     nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(aElement));
    3515               0 :     NS_ASSERTION(objContent,
    3516                 :                  "applet, embed and object must implement "
    3517                 :                  "nsIObjectLoadingContent!");
    3518                 : 
    3519               0 :     objContent->GetDisplayedType(&type);
    3520                 :   }
    3521                 : 
    3522                 :   static const FrameConstructionDataByInt sObjectData[] = {
    3523                 :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_LOADING,
    3524                 :                       NS_NewEmptyFrame),
    3525                 :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_PLUGIN,
    3526                 :                       NS_NewObjectFrame),
    3527                 :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_IMAGE,
    3528                 :                       NS_NewImageFrame),
    3529                 :     SIMPLE_INT_CREATE(nsIObjectLoadingContent::TYPE_DOCUMENT,
    3530                 :                       NS_NewSubDocumentFrame)
    3531                 :     // Nothing for TYPE_NULL so we'll construct frames by display there
    3532                 :   };
    3533                 : 
    3534                 :   return FindDataByInt((PRInt32)type, aElement, aStyleContext,
    3535               0 :                        sObjectData, ArrayLength(sObjectData));
    3536                 : }
    3537                 : 
    3538                 : /* static */
    3539                 : const nsCSSFrameConstructor::FrameConstructionData*
    3540               0 : nsCSSFrameConstructor::FindCanvasData(Element* aElement,
    3541                 :                                       nsStyleContext* aStyleContext)
    3542                 : {
    3543                 :   // We want to check whether script is enabled on the document that
    3544                 :   // could be painting to the canvas.  That's the owner document of
    3545                 :   // the canvas, except when the owner document is a static document,
    3546                 :   // in which case it's the original document it was cloned from.
    3547               0 :   nsIDocument* doc = aElement->OwnerDoc();
    3548               0 :   if (doc->IsStaticDocument()) {
    3549               0 :     doc = doc->GetOriginalDocument();
    3550                 :   }
    3551               0 :   if (!doc->IsScriptEnabled()) {
    3552               0 :     return nsnull;
    3553                 :   }
    3554                 : 
    3555                 :   static const FrameConstructionData sCanvasData =
    3556                 :     FCDATA_WITH_WRAPPING_BLOCK(0, NS_NewHTMLCanvasFrame,
    3557                 :                                nsCSSAnonBoxes::htmlCanvasContent);
    3558               0 :   return &sCanvasData;
    3559                 : }
    3560                 : 
    3561                 : nsresult
    3562               0 : nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
    3563                 :                                                       nsFrameConstructorState& aState,
    3564                 :                                                       nsIFrame* aParentFrame,
    3565                 :                                                       nsFrameItems& aFrameItems)
    3566                 : {
    3567               0 :   const FrameConstructionData* data = aItem.mFCData;
    3568               0 :   NS_ASSERTION(data, "Must have frame construction data");
    3569                 : 
    3570               0 :   PRUint32 bits = data->mBits;
    3571                 : 
    3572               0 :   NS_ASSERTION(!(bits & FCDATA_FUNC_IS_DATA_GETTER),
    3573                 :                "Should have dealt with this inside the data finder");
    3574                 : 
    3575                 :   // Some sets of bits are not compatible with each other
    3576                 : #define CHECK_ONLY_ONE_BIT(_bit1, _bit2)               \
    3577                 :   NS_ASSERTION(!(bits & _bit1) || !(bits & _bit2),     \
    3578                 :                "Only one of these bits should be set")
    3579               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_FORCE_NULL_ABSPOS_CONTAINER);
    3580               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_WRAP_KIDS_IN_BLOCKS);
    3581               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_MAY_NEED_SCROLLFRAME);
    3582               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_IS_POPUP);
    3583               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_SKIP_ABSPOS_PUSH);
    3584               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3585                 :                      FCDATA_DISALLOW_GENERATED_CONTENT);
    3586               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR, FCDATA_ALLOW_BLOCK_STYLES);
    3587               0 :   CHECK_ONLY_ONE_BIT(FCDATA_FUNC_IS_FULL_CTOR,
    3588                 :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3589               0 :   CHECK_ONLY_ONE_BIT(FCDATA_WRAP_KIDS_IN_BLOCKS,
    3590                 :                      FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS);
    3591                 : #undef CHECK_ONLY_ONE_BIT
    3592               0 :   NS_ASSERTION(!(bits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) ||
    3593                 :                ((bits & FCDATA_FUNC_IS_FULL_CTOR) &&
    3594                 :                 data->mFullConstructor ==
    3595                 :                   &nsCSSFrameConstructor::ConstructNonScrollableBlock),
    3596                 :                "Unexpected FCDATA_FORCED_NON_SCROLLABLE_BLOCK flag");
    3597                 : 
    3598                 :   // Don't create a subdocument frame for iframes if we're creating extra frames
    3599               0 :   if (aState.mCreatingExtraFrames && aItem.mContent->IsHTML() &&
    3600               0 :       aItem.mContent->Tag() == nsGkAtoms::iframe)
    3601                 :   {
    3602               0 :     return NS_OK;
    3603                 :   }
    3604                 : 
    3605               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    3606               0 :   const nsStyleDisplay* display = styleContext->GetStyleDisplay();
    3607               0 :   nsIContent* const content = aItem.mContent;
    3608                 : 
    3609                 :   // Push the content as a style ancestor now, so we don't have to do
    3610                 :   // it in our various full-constructor functions.  In particular,
    3611                 :   // since a number of full-constructor functions don't actually call
    3612                 :   // ProcessChildren in some cases (e.g. for CSS anonymous table boxes
    3613                 :   // or for situations where only anonymouse children are having
    3614                 :   // frames constructed), this is the best place to bottleneck the
    3615                 :   // pushing of the content instead of having to do it in multiple
    3616                 :   // places.
    3617                 :   AncestorFilter::AutoAncestorPusher
    3618               0 :     ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
    3619                 :                    aState.mTreeMatchContext.mAncestorFilter,
    3620               0 :                    content->IsElement() ? content->AsElement() : nsnull);
    3621                 : 
    3622                 :   nsIFrame* newFrame;
    3623                 :   nsIFrame* primaryFrame;
    3624               0 :   if (bits & FCDATA_FUNC_IS_FULL_CTOR) {
    3625                 :     nsresult rv =
    3626                 :       (this->*(data->mFullConstructor))(aState, aItem, aParentFrame,
    3627               0 :                                         display, aFrameItems, &newFrame);
    3628               0 :     if (NS_FAILED(rv)) {
    3629               0 :       return rv;
    3630                 :     }
    3631                 : 
    3632               0 :     primaryFrame = newFrame;
    3633                 :   } else {
    3634                 :     newFrame =
    3635               0 :       (*data->mFunc.mCreationFunc)(mPresShell, styleContext);
    3636               0 :     if (!newFrame) {
    3637               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3638                 :     }
    3639                 : 
    3640               0 :     bool allowOutOfFlow = !(bits & FCDATA_DISALLOW_OUT_OF_FLOW);
    3641               0 :     bool isPopup = aItem.mIsPopup;
    3642               0 :     NS_ASSERTION(!isPopup ||
    3643                 :                  (aState.mPopupItems.containingBlock &&
    3644                 :                   aState.mPopupItems.containingBlock->GetType() ==
    3645                 :                     nsGkAtoms::popupSetFrame),
    3646                 :                  "Should have a containing block here!");
    3647                 : 
    3648                 :     nsIFrame* geometricParent =
    3649                 :       isPopup ? aState.mPopupItems.containingBlock :
    3650                 :       (allowOutOfFlow ? aState.GetGeometricParent(display, aParentFrame)
    3651               0 :                       : aParentFrame);
    3652                 : 
    3653               0 :     nsresult rv = NS_OK;
    3654                 : 
    3655                 :     // Must init frameToAddToList to null, since it's inout
    3656               0 :     nsIFrame* frameToAddToList = nsnull;
    3657               0 :     if ((bits & FCDATA_MAY_NEED_SCROLLFRAME) &&
    3658               0 :         display->IsScrollableOverflow()) {
    3659                 :       BuildScrollFrame(aState, content, styleContext, newFrame,
    3660               0 :                        geometricParent, frameToAddToList);
    3661                 :     } else {
    3662                 :       rv = InitAndRestoreFrame(aState, content, geometricParent, nsnull,
    3663               0 :                                newFrame);
    3664               0 :       NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed");
    3665                 :       // See whether we need to create a view
    3666               0 :       nsContainerFrame::CreateViewForFrame(newFrame, false);
    3667               0 :       frameToAddToList = newFrame;
    3668                 :     }
    3669                 : 
    3670                 :     // Use frameToAddToList as the primary frame.  In the non-scrollframe case
    3671                 :     // they're equal, but in the scrollframe case newFrame is the scrolled
    3672                 :     // frame, while frameToAddToList is the scrollframe (and should be the
    3673                 :     // primary frame).
    3674               0 :     primaryFrame = frameToAddToList;
    3675                 : 
    3676                 :     // If we need to create a block formatting context to wrap our
    3677                 :     // kids, do it now.
    3678               0 :     const nsStyleDisplay* maybeAbsoluteContainingBlockDisplay = display;
    3679               0 :     nsIFrame* maybeAbsoluteContainingBlock = newFrame;
    3680               0 :     nsIFrame* possiblyLeafFrame = newFrame;
    3681               0 :     if (bits & FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS) {
    3682               0 :       nsRefPtr<nsStyleContext> blockContext;
    3683                 :       blockContext =
    3684                 :         mPresShell->StyleSet()->ResolveAnonymousBoxStyle(*data->mAnonBoxPseudo,
    3685               0 :                                                          styleContext);
    3686                 :       nsIFrame* blockFrame =
    3687               0 :         NS_NewBlockFormattingContext(mPresShell, blockContext);
    3688               0 :       if (NS_UNLIKELY(!blockFrame)) {
    3689               0 :         primaryFrame->Destroy();
    3690               0 :         return NS_ERROR_OUT_OF_MEMORY;
    3691                 :       }
    3692                 : 
    3693               0 :       rv = InitAndRestoreFrame(aState, content, newFrame, nsnull, blockFrame);
    3694               0 :       if (NS_FAILED(rv)) {
    3695               0 :         blockFrame->Destroy();
    3696               0 :         primaryFrame->Destroy();
    3697               0 :         return rv;
    3698                 :       }
    3699                 : 
    3700               0 :       SetInitialSingleChild(newFrame, blockFrame);
    3701                 : 
    3702                 :       // Now figure out whether newFrame or blockFrame should be the
    3703                 :       // absolute container.  It should be the latter if it's
    3704                 :       // positioned, otherwise the former.
    3705               0 :       const nsStyleDisplay* blockDisplay = blockContext->GetStyleDisplay();
    3706               0 :       if (blockDisplay->IsPositioned()) {
    3707               0 :         maybeAbsoluteContainingBlockDisplay = blockDisplay;
    3708               0 :         maybeAbsoluteContainingBlock = blockFrame;
    3709                 :       }
    3710                 :       
    3711                 :       // Our kids should go into the blockFrame
    3712               0 :       newFrame = blockFrame;
    3713                 :     }
    3714                 : 
    3715                 :     rv = aState.AddChild(frameToAddToList, aFrameItems, content, styleContext,
    3716               0 :                          aParentFrame, allowOutOfFlow, allowOutOfFlow, isPopup);
    3717               0 :     if (NS_FAILED(rv)) {
    3718               0 :       return rv;
    3719                 :     }
    3720                 : 
    3721                 : #ifdef MOZ_XUL
    3722                 :     // Icky XUL stuff, sadly
    3723                 : 
    3724               0 :     if (aItem.mIsRootPopupgroup) {
    3725               0 :       NS_ASSERTION(nsIRootBox::GetRootBox(mPresShell) &&
    3726                 :                    nsIRootBox::GetRootBox(mPresShell)->GetPopupSetFrame() ==
    3727                 :                      newFrame,
    3728                 :                    "Unexpected PopupSetFrame");
    3729               0 :       aState.mPopupItems.containingBlock = newFrame;
    3730               0 :       aState.mHavePendingPopupgroup = false;
    3731                 :     }
    3732                 : #endif /* MOZ_XUL */
    3733                 : 
    3734                 :     // Process the child content if requested
    3735               0 :     nsFrameItems childItems;
    3736               0 :     nsFrameConstructorSaveState absoluteSaveState;
    3737                 : 
    3738               0 :     if (bits & FCDATA_FORCE_NULL_ABSPOS_CONTAINER) {
    3739               0 :       aState.PushAbsoluteContainingBlock(nsnull, absoluteSaveState);
    3740               0 :     } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH) &&
    3741               0 :                maybeAbsoluteContainingBlockDisplay->IsPositioned()) {
    3742                 :       aState.PushAbsoluteContainingBlock(maybeAbsoluteContainingBlock,
    3743               0 :                                          absoluteSaveState);
    3744                 :     }
    3745                 : 
    3746               0 :     if (bits & FCDATA_USE_CHILD_ITEMS) {
    3747                 :       rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
    3748               0 :                                        childItems);
    3749                 :     } else {
    3750                 :       // Process the child frames.
    3751                 :       rv = ProcessChildren(aState, content, styleContext, newFrame,
    3752                 :                            !(bits & FCDATA_DISALLOW_GENERATED_CONTENT),
    3753                 :                            childItems,
    3754                 :                            (bits & FCDATA_ALLOW_BLOCK_STYLES) != 0,
    3755               0 :                            aItem.mPendingBinding, possiblyLeafFrame);
    3756                 :     }
    3757                 : 
    3758                 : #ifdef MOZ_XUL
    3759                 :     // More icky XUL stuff
    3760               0 :     if (aItem.mNameSpaceID == kNameSpaceID_XUL &&
    3761                 :         (aItem.mTag == nsGkAtoms::treechildren || // trees always need titletips
    3762               0 :          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext) ||
    3763               0 :          content->HasAttr(kNameSpaceID_None, nsGkAtoms::tooltip))) {
    3764               0 :       nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    3765               0 :       if (rootBox) {
    3766               0 :         rootBox->AddTooltipSupport(content);
    3767                 :       }
    3768                 :     }
    3769                 : #endif
    3770                 : 
    3771               0 :     if (NS_SUCCEEDED(rv) && (bits & FCDATA_WRAP_KIDS_IN_BLOCKS)) {
    3772               0 :       nsFrameItems newItems;
    3773               0 :       nsFrameItems currentBlock;
    3774                 :       nsIFrame* f;
    3775               0 :       while ((f = childItems.FirstChild()) != nsnull) {
    3776               0 :         bool wrapFrame = IsInlineFrame(f) || IsFrameSpecial(f);
    3777               0 :         if (!wrapFrame) {
    3778               0 :           rv = FlushAccumulatedBlock(aState, content, newFrame, &currentBlock, &newItems);
    3779               0 :           if (NS_FAILED(rv))
    3780               0 :             break;
    3781                 :         }
    3782                 : 
    3783               0 :         childItems.RemoveFrame(f);
    3784               0 :         if (wrapFrame) {
    3785               0 :           currentBlock.AddChild(f);
    3786                 :         } else {
    3787               0 :           newItems.AddChild(f);
    3788                 :         }
    3789                 :       }
    3790               0 :       rv = FlushAccumulatedBlock(aState, content, newFrame, &currentBlock, &newItems);
    3791                 : 
    3792               0 :       if (childItems.NotEmpty()) {
    3793                 :         // an error must have occurred, delete unprocessed frames
    3794               0 :         childItems.DestroyFrames();
    3795                 :       }
    3796                 : 
    3797               0 :       childItems = newItems;
    3798                 :     }
    3799                 : 
    3800                 :     // Set the frame's initial child list
    3801                 :     // Note that MathML depends on this being called even if
    3802                 :     // childItems is empty!
    3803               0 :     newFrame->SetInitialChildList(kPrincipalList, childItems);
    3804                 :   }
    3805                 : 
    3806               0 :   NS_ASSERTION(newFrame->IsFrameOfType(nsIFrame::eLineParticipant) ==
    3807                 :                ((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
    3808                 :                "Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
    3809                 : 
    3810                 :   // Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
    3811                 :   // generated content that doesn't have one yet.  Note that we have to examine
    3812                 :   // the frame bit, because by this point mIsGeneratedContent has been cleared
    3813                 :   // on aItem.
    3814               0 :   if ((!aState.mCreatingExtraFrames ||
    3815               0 :        ((primaryFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) &&
    3816               0 :         !aItem.mContent->GetPrimaryFrame())) &&
    3817               0 :        !(bits & FCDATA_SKIP_FRAMESET)) {
    3818               0 :     aItem.mContent->SetPrimaryFrame(primaryFrame);
    3819                 :   }
    3820                 : 
    3821               0 :   return NS_OK;
    3822                 : }
    3823                 : 
    3824                 : // after the node has been constructed and initialized create any
    3825                 : // anonymous content a node needs.
    3826                 : nsresult
    3827               0 : nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
    3828                 :                                              nsIContent*              aParent,
    3829                 :                                              nsIFrame*                aParentFrame,
    3830                 :                                              PendingBinding*          aPendingBinding,
    3831                 :                                              nsFrameItems&            aChildItems)
    3832                 : {
    3833               0 :   nsAutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> newAnonymousItems;
    3834               0 :   nsresult rv = GetAnonymousContent(aParent, aParentFrame, newAnonymousItems);
    3835               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3836                 : 
    3837               0 :   PRUint32 count = newAnonymousItems.Length();
    3838               0 :   if (count == 0) {
    3839               0 :     return NS_OK;
    3840                 :   }
    3841                 : 
    3842                 :   nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
    3843               0 :                                                            aPendingBinding);
    3844                 :   AncestorFilter::AutoAncestorPusher
    3845               0 :     ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
    3846                 :                    aState.mTreeMatchContext.mAncestorFilter,
    3847               0 :                    aParent->AsElement());
    3848                 : 
    3849               0 :   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
    3850               0 :   NS_ASSERTION(creator,
    3851                 :                "How can that happen if we have nodes to construct frames for?");
    3852                 : 
    3853               0 :   for (PRUint32 i=0; i < count; i++) {
    3854               0 :     nsIContent* content = newAnonymousItems[i].mContent;
    3855               0 :     NS_ASSERTION(content, "null anonymous content?");
    3856               0 :     NS_ASSERTION(!newAnonymousItems[i].mStyleContext, "Unexpected style context");
    3857                 : 
    3858               0 :     nsIFrame* newFrame = creator->CreateFrameFor(content);
    3859               0 :     if (newFrame) {
    3860               0 :       NS_ASSERTION(content->GetPrimaryFrame(),
    3861                 :                    "Content must have a primary frame now");
    3862               0 :       aChildItems.AddChild(newFrame);
    3863                 :     }
    3864                 :     else {
    3865                 :       // create the frame and attach it to our frame
    3866               0 :       ConstructFrame(aState, content, aParentFrame, aChildItems);
    3867                 :     }
    3868                 :   }
    3869                 : 
    3870               0 :   return NS_OK;
    3871                 : }
    3872                 : 
    3873                 : nsresult
    3874               0 : nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
    3875                 :                                            nsIFrame* aParentFrame,
    3876                 :                                            nsTArray<nsIAnonymousContentCreator::ContentInfo>& aContent)
    3877                 : {
    3878               0 :   nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
    3879               0 :   if (!creator)
    3880               0 :     return NS_OK;
    3881                 : 
    3882               0 :   nsresult rv = creator->CreateAnonymousContent(aContent);
    3883               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3884                 : 
    3885               0 :   PRUint32 count = aContent.Length();
    3886               0 :   for (PRUint32 i=0; i < count; i++) {
    3887                 :     // get our child's content and set its parent to our content
    3888               0 :     nsIContent* content = aContent[i].mContent;
    3889               0 :     NS_ASSERTION(content, "null anonymous content?");
    3890                 : 
    3891                 :     // least-surprise CSS binding until we do the SVG specified
    3892                 :     // cascading rules for <svg:use> - bug 265894
    3893               0 :     if (aParent &&
    3894               0 :         aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) {
    3895               0 :       content->SetFlags(NODE_IS_ANONYMOUS);
    3896                 :     } else {
    3897               0 :       content->SetNativeAnonymous();
    3898                 :     }
    3899                 : 
    3900               0 :     rv = content->BindToTree(mDocument, aParent, aParent, true);
    3901               0 :     if (NS_FAILED(rv)) {
    3902               0 :       content->UnbindFromTree();
    3903               0 :       return rv;
    3904                 :     }
    3905                 :   }
    3906                 : 
    3907               0 :   return NS_OK;
    3908                 : }
    3909                 : 
    3910                 : static
    3911               0 : bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
    3912                 : {
    3913                 :   return (aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX || 
    3914                 : #ifdef MOZ_XUL
    3915                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_GRID || 
    3916                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK ||
    3917                 : #endif
    3918                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_BOX
    3919                 : #ifdef MOZ_XUL
    3920                 :           || aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID ||
    3921                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_STACK ||
    3922                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID_GROUP ||
    3923                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_GRID_LINE ||
    3924                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_DECK ||
    3925                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_POPUP ||
    3926                 :           aDisplay->mDisplay == NS_STYLE_DISPLAY_GROUPBOX
    3927                 : #endif
    3928               0 :           );
    3929                 : }
    3930                 : 
    3931                 : 
    3932                 : // XUL frames are not allowed to be out of flow.
    3933                 : #define SIMPLE_XUL_FCDATA(_func)                                        \
    3934                 :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH,    \
    3935                 :               _func)
    3936                 : #define SCROLLABLE_XUL_FCDATA(_func)                                    \
    3937                 :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |   \
    3938                 :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    3939                 : // .. but we allow some XUL frames to be _containers_ for out-of-flow content
    3940                 : // (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH)
    3941                 : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func)                   \
    3942                 :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    3943                 :               FCDATA_MAY_NEED_SCROLLFRAME, _func)
    3944                 : 
    3945                 : #define SIMPLE_XUL_CREATE(_tag, _func)            \
    3946                 :   { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) }
    3947                 : #define SCROLLABLE_XUL_CREATE(_tag, _func)            \
    3948                 :   { &nsGkAtoms::_tag, SCROLLABLE_XUL_FCDATA(_func) }
    3949                 : #define SIMPLE_XUL_INT_CREATE(_int, _func)      \
    3950                 :   { _int, SIMPLE_XUL_FCDATA(_func) }
    3951                 : #define SCROLLABLE_XUL_INT_CREATE(_int, _func)                          \
    3952                 :   { _int, SCROLLABLE_XUL_FCDATA(_func) }
    3953                 : #define SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(_int, _func)         \
    3954                 :   { _int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) }
    3955                 : 
    3956                 : static
    3957               0 : nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell,
    3958                 :                              nsStyleContext* aStyleContext)
    3959                 : {
    3960               0 :   nsCOMPtr<nsBoxLayout> layout;
    3961               0 :   NS_NewGridLayout2(aPresShell, getter_AddRefs(layout));
    3962               0 :   if (!layout) {
    3963               0 :     return nsnull;
    3964                 :   }
    3965                 : 
    3966               0 :   return NS_NewBoxFrame(aPresShell, aStyleContext, false, layout);
    3967                 : }
    3968                 : 
    3969                 : /* static */
    3970                 : const nsCSSFrameConstructor::FrameConstructionData*
    3971               0 : nsCSSFrameConstructor::FindXULTagData(Element* aElement,
    3972                 :                                       nsIAtom* aTag,
    3973                 :                                       PRInt32 aNameSpaceID,
    3974                 :                                       nsStyleContext* aStyleContext)
    3975                 : {
    3976               0 :   if (aNameSpaceID != kNameSpaceID_XUL) {
    3977               0 :     return nsnull;
    3978                 :   }
    3979                 : 
    3980                 :   static const FrameConstructionDataByTag sXULTagData[] = {
    3981                 : #ifdef MOZ_XUL
    3982                 :     SCROLLABLE_XUL_CREATE(button, NS_NewButtonBoxFrame),
    3983                 :     SCROLLABLE_XUL_CREATE(checkbox, NS_NewButtonBoxFrame),
    3984                 :     SCROLLABLE_XUL_CREATE(radio, NS_NewButtonBoxFrame),
    3985                 :     SCROLLABLE_XUL_CREATE(autorepeatbutton, NS_NewAutoRepeatBoxFrame),
    3986                 :     SCROLLABLE_XUL_CREATE(titlebar, NS_NewTitleBarFrame),
    3987                 :     SCROLLABLE_XUL_CREATE(resizer, NS_NewResizerFrame),
    3988                 :     SIMPLE_XUL_CREATE(image, NS_NewImageBoxFrame),
    3989                 :     SIMPLE_XUL_CREATE(spring, NS_NewLeafBoxFrame),
    3990                 :     SIMPLE_XUL_CREATE(spacer, NS_NewLeafBoxFrame),
    3991                 :     SIMPLE_XUL_CREATE(treechildren, NS_NewTreeBodyFrame),
    3992                 :     SIMPLE_XUL_CREATE(treecol, NS_NewTreeColFrame),
    3993                 :     SIMPLE_XUL_CREATE(text, NS_NewTextBoxFrame),
    3994                 :     SIMPLE_TAG_CHAIN(label, nsCSSFrameConstructor::FindXULLabelData),
    3995                 :     SIMPLE_TAG_CHAIN(description, nsCSSFrameConstructor::FindXULDescriptionData),
    3996                 :     SIMPLE_XUL_CREATE(menu, NS_NewMenuFrame),
    3997                 :     SIMPLE_XUL_CREATE(menubutton, NS_NewMenuFrame),
    3998                 :     SIMPLE_XUL_CREATE(menuitem, NS_NewMenuItemFrame),
    3999                 : #ifdef XP_MACOSX
    4000                 :     SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
    4001                 : #else
    4002                 :     SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
    4003                 : #endif /* XP_MACOSX */
    4004                 :     SIMPLE_TAG_CHAIN(popupgroup, nsCSSFrameConstructor::FindPopupGroupData),
    4005                 :     SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
    4006                 :     SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
    4007                 :     SIMPLE_XUL_CREATE(browser, NS_NewSubDocumentFrame),
    4008                 :     SIMPLE_XUL_CREATE(progressmeter, NS_NewProgressMeterFrame),
    4009                 :     SIMPLE_XUL_CREATE(splitter, NS_NewSplitterFrame),
    4010                 :     SIMPLE_TAG_CHAIN(listboxbody,
    4011                 :                      nsCSSFrameConstructor::FindXULListBoxBodyData),
    4012                 :     SIMPLE_TAG_CHAIN(listitem, nsCSSFrameConstructor::FindXULListItemData),
    4013                 : #endif /* MOZ_XUL */
    4014                 :     SIMPLE_XUL_CREATE(slider, NS_NewSliderFrame),
    4015                 :     SIMPLE_XUL_CREATE(scrollbar, NS_NewScrollbarFrame),
    4016                 :     SIMPLE_XUL_CREATE(scrollbarbutton, NS_NewScrollbarButtonFrame)
    4017                 : };
    4018                 : 
    4019                 :   return FindDataByTag(aTag, aElement, aStyleContext, sXULTagData,
    4020               0 :                        ArrayLength(sXULTagData));
    4021                 : }
    4022                 : 
    4023                 : #ifdef MOZ_XUL
    4024                 : /* static */
    4025                 : const nsCSSFrameConstructor::FrameConstructionData*
    4026               0 : nsCSSFrameConstructor::FindPopupGroupData(Element* aElement,
    4027                 :                                           nsStyleContext* /* unused */)
    4028                 : {
    4029               0 :   if (!aElement->IsRootOfNativeAnonymousSubtree()) {
    4030               0 :     return nsnull;
    4031                 :   }
    4032                 : 
    4033                 :   static const FrameConstructionData sPopupSetData =
    4034                 :     SIMPLE_XUL_FCDATA(NS_NewPopupSetFrame);
    4035               0 :   return &sPopupSetData;
    4036                 : }
    4037                 : 
    4038                 : /* static */
    4039                 : const nsCSSFrameConstructor::FrameConstructionData
    4040                 : nsCSSFrameConstructor::sXULTextBoxData = SIMPLE_XUL_FCDATA(NS_NewTextBoxFrame);
    4041                 : 
    4042                 : /* static */
    4043                 : const nsCSSFrameConstructor::FrameConstructionData*
    4044               0 : nsCSSFrameConstructor::FindXULLabelData(Element* aElement,
    4045                 :                                         nsStyleContext* /* unused */)
    4046                 : {
    4047               0 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4048               0 :     return &sXULTextBoxData;
    4049                 :   }
    4050                 : 
    4051                 :   static const FrameConstructionData sLabelData =
    4052                 :     SIMPLE_XUL_FCDATA(NS_NewXULLabelFrame);
    4053               0 :   return &sLabelData;
    4054                 : }
    4055                 : 
    4056                 : static nsIFrame*
    4057               0 : NS_NewXULDescriptionFrame(nsIPresShell* aPresShell, nsStyleContext *aContext)
    4058                 : {
    4059                 :   // XXXbz do we really need to set those flags?  If the parent is not
    4060                 :   // a block we'll get them anyway, and if it is, do we want them?
    4061                 :   return NS_NewBlockFrame(aPresShell, aContext,
    4062               0 :                           NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT);
    4063                 : }
    4064                 : 
    4065                 : /* static */
    4066                 : const nsCSSFrameConstructor::FrameConstructionData*
    4067               0 : nsCSSFrameConstructor::FindXULDescriptionData(Element* aElement,
    4068                 :                                               nsStyleContext* /* unused */)
    4069                 : {
    4070               0 :   if (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::value)) {
    4071               0 :     return &sXULTextBoxData;
    4072                 :   }
    4073                 : 
    4074                 :   static const FrameConstructionData sDescriptionData =
    4075                 :     SIMPLE_XUL_FCDATA(NS_NewXULDescriptionFrame);
    4076               0 :   return &sDescriptionData;
    4077                 : }
    4078                 : 
    4079                 : #ifdef XP_MACOSX
    4080                 : /* static */
    4081                 : const nsCSSFrameConstructor::FrameConstructionData*
    4082                 : nsCSSFrameConstructor::FindXULMenubarData(Element* aElement,
    4083                 :                                           nsStyleContext* aStyleContext)
    4084                 : {
    4085                 :   nsCOMPtr<nsISupports> container =
    4086                 :     aStyleContext->PresContext()->GetContainer();
    4087                 :   if (container) {
    4088                 :     nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
    4089                 :     if (treeItem) {
    4090                 :       PRInt32 type;
    4091                 :       treeItem->GetItemType(&type);
    4092                 :       if (nsIDocShellTreeItem::typeChrome == type) {
    4093                 :         nsCOMPtr<nsIDocShellTreeItem> parent;
    4094                 :         treeItem->GetParent(getter_AddRefs(parent));
    4095                 :         if (!parent) {
    4096                 :           // This is the root.  Suppress the menubar, since on Mac
    4097                 :           // window menus are not attached to the window.
    4098                 :           static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    4099                 :           return &sSuppressData;
    4100                 :         }
    4101                 :       }
    4102                 :     }
    4103                 :   }
    4104                 : 
    4105                 :   static const FrameConstructionData sMenubarData =
    4106                 :     SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
    4107                 :   return &sMenubarData;
    4108                 : }
    4109                 : #endif /* XP_MACOSX */
    4110                 : 
    4111                 : /* static */
    4112                 : const nsCSSFrameConstructor::FrameConstructionData*
    4113               0 : nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
    4114                 :                                               nsStyleContext* aStyleContext)
    4115                 : {
    4116               0 :   if (aStyleContext->GetStyleDisplay()->mDisplay !=
    4117                 :         NS_STYLE_DISPLAY_GRID_GROUP) {
    4118               0 :     return nsnull;
    4119                 :   }
    4120                 : 
    4121                 :   static const FrameConstructionData sListBoxBodyData =
    4122                 :     SCROLLABLE_XUL_FCDATA(NS_NewListBoxBodyFrame);
    4123               0 :   return &sListBoxBodyData;
    4124                 : }
    4125                 : 
    4126                 : /* static */
    4127                 : const nsCSSFrameConstructor::FrameConstructionData*
    4128               0 : nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
    4129                 :                                            nsStyleContext* aStyleContext)
    4130                 : {
    4131               0 :   if (aStyleContext->GetStyleDisplay()->mDisplay !=
    4132                 :         NS_STYLE_DISPLAY_GRID_LINE) {
    4133               0 :     return nsnull;
    4134                 :   }
    4135                 : 
    4136                 :   static const FrameConstructionData sListItemData =
    4137                 :     SCROLLABLE_XUL_FCDATA(NS_NewListItemFrame);
    4138               0 :   return &sListItemData;
    4139                 : }
    4140                 : 
    4141                 : #endif /* MOZ_XUL */
    4142                 : 
    4143                 : /* static */
    4144                 : const nsCSSFrameConstructor::FrameConstructionData*
    4145               0 : nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
    4146                 :                                           Element* aElement,
    4147                 :                                           nsStyleContext* aStyleContext)
    4148                 : {
    4149                 :   static const FrameConstructionDataByInt sXULDisplayData[] = {
    4150                 :     SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX,
    4151                 :                                                NS_NewBoxFrame),
    4152                 :     SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX,
    4153                 :                                                NS_NewBoxFrame),
    4154                 : #ifdef MOZ_XUL
    4155                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_GRID, NS_NewGridBoxFrame),
    4156                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GRID, NS_NewGridBoxFrame),
    4157                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GRID_GROUP,
    4158                 :                               NS_NewGridRowGroupFrame),
    4159                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GRID_LINE,
    4160                 :                               NS_NewGridRowLeafFrame),
    4161                 :     SIMPLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_DECK, NS_NewDeckFrame),
    4162                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GROUPBOX, NS_NewGroupBoxFrame),
    4163                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_STACK, NS_NewStackFrame),
    4164                 :     SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_STACK, NS_NewStackFrame),
    4165                 :     { NS_STYLE_DISPLAY_POPUP,
    4166                 :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
    4167                 :                   FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame) }
    4168                 : #endif /* MOZ_XUL */
    4169                 :   };
    4170                 : 
    4171                 :   // Processing by display here:
    4172                 :   return FindDataByInt(aDisplay->mDisplay, aElement, aStyleContext,
    4173               0 :                        sXULDisplayData, ArrayLength(sXULDisplayData));
    4174                 : }
    4175                 : 
    4176                 : already_AddRefed<nsStyleContext>
    4177               0 : nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
    4178                 :                                                 nsIContent*              aContent,
    4179                 :                                                 nsStyleContext*          aContentStyle,
    4180                 :                                                 nsIFrame*                aParentFrame,
    4181                 :                                                 nsIAtom*                 aScrolledPseudo,
    4182                 :                                                 bool                     aIsRoot,
    4183                 :                                                 nsIFrame*&               aNewFrame)
    4184                 : {
    4185               0 :   nsIFrame* gfxScrollFrame = aNewFrame;
    4186                 : 
    4187               0 :   nsFrameItems anonymousItems;
    4188                 : 
    4189               0 :   nsRefPtr<nsStyleContext> contentStyle = aContentStyle;
    4190                 : 
    4191               0 :   if (!gfxScrollFrame) {
    4192                 :     // Build a XULScrollFrame when the child is a box, otherwise an
    4193                 :     // HTMLScrollFrame
    4194                 :     // XXXbz this is the lone remaining consumer of IsXULDisplayType.
    4195                 :     // I wonder whether we can eliminate that somehow.
    4196               0 :     if (IsXULDisplayType(aContentStyle->GetStyleDisplay())) {
    4197               0 :       gfxScrollFrame = NS_NewXULScrollFrame(mPresShell, contentStyle, aIsRoot);
    4198                 :     } else {
    4199               0 :       gfxScrollFrame = NS_NewHTMLScrollFrame(mPresShell, contentStyle, aIsRoot);
    4200                 :     }
    4201                 : 
    4202               0 :     InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, gfxScrollFrame);
    4203                 :   }
    4204                 : 
    4205                 :   // if there are any anonymous children for the scroll frame, create
    4206                 :   // frames for them.
    4207                 :   // Pass a null pending binding: we don't care how constructors for any of
    4208                 :   // this anonymous content order with anything else.  It's never been
    4209                 :   // consistent anyway.
    4210                 :   CreateAnonymousFrames(aState, aContent, gfxScrollFrame, nsnull,
    4211               0 :                         anonymousItems);
    4212                 : 
    4213               0 :   aNewFrame = gfxScrollFrame;
    4214                 : 
    4215                 :   // we used the style that was passed in. So resolve another one.
    4216               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    4217                 :   nsStyleContext* aScrolledChildStyle =
    4218               0 :     styleSet->ResolveAnonymousBoxStyle(aScrolledPseudo, contentStyle).get();
    4219                 : 
    4220               0 :   if (gfxScrollFrame) {
    4221               0 :      gfxScrollFrame->SetInitialChildList(kPrincipalList, anonymousItems);
    4222                 :   }
    4223                 : 
    4224               0 :   return aScrolledChildStyle;
    4225                 : }
    4226                 : 
    4227                 : void
    4228               0 : nsCSSFrameConstructor::FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
    4229                 :                                                  nsIFrame* aScrolledFrame)
    4230                 : {
    4231               0 :   nsFrameList scrolled(aScrolledFrame, aScrolledFrame);
    4232               0 :   aScrollFrame->AppendFrames(kPrincipalList, scrolled);
    4233               0 : }
    4234                 : 
    4235                 : 
    4236                 : /**
    4237                 :  * Called to wrap a gfx scrollframe around a frame. The hierarchy will look like this
    4238                 :  *
    4239                 :  * ------- for gfx scrollbars ------
    4240                 :  *
    4241                 :  *
    4242                 :  *            ScrollFrame
    4243                 :  *                 ^
    4244                 :  *                 |
    4245                 :  *               Frame (scrolled frame you passed in)
    4246                 :  *
    4247                 :  *
    4248                 :  *-----------------------------------
    4249                 :  * LEGEND:
    4250                 :  * 
    4251                 :  * ScrollFrame: This is a frame that manages gfx cross platform frame based scrollbars.
    4252                 :  *
    4253                 :  * @param aContent the content node of the child to wrap.
    4254                 :  * @param aScrolledFrame The frame of the content to wrap. This should not be
    4255                 :  *                    Initialized. This method will initialize it with a scrolled pseudo
    4256                 :  *                    and no nsIContent. The content will be attached to the scrollframe 
    4257                 :  *                    returned.
    4258                 :  * @param aContentStyle the style context that has already been resolved for the content being passed in.
    4259                 :  *
    4260                 :  * @param aParentFrame The parent to attach the scroll frame to
    4261                 :  *
    4262                 :  * @param aNewFrame The new scrollframe or gfx scrollframe that we create. It will contain the
    4263                 :  *                  scrolled frame you passed in. (returned)
    4264                 :  *                  If this is not null, we'll just use it
    4265                 :  * @param aScrolledContentStyle the style that was resolved for the scrolled frame. (returned)
    4266                 :  */
    4267                 : nsresult
    4268               0 : nsCSSFrameConstructor::BuildScrollFrame(nsFrameConstructorState& aState,
    4269                 :                                         nsIContent*              aContent,
    4270                 :                                         nsStyleContext*          aContentStyle,
    4271                 :                                         nsIFrame*                aScrolledFrame,
    4272                 :                                         nsIFrame*                aParentFrame,
    4273                 :                                         nsIFrame*&               aNewFrame)
    4274                 : {
    4275                 :     nsRefPtr<nsStyleContext> scrolledContentStyle =
    4276                 :       BeginBuildingScrollFrame(aState, aContent, aContentStyle, aParentFrame,
    4277                 :                                nsCSSAnonBoxes::scrolledContent,
    4278               0 :                                false, aNewFrame);
    4279                 :     
    4280               0 :     aScrolledFrame->SetStyleContextWithoutNotification(scrolledContentStyle);
    4281               0 :     InitAndRestoreFrame(aState, aContent, aNewFrame, nsnull, aScrolledFrame);
    4282                 : 
    4283               0 :     FinishBuildingScrollFrame(aNewFrame, aScrolledFrame);
    4284               0 :     return NS_OK;
    4285                 : }
    4286                 : 
    4287                 : const nsCSSFrameConstructor::FrameConstructionData*
    4288               0 : nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
    4289                 :                                        Element* aElement,
    4290                 :                                        nsStyleContext* aStyleContext)
    4291                 : {
    4292                 :   PR_STATIC_ASSERT(eParentTypeCount < (1 << (32 - FCDATA_PARENT_TYPE_OFFSET)));
    4293                 : 
    4294                 :   // The style system ensures that floated and positioned frames are
    4295                 :   // block-level.
    4296               0 :   NS_ASSERTION(!(aDisplay->IsFloating() ||
    4297                 :                  aDisplay->IsAbsolutelyPositioned()) ||
    4298                 :                aDisplay->IsBlockOutside(),
    4299                 :                "Style system did not apply CSS2.1 section 9.7 fixups");
    4300                 : 
    4301                 :   // If this is "body", try propagating its scroll style to the viewport
    4302                 :   // Note that we need to do this even if the body is NOT scrollable;
    4303                 :   // it might have dynamically changed from scrollable to not scrollable,
    4304                 :   // and that might need to be propagated.
    4305                 :   // XXXbz is this the right place to do this?  If this code moves,
    4306                 :   // make this function static.
    4307               0 :   bool propagatedScrollToViewport = false;
    4308               0 :   if (aElement->IsHTML(nsGkAtoms::body)) {
    4309                 :     propagatedScrollToViewport =
    4310               0 :       PropagateScrollToViewport() == aElement;
    4311                 :   }
    4312                 : 
    4313               0 :   NS_ASSERTION(!propagatedScrollToViewport ||
    4314                 :                !mPresShell->GetPresContext()->IsPaginated(),
    4315                 :                "Shouldn't propagate scroll in paginated contexts");
    4316                 : 
    4317                 :   // If the frame is a block-level frame and is scrollable, then wrap it in a
    4318                 :   // scroll frame.
    4319                 :   // XXX Ignore tables for the time being
    4320                 :   // XXXbz it would be nice to combine this with the other block
    4321                 :   // case... Think about how do do this?
    4322               0 :   if (aDisplay->IsBlockInside() &&
    4323               0 :       aDisplay->IsScrollableOverflow() &&
    4324               0 :       !propagatedScrollToViewport) {
    4325                 :     // Except we don't want to do that for paginated contexts for
    4326                 :     // frames that are block-outside and aren't frames for native
    4327                 :     // anonymous stuff.
    4328               0 :     if (mPresShell->GetPresContext()->IsPaginated() &&
    4329               0 :         aDisplay->IsBlockOutside() &&
    4330               0 :         !aElement->IsInNativeAnonymousSubtree()) {
    4331                 :       static const FrameConstructionData sForcedNonScrollableBlockData =
    4332                 :         FULL_CTOR_FCDATA(FCDATA_FORCED_NON_SCROLLABLE_BLOCK,
    4333                 :                          &nsCSSFrameConstructor::ConstructNonScrollableBlock);
    4334               0 :       return &sForcedNonScrollableBlockData;
    4335                 :     }
    4336                 : 
    4337                 :     static const FrameConstructionData sScrollableBlockData =
    4338                 :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructScrollableBlock);
    4339               0 :     return &sScrollableBlockData;
    4340                 :   }
    4341                 : 
    4342                 :   // Handle various non-scrollable blocks
    4343               0 :   if (aDisplay->IsBlockInside()) {
    4344                 :     static const FrameConstructionData sNonScrollableBlockData =
    4345                 :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
    4346               0 :     return &sNonScrollableBlockData;
    4347                 :   }
    4348                 : 
    4349                 :   static const FrameConstructionDataByInt sDisplayData[] = {
    4350                 :     // To keep the hash table small don't add inline frames (they're
    4351                 :     // typically things like FONT and B), because we can quickly
    4352                 :     // find them if we need to.
    4353                 :     // XXXbz the "quickly" part is a bald-faced lie!
    4354                 :     { NS_STYLE_DISPLAY_INLINE,
    4355                 :       FULL_CTOR_FCDATA(FCDATA_IS_INLINE | FCDATA_IS_LINE_PARTICIPANT,
    4356                 :                        &nsCSSFrameConstructor::ConstructInline) },
    4357                 :     { NS_STYLE_DISPLAY_TABLE,
    4358                 :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
    4359                 :     { NS_STYLE_DISPLAY_INLINE_TABLE,
    4360                 :       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
    4361                 :     { NS_STYLE_DISPLAY_TABLE_CAPTION,
    4362                 :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_ALLOW_BLOCK_STYLES |
    4363                 :                   FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
    4364                 :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4365                 :                   NS_NewTableCaptionFrame) },
    4366                 :     { NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
    4367                 :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4368                 :                   FCDATA_SKIP_ABSPOS_PUSH |
    4369                 :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4370                 :                   NS_NewTableRowGroupFrame) },
    4371                 :     { NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
    4372                 :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4373                 :                   FCDATA_SKIP_ABSPOS_PUSH |
    4374                 :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4375                 :                   NS_NewTableRowGroupFrame) },
    4376                 :     { NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
    4377                 :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4378                 :                   FCDATA_SKIP_ABSPOS_PUSH |
    4379                 :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4380                 :                   NS_NewTableRowGroupFrame) },
    4381                 :     { NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
    4382                 :       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
    4383                 :                   FCDATA_SKIP_ABSPOS_PUSH |
    4384                 :                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    4385                 :                   NS_NewTableColGroupFrame) },
    4386                 :     { NS_STYLE_DISPLAY_TABLE_COLUMN,
    4387                 :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4388                 :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeColGroup),
    4389                 :                        &nsCSSFrameConstructor::ConstructTableCol) },
    4390                 :     { NS_STYLE_DISPLAY_TABLE_ROW,
    4391                 :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4392                 :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
    4393                 :                        &nsCSSFrameConstructor::ConstructTableRow) },
    4394                 :     { NS_STYLE_DISPLAY_TABLE_CELL,
    4395                 :       FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART |
    4396                 :                        FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
    4397                 :                        &nsCSSFrameConstructor::ConstructTableCell) }
    4398                 :   };
    4399                 : 
    4400                 :   return FindDataByInt(aDisplay->mDisplay, aElement, aStyleContext,
    4401               0 :                        sDisplayData, ArrayLength(sDisplayData));
    4402                 : }
    4403                 : 
    4404                 : nsresult
    4405               0 : nsCSSFrameConstructor::ConstructScrollableBlock(nsFrameConstructorState& aState,
    4406                 :                                                 FrameConstructionItem&   aItem,
    4407                 :                                                 nsIFrame*                aParentFrame,
    4408                 :                                                 const nsStyleDisplay*    aDisplay,
    4409                 :                                                 nsFrameItems&            aFrameItems,
    4410                 :                                                 nsIFrame**               aNewFrame)
    4411                 : {
    4412               0 :   nsIContent* const content = aItem.mContent;
    4413               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    4414                 : 
    4415               0 :   *aNewFrame = nsnull;
    4416                 :   nsRefPtr<nsStyleContext> scrolledContentStyle
    4417                 :     = BeginBuildingScrollFrame(aState, content, styleContext,
    4418                 :                                aState.GetGeometricParent(aDisplay, aParentFrame),
    4419                 :                                nsCSSAnonBoxes::scrolledContent,
    4420               0 :                                false, *aNewFrame);
    4421                 : 
    4422                 :   // Create our block frame
    4423                 :   // pass a temporary stylecontext, the correct one will be set later
    4424                 :   nsIFrame* scrolledFrame =
    4425               0 :     NS_NewBlockFormattingContext(mPresShell, styleContext);
    4426                 : 
    4427               0 :   nsFrameItems blockItem;
    4428                 :   nsresult rv = ConstructBlock(aState,
    4429                 :                                scrolledContentStyle->GetStyleDisplay(), content,
    4430                 :                                *aNewFrame, *aNewFrame, scrolledContentStyle,
    4431               0 :                                &scrolledFrame, blockItem, aDisplay->IsPositioned(),
    4432               0 :                                aItem.mPendingBinding);
    4433               0 :   if (NS_UNLIKELY(NS_FAILED(rv))) {
    4434                 :     // XXXbz any cleanup needed here?
    4435               0 :     return rv;
    4436                 :   }
    4437                 : 
    4438               0 :   NS_ASSERTION(blockItem.FirstChild() == scrolledFrame,
    4439                 :                "Scrollframe's frameItems should be exactly the scrolled frame");
    4440               0 :   FinishBuildingScrollFrame(*aNewFrame, scrolledFrame);
    4441                 : 
    4442                 :   rv = aState.AddChild(*aNewFrame, aFrameItems, content, styleContext,
    4443               0 :                        aParentFrame);
    4444               0 :   return rv;
    4445                 : }
    4446                 : 
    4447                 : nsresult
    4448               0 : nsCSSFrameConstructor::ConstructNonScrollableBlock(nsFrameConstructorState& aState,
    4449                 :                                                    FrameConstructionItem&   aItem,
    4450                 :                                                    nsIFrame*                aParentFrame,
    4451                 :                                                    const nsStyleDisplay*    aDisplay,
    4452                 :                                                    nsFrameItems&            aFrameItems,
    4453                 :                                                    nsIFrame**               aNewFrame)
    4454                 : {
    4455               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
    4456                 : 
    4457                 :   // We want a block formatting context root in paginated contexts for
    4458                 :   // every block that would be scrollable in a non-paginated context.
    4459                 :   // We mark our blocks with a bit here if this condition is true, so
    4460                 :   // we can check it later in nsFrame::ApplyPaginatedOverflowClipping.
    4461                 :   bool clipPaginatedOverflow =
    4462               0 :     (aItem.mFCData->mBits & FCDATA_FORCED_NON_SCROLLABLE_BLOCK) != 0;
    4463               0 :   if (aDisplay->IsAbsolutelyPositioned() ||
    4464               0 :       aDisplay->IsFloating() ||
    4465                 :       NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay->mDisplay ||
    4466                 :       clipPaginatedOverflow) {
    4467               0 :     *aNewFrame = NS_NewBlockFormattingContext(mPresShell, styleContext);
    4468               0 :     if (clipPaginatedOverflow) {
    4469               0 :       (*aNewFrame)->AddStateBits(NS_BLOCK_CLIP_PAGINATED_OVERFLOW);
    4470                 :     }
    4471                 :   } else {
    4472               0 :     *aNewFrame = NS_NewBlockFrame(mPresShell, styleContext);
    4473                 :   }
    4474                 : 
    4475                 :   return ConstructBlock(aState, aDisplay, aItem.mContent,
    4476                 :                         aState.GetGeometricParent(aDisplay, aParentFrame),
    4477                 :                         aParentFrame, styleContext, aNewFrame,
    4478               0 :                         aFrameItems, aDisplay->IsPositioned(),
    4479               0 :                         aItem.mPendingBinding);
    4480                 : }
    4481                 : 
    4482                 : 
    4483                 : nsresult 
    4484               0 : nsCSSFrameConstructor::InitAndRestoreFrame(const nsFrameConstructorState& aState,
    4485                 :                                            nsIContent*              aContent,
    4486                 :                                            nsIFrame*                aParentFrame,
    4487                 :                                            nsIFrame*                aPrevInFlow,
    4488                 :                                            nsIFrame*                aNewFrame,
    4489                 :                                            bool                     aAllowCounters)
    4490                 : {
    4491               0 :   NS_PRECONDITION(mUpdateCount != 0,
    4492                 :                   "Should be in an update while creating frames");
    4493                 :   
    4494               0 :   nsresult rv = NS_OK;
    4495                 :   
    4496               0 :   NS_ASSERTION(aNewFrame, "Null frame cannot be initialized");
    4497               0 :   if (!aNewFrame)
    4498               0 :     return NS_ERROR_NULL_POINTER;
    4499                 : 
    4500                 :   // Initialize the frame
    4501               0 :   rv = aNewFrame->Init(aContent, aParentFrame, aPrevInFlow);
    4502               0 :   aNewFrame->AddStateBits(aState.mAdditionalStateBits);
    4503                 : 
    4504               0 :   if (aState.mFrameState) {
    4505                 :     // Restore frame state for just the newly created frame.
    4506               0 :     RestoreFrameStateFor(aNewFrame, aState.mFrameState);
    4507                 :   }
    4508                 : 
    4509               0 :   if (aAllowCounters && !aPrevInFlow &&
    4510               0 :       mCounterManager.AddCounterResetsAndIncrements(aNewFrame)) {
    4511               0 :     CountersDirty();
    4512                 :   }
    4513                 : 
    4514               0 :   return rv;
    4515                 : }
    4516                 : 
    4517                 : already_AddRefed<nsStyleContext>
    4518               0 : nsCSSFrameConstructor::ResolveStyleContext(nsIFrame*         aParentFrame,
    4519                 :                                            nsIContent*       aContent,
    4520                 :                                            nsFrameConstructorState* aState)
    4521                 : {
    4522               0 :   nsStyleContext* parentStyleContext = nsnull;
    4523               0 :   NS_ASSERTION(aContent->GetParent(), "Must have parent here");
    4524                 : 
    4525               0 :   aParentFrame = nsFrame::CorrectStyleParentFrame(aParentFrame, nsnull);
    4526                 : 
    4527               0 :   if (aParentFrame) {
    4528                 :     // Resolve the style context based on the content object and the parent
    4529                 :     // style context
    4530               0 :     parentStyleContext = aParentFrame->GetStyleContext();
    4531                 :   } else {
    4532                 :     // Perhaps aParentFrame is a canvasFrame and we're replicating
    4533                 :     // fixed-pos frames.
    4534                 :     // XXX should we create a way to tell ConstructFrame which style
    4535                 :     // context to use, and pass it the style context for the
    4536                 :     // previous page's fixed-pos frame?
    4537                 :   }
    4538                 : 
    4539               0 :   return ResolveStyleContext(parentStyleContext, aContent, aState);
    4540                 : }
    4541                 : 
    4542                 : already_AddRefed<nsStyleContext>
    4543               0 : nsCSSFrameConstructor::ResolveStyleContext(nsStyleContext* aParentStyleContext,
    4544                 :                                            nsIContent* aContent,
    4545                 :                                            nsFrameConstructorState* aState)
    4546                 : {
    4547               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    4548               0 :   aContent->OwnerDoc()->FlushPendingLinkUpdates();
    4549                 :   
    4550               0 :   if (aContent->IsElement()) {
    4551               0 :     if (aState) {
    4552                 :       return styleSet->ResolveStyleFor(aContent->AsElement(),
    4553                 :                                        aParentStyleContext,
    4554               0 :                                        aState->mTreeMatchContext);
    4555                 :     }
    4556               0 :     return styleSet->ResolveStyleFor(aContent->AsElement(), aParentStyleContext);
    4557                 : 
    4558                 :   }
    4559                 : 
    4560               0 :   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
    4561                 :                "shouldn't waste time creating style contexts for "
    4562                 :                "comments and processing instructions");
    4563                 : 
    4564               0 :   return styleSet->ResolveStyleForNonElement(aParentStyleContext);
    4565                 : }
    4566                 : 
    4567                 : // MathML Mod - RBS
    4568                 : nsresult
    4569               0 : nsCSSFrameConstructor::FlushAccumulatedBlock(nsFrameConstructorState& aState,
    4570                 :                                              nsIContent* aContent,
    4571                 :                                              nsIFrame* aParentFrame,
    4572                 :                                              nsFrameItems* aBlockItems,
    4573                 :                                              nsFrameItems* aNewItems)
    4574                 : {
    4575               0 :   if (aBlockItems->IsEmpty()) {
    4576                 :     // Nothing to do
    4577               0 :     return NS_OK;
    4578                 :   }
    4579                 : 
    4580                 :   nsStyleContext* parentContext =
    4581                 :     nsFrame::CorrectStyleParentFrame(aParentFrame,
    4582               0 :                                      nsCSSAnonBoxes::mozMathMLAnonymousBlock)->GetStyleContext(); 
    4583               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    4584               0 :   nsRefPtr<nsStyleContext> blockContext;
    4585                 :   blockContext = styleSet->
    4586                 :     ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozMathMLAnonymousBlock,
    4587               0 :                              parentContext);
    4588                 : 
    4589                 :   // then, create a block frame that will wrap the child frames. Make it a
    4590                 :   // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
    4591                 :   // is not a suitable block.
    4592                 :   nsIFrame* blockFrame = NS_NewMathMLmathBlockFrame(mPresShell, blockContext,
    4593               0 :                           NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT);
    4594               0 :   if (NS_UNLIKELY(!blockFrame))
    4595               0 :     return NS_ERROR_OUT_OF_MEMORY;
    4596                 : 
    4597               0 :   InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, blockFrame);
    4598               0 :   ReparentFrames(this, blockFrame, *aBlockItems);
    4599                 :   // abs-pos and floats are disabled in MathML children so we don't have to
    4600                 :   // worry about messing up those.
    4601               0 :   blockFrame->SetInitialChildList(kPrincipalList, *aBlockItems);
    4602               0 :   NS_ASSERTION(aBlockItems->IsEmpty(), "What happened?");
    4603               0 :   aBlockItems->Clear();
    4604               0 :   aNewItems->AddChild(blockFrame);
    4605               0 :   return NS_OK;
    4606                 : }
    4607                 : 
    4608                 : // Only <math> elements can be floated or positioned.  All other MathML
    4609                 : // should be in-flow.
    4610                 : #define SIMPLE_MATHML_CREATE(_tag, _func)                               \
    4611                 :   { &nsGkAtoms::_tag,                                                   \
    4612                 :       FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                         \
    4613                 :                   FCDATA_FORCE_NULL_ABSPOS_CONTAINER |                  \
    4614                 :                   FCDATA_WRAP_KIDS_IN_BLOCKS, _func) }
    4615                 : 
    4616                 : /* static */
    4617                 : const nsCSSFrameConstructor::FrameConstructionData*
    4618               0 : nsCSSFrameConstructor::FindMathMLData(Element* aElement,
    4619                 :                                       nsIAtom* aTag,
    4620                 :                                       PRInt32 aNameSpaceID,
    4621                 :                                       nsStyleContext* aStyleContext)
    4622                 : {
    4623                 :   // Make sure that we remain confined in the MathML world
    4624               0 :   if (aNameSpaceID != kNameSpaceID_MathML) 
    4625               0 :     return nsnull;
    4626                 : 
    4627                 :   // Handle <math> specially, because it sometimes produces inlines
    4628               0 :   if (aTag == nsGkAtoms::math) {
    4629                 :     // This needs to match the test in EnsureBlockDisplay in
    4630                 :     // nsRuleNode.cpp.  Though the behavior here for the display:table
    4631                 :     // case is pretty weird...
    4632               0 :     if (aStyleContext->GetStyleDisplay()->IsBlockOutside()) {
    4633                 :       static const FrameConstructionData sBlockMathData =
    4634                 :         FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    4635                 :                     FCDATA_WRAP_KIDS_IN_BLOCKS,
    4636                 :                     NS_CreateNewMathMLmathBlockFrame);
    4637               0 :       return &sBlockMathData;
    4638                 :     }
    4639                 : 
    4640                 :     static const FrameConstructionData sInlineMathData =
    4641                 :       FCDATA_DECL(FCDATA_FORCE_NULL_ABSPOS_CONTAINER |
    4642                 :                   FCDATA_IS_LINE_PARTICIPANT |
    4643                 :                   FCDATA_WRAP_KIDS_IN_BLOCKS,
    4644                 :                   NS_NewMathMLmathInlineFrame);
    4645               0 :     return &sInlineMathData;
    4646                 :   }
    4647                 :       
    4648                 : 
    4649                 :   static const FrameConstructionDataByTag sMathMLData[] = {
    4650                 :     SIMPLE_MATHML_CREATE(mi_, NS_NewMathMLTokenFrame),
    4651                 :     SIMPLE_MATHML_CREATE(mn_, NS_NewMathMLTokenFrame),
    4652                 :     SIMPLE_MATHML_CREATE(ms_, NS_NewMathMLTokenFrame),
    4653                 :     SIMPLE_MATHML_CREATE(mtext_, NS_NewMathMLTokenFrame),
    4654                 :     SIMPLE_MATHML_CREATE(mo_, NS_NewMathMLmoFrame),
    4655                 :     SIMPLE_MATHML_CREATE(mfrac_, NS_NewMathMLmfracFrame),
    4656                 :     SIMPLE_MATHML_CREATE(msup_, NS_NewMathMLmsupFrame),
    4657                 :     SIMPLE_MATHML_CREATE(msub_, NS_NewMathMLmsubFrame),
    4658                 :     SIMPLE_MATHML_CREATE(msubsup_, NS_NewMathMLmsubsupFrame),
    4659                 :     SIMPLE_MATHML_CREATE(munder_, NS_NewMathMLmunderoverFrame),
    4660                 :     SIMPLE_MATHML_CREATE(mover_, NS_NewMathMLmunderoverFrame),
    4661                 :     SIMPLE_MATHML_CREATE(munderover_, NS_NewMathMLmunderoverFrame),
    4662                 :     SIMPLE_MATHML_CREATE(mphantom_, NS_NewMathMLmphantomFrame),
    4663                 :     SIMPLE_MATHML_CREATE(mpadded_, NS_NewMathMLmpaddedFrame),
    4664                 :     SIMPLE_MATHML_CREATE(mspace_, NS_NewMathMLmspaceFrame),
    4665                 :     SIMPLE_MATHML_CREATE(none, NS_NewMathMLmspaceFrame),
    4666                 :     SIMPLE_MATHML_CREATE(mprescripts_, NS_NewMathMLmspaceFrame),
    4667                 :     SIMPLE_MATHML_CREATE(mfenced_, NS_NewMathMLmfencedFrame),
    4668                 :     SIMPLE_MATHML_CREATE(mmultiscripts_, NS_NewMathMLmmultiscriptsFrame),
    4669                 :     SIMPLE_MATHML_CREATE(mstyle_, NS_NewMathMLmstyleFrame),
    4670                 :     SIMPLE_MATHML_CREATE(msqrt_, NS_NewMathMLmsqrtFrame),
    4671                 :     SIMPLE_MATHML_CREATE(mroot_, NS_NewMathMLmrootFrame),
    4672                 :     SIMPLE_MATHML_CREATE(maction_, NS_NewMathMLmactionFrame),
    4673                 :     SIMPLE_MATHML_CREATE(mrow_, NS_NewMathMLmrowFrame),
    4674                 :     SIMPLE_MATHML_CREATE(merror_, NS_NewMathMLmrowFrame),
    4675                 :     SIMPLE_MATHML_CREATE(menclose_, NS_NewMathMLmencloseFrame),
    4676                 :     SIMPLE_MATHML_CREATE(semantics_, NS_NewMathMLsemanticsFrame)
    4677                 :   };
    4678                 : 
    4679                 :   return FindDataByTag(aTag, aElement, aStyleContext, sMathMLData,
    4680               0 :                        ArrayLength(sMathMLData));
    4681                 : }
    4682                 : 
    4683                 : // Only outer <svg> elements can be floated or positioned.  All other SVG
    4684                 : // should be in-flow.
    4685                 : #define SIMPLE_SVG_FCDATA(_func)                                        \
    4686                 :   FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW |                             \
    4687                 :               FCDATA_SKIP_ABSPOS_PUSH |                                 \
    4688                 :               FCDATA_DISALLOW_GENERATED_CONTENT,  _func)
    4689                 : #define SIMPLE_SVG_CREATE(_tag, _func)            \
    4690                 :   { &nsGkAtoms::_tag, SIMPLE_SVG_FCDATA(_func) }
    4691                 : 
    4692                 : static bool
    4693               0 : IsFilterPrimitiveChildTag(const nsIAtom* aTag)
    4694                 : {
    4695                 :   return aTag == nsGkAtoms::feDistantLight ||
    4696                 :          aTag == nsGkAtoms::fePointLight ||
    4697                 :          aTag == nsGkAtoms::feSpotLight ||
    4698                 :          aTag == nsGkAtoms::feFuncR ||
    4699                 :          aTag == nsGkAtoms::feFuncG ||
    4700                 :          aTag == nsGkAtoms::feFuncB ||
    4701                 :          aTag == nsGkAtoms::feFuncA ||
    4702               0 :          aTag == nsGkAtoms::feMergeNode;
    4703                 : }
    4704                 : 
    4705                 : /* static */
    4706                 : const nsCSSFrameConstructor::FrameConstructionData*
    4707               0 : nsCSSFrameConstructor::FindSVGData(Element* aElement,
    4708                 :                                    nsIAtom* aTag,
    4709                 :                                    PRInt32 aNameSpaceID,
    4710                 :                                    nsIFrame* aParentFrame,
    4711                 :                                    nsStyleContext* aStyleContext)
    4712                 : {
    4713               0 :   if (aNameSpaceID != kNameSpaceID_SVG) {
    4714               0 :     return nsnull;
    4715                 :   }
    4716                 : 
    4717                 :   static const FrameConstructionData sSuppressData = SUPPRESS_FCDATA();
    4718                 :   static const FrameConstructionData sContainerData =
    4719                 :     SIMPLE_SVG_FCDATA(NS_NewSVGContainerFrame);
    4720                 : 
    4721               0 :   bool parentIsSVG = false;
    4722                 :   nsIContent* parentContent =
    4723               0 :     aParentFrame ? aParentFrame->GetContent() : nsnull;
    4724                 :   // XXXbz should this really be based on the XBL-resolved tag of the parent
    4725                 :   // frame's content?  Should it not be based on the type of the parent frame
    4726                 :   // (e.g. whether it's an SVG frame)?
    4727               0 :   if (parentContent) {
    4728                 :     PRInt32 parentNSID;
    4729                 :     nsIAtom* parentTag =
    4730                 :       parentContent->OwnerDoc()->BindingManager()->
    4731               0 :         ResolveTag(parentContent, &parentNSID);
    4732                 : 
    4733                 :     // It's not clear whether the SVG spec intends to allow any SVG
    4734                 :     // content within svg:foreignObject at all (SVG 1.1, section
    4735                 :     // 23.2), but if it does, it better be svg:svg.  So given that
    4736                 :     // we're allowing it, treat it as a non-SVG parent.
    4737                 :     parentIsSVG = parentNSID == kNameSpaceID_SVG &&
    4738               0 :                   parentTag != nsGkAtoms::foreignObject;
    4739                 :   }
    4740                 : 
    4741               0 :   if ((aTag != nsGkAtoms::svg && !parentIsSVG) ||
    4742                 :       (aTag == nsGkAtoms::desc || aTag == nsGkAtoms::title)) {
    4743                 :     // Sections 5.1 and G.4 of SVG 1.1 say that SVG elements other than
    4744                 :     // svg:svg not contained within svg:svg are incorrect, although they
    4745                 :     // don't seem to specify error handling.  Ignore them, since many of
    4746                 :     // our frame classes can't deal.  It *may* be that the document
    4747                 :     // should at that point be considered in error according to F.2, but
    4748                 :     // it's hard to tell.
    4749                 :     //
    4750                 :     // Style mutation can't change this situation, so don't bother
    4751                 :     // adding to the undisplayed content map.
    4752                 :     //
    4753                 :     // We don't currently handle any UI for desc/title
    4754               0 :     return &sSuppressData;
    4755                 :   }
    4756                 : 
    4757                 :   // We don't need frames for animation elements
    4758               0 :   if (aElement->IsNodeOfType(nsINode::eANIMATION)) {
    4759               0 :     return &sSuppressData;
    4760                 :   }
    4761                 : 
    4762               0 :   if (aTag == nsGkAtoms::svg && !parentIsSVG) {
    4763                 :     // We need outer <svg> elements to have an nsSVGOuterSVGFrame regardless
    4764                 :     // of whether they fail conditional processing attributes, since various
    4765                 :     // SVG frames assume that one exists.  We handle the non-rendering
    4766                 :     // of failing outer <svg> element contents like <switch> statements,
    4767                 :     // and do the PassesConditionalProcessingTests call in
    4768                 :     // nsSVGOuterSVGFrame::Init.
    4769                 :     static const FrameConstructionData sOuterSVGData =
    4770                 :       FCDATA_DECL(FCDATA_SKIP_ABSPOS_PUSH | FCDATA_DISALLOW_GENERATED_CONTENT,
    4771                 :                   NS_NewSVGOuterSVGFrame);
    4772               0 :     return &sOuterSVGData;
    4773                 :   }
    4774                 :   
    4775               0 :   nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(aElement));
    4776               0 :   if (tests && !tests->PassesConditionalProcessingTests()) {
    4777                 :     // Elements with failing conditional processing attributes never get
    4778                 :     // rendered.  Note that this is not where we select which frame in a
    4779                 :     // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
    4780               0 :     return &sContainerData;
    4781                 :   }
    4782                 : 
    4783                 :   // Prevent bad frame types being children of filters or parents of filter
    4784                 :   // primitives:
    4785               0 :   bool parentIsFilter = aParentFrame->GetType() == nsGkAtoms::svgFilterFrame;
    4786                 :   nsCOMPtr<nsIDOMSVGFilterPrimitiveStandardAttributes> filterPrimitive =
    4787               0 :     do_QueryInterface(aElement);
    4788               0 :   if ((parentIsFilter && !filterPrimitive) ||
    4789               0 :       (!parentIsFilter && filterPrimitive)) {
    4790               0 :     return &sSuppressData;
    4791                 :   }
    4792                 : 
    4793                 :   // Prevent bad frame types being children of filter primitives or parents of
    4794                 :   // filter primitive children:
    4795                 :   bool parentIsFEContainerFrame =
    4796               0 :     aParentFrame->GetType() == nsGkAtoms::svgFEContainerFrame;
    4797               0 :   if ((parentIsFEContainerFrame && !IsFilterPrimitiveChildTag(aTag)) ||
    4798               0 :       (!parentIsFEContainerFrame && IsFilterPrimitiveChildTag(aTag))) {
    4799               0 :     return &sSuppressData;
    4800                 :   }
    4801                 : 
    4802                 :   // Special cases for text/tspan/textPath, because the kind of frame
    4803                 :   // they get depends on the parent frame.  We ignore 'a' elements when
    4804                 :   // determining the parent, however.
    4805                 :   nsIFrame *ancestorFrame =
    4806               0 :     nsSVGUtils::GetFirstNonAAncestorFrame(aParentFrame);
    4807               0 :   if (ancestorFrame) {
    4808               0 :     if (aTag == nsGkAtoms::tspan || aTag == nsGkAtoms::altGlyph) {
    4809                 :       // tspan and altGlyph must be children of another text content element.
    4810               0 :       nsSVGTextContainerFrame* metrics = do_QueryFrame(ancestorFrame);
    4811               0 :       if (!metrics) {
    4812               0 :         return &sSuppressData;
    4813               0 :       }
    4814               0 :     } else if (aTag == nsGkAtoms::textPath) {
    4815                 :       // textPath must be a child of text.
    4816               0 :       nsIAtom* ancestorFrameType = ancestorFrame->GetType();
    4817               0 :       if (ancestorFrameType != nsGkAtoms::svgTextFrame) {
    4818               0 :         return &sSuppressData;
    4819                 :       }
    4820               0 :     } else if (aTag != nsGkAtoms::a) {
    4821                 :       // Every other element except 'a' must not be a child of a text content
    4822                 :       // element.
    4823               0 :       nsSVGTextContainerFrame* metrics = do_QueryFrame(ancestorFrame);
    4824               0 :       if (metrics) {
    4825               0 :         return &sSuppressData;
    4826                 :       }
    4827                 :     }
    4828                 :   }
    4829                 : 
    4830                 :   static const FrameConstructionDataByTag sSVGData[] = {
    4831                 :     SIMPLE_SVG_CREATE(svg, NS_NewSVGInnerSVGFrame),
    4832                 :     SIMPLE_SVG_CREATE(g, NS_NewSVGGFrame),
    4833                 :     SIMPLE_SVG_CREATE(svgSwitch, NS_NewSVGSwitchFrame),
    4834                 :     SIMPLE_SVG_CREATE(polygon, NS_NewSVGPathGeometryFrame),
    4835                 :     SIMPLE_SVG_CREATE(polyline, NS_NewSVGPathGeometryFrame),
    4836                 :     SIMPLE_SVG_CREATE(circle, NS_NewSVGPathGeometryFrame),
    4837                 :     SIMPLE_SVG_CREATE(ellipse, NS_NewSVGPathGeometryFrame),
    4838                 :     SIMPLE_SVG_CREATE(line, NS_NewSVGPathGeometryFrame),
    4839                 :     SIMPLE_SVG_CREATE(rect, NS_NewSVGPathGeometryFrame),
    4840                 :     SIMPLE_SVG_CREATE(path, NS_NewSVGPathGeometryFrame),
    4841                 :     SIMPLE_SVG_CREATE(defs, NS_NewSVGContainerFrame),
    4842                 :     SIMPLE_SVG_CREATE(generic, NS_NewSVGGenericContainerFrame),
    4843                 :     { &nsGkAtoms::foreignObject,
    4844                 :       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_DISALLOW_OUT_OF_FLOW,
    4845                 :                                  NS_NewSVGForeignObjectFrame,
    4846                 :                                  nsCSSAnonBoxes::mozSVGForeignContent) },
    4847                 :     SIMPLE_SVG_CREATE(a, NS_NewSVGAFrame),
    4848                 :     SIMPLE_SVG_CREATE(altGlyph, NS_NewSVGTSpanFrame),
    4849                 :     SIMPLE_SVG_CREATE(text, NS_NewSVGTextFrame),
    4850                 :     SIMPLE_SVG_CREATE(tspan, NS_NewSVGTSpanFrame),
    4851                 :     SIMPLE_SVG_CREATE(linearGradient, NS_NewSVGLinearGradientFrame),
    4852                 :     SIMPLE_SVG_CREATE(radialGradient, NS_NewSVGRadialGradientFrame),
    4853                 :     SIMPLE_SVG_CREATE(stop, NS_NewSVGStopFrame),
    4854                 :     SIMPLE_SVG_CREATE(use, NS_NewSVGUseFrame),
    4855                 :     SIMPLE_SVG_CREATE(marker, NS_NewSVGMarkerFrame),
    4856                 :     SIMPLE_SVG_CREATE(image, NS_NewSVGImageFrame),
    4857                 :     SIMPLE_SVG_CREATE(clipPath, NS_NewSVGClipPathFrame),
    4858                 :     SIMPLE_SVG_CREATE(textPath, NS_NewSVGTextPathFrame),
    4859                 :     SIMPLE_SVG_CREATE(filter, NS_NewSVGFilterFrame),
    4860                 :     SIMPLE_SVG_CREATE(pattern, NS_NewSVGPatternFrame),
    4861                 :     SIMPLE_SVG_CREATE(mask, NS_NewSVGMaskFrame),
    4862                 :     SIMPLE_SVG_CREATE(feDistantLight, NS_NewSVGFEUnstyledLeafFrame),
    4863                 :     SIMPLE_SVG_CREATE(fePointLight, NS_NewSVGFEUnstyledLeafFrame),
    4864                 :     SIMPLE_SVG_CREATE(feSpotLight, NS_NewSVGFEUnstyledLeafFrame),
    4865                 :     SIMPLE_SVG_CREATE(feBlend, NS_NewSVGFELeafFrame),
    4866                 :     SIMPLE_SVG_CREATE(feColorMatrix, NS_NewSVGFELeafFrame),
    4867                 :     SIMPLE_SVG_CREATE(feFuncR, NS_NewSVGFEUnstyledLeafFrame),
    4868                 :     SIMPLE_SVG_CREATE(feFuncG, NS_NewSVGFEUnstyledLeafFrame),
    4869                 :     SIMPLE_SVG_CREATE(feFuncB, NS_NewSVGFEUnstyledLeafFrame),
    4870                 :     SIMPLE_SVG_CREATE(feFuncA, NS_NewSVGFEUnstyledLeafFrame),
    4871                 :     SIMPLE_SVG_CREATE(feComposite, NS_NewSVGFELeafFrame),
    4872                 :     SIMPLE_SVG_CREATE(feComponentTransfer, NS_NewSVGFEContainerFrame),
    4873                 :     SIMPLE_SVG_CREATE(feConvolveMatrix, NS_NewSVGFELeafFrame),
    4874                 :     SIMPLE_SVG_CREATE(feDiffuseLighting, NS_NewSVGFEContainerFrame),
    4875                 :     SIMPLE_SVG_CREATE(feDisplacementMap, NS_NewSVGFELeafFrame),
    4876                 :     SIMPLE_SVG_CREATE(feFlood, NS_NewSVGFELeafFrame),
    4877                 :     SIMPLE_SVG_CREATE(feGaussianBlur, NS_NewSVGFELeafFrame),
    4878                 :     SIMPLE_SVG_CREATE(feImage, NS_NewSVGFEImageFrame),
    4879                 :     SIMPLE_SVG_CREATE(feMerge, NS_NewSVGFEContainerFrame),
    4880                 :     SIMPLE_SVG_CREATE(feMergeNode, NS_NewSVGFEUnstyledLeafFrame),
    4881                 :     SIMPLE_SVG_CREATE(feMorphology, NS_NewSVGFELeafFrame), 
    4882                 :     SIMPLE_SVG_CREATE(feOffset, NS_NewSVGFELeafFrame), 
    4883                 :     SIMPLE_SVG_CREATE(feSpecularLighting, NS_NewSVGFEContainerFrame),
    4884                 :     SIMPLE_SVG_CREATE(feTile, NS_NewSVGFELeafFrame), 
    4885                 :     SIMPLE_SVG_CREATE(feTurbulence, NS_NewSVGFELeafFrame) 
    4886                 :   };
    4887                 : 
    4888                 :   const FrameConstructionData* data =
    4889                 :     FindDataByTag(aTag, aElement, aStyleContext, sSVGData,
    4890               0 :                   ArrayLength(sSVGData));
    4891                 : 
    4892               0 :   if (!data) {
    4893               0 :     data = &sContainerData;
    4894                 :   }
    4895                 : 
    4896               0 :   return data;
    4897                 : }
    4898                 : 
    4899                 : void
    4900               0 : nsCSSFrameConstructor::AddPageBreakItem(nsIContent* aContent,
    4901                 :                                         nsStyleContext* aMainStyleContext,
    4902                 :                                         FrameConstructionItemList& aItems)
    4903                 : {
    4904               0 :   nsRefPtr<nsStyleContext> pseudoStyle;
    4905                 :   // Use the same parent style context that |aMainStyleContext| has, since
    4906                 :   // that's easier to re-resolve and it doesn't matter in practice.
    4907                 :   // (Getting different parents can result in framechange hints, e.g.,
    4908                 :   // for user-modify.)
    4909                 :   pseudoStyle =
    4910                 :     mPresShell->StyleSet()->
    4911                 :       ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak,
    4912               0 :                                aMainStyleContext->GetParent());
    4913                 : 
    4914               0 :   NS_ASSERTION(pseudoStyle->GetStyleDisplay()->mDisplay ==
    4915                 :                  NS_STYLE_DISPLAY_BLOCK, "Unexpected display");
    4916                 : 
    4917                 :   static const FrameConstructionData sPageBreakData =
    4918                 :     FCDATA_DECL(FCDATA_SKIP_FRAMESET, NS_NewPageBreakFrame);
    4919                 : 
    4920                 :   // Lie about the tag and namespace so we don't trigger anything
    4921                 :   // interesting during frame construction.
    4922                 :   aItems.AppendItem(&sPageBreakData, aContent, nsCSSAnonBoxes::pageBreak,
    4923               0 :                     kNameSpaceID_None, nsnull, pseudoStyle.forget(), true);
    4924               0 : }
    4925                 : 
    4926                 : nsresult
    4927               0 : nsCSSFrameConstructor::ConstructFrame(nsFrameConstructorState& aState,
    4928                 :                                       nsIContent*              aContent,
    4929                 :                                       nsIFrame*                aParentFrame,
    4930                 :                                       nsFrameItems&            aFrameItems)
    4931                 : 
    4932                 : {
    4933               0 :   NS_PRECONDITION(nsnull != aParentFrame, "no parent frame");
    4934               0 :   FrameConstructionItemList items;
    4935               0 :   AddFrameConstructionItems(aState, aContent, true, aParentFrame, items);
    4936                 : 
    4937               0 :   for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
    4938               0 :     NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
    4939                 :                  "This is not going to work");
    4940                 :     nsresult rv =
    4941               0 :       ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
    4942               0 :     NS_ENSURE_SUCCESS(rv, rv);
    4943                 :   }
    4944                 : 
    4945               0 :   return NS_OK;
    4946                 : }
    4947                 : 
    4948                 : void
    4949               0 : nsCSSFrameConstructor::AddFrameConstructionItems(nsFrameConstructorState& aState,
    4950                 :                                                  nsIContent* aContent,
    4951                 :                                                  bool aSuppressWhiteSpaceOptimizations,
    4952                 :                                                  nsIFrame* aParentFrame,
    4953                 :                                                  FrameConstructionItemList& aItems)
    4954                 : {
    4955               0 :   aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
    4956               0 :   if (aContent->IsElement()) {
    4957                 :     // We can't just remove our pending restyle flags, since we may
    4958                 :     // have restyle-later-siblings set on us.  But we _can_ remove the
    4959                 :     // "is possible restyle root" flags, and need to.  Otherwise we can
    4960                 :     // end up with stale such flags (e.g. if we used to have a
    4961                 :     // display:none parent when our last restyle was posted and
    4962                 :     // processed and now no longer do).
    4963                 :     aContent->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS &
    4964               0 :                          ~ELEMENT_PENDING_RESTYLE_FLAGS);
    4965                 :   }
    4966                 : 
    4967                 :   // XXX the GetContent() != aContent check is needed due to bug 135040.
    4968                 :   // Remove it once that's fixed.  
    4969               0 :   if (aContent->GetPrimaryFrame() &&
    4970               0 :       aContent->GetPrimaryFrame()->GetContent() == aContent &&
    4971               0 :       !aState.mCreatingExtraFrames) {
    4972                 :     NS_ERROR("asked to create frame construction item for a node that already "
    4973               0 :              "has a frame");
    4974               0 :     return;
    4975                 :   }
    4976                 : 
    4977                 :   // don't create a whitespace frame if aParent doesn't want it
    4978               0 :   if (!NeedFrameFor(aState, aParentFrame, aContent)) {
    4979               0 :     return;
    4980                 :   }
    4981                 : 
    4982                 :   // never create frames for comments or PIs
    4983               0 :   if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
    4984               0 :       aContent->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION))
    4985               0 :     return;
    4986                 : 
    4987               0 :   nsRefPtr<nsStyleContext> styleContext;
    4988               0 :   styleContext = ResolveStyleContext(aParentFrame, aContent, &aState);
    4989                 : 
    4990                 :   AddFrameConstructionItemsInternal(aState, aContent, aParentFrame,
    4991                 :                                     aContent->Tag(), aContent->GetNameSpaceID(),
    4992                 :                                     aSuppressWhiteSpaceOptimizations,
    4993                 :                                     styleContext,
    4994                 :                                     ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK,
    4995               0 :                                     aItems);
    4996                 : }
    4997                 : 
    4998                 : /**
    4999                 :  * Set aContent as undisplayed content with style context aStyleContext.  This
    5000                 :  * method enforces the invariant that all style contexts in the undisplayed
    5001                 :  * content map must be non-pseudo contexts and also handles unbinding
    5002                 :  * undisplayed generated content as needed.
    5003                 :  */
    5004                 : static void
    5005               0 : SetAsUndisplayedContent(nsFrameManager* aFrameManager, nsIContent* aContent,
    5006                 :                         nsStyleContext* aStyleContext,
    5007                 :                         bool aIsGeneratedContent)
    5008                 : {
    5009               0 :   if (aStyleContext->GetPseudo()) {
    5010               0 :     if (aIsGeneratedContent) {
    5011               0 :       aContent->UnbindFromTree();
    5012                 :     }
    5013               0 :     return;
    5014                 :   }
    5015                 : 
    5016               0 :   NS_ASSERTION(!aIsGeneratedContent, "Should have had pseudo type");
    5017               0 :   aFrameManager->SetUndisplayedContent(aContent, aStyleContext);
    5018                 : }
    5019                 : 
    5020                 : void
    5021               0 : nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
    5022                 :                                                          nsIContent* aContent,
    5023                 :                                                          nsIFrame* aParentFrame,
    5024                 :                                                          nsIAtom* aTag,
    5025                 :                                                          PRInt32 aNameSpaceID,
    5026                 :                                                          bool aSuppressWhiteSpaceOptimizations,
    5027                 :                                                          nsStyleContext* aStyleContext,
    5028                 :                                                          PRUint32 aFlags,
    5029                 :                                                          FrameConstructionItemList& aItems)
    5030                 : {
    5031               0 :   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT) ||
    5032                 :                   aContent->IsElement(),
    5033                 :                   "Shouldn't get anything else here!");
    5034                 : 
    5035                 :   // The following code allows the user to specify the base tag
    5036                 :   // of an element using XBL.  XUL and HTML objects (like boxes, menus, etc.)
    5037                 :   // can then be extended arbitrarily.
    5038               0 :   const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
    5039               0 :   nsRefPtr<nsStyleContext> styleContext(aStyleContext);
    5040               0 :   PendingBinding* pendingBinding = nsnull;
    5041               0 :   if ((aFlags & ITEM_ALLOW_XBL_BASE) && display->mBinding)
    5042                 :   {
    5043                 :     // Ensure that our XBL bindings are installed.
    5044                 : 
    5045               0 :     nsIXBLService * xblService = GetXBLService();
    5046               0 :     if (!xblService)
    5047                 :       return;
    5048                 : 
    5049                 :     bool resolveStyle;
    5050                 : 
    5051               0 :     nsAutoPtr<PendingBinding> newPendingBinding(new PendingBinding());
    5052                 : 
    5053                 :     nsresult rv = xblService->LoadBindings(aContent, display->mBinding->GetURI(),
    5054               0 :                                            display->mBinding->mOriginPrincipal,
    5055                 :                                            false,
    5056               0 :                                            getter_AddRefs(newPendingBinding->mBinding),
    5057               0 :                                            &resolveStyle);
    5058               0 :     if (NS_FAILED(rv) && rv != NS_ERROR_XBL_BLOCKED)
    5059                 :       return;
    5060                 : 
    5061               0 :     if (newPendingBinding->mBinding) {
    5062               0 :       pendingBinding = newPendingBinding;
    5063                 :       // aState takes over owning newPendingBinding
    5064               0 :       aState.AddPendingBinding(newPendingBinding.forget());
    5065                 :     }
    5066                 : 
    5067               0 :     if (resolveStyle) {
    5068                 :       styleContext =
    5069               0 :         ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
    5070               0 :       display = styleContext->GetStyleDisplay();
    5071               0 :       aStyleContext = styleContext;
    5072                 :     }
    5073                 : 
    5074               0 :     aTag = mDocument->BindingManager()->ResolveTag(aContent, &aNameSpaceID);
    5075                 :   }
    5076                 : 
    5077               0 :   bool isGeneratedContent = ((aFlags & ITEM_IS_GENERATED_CONTENT) != 0);
    5078                 : 
    5079                 :   // Pre-check for display "none" - if we find that, don't create
    5080                 :   // any frame at all
    5081               0 :   if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
    5082               0 :     SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
    5083                 :     return;
    5084                 :   }
    5085                 : 
    5086               0 :   bool isText = !aContent->IsElement();
    5087                 : 
    5088                 :   // never create frames for non-option/optgroup kids of <select> and
    5089                 :   // non-option kids of <optgroup> inside a <select>.
    5090                 :   // XXXbz it's not clear how this should best work with XBL.
    5091               0 :   nsIContent *parent = aContent->GetParent();
    5092               0 :   if (parent) {
    5093                 :     // Check tag first, since that check will usually fail
    5094               0 :     nsIAtom* parentTag = parent->Tag();
    5095               0 :     if ((parentTag == nsGkAtoms::select || parentTag == nsGkAtoms::optgroup) &&
    5096               0 :         parent->IsHTML() &&
    5097                 :         // <option> is ok no matter what
    5098               0 :         !aContent->IsHTML(nsGkAtoms::option) &&
    5099                 :         // <optgroup> is OK in <select> but not in <optgroup>
    5100               0 :         (!aContent->IsHTML(nsGkAtoms::optgroup) ||
    5101                 :          parentTag != nsGkAtoms::select) &&
    5102                 :         // Allow native anonymous content no matter what
    5103               0 :         !aContent->IsRootOfNativeAnonymousSubtree()) {
    5104                 :       // No frame for aContent
    5105               0 :       if (!isText) {
    5106               0 :         SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
    5107                 :       }
    5108                 :       return;
    5109                 :     }
    5110                 :   }
    5111                 : 
    5112               0 :   bool isPopup = false;
    5113                 :   // Try to find frame construction data for this content
    5114                 :   const FrameConstructionData* data;
    5115               0 :   if (isText) {
    5116               0 :     data = FindTextData(aParentFrame);
    5117               0 :     if (!data) {
    5118                 :       // Nothing to do here; suppressed text inside SVG
    5119                 :       return;
    5120                 :     }
    5121                 :   } else {
    5122               0 :     Element* element = aContent->AsElement();
    5123                 : 
    5124                 :     // Don't create frames for non-SVG element children of SVG elements.
    5125               0 :     if (aNameSpaceID != kNameSpaceID_SVG &&
    5126                 :         aParentFrame &&
    5127               0 :         aParentFrame->IsFrameOfType(nsIFrame::eSVG) &&
    5128               0 :         !aParentFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)
    5129                 :         ) {
    5130                 :       SetAsUndisplayedContent(this, element, styleContext,
    5131               0 :                               isGeneratedContent);
    5132                 :       return;
    5133                 :     }
    5134                 : 
    5135                 :     data = FindHTMLData(element, aTag, aNameSpaceID, aParentFrame,
    5136               0 :                         styleContext);
    5137               0 :     if (!data) {
    5138               0 :       data = FindXULTagData(element, aTag, aNameSpaceID, styleContext);
    5139                 :     }
    5140               0 :     if (!data) {
    5141               0 :       data = FindMathMLData(element, aTag, aNameSpaceID, styleContext);
    5142                 :     }
    5143               0 :     if (!data) {
    5144                 :       data = FindSVGData(element, aTag, aNameSpaceID, aParentFrame,
    5145               0 :                          styleContext);
    5146                 :     }
    5147                 : 
    5148                 :     // Now check for XUL display types
    5149               0 :     if (!data) {
    5150               0 :       data = FindXULDisplayData(display, element, styleContext);
    5151                 :     }
    5152                 : 
    5153                 :     // And general display types
    5154               0 :     if (!data) {
    5155               0 :       data = FindDisplayData(display, element, styleContext);
    5156                 :     }
    5157                 : 
    5158               0 :     NS_ASSERTION(data, "Should have frame construction data now");
    5159                 : 
    5160               0 :     if (data->mBits & FCDATA_SUPPRESS_FRAME) {
    5161               0 :       SetAsUndisplayedContent(this, element, styleContext, isGeneratedContent);
    5162                 :       return;
    5163                 :     }
    5164                 : 
    5165                 : #ifdef MOZ_XUL
    5166               0 :     if ((data->mBits & FCDATA_IS_POPUP) &&
    5167                 :         (!aParentFrame || // Parent is inline
    5168               0 :          aParentFrame->GetType() != nsGkAtoms::menuFrame)) {
    5169               0 :       if (!aState.mPopupItems.containingBlock &&
    5170               0 :           !aState.mHavePendingPopupgroup) {
    5171                 :         SetAsUndisplayedContent(this, element, styleContext,
    5172               0 :                                 isGeneratedContent);
    5173                 :         return;
    5174                 :       }
    5175                 : 
    5176               0 :       isPopup = true;
    5177                 :     }
    5178                 : #endif /* MOZ_XUL */
    5179                 :   }
    5180                 : 
    5181               0 :   PRUint32 bits = data->mBits;
    5182                 : 
    5183                 :   // Inside colgroups, suppress everything except columns.
    5184               0 :   if (aParentFrame &&
    5185               0 :       aParentFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
    5186               0 :       (!(bits & FCDATA_IS_TABLE_PART) ||
    5187                 :        display->mDisplay != NS_STYLE_DISPLAY_TABLE_COLUMN)) {
    5188               0 :     SetAsUndisplayedContent(this, aContent, styleContext, isGeneratedContent);
    5189                 :     return;
    5190                 :   }
    5191                 : 
    5192                 :   bool canHavePageBreak =
    5193                 :     (aFlags & ITEM_ALLOW_PAGE_BREAK) &&
    5194               0 :     aState.mPresContext->IsPaginated() &&
    5195               0 :     !display->IsAbsolutelyPositioned() &&
    5196               0 :     !(bits & FCDATA_IS_TABLE_PART);
    5197                 : 
    5198               0 :   if (canHavePageBreak && display->mBreakBefore) {
    5199               0 :     AddPageBreakItem(aContent, aStyleContext, aItems);
    5200                 :   }
    5201                 : 
    5202                 :   FrameConstructionItem* item =
    5203                 :     aItems.AppendItem(data, aContent, aTag, aNameSpaceID,
    5204                 :                       pendingBinding, styleContext.forget(),
    5205               0 :                       aSuppressWhiteSpaceOptimizations);
    5206               0 :   if (!item) {
    5207               0 :     if (isGeneratedContent) {
    5208               0 :       aContent->UnbindFromTree();
    5209                 :     }
    5210                 :     return;
    5211                 :   }
    5212                 : 
    5213               0 :   item->mIsText = isText;
    5214               0 :   item->mIsGeneratedContent = isGeneratedContent;
    5215               0 :   if (isGeneratedContent) {
    5216               0 :     NS_ADDREF(item->mContent);
    5217                 :   }
    5218                 :   item->mIsRootPopupgroup =
    5219                 :     aNameSpaceID == kNameSpaceID_XUL && aTag == nsGkAtoms::popupgroup &&
    5220               0 :     aContent->IsRootOfNativeAnonymousSubtree();
    5221               0 :   if (item->mIsRootPopupgroup) {
    5222               0 :     aState.mHavePendingPopupgroup = true;
    5223                 :   }
    5224               0 :   item->mIsPopup = isPopup;
    5225                 : 
    5226               0 :   if (canHavePageBreak && display->mBreakAfter) {
    5227               0 :     AddPageBreakItem(aContent, aStyleContext, aItems);
    5228                 :   }
    5229                 : 
    5230               0 :   if (bits & FCDATA_IS_INLINE) {
    5231                 :     // To correctly set item->mIsAllInline we need to build up our child items
    5232                 :     // right now.
    5233               0 :     BuildInlineChildItems(aState, *item);
    5234               0 :     item->mHasInlineEnds = true;
    5235               0 :     item->mIsBlock = false;
    5236                 :   } else {
    5237                 :     // Compute a boolean isInline which is guaranteed to be false for blocks
    5238                 :     // (but may also be false for some inlines).
    5239                 :     bool isInline =
    5240                 :       // Table-internal things are inline-outside if and only if they're kids of
    5241                 :       // inlines, since they'll trigger construction of inline-table
    5242                 :       // pseudos.
    5243                 :       ((bits & FCDATA_IS_TABLE_PART) &&
    5244                 :        (!aParentFrame || // No aParentFrame means inline
    5245               0 :         aParentFrame->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)) ||
    5246                 :       // Things that are inline-outside but aren't inline frames are inline
    5247               0 :       display->IsInlineOutside() ||
    5248                 :       // Popups that are certainly out of flow.
    5249               0 :       isPopup;
    5250                 : 
    5251                 :     // Set mIsAllInline conservatively.  It just might be that even an inline
    5252                 :     // that has mIsAllInline false doesn't need an {ib} split.  So this is just
    5253                 :     // an optimization to keep from doing too much work in cases when we can
    5254                 :     // show that mIsAllInline is true..
    5255                 :     item->mIsAllInline = item->mHasInlineEnds = isInline ||
    5256                 :       // Figure out whether we're guaranteed this item will be out of flow.
    5257                 :       // This is not a precise test, since one of our ancestor inlines might add
    5258                 :       // an absolute containing block (if it's relatively positioned) when there
    5259                 :       // wasn't such a containing block before.  But it's conservative in the
    5260                 :       // sense that anything that will really end up as an in-flow non-inline
    5261                 :       // will test false here.  In other words, if this test is true we're
    5262                 :       // guaranteed to be inline; if it's false we don't know what we'll end up
    5263                 :       // as.
    5264                 :       //
    5265                 :       // If we make this test precise, we can remove some of the code dealing
    5266                 :       // with the imprecision in ConstructInline and adjust the comments on
    5267                 :       // mIsAllInline and mIsBlock in the header.  And probably remove mIsBlock
    5268                 :       // altogether, since then it will always be equal to !mHasInlineEnds.
    5269               0 :       (!(bits & FCDATA_DISALLOW_OUT_OF_FLOW) &&
    5270               0 :        aState.GetGeometricParent(display, nsnull));
    5271                 : 
    5272                 :     // Set mIsBlock conservatively.  It's OK to set it false for some real
    5273                 :     // blocks, but not OK to set it true for things that aren't blocks.  Since
    5274                 :     // isOutOfFlow might be false even in cases when the frame will end up
    5275                 :     // out-of-flow, we can't use it here.  But we _can_ say that the frame will
    5276                 :     // for sure end up in-flow if it's not floated or absolutely positioned.
    5277                 :     item->mIsBlock =
    5278               0 :       !isInline && !display->IsAbsolutelyPositioned() && !display->IsFloating();
    5279                 :   }
    5280                 : 
    5281               0 :   if (item->mIsAllInline) {
    5282               0 :     aItems.InlineItemAdded();
    5283               0 :   } else if (item->mIsBlock) {
    5284               0 :     aItems.BlockItemAdded();
    5285                 :   }
    5286                 : 
    5287                 :   // Our item should be treated as a line participant if we have the relevant
    5288                 :   // bit and are going to be in-flow.  Note that this really only matters if
    5289                 :   // our ancestor is a box or some such, so the fact that we might have an
    5290                 :   // inline ancestor that might become a containing block is not relevant here.
    5291               0 :   if ((bits & FCDATA_IS_LINE_PARTICIPANT) &&
    5292                 :       ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
    5293               0 :        !aState.GetGeometricParent(display, nsnull))) {
    5294               0 :     item->mIsLineParticipant = true;
    5295               0 :     aItems.LineParticipantItemAdded();
    5296                 :   }
    5297                 : }
    5298                 : 
    5299                 : static void
    5300               0 : DestroyContent(void* aPropertyValue)
    5301                 : {
    5302               0 :   nsIContent* content = static_cast<nsIContent*>(aPropertyValue);
    5303               0 :   content->UnbindFromTree();
    5304               0 :   NS_RELEASE(content);
    5305               0 : }
    5306                 : 
    5307               0 : NS_DECLARE_FRAME_PROPERTY(BeforeProperty, DestroyContent)
    5308               0 : NS_DECLARE_FRAME_PROPERTY(AfterProperty, DestroyContent)
    5309                 : 
    5310                 : static const FramePropertyDescriptor*
    5311               0 : GenConPseudoToProperty(nsIAtom* aPseudo)
    5312                 : {
    5313               0 :   NS_ASSERTION(aPseudo == nsCSSPseudoElements::before ||
    5314                 :                aPseudo == nsCSSPseudoElements::after,
    5315                 :                "Bad gen-con pseudo");
    5316                 :   return aPseudo == nsCSSPseudoElements::before ? BeforeProperty()
    5317               0 :       : AfterProperty();
    5318                 : }
    5319                 : 
    5320                 : /**
    5321                 :  * Return true if the frame construction item pointed to by aIter will
    5322                 :  * create a frame adjacent to a line boundary in the frame tree, and that
    5323                 :  * line boundary is induced by a content node adjacent to the frame's
    5324                 :  * content node in the content tree. The latter condition is necessary so
    5325                 :  * that ContentAppended/ContentInserted/ContentRemoved can easily find any
    5326                 :  * text nodes that were suppressed here.
    5327                 :  */
    5328                 : bool
    5329               0 : nsCSSFrameConstructor::AtLineBoundary(FCItemIterator& aIter)
    5330                 : {
    5331               0 :   if (aIter.item().mSuppressWhiteSpaceOptimizations) {
    5332               0 :     return false;
    5333                 :   }
    5334                 : 
    5335               0 :   if (aIter.AtStart()) {
    5336               0 :     if (aIter.List()->HasLineBoundaryAtStart() &&
    5337               0 :         !aIter.item().mContent->GetPreviousSibling())
    5338               0 :       return true;
    5339                 :   } else {
    5340               0 :     FCItemIterator prev = aIter;
    5341               0 :     prev.Prev();
    5342               0 :     if (prev.item().IsLineBoundary() &&
    5343               0 :         !prev.item().mSuppressWhiteSpaceOptimizations &&
    5344               0 :         aIter.item().mContent->GetPreviousSibling() == prev.item().mContent)
    5345               0 :       return true;
    5346                 :   }
    5347                 : 
    5348               0 :   FCItemIterator next = aIter;
    5349               0 :   next.Next();
    5350               0 :   if (next.IsDone()) {
    5351               0 :     if (aIter.List()->HasLineBoundaryAtEnd() &&
    5352               0 :         !aIter.item().mContent->GetNextSibling())
    5353               0 :       return true;
    5354                 :   } else {
    5355               0 :     if (next.item().IsLineBoundary() &&
    5356               0 :         !next.item().mSuppressWhiteSpaceOptimizations &&
    5357               0 :         aIter.item().mContent->GetNextSibling() == next.item().mContent)
    5358               0 :       return true;
    5359                 :   }
    5360                 : 
    5361               0 :   return false;
    5362                 : }
    5363                 : 
    5364                 : nsresult
    5365               0 : nsCSSFrameConstructor::ConstructFramesFromItem(nsFrameConstructorState& aState,
    5366                 :                                                FCItemIterator& aIter,
    5367                 :                                                nsIFrame* aParentFrame,
    5368                 :                                                nsFrameItems& aFrameItems)
    5369                 : {
    5370               0 :   nsIFrame* adjParentFrame = aParentFrame;
    5371               0 :   FrameConstructionItem& item = aIter.item();
    5372               0 :   nsStyleContext* styleContext = item.mStyleContext;
    5373               0 :   AdjustParentFrame(adjParentFrame, item.mFCData, styleContext);
    5374                 : 
    5375               0 :   if (item.mIsText) {
    5376                 :     // If this is collapsible whitespace next to a line boundary,
    5377                 :     // don't create a frame. item.IsWhitespace() also sets the
    5378                 :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag in the text node. (If we
    5379                 :     // end up creating a frame, nsTextFrame::Init will clear the flag.)
    5380                 :     // We don't do this for generated content, because some generated
    5381                 :     // text content is empty text nodes that are about to be initialized.
    5382                 :     // (We check mAdditionalStateBits because only the generated content
    5383                 :     // container's frame construction item is marked with
    5384                 :     // mIsGeneratedContent, and we might not have an aParentFrame.)
    5385                 :     // We don't do it for content that may have XBL anonymous siblings,
    5386                 :     // because they make it difficult to correctly create the frame
    5387                 :     // due to dynamic changes.
    5388                 :     // We don't do it for text that's not a line participant (i.e. SVG text).
    5389               0 :     if (AtLineBoundary(aIter) &&
    5390               0 :         !styleContext->GetStyleText()->NewlineIsSignificant() &&
    5391               0 :         aIter.List()->ParentHasNoXBLChildren() &&
    5392               0 :         !(aState.mAdditionalStateBits & NS_FRAME_GENERATED_CONTENT) &&
    5393                 :         (item.mFCData->mBits & FCDATA_IS_LINE_PARTICIPANT) &&
    5394               0 :         item.IsWhitespace(aState))
    5395               0 :       return NS_OK;
    5396                 : 
    5397                 :     return ConstructTextFrame(item.mFCData, aState, item.mContent,
    5398                 :                               adjParentFrame, styleContext,
    5399               0 :                               aFrameItems);
    5400                 :   }
    5401                 : 
    5402                 :   // Start background loads during frame construction so that we're
    5403                 :   // guaranteed that they will be started before onload fires.
    5404               0 :   styleContext->StartBackgroundImageLoads();
    5405                 : 
    5406               0 :   nsFrameState savedStateBits = aState.mAdditionalStateBits;
    5407               0 :   if (item.mIsGeneratedContent) {
    5408                 :     // Ensure that frames created here are all tagged with
    5409                 :     // NS_FRAME_GENERATED_CONTENT.
    5410               0 :     aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
    5411                 : 
    5412                 :     // Note that we're not necessarily setting this property on the primary
    5413                 :     // frame for the content for which this is generated content.  We might be
    5414                 :     // setting it on a table pseudo-frame inserted under that instead.  That's
    5415                 :     // OK, though; we just need to do the property set so that the content will
    5416                 :     // get cleaned up when the frame is destroyed.
    5417                 :     aParentFrame->Properties().Set(GenConPseudoToProperty(styleContext->GetPseudo()),
    5418               0 :                                    item.mContent);
    5419                 : 
    5420                 :     // Now that we've passed ownership of item.mContent to the frame, unset
    5421                 :     // our generated content flag so we don't release or unbind it ourselves.
    5422               0 :     item.mIsGeneratedContent = false;
    5423                 :   }
    5424                 : 
    5425                 :   // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
    5426                 :   nsresult rv = ConstructFrameFromItemInternal(item, aState, adjParentFrame,
    5427               0 :                                                aFrameItems);
    5428                 : 
    5429               0 :   aState.mAdditionalStateBits = savedStateBits;
    5430                 : 
    5431               0 :   return rv;
    5432                 : }
    5433                 : 
    5434                 : 
    5435                 : inline bool
    5436                 : IsRootBoxFrame(nsIFrame *aFrame)
    5437                 : {
    5438                 :   return (aFrame->GetType() == nsGkAtoms::rootFrame);
    5439                 : }
    5440                 : 
    5441                 : nsresult
    5442               0 : nsCSSFrameConstructor::ReconstructDocElementHierarchy()
    5443                 : {
    5444               0 :   Element* rootElement = mDocument->GetRootElement();
    5445               0 :   if (!rootElement) {
    5446                 :     /* nothing to do */
    5447               0 :     return NS_OK;
    5448                 :   }
    5449               0 :   return RecreateFramesForContent(rootElement, false);
    5450                 : }
    5451                 : 
    5452                 : nsIFrame*
    5453               0 : nsCSSFrameConstructor::GetFrameFor(nsIContent* aContent)
    5454                 : {
    5455                 :   // Get the primary frame associated with the content
    5456               0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    5457                 : 
    5458               0 :   if (!frame)
    5459               0 :     return nsnull;
    5460                 : 
    5461                 :   // If the content of the frame is not the desired content then this is not
    5462                 :   // really a frame for the desired content.
    5463                 :   // XXX This check is needed due to bug 135040. Remove it once that's fixed.
    5464               0 :   if (frame->GetContent() != aContent) {
    5465               0 :     return nsnull;
    5466                 :   }
    5467                 : 
    5468               0 :   nsIFrame* insertionFrame = frame->GetContentInsertionFrame();
    5469                 : 
    5470               0 :   NS_ASSERTION(insertionFrame == frame || !frame->IsLeaf(),
    5471                 :     "The insertion frame is the primary frame or the primary frame isn't a leaf");
    5472                 : 
    5473               0 :   return insertionFrame;
    5474                 : }
    5475                 : 
    5476                 : nsIFrame*
    5477               0 : nsCSSFrameConstructor::GetAbsoluteContainingBlock(nsIFrame* aFrame)
    5478                 : {
    5479               0 :   NS_PRECONDITION(nsnull != mRootElementFrame, "no root element frame");
    5480                 : 
    5481                 :   // Starting with aFrame, look for a frame that is absolutely positioned or
    5482                 :   // relatively positioned
    5483               0 :   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
    5484               0 :     if (frame->IsFrameOfType(nsIFrame::eMathML)) {
    5485                 :       // If it's mathml, bail out -- no absolute positioning out from inside
    5486                 :       // mathml frames.  Note that we don't make this part of the loop
    5487                 :       // condition because of the stuff at the end of this method...
    5488               0 :       return nsnull;
    5489                 :     }
    5490                 : 
    5491                 :     // If the frame is positioned, we will probably return it as the containing
    5492                 :     // block (see the exceptions below).  Otherwise, we'll start looking at the
    5493                 :     // parent frame, unless we're dealing with a scrollframe.
    5494                 :     // Scrollframes are special since they're not positioned, but their
    5495                 :     // scrolledframe might be.  So, we need to check this special case to return
    5496                 :     // the correct containing block (the scrolledframe) in that case.
    5497               0 :     const nsStyleDisplay* disp = frame->GetStyleDisplay();
    5498               0 :     if (!disp->IsPositioned()) {
    5499               0 :       continue;
    5500                 :     }
    5501               0 :     nsIFrame* absPosCBCandidate = nsnull;
    5502               0 :     if (frame->GetType() == nsGkAtoms::scrollFrame) {
    5503               0 :       nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
    5504               0 :       absPosCBCandidate = scrollFrame->GetScrolledFrame();
    5505                 :     } else {
    5506                 :       // Only first continuations can be containing blocks.
    5507               0 :       absPosCBCandidate = frame->GetFirstContinuation();
    5508                 :     }
    5509                 :     // Is the frame really an absolute container?
    5510               0 :     if (!absPosCBCandidate || !absPosCBCandidate->IsAbsoluteContainer()) {
    5511               0 :       continue;
    5512                 :     }
    5513                 : 
    5514                 :     // For tables, return the outer table frame.
    5515               0 :     if (absPosCBCandidate->GetType() == nsGkAtoms::tableFrame) {
    5516               0 :       return absPosCBCandidate->GetParent();
    5517                 :     }
    5518                 :     // For outer table frames, we can just return absPosCBCandidate.
    5519               0 :     return absPosCBCandidate;
    5520                 :   }
    5521                 : 
    5522                 :   // It is possible for the search for the containing block to fail, because
    5523                 :   // no absolute container can be found in the parent chain.  In those cases,
    5524                 :   // we fall back to the document element's containing block.
    5525               0 :   return mHasRootAbsPosContainingBlock ? mDocElementContainingBlock : nsnull;
    5526                 : }
    5527                 : 
    5528                 : nsIFrame*
    5529               0 : nsCSSFrameConstructor::GetFloatContainingBlock(nsIFrame* aFrame)
    5530                 : {
    5531                 :   // Starting with aFrame, look for a frame that is a float containing block.
    5532                 :   // IF we hit a mathml frame, bail out; we don't allow floating out of mathml
    5533                 :   // frames, because they don't seem to be able to deal.
    5534                 :   // The logic here needs to match the logic in ProcessChildren()
    5535               0 :   for (nsIFrame* containingBlock = aFrame;
    5536               0 :        containingBlock && !containingBlock->IsFrameOfType(nsIFrame::eMathML) &&
    5537               0 :        !containingBlock->IsBoxFrame();
    5538                 :        containingBlock = containingBlock->GetParent()) {
    5539               0 :     if (containingBlock->IsFloatContainingBlock()) {
    5540               0 :       return containingBlock;
    5541                 :     }
    5542                 :   }
    5543                 : 
    5544                 :   // If we didn't find a containing block, then there just isn't
    5545                 :   // one.... return null
    5546               0 :   return nsnull;
    5547                 : }
    5548                 : 
    5549                 : /**
    5550                 :  * This function will check whether aContainer has :after generated content.
    5551                 :  * If so, appending to it should actually insert.  The return value is the
    5552                 :  * parent to use for newly-appended content.  *aAfterFrame points to the :after
    5553                 :  * frame before which appended content should go, if there is one.
    5554                 :  */
    5555                 : static nsIFrame*
    5556               0 : AdjustAppendParentForAfterContent(nsPresContext* aPresContext,
    5557                 :                                   nsIContent* aContainer,
    5558                 :                                   nsIFrame* aParentFrame,
    5559                 :                                   nsIFrame** aAfterFrame)
    5560                 : {
    5561                 :   // See if the parent has an :after pseudo-element.  Check for the presence
    5562                 :   // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive.
    5563               0 :   nsStyleContext* parentStyle = aParentFrame->GetStyleContext();
    5564               0 :   if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle,
    5565                 :                                     nsCSSPseudoElements::ePseudo_after,
    5566                 :                                     aPresContext)) {
    5567               0 :     nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame);
    5568               0 :     if (afterFrame) {
    5569               0 :       *aAfterFrame = afterFrame;
    5570               0 :       return afterFrame->GetParent();
    5571                 :     }
    5572                 :   }
    5573                 : 
    5574               0 :   *aAfterFrame = nsnull;
    5575                 : 
    5576               0 :   if (IsFrameSpecial(aParentFrame)) {
    5577                 :     // We might be in a situation where the last part of the {ib} split was
    5578                 :     // empty.  Since we have no ::after pseudo-element, we do in fact want to be
    5579                 :     // appending to that last part, so advance to it if needed.  Note that here
    5580                 :     // aParentFrame is the result of a GetLastSpecialSibling call, so must be
    5581                 :     // either the last or next to last special sibling.
    5582               0 :     nsIFrame* trailingInline = GetSpecialSibling(aParentFrame);
    5583               0 :     if (trailingInline) {
    5584               0 :       aParentFrame = trailingInline;
    5585                 :     }
    5586                 : 
    5587                 :     // Always make sure to look at the last continuation of the frame
    5588                 :     // for the {ib} case, even if that continuation is empty.  We
    5589                 :     // don't do this for the non-special-frame case, since in the
    5590                 :     // other cases appending to the last nonempty continuation is fine
    5591                 :     // and in fact not doing that can confuse code that doesn't know
    5592                 :     // to pull kids from continuations other than its next one.
    5593               0 :     aParentFrame = aParentFrame->GetLastContinuation();
    5594                 :   }
    5595                 : 
    5596               0 :   return aParentFrame;
    5597                 : }
    5598                 : 
    5599                 : /**
    5600                 :  * This function will get the previous sibling to use for an append operation.
    5601                 :  * it takes a parent frame (must not be null) and its :after frame (may be
    5602                 :  * null).
    5603                 :  */
    5604                 : static nsIFrame*
    5605               0 : FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
    5606                 : {
    5607               0 :   if (aAfterFrame) {
    5608               0 :     NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
    5609               0 :     return aAfterFrame->GetPrevSibling();
    5610                 :   }
    5611                 : 
    5612               0 :   return aParentFrame->GetLastChild(kPrincipalList);
    5613                 : }
    5614                 : 
    5615                 : /**
    5616                 :  * This function will get the next sibling for a frame insert operation given
    5617                 :  * the parent and previous sibling.  aPrevSibling may be null.
    5618                 :  */
    5619                 : static nsIFrame*
    5620               0 : GetInsertNextSibling(nsIFrame* aParentFrame, nsIFrame* aPrevSibling)
    5621                 : {
    5622               0 :   if (aPrevSibling) {
    5623               0 :     return aPrevSibling->GetNextSibling();
    5624                 :   }
    5625                 : 
    5626               0 :   return aParentFrame->GetFirstPrincipalChild();
    5627                 : }
    5628                 : 
    5629                 : /**
    5630                 :  * This function is called by ContentAppended() and ContentInserted() when
    5631                 :  * appending flowed frames to a parent's principal child list. It handles the
    5632                 :  * case where the parent is the trailing inline of an {ib} split.
    5633                 :  */
    5634                 : nsresult
    5635               0 : nsCSSFrameConstructor::AppendFramesToParent(nsFrameConstructorState&       aState,
    5636                 :                                             nsIFrame*                      aParentFrame,
    5637                 :                                             nsFrameItems&                  aFrameList,
    5638                 :                                             nsIFrame*                      aPrevSibling,
    5639                 :                                             bool                           aIsRecursiveCall)
    5640                 : {
    5641               0 :   NS_PRECONDITION(!IsFrameSpecial(aParentFrame) ||
    5642                 :                   !GetSpecialSibling(aParentFrame) ||
    5643                 :                   !GetSpecialSibling(aParentFrame)->GetFirstPrincipalChild(),
    5644                 :                   "aParentFrame has a special sibling with kids?");
    5645               0 :   NS_PRECONDITION(!aPrevSibling || aPrevSibling->GetParent() == aParentFrame,
    5646                 :                   "Parent and prevsibling don't match");
    5647                 : 
    5648               0 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aParentFrame, aPrevSibling);
    5649                 : 
    5650               0 :   NS_ASSERTION(nextSibling ||
    5651                 :                !aParentFrame->GetNextContinuation() ||
    5652                 :                !aParentFrame->GetNextContinuation()->GetFirstPrincipalChild() ||
    5653                 :                aIsRecursiveCall,
    5654                 :                "aParentFrame has later continuations with kids?");
    5655               0 :   NS_ASSERTION(nextSibling ||
    5656                 :                !IsFrameSpecial(aParentFrame) ||
    5657                 :                (IsInlineFrame(aParentFrame) &&
    5658                 :                 !GetSpecialSibling(aParentFrame) &&
    5659                 :                 !aParentFrame->GetNextContinuation()) ||
    5660                 :                aIsRecursiveCall,
    5661                 :                "aParentFrame is not last?");
    5662                 : 
    5663                 :   // If we're inserting a list of frames at the end of the trailing inline
    5664                 :   // of an {ib} split, we may need to create additional {ib} siblings to parent
    5665                 :   // them.
    5666               0 :   if (!nextSibling && IsFrameSpecial(aParentFrame)) {
    5667                 :     // When we get here, our frame list might start with a block.  If it does
    5668                 :     // so, and aParentFrame is an inline, and it and all its previous
    5669                 :     // continuations have no siblings, then put the initial blocks from the
    5670                 :     // frame list into the previous block of the {ib} split.  Note that we
    5671                 :     // didn't want to stop at the block part of the split when figuring out
    5672                 :     // initial parent, because that could screw up float parenting; it's easier
    5673                 :     // to do this little fixup here instead.
    5674               0 :     if (aFrameList.NotEmpty() && !IsInlineOutside(aFrameList.FirstChild())) {
    5675                 :       // See whether our trailing inline is empty
    5676               0 :       nsIFrame* firstContinuation = aParentFrame->GetFirstContinuation();
    5677               0 :       if (firstContinuation->PrincipalChildList().IsEmpty()) {
    5678                 :         // Our trailing inline is empty.  Collect our starting blocks from
    5679                 :         // aFrameList, get the right parent frame for them, and put them in.
    5680                 :         nsFrameList::FrameLinkEnumerator firstNonBlockEnumerator =
    5681               0 :           FindFirstNonBlock(aFrameList);
    5682               0 :         nsFrameList blockKids = aFrameList.ExtractHead(firstNonBlockEnumerator);
    5683               0 :         NS_ASSERTION(blockKids.NotEmpty(), "No blocks?");
    5684                 : 
    5685                 :         nsIFrame* prevBlock =
    5686               0 :           GetSpecialPrevSibling(firstContinuation)->GetLastContinuation();
    5687               0 :         NS_ASSERTION(prevBlock, "Should have previous block here");
    5688                 : 
    5689               0 :         MoveChildrenTo(aState.mPresContext, aParentFrame, prevBlock, blockKids);
    5690                 :       }
    5691                 :     }
    5692                 : 
    5693                 :     // We want to put some of the frames into this inline frame.
    5694               0 :     nsFrameList::FrameLinkEnumerator firstBlockEnumerator(aFrameList);
    5695               0 :     FindFirstBlock(firstBlockEnumerator);
    5696                 : 
    5697               0 :     nsFrameList inlineKids = aFrameList.ExtractHead(firstBlockEnumerator);
    5698               0 :     if (!inlineKids.IsEmpty()) {
    5699               0 :       AppendFrames(aParentFrame, kPrincipalList, inlineKids);
    5700                 :     }
    5701                 : 
    5702               0 :     if (!aFrameList.IsEmpty()) {
    5703               0 :       const nsStyleDisplay* parentDisplay = aParentFrame->GetStyleDisplay();
    5704                 :       bool positioned =
    5705                 :         parentDisplay->mPosition == NS_STYLE_POSITION_RELATIVE ||
    5706               0 :         parentDisplay->HasTransform();
    5707               0 :       nsFrameItems ibSiblings;
    5708                 :       CreateIBSiblings(aState, aParentFrame, positioned, aFrameList,
    5709               0 :                        ibSiblings);
    5710                 : 
    5711                 :       // Make sure to trigger reflow of the inline that used to be our
    5712                 :       // last one and now isn't anymore, since its GetSkipSides() has
    5713                 :       // changed.
    5714                 :       mPresShell->FrameNeedsReflow(aParentFrame,
    5715                 :                                    nsIPresShell::eTreeChange,
    5716               0 :                                    NS_FRAME_HAS_DIRTY_CHILDREN);
    5717                 : 
    5718                 :       // Recurse so we create new ib siblings as needed for aParentFrame's parent
    5719                 :       return AppendFramesToParent(aState, aParentFrame->GetParent(), ibSiblings,
    5720               0 :                                   aParentFrame, true);
    5721                 :     }
    5722                 : 
    5723               0 :     return NS_OK;
    5724                 :   }
    5725                 :   
    5726                 :   // Insert the frames after our aPrevSibling
    5727               0 :   return InsertFrames(aParentFrame, kPrincipalList, aPrevSibling, aFrameList);
    5728                 : }
    5729                 : 
    5730                 : #define UNSET_DISPLAY 255
    5731                 : 
    5732                 : // This gets called to see if the frames corresponding to aSibling and aContent
    5733                 : // should be siblings in the frame tree. Although (1) rows and cols, (2) row
    5734                 : // groups and col groups, (3) row groups and captions, (4) legends and content
    5735                 : // inside fieldsets, (5) popups and other kids of the menu are siblings from a
    5736                 : // content perspective, they are not considered siblings in the frame tree.
    5737                 : bool
    5738               0 : nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
    5739                 :                                       nsIContent*            aContent,
    5740                 :                                       PRUint8&               aDisplay)
    5741                 : {
    5742               0 :   nsIFrame* parentFrame = aSibling->GetParent();
    5743               0 :   nsIAtom* parentType = nsnull;
    5744               0 :   nsIAtom* grandparentType = nsnull;
    5745               0 :   if (parentFrame) {
    5746               0 :     parentType = parentFrame->GetType();
    5747               0 :     nsIFrame* grandparentFrame = parentFrame->GetParent();
    5748               0 :     if (grandparentFrame) {
    5749               0 :       grandparentType = grandparentFrame->GetType();
    5750                 :     }
    5751                 :   }
    5752                 :     
    5753               0 :   PRUint8 siblingDisplay = aSibling->GetStyleDisplay()->mDisplay;
    5754               0 :   if ((NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == siblingDisplay) ||
    5755                 :       (NS_STYLE_DISPLAY_TABLE_COLUMN       == siblingDisplay) ||
    5756                 :       (NS_STYLE_DISPLAY_TABLE_CAPTION      == siblingDisplay) ||
    5757                 :       (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == siblingDisplay) ||
    5758                 :       (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == siblingDisplay) ||
    5759                 :       (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == siblingDisplay) ||
    5760                 :       nsGkAtoms::menuFrame == parentType) {
    5761                 :     // if we haven't already, construct a style context to find the display type of aContent
    5762               0 :     if (UNSET_DISPLAY == aDisplay) {
    5763               0 :       nsRefPtr<nsStyleContext> styleContext;
    5764               0 :       nsIFrame* styleParent = aSibling->GetParentStyleContextFrame();
    5765               0 :       if (!styleParent) {
    5766               0 :         NS_NOTREACHED("Shouldn't happen");
    5767               0 :         return false;
    5768                 :       }
    5769                 :       // XXXbz when this code is killed, the state argument to
    5770                 :       // ResolveStyleContext can be made non-optional.
    5771               0 :       styleContext = ResolveStyleContext(styleParent, aContent, nsnull);
    5772               0 :       if (!styleContext) return false;
    5773               0 :       const nsStyleDisplay* display = styleContext->GetStyleDisplay();
    5774               0 :       aDisplay = display->mDisplay;
    5775                 :     }
    5776               0 :     if (nsGkAtoms::menuFrame == parentType) {
    5777                 :       return
    5778                 :         (NS_STYLE_DISPLAY_POPUP == aDisplay) ==
    5779               0 :         (NS_STYLE_DISPLAY_POPUP == siblingDisplay);
    5780                 :     }
    5781                 :     // To have decent performance we want to return false in cases in which
    5782                 :     // reordering the two siblings has no effect on display.  To ensure
    5783                 :     // correctness, we MUST return false in cases where the two siblings have
    5784                 :     // the same desired parent type and live on different display lists.
    5785                 :     // Specificaly, columns and column groups should only consider columns and
    5786                 :     // column groups as valid siblings.  Captions should only consider other
    5787                 :     // captions.  All other things should consider each other as valid
    5788                 :     // siblings.  The restriction in the |if| above on siblingDisplay is ok,
    5789                 :     // because for correctness the only part that really needs to happen is to
    5790                 :     // not consider captions, column groups, and row/header/footer groups
    5791                 :     // siblings of each other.  Treating a column or colgroup as a valid
    5792                 :     // sibling of a non-table-related frame will just mean we end up reframing.
    5793               0 :     if ((siblingDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION) !=
    5794                 :         (aDisplay == NS_STYLE_DISPLAY_TABLE_CAPTION)) {
    5795                 :       // One's a caption and the other is not.  Not valid siblings.
    5796               0 :       return false;
    5797                 :     }
    5798                 : 
    5799               0 :     if ((siblingDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ||
    5800                 :          siblingDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN) !=
    5801                 :         (aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ||
    5802                 :          aDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN)) {
    5803                 :       // One's a column or column group and the other is not.  Not valid
    5804                 :       // siblings.
    5805               0 :       return false;
    5806                 :     }
    5807                 : 
    5808               0 :     return true;
    5809                 :   }
    5810               0 :   else if (nsGkAtoms::fieldSetFrame == parentType ||
    5811                 :            (nsGkAtoms::fieldSetFrame == grandparentType &&
    5812                 :             nsGkAtoms::blockFrame == parentType)) {
    5813                 :     // Legends can be sibling of legends but not of other content in the fieldset
    5814               0 :     nsIAtom* sibType = aSibling->GetType();
    5815               0 :     nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aContent));
    5816                 : 
    5817               0 :     if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
    5818               0 :         (!legendContent && (nsGkAtoms::legendFrame == sibType)))
    5819               0 :       return false;
    5820                 :   }
    5821                 : 
    5822               0 :   return true;
    5823                 : }
    5824                 : 
    5825                 : nsIFrame*
    5826               0 : nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
    5827                 :                                                   nsIContent* aTargetContent,
    5828                 :                                                   PRUint8& aTargetContentDisplay,
    5829                 :                                                   bool aPrevSibling)
    5830                 : {
    5831               0 :   nsIFrame* sibling = aContent->GetPrimaryFrame();
    5832               0 :   if (!sibling || sibling->GetContent() != aContent) {
    5833                 :     // XXX the GetContent() != aContent check is needed due to bug 135040.
    5834                 :     // Remove it once that's fixed.
    5835               0 :     return nsnull;
    5836                 :   }
    5837                 : 
    5838                 :   // If the frame is out-of-flow, GetPrimaryFrame() will have returned the
    5839                 :   // out-of-flow frame; we want the placeholder.
    5840               0 :   if (sibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    5841               0 :     nsIFrame* placeholderFrame = GetPlaceholderFrameFor(sibling);
    5842               0 :     NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
    5843               0 :     sibling = placeholderFrame;
    5844                 :   }
    5845                 : 
    5846                 :   // The frame we have now should never be a continuation
    5847               0 :   NS_ASSERTION(!sibling->GetPrevContinuation(), "How did that happen?");
    5848                 : 
    5849               0 :   if (aPrevSibling) {
    5850                 :     // The frame may be a special frame (a split inline frame that
    5851                 :     // contains a block).  Get the last part of that split.
    5852               0 :     if (IsFrameSpecial(sibling)) {
    5853               0 :       sibling = GetLastSpecialSibling(sibling, true);
    5854                 :     }
    5855                 : 
    5856                 :     // The frame may have a continuation. If so, we want the last
    5857                 :     // non-overflow-container continuation as our previous sibling.
    5858               0 :     sibling = sibling->GetTailContinuation();
    5859                 :   }
    5860                 : 
    5861               0 :   if (aTargetContent &&
    5862               0 :       !IsValidSibling(sibling, aTargetContent, aTargetContentDisplay)) {
    5863               0 :     sibling = nsnull;
    5864                 :   }
    5865                 : 
    5866               0 :   return sibling;
    5867                 : }
    5868                 : 
    5869                 : nsIFrame*
    5870               0 : nsCSSFrameConstructor::FindPreviousSibling(const ChildIterator& aFirst,
    5871                 :                                            ChildIterator aIter,
    5872                 :                                            PRUint8& aTargetContentDisplay)
    5873                 : {
    5874               0 :   nsIContent* child = *aIter;
    5875                 : 
    5876                 :   // Note: not all content objects are associated with a frame (e.g., if it's
    5877                 :   // `display: none') so keep looking until we find a previous frame
    5878               0 :   while (aIter != aFirst) {
    5879               0 :     --aIter;
    5880                 :     nsIFrame* prevSibling =
    5881               0 :       FindFrameForContentSibling(*aIter, child, aTargetContentDisplay, true);
    5882                 : 
    5883               0 :     if (prevSibling) {
    5884                 :       // Found a previous sibling, we're done!
    5885               0 :       return prevSibling;
    5886                 :     }
    5887                 :   }
    5888                 : 
    5889               0 :   return nsnull;
    5890                 : }
    5891                 : 
    5892                 : nsIFrame*
    5893               0 : nsCSSFrameConstructor::FindNextSibling(ChildIterator aIter,
    5894                 :                                        const ChildIterator& aLast,
    5895                 :                                        PRUint8& aTargetContentDisplay)
    5896                 : {
    5897               0 :   if (aIter == aLast) {
    5898                 :     // XXXbz Can happen when XBL lies to us about insertion points.  This check
    5899                 :     // might be able to go away once bug 474324 is fixed.
    5900               0 :     return nsnull;
    5901                 :   }
    5902                 : 
    5903               0 :   nsIContent* child = *aIter;
    5904                 : 
    5905               0 :   while (++aIter != aLast) {
    5906                 :     nsIFrame* nextSibling =
    5907               0 :       FindFrameForContentSibling(*aIter, child, aTargetContentDisplay, false);
    5908                 : 
    5909               0 :     if (nextSibling) {
    5910                 :       // We found a next sibling, we're done!
    5911               0 :       return nextSibling;
    5912                 :     }
    5913                 :   }
    5914                 : 
    5915               0 :   return nsnull;
    5916                 : }
    5917                 : 
    5918                 : // For fieldsets, returns the area frame, if the child is not a legend. 
    5919                 : static nsIFrame*
    5920               0 : GetAdjustedParentFrame(nsIFrame*       aParentFrame,
    5921                 :                        nsIAtom*        aParentFrameType,
    5922                 :                        nsIContent*     aChildContent)
    5923                 : {
    5924               0 :   NS_PRECONDITION(nsGkAtoms::tableOuterFrame != aParentFrameType,
    5925                 :                   "Shouldn't be happening!");
    5926                 :   
    5927               0 :   nsIFrame* newParent = nsnull;
    5928                 : 
    5929               0 :   if (nsGkAtoms::fieldSetFrame == aParentFrameType) {
    5930                 :     // If the parent is a fieldSet, use the fieldSet's area frame as the
    5931                 :     // parent unless the new content is a legend. 
    5932               0 :     nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aChildContent));
    5933               0 :     if (!legendContent) {
    5934               0 :       newParent = GetFieldSetBlockFrame(aParentFrame);
    5935                 :     }
    5936                 :   }
    5937               0 :   return (newParent) ? newParent : aParentFrame;
    5938                 : }
    5939                 : 
    5940                 : nsIFrame*
    5941               0 : nsCSSFrameConstructor::GetInsertionPrevSibling(nsIFrame*& aParentFrame,
    5942                 :                                                nsIContent* aContainer,
    5943                 :                                                nsIContent* aChild,
    5944                 :                                                bool* aIsAppend,
    5945                 :                                                bool* aIsRangeInsertSafe,
    5946                 :                                                nsIContent* aStartSkipChild,
    5947                 :                                                nsIContent* aEndSkipChild)
    5948                 : {
    5949               0 :   *aIsAppend = false;
    5950                 : 
    5951                 :   // Find the frame that precedes the insertion point. Walk backwards
    5952                 :   // from the parent frame to get the parent content, because if an
    5953                 :   // XBL insertion point is involved, we'll need to use _that_ to find
    5954                 :   // the preceding frame.
    5955                 : 
    5956               0 :   NS_PRECONDITION(aParentFrame, "Must have parent frame to start with");
    5957               0 :   nsIContent* container = aParentFrame->GetContent();
    5958                 : 
    5959               0 :   ChildIterator first, last;
    5960               0 :   ChildIterator::Init(container, &first, &last);
    5961               0 :   ChildIterator iter(first);
    5962               0 :   bool xblCase = iter.XBLInvolved() || container != aContainer;
    5963               0 :   if (xblCase || !aChild->IsRootOfAnonymousSubtree()) {
    5964                 :     // The check for IsRootOfAnonymousSubtree() is because editor is
    5965                 :     // severely broken and calls us directly for native anonymous
    5966                 :     // nodes that it creates.
    5967               0 :     if (aStartSkipChild) {
    5968               0 :       iter.seek(aStartSkipChild);
    5969                 :     } else {
    5970               0 :       iter.seek(aChild);
    5971                 :     }
    5972                 :   }
    5973                 : #ifdef DEBUG
    5974                 :   else {
    5975                 :     NS_WARNING("Someone passed native anonymous content directly into frame "
    5976               0 :                "construction.  Stop doing that!");
    5977                 :   }
    5978                 : #endif
    5979                 : 
    5980               0 :   PRUint8 childDisplay = UNSET_DISPLAY;
    5981               0 :   nsIFrame* prevSibling = FindPreviousSibling(first, iter, childDisplay);
    5982                 : 
    5983                 :   // Now, find the geometric parent so that we can handle
    5984                 :   // continuations properly. Use the prev sibling if we have it;
    5985                 :   // otherwise use the next sibling.
    5986               0 :   if (prevSibling) {
    5987               0 :     aParentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
    5988                 :   }
    5989                 :   else {
    5990                 :     // If there is no previous sibling, then find the frame that follows
    5991               0 :     if (aEndSkipChild) {
    5992               0 :       iter.seek(aEndSkipChild);
    5993               0 :       iter--;
    5994                 :     }
    5995               0 :     nsIFrame* nextSibling = FindNextSibling(iter, last, childDisplay);
    5996                 : 
    5997               0 :     if (nextSibling) {
    5998               0 :       aParentFrame = nextSibling->GetParent()->GetContentInsertionFrame();
    5999                 :     }
    6000                 :     else {
    6001                 :       // No previous or next sibling, so treat this like an appended frame.
    6002               0 :       *aIsAppend = true;
    6003               0 :       if (IsFrameSpecial(aParentFrame)) {
    6004                 :         // Since we're appending, we'll walk to the last anonymous frame
    6005                 :         // that was created for the broken inline frame.  But don't walk
    6006                 :         // to the trailing inline if it's empty; stop at the block.
    6007               0 :         aParentFrame = GetLastSpecialSibling(aParentFrame, false);
    6008                 :       }
    6009                 :       // Get continuation that parents the last child.  This MUST be done
    6010                 :       // before the AdjustAppendParentForAfterContent call.
    6011               0 :       aParentFrame = nsLayoutUtils::GetLastContinuationWithChild(aParentFrame);
    6012                 :       // Deal with fieldsets
    6013                 :       aParentFrame = ::GetAdjustedParentFrame(aParentFrame,
    6014               0 :                                               aParentFrame->GetType(),
    6015               0 :                                               aChild);
    6016                 :       nsIFrame* appendAfterFrame;
    6017                 :       aParentFrame =
    6018                 :         ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
    6019                 :                                             container, aParentFrame,
    6020               0 :                                             &appendAfterFrame);
    6021               0 :       prevSibling = ::FindAppendPrevSibling(aParentFrame, appendAfterFrame);
    6022                 :     }
    6023                 :   }
    6024                 : 
    6025               0 :   *aIsRangeInsertSafe = (childDisplay == UNSET_DISPLAY);
    6026               0 :   return prevSibling;
    6027                 : }
    6028                 : 
    6029                 : static bool
    6030               0 : IsSpecialFramesetChild(nsIContent* aContent)
    6031                 : {
    6032                 :   // IMPORTANT: This must match the conditions in nsHTMLFramesetFrame::Init.
    6033               0 :   return aContent->IsHTML() &&
    6034               0 :     (aContent->Tag() == nsGkAtoms::frameset ||
    6035               0 :      aContent->Tag() == nsGkAtoms::frame);
    6036                 : }
    6037                 : 
    6038                 : static void
    6039                 : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node);
    6040                 : 
    6041                 : #ifdef MOZ_XUL
    6042                 : 
    6043                 : static
    6044                 : bool
    6045               0 : IsXULListBox(nsIContent* aContainer)
    6046                 : {
    6047               0 :   return (aContainer->IsXUL() && aContainer->Tag() == nsGkAtoms::listbox);
    6048                 : }
    6049                 : 
    6050                 : static
    6051                 : nsListBoxBodyFrame*
    6052               0 : MaybeGetListBoxBodyFrame(nsIContent* aContainer, nsIContent* aChild)
    6053                 : {
    6054               0 :   if (!aContainer)
    6055               0 :     return nsnull;
    6056                 : 
    6057               0 :   if (IsXULListBox(aContainer) &&
    6058               0 :       aChild->IsXUL() && aChild->Tag() == nsGkAtoms::listitem) {
    6059               0 :     nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(aContainer);
    6060               0 :     nsCOMPtr<nsIBoxObject> boxObject;
    6061               0 :     xulElement->GetBoxObject(getter_AddRefs(boxObject));
    6062               0 :     nsCOMPtr<nsPIListBoxObject> listBoxObject = do_QueryInterface(boxObject);
    6063               0 :     if (listBoxObject) {
    6064               0 :       return listBoxObject->GetListBoxBody(false);
    6065                 :     }
    6066                 :   }
    6067                 : 
    6068               0 :   return nsnull;
    6069                 : }
    6070                 : #endif
    6071                 : 
    6072                 : void
    6073               0 : nsCSSFrameConstructor::AddTextItemIfNeeded(nsFrameConstructorState& aState,
    6074                 :                                            nsIFrame* aParentFrame,
    6075                 :                                            nsIContent* aPossibleTextContent,
    6076                 :                                            FrameConstructionItemList& aItems)
    6077                 : {
    6078               0 :   NS_PRECONDITION(aPossibleTextContent, "Must have node");
    6079               0 :   if (!aPossibleTextContent->IsNodeOfType(nsINode::eTEXT) ||
    6080               0 :       !aPossibleTextContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
    6081                 :     // Not text, or not suppressed due to being all-whitespace (if it
    6082                 :     // were being suppressed, it would have the
    6083                 :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
    6084               0 :     return;
    6085                 :   }
    6086               0 :   NS_ASSERTION(!aPossibleTextContent->GetPrimaryFrame(),
    6087                 :                "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    6088                 :   AddFrameConstructionItems(aState, aPossibleTextContent, false,
    6089               0 :                             aParentFrame, aItems);
    6090                 : }
    6091                 : 
    6092                 : void
    6093               0 : nsCSSFrameConstructor::ReframeTextIfNeeded(nsIContent* aParentContent,
    6094                 :                                            nsIContent* aContent)
    6095                 : {
    6096               0 :   if (!aContent->IsNodeOfType(nsINode::eTEXT) ||
    6097               0 :       !aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
    6098                 :     // Not text, or not suppressed due to being all-whitespace (if it
    6099                 :     // were being suppressed, it would have the
    6100                 :     // NS_CREATE_FRAME_IF_NON_WHITESPACE flag)
    6101               0 :     return;
    6102                 :   }
    6103               0 :   NS_ASSERTION(!aContent->GetPrimaryFrame(),
    6104                 :                "Text node has a frame and NS_CREATE_FRAME_IF_NON_WHITESPACE");
    6105               0 :   ContentInserted(aParentContent, aContent, nsnull, false);
    6106                 : }
    6107                 : 
    6108                 : // We want to disable lazy frame construction for nodes that are under an
    6109                 : // editor. We use nsINode::IsEditable, but that includes inputs with type text
    6110                 : // and password and textareas, which are common and aren't really editable (the
    6111                 : // native anonymous content under them is what is actually editable) so we want
    6112                 : // to construct frames for those lazily.
    6113                 : // The logic for this check is based on
    6114                 : // nsGenericHTMLFormElement::UpdateEditableFormControlState and so must be kept
    6115                 : // in sync with that.  MayHaveContentEditableAttr() being true only indicates
    6116                 : // a contenteditable attribute, it doesn't indicate whether it is true or false,
    6117                 : // so we force eager construction in some cases when the node is not editable,
    6118                 : // but that should be rare.
    6119                 : static inline bool
    6120               0 : IsActuallyEditable(nsIContent* aContainer, nsIContent* aChild)
    6121                 : {
    6122               0 :   return (aChild->IsEditable() &&
    6123               0 :           (aContainer->IsEditable() ||
    6124               0 :            aChild->MayHaveContentEditableAttr()));
    6125                 : }
    6126                 : 
    6127                 : // For inserts aChild should be valid, for appends it should be null.
    6128                 : // Returns true if this operation can be lazy, false if not.
    6129                 : bool
    6130               0 : nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
    6131                 :                                             nsIContent* aContainer,
    6132                 :                                             nsIContent* aChild)
    6133                 : {
    6134               0 :   if (mPresShell->GetPresContext()->IsChrome() || !aContainer ||
    6135               0 :       aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXUL()) {
    6136               0 :     return false;
    6137                 :   }
    6138                 : 
    6139               0 :   if (aOperation == CONTENTINSERT) {
    6140               0 :     if (aChild->IsRootOfAnonymousSubtree() ||
    6141               0 :         aChild->IsXUL() || IsActuallyEditable(aContainer, aChild)) {
    6142               0 :       return false;
    6143                 :     }
    6144                 :   } else { // CONTENTAPPEND
    6145               0 :     NS_ASSERTION(aOperation == CONTENTAPPEND,
    6146                 :                  "operation should be either insert or append");
    6147               0 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    6148               0 :       NS_ASSERTION(!child->IsRootOfAnonymousSubtree(),
    6149                 :                    "Should be coming through the CONTENTAPPEND case");
    6150               0 :       if (child->IsXUL() || IsActuallyEditable(aContainer, child)) {
    6151               0 :         return false;
    6152                 :       }
    6153                 :     }
    6154                 :   }
    6155                 : 
    6156                 :   // We can construct lazily; just need to set suitable bits in the content
    6157                 :   // tree.
    6158                 : 
    6159                 :   // Walk up the tree setting the NODE_DESCENDANTS_NEED_FRAMES bit as we go.
    6160               0 :   nsIContent* content = aContainer;
    6161                 : #ifdef DEBUG
    6162                 :   // If we hit a node with no primary frame, or the NODE_NEEDS_FRAME bit set
    6163                 :   // we want to assert, but leaf frames that process their own children and may
    6164                 :   // ignore anonymous children (eg framesets) make this complicated. So we set
    6165                 :   // these two booleans if we encounter these situations and unset them if we
    6166                 :   // hit a node with a leaf frame.
    6167               0 :   bool noPrimaryFrame = false;
    6168               0 :   bool needsFrameBitSet = false;
    6169                 : #endif
    6170               0 :   while (content &&
    6171               0 :          !content->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    6172                 : #ifdef DEBUG
    6173               0 :     if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
    6174               0 :       noPrimaryFrame = needsFrameBitSet = false;
    6175                 :     }
    6176               0 :     if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
    6177               0 :       noPrimaryFrame = true;
    6178                 :     }
    6179               0 :     if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
    6180               0 :       needsFrameBitSet = true;
    6181                 :     }
    6182                 : #endif
    6183               0 :     content->SetFlags(NODE_DESCENDANTS_NEED_FRAMES);
    6184               0 :     content = content->GetFlattenedTreeParent();
    6185                 :   }
    6186                 : #ifdef DEBUG
    6187               0 :   if (content && content->GetPrimaryFrame() &&
    6188               0 :       content->GetPrimaryFrame()->IsLeaf()) {
    6189               0 :     noPrimaryFrame = needsFrameBitSet = false;
    6190                 :   }
    6191               0 :   NS_ASSERTION(!noPrimaryFrame, "Ancestors of nodes with frames to be "
    6192                 :     "constructed lazily should have frames");
    6193               0 :   NS_ASSERTION(!needsFrameBitSet, "Ancestors of nodes with frames to be "
    6194                 :     "constructed lazily should not have NEEDS_FRAME bit set");
    6195                 : #endif
    6196                 : 
    6197                 :   // Set NODE_NEEDS_FRAME on the new nodes.
    6198               0 :   if (aOperation == CONTENTINSERT) {
    6199               0 :     NS_ASSERTION(!aChild->GetPrimaryFrame() ||
    6200                 :                  aChild->GetPrimaryFrame()->GetContent() != aChild,
    6201                 :                  //XXX the aChild->GetPrimaryFrame()->GetContent() != aChild
    6202                 :                  // check is needed due to bug 135040. Remove it once that's
    6203                 :                  // fixed.
    6204                 :                  "setting NEEDS_FRAME on a node that already has a frame?");
    6205               0 :     aChild->SetFlags(NODE_NEEDS_FRAME);
    6206                 :   } else { // CONTENTAPPEND
    6207               0 :     for (nsIContent* child = aChild; child; child = child->GetNextSibling()) {
    6208               0 :       NS_ASSERTION(!child->GetPrimaryFrame() ||
    6209                 :                    child->GetPrimaryFrame()->GetContent() != child,
    6210                 :                    //XXX the child->GetPrimaryFrame()->GetContent() != child
    6211                 :                    // check is needed due to bug 135040. Remove it once that's
    6212                 :                    // fixed.
    6213                 :                    "setting NEEDS_FRAME on a node that already has a frame?");
    6214               0 :       child->SetFlags(NODE_NEEDS_FRAME);
    6215                 :     }
    6216                 :   }
    6217                 : 
    6218               0 :   PostRestyleEventInternal(true);
    6219               0 :   return true;
    6220                 : }
    6221                 : 
    6222                 : void
    6223               0 : nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent)
    6224                 : {
    6225               0 :   NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME),
    6226                 :     "shouldn't get here with a content node that has needs frame bit set");
    6227               0 :   NS_ASSERTION(aContent->HasFlag(NODE_DESCENDANTS_NEED_FRAMES),
    6228                 :     "should only get here with a content node that has descendants needing frames");
    6229                 : 
    6230               0 :   aContent->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
    6231                 : 
    6232                 :   // We could either descend first (on nodes that don't have NODE_NEEDS_FRAME
    6233                 :   // set) or issue content notifications for our kids first. In absence of
    6234                 :   // anything definitive either way we'll go with the latter.
    6235                 : 
    6236                 :   // It might be better to use GetChildArray and scan it completely first and
    6237                 :   // then issue all notifications. (We have to scan it completely first because
    6238                 :   // constructing frames can set attributes, which can change the storage of
    6239                 :   // child lists).
    6240                 : 
    6241                 :   // Scan the children of aContent to see what operations (if any) we need to
    6242                 :   // perform.
    6243               0 :   PRUint32 childCount = aContent->GetChildCount();
    6244               0 :   bool inRun = false;
    6245               0 :   nsIContent* firstChildInRun = nsnull;
    6246               0 :   for (PRUint32 i = 0; i < childCount; i++) {
    6247               0 :     nsIContent* child = aContent->GetChildAt(i);
    6248               0 :     if (child->HasFlag(NODE_NEEDS_FRAME)) {
    6249               0 :       NS_ASSERTION(!child->GetPrimaryFrame() ||
    6250                 :                    child->GetPrimaryFrame()->GetContent() != child,
    6251                 :                    //XXX the child->GetPrimaryFrame()->GetContent() != child
    6252                 :                    // check is needed due to bug 135040. Remove it once that's
    6253                 :                    // fixed.
    6254                 :                    "NEEDS_FRAME set on a node that already has a frame?");
    6255               0 :       if (!inRun) {
    6256               0 :         inRun = true;
    6257               0 :         firstChildInRun = child;
    6258                 :       }
    6259                 :     } else {
    6260               0 :       if (inRun) {
    6261               0 :         inRun = false;
    6262                 :         // generate a ContentRangeInserted for [startOfRun,i)
    6263                 :         ContentRangeInserted(aContent, firstChildInRun, child, nsnull,
    6264               0 :                              false);
    6265                 :       }
    6266                 :     }
    6267                 :   }
    6268               0 :   if (inRun) {
    6269               0 :     ContentAppended(aContent, firstChildInRun, false);
    6270                 :   }
    6271                 : 
    6272                 :   // Now descend.
    6273               0 :   ChildIterator iter, last;
    6274               0 :   for (ChildIterator::Init(aContent, &iter, &last);
    6275                 :        iter != last;
    6276                 :        ++iter) {
    6277               0 :     nsIContent* child = *iter;
    6278               0 :     if (child->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    6279               0 :       CreateNeededFrames(child);
    6280                 :     }
    6281                 :   }
    6282               0 : }
    6283                 : 
    6284               0 : void nsCSSFrameConstructor::CreateNeededFrames()
    6285                 : {
    6286               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    6287                 :                "Someone forgot a script blocker");
    6288                 : 
    6289               0 :   Element* rootElement = mDocument->GetRootElement();
    6290               0 :   NS_ASSERTION(!rootElement || !rootElement->HasFlag(NODE_NEEDS_FRAME),
    6291                 :     "root element should not have frame created lazily");
    6292               0 :   if (rootElement && rootElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES)) {
    6293               0 :     BeginUpdate();
    6294               0 :     CreateNeededFrames(rootElement);
    6295               0 :     EndUpdate();
    6296                 :   }
    6297               0 : }
    6298                 : 
    6299                 : void
    6300               0 : nsCSSFrameConstructor::IssueSingleInsertNofications(nsIContent* aContainer,
    6301                 :                                                     nsIContent* aStartChild,
    6302                 :                                                     nsIContent* aEndChild,
    6303                 :                                                     bool aAllowLazyConstruction)
    6304                 : {
    6305               0 :   for (nsIContent* child = aStartChild;
    6306                 :        child != aEndChild;
    6307               0 :        child = child->GetNextSibling()) {
    6308               0 :     if ((child->GetPrimaryFrame() ||
    6309               0 :          GetUndisplayedContent(child))
    6310                 : #ifdef MOZ_XUL
    6311                 :         //  Except listboxes suck, so do NOT skip anything here if
    6312                 :         //  we plan to notify a listbox.
    6313               0 :         && !MaybeGetListBoxBodyFrame(aContainer, child)
    6314                 : #endif
    6315                 :         ) {
    6316                 :       // Already have a frame or undisplayed entry for this content; a
    6317                 :       // previous ContentInserted in this loop must have reconstructed
    6318                 :       // its insertion parent.  Skip it.
    6319               0 :       continue;
    6320                 :     }
    6321                 :     // Call ContentInserted with this node.
    6322                 :     ContentInserted(aContainer, child, mTempFrameTreeState,
    6323               0 :                     aAllowLazyConstruction);
    6324                 :   }
    6325               0 : }
    6326                 : 
    6327                 : nsIFrame*
    6328               0 : nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer,
    6329                 :                                               nsIFrame* aParentFrame,
    6330                 :                                               nsIContent* aStartChild,
    6331                 :                                               nsIContent* aEndChild,
    6332                 :                                               bool aAllowLazyConstruction)
    6333                 : {
    6334                 :   // See if we have an XBL insertion point. If so, then that's our
    6335                 :   // real parent frame; if not, then the frame hasn't been built yet
    6336                 :   // and we just bail.
    6337                 :   nsIFrame* insertionPoint;
    6338               0 :   bool multiple = false;
    6339               0 :   GetInsertionPoint(aParentFrame, nsnull, &insertionPoint, &multiple);
    6340               0 :   if (! insertionPoint)
    6341               0 :     return nsnull; // Don't build the frames.
    6342                 :  
    6343               0 :   bool hasInsertion = false;
    6344               0 :   if (!multiple) {
    6345                 :     // XXXbz XBL2/sXBL issue
    6346               0 :     nsIDocument* document = aStartChild->GetDocument();
    6347                 :     // XXXbz how would |document| be null here?
    6348               0 :     if (document &&
    6349               0 :         document->BindingManager()->GetInsertionParent(aStartChild)) {
    6350               0 :       hasInsertion = true;
    6351                 :     }
    6352                 :   }
    6353                 : 
    6354               0 :   if (multiple || hasInsertion) {
    6355                 :     // We have an insertion point.  There are some additional tests we need to do
    6356                 :     // in order to ensure that an append is a safe operation.
    6357               0 :     PRUint32 childCount = 0;
    6358                 : 
    6359               0 :     if (!multiple) {
    6360                 :       // We may need to make multiple ContentInserted calls instead.  A
    6361                 :       // reasonable heuristic to employ (in order to maintain good performance)
    6362                 :       // is to find out if the insertion point's content node contains any
    6363                 :       // explicit children.  If it does not, then it is highly likely that 
    6364                 :       // an append is occurring.  (Note it is not definite, and there are insane
    6365                 :       // cases we will not deal with by employing this heuristic, but it beats
    6366                 :       // always falling back to multiple ContentInserted calls).
    6367                 :       //
    6368                 :       // In the multiple insertion point case, we know we're going to need to do
    6369                 :       // multiple ContentInserted calls anyway.
    6370               0 :       childCount = insertionPoint->GetContent()->GetChildCount();
    6371                 :     }
    6372                 :  
    6373                 :     // If we have multiple insertion points or if we have an insertion point
    6374                 :     // and the operation is not a true append or if the insertion point already
    6375                 :     // has explicit children, then we must fall back.
    6376               0 :     if (multiple || aEndChild != nsnull || childCount > 0) {
    6377                 :       // Now comes the fun part.  For each inserted child, make a
    6378                 :       // ContentInserted call as if it had just gotten inserted and
    6379                 :       // let ContentInserted handle the mess.
    6380                 :       IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    6381               0 :                                    aAllowLazyConstruction);
    6382               0 :       return nsnull;
    6383                 :     }
    6384                 :   }
    6385                 : 
    6386               0 :   return insertionPoint;
    6387                 : }
    6388                 : 
    6389                 : bool
    6390               0 : nsCSSFrameConstructor::MaybeRecreateForFrameset(nsIFrame* aParentFrame,
    6391                 :                                                 nsIContent* aStartChild,
    6392                 :                                                 nsIContent* aEndChild)
    6393                 : {
    6394               0 :   if (aParentFrame->GetType() == nsGkAtoms::frameSetFrame) {
    6395                 :     // Check whether we have any kids we care about.
    6396               0 :     for (nsIContent* cur = aStartChild;
    6397                 :          cur != aEndChild;
    6398               0 :          cur = cur->GetNextSibling()) {
    6399               0 :       if (IsSpecialFramesetChild(cur)) {
    6400                 :         // Just reframe the parent, since framesets are weird like that.
    6401               0 :         RecreateFramesForContent(aParentFrame->GetContent(), false);
    6402               0 :         return true;
    6403                 :       }
    6404                 :     }
    6405                 :   }
    6406               0 :   return false;
    6407                 : }
    6408                 : 
    6409                 : nsresult
    6410               0 : nsCSSFrameConstructor::ContentAppended(nsIContent*     aContainer,
    6411                 :                                        nsIContent*     aFirstNewContent,
    6412                 :                                        bool            aAllowLazyConstruction)
    6413                 : {
    6414               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    6415               0 :   NS_PRECONDITION(mUpdateCount != 0,
    6416                 :                   "Should be in an update while creating frames");
    6417                 : 
    6418                 : #ifdef DEBUG
    6419               0 :   if (gNoisyContentUpdates) {
    6420                 :     printf("nsCSSFrameConstructor::ContentAppended container=%p "
    6421                 :            "first-child=%p lazy=%d\n",
    6422                 :            static_cast<void*>(aContainer), aFirstNewContent,
    6423               0 :            aAllowLazyConstruction);
    6424               0 :     if (gReallyNoisyContentUpdates && aContainer) {
    6425               0 :       aContainer->List(stdout, 0);
    6426                 :     }
    6427                 :   }
    6428                 : #endif
    6429                 : 
    6430                 : #ifdef DEBUG
    6431               0 :   for (nsIContent* child = aFirstNewContent;
    6432                 :        child;
    6433               0 :        child = child->GetNextSibling()) {
    6434                 :     // XXX the GetContent() != child check is needed due to bug 135040.
    6435                 :     // Remove it once that's fixed.  
    6436               0 :     NS_ASSERTION(!child->GetPrimaryFrame() ||
    6437                 :                  child->GetPrimaryFrame()->GetContent() != child,
    6438                 :                  "asked to construct a frame for a node that already has a frame");
    6439                 :   }
    6440                 : #endif
    6441                 : 
    6442                 : #ifdef MOZ_XUL
    6443               0 :   if (aContainer) {
    6444                 :     PRInt32 namespaceID;
    6445                 :     nsIAtom* tag =
    6446               0 :       mDocument->BindingManager()->ResolveTag(aContainer, &namespaceID);
    6447                 : 
    6448                 :     // Just ignore tree tags, anyway we don't create any frames for them.
    6449               0 :     if (tag == nsGkAtoms::treechildren ||
    6450                 :         tag == nsGkAtoms::treeitem ||
    6451                 :         tag == nsGkAtoms::treerow)
    6452               0 :       return NS_OK;
    6453                 : 
    6454                 :   }
    6455                 : #endif // MOZ_XUL
    6456                 : 
    6457                 :   // Get the frame associated with the content
    6458               0 :   nsIFrame* parentFrame = GetFrameFor(aContainer);
    6459               0 :   if (! parentFrame)
    6460               0 :     return NS_OK;
    6461                 : 
    6462               0 :   if (aAllowLazyConstruction &&
    6463               0 :       MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) {
    6464               0 :     return NS_OK;
    6465                 :   }
    6466                 : 
    6467               0 :   LAYOUT_PHASE_TEMP_EXIT();
    6468                 :   parentFrame = GetRangeInsertionPoint(aContainer, parentFrame,
    6469                 :                                        aFirstNewContent, nsnull,
    6470               0 :                                        aAllowLazyConstruction);
    6471               0 :   LAYOUT_PHASE_TEMP_REENTER();
    6472               0 :   if (!parentFrame) {
    6473               0 :     return NS_OK;
    6474                 :   }
    6475                 : 
    6476               0 :   LAYOUT_PHASE_TEMP_EXIT();
    6477               0 :   if (MaybeRecreateForFrameset(parentFrame, aFirstNewContent, nsnull)) {
    6478               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6479               0 :     return NS_OK;
    6480                 :   }
    6481               0 :   LAYOUT_PHASE_TEMP_REENTER();  
    6482                 : 
    6483               0 :   if (parentFrame->IsLeaf()) {
    6484                 :     // Nothing to do here; we shouldn't be constructing kids of leaves
    6485                 :     // Clear lazy bits so we don't try to construct again.
    6486               0 :     ClearLazyBits(aFirstNewContent, nsnull);
    6487               0 :     return NS_OK;
    6488                 :   }
    6489                 :   
    6490               0 :   if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    6491               0 :     LAYOUT_PHASE_TEMP_EXIT();
    6492               0 :     nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
    6493               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6494               0 :     return rv;
    6495                 :   }
    6496                 : 
    6497                 :   // If the frame we are manipulating is a ``special'' frame (that is, one
    6498                 :   // that's been created as a result of a block-in-inline situation) then we
    6499                 :   // need to append to the last special sibling, not to the frame itself.
    6500               0 :   bool parentSpecial = IsFrameSpecial(parentFrame);
    6501               0 :   if (parentSpecial) {
    6502                 : #ifdef DEBUG
    6503               0 :     if (gNoisyContentUpdates) {
    6504               0 :       printf("nsCSSFrameConstructor::ContentAppended: parentFrame=");
    6505               0 :       nsFrame::ListTag(stdout, parentFrame);
    6506               0 :       printf(" is special\n");
    6507                 :     }
    6508                 : #endif
    6509                 : 
    6510                 :     // Since we're appending, we'll walk to the last anonymous frame
    6511                 :     // that was created for the broken inline frame.  But don't walk
    6512                 :     // to the trailing inline if it's empty; stop at the block.
    6513               0 :     parentFrame = GetLastSpecialSibling(parentFrame, false);
    6514                 :   }
    6515                 : 
    6516                 :   // Get continuation that parents the last child.  This MUST be done
    6517                 :   // before the AdjustAppendParentForAfterContent call.
    6518               0 :   parentFrame = nsLayoutUtils::GetLastContinuationWithChild(parentFrame);
    6519                 : 
    6520                 :   // We should never get here with fieldsets, since they have multiple
    6521                 :   // insertion points.
    6522               0 :   NS_ASSERTION(parentFrame->GetType() != nsGkAtoms::fieldSetFrame,
    6523                 :                "Unexpected parent");
    6524                 : 
    6525                 :   // Deal with possible :after generated content on the parent
    6526                 :   nsIFrame* parentAfterFrame;
    6527                 :   parentFrame =
    6528                 :     ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
    6529                 :                                         aContainer, parentFrame,
    6530               0 :                                         &parentAfterFrame);
    6531                 :   
    6532                 :   // Create some new frames
    6533                 :   nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
    6534                 :                                 GetAbsoluteContainingBlock(parentFrame),
    6535               0 :                                 GetFloatContainingBlock(parentFrame));
    6536               0 :   state.mTreeMatchContext.mAncestorFilter.Init(aContainer->AsElement());
    6537                 : 
    6538                 :   // See if the containing block has :first-letter style applied.
    6539               0 :   bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
    6540               0 :   nsIFrame* containingBlock = state.mFloatedItems.containingBlock;
    6541               0 :   if (containingBlock) {
    6542               0 :     haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
    6543                 :     haveFirstLineStyle =
    6544                 :       ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    6545               0 :                                containingBlock->GetStyleContext());
    6546                 :   }
    6547                 : 
    6548               0 :   if (haveFirstLetterStyle) {
    6549                 :     // Before we get going, remove the current letter frames
    6550                 :     RemoveLetterFrames(state.mPresContext, state.mPresShell,
    6551               0 :                        containingBlock);
    6552                 :   }
    6553                 : 
    6554               0 :   nsIAtom* frameType = parentFrame->GetType();
    6555                 :   bool haveNoXBLChildren =
    6556               0 :     mDocument->BindingManager()->GetXBLChildNodesFor(aContainer) == nsnull;
    6557               0 :   FrameConstructionItemList items;
    6558               0 :   if (aFirstNewContent->GetPreviousSibling() &&
    6559               0 :       GetParentType(frameType) == eTypeBlock &&
    6560                 :       haveNoXBLChildren) {
    6561                 :     // If there's a text node in the normal content list just before the new
    6562                 :     // items, and it has no frame, make a frame construction item for it. If it
    6563                 :     // doesn't need a frame, ConstructFramesFromItemList below won't give it
    6564                 :     // one.  No need to do all this if our parent type is not block, though,
    6565                 :     // since WipeContainingBlock already handles that situation.
    6566                 :     //
    6567                 :     // Because we're appending, we don't need to worry about any text
    6568                 :     // after the appended content; there can only be XBL anonymous content
    6569                 :     // (text in an XBL binding is not suppressed) or generated content
    6570                 :     // (and bare text nodes are not generated). Native anonymous content
    6571                 :     // generated by frames never participates in inline layout.
    6572                 :     AddTextItemIfNeeded(state, parentFrame,
    6573               0 :                         aFirstNewContent->GetPreviousSibling(), items);
    6574                 :   }
    6575               0 :   for (nsIContent* child = aFirstNewContent;
    6576                 :        child;
    6577               0 :        child = child->GetNextSibling()) {
    6578               0 :     AddFrameConstructionItems(state, child, false, parentFrame, items);
    6579                 :   }
    6580                 : 
    6581               0 :   nsIFrame* prevSibling = ::FindAppendPrevSibling(parentFrame, parentAfterFrame);
    6582                 : 
    6583                 :   // Perform special check for diddling around with the frames in
    6584                 :   // a special inline frame.
    6585                 :   // If we're appending before :after content, then we're not really
    6586                 :   // appending, so let WipeContainingBlock know that.
    6587               0 :   LAYOUT_PHASE_TEMP_EXIT();
    6588               0 :   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
    6589                 :                           true, prevSibling)) {
    6590               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6591               0 :     return NS_OK;
    6592                 :   }
    6593               0 :   LAYOUT_PHASE_TEMP_REENTER();
    6594                 : 
    6595                 :   // If the parent is a block frame, and we're not in a special case
    6596                 :   // where frames can be moved around, determine if the list is for the
    6597                 :   // start or end of the block.
    6598               0 :   if (nsLayoutUtils::GetAsBlock(parentFrame) && !haveFirstLetterStyle &&
    6599               0 :       !haveFirstLineStyle && !parentSpecial) {
    6600                 :     items.SetLineBoundaryAtStart(!prevSibling ||
    6601               0 :         !prevSibling->GetStyleDisplay()->IsInlineOutside() ||
    6602               0 :         prevSibling->GetType() == nsGkAtoms::brFrame);
    6603                 :     // :after content can't be <br> so no need to check it
    6604               0 :     items.SetLineBoundaryAtEnd(!parentAfterFrame ||
    6605               0 :         !parentAfterFrame->GetStyleDisplay()->IsInlineOutside());
    6606                 :   }
    6607                 :   // To suppress whitespace-only text frames, we have to verify that
    6608                 :   // our container's DOM child list matches its flattened tree child list.
    6609                 :   // This is guaranteed to be true if GetXBLChildNodesFor() returns null.
    6610               0 :   items.SetParentHasNoXBLChildren(haveNoXBLChildren);
    6611                 : 
    6612               0 :   nsFrameItems frameItems;
    6613               0 :   ConstructFramesFromItemList(state, items, parentFrame, frameItems);
    6614                 : 
    6615               0 :   for (nsIContent* child = aFirstNewContent;
    6616                 :        child;
    6617               0 :        child = child->GetNextSibling()) {
    6618                 :     // Invalidate now instead of before the WipeContainingBlock call, just in
    6619                 :     // case we do wipe; in that case we don't need to do this walk at all.
    6620                 :     // XXXbz does that matter?  Would it make more sense to save some virtual
    6621                 :     // GetChildAt calls instead and do this during construction of our
    6622                 :     // FrameConstructionItemList?
    6623               0 :     InvalidateCanvasIfNeeded(mPresShell, child);
    6624                 :   }
    6625                 : 
    6626                 :   // if the container is a table and a caption was appended, it needs to be put
    6627                 :   // in the outer table frame's additional child list.
    6628               0 :   nsFrameItems captionItems;
    6629               0 :   if (nsGkAtoms::tableFrame == frameType) {
    6630                 :     // Pull out the captions.  Note that we don't want to do that as we go,
    6631                 :     // because processing a single caption can add a whole bunch of things to
    6632                 :     // the frame items due to pseudoframe processing.  So we'd have to pull
    6633                 :     // captions from a list anyway; might as well do that here.
    6634                 :     // XXXbz this is no longer true; we could pull captions directly out of the
    6635                 :     // FrameConstructionItemList now.
    6636               0 :     PullOutCaptionFrames(frameItems, captionItems);
    6637                 :   }
    6638                 :   
    6639               0 :   if (haveFirstLineStyle && parentFrame == containingBlock) {
    6640                 :     // It's possible that some of the new frames go into a
    6641                 :     // first-line frame. Look at them and see...
    6642                 :     AppendFirstLineFrames(state, containingBlock->GetContent(),
    6643               0 :                           containingBlock, frameItems); 
    6644                 :   }
    6645                 : 
    6646                 :   // Notify the parent frame passing it the list of new frames
    6647                 :   // Append the flowed frames to the principal child list; captions
    6648                 :   // need special treatment
    6649               0 :   if (captionItems.NotEmpty()) { // append the caption to the outer table
    6650               0 :     NS_ASSERTION(nsGkAtoms::tableFrame == frameType, "how did that happen?");
    6651               0 :     nsIFrame* outerTable = parentFrame->GetParent();
    6652               0 :     AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    6653                 :   }
    6654                 : 
    6655               0 :   if (frameItems.NotEmpty()) { // append the in-flow kids
    6656               0 :     AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
    6657                 :   }
    6658                 : 
    6659                 :   // Recover first-letter frames
    6660               0 :   if (haveFirstLetterStyle) {
    6661               0 :     RecoverLetterFrames(containingBlock);
    6662                 :   }
    6663                 : 
    6664                 : #ifdef DEBUG
    6665               0 :   if (gReallyNoisyContentUpdates) {
    6666               0 :     printf("nsCSSFrameConstructor::ContentAppended: resulting frame model:\n");
    6667               0 :     parentFrame->List(stdout, 0);
    6668                 :   }
    6669                 : #endif
    6670                 : 
    6671                 : #ifdef ACCESSIBILITY
    6672               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
    6673               0 :   if (accService) {
    6674                 :     accService->ContentRangeInserted(mPresShell, aContainer,
    6675               0 :                                      aFirstNewContent, nsnull);
    6676                 :   }
    6677                 : #endif
    6678                 : 
    6679               0 :   return NS_OK;
    6680                 : }
    6681                 : 
    6682                 : #ifdef MOZ_XUL
    6683                 : 
    6684                 : enum content_operation
    6685                 : {
    6686                 :     CONTENT_INSERTED,
    6687                 :     CONTENT_REMOVED
    6688                 : };
    6689                 : 
    6690                 : // Helper function to lookup the listbox body frame and send a notification
    6691                 : // for insertion or removal of content
    6692                 : static
    6693               0 : bool NotifyListBoxBody(nsPresContext*    aPresContext,
    6694                 :                          nsIContent*        aContainer,
    6695                 :                          nsIContent*        aChild,
    6696                 :                          // Only used for the removed notification
    6697                 :                          nsIContent*        aOldNextSibling,
    6698                 :                          nsIDocument*       aDocument,                         
    6699                 :                          nsIFrame*          aChildFrame,
    6700                 :                          content_operation  aOperation)
    6701                 : {
    6702                 :   nsListBoxBodyFrame* listBoxBodyFrame =
    6703               0 :     MaybeGetListBoxBodyFrame(aContainer, aChild);
    6704               0 :   if (listBoxBodyFrame) {
    6705               0 :     if (aOperation == CONTENT_REMOVED) {
    6706                 :       // Except if we have an aChildFrame and its parent is not the right
    6707                 :       // thing, then we don't do this.  Pseudo frames are so much fun....
    6708               0 :       if (!aChildFrame || aChildFrame->GetParent() == listBoxBodyFrame) {
    6709                 :         listBoxBodyFrame->OnContentRemoved(aPresContext, aContainer,
    6710               0 :                                            aChildFrame, aOldNextSibling);
    6711               0 :         return true;
    6712                 :       }
    6713                 :     } else {
    6714               0 :       listBoxBodyFrame->OnContentInserted(aPresContext, aChild);
    6715               0 :       return true;
    6716                 :     }
    6717                 :   }
    6718                 : 
    6719               0 :   return false;
    6720                 : }
    6721                 : #endif // MOZ_XUL
    6722                 : 
    6723                 : nsresult
    6724               0 : nsCSSFrameConstructor::ContentInserted(nsIContent*            aContainer,
    6725                 :                                        nsIContent*            aChild,
    6726                 :                                        nsILayoutHistoryState* aFrameState,
    6727                 :                                        bool                   aAllowLazyConstruction)
    6728                 : {
    6729                 :   return ContentRangeInserted(aContainer,
    6730                 :                               aChild,
    6731                 :                               aChild->GetNextSibling(),
    6732                 :                               aFrameState,
    6733               0 :                               aAllowLazyConstruction);
    6734                 : }
    6735                 : 
    6736                 : // ContentRangeInserted handles creating frames for a range of nodes that
    6737                 : // aren't at the end of their childlist. ContentRangeInserted isn't a real
    6738                 : // content notification, but rather it handles regular ContentInserted calls
    6739                 : // for a single node as well as the lazy construction of frames for a range of
    6740                 : // nodes when called from CreateNeededFrames. For a range of nodes to be
    6741                 : // suitable to have its frames constructed all at once they must meet the same
    6742                 : // conditions that ContentAppended imposes (GetRangeInsertionPoint checks
    6743                 : // these), plus more. Namely when finding the insertion prevsibling we must not
    6744                 : // need to consult something specific to any one node in the range, so that the
    6745                 : // insertion prevsibling would be the same for each node in the range. So we
    6746                 : // pass the first node in the range to GetInsertionPrevSibling, and if
    6747                 : // IsValidSibling (the only place GetInsertionPrevSibling might look at the
    6748                 : // passed in node itself) needs to resolve style on the node we record this and
    6749                 : // return that this range needs to be split up and inserted separately. Table
    6750                 : // captions need extra attention as we need to determine where to insert them
    6751                 : // in the caption list, while skipping any nodes in the range being inserted
    6752                 : // (because when we treat the caption frames the other nodes have had their
    6753                 : // frames constructed but not yet inserted into the frame tree).
    6754                 : nsresult
    6755               0 : nsCSSFrameConstructor::ContentRangeInserted(nsIContent*            aContainer,
    6756                 :                                             nsIContent*            aStartChild,
    6757                 :                                             nsIContent*            aEndChild,
    6758                 :                                             nsILayoutHistoryState* aFrameState,
    6759                 :                                             bool                   aAllowLazyConstruction)
    6760                 : {
    6761               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    6762               0 :   NS_PRECONDITION(mUpdateCount != 0,
    6763                 :                   "Should be in an update while creating frames");
    6764                 : 
    6765               0 :   NS_PRECONDITION(aStartChild, "must always pass a child");
    6766                 : 
    6767                 :   // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
    6768                 :   // the :empty pseudo-class?
    6769                 : #ifdef DEBUG
    6770               0 :   if (gNoisyContentUpdates) {
    6771                 :     printf("nsCSSFrameConstructor::ContentRangeInserted container=%p "
    6772                 :            "start-child=%p end-child=%p lazy=%d\n",
    6773                 :            static_cast<void*>(aContainer),
    6774                 :            static_cast<void*>(aStartChild), static_cast<void*>(aEndChild),
    6775               0 :            aAllowLazyConstruction);
    6776               0 :     if (gReallyNoisyContentUpdates) {
    6777               0 :       if (aContainer) {
    6778               0 :         aContainer->List(stdout,0);
    6779                 :       } else {
    6780               0 :         aStartChild->List(stdout, 0);
    6781                 :       }
    6782                 :     }
    6783                 :   }
    6784                 : #endif
    6785                 : 
    6786                 : #ifdef DEBUG
    6787               0 :   for (nsIContent* child = aStartChild;
    6788                 :        child != aEndChild;
    6789               0 :        child = child->GetNextSibling()) {
    6790                 :     // XXX the GetContent() != child check is needed due to bug 135040.
    6791                 :     // Remove it once that's fixed.  
    6792               0 :     NS_ASSERTION(!child->GetPrimaryFrame() ||
    6793                 :                  child->GetPrimaryFrame()->GetContent() != child,
    6794                 :                  "asked to construct a frame for a node that already has a frame");
    6795                 :   }
    6796                 : #endif
    6797                 : 
    6798               0 :   nsresult rv = NS_OK;
    6799                 : 
    6800               0 :   bool isSingleInsert = (aStartChild->GetNextSibling() == aEndChild);
    6801               0 :   NS_ASSERTION(isSingleInsert || !aAllowLazyConstruction,
    6802                 :                "range insert shouldn't be lazy");
    6803               0 :   NS_ASSERTION(isSingleInsert || aEndChild,
    6804                 :                "range should not include all nodes after aStartChild");
    6805                 : 
    6806                 : #ifdef MOZ_XUL
    6807               0 :   if (aContainer && IsXULListBox(aContainer)) {
    6808               0 :     if (isSingleInsert) {
    6809               0 :       if (NotifyListBoxBody(mPresShell->GetPresContext(), aContainer,
    6810                 :                             // The insert case in NotifyListBoxBody
    6811                 :                             // doesn't use "old next sibling".
    6812                 :                             aStartChild, nsnull, 
    6813               0 :                             mDocument, nsnull, CONTENT_INSERTED)) {
    6814               0 :         return NS_OK;
    6815                 :       }
    6816                 :     } else {
    6817                 :       // We don't handle a range insert to a listbox parent, issue single
    6818                 :       // ContertInserted calls for each node inserted.
    6819               0 :       LAYOUT_PHASE_TEMP_EXIT();
    6820                 :       IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    6821               0 :                                    aAllowLazyConstruction);
    6822               0 :       LAYOUT_PHASE_TEMP_REENTER();
    6823               0 :       return NS_OK;
    6824                 :     }
    6825                 :   }
    6826                 : #endif // MOZ_XUL
    6827                 :   
    6828                 :   // If we have a null parent, then this must be the document element being
    6829                 :   // inserted, or some other child of the document in the DOM (might be a PI,
    6830                 :   // say).
    6831               0 :   if (! aContainer) {
    6832               0 :     NS_ASSERTION(isSingleInsert,
    6833                 :                  "root node insertion should be a single insertion");
    6834               0 :     Element *docElement = mDocument->GetRootElement();
    6835                 : 
    6836               0 :     if (aStartChild != docElement) {
    6837                 :       // Not the root element; just bail out
    6838               0 :       return NS_OK;
    6839                 :     }
    6840                 : 
    6841               0 :     NS_PRECONDITION(nsnull == mRootElementFrame,
    6842                 :                     "root element frame already created");
    6843                 : 
    6844                 :     // Create frames for the document element and its child elements
    6845                 :     nsIFrame*               docElementFrame;
    6846               0 :     rv = ConstructDocElementFrame(docElement, aFrameState, &docElementFrame);
    6847                 : 
    6848               0 :     if (NS_SUCCEEDED(rv) && docElementFrame) {
    6849               0 :       InvalidateCanvasIfNeeded(mPresShell, aStartChild);
    6850                 : #ifdef DEBUG
    6851               0 :       if (gReallyNoisyContentUpdates) {
    6852                 :         printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame "
    6853               0 :                "model:\n");
    6854               0 :         mFixedContainingBlock->List(stdout, 0);
    6855                 :       }
    6856                 : #endif
    6857                 :     }
    6858                 : 
    6859                 : #ifdef ACCESSIBILITY
    6860               0 :     nsAccessibilityService* accService = nsIPresShell::AccService();
    6861               0 :     if (accService) {
    6862                 :       accService->ContentRangeInserted(mPresShell, aContainer,
    6863               0 :                                        aStartChild, aEndChild);
    6864                 :     }
    6865                 : #endif
    6866                 : 
    6867               0 :     return NS_OK;
    6868                 :   }
    6869                 : 
    6870                 :   // Otherwise, we've got parent content. Find its frame.
    6871               0 :   nsIFrame* parentFrame = GetFrameFor(aContainer);
    6872               0 :   if (! parentFrame)
    6873               0 :     return NS_OK;
    6874                 : 
    6875               0 :   if (aAllowLazyConstruction &&
    6876               0 :       MaybeConstructLazily(CONTENTINSERT, aContainer, aStartChild)) {
    6877               0 :     return NS_OK;
    6878                 :   }
    6879                 : 
    6880               0 :   if (isSingleInsert) {
    6881                 :     // See if we have an XBL insertion point. If so, then that's our
    6882                 :     // real parent frame; if not, then the frame hasn't been built yet
    6883                 :     // and we just bail.
    6884                 :     nsIFrame* insertionPoint;
    6885               0 :     GetInsertionPoint(parentFrame, aStartChild, &insertionPoint);
    6886               0 :     if (! insertionPoint)
    6887               0 :       return NS_OK; // Don't build the frames.
    6888                 : 
    6889               0 :     parentFrame = insertionPoint;
    6890                 :   } else {
    6891                 :     // Get our insertion point. If we need to issue single ContentInserted's
    6892                 :     // GetRangeInsertionPoint will take care of that for us.
    6893               0 :     LAYOUT_PHASE_TEMP_EXIT();
    6894                 :     parentFrame = GetRangeInsertionPoint(aContainer, parentFrame,
    6895                 :                                          aStartChild, aEndChild,
    6896               0 :                                          aAllowLazyConstruction);
    6897               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6898               0 :     if (!parentFrame) {
    6899               0 :       return NS_OK;
    6900                 :     }
    6901                 :   }
    6902                 : 
    6903                 :   bool isAppend, isRangeInsertSafe;
    6904                 :   nsIFrame* prevSibling =
    6905                 :     GetInsertionPrevSibling(parentFrame, aContainer, aStartChild,
    6906               0 :                             &isAppend, &isRangeInsertSafe);
    6907                 : 
    6908                 :   // check if range insert is safe
    6909               0 :   if (!isSingleInsert && !isRangeInsertSafe) {
    6910                 :     // must fall back to a single ContertInserted for each child in the range
    6911               0 :     LAYOUT_PHASE_TEMP_EXIT();
    6912                 :     IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    6913               0 :                                  aAllowLazyConstruction);
    6914               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6915               0 :     return NS_OK;
    6916                 :   }
    6917                 : 
    6918               0 :   nsIContent* container = parentFrame->GetContent();
    6919                 : 
    6920               0 :   nsIAtom* frameType = parentFrame->GetType();
    6921               0 :   LAYOUT_PHASE_TEMP_EXIT();
    6922               0 :   if (MaybeRecreateForFrameset(parentFrame, aStartChild, aEndChild)) {
    6923               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6924               0 :     return NS_OK;
    6925                 :   }
    6926               0 :   LAYOUT_PHASE_TEMP_REENTER();
    6927                 : 
    6928                 :   // We should only get here with fieldsets when doing a single insert, because
    6929                 :   // fieldsets have multiple insertion points.
    6930               0 :   NS_ASSERTION(isSingleInsert || frameType != nsGkAtoms::fieldSetFrame,
    6931                 :                "Unexpected parent");
    6932               0 :   if (frameType == nsGkAtoms::fieldSetFrame &&
    6933               0 :       aStartChild->Tag() == nsGkAtoms::legend) {
    6934                 :     // Just reframe the parent, since figuring out whether this
    6935                 :     // should be the new legend and then handling it is too complex.
    6936                 :     // We could do a little better here --- check if the fieldset already
    6937                 :     // has a legend which occurs earlier in its child list than this node,
    6938                 :     // and if so, proceed. But we'd have to extend nsFieldSetFrame
    6939                 :     // to locate this legend in the inserted frames and extract it.
    6940               0 :     LAYOUT_PHASE_TEMP_EXIT();
    6941               0 :     nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
    6942               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6943               0 :     return rv;
    6944                 :   }
    6945                 : 
    6946                 :   // Don't construct kids of leaves
    6947               0 :   if (parentFrame->IsLeaf()) {
    6948                 :     // Clear lazy bits so we don't try to construct again.
    6949               0 :     ClearLazyBits(aStartChild, aEndChild);
    6950               0 :     return NS_OK;
    6951                 :   }
    6952                 : 
    6953               0 :   if (parentFrame->IsFrameOfType(nsIFrame::eMathML)) {
    6954               0 :     LAYOUT_PHASE_TEMP_EXIT();
    6955               0 :     nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
    6956               0 :     LAYOUT_PHASE_TEMP_REENTER();
    6957               0 :     return rv;
    6958                 :   }
    6959                 : 
    6960                 :   nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
    6961                 :                                 GetAbsoluteContainingBlock(parentFrame),
    6962                 :                                 GetFloatContainingBlock(parentFrame),
    6963               0 :                                 aFrameState);
    6964                 :   state.mTreeMatchContext.mAncestorFilter.Init(aContainer ?
    6965               0 :                                                  aContainer->AsElement() :
    6966               0 :                                                  nsnull);
    6967                 : 
    6968                 :   // Recover state for the containing block - we need to know if
    6969                 :   // it has :first-letter or :first-line style applied to it. The
    6970                 :   // reason we care is that the internal structure in these cases
    6971                 :   // is not the normal structure and requires custom updating
    6972                 :   // logic.
    6973               0 :   nsIFrame* containingBlock = state.mFloatedItems.containingBlock;
    6974               0 :   bool haveFirstLetterStyle = false;
    6975               0 :   bool haveFirstLineStyle = false;
    6976                 : 
    6977                 :   // In order to shave off some cycles, we only dig up the
    6978                 :   // containing block haveFirst* flags if the parent frame where
    6979                 :   // the insertion/append is occurring is an inline or block
    6980                 :   // container. For other types of containers this isn't relevant.
    6981               0 :   const nsStyleDisplay* parentDisplay = parentFrame->GetStyleDisplay();
    6982                 : 
    6983                 :   // Examine the parentFrame where the insertion is taking
    6984                 :   // place. If it's a certain kind of container then some special
    6985                 :   // processing is done.
    6986               0 :   if ((NS_STYLE_DISPLAY_BLOCK == parentDisplay->mDisplay) ||
    6987                 :       (NS_STYLE_DISPLAY_LIST_ITEM == parentDisplay->mDisplay) ||
    6988                 :       (NS_STYLE_DISPLAY_INLINE == parentDisplay->mDisplay) ||
    6989                 :       (NS_STYLE_DISPLAY_INLINE_BLOCK == parentDisplay->mDisplay)) {
    6990                 :     // Recover the special style flags for the containing block
    6991               0 :     if (containingBlock) {
    6992               0 :       haveFirstLetterStyle = HasFirstLetterStyle(containingBlock);
    6993                 :       haveFirstLineStyle =
    6994                 :         ShouldHaveFirstLineStyle(containingBlock->GetContent(),
    6995               0 :                                  containingBlock->GetStyleContext());
    6996                 :     }
    6997                 : 
    6998               0 :     if (haveFirstLetterStyle) {
    6999                 :       // If our current parentFrame is a Letter frame, use its parent as our
    7000                 :       // new parent hint
    7001               0 :       if (parentFrame->GetType() == nsGkAtoms::letterFrame) {
    7002                 :         // If parentFrame is out of flow, then we actually want the parent of
    7003                 :         // the placeholder frame.
    7004               0 :         if (parentFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    7005                 :           nsPlaceholderFrame* placeholderFrame =
    7006               0 :             GetPlaceholderFrameFor(parentFrame);
    7007               0 :           NS_ASSERTION(placeholderFrame, "No placeholder for out-of-flow?");
    7008               0 :           parentFrame = placeholderFrame->GetParent();
    7009                 :         } else {
    7010               0 :           parentFrame = parentFrame->GetParent();
    7011                 :         }
    7012                 :       }
    7013                 : 
    7014                 :       // Remove the old letter frames before doing the insertion
    7015                 :       RemoveLetterFrames(state.mPresContext, mPresShell,
    7016               0 :                          state.mFloatedItems.containingBlock);
    7017                 : 
    7018                 :       // Removing the letterframes messes around with the frame tree, removing
    7019                 :       // and creating frames.  We need to reget our prevsibling, parent frame,
    7020                 :       // etc.
    7021                 :       prevSibling = GetInsertionPrevSibling(parentFrame, aContainer,
    7022                 :                                             aStartChild, &isAppend,
    7023               0 :                                             &isRangeInsertSafe);
    7024                 : 
    7025                 :       // Need check whether a range insert is still safe.
    7026               0 :       if (!isSingleInsert && !isRangeInsertSafe) {
    7027                 :         // Need to recover the letter frames first.
    7028               0 :         RecoverLetterFrames(state.mFloatedItems.containingBlock);
    7029                 : 
    7030                 :         // must fall back to a single ContertInserted for each child in the range
    7031               0 :         LAYOUT_PHASE_TEMP_EXIT();
    7032                 :         IssueSingleInsertNofications(aContainer, aStartChild, aEndChild,
    7033               0 :                                      aAllowLazyConstruction);
    7034               0 :         LAYOUT_PHASE_TEMP_REENTER();
    7035               0 :         return NS_OK;
    7036                 :       }
    7037                 : 
    7038               0 :       container = parentFrame->GetContent();
    7039               0 :       frameType = parentFrame->GetType();
    7040                 :     }
    7041                 :   }
    7042                 : 
    7043               0 :   if (!prevSibling) {
    7044                 :     // We're inserting the new frames as the first child. See if the
    7045                 :     // parent has a :before pseudo-element
    7046               0 :     nsIFrame* firstChild = parentFrame->GetFirstPrincipalChild();
    7047                 : 
    7048               0 :     if (firstChild &&
    7049                 :         nsLayoutUtils::IsGeneratedContentFor(container, firstChild,
    7050               0 :                                              nsCSSPseudoElements::before)) {
    7051                 :       // Insert the new frames after the last continuation of the :before
    7052               0 :       prevSibling = firstChild->GetTailContinuation();
    7053               0 :       parentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
    7054                 :       // Don't change isAppend here; we'll can call AppendFrames as needed, and
    7055                 :       // the change to our prevSibling doesn't affect that.
    7056                 :     }
    7057                 :   }
    7058                 : 
    7059               0 :   FrameConstructionItemList items;
    7060               0 :   ParentType parentType = GetParentType(frameType);
    7061                 :   bool haveNoXBLChildren =
    7062               0 :     mDocument->BindingManager()->GetXBLChildNodesFor(aContainer) == nsnull;
    7063               0 :   if (aStartChild->GetPreviousSibling() &&
    7064                 :       parentType == eTypeBlock && haveNoXBLChildren) {
    7065                 :     // If there's a text node in the normal content list just before the
    7066                 :     // new nodes, and it has no frame, make a frame construction item for
    7067                 :     // it, because it might need a frame now.  No need to do this if our
    7068                 :     // parent type is not block, though, since WipeContainingBlock
    7069                 :     // already handles that sitation.
    7070                 :     AddTextItemIfNeeded(state, parentFrame, aStartChild->GetPreviousSibling(),
    7071               0 :                         items);
    7072                 :   }
    7073                 : 
    7074               0 :   if (isSingleInsert) {
    7075                 :     AddFrameConstructionItems(state, aStartChild,
    7076               0 :                               aStartChild->IsRootOfAnonymousSubtree(),
    7077               0 :                               parentFrame, items);
    7078                 :   } else {
    7079               0 :     for (nsIContent* child = aStartChild;
    7080                 :          child != aEndChild;
    7081               0 :          child = child->GetNextSibling()){
    7082               0 :       AddFrameConstructionItems(state, child, false, parentFrame, items);
    7083                 :     }
    7084                 :   }
    7085                 : 
    7086               0 :   if (aEndChild && parentType == eTypeBlock && haveNoXBLChildren) {
    7087                 :     // If there's a text node in the normal content list just after the
    7088                 :     // new nodes, and it has no frame, make a frame construction item for
    7089                 :     // it, because it might need a frame now.  No need to do this if our
    7090                 :     // parent type is not block, though, since WipeContainingBlock
    7091                 :     // already handles that sitation.
    7092               0 :     AddTextItemIfNeeded(state, parentFrame, aEndChild, items);
    7093                 :   }
    7094                 : 
    7095                 :   // Perform special check for diddling around with the frames in
    7096                 :   // a special inline frame.
    7097                 :   // If we're appending before :after content, then we're not really
    7098                 :   // appending, so let WipeContainingBlock know that.
    7099               0 :   LAYOUT_PHASE_TEMP_EXIT();
    7100               0 :   if (WipeContainingBlock(state, containingBlock, parentFrame, items,
    7101               0 :                           isAppend, prevSibling)) {
    7102               0 :     LAYOUT_PHASE_TEMP_REENTER();
    7103               0 :     return NS_OK;
    7104                 :   }
    7105               0 :   LAYOUT_PHASE_TEMP_REENTER();
    7106                 : 
    7107                 :   // If the container is a table and a caption will be appended, it needs to be
    7108                 :   // put in the outer table frame's additional child list.
    7109                 :   // We make no attempt here to set flags to indicate whether the list
    7110                 :   // will be at the start or end of a block. It doesn't seem worthwhile.
    7111               0 :   nsFrameItems frameItems, captionItems;
    7112               0 :   ConstructFramesFromItemList(state, items, parentFrame, frameItems);
    7113                 : 
    7114               0 :   if (frameItems.NotEmpty()) {
    7115               0 :     for (nsIContent* child = aStartChild;
    7116                 :          child != aEndChild;
    7117               0 :          child = child->GetNextSibling()){
    7118               0 :       InvalidateCanvasIfNeeded(mPresShell, child);
    7119                 :     }
    7120                 : 
    7121               0 :     if (nsGkAtoms::tableFrame == frameType ||
    7122                 :         nsGkAtoms::tableOuterFrame == frameType) {
    7123               0 :       PullOutCaptionFrames(frameItems, captionItems);
    7124                 :     }
    7125                 :   }
    7126                 : 
    7127                 :   // If the parent of our current prevSibling is different from the frame we'll
    7128                 :   // actually use as the parent, then the calculated insertion point is now
    7129                 :   // invalid and as it is unknown where to insert correctly we append instead
    7130                 :   // (bug 341858).
    7131                 :   // This can affect our prevSibling and isAppend, but should not have any
    7132                 :   // effect on the WipeContainingBlock above, since this should only happen
    7133                 :   // when neither parent is a special frame and should not affect whitespace
    7134                 :   // handling inside table-related frames (and in fact, can only happen when
    7135                 :   // one of the parents is an outer table and one is an inner table or when the
    7136                 :   // parent is a fieldset or fieldset content frame).  So it won't affect the
    7137                 :   // {ib} or XUL box cases in WipeContainingBlock(), and the table pseudo
    7138                 :   // handling will only be affected by us maybe thinking we're not inserting
    7139                 :   // at the beginning, whereas we really are.  That would have made us reframe
    7140                 :   // unnecessarily, but that's ok.
    7141                 :   // XXXbz we should push our frame construction item code up higher, so we
    7142                 :   // know what our items are by the time we start figuring out previous
    7143                 :   // siblings
    7144               0 :   if (prevSibling && frameItems.NotEmpty() &&
    7145               0 :       frameItems.FirstChild()->GetParent() != prevSibling->GetParent()) {
    7146                 : #ifdef DEBUG
    7147               0 :     nsIFrame* frame1 = frameItems.FirstChild()->GetParent();
    7148               0 :     nsIFrame* frame2 = prevSibling->GetParent();
    7149               0 :     NS_ASSERTION(!IsFrameSpecial(frame1) && !IsFrameSpecial(frame2),
    7150                 :                  "Neither should be special");
    7151               0 :     NS_ASSERTION((frame1->GetType() == nsGkAtoms::tableFrame &&
    7152                 :                   frame2->GetType() == nsGkAtoms::tableOuterFrame) ||
    7153                 :                  (frame1->GetType() == nsGkAtoms::tableOuterFrame &&
    7154                 :                   frame2->GetType() == nsGkAtoms::tableFrame) ||
    7155                 :                  frame1->GetType() == nsGkAtoms::fieldSetFrame ||
    7156                 :                  (frame1->GetParent() &&
    7157                 :                   frame1->GetParent()->GetType() == nsGkAtoms::fieldSetFrame),
    7158                 :                  "Unexpected frame types");
    7159                 : #endif
    7160               0 :     isAppend = true;
    7161                 :     nsIFrame* appendAfterFrame;
    7162                 :     parentFrame =
    7163                 :       ::AdjustAppendParentForAfterContent(mPresShell->GetPresContext(),
    7164                 :                                           container,
    7165                 :                                           frameItems.FirstChild()->GetParent(),
    7166               0 :                                           &appendAfterFrame);
    7167               0 :     prevSibling = ::FindAppendPrevSibling(parentFrame, appendAfterFrame);
    7168                 :   }
    7169                 : 
    7170               0 :   if (haveFirstLineStyle && parentFrame == containingBlock) {
    7171                 :     // It's possible that the new frame goes into a first-line
    7172                 :     // frame. Look at it and see...
    7173               0 :     if (isAppend) {
    7174                 :       // Use append logic when appending
    7175                 :       AppendFirstLineFrames(state, containingBlock->GetContent(),
    7176               0 :                             containingBlock, frameItems); 
    7177                 :     }
    7178                 :     else {
    7179                 :       // Use more complicated insert logic when inserting
    7180                 :       // XXXbz this method is a no-op, so it's easy for the args being passed
    7181                 :       // here to make no sense without anyone noticing...  If it ever stops
    7182                 :       // being a no-op, vet them carefully!
    7183                 :       InsertFirstLineFrames(state, container, containingBlock, &parentFrame,
    7184               0 :                             prevSibling, frameItems);
    7185                 :     }
    7186                 :   }
    7187                 :       
    7188                 :   // We might have captions; put them into the caption list of the
    7189                 :   // outer table frame.
    7190               0 :   if (captionItems.NotEmpty()) {
    7191               0 :     NS_ASSERTION(nsGkAtoms::tableFrame == frameType ||
    7192                 :                  nsGkAtoms::tableOuterFrame == frameType,
    7193                 :                  "parent for caption is not table?");
    7194                 :     // We need to determine where to put the caption items; start with the
    7195                 :     // the parent frame that has already been determined and get the insertion
    7196                 :     // prevsibling of the first caption item.
    7197               0 :     nsIFrame* captionParent = parentFrame;
    7198                 :     bool captionIsAppend;
    7199               0 :     nsIFrame* captionPrevSibling = nsnull;
    7200                 : 
    7201                 :     // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
    7202                 :     bool ignored;
    7203               0 :     if (isSingleInsert) {
    7204                 :       captionPrevSibling =
    7205                 :         GetInsertionPrevSibling(captionParent, aContainer, aStartChild,
    7206               0 :                                 &captionIsAppend, &ignored);
    7207                 :     } else {
    7208               0 :       nsIContent* firstCaption = captionItems.FirstChild()->GetContent();
    7209                 :       // It is very important here that we skip the children in
    7210                 :       // [aStartChild,aEndChild) when looking for a
    7211                 :       // prevsibling.
    7212                 :       captionPrevSibling =
    7213                 :         GetInsertionPrevSibling(captionParent, aContainer, firstCaption,
    7214                 :                                 &captionIsAppend, &ignored,
    7215               0 :                                 aStartChild, aEndChild);
    7216                 :     }
    7217                 : 
    7218               0 :     nsIFrame* outerTable = nsnull;
    7219               0 :     if (GetCaptionAdjustedParent(captionParent, captionItems.FirstChild(),
    7220               0 :                                  &outerTable)) {
    7221                 :       // If the parent is not an outer table frame we will try to add frames
    7222                 :       // to a named child list that the parent does not honour and the frames
    7223                 :       // will get lost
    7224               0 :       NS_ASSERTION(nsGkAtoms::tableOuterFrame == outerTable->GetType(),
    7225                 :                    "Pseudo frame construction failure; "
    7226                 :                    "a caption can be only a child of an outer table frame");
    7227                 : 
    7228                 :       // If the parent of our current prevSibling is different from the frame
    7229                 :       // we'll actually use as the parent, then the calculated insertion
    7230                 :       // point is now invalid (bug 341382).
    7231               0 :       if (captionPrevSibling &&
    7232               0 :           captionPrevSibling->GetParent() != outerTable) {
    7233               0 :           captionPrevSibling = nsnull;
    7234                 :       }
    7235               0 :       if (captionIsAppend) {
    7236               0 :         AppendFrames(outerTable, nsIFrame::kCaptionList, captionItems);
    7237                 :       } else {
    7238                 :         InsertFrames(outerTable, nsIFrame::kCaptionList,
    7239               0 :                      captionPrevSibling, captionItems);
    7240                 :       }
    7241                 :     }
    7242                 :   }
    7243                 : 
    7244               0 :   if (frameItems.NotEmpty()) {
    7245                 :     // Notify the parent frame
    7246               0 :     if (isAppend) {
    7247               0 :       AppendFramesToParent(state, parentFrame, frameItems, prevSibling);
    7248                 :     } else {
    7249               0 :       InsertFrames(parentFrame, kPrincipalList, prevSibling, frameItems);
    7250                 :     }
    7251                 :   }
    7252                 : 
    7253               0 :   if (haveFirstLetterStyle) {
    7254                 :     // Recover the letter frames for the containing block when
    7255                 :     // it has first-letter style.
    7256               0 :     RecoverLetterFrames(state.mFloatedItems.containingBlock);
    7257                 :   }
    7258                 : 
    7259                 : #ifdef DEBUG
    7260               0 :   if (gReallyNoisyContentUpdates && parentFrame) {
    7261               0 :     printf("nsCSSFrameConstructor::ContentRangeInserted: resulting frame model:\n");
    7262               0 :     parentFrame->List(stdout, 0);
    7263                 :   }
    7264                 : #endif
    7265                 : 
    7266                 : #ifdef ACCESSIBILITY
    7267               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
    7268               0 :   if (accService) {
    7269                 :     accService->ContentRangeInserted(mPresShell, aContainer,
    7270               0 :                                      aStartChild, aEndChild);
    7271                 :   }
    7272                 : #endif
    7273                 : 
    7274               0 :   return NS_OK;
    7275                 : }
    7276                 : 
    7277                 : nsresult
    7278               0 : nsCSSFrameConstructor::ContentRemoved(nsIContent* aContainer,
    7279                 :                                       nsIContent* aChild,
    7280                 :                                       nsIContent* aOldNextSibling,
    7281                 :                                       RemoveFlags aFlags,
    7282                 :                                       bool*     aDidReconstruct)
    7283                 : {
    7284               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7285               0 :   NS_PRECONDITION(mUpdateCount != 0,
    7286                 :                   "Should be in an update while destroying frames");
    7287                 : 
    7288               0 :   *aDidReconstruct = false;
    7289                 :   
    7290                 :   // XXXldb Do we need to re-resolve style to handle the CSS2 + combinator and
    7291                 :   // the :empty pseudo-class?
    7292                 : 
    7293                 : #ifdef DEBUG
    7294               0 :   if (gNoisyContentUpdates) {
    7295                 :     printf("nsCSSFrameConstructor::ContentRemoved container=%p child=%p "
    7296                 :            "old-next-sibling=%p\n",
    7297                 :            static_cast<void*>(aContainer),
    7298                 :            static_cast<void*>(aChild),
    7299               0 :            static_cast<void*>(aOldNextSibling));
    7300               0 :     if (gReallyNoisyContentUpdates) {
    7301               0 :       aContainer->List(stdout, 0);
    7302                 :     }
    7303                 :   }
    7304                 : #endif
    7305                 : 
    7306               0 :   nsPresContext *presContext = mPresShell->GetPresContext();
    7307               0 :   nsresult                  rv = NS_OK;
    7308                 : 
    7309                 :   // Find the child frame that maps the content
    7310               0 :   nsIFrame* childFrame = aChild->GetPrimaryFrame();
    7311                 : 
    7312               0 :   if (!childFrame || childFrame->GetContent() != aChild) {
    7313                 :     // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    7314                 :     // Remove it once that's fixed.
    7315               0 :     ClearUndisplayedContentIn(aChild, aContainer);
    7316                 :   }
    7317                 : 
    7318                 : #ifdef MOZ_XUL
    7319               0 :   if (NotifyListBoxBody(presContext, aContainer, aChild, aOldNextSibling, 
    7320               0 :                         mDocument, childFrame, CONTENT_REMOVED))
    7321               0 :     return NS_OK;
    7322                 : 
    7323                 : #endif // MOZ_XUL
    7324                 : 
    7325                 :   // If we're removing the root, then make sure to remove things starting at
    7326                 :   // the viewport's child instead of the primary frame (which might even be
    7327                 :   // null if the root had an XBL binding or display:none, even though the
    7328                 :   // frames above it got created).  We do the adjustment after the childFrame
    7329                 :   // check above, because we do want to clear any undisplayed content we might
    7330                 :   // have for the root.  Detecting removal of a root is a little exciting; in
    7331                 :   // particular, having a null aContainer is necessary but NOT sufficient.  Due
    7332                 :   // to how we process reframes, the content node might not even be in our
    7333                 :   // document by now.  So explicitly check whether the viewport's first kid's
    7334                 :   // content node is aChild.
    7335               0 :   bool isRoot = false;
    7336               0 :   if (!aContainer) {
    7337               0 :     nsIFrame* viewport = GetRootFrame();
    7338               0 :     if (viewport) {
    7339               0 :       nsIFrame* firstChild = viewport->GetFirstPrincipalChild();
    7340               0 :       if (firstChild && firstChild->GetContent() == aChild) {
    7341               0 :         isRoot = true;
    7342               0 :         childFrame = firstChild;
    7343               0 :         NS_ASSERTION(!childFrame->GetNextSibling(), "How did that happen?");
    7344                 :       }
    7345                 :     }
    7346                 :   }
    7347                 : 
    7348               0 :   if (childFrame) {
    7349               0 :     InvalidateCanvasIfNeeded(mPresShell, aChild);
    7350                 :     
    7351                 :     // See whether we need to remove more than just childFrame
    7352               0 :     LAYOUT_PHASE_TEMP_EXIT();
    7353               0 :     if (MaybeRecreateContainerForFrameRemoval(childFrame, &rv)) {
    7354               0 :       LAYOUT_PHASE_TEMP_REENTER();
    7355               0 :       *aDidReconstruct = true;
    7356               0 :       return rv;
    7357                 :     }
    7358               0 :     LAYOUT_PHASE_TEMP_REENTER();
    7359                 : 
    7360                 :     // Get the childFrame's parent frame
    7361               0 :     nsIFrame* parentFrame = childFrame->GetParent();
    7362               0 :     nsIAtom* parentType = parentFrame->GetType();
    7363                 : 
    7364               0 :     if (parentType == nsGkAtoms::frameSetFrame &&
    7365               0 :         IsSpecialFramesetChild(aChild)) {
    7366                 :       // Just reframe the parent, since framesets are weird like that.
    7367               0 :       *aDidReconstruct = true;
    7368               0 :       LAYOUT_PHASE_TEMP_EXIT();
    7369               0 :       nsresult rv = RecreateFramesForContent(parentFrame->GetContent(), false);
    7370               0 :       LAYOUT_PHASE_TEMP_REENTER();
    7371               0 :       return rv;
    7372                 :     }
    7373                 : 
    7374                 :     // If we're a child of MathML, then we should reframe the MathML content.
    7375                 :     // If we're non-MathML, then we would be wrapped in a block so we need to
    7376                 :     // check our grandparent in that case.
    7377                 :     nsIFrame* possibleMathMLAncestor = parentType == nsGkAtoms::blockFrame ? 
    7378               0 :          parentFrame->GetParent() : parentFrame;
    7379               0 :     if (possibleMathMLAncestor->IsFrameOfType(nsIFrame::eMathML)) {
    7380               0 :       *aDidReconstruct = true;
    7381               0 :       LAYOUT_PHASE_TEMP_EXIT();
    7382               0 :       nsresult rv = RecreateFramesForContent(possibleMathMLAncestor->GetContent(), false);
    7383               0 :       LAYOUT_PHASE_TEMP_REENTER();
    7384               0 :       return rv;
    7385                 :     }
    7386                 : 
    7387                 :     // Undo XUL wrapping if it's no longer needed.
    7388                 :     // (If we're in the XUL block-wrapping situation, parentFrame is the
    7389                 :     // wrapper frame.)
    7390               0 :     nsIFrame* grandparentFrame = parentFrame->GetParent();
    7391               0 :     if (grandparentFrame && grandparentFrame->IsBoxFrame() &&
    7392               0 :         (grandparentFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
    7393                 :         // check if this frame is the only one needing wrapping
    7394               0 :         aChild == AnyKidsNeedBlockParent(parentFrame->GetFirstPrincipalChild()) &&
    7395               0 :         !AnyKidsNeedBlockParent(childFrame->GetNextSibling())) {
    7396               0 :       *aDidReconstruct = true;
    7397               0 :       LAYOUT_PHASE_TEMP_EXIT();
    7398               0 :       nsresult rv = RecreateFramesForContent(grandparentFrame->GetContent(), true);
    7399               0 :       LAYOUT_PHASE_TEMP_REENTER();
    7400               0 :       return rv;
    7401                 :     }
    7402                 : 
    7403                 : #ifdef ACCESSIBILITY
    7404               0 :     nsAccessibilityService* accService = nsIPresShell::AccService();
    7405               0 :     if (accService) {
    7406               0 :       accService->ContentRemoved(mPresShell, aContainer, aChild);
    7407                 :     }
    7408                 : #endif
    7409                 : 
    7410                 :     // Examine the containing-block for the removed content and see if
    7411                 :     // :first-letter style applies.
    7412               0 :     nsIFrame* inflowChild = childFrame;
    7413               0 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    7414               0 :       inflowChild = GetPlaceholderFrameFor(childFrame);
    7415               0 :       NS_ASSERTION(inflowChild, "No placeholder for out-of-flow?");
    7416                 :     }
    7417                 :     nsIFrame* containingBlock =
    7418               0 :       GetFloatContainingBlock(inflowChild->GetParent());
    7419               0 :     bool haveFLS = containingBlock && HasFirstLetterStyle(containingBlock);
    7420               0 :     if (haveFLS) {
    7421                 :       // Trap out to special routine that handles adjusting a blocks
    7422                 :       // frame tree when first-letter style is present.
    7423                 : #ifdef NOISY_FIRST_LETTER
    7424                 :       printf("ContentRemoved: containingBlock=");
    7425                 :       nsFrame::ListTag(stdout, containingBlock);
    7426                 :       printf(" parentFrame=");
    7427                 :       nsFrame::ListTag(stdout, parentFrame);
    7428                 :       printf(" childFrame=");
    7429                 :       nsFrame::ListTag(stdout, childFrame);
    7430                 :       printf("\n");
    7431                 : #endif
    7432                 : 
    7433                 :       // First update the containing blocks structure by removing the
    7434                 :       // existing letter frames. This makes the subsequent logic
    7435                 :       // simpler.
    7436               0 :       RemoveLetterFrames(presContext, mPresShell, containingBlock);
    7437                 : 
    7438                 :       // Recover childFrame and parentFrame
    7439               0 :       childFrame = aChild->GetPrimaryFrame();
    7440               0 :       if (!childFrame || childFrame->GetContent() != aChild) {
    7441                 :         // XXXbz the GetContent() != aChild check is needed due to bug 135040.
    7442                 :         // Remove it once that's fixed.
    7443               0 :         ClearUndisplayedContentIn(aChild, aContainer);
    7444               0 :         return NS_OK;
    7445                 :       }
    7446               0 :       parentFrame = childFrame->GetParent();
    7447               0 :       parentType = parentFrame->GetType();
    7448                 : 
    7449                 : #ifdef NOISY_FIRST_LETTER
    7450                 :       printf("  ==> revised parentFrame=");
    7451                 :       nsFrame::ListTag(stdout, parentFrame);
    7452                 :       printf(" childFrame=");
    7453                 :       nsFrame::ListTag(stdout, childFrame);
    7454                 :       printf("\n");
    7455                 : #endif
    7456                 :     }
    7457                 : 
    7458                 : #ifdef DEBUG
    7459               0 :     if (gReallyNoisyContentUpdates) {
    7460               0 :       printf("nsCSSFrameConstructor::ContentRemoved: childFrame=");
    7461               0 :       nsFrame::ListTag(stdout, childFrame);
    7462               0 :       putchar('\n');
    7463               0 :       parentFrame->List(stdout, 0);
    7464                 :     }
    7465                 : #endif
    7466                 : 
    7467                 : 
    7468                 :     // Notify the parent frame that it should delete the frame
    7469               0 :     if (childFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    7470               0 :       childFrame = GetPlaceholderFrameFor(childFrame);
    7471               0 :       NS_ASSERTION(childFrame, "Missing placeholder frame for out of flow.");
    7472               0 :       parentFrame = childFrame->GetParent();
    7473                 :     }
    7474                 :     rv = RemoveFrame(nsLayoutUtils::GetChildListNameFor(childFrame),
    7475               0 :                      childFrame);
    7476                 :     //XXXfr NS_ENSURE_SUCCESS(rv, rv) ?
    7477                 : 
    7478               0 :     if (isRoot) {
    7479               0 :       mRootElementFrame = nsnull;
    7480               0 :       mRootElementStyleFrame = nsnull;
    7481               0 :       mDocElementContainingBlock = nsnull;
    7482               0 :       mPageSequenceFrame = nsnull;
    7483               0 :       mGfxScrollFrame = nsnull;
    7484               0 :       mHasRootAbsPosContainingBlock = false;
    7485               0 :       mFixedContainingBlock = GetRootFrame();
    7486                 :     }
    7487                 : 
    7488               0 :     if (haveFLS && mRootElementFrame) {
    7489               0 :       RecoverLetterFrames(containingBlock);
    7490                 :     }
    7491                 : 
    7492                 :     // If we're just reconstructing frames for the element, then the
    7493                 :     // following ContentInserted notification on the element will
    7494                 :     // take care of fixing up any adjacent text nodes.  We don't need
    7495                 :     // to do this if the table parent type of our parent type is not
    7496                 :     // eTypeBlock, though, because in that case the whitespace isn't
    7497                 :     // being suppressed due to us anyway.
    7498               0 :     if (aContainer && !aChild->IsRootOfAnonymousSubtree() &&
    7499                 :         aFlags != REMOVE_FOR_RECONSTRUCTION &&
    7500               0 :         GetParentType(parentType) == eTypeBlock) {
    7501                 :       // Adjacent whitespace-only text nodes might have been suppressed if
    7502                 :       // this node does not have inline ends. Create frames for them now
    7503                 :       // if necessary.
    7504                 :       // Reframe any text node just before the node being removed, if there is
    7505                 :       // one, and if it's not the last child or the first child. If a whitespace
    7506                 :       // textframe was being suppressed and it's now the last child or first
    7507                 :       // child then it can stay suppressed since the parent must be a block
    7508                 :       // and hence it's adjacent to a block end.
    7509                 :       // If aOldNextSibling is null, then the text node before the node being
    7510                 :       // removed is the last node, and we don't need to worry about it.
    7511               0 :       if (aOldNextSibling) {
    7512               0 :         nsIContent* prevSibling = aOldNextSibling->GetPreviousSibling();
    7513               0 :         if (prevSibling && prevSibling->GetPreviousSibling()) {
    7514               0 :           LAYOUT_PHASE_TEMP_EXIT();
    7515               0 :           ReframeTextIfNeeded(aContainer, prevSibling);
    7516               0 :           LAYOUT_PHASE_TEMP_REENTER();
    7517                 :         }
    7518                 :       }
    7519                 :       // Reframe any text node just after the node being removed, if there is
    7520                 :       // one, and if it's not the last child or the first child.
    7521               0 :       if (aOldNextSibling && aOldNextSibling->GetNextSibling() &&
    7522               0 :           aOldNextSibling->GetPreviousSibling()) {
    7523               0 :         LAYOUT_PHASE_TEMP_EXIT();
    7524               0 :         ReframeTextIfNeeded(aContainer, aOldNextSibling);
    7525               0 :         LAYOUT_PHASE_TEMP_REENTER();
    7526                 :       }
    7527                 :     }
    7528                 : 
    7529                 : #ifdef DEBUG
    7530               0 :     if (gReallyNoisyContentUpdates && parentFrame) {
    7531               0 :       printf("nsCSSFrameConstructor::ContentRemoved: resulting frame model:\n");
    7532               0 :       parentFrame->List(stdout, 0);
    7533                 :     }
    7534                 : #endif
    7535                 :   }
    7536                 : 
    7537               0 :   return rv;
    7538                 : }
    7539                 : 
    7540                 : #ifdef DEBUG
    7541                 :   // To ensure that the functions below are only called within
    7542                 :   // |ApplyRenderingChangeToTree|.
    7543                 : static bool gInApplyRenderingChangeToTree = false;
    7544                 : #endif
    7545                 : 
    7546                 : static void
    7547                 : DoApplyRenderingChangeToTree(nsIFrame* aFrame,
    7548                 :                              nsFrameManager* aFrameManager,
    7549                 :                              nsChangeHint aChange);
    7550                 : 
    7551                 : /**
    7552                 :  * This rect is relative to aFrame's parent
    7553                 :  */
    7554                 : static void
    7555               0 : UpdateViewsForTree(nsIFrame* aFrame,
    7556                 :                    nsFrameManager* aFrameManager,
    7557                 :                    nsChangeHint aChange)
    7558                 : {
    7559               0 :   NS_PRECONDITION(gInApplyRenderingChangeToTree,
    7560                 :                   "should only be called within ApplyRenderingChangeToTree");
    7561                 : 
    7562               0 :   nsIView* view = aFrame->GetView();
    7563               0 :   if (view) {
    7564               0 :     if (aChange & nsChangeHint_SyncFrameView) {
    7565                 :       nsContainerFrame::SyncFrameViewProperties(aFrame->PresContext(),
    7566               0 :                                                 aFrame, nsnull, view);
    7567                 :     }
    7568                 :   }
    7569                 : 
    7570               0 :   nsIFrame::ChildListIterator lists(aFrame);
    7571               0 :   for (; !lists.IsDone(); lists.Next()) {
    7572               0 :     nsFrameList::Enumerator childFrames(lists.CurrentList());
    7573               0 :     for (; !childFrames.AtEnd(); childFrames.Next()) {
    7574               0 :       nsIFrame* child = childFrames.get();
    7575               0 :       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
    7576                 :         // only do frames that don't have placeholders
    7577               0 :         if (nsGkAtoms::placeholderFrame == child->GetType()) {
    7578                 :           // do the out-of-flow frame and its continuations
    7579                 :           nsIFrame* outOfFlowFrame =
    7580               0 :             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
    7581               0 :           do {
    7582                 :             DoApplyRenderingChangeToTree(outOfFlowFrame, aFrameManager,
    7583               0 :                                          aChange);
    7584               0 :           } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
    7585               0 :         } else if (lists.CurrentID() == nsIFrame::kPopupList) {
    7586                 :           DoApplyRenderingChangeToTree(child, aFrameManager,
    7587               0 :                                        aChange);
    7588                 :         } else {  // regular frame
    7589               0 :           if ((child->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) &&
    7590                 :               (aChange & nsChangeHint_RepaintFrame)) {
    7591                 :             FrameLayerBuilder::InvalidateThebesLayerContents(child,
    7592               0 :               child->GetVisualOverflowRectRelativeToSelf());
    7593                 :           }
    7594               0 :           UpdateViewsForTree(child, aFrameManager, aChange);
    7595                 :         }
    7596                 :       }
    7597                 :     }
    7598                 :   }
    7599               0 : }
    7600                 : 
    7601                 : static void
    7602               0 : DoApplyRenderingChangeToTree(nsIFrame* aFrame,
    7603                 :                              nsFrameManager* aFrameManager,
    7604                 :                              nsChangeHint aChange)
    7605                 : {
    7606               0 :   NS_PRECONDITION(gInApplyRenderingChangeToTree,
    7607                 :                   "should only be called within ApplyRenderingChangeToTree");
    7608                 : 
    7609               0 :   for ( ; aFrame; aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame)) {
    7610                 :     // Get view if this frame has one and trigger an update. If the
    7611                 :     // frame doesn't have a view, find the nearest containing view
    7612                 :     // (adjusting r's coordinate system to reflect the nesting) and
    7613                 :     // update there.
    7614                 :     // We don't need to update transforms in UpdateViewsForTree, because
    7615                 :     // there can't be any out-of-flows or popups that need to be transformed;
    7616                 :     // all out-of-flow descendants of the transformed element must also be
    7617                 :     // descendants of the transformed frame.
    7618                 :     UpdateViewsForTree(aFrame, aFrameManager,
    7619                 :                        nsChangeHint(aChange & (nsChangeHint_RepaintFrame |
    7620                 :                                                nsChangeHint_SyncFrameView |
    7621               0 :                                                nsChangeHint_UpdateOpacityLayer)));
    7622                 : 
    7623                 :     // if frame has view, will already be invalidated
    7624               0 :     if (aChange & nsChangeHint_RepaintFrame) {
    7625               0 :       if (aFrame->IsFrameOfType(nsIFrame::eSVG)) {
    7626               0 :         if (aChange & nsChangeHint_UpdateEffects) {
    7627                 :           // Invalidate the frame's old bounds, update its bounds, invalidate its new
    7628                 :           // bounds, and then inform anyone observing _us_ that we've changed:
    7629               0 :           nsSVGUtils::UpdateGraphic(aFrame);
    7630                 :         } else {
    7631                 :           // Just invalidate our area:
    7632               0 :           nsSVGUtils::InvalidateCoveredRegion(aFrame);
    7633                 :         }
    7634                 :       } else {
    7635               0 :         aFrame->InvalidateOverflowRect();
    7636                 :       }
    7637                 :     }
    7638               0 :     if (aChange & nsChangeHint_UpdateOpacityLayer) {
    7639               0 :       aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
    7640               0 :       aFrame->InvalidateLayer(aFrame->GetVisualOverflowRectRelativeToSelf(),
    7641               0 :                               nsDisplayItem::TYPE_OPACITY);
    7642                 :     }
    7643                 :     
    7644               0 :     if (aChange & nsChangeHint_UpdateTransformLayer) {
    7645               0 :       aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
    7646                 :       // Invalidate the old transformed area. The new transformed area
    7647                 :       // will be invalidated by nsFrame::FinishAndStoreOverflowArea.
    7648               0 :       aFrame->InvalidateTransformLayer();
    7649                 :     }
    7650                 :   }
    7651               0 : }
    7652                 : 
    7653                 : static void
    7654               0 : ApplyRenderingChangeToTree(nsPresContext* aPresContext,
    7655                 :                            nsIFrame* aFrame,
    7656                 :                            nsChangeHint aChange)
    7657                 : {
    7658               0 :   NS_ASSERTION(!(aChange & nsChangeHint_UpdateTransformLayer) ||
    7659                 :                aFrame->GetStyleDisplay()->HasTransform(),
    7660                 :                "Only transform style should give a UpdateTransformLayer hint");
    7661                 : 
    7662               0 :   nsIPresShell *shell = aPresContext->PresShell();
    7663               0 :   if (shell->IsPaintingSuppressed()) {
    7664                 :     // Don't allow synchronous rendering changes when painting is turned off.
    7665               0 :     aChange = NS_SubtractHint(aChange, nsChangeHint_RepaintFrame);
    7666               0 :     if (!aChange) {
    7667               0 :       return;
    7668                 :     }
    7669                 :   }
    7670                 : 
    7671                 :   // If the frame's background is propagated to an ancestor, walk up to
    7672                 :   // that ancestor.
    7673                 :   nsStyleContext *bgSC;
    7674               0 :   while (!nsCSSRendering::FindBackground(aPresContext, aFrame, &bgSC)) {
    7675               0 :     aFrame = aFrame->GetParent();
    7676               0 :     NS_ASSERTION(aFrame, "root frame must paint");
    7677                 :   }
    7678                 : 
    7679                 :   // Trigger rendering updates by damaging this frame and any
    7680                 :   // continuations of this frame.
    7681                 : 
    7682                 :   // XXX this needs to detect the need for a view due to an opacity change and deal with it...
    7683                 : 
    7684                 : #ifdef DEBUG
    7685               0 :   gInApplyRenderingChangeToTree = true;
    7686                 : #endif
    7687               0 :   DoApplyRenderingChangeToTree(aFrame, shell->FrameManager(), aChange);
    7688                 : #ifdef DEBUG
    7689               0 :   gInApplyRenderingChangeToTree = false;
    7690                 : #endif
    7691                 : }
    7692                 : 
    7693                 : /**
    7694                 :  * This method invalidates the canvas when frames are removed or added for a
    7695                 :  * node that might have its background propagated to the canvas, i.e., a
    7696                 :  * document root node or an HTML BODY which is a child of the root node.
    7697                 :  *
    7698                 :  * @param aFrame a frame for a content node about to be removed or a frame that
    7699                 :  *               was just created for a content node that was inserted.
    7700                 :  */ 
    7701                 : static void
    7702               0 : InvalidateCanvasIfNeeded(nsIPresShell* presShell, nsIContent* node)
    7703                 : {
    7704               0 :   NS_PRECONDITION(presShell->GetRootFrame(), "What happened here?");
    7705               0 :   NS_PRECONDITION(presShell->GetPresContext(), "Say what?");
    7706                 : 
    7707                 :   //  Note that both in ContentRemoved and ContentInserted the content node
    7708                 :   //  will still have the right parent pointer, so looking at that is ok.
    7709                 :   
    7710               0 :   nsIContent* parent = node->GetParent();
    7711               0 :   if (parent) {
    7712                 :     // Has a parent; might not be what we want
    7713               0 :     nsIContent* grandParent = parent->GetParent();
    7714               0 :     if (grandParent) {
    7715                 :       // Has a grandparent, so not what we want
    7716               0 :       return;
    7717                 :     }
    7718                 : 
    7719                 :     // Check whether it's an HTML body
    7720               0 :     if (node->Tag() != nsGkAtoms::body ||
    7721               0 :         !node->IsHTML()) {
    7722               0 :       return;
    7723                 :     }
    7724                 :   }
    7725                 : 
    7726                 :   // At this point the node has no parent or it's an HTML <body> child of the
    7727                 :   // root.  We might not need to invalidate in this case (eg we might be in
    7728                 :   // XHTML or something), but chances are we want to.  Play it safe.
    7729                 :   // Invalidate the viewport.
    7730                 : 
    7731               0 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    7732               0 :   rootFrame->InvalidateFrameSubtree();
    7733                 : }
    7734                 : 
    7735                 : nsresult
    7736               0 : nsCSSFrameConstructor::StyleChangeReflow(nsIFrame* aFrame,
    7737                 :                                          nsChangeHint aHint)
    7738                 : {
    7739                 :   // If the frame hasn't even received an initial reflow, then don't
    7740                 :   // send it a style-change reflow!
    7741               0 :   if (aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)
    7742               0 :     return NS_OK;
    7743                 : 
    7744                 : #ifdef DEBUG
    7745               0 :   if (gNoisyContentUpdates) {
    7746               0 :     printf("nsCSSFrameConstructor::StyleChangeReflow: aFrame=");
    7747               0 :     nsFrame::ListTag(stdout, aFrame);
    7748               0 :     printf("\n");
    7749                 :   }
    7750                 : #endif
    7751                 : 
    7752                 :   nsIPresShell::IntrinsicDirty dirtyType;
    7753               0 :   if (aHint & nsChangeHint_ClearDescendantIntrinsics) {
    7754               0 :     NS_ASSERTION(aHint & nsChangeHint_ClearAncestorIntrinsics,
    7755                 :                  "Please read the comments in nsChangeHint.h");
    7756               0 :     dirtyType = nsIPresShell::eStyleChange;
    7757               0 :   } else if (aHint & nsChangeHint_ClearAncestorIntrinsics) {
    7758               0 :     dirtyType = nsIPresShell::eTreeChange;
    7759                 :   } else {
    7760               0 :     dirtyType = nsIPresShell::eResize;
    7761                 :   }
    7762                 : 
    7763                 :   nsFrameState dirtyBits;
    7764               0 :   if (aHint & nsChangeHint_NeedDirtyReflow) {
    7765               0 :     dirtyBits = NS_FRAME_IS_DIRTY;
    7766                 :   } else {
    7767               0 :     dirtyBits = NS_FRAME_HAS_DIRTY_CHILDREN;
    7768                 :   }
    7769                 : 
    7770               0 :   do {
    7771               0 :     mPresShell->FrameNeedsReflow(aFrame, dirtyType, dirtyBits);
    7772               0 :     aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame);
    7773                 :   } while (aFrame);
    7774                 : 
    7775               0 :   return NS_OK;
    7776                 : }
    7777                 : 
    7778                 : nsresult
    7779               0 : nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
    7780                 :                                             CharacterDataChangeInfo* aInfo)
    7781                 : {
    7782               0 :   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
    7783               0 :   nsresult      rv = NS_OK;
    7784                 : 
    7785               0 :   if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
    7786               0 :        !aContent->TextIsOnlyWhitespace()) ||
    7787               0 :       (aContent->HasFlag(NS_REFRAME_IF_WHITESPACE) &&
    7788               0 :        aContent->TextIsOnlyWhitespace())) {
    7789                 : #ifdef DEBUG
    7790               0 :     nsIFrame* frame = aContent->GetPrimaryFrame();
    7791               0 :     NS_ASSERTION(!frame || !frame->IsGeneratedContentFrame(),
    7792                 :                  "Bit should never be set on generated content");
    7793                 : #endif
    7794               0 :     LAYOUT_PHASE_TEMP_EXIT();
    7795               0 :     nsresult rv = RecreateFramesForContent(aContent, false);
    7796               0 :     LAYOUT_PHASE_TEMP_REENTER();
    7797               0 :     return rv;
    7798                 :   }
    7799                 : 
    7800                 :   // Find the child frame
    7801               0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    7802                 : 
    7803                 :   // Notify the first frame that maps the content. It will generate a reflow
    7804                 :   // command
    7805                 : 
    7806                 :   // It's possible the frame whose content changed isn't inserted into the
    7807                 :   // frame hierarchy yet, or that there is no frame that maps the content
    7808               0 :   if (nsnull != frame) {
    7809                 : #if 0
    7810                 :     NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
    7811                 :        ("nsCSSFrameConstructor::CharacterDataChanged: content=%p[%s] subcontent=%p frame=%p",
    7812                 :         aContent, ContentTag(aContent, 0),
    7813                 :         aSubContent, frame));
    7814                 : #endif
    7815                 : 
    7816                 :     // Special check for text content that is a child of a letter frame.  If
    7817                 :     // this happens, we should remove the letter frame, do whatever we're
    7818                 :     // planning to do with this notification, then put the letter frame back.
    7819                 :     // Note that this is basically what RecreateFramesForContent ends up doing;
    7820                 :     // the reason we dont' want to call that here is that our text content
    7821                 :     // could be native anonymous, in which case RecreateFramesForContent would
    7822                 :     // completely barf on it.  And recreating the non-anonymous ancestor would
    7823                 :     // just lead us to come back into this notification (e.g. if quotes or
    7824                 :     // counters are involved), leading to a loop.
    7825               0 :     nsIFrame* block = GetFloatContainingBlock(frame);
    7826               0 :     bool haveFirstLetterStyle = false;
    7827               0 :     if (block) {
    7828                 :       // See if the block has first-letter style applied to it.
    7829               0 :       haveFirstLetterStyle = HasFirstLetterStyle(block);
    7830               0 :       if (haveFirstLetterStyle) {
    7831                 :         RemoveLetterFrames(mPresShell->GetPresContext(), mPresShell,
    7832               0 :                            block);
    7833                 :         // Reget |frame|, since we might have killed it.
    7834                 :         // Do we really need to call CharacterDataChanged in this case, though?
    7835               0 :         frame = aContent->GetPrimaryFrame();
    7836               0 :         NS_ASSERTION(frame, "Should have frame here!");
    7837                 :       }
    7838                 :     }
    7839                 : 
    7840               0 :     frame->CharacterDataChanged(aInfo);
    7841                 : 
    7842               0 :     if (haveFirstLetterStyle) {
    7843               0 :       RecoverLetterFrames(block);
    7844                 :     }
    7845                 :   }
    7846                 : 
    7847               0 :   return rv;
    7848                 : }
    7849                 : 
    7850               0 : NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nsnull)
    7851                 : 
    7852                 : nsresult
    7853               0 : nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
    7854                 : {
    7855               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    7856                 :                "Someone forgot a script blocker");
    7857               0 :   PRInt32 count = aChangeList.Count();
    7858               0 :   if (!count)
    7859               0 :     return NS_OK;
    7860                 : 
    7861                 :   // Make sure to not rebuild quote or counter lists while we're
    7862                 :   // processing restyles
    7863               0 :   BeginUpdate();
    7864                 : 
    7865               0 :   nsPresContext* presContext = mPresShell->GetPresContext();
    7866               0 :   FramePropertyTable* propTable = presContext->PropertyTable();
    7867                 : 
    7868                 :   // Mark frames so that we skip frames that die along the way, bug 123049.
    7869                 :   // A frame can be in the list multiple times with different hints. Further
    7870                 :   // optmization is possible if nsStyleChangeList::AppendChange could coalesce
    7871               0 :   PRInt32 index = count;
    7872                 : 
    7873               0 :   while (0 <= --index) {
    7874                 :     const nsStyleChangeData* changeData;
    7875               0 :     aChangeList.ChangeAt(index, &changeData);
    7876               0 :     if (changeData->mFrame) {
    7877                 :       propTable->Set(changeData->mFrame, ChangeListProperty(),
    7878               0 :                      NS_INT32_TO_PTR(1));
    7879                 :     }
    7880                 :   }
    7881                 : 
    7882               0 :   index = count;
    7883               0 :   bool didInvalidate = false;
    7884               0 :   bool didReflow = false;
    7885                 : 
    7886               0 :   while (0 <= --index) {
    7887                 :     nsIFrame* frame;
    7888                 :     nsIContent* content;
    7889                 :     nsChangeHint hint;
    7890               0 :     aChangeList.ChangeAt(index, frame, content, hint);
    7891                 : 
    7892               0 :     NS_ASSERTION(!(hint & nsChangeHint_ReflowFrame) ||
    7893                 :                  (hint & nsChangeHint_NeedReflow),
    7894                 :                  "Reflow hint bits set without actually asking for a reflow");
    7895                 : 
    7896               0 :     if (frame && frame->GetContent() != content) {
    7897                 :       // XXXbz this is due to image maps messing with the primary frame of
    7898                 :       // <area>s.  See bug 135040.  Remove this block once that's fixed.
    7899               0 :       frame = nsnull;
    7900               0 :       if (!(hint & nsChangeHint_ReconstructFrame)) {
    7901               0 :         continue;
    7902                 :       }
    7903                 :     }
    7904                 : 
    7905                 :     // skip any frame that has been destroyed due to a ripple effect
    7906               0 :     if (frame) {
    7907               0 :       if (!propTable->Get(frame, ChangeListProperty()))
    7908               0 :         continue;
    7909                 :     }
    7910                 : 
    7911               0 :     if (hint & nsChangeHint_ReconstructFrame) {
    7912                 :       // If we ever start passing true here, be careful of restyles
    7913                 :       // that involve a reframe and animations.  In particular, if the
    7914                 :       // restyle we're processing here is an animation restyle, but
    7915                 :       // the style resolution we will do for the frame construction
    7916                 :       // happens async when we're not in an animation restyle already,
    7917                 :       // problems could arise.
    7918               0 :       RecreateFramesForContent(content, false);
    7919                 :     } else {
    7920               0 :       NS_ASSERTION(frame, "This shouldn't happen");
    7921               0 :       if (hint & nsChangeHint_UpdateEffects) {
    7922               0 :         nsSVGEffects::UpdateEffects(frame);
    7923                 :       }
    7924               0 :       if (hint & nsChangeHint_NeedReflow) {
    7925               0 :         StyleChangeReflow(frame, hint);
    7926               0 :         didReflow = true;
    7927                 :       }
    7928               0 :       if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
    7929                 :                   nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer)) {
    7930               0 :         ApplyRenderingChangeToTree(presContext, frame, hint);
    7931               0 :         didInvalidate = true;
    7932                 :       }
    7933               0 :       if ((hint & nsChangeHint_UpdateOverflow) && !didReflow) {
    7934               0 :         while (frame) {
    7935                 :           nsOverflowAreas* pre = static_cast<nsOverflowAreas*>
    7936               0 :             (frame->Properties().Get(frame->PreTransformOverflowAreasProperty()));
    7937               0 :           if (pre) {
    7938                 :             // FinishAndStoreOverflow will change the overflow areas passed in,
    7939                 :             // so make a copy.
    7940               0 :             nsOverflowAreas overflowAreas = *pre;
    7941               0 :             frame->FinishAndStoreOverflow(overflowAreas, frame->GetSize());
    7942                 :           } else {
    7943               0 :             frame->UpdateOverflow();
    7944                 :           }
    7945                 : 
    7946                 :           nsIFrame* next =
    7947               0 :             nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
    7948                 :           // Update the ancestors' overflow after we have updated the overflow
    7949                 :           // for all the continuations with the same parent.
    7950               0 :           if (!next || frame->GetParent() != next->GetParent()) {
    7951               0 :             for (nsIFrame* ancestor = frame->GetParent(); ancestor;
    7952                 :                  ancestor = ancestor->GetParent()) {
    7953               0 :               if (!ancestor->UpdateOverflow()) {
    7954               0 :                 break;
    7955                 :               }
    7956                 :             }
    7957                 :           }
    7958               0 :           frame = next;
    7959                 :         }
    7960                 :       }
    7961               0 :       if (hint & nsChangeHint_UpdateCursor) {
    7962               0 :         mPresShell->SynthesizeMouseMove(false);
    7963                 :       }
    7964                 :     }
    7965                 :   }
    7966                 : 
    7967               0 :   EndUpdate();
    7968                 : 
    7969               0 :   if (didInvalidate && !didReflow) {
    7970                 :     // RepaintFrame changes can indicate changes in opacity etc which
    7971                 :     // can require plugin clipping to change. If we requested a reflow,
    7972                 :     // we don't need to do this since the reflow will do it for us.
    7973               0 :     nsIFrame* rootFrame = GetRootFrame();
    7974               0 :     nsRootPresContext* rootPC = presContext->GetRootPresContext();
    7975               0 :     if (rootPC) {
    7976               0 :       rootPC->RequestUpdatePluginGeometry(rootFrame);
    7977                 :     }
    7978                 :   }
    7979                 : 
    7980                 :   // cleanup references and verify the style tree.  Note that the latter needs
    7981                 :   // to happen once we've processed the whole list, since until then the tree
    7982                 :   // is not in fact in a consistent state.
    7983               0 :   index = count;
    7984               0 :   while (0 <= --index) {
    7985                 :     const nsStyleChangeData* changeData;
    7986               0 :     aChangeList.ChangeAt(index, &changeData);
    7987               0 :     if (changeData->mFrame) {
    7988               0 :       propTable->Delete(changeData->mFrame, ChangeListProperty());
    7989                 :     }
    7990                 : 
    7991                 : #ifdef DEBUG
    7992                 :     // reget frame from content since it may have been regenerated...
    7993               0 :     if (changeData->mContent) {
    7994               0 :       nsIFrame* frame = changeData->mContent->GetPrimaryFrame();
    7995               0 :       if (frame) {
    7996               0 :         DebugVerifyStyleTree(frame);
    7997                 :       }
    7998                 :     } else {
    7999               0 :       NS_WARNING("Unable to test style tree integrity -- no content node");
    8000                 :     }
    8001                 : #endif
    8002                 :   }
    8003                 : 
    8004               0 :   aChangeList.Clear();
    8005               0 :   return NS_OK;
    8006                 : }
    8007                 : 
    8008                 : void
    8009               0 : nsCSSFrameConstructor::RestyleElement(Element        *aElement,
    8010                 :                                       nsIFrame       *aPrimaryFrame,
    8011                 :                                       nsChangeHint   aMinHint,
    8012                 :                                       RestyleTracker& aRestyleTracker,
    8013                 :                                       bool            aRestyleDescendants)
    8014                 : {
    8015               0 :   NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
    8016                 :                "frame/content mismatch");
    8017               0 :   if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
    8018                 :     // XXXbz this is due to image maps messing with the primary frame pointer
    8019                 :     // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
    8020               0 :     aPrimaryFrame = nsnull;
    8021                 :   }
    8022               0 :   NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aElement,
    8023                 :                "frame/content mismatch");
    8024                 : 
    8025               0 :   if (aMinHint & nsChangeHint_ReconstructFrame) {
    8026               0 :     RecreateFramesForContent(aElement, false);
    8027               0 :   } else if (aPrimaryFrame) {
    8028               0 :     nsStyleChangeList changeList;
    8029                 :     ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
    8030               0 :                           aRestyleTracker, aRestyleDescendants);
    8031               0 :     ProcessRestyledFrames(changeList);
    8032                 :   } else {
    8033                 :     // no frames, reconstruct for content
    8034               0 :     MaybeRecreateFramesForElement(aElement);
    8035                 :   }
    8036               0 : }
    8037                 : 
    8038                 : nsresult
    8039               0 : nsCSSFrameConstructor::ContentStateChanged(nsIContent* aContent,
    8040                 :                                            nsEventStates aStateMask)
    8041                 : {
    8042                 :   // XXXbz it would be good if this function only took Elements, but
    8043                 :   // we'd have to make ESM guarantee that usefully.
    8044               0 :   if (!aContent->IsElement()) {
    8045               0 :     return NS_OK;
    8046                 :   }
    8047                 : 
    8048               0 :   Element* aElement = aContent->AsElement();
    8049                 : 
    8050               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
    8051               0 :   nsPresContext *presContext = mPresShell->GetPresContext();
    8052               0 :   NS_ASSERTION(styleSet, "couldn't get style set");
    8053                 : 
    8054               0 :   nsChangeHint hint = NS_STYLE_HINT_NONE;
    8055                 :   // Any change to a content state that affects which frames we construct
    8056                 :   // must lead to a frame reconstruct here if we already have a frame.
    8057                 :   // Note that we never decide through non-CSS means to not create frames
    8058                 :   // based on content states, so if we already don't have a frame we don't
    8059                 :   // need to force a reframe -- if it's needed, the HasStateDependentStyle
    8060                 :   // call will handle things.
    8061               0 :   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
    8062               0 :   if (primaryFrame) {
    8063                 :     // If it's generated content, ignore LOADING/etc state changes on it.
    8064               0 :     if (!primaryFrame->IsGeneratedContentFrame() &&
    8065                 :         aStateMask.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
    8066                 :                                          NS_EVENT_STATE_USERDISABLED |
    8067                 :                                          NS_EVENT_STATE_SUPPRESSED |
    8068               0 :                                          NS_EVENT_STATE_LOADING)) {
    8069               0 :       hint = nsChangeHint_ReconstructFrame;
    8070                 :     } else {
    8071               0 :       PRUint8 app = primaryFrame->GetStyleDisplay()->mAppearance;
    8072               0 :       if (app) {
    8073               0 :         nsITheme *theme = presContext->GetTheme();
    8074               0 :         if (theme && theme->ThemeSupportsWidget(presContext,
    8075               0 :                                                 primaryFrame, app)) {
    8076               0 :           bool repaint = false;
    8077               0 :           theme->WidgetStateChanged(primaryFrame, app, nsnull, &repaint);
    8078               0 :           if (repaint) {
    8079               0 :             NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
    8080                 :           }
    8081                 :         }
    8082                 :       }
    8083                 :     }
    8084                 : 
    8085               0 :     primaryFrame->ContentStatesChanged(aStateMask);
    8086                 :   }
    8087                 : 
    8088               0 :   if (aStateMask.HasState(NS_EVENT_STATE_HOVER) &&
    8089               0 :       !aElement->HasFlag(NODE_HAS_RELEVANT_HOVER_RULES)) {
    8090               0 :     aStateMask &= ~NS_EVENT_STATE_HOVER;
    8091                 :   }
    8092                 : 
    8093               0 :   nsRestyleHint rshint = aStateMask.IsEmpty() ?
    8094                 :       nsRestyleHint(0) :
    8095               0 :       styleSet->HasStateDependentStyle(presContext, aElement, aStateMask);
    8096                 :       
    8097               0 :   if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && rshint != 0) {
    8098               0 :     ++mHoverGeneration;
    8099                 :   }
    8100                 : 
    8101               0 :   if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
    8102                 :     // Exposing information to the page about whether the link is
    8103                 :     // visited or not isn't really something we can worry about here.
    8104                 :     // FIXME: We could probably do this a bit better.
    8105               0 :     NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
    8106                 :   }
    8107                 : 
    8108               0 :   PostRestyleEvent(aElement, rshint, hint);
    8109               0 :   return NS_OK;
    8110                 : }
    8111                 : 
    8112                 : void
    8113               0 : nsCSSFrameConstructor::AttributeWillChange(Element* aElement,
    8114                 :                                            PRInt32 aNameSpaceID,
    8115                 :                                            nsIAtom* aAttribute,
    8116                 :                                            PRInt32 aModType)
    8117                 : {
    8118                 :   nsRestyleHint rshint =
    8119                 :     mPresShell->StyleSet()->HasAttributeDependentStyle(mPresShell->GetPresContext(),
    8120                 :                                                        aElement,
    8121                 :                                                        aAttribute,
    8122                 :                                                        aModType,
    8123               0 :                                                        false);
    8124               0 :   PostRestyleEvent(aElement, rshint, NS_STYLE_HINT_NONE);
    8125               0 : }
    8126                 : 
    8127                 : void
    8128               0 : nsCSSFrameConstructor::AttributeChanged(Element* aElement,
    8129                 :                                         PRInt32 aNameSpaceID,
    8130                 :                                         nsIAtom* aAttribute,
    8131                 :                                         PRInt32 aModType)
    8132                 : {
    8133                 :   // Hold onto the PresShell to prevent ourselves from being destroyed.
    8134                 :   // XXXbz how, exactly, would this attribute change cause us to be
    8135                 :   // destroyed from inside this function?
    8136               0 :   nsCOMPtr<nsIPresShell> shell = mPresShell;
    8137                 : 
    8138                 :   // Get the frame associated with the content which is the highest in the frame tree
    8139               0 :   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
    8140                 : 
    8141                 : #if 0
    8142                 :   NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
    8143                 :      ("HTMLStyleSheet::AttributeChanged: content=%p[%s] frame=%p",
    8144                 :       aContent, ContentTag(aElement, 0), frame));
    8145                 : #endif
    8146                 : 
    8147                 :   // the style tag has its own interpretation based on aHint 
    8148               0 :   nsChangeHint hint = aElement->GetAttributeChangeHint(aAttribute, aModType);
    8149                 : 
    8150               0 :   bool reframe = (hint & nsChangeHint_ReconstructFrame) != 0;
    8151                 : 
    8152                 : #ifdef MOZ_XUL
    8153                 :   // The following listbox widget trap prevents offscreen listbox widget
    8154                 :   // content from being removed and re-inserted (which is what would
    8155                 :   // happen otherwise).
    8156               0 :   if (!primaryFrame && !reframe) {
    8157                 :     PRInt32 namespaceID;
    8158                 :     nsIAtom* tag =
    8159               0 :       mDocument->BindingManager()->ResolveTag(aElement, &namespaceID);
    8160                 : 
    8161               0 :     if (namespaceID == kNameSpaceID_XUL &&
    8162                 :         (tag == nsGkAtoms::listitem ||
    8163                 :          tag == nsGkAtoms::listcell))
    8164                 :       return;
    8165                 :   }
    8166                 : 
    8167               0 :   if (aAttribute == nsGkAtoms::tooltiptext ||
    8168                 :       aAttribute == nsGkAtoms::tooltip) 
    8169                 :   {
    8170               0 :     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    8171               0 :     if (rootBox) {
    8172               0 :       if (aModType == nsIDOMMutationEvent::REMOVAL)
    8173               0 :         rootBox->RemoveTooltipSupport(aElement);
    8174               0 :       if (aModType == nsIDOMMutationEvent::ADDITION)
    8175               0 :         rootBox->AddTooltipSupport(aElement);
    8176                 :     }
    8177                 :   }
    8178                 : 
    8179                 : #endif // MOZ_XUL
    8180                 : 
    8181               0 :   if (primaryFrame) {
    8182                 :     // See if we have appearance information for a theme.
    8183               0 :     const nsStyleDisplay* disp = primaryFrame->GetStyleDisplay();
    8184               0 :     if (disp->mAppearance) {
    8185               0 :       nsPresContext* presContext = mPresShell->GetPresContext();
    8186               0 :       nsITheme *theme = presContext->GetTheme();
    8187               0 :       if (theme && theme->ThemeSupportsWidget(presContext, primaryFrame, disp->mAppearance)) {
    8188               0 :         bool repaint = false;
    8189               0 :         theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute, &repaint);
    8190               0 :         if (repaint)
    8191               0 :           NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
    8192                 :       }
    8193                 :     }
    8194                 :    
    8195                 :     // let the frame deal with it now, so we don't have to deal later
    8196               0 :     primaryFrame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
    8197                 :     // XXXwaterson should probably check for special IB siblings
    8198                 :     // here, and propagate the AttributeChanged notification to
    8199                 :     // them, as well. Currently, inline frames don't do anything on
    8200                 :     // this notification, so it's not that big a deal.
    8201                 :   }
    8202                 : 
    8203                 :   // See if we can optimize away the style re-resolution -- must be called after
    8204                 :   // the frame's AttributeChanged() in case it does something that affects the style
    8205                 :   nsRestyleHint rshint =
    8206                 :     mPresShell->StyleSet()->HasAttributeDependentStyle(mPresShell->GetPresContext(),
    8207                 :                                                        aElement,
    8208                 :                                                        aAttribute,
    8209                 :                                                        aModType,
    8210               0 :                                                        true);
    8211                 : 
    8212               0 :   PostRestyleEvent(aElement, rshint, hint);
    8213                 : }
    8214                 : 
    8215                 : void
    8216               0 : nsCSSFrameConstructor::BeginUpdate() {
    8217               0 :   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
    8218                 :                "Someone forgot a script blocker");
    8219                 : 
    8220                 :   nsRootPresContext* rootPresContext =
    8221               0 :     mPresShell->GetPresContext()->GetRootPresContext();
    8222               0 :   if (rootPresContext) {
    8223               0 :     rootPresContext->IncrementDOMGeneration();
    8224                 :   }
    8225                 : 
    8226               0 :   ++mUpdateCount;
    8227               0 : }
    8228                 : 
    8229                 : void
    8230               0 : nsCSSFrameConstructor::EndUpdate()
    8231                 : {
    8232               0 :   if (mUpdateCount == 1) {
    8233                 :     // This is the end of our last update.  Before we decrement
    8234                 :     // mUpdateCount, recalc quotes and counters as needed.
    8235                 : 
    8236               0 :     RecalcQuotesAndCounters();
    8237               0 :     NS_ASSERTION(mUpdateCount == 1, "Odd update count");
    8238                 :   }
    8239               0 :   NS_ASSERTION(mUpdateCount, "Negative mUpdateCount!");
    8240               0 :   --mUpdateCount;
    8241               0 : }
    8242                 : 
    8243                 : void
    8244               0 : nsCSSFrameConstructor::RecalcQuotesAndCounters()
    8245                 : {
    8246               0 :   if (mQuotesDirty) {
    8247               0 :     mQuotesDirty = false;
    8248               0 :     mQuoteList.RecalcAll();
    8249                 :   }
    8250                 : 
    8251               0 :   if (mCountersDirty) {
    8252               0 :     mCountersDirty = false;
    8253               0 :     mCounterManager.RecalcAll();
    8254                 :   }
    8255                 : 
    8256               0 :   NS_ASSERTION(!mQuotesDirty, "Quotes updates will be lost");
    8257               0 :   NS_ASSERTION(!mCountersDirty, "Counter updates will be lost");  
    8258               0 : }
    8259                 : 
    8260                 : void
    8261               0 : nsCSSFrameConstructor::WillDestroyFrameTree()
    8262                 : {
    8263                 : #if defined(DEBUG_dbaron_off)
    8264                 :   mCounterManager.Dump();
    8265                 : #endif
    8266                 : 
    8267               0 :   mIsDestroyingFrameTree = true;
    8268                 : 
    8269                 :   // Prevent frame tree destruction from being O(N^2)
    8270               0 :   mQuoteList.Clear();
    8271               0 :   mCounterManager.Clear();
    8272                 : 
    8273                 :   // Remove our presshell as a style flush observer.  But leave
    8274                 :   // mObservingRefreshDriver true so we don't readd to it even if someone tries
    8275                 :   // to post restyle events on us from this point on for some reason.
    8276                 :   mPresShell->GetPresContext()->RefreshDriver()->
    8277               0 :     RemoveStyleFlushObserver(mPresShell);
    8278                 : 
    8279               0 :   nsFrameManager::Destroy();
    8280               0 : }
    8281                 : 
    8282                 : //STATIC
    8283                 : 
    8284                 : // XXXbz I'd really like this method to go away. Once we have inline-block and
    8285                 : // I can just use that for sized broken images, that can happen, maybe.
    8286               0 : void nsCSSFrameConstructor::GetAlternateTextFor(nsIContent*    aContent,
    8287                 :                                                 nsIAtom*       aTag,  // content object's tag
    8288                 :                                                 nsXPIDLString& aAltText)
    8289                 : {
    8290                 :   // The "alt" attribute specifies alternate text that is rendered
    8291                 :   // when the image can not be displayed
    8292                 : 
    8293                 :   // If there's no "alt" attribute, and aContent is an input    
    8294                 :   // element, then use the value of the "value" attribute
    8295               0 :   if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aAltText) &&
    8296                 :       nsGkAtoms::input == aTag) {
    8297                 :     // If there's no "value" attribute either, then use the localized string 
    8298                 :     // for "Submit" as the alternate text.
    8299               0 :     if (!aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aAltText)) {
    8300                 :       nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
    8301               0 :                                          "Submit", aAltText);      
    8302                 :     }
    8303                 :   }
    8304               0 : }
    8305                 : 
    8306                 : nsresult
    8307               0 : nsCSSFrameConstructor::CreateContinuingOuterTableFrame(nsIPresShell*    aPresShell,
    8308                 :                                                        nsPresContext*  aPresContext,
    8309                 :                                                        nsIFrame*        aFrame,
    8310                 :                                                        nsIFrame*        aParentFrame,
    8311                 :                                                        nsIContent*      aContent,
    8312                 :                                                        nsStyleContext*  aStyleContext,
    8313                 :                                                        nsIFrame**       aContinuingFrame)
    8314                 : {
    8315               0 :   nsIFrame* newFrame = NS_NewTableOuterFrame(aPresShell, aStyleContext);
    8316                 : 
    8317               0 :   if (newFrame) {
    8318               0 :     newFrame->Init(aContent, aParentFrame, aFrame);
    8319                 : 
    8320                 :     // Create a continuing inner table frame, and if there's a caption then
    8321                 :     // replicate the caption
    8322               0 :     nsFrameItems  newChildFrames;
    8323                 : 
    8324               0 :     nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
    8325               0 :     if (childFrame) {
    8326                 :       nsIFrame* continuingTableFrame;
    8327                 :       nsresult rv = CreateContinuingFrame(aPresContext, childFrame, newFrame,
    8328               0 :                                           &continuingTableFrame);
    8329               0 :       if (NS_FAILED(rv)) {
    8330               0 :         newFrame->Destroy();
    8331               0 :         *aContinuingFrame = nsnull;
    8332               0 :         return rv;
    8333                 :       }
    8334               0 :       newChildFrames.AddChild(continuingTableFrame);
    8335                 :       
    8336               0 :       NS_ASSERTION(!childFrame->GetNextSibling(),"there can be only one inner table frame");
    8337                 :     }
    8338                 : 
    8339                 :     // Set the outer table's initial child list
    8340               0 :     newFrame->SetInitialChildList(kPrincipalList, newChildFrames);
    8341                 :     
    8342               0 :     *aContinuingFrame = newFrame;
    8343               0 :     return NS_OK;
    8344                 :   }
    8345                 :   else {
    8346               0 :     *aContinuingFrame = nsnull;
    8347               0 :     return NS_ERROR_OUT_OF_MEMORY;
    8348                 :   }
    8349                 : }
    8350                 : 
    8351                 : nsresult
    8352               0 : nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell, 
    8353                 :                                                   nsPresContext*  aPresContext,
    8354                 :                                                   nsIFrame*        aFrame,
    8355                 :                                                   nsIFrame*        aParentFrame,
    8356                 :                                                   nsIContent*      aContent,
    8357                 :                                                   nsStyleContext*  aStyleContext,
    8358                 :                                                   nsIFrame**       aContinuingFrame)
    8359                 : {
    8360               0 :   nsIFrame* newFrame = NS_NewTableFrame(aPresShell, aStyleContext);
    8361                 : 
    8362               0 :   if (newFrame) {
    8363               0 :     newFrame->Init(aContent, aParentFrame, aFrame);
    8364                 : 
    8365                 :     // Replicate any header/footer frames
    8366               0 :     nsFrameItems  childFrames;
    8367               0 :     nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
    8368               0 :     for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
    8369                 :       // See if it's a header/footer, possibly wrapped in a scroll frame.
    8370                 :       nsTableRowGroupFrame* rowGroupFrame =
    8371               0 :         static_cast<nsTableRowGroupFrame*>(childFrame);
    8372                 :       // If the row group was continued, then don't replicate it.
    8373               0 :       nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
    8374               0 :       if (rgNextInFlow) {
    8375               0 :         rowGroupFrame->SetRepeatable(false);
    8376                 :       }
    8377               0 :       else if (rowGroupFrame->IsRepeatable()) {
    8378                 :         // Replicate the header/footer frame.
    8379                 :         nsTableRowGroupFrame*   headerFooterFrame;
    8380               0 :         nsFrameItems            childItems;
    8381                 :         nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
    8382                 :                                       GetAbsoluteContainingBlock(newFrame),
    8383               0 :                                       nsnull);
    8384               0 :         state.mCreatingExtraFrames = true;
    8385                 : 
    8386                 :         headerFooterFrame = static_cast<nsTableRowGroupFrame*>
    8387               0 :                                        (NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
    8388               0 :         nsIContent* headerFooter = rowGroupFrame->GetContent();
    8389               0 :         headerFooterFrame->Init(headerFooter, newFrame, nsnull);
    8390                 :         ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
    8391                 :                         headerFooterFrame, true, childItems, false,
    8392               0 :                         nsnull);
    8393               0 :         NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
    8394               0 :         headerFooterFrame->SetInitialChildList(kPrincipalList, childItems);
    8395               0 :         headerFooterFrame->SetRepeatable(true);
    8396                 : 
    8397                 :         // Table specific initialization
    8398               0 :         headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
    8399                 : 
    8400                 :         // XXX Deal with absolute and fixed frames...
    8401               0 :         childFrames.AddChild(headerFooterFrame);
    8402                 :       }
    8403                 :     }
    8404                 :     
    8405                 :     // Set the table frame's initial child list
    8406               0 :     newFrame->SetInitialChildList(kPrincipalList, childFrames);
    8407                 :     
    8408               0 :     *aContinuingFrame = newFrame;
    8409               0 :     return NS_OK;
    8410                 :   }
    8411                 :   else {
    8412               0 :     *aContinuingFrame = nsnull;
    8413               0 :     return NS_ERROR_OUT_OF_MEMORY;
    8414                 :   }
    8415                 : }
    8416                 : 
    8417                 : nsresult
    8418               0 : nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext,
    8419                 :                                              nsIFrame*       aFrame,
    8420                 :                                              nsIFrame*       aParentFrame,
    8421                 :                                              nsIFrame**      aContinuingFrame,
    8422                 :                                              bool            aIsFluid)
    8423                 : {
    8424               0 :   nsIPresShell*              shell = aPresContext->PresShell();
    8425               0 :   nsStyleContext*            styleContext = aFrame->GetStyleContext();
    8426               0 :   nsIFrame*                  newFrame = nsnull;
    8427               0 :   nsresult                   rv = NS_OK;
    8428               0 :   nsIFrame*                  nextContinuation = aFrame->GetNextContinuation();
    8429               0 :   nsIFrame*                  nextInFlow = aFrame->GetNextInFlow();
    8430                 : 
    8431                 :   // Use the frame type to determine what type of frame to create
    8432               0 :   nsIAtom* frameType = aFrame->GetType();
    8433               0 :   nsIContent* content = aFrame->GetContent();
    8434                 : 
    8435               0 :   NS_ASSERTION(aFrame->GetSplittableType() != NS_FRAME_NOT_SPLITTABLE,
    8436                 :                "why CreateContinuingFrame for a non-splittable frame?");
    8437                 :   
    8438               0 :   if (nsGkAtoms::textFrame == frameType) {
    8439               0 :     newFrame = NS_NewContinuingTextFrame(shell, styleContext);
    8440                 : 
    8441               0 :     if (newFrame) {
    8442               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8443                 :     }
    8444                 :     
    8445               0 :   } else if (nsGkAtoms::inlineFrame == frameType) {
    8446               0 :     newFrame = NS_NewInlineFrame(shell, styleContext);
    8447                 : 
    8448               0 :     if (newFrame) {
    8449               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8450                 :     }
    8451                 :   
    8452               0 :   } else if (nsGkAtoms::blockFrame == frameType) {
    8453               0 :     newFrame = NS_NewBlockFrame(shell, styleContext);
    8454                 : 
    8455               0 :     if (newFrame) {
    8456               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8457                 :     }
    8458                 :   
    8459                 : #ifdef MOZ_XUL
    8460               0 :   } else if (nsGkAtoms::XULLabelFrame == frameType) {
    8461               0 :     newFrame = NS_NewXULLabelFrame(shell, styleContext);
    8462                 : 
    8463               0 :     if (newFrame) {
    8464               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8465                 :     }
    8466                 : #endif  
    8467               0 :   } else if (nsGkAtoms::columnSetFrame == frameType) {
    8468               0 :     newFrame = NS_NewColumnSetFrame(shell, styleContext, 0);
    8469                 : 
    8470               0 :     if (newFrame) {
    8471               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8472                 :     }
    8473                 : 
    8474               0 :   } else if (nsGkAtoms::pageFrame == frameType) {
    8475                 :     nsIFrame* canvasFrame;
    8476                 :     rv = ConstructPageFrame(shell, aPresContext, aParentFrame, aFrame,
    8477               0 :                             newFrame, canvasFrame);
    8478               0 :   } else if (nsGkAtoms::tableOuterFrame == frameType) {
    8479                 :     rv = CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
    8480               0 :                                          content, styleContext, &newFrame);
    8481                 : 
    8482               0 :   } else if (nsGkAtoms::tableFrame == frameType) {
    8483                 :     rv = CreateContinuingTableFrame(shell, aPresContext, aFrame, aParentFrame,
    8484               0 :                                     content, styleContext, &newFrame);
    8485                 : 
    8486               0 :   } else if (nsGkAtoms::tableRowGroupFrame == frameType) {
    8487               0 :     newFrame = NS_NewTableRowGroupFrame(shell, styleContext);
    8488                 : 
    8489               0 :     if (newFrame) {
    8490               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8491                 :     }
    8492                 : 
    8493               0 :   } else if (nsGkAtoms::tableRowFrame == frameType) {
    8494               0 :     newFrame = NS_NewTableRowFrame(shell, styleContext);
    8495                 : 
    8496               0 :     if (newFrame) {
    8497               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8498                 : 
    8499                 :       // Create a continuing frame for each table cell frame
    8500               0 :       nsFrameItems  newChildList;
    8501               0 :       nsIFrame* cellFrame = aFrame->GetFirstPrincipalChild();
    8502               0 :       while (cellFrame) {
    8503                 :         // See if it's a table cell frame
    8504               0 :         if (IS_TABLE_CELL(cellFrame->GetType())) {
    8505                 :           nsIFrame* continuingCellFrame;
    8506                 :           rv = CreateContinuingFrame(aPresContext, cellFrame, newFrame,
    8507               0 :                                      &continuingCellFrame);
    8508               0 :           if (NS_FAILED(rv)) {
    8509               0 :             newChildList.DestroyFrames();
    8510               0 :             newFrame->Destroy();
    8511               0 :             *aContinuingFrame = nsnull;
    8512               0 :             return NS_ERROR_OUT_OF_MEMORY;
    8513                 :           }
    8514               0 :           newChildList.AddChild(continuingCellFrame);
    8515                 :         }
    8516               0 :         cellFrame = cellFrame->GetNextSibling();
    8517                 :       }
    8518                 :       
    8519                 :       // Set the table cell's initial child list
    8520               0 :       newFrame->SetInitialChildList(kPrincipalList, newChildList);
    8521                 :     }
    8522                 : 
    8523               0 :   } else if (IS_TABLE_CELL(frameType)) {
    8524                 :     // Warning: If you change this and add a wrapper frame around table cell
    8525                 :     // frames, make sure Bug 368554 doesn't regress!
    8526                 :     // See IsInAutoWidthTableCellForQuirk() in nsImageFrame.cpp.
    8527               0 :     newFrame = NS_NewTableCellFrame(shell, styleContext, IsBorderCollapse(aParentFrame));
    8528                 : 
    8529               0 :     if (newFrame) {
    8530               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8531                 : 
    8532                 :       // Create a continuing area frame
    8533                 :       nsIFrame* continuingBlockFrame;
    8534               0 :       nsIFrame* blockFrame = aFrame->GetFirstPrincipalChild();
    8535                 :       rv = CreateContinuingFrame(aPresContext, blockFrame, newFrame,
    8536               0 :                                  &continuingBlockFrame);
    8537               0 :       if (NS_FAILED(rv)) {
    8538               0 :         newFrame->Destroy();
    8539               0 :         *aContinuingFrame = nsnull;
    8540               0 :         return rv;
    8541                 :       }
    8542                 : 
    8543                 :       // Set the table cell's initial child list
    8544               0 :       SetInitialSingleChild(newFrame, continuingBlockFrame);
    8545                 :     }
    8546                 :   
    8547               0 :   } else if (nsGkAtoms::lineFrame == frameType) {
    8548               0 :     newFrame = NS_NewFirstLineFrame(shell, styleContext);
    8549                 : 
    8550               0 :     if (newFrame) {
    8551               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8552                 :     }
    8553                 :   
    8554               0 :   } else if (nsGkAtoms::letterFrame == frameType) {
    8555               0 :     newFrame = NS_NewFirstLetterFrame(shell, styleContext);
    8556                 : 
    8557               0 :     if (newFrame) {
    8558               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8559                 :     }
    8560                 : 
    8561               0 :   } else if (nsGkAtoms::imageFrame == frameType) {
    8562               0 :     newFrame = NS_NewImageFrame(shell, styleContext);
    8563                 : 
    8564               0 :     if (newFrame) {
    8565               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8566                 :     }
    8567               0 :   } else if (nsGkAtoms::imageControlFrame == frameType) {
    8568               0 :     newFrame = NS_NewImageControlFrame(shell, styleContext);
    8569                 : 
    8570               0 :     if (newFrame) {
    8571               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8572                 :     }    
    8573               0 :   } else if (nsGkAtoms::placeholderFrame == frameType) {
    8574                 :     // create a continuing out of flow frame
    8575               0 :     nsIFrame* oofFrame = nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
    8576                 :     nsIFrame* oofContFrame;
    8577               0 :     rv = CreateContinuingFrame(aPresContext, oofFrame, aParentFrame, &oofContFrame);
    8578               0 :     if (NS_FAILED(rv)) {
    8579               0 :       *aContinuingFrame = nsnull;
    8580               0 :       return rv;
    8581                 :     }
    8582                 :     // create a continuing placeholder frame
    8583                 :     rv = CreatePlaceholderFrameFor(shell, content, oofContFrame, styleContext,
    8584                 :                                    aParentFrame, aFrame,
    8585               0 :                                    aFrame->GetStateBits() & PLACEHOLDER_TYPE_MASK,
    8586               0 :                                    &newFrame);
    8587               0 :     if (NS_FAILED(rv)) {
    8588               0 :       oofContFrame->Destroy();
    8589               0 :       *aContinuingFrame = nsnull;
    8590               0 :       return rv;
    8591                 :     }
    8592               0 :   } else if (nsGkAtoms::fieldSetFrame == frameType) {
    8593               0 :     newFrame = NS_NewFieldSetFrame(shell, styleContext);
    8594                 : 
    8595               0 :     if (newFrame) {
    8596               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8597                 : 
    8598                 :       // Create a continuing area frame
    8599                 :       // XXXbz we really shouldn't have to do this by hand!
    8600                 :       nsIFrame* continuingBlockFrame;
    8601               0 :       nsIFrame* blockFrame = GetFieldSetBlockFrame(aFrame);
    8602                 :       rv = CreateContinuingFrame(aPresContext, blockFrame, newFrame,
    8603               0 :                                  &continuingBlockFrame);
    8604               0 :       if (NS_FAILED(rv)) {
    8605               0 :         newFrame->Destroy();
    8606               0 :         *aContinuingFrame = nsnull;
    8607               0 :         return rv;
    8608                 :       }
    8609                 :       // Set the fieldset's initial child list
    8610               0 :       SetInitialSingleChild(newFrame, continuingBlockFrame);
    8611                 :     }
    8612               0 :   } else if (nsGkAtoms::legendFrame == frameType) {
    8613               0 :     newFrame = NS_NewLegendFrame(shell, styleContext);
    8614                 : 
    8615               0 :     if (newFrame) {
    8616               0 :       newFrame->Init(content, aParentFrame, aFrame);
    8617                 :     }
    8618                 :   } else {
    8619               0 :     NS_NOTREACHED("unexpected frame type");
    8620               0 :     *aContinuingFrame = nsnull;
    8621               0 :     return NS_ERROR_UNEXPECTED;
    8622                 :   }
    8623                 : 
    8624               0 :   *aContinuingFrame = newFrame;
    8625                 : 
    8626               0 :   if (!newFrame) {
    8627               0 :     return NS_ERROR_OUT_OF_MEMORY;
    8628                 :   }
    8629                 : 
    8630                 :   // Init() set newFrame to be a fluid continuation of aFrame.
    8631                 :   // If we want a non-fluid continuation, we need to call SetPrevContinuation()
    8632                 :   // to reset NS_FRAME_IS_FLUID_CONTINUATION.
    8633               0 :   if (!aIsFluid) {
    8634               0 :     newFrame->SetPrevContinuation(aFrame);
    8635                 :   }
    8636                 : 
    8637                 :   // A continuation of generated content is also generated content
    8638               0 :   if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) {
    8639               0 :     newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT);
    8640                 :   }
    8641                 : 
    8642                 :   // A continuation of an out-of-flow is also an out-of-flow
    8643               0 :   if (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
    8644               0 :     newFrame->AddStateBits(NS_FRAME_OUT_OF_FLOW);
    8645                 :   }
    8646                 : 
    8647               0 :   if (nextInFlow) {
    8648               0 :     nextInFlow->SetPrevInFlow(newFrame);
    8649               0 :     newFrame->SetNextInFlow(nextInFlow);
    8650               0 :   } else if (nextContinuation) {
    8651               0 :     nextContinuation->SetPrevContinuation(newFrame);
    8652               0 :     newFrame->SetNextContinuation(nextContinuation);
    8653                 :   }
    8654                 : 
    8655               0 :   NS_POSTCONDITION(!newFrame->GetNextSibling(), "unexpected sibling");
    8656               0 :   return NS_OK;
    8657                 : }
    8658                 : 
    8659                 : nsresult
    8660               0 : nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame)
    8661                 : {
    8662                 :   // Now deal with fixed-pos things....  They should appear on all pages,
    8663                 :   // so we want to move over the placeholders when processing the child
    8664                 :   // of the pageContentFrame.
    8665                 : 
    8666               0 :   nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow();
    8667               0 :   if (!prevPageContentFrame) {
    8668               0 :     return NS_OK;
    8669                 :   }
    8670               0 :   nsIFrame* canvasFrame = aParentFrame->GetFirstPrincipalChild();
    8671               0 :   nsIFrame* prevCanvasFrame = prevPageContentFrame->GetFirstPrincipalChild();
    8672               0 :   if (!canvasFrame || !prevCanvasFrame) {
    8673                 :     // document's root element frame missing
    8674               0 :     return NS_ERROR_UNEXPECTED;
    8675                 :   }
    8676                 : 
    8677               0 :   nsFrameItems fixedPlaceholders;
    8678               0 :   nsIFrame* firstFixed = prevPageContentFrame->GetFirstChild(nsIFrame::kFixedList);
    8679               0 :   if (!firstFixed) {
    8680               0 :     return NS_OK;
    8681                 :   }
    8682                 : 
    8683                 :   // Don't allow abs-pos descendants of the fixed content to escape the content.
    8684                 :   // This should not normally be possible (because fixed-pos elements should
    8685                 :   // be absolute containers) but fixed-pos tables currently aren't abs-pos
    8686                 :   // containers.
    8687                 :   nsFrameConstructorState state(mPresShell, aParentFrame,
    8688                 :                                 nsnull,
    8689               0 :                                 mRootElementFrame);
    8690               0 :   state.mCreatingExtraFrames = true;
    8691                 : 
    8692                 :   // We can't use an ancestor filter here, because we're not going to
    8693                 :   // be usefully recurring down the tree.  This means that other
    8694                 :   // places in frame construction can't assume a filter is
    8695                 :   // initialized!
    8696                 : 
    8697                 :   // Iterate across fixed frames and replicate each whose placeholder is a
    8698                 :   // descendant of aFrame. (We don't want to explicitly copy placeholders that
    8699                 :   // are within fixed frames, because that would cause duplicates on the new
    8700                 :   // page - bug 389619)
    8701               0 :   for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) {
    8702               0 :     nsIFrame* prevPlaceholder = GetPlaceholderFrameFor(fixed);
    8703               0 :     if (prevPlaceholder &&
    8704               0 :         nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) {
    8705                 :       // We want to use the same style as the primary style frame for
    8706                 :       // our content
    8707               0 :       nsIContent* content = fixed->GetContent();
    8708                 :       nsStyleContext* styleContext =
    8709                 :         nsLayoutUtils::GetStyleFrame(content->GetPrimaryFrame())->
    8710               0 :           GetStyleContext();
    8711               0 :       FrameConstructionItemList items;
    8712                 :       AddFrameConstructionItemsInternal(state, content, canvasFrame,
    8713                 :                                         content->Tag(),
    8714                 :                                         content->GetNameSpaceID(),
    8715                 :                                         true,
    8716                 :                                         styleContext,
    8717                 :                                         ITEM_ALLOW_XBL_BASE |
    8718                 :                                           ITEM_ALLOW_PAGE_BREAK,
    8719               0 :                                         items);
    8720               0 :       for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) {
    8721               0 :         NS_ASSERTION(iter.item().DesiredParentType() ==
    8722                 :                        GetParentType(canvasFrame),
    8723                 :                      "This is not going to work");
    8724                 :         nsresult rv =
    8725               0 :           ConstructFramesFromItem(state, iter, canvasFrame, fixedPlaceholders);
    8726               0 :         NS_ENSURE_SUCCESS(rv, rv);
    8727                 :       }
    8728                 :     }
    8729                 :   }
    8730                 : 
    8731                 :   // Add the placeholders to our primary child list.
    8732                 :   // XXXbz this is a little screwed up, since the fixed frames will have 
    8733                 :   // broken auto-positioning. Oh, well.
    8734               0 :   NS_ASSERTION(!canvasFrame->GetFirstPrincipalChild(),
    8735                 :                "leaking frames; doc root continuation must be empty");
    8736               0 :   canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
    8737               0 :   return NS_OK;
    8738                 : }
    8739                 : 
    8740                 : nsresult
    8741               0 : nsCSSFrameConstructor::GetInsertionPoint(nsIFrame*     aParentFrame,
    8742                 :                                          nsIContent*   aChildContent,
    8743                 :                                          nsIFrame**    aInsertionPoint,
    8744                 :                                          bool*       aMultiple)
    8745                 : {
    8746                 :   // Make the insertion point be the parent frame by default, in case
    8747                 :   // we have to bail early.
    8748               0 :   *aInsertionPoint = aParentFrame;
    8749                 : 
    8750               0 :   nsIContent* container = aParentFrame->GetContent();
    8751               0 :   if (!container)
    8752               0 :     return NS_OK;
    8753                 : 
    8754               0 :   nsBindingManager *bindingManager = mDocument->BindingManager();
    8755                 : 
    8756                 :   nsIContent* insertionElement;
    8757               0 :   if (aChildContent) {
    8758                 :     // We've got an explicit insertion child. Check to see if it's
    8759                 :     // anonymous.
    8760               0 :     if (aChildContent->GetBindingParent() == container) {
    8761                 :       // This child content is anonymous. Don't use the insertion
    8762                 :       // point, since that's only for the explicit kids.
    8763               0 :       return NS_OK;
    8764                 :     }
    8765                 : 
    8766                 :     PRUint32 index;
    8767                 :     insertionElement = bindingManager->GetInsertionPoint(container,
    8768                 :                                                          aChildContent,
    8769               0 :                                                          &index);
    8770                 :   }
    8771                 :   else {
    8772                 :     bool multiple;
    8773                 :     PRUint32 index;
    8774                 :     insertionElement = bindingManager->GetSingleInsertionPoint(container,
    8775                 :                                                                &index,
    8776               0 :                                                                &multiple);
    8777               0 :     if (multiple && aMultiple)
    8778               0 :       *aMultiple = multiple; // Record the fact that filters are in use.
    8779                 :   }
    8780                 : 
    8781               0 :   if (insertionElement) {
    8782               0 :     nsIFrame* insertionPoint = insertionElement->GetPrimaryFrame();
    8783               0 :     if (insertionPoint) {
    8784                 :       // Use the content insertion frame of the insertion point.
    8785               0 :       insertionPoint = insertionPoint->GetContentInsertionFrame();
    8786               0 :       if (insertionPoint && insertionPoint != aParentFrame) 
    8787               0 :         GetInsertionPoint(insertionPoint, aChildContent, aInsertionPoint, aMultiple);
    8788                 :     }
    8789                 :     else {
    8790                 :       // There was no frame created yet for the insertion point.
    8791               0 :       *aInsertionPoint = nsnull;
    8792                 :     }
    8793                 :   }
    8794                 : 
    8795                 :   // fieldsets have multiple insertion points.  Note that we might
    8796                 :   // have to look at insertionElement here...
    8797               0 :   if (aMultiple && !*aMultiple) {
    8798               0 :     nsIContent* content = insertionElement ? insertionElement : container;
    8799               0 :     if (content->IsHTML(nsGkAtoms::fieldset)) {
    8800               0 :       *aMultiple = true;
    8801                 :     }
    8802                 :   }
    8803                 : 
    8804               0 :   return NS_OK;
    8805                 : }
    8806                 : 
    8807                 : // Capture state for the frame tree rooted at the frame associated with the
    8808                 : // content object, aContent
    8809                 : nsresult
    8810               0 : nsCSSFrameConstructor::CaptureStateForFramesOf(nsIContent* aContent,
    8811                 :                                                nsILayoutHistoryState* aHistoryState)
    8812                 : {
    8813               0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    8814               0 :   if (frame == mRootElementFrame) {
    8815               0 :     frame = mFixedContainingBlock;
    8816                 :   }
    8817               0 :   if (frame) {
    8818               0 :     CaptureStateFor(frame, aHistoryState);
    8819                 :   }
    8820               0 :   return NS_OK;
    8821                 : }
    8822                 : 
    8823                 : // Capture state for the frame tree rooted at aFrame.
    8824                 : nsresult
    8825               0 : nsCSSFrameConstructor::CaptureStateFor(nsIFrame* aFrame,
    8826                 :                                        nsILayoutHistoryState* aHistoryState)
    8827                 : {
    8828               0 :   if (aFrame && aHistoryState) {
    8829               0 :     CaptureFrameState(aFrame, aHistoryState);
    8830                 :   }
    8831               0 :   return NS_OK;
    8832                 : }
    8833                 : 
    8834                 : nsresult
    8835               0 : nsCSSFrameConstructor::MaybeRecreateFramesForElement(Element* aElement)
    8836                 : {
    8837               0 :   nsresult result = NS_OK;
    8838                 : 
    8839               0 :   nsStyleContext *oldContext = GetUndisplayedContent(aElement);
    8840               0 :   if (oldContext) {
    8841                 :     // The parent has a frame, so try resolving a new context.
    8842                 :     nsRefPtr<nsStyleContext> newContext = mPresShell->StyleSet()->
    8843               0 :       ResolveStyleFor(aElement, oldContext->GetParent());
    8844                 : 
    8845               0 :     ChangeUndisplayedContent(aElement, newContext);
    8846               0 :     if (newContext->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_NONE) {
    8847               0 :       result = RecreateFramesForContent(aElement, false);
    8848                 :     }
    8849                 :   }
    8850               0 :   return result;
    8851                 : }
    8852                 : 
    8853                 : static nsIFrame*
    8854               0 : FindFirstNonWhitespaceChild(nsIFrame* aParentFrame)
    8855                 : {
    8856               0 :   nsIFrame* f = aParentFrame->GetFirstPrincipalChild();
    8857               0 :   while (f && f->GetType() == nsGkAtoms::textFrame &&
    8858               0 :          f->GetContent()->TextIsOnlyWhitespace()) {
    8859               0 :     f = f->GetNextSibling();
    8860                 :   }
    8861               0 :   return f;
    8862                 : }
    8863                 : 
    8864                 : static nsIFrame*
    8865               0 : FindNextNonWhitespaceSibling(nsIFrame* aFrame)
    8866                 : {
    8867               0 :   nsIFrame* f = aFrame;
    8868               0 :   do {
    8869               0 :     f = f->GetNextSibling();
    8870               0 :   } while (f && f->GetType() == nsGkAtoms::textFrame &&
    8871               0 :            f->GetContent()->TextIsOnlyWhitespace());
    8872               0 :   return f;
    8873                 : }
    8874                 : 
    8875                 : bool
    8876               0 : nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
    8877                 :                                                              nsresult* aResult)
    8878                 : {
    8879               0 :   NS_PRECONDITION(aFrame, "Must have a frame");
    8880               0 :   NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root");
    8881               0 :   NS_PRECONDITION(aResult, "Null out param?");
    8882               0 :   NS_PRECONDITION(aFrame == aFrame->GetFirstContinuation(),
    8883                 :                   "aFrame not the result of GetPrimaryFrame()?");
    8884                 : 
    8885               0 :   if (IsFrameSpecial(aFrame)) {
    8886                 :     // The removal functions can't handle removal of an {ib} split directly; we
    8887                 :     // need to rebuild the containing block.
    8888                 : #ifdef DEBUG
    8889               0 :     if (gNoisyContentUpdates) {
    8890                 :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8891               0 :              "frame=");
    8892               0 :       nsFrame::ListTag(stdout, aFrame);
    8893               0 :       printf(" is special\n");
    8894                 :     }
    8895                 : #endif
    8896                 : 
    8897               0 :     *aResult = ReframeContainingBlock(aFrame);
    8898               0 :     return true;
    8899                 :   }
    8900                 : 
    8901               0 :   if (aFrame->GetType() == nsGkAtoms::legendFrame &&
    8902               0 :       aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) {
    8903                 :     // When we remove the legend for a fieldset, we should reframe
    8904                 :     // the fieldset to ensure another legend is used, if there is one
    8905               0 :     *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), false);
    8906               0 :     return true;
    8907                 :   }
    8908                 : 
    8909                 :   // Now check for possibly needing to reconstruct due to a pseudo parent
    8910                 :   nsIFrame* inFlowFrame =
    8911               0 :     (aFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) ?
    8912               0 :       GetPlaceholderFrameFor(aFrame) : aFrame;
    8913               0 :   NS_ASSERTION(inFlowFrame, "How did that happen?");
    8914               0 :   nsIFrame* parent = inFlowFrame->GetParent();
    8915               0 :   if (IsTablePseudo(parent)) {
    8916               0 :     if (FindFirstNonWhitespaceChild(parent) == inFlowFrame ||
    8917               0 :         !FindNextNonWhitespaceSibling(inFlowFrame->GetLastContinuation()) ||
    8918                 :         // If we're a table-column-group, then the GetFirstChild check above is
    8919                 :         // not going to catch cases when we're the first child.
    8920               0 :         (inFlowFrame->GetType() == nsGkAtoms::tableColGroupFrame &&
    8921               0 :          parent->GetFirstChild(nsIFrame::kColGroupList) == inFlowFrame) ||
    8922                 :         // Similar if we're a table-caption.
    8923               0 :         (inFlowFrame->GetType() == nsGkAtoms::tableCaptionFrame &&
    8924               0 :          parent->GetFirstChild(nsIFrame::kCaptionList) == inFlowFrame)) {
    8925                 :       // We're the first or last frame in the pseudo.  Need to reframe.
    8926                 :       // Good enough to recreate frames for |parent|'s content
    8927               0 :       *aResult = RecreateFramesForContent(parent->GetContent(), true);
    8928               0 :       return true;
    8929                 :     }
    8930                 :   }
    8931                 : 
    8932                 :   // Might need to reconstruct things if this frame's nextSibling is a table
    8933                 :   // pseudo, since removal of this frame might mean that this pseudo needs to
    8934                 :   // get merged with the frame's prevSibling.
    8935                 :   // XXXbz it would be really nice if we had the prevSibling here too, to check
    8936                 :   // whether this is in fact the case...
    8937                 :   nsIFrame* nextSibling =
    8938               0 :     FindNextNonWhitespaceSibling(inFlowFrame->GetLastContinuation());
    8939               0 :   NS_ASSERTION(!IsTablePseudo(inFlowFrame), "Shouldn't happen here");
    8940               0 :   if (nextSibling && IsTablePseudo(nextSibling)) {
    8941                 : #ifdef DEBUG
    8942               0 :     if (gNoisyContentUpdates) {
    8943                 :       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    8944               0 :              "frame=");
    8945               0 :       nsFrame::ListTag(stdout, aFrame);
    8946               0 :       printf(" has a table pseudo next sibling of different type\n");
    8947                 :     }
    8948                 : #endif
    8949                 :     // Good enough to recreate frames for aFrame's parent's content; even if
    8950                 :     // aFrame's parent is a table pseudo, that'll be the right content node.
    8951               0 :     *aResult = RecreateFramesForContent(parent->GetContent(), true);
    8952               0 :     return true;
    8953                 :   }
    8954                 : 
    8955                 : #ifdef MOZ_XUL
    8956               0 :   if (aFrame->GetType() == nsGkAtoms::popupSetFrame) {
    8957               0 :     nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
    8958               0 :     if (rootBox && rootBox->GetPopupSetFrame() == aFrame) {
    8959               0 :       *aResult = ReconstructDocElementHierarchy();
    8960               0 :       return true;
    8961                 :     }
    8962                 :   }
    8963                 : #endif
    8964                 : 
    8965                 :   // Reconstruct if inflowFrame is parent's only child, and parent is, or has,
    8966                 :   // a non-fluid continuation, i.e. it was split by bidi resolution
    8967               0 :   if (!inFlowFrame->GetPrevSibling() &&
    8968               0 :       !inFlowFrame->GetNextSibling() &&
    8969               0 :       (parent->GetPrevContinuation() && !parent->GetPrevInFlow() ||
    8970               0 :        parent->GetNextContinuation() && !parent->GetNextInFlow())) {
    8971               0 :     *aResult = RecreateFramesForContent(parent->GetContent(), true);
    8972               0 :     return true;
    8973                 :   }
    8974                 : 
    8975                 :   // We might still need to reconstruct things if the parent of inFlowFrame is
    8976                 :   // special, since in that case the removal of aFrame might affect the
    8977                 :   // splitting of its parent.
    8978               0 :   if (!IsFrameSpecial(parent)) {
    8979               0 :     return false;
    8980                 :   }
    8981                 : 
    8982                 :   // If inFlowFrame is not the only in-flow child of |parent|, then removing
    8983                 :   // it will change nothing about the {ib} split.
    8984               0 :   if (inFlowFrame != parent->GetFirstPrincipalChild() ||
    8985               0 :       inFlowFrame->GetLastContinuation()->GetNextSibling()) {
    8986               0 :     return false;
    8987                 :   }
    8988                 : 
    8989                 :   // If the parent is the first or last part of the {ib} split, then
    8990                 :   // removing one of its kids will have no effect on the splitting.
    8991                 :   // Get the first continuation up front so we don't have to do it twice.
    8992               0 :   nsIFrame* parentFirstContinuation = parent->GetFirstContinuation();
    8993               0 :   if (!GetSpecialSibling(parentFirstContinuation) ||
    8994               0 :       !GetSpecialPrevSibling(parentFirstContinuation)) {
    8995               0 :     return false;
    8996                 :   }
    8997                 : 
    8998                 : #ifdef DEBUG
    8999               0 :   if (gNoisyContentUpdates) {
    9000                 :     printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
    9001               0 :            "frame=");
    9002               0 :     nsFrame::ListTag(stdout, parent);
    9003               0 :     printf(" is special\n");
    9004                 :   }
    9005                 : #endif
    9006                 : 
    9007               0 :   *aResult = ReframeContainingBlock(parent);
    9008               0 :   return true;
    9009                 : }
    9010                 :  
    9011                 : nsresult
    9012               0 : nsCSSFrameConstructor::RecreateFramesForContent(nsIContent* aContent,
    9013                 :                                                 bool aAsyncInsert)
    9014                 : {
    9015               0 :   NS_PRECONDITION(!aAsyncInsert || aContent->IsElement(),
    9016                 :                   "Can only insert elements async");
    9017                 :   // If there is no document, we don't want to recreate frames for it.  (You
    9018                 :   // shouldn't generally be giving this method content without a document
    9019                 :   // anyway).
    9020                 :   // Rebuilding the frame tree can have bad effects, especially if it's the
    9021                 :   // frame tree for chrome (see bug 157322).
    9022               0 :   NS_ENSURE_TRUE(aContent->GetDocument(), NS_ERROR_FAILURE);
    9023                 : 
    9024                 :   // Is the frame `special'? If so, we need to reframe the containing
    9025                 :   // block *here*, rather than trying to remove and re-insert the
    9026                 :   // content (which would otherwise result in *two* nested reframe
    9027                 :   // containing block from ContentRemoved() and ContentInserted(),
    9028                 :   // below!).  We'd really like to optimize away one of those
    9029                 :   // containing block reframes, hence the code here.
    9030                 : 
    9031               0 :   nsIFrame* frame = aContent->GetPrimaryFrame();
    9032               0 :   if (frame && frame->IsFrameOfType(nsIFrame::eMathML)) {
    9033                 :     // Reframe the topmost MathML element to prevent exponential blowup
    9034                 :     // (see bug 397518)
    9035               0 :     while (true) {
    9036               0 :       nsIContent* parentContent = aContent->GetParent();
    9037               0 :       nsIFrame* parentContentFrame = parentContent->GetPrimaryFrame();
    9038               0 :       if (!parentContentFrame || !parentContentFrame->IsFrameOfType(nsIFrame::eMathML))
    9039                 :         break;
    9040               0 :       aContent = parentContent;
    9041               0 :       frame = parentContentFrame;
    9042                 :     }
    9043                 :   }
    9044                 : 
    9045               0 :   if (frame) {
    9046               0 :     nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(frame);
    9047               0 :     if (nonGeneratedAncestor->GetContent() != aContent) {
    9048               0 :       return RecreateFramesForContent(nonGeneratedAncestor->GetContent(), aAsyncInsert);
    9049                 :     }
    9050                 : 
    9051               0 :     nsIFrame* parent = frame->GetParent();
    9052               0 :     nsIContent* parentContent = parent ? parent->GetContent() : nsnull;
    9053                 :     // If the parent frame is a leaf then the subsequent insert will fail to
    9054                 :     // create a frame, so we need to recreate the parent content. This happens
    9055                 :     // with native anonymous content from the editor.
    9056               0 :     if (parent && parent->IsLeaf() && parentContent &&
    9057                 :         parentContent != aContent) {
    9058               0 :       return RecreateFramesForContent(parentContent, aAsyncInsert);
    9059                 :     }
    9060                 :   }
    9061                 : 
    9062               0 :   nsresult rv = NS_OK;
    9063                 : 
    9064               0 :   if (frame && MaybeRecreateContainerForFrameRemoval(frame, &rv)) {
    9065               0 :     return rv;
    9066                 :   }
    9067                 : 
    9068               0 :   nsINode* containerNode = aContent->GetNodeParent();
    9069                 :   // XXXbz how can containerNode be null here?
    9070               0 :   if (containerNode) {
    9071                 :     // Before removing the frames associated with the content object,
    9072                 :     // ask them to save their state onto a temporary state object.
    9073               0 :     CaptureStateForFramesOf(aContent, mTempFrameTreeState);
    9074                 : 
    9075                 :     // Need the nsIContent parent, which might be null here, since we need to
    9076                 :     // pass it to ContentInserted and ContentRemoved.
    9077               0 :     nsCOMPtr<nsIContent> container = aContent->GetParent();
    9078                 : 
    9079                 :     // Remove the frames associated with the content object.
    9080                 :     bool didReconstruct;
    9081                 :     rv = ContentRemoved(container, aContent,
    9082               0 :                         aContent->IsRootOfAnonymousSubtree() ?
    9083                 :                           nsnull :
    9084               0 :                           aContent->GetNextSibling(),
    9085               0 :                         REMOVE_FOR_RECONSTRUCTION, &didReconstruct);
    9086                 : 
    9087               0 :     if (NS_SUCCEEDED(rv) && !didReconstruct) {
    9088                 :       // Now, recreate the frames associated with this content object. If
    9089                 :       // ContentRemoved triggered reconstruction, then we don't need to do this
    9090                 :       // because the frames will already have been built.
    9091               0 :       if (aAsyncInsert) {
    9092                 :         PostRestyleEvent(aContent->AsElement(), nsRestyleHint(0),
    9093               0 :                          nsChangeHint_ReconstructFrame);
    9094                 :       } else {
    9095               0 :         rv = ContentInserted(container, aContent, mTempFrameTreeState, false);
    9096                 :       }
    9097                 :     }
    9098                 :   }
    9099                 : 
    9100               0 :   return rv;
    9101                 : }
    9102                 : 
    9103                 : //////////////////////////////////////////////////////////////////////
    9104                 : 
    9105                 : // Block frame construction code
    9106                 : 
    9107                 : already_AddRefed<nsStyleContext>
    9108               0 : nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
    9109                 :                                            nsStyleContext* aStyleContext)
    9110                 : {
    9111               0 :   if (aContent) {
    9112                 :     return mPresShell->StyleSet()->
    9113                 :       ResolvePseudoElementStyle(aContent->AsElement(),
    9114                 :                                 nsCSSPseudoElements::ePseudo_firstLetter,
    9115               0 :                                 aStyleContext);
    9116                 :   }
    9117               0 :   return nsnull;
    9118                 : }
    9119                 : 
    9120                 : already_AddRefed<nsStyleContext>
    9121               0 : nsCSSFrameConstructor::GetFirstLineStyle(nsIContent* aContent,
    9122                 :                                          nsStyleContext* aStyleContext)
    9123                 : {
    9124               0 :   if (aContent) {
    9125                 :     return mPresShell->StyleSet()->
    9126                 :       ResolvePseudoElementStyle(aContent->AsElement(),
    9127                 :                                 nsCSSPseudoElements::ePseudo_firstLine,
    9128               0 :                                 aStyleContext);
    9129                 :   }
    9130               0 :   return nsnull;
    9131                 : }
    9132                 : 
    9133                 : // Predicate to see if a given content (block element) has
    9134                 : // first-letter style applied to it.
    9135                 : bool
    9136               0 : nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(nsIContent* aContent,
    9137                 :                                                   nsStyleContext* aStyleContext)
    9138                 : {
    9139                 :   return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
    9140                 :                                        nsCSSPseudoElements::ePseudo_firstLetter,
    9141               0 :                                        mPresShell->GetPresContext());
    9142                 : }
    9143                 : 
    9144                 : bool
    9145               0 : nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame)
    9146                 : {
    9147               0 :   NS_PRECONDITION(aBlockFrame, "Need a frame");
    9148               0 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
    9149                 :                "Not a block frame?");
    9150                 : 
    9151               0 :   return (aBlockFrame->GetStateBits() & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0;
    9152                 : }
    9153                 : 
    9154                 : bool
    9155               0 : nsCSSFrameConstructor::ShouldHaveFirstLineStyle(nsIContent* aContent,
    9156                 :                                                 nsStyleContext* aStyleContext)
    9157                 : {
    9158                 :   bool hasFirstLine =
    9159                 :     nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
    9160                 :                                   nsCSSPseudoElements::ePseudo_firstLine,
    9161               0 :                                   mPresShell->GetPresContext());
    9162               0 :   if (hasFirstLine) {
    9163                 :     // But disable for fieldsets
    9164                 :     PRInt32 namespaceID;
    9165                 :     nsIAtom* tag = mDocument->BindingManager()->ResolveTag(aContent,
    9166               0 :                                                            &namespaceID);
    9167                 :     // This check must match the one in FindHTMLData.
    9168                 :     hasFirstLine = tag != nsGkAtoms::fieldset ||
    9169               0 :       namespaceID != kNameSpaceID_XHTML;
    9170                 :   }
    9171                 : 
    9172               0 :   return hasFirstLine;
    9173                 : }
    9174                 : 
    9175                 : void
    9176               0 : nsCSSFrameConstructor::ShouldHaveSpecialBlockStyle(nsIContent* aContent,
    9177                 :                                                    nsStyleContext* aStyleContext,
    9178                 :                                                    bool* aHaveFirstLetterStyle,
    9179                 :                                                    bool* aHaveFirstLineStyle)
    9180                 : {
    9181                 :   *aHaveFirstLetterStyle =
    9182               0 :     ShouldHaveFirstLetterStyle(aContent, aStyleContext);
    9183                 :   *aHaveFirstLineStyle =
    9184               0 :     ShouldHaveFirstLineStyle(aContent, aStyleContext);
    9185               0 : }
    9186                 : 
    9187                 : /* static */
    9188                 : const nsCSSFrameConstructor::PseudoParentData
    9189                 : nsCSSFrameConstructor::sPseudoParentData[eParentTypeCount] = {
    9190                 :   { // Cell
    9191                 :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9192                 :                      FCDATA_USE_CHILD_ITEMS |
    9193                 :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRow),
    9194                 :                      &nsCSSFrameConstructor::ConstructTableCell),
    9195                 :     &nsCSSAnonBoxes::tableCell
    9196                 :   },
    9197                 :   { // Row
    9198                 :     FULL_CTOR_FCDATA(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9199                 :                      FCDATA_USE_CHILD_ITEMS |
    9200                 :                      FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRowGroup),
    9201                 :                      &nsCSSFrameConstructor::ConstructTableRow),
    9202                 :     &nsCSSAnonBoxes::tableRow
    9203                 :   },
    9204                 :   { // Row group
    9205                 :     FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9206                 :                 FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
    9207                 :                 FCDATA_SKIP_ABSPOS_PUSH |
    9208                 :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    9209                 :                 NS_NewTableRowGroupFrame),
    9210                 :     &nsCSSAnonBoxes::tableRowGroup
    9211                 :   },
    9212                 :   { // Column group
    9213                 :     FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_SKIP_FRAMESET |
    9214                 :                 FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_USE_CHILD_ITEMS |
    9215                 :                 FCDATA_SKIP_ABSPOS_PUSH |
    9216                 :                 FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
    9217                 :                 NS_NewTableColGroupFrame),
    9218                 :     &nsCSSAnonBoxes::tableColGroup
    9219                 :   },
    9220                 :   { // Table
    9221                 :     FULL_CTOR_FCDATA(FCDATA_SKIP_FRAMESET | FCDATA_USE_CHILD_ITEMS,
    9222                 :                      &nsCSSFrameConstructor::ConstructTable),
    9223                 :     &nsCSSAnonBoxes::table
    9224                 :   }
    9225                 : };
    9226                 : 
    9227                 : /*
    9228                 :  * This function works as follows: we walk through the child list (aItems) and
    9229                 :  * find items that cannot have aParentFrame as their parent.  We wrap
    9230                 :  * continuous runs of such items into a FrameConstructionItem for a frame that
    9231                 :  * gets them closer to their desired parents.  For example, a run of non-row
    9232                 :  * children of a row-group will get wrapped in a row.  When we later construct
    9233                 :  * the frame for this wrapper (in this case for the row), it'll be the correct
    9234                 :  * parent for the cells in the set of items we wrapped or we'll wrap cells
    9235                 :  * around everything else.  At the end of this method, aItems is guaranteed to
    9236                 :  * contain only items for frames that can be direct kids of aParentFrame.
    9237                 :  */
    9238                 : nsresult
    9239               0 : nsCSSFrameConstructor::CreateNeededTablePseudos(nsFrameConstructorState& aState,
    9240                 :                                                 FrameConstructionItemList& aItems,
    9241                 :                                                 nsIFrame* aParentFrame)
    9242                 : {
    9243               0 :   ParentType ourParentType = GetParentType(aParentFrame);
    9244               0 :   if (aItems.AllWantParentType(ourParentType)) {
    9245                 :     // Nothing to do here
    9246               0 :     return NS_OK;
    9247                 :   }
    9248                 : 
    9249               0 :   FCItemIterator iter(aItems);
    9250               0 :   do {
    9251               0 :     if (iter.SkipItemsWantingParentType(ourParentType)) {
    9252                 :       // Nothing else to do here; we're finished
    9253               0 :       return NS_OK;
    9254                 :     }
    9255                 : 
    9256                 :     // Now we're pointing to the first child that wants a different parent
    9257                 :     // type.
    9258                 : 
    9259                 :     // Now try to figure out what kids we can group together.  We can generally
    9260                 :     // group everything that has a different desired parent type from us.  Two
    9261                 :     // exceptions to this:
    9262                 :     // 1) If our parent type is table, we can't group columns with anything
    9263                 :     //    else other than whitespace.
    9264                 :     // 2) Whitespace that lies between two things we can group which both want
    9265                 :     //    a non-block parent should be dropped, even if we can't group them
    9266                 :     //    with each other and even if the whitespace wants a parent of
    9267                 :     //    ourParentType.  Ends of the list count as things that don't want a
    9268                 :     //    block parent (so that for example we'll drop a whitespace-only list).
    9269                 : 
    9270               0 :     FCItemIterator endIter(iter); /* iterator to find the end of the group */
    9271               0 :     ParentType groupingParentType = endIter.item().DesiredParentType();
    9272               0 :     if (aItems.AllWantParentType(groupingParentType) &&
    9273                 :         groupingParentType != eTypeBlock) {
    9274                 :       // Just group them all and be done with it.  We need the check for
    9275                 :       // eTypeBlock here to catch the "all the items are whitespace" case
    9276                 :       // described above.
    9277               0 :       endIter.SetToEnd();
    9278                 :     } else {
    9279                 :       // Locate the end of the group.
    9280                 : 
    9281                 :       // Keep track of the type the previous item wanted, in case we have to
    9282                 :       // deal with whitespace.  Start it off with ourParentType, since that's
    9283                 :       // the last thing |iter| would have skipped over.
    9284               0 :       ParentType prevParentType = ourParentType;
    9285               0 :       do {
    9286                 :         /* Walk an iterator past any whitespace that we might be able to drop from the list */
    9287               0 :         FCItemIterator spaceEndIter(endIter);
    9288               0 :         if (prevParentType != eTypeBlock &&
    9289               0 :             !aParentFrame->IsGeneratedContentFrame() &&
    9290               0 :             spaceEndIter.item().IsWhitespace(aState)) {
    9291               0 :           bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
    9292                 : 
    9293                 :           // We drop the whitespace if these are not trailing spaces and the next item
    9294                 :           // does not want a block parent (see case 2 above)
    9295                 :           // if these are trailing spaces and aParentFrame is a tabular container
    9296                 :           // according to rule 1.3 of CSS 2.1 Sec 17.2.1. (Being a tabular container
    9297                 :           // pretty much means ourParentType != eTypeBlock besides the eTypeColGroup case,
    9298                 :           // which won't reach here.)
    9299               0 :           if ((trailingSpaces && ourParentType != eTypeBlock) ||
    9300               0 :               (!trailingSpaces && spaceEndIter.item().DesiredParentType() != 
    9301                 :                eTypeBlock)) {
    9302               0 :             bool updateStart = (iter == endIter);
    9303               0 :             endIter.DeleteItemsTo(spaceEndIter);
    9304               0 :             NS_ASSERTION(trailingSpaces == endIter.IsDone(), "These should match");
    9305                 : 
    9306               0 :             if (updateStart) {
    9307               0 :               iter = endIter;
    9308                 :             }
    9309                 : 
    9310               0 :             if (trailingSpaces) {
    9311               0 :               break; /* Found group end */
    9312                 :             }
    9313                 : 
    9314               0 :             if (updateStart) {
    9315                 :               // Update groupingParentType, since it might have been eTypeBlock
    9316                 :               // just because of the whitespace.
    9317               0 :               groupingParentType = iter.item().DesiredParentType();
    9318                 :             }
    9319                 :           }
    9320                 :         }
    9321                 : 
    9322                 :         // Now endIter points to a non-whitespace item or a non-droppable
    9323                 :         // whitespace item. In the latter case, if this is the end of the group
    9324                 :         // we'll traverse this whitespace again.  But it'll all just be quick
    9325                 :         // DesiredParentType() checks which will match ourParentType (that's
    9326                 :         // what it means that this is the group end), so it's OK.
    9327               0 :         prevParentType = endIter.item().DesiredParentType();
    9328               0 :         if (prevParentType == ourParentType) {
    9329                 :           // End the group at endIter.
    9330               0 :           break;
    9331                 :         }
    9332                 : 
    9333               0 :         if (ourParentType == eTypeTable &&
    9334                 :             (prevParentType == eTypeColGroup) !=
    9335                 :             (groupingParentType == eTypeColGroup)) {
    9336                 :           // Either we started with columns and now found something else, or vice
    9337                 :           // versa.  In any case, end the grouping.
    9338               0 :           break;
    9339                 :         }
    9340                 : 
    9341                 :         // Include the whitespace we didn't drop (if any) in the group, since
    9342                 :         // this is not the end of the group.  Note that this doesn't change
    9343                 :         // prevParentType, since if we didn't drop the whitespace then we ended
    9344                 :         // at something that wants a block parent.
    9345               0 :         endIter = spaceEndIter;
    9346                 : 
    9347               0 :         endIter.Next();
    9348               0 :       } while (!endIter.IsDone());
    9349                 :     }
    9350                 : 
    9351               0 :     if (iter == endIter) {
    9352                 :       // Nothing to wrap here; just skipped some whitespace
    9353               0 :       continue;
    9354                 :     }
    9355                 : 
    9356                 :     // Now group together all the items between iter and endIter.  The right
    9357                 :     // parent type to use depends on ourParentType.
    9358                 :     ParentType wrapperType;
    9359               0 :     switch (ourParentType) {
    9360                 :       case eTypeBlock:
    9361               0 :         wrapperType = eTypeTable;
    9362               0 :         break;
    9363                 :       case eTypeRow:
    9364                 :         // The parent type for a cell is eTypeBlock, since that's what a cell
    9365                 :         // looks like to its kids.
    9366               0 :         wrapperType = eTypeBlock;
    9367               0 :         break;
    9368                 :       case eTypeRowGroup:
    9369               0 :         wrapperType = eTypeRow;
    9370               0 :         break;
    9371                 :       case eTypeTable:
    9372                 :         // Either colgroup or rowgroup, depending on what we're grouping.
    9373                 :         wrapperType = groupingParentType == eTypeColGroup ?
    9374               0 :           eTypeColGroup : eTypeRowGroup;
    9375               0 :         break;
    9376                 :       default:
    9377               0 :         NS_NOTREACHED("Colgroups should be suppresing non-col child items");
    9378               0 :         break;
    9379                 :     }
    9380                 : 
    9381               0 :     const PseudoParentData& pseudoData = sPseudoParentData[wrapperType];
    9382               0 :     nsIAtom* pseudoType = *pseudoData.mPseudoType;
    9383               0 :     nsStyleContext* parentStyle = aParentFrame->GetStyleContext();
    9384               0 :     nsIContent* parentContent = aParentFrame->GetContent();
    9385                 : 
    9386               0 :     if (pseudoType == nsCSSAnonBoxes::table &&
    9387               0 :         parentStyle->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE) {
    9388               0 :       pseudoType = nsCSSAnonBoxes::inlineTable;
    9389                 :     }
    9390                 : 
    9391                 :     nsRefPtr<nsStyleContext> wrapperStyle =
    9392               0 :       mPresShell->StyleSet()->ResolveAnonymousBoxStyle(pseudoType, parentStyle);
    9393                 :     FrameConstructionItem* newItem =
    9394                 :       new FrameConstructionItem(&pseudoData.mFCData,
    9395                 :                                 // Use the content of our parent frame
    9396                 :                                 parentContent,
    9397                 :                                 // Lie about the tag; it doesn't matter anyway
    9398                 :                                 pseudoType,
    9399                 :                                 // The namespace does matter, however; it needs
    9400                 :                                 // to match that of our first child item to
    9401                 :                                 // match the old behavior
    9402               0 :                                 iter.item().mNameSpaceID,
    9403                 :                                 // no pending binding
    9404                 :                                 nsnull,
    9405                 :                                 wrapperStyle.forget(),
    9406               0 :                                 true);
    9407                 : 
    9408                 :     // Here we're cheating a tad... technically, table-internal items should be
    9409                 :     // inline if aParentFrame is inline, but they'll get wrapped in an
    9410                 :     // inline-table in the end, so it'll all work out.  In any case, arguably
    9411                 :     // we don't need to maintain this state at this point... but it's better
    9412                 :     // to, I guess.
    9413                 :     newItem->mIsAllInline = newItem->mHasInlineEnds =
    9414               0 :       newItem->mStyleContext->GetStyleDisplay()->IsInlineOutside();
    9415                 : 
    9416                 :     // Table pseudo frames always induce line boundaries around their
    9417                 :     // contents.
    9418               0 :     newItem->mChildItems.SetLineBoundaryAtStart(true);
    9419               0 :     newItem->mChildItems.SetLineBoundaryAtEnd(true);
    9420                 :     // The parent of the items in aItems is also the parent of the items
    9421                 :     // in mChildItems
    9422                 :     newItem->mChildItems.SetParentHasNoXBLChildren(
    9423               0 :       aItems.ParentHasNoXBLChildren());
    9424                 : 
    9425                 :     // Eat up all items between |iter| and |endIter| and put them in our wrapper
    9426                 :     // Advances |iter| to point to |endIter|.
    9427               0 :     iter.AppendItemsToList(endIter, newItem->mChildItems);
    9428                 : 
    9429               0 :     iter.InsertItem(newItem);
    9430                 : 
    9431                 :     // Now |iter| points to the item that was the first one we didn't wrap;
    9432                 :     // loop and see whether we need to skip it or wrap it in something
    9433                 :     // different.
    9434               0 :   } while (!iter.IsDone());
    9435                 : 
    9436               0 :   return NS_OK;
    9437                 : }
    9438                 : 
    9439                 : inline nsresult
    9440               0 : nsCSSFrameConstructor::ConstructFramesFromItemList(nsFrameConstructorState& aState,
    9441                 :                                                    FrameConstructionItemList& aItems,
    9442                 :                                                    nsIFrame* aParentFrame,
    9443                 :                                                    nsFrameItems& aFrameItems)
    9444                 : {
    9445               0 :   nsresult rv = CreateNeededTablePseudos(aState, aItems, aParentFrame);
    9446               0 :   NS_ENSURE_SUCCESS(rv, rv);
    9447                 : 
    9448                 : #ifdef DEBUG
    9449               0 :   for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
    9450               0 :     NS_ASSERTION(iter.item().DesiredParentType() == GetParentType(aParentFrame),
    9451                 :                  "Needed pseudos didn't get created; expect bad things");
    9452                 :   }
    9453                 : #endif
    9454                 : 
    9455               0 :   for (FCItemIterator iter(aItems); !iter.IsDone(); iter.Next()) {
    9456               0 :     rv = ConstructFramesFromItem(aState, iter, aParentFrame, aFrameItems);
    9457               0 :     NS_ENSURE_SUCCESS(rv, rv);
    9458                 :   }
    9459                 : 
    9460               0 :   NS_ASSERTION(!aState.mHavePendingPopupgroup,
    9461                 :                "Should have proccessed it by now");
    9462                 : 
    9463               0 :   return NS_OK;
    9464                 : }
    9465                 : 
    9466                 : nsresult
    9467               0 : nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
    9468                 :                                        nsIContent*              aContent,
    9469                 :                                        nsStyleContext*          aStyleContext,
    9470                 :                                        nsIFrame*                aFrame,
    9471                 :                                        const bool               aCanHaveGeneratedContent,
    9472                 :                                        nsFrameItems&            aFrameItems,
    9473                 :                                        const bool               aAllowBlockStyles,
    9474                 :                                        PendingBinding*          aPendingBinding,
    9475                 :                                        nsIFrame*                aPossiblyLeafFrame)
    9476                 : {
    9477               0 :   NS_PRECONDITION(aFrame, "Must have parent frame here");
    9478               0 :   NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
    9479                 :                   "Parent frame in ProcessChildren should be its own "
    9480                 :                   "content insertion frame");
    9481                 : 
    9482               0 :   if (!aPossiblyLeafFrame) {
    9483               0 :     aPossiblyLeafFrame = aFrame;
    9484                 :   }
    9485                 : 
    9486                 :   // XXXbz ideally, this would do all the pushing of various
    9487                 :   // containing blocks as needed, so callers don't have to do it...
    9488                 : 
    9489               0 :   bool haveFirstLetterStyle = false, haveFirstLineStyle = false;
    9490               0 :   if (aAllowBlockStyles) {
    9491                 :     ShouldHaveSpecialBlockStyle(aContent, aStyleContext, &haveFirstLetterStyle,
    9492               0 :                                 &haveFirstLineStyle);
    9493                 :   }
    9494                 : 
    9495                 :   // The logic here needs to match the logic in GetFloatContainingBlock()
    9496               0 :   nsFrameConstructorSaveState floatSaveState;
    9497               0 :   if (aFrame->IsFrameOfType(nsIFrame::eMathML) ||
    9498               0 :       aFrame->IsBoxFrame()) {
    9499               0 :     aState.PushFloatContainingBlock(nsnull, floatSaveState);
    9500               0 :   } else if (aFrame->IsFloatContainingBlock()) {
    9501               0 :     aState.PushFloatContainingBlock(aFrame, floatSaveState);
    9502                 :   }
    9503                 : 
    9504                 :   nsFrameConstructorState::PendingBindingAutoPusher pusher(aState,
    9505               0 :                                                            aPendingBinding);
    9506                 : 
    9507               0 :   FrameConstructionItemList itemsToConstruct;
    9508               0 :   nsresult rv = NS_OK;
    9509                 : 
    9510                 :   // If we have first-letter or first-line style then frames can get
    9511                 :   // moved around so don't set these flags.
    9512               0 :   if (aAllowBlockStyles && !haveFirstLetterStyle && !haveFirstLineStyle) {
    9513               0 :     itemsToConstruct.SetLineBoundaryAtStart(true);
    9514               0 :     itemsToConstruct.SetLineBoundaryAtEnd(true);
    9515                 :   }
    9516                 : 
    9517                 :   // Create any anonymous frames we need here.  This must happen before the
    9518                 :   // non-anonymous children are processed to ensure that popups are never
    9519                 :   // constructed before the popupset.
    9520               0 :   nsAutoTArray<nsIAnonymousContentCreator::ContentInfo, 4> anonymousItems;
    9521               0 :   GetAnonymousContent(aContent, aPossiblyLeafFrame, anonymousItems);
    9522               0 :   for (PRUint32 i = 0; i < anonymousItems.Length(); ++i) {
    9523               0 :     nsIContent* content = anonymousItems[i].mContent;
    9524                 : #ifdef DEBUG
    9525               0 :     nsIAnonymousContentCreator* creator = do_QueryFrame(aFrame);
    9526               0 :     NS_ASSERTION(!creator || !creator->CreateFrameFor(content),
    9527                 :                  "If you need to use CreateFrameFor, you need to call "
    9528                 :                  "CreateAnonymousFrames manually and not follow the standard "
    9529                 :                  "ProcessChildren() codepath for this frame");
    9530                 : #endif
    9531                 :     // Assert some things about this content
    9532               0 :     NS_ABORT_IF_FALSE(!(content->GetFlags() &
    9533                 :                         (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),
    9534                 :                       "Should not be marked as needing frames");
    9535               0 :     NS_ABORT_IF_FALSE(!content->IsElement() ||
    9536                 :                       !(content->GetFlags() & ELEMENT_ALL_RESTYLE_FLAGS),
    9537                 :                       "Should have no pending restyle flags");
    9538               0 :     NS_ABORT_IF_FALSE(!content->GetPrimaryFrame(),
    9539                 :                       "Should have no existing frame");
    9540               0 :     NS_ABORT_IF_FALSE(!content->IsNodeOfType(nsINode::eCOMMENT) &&
    9541                 :                       !content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION),
    9542                 :                       "Why is someone creating garbage anonymous content");
    9543                 : 
    9544               0 :     nsRefPtr<nsStyleContext> styleContext;
    9545               0 :     if (anonymousItems[i].mStyleContext) {
    9546               0 :       styleContext = anonymousItems[i].mStyleContext.forget();
    9547                 :     } else {
    9548               0 :       styleContext = ResolveStyleContext(aFrame, content, &aState);
    9549                 :     }
    9550                 : 
    9551                 :     AddFrameConstructionItemsInternal(aState, content, aFrame,
    9552                 :                                       content->Tag(), content->GetNameSpaceID(),
    9553                 :                                       true, styleContext,
    9554                 :                                       ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK,
    9555               0 :                                       itemsToConstruct);
    9556                 :   }
    9557                 : 
    9558               0 :   if (!aPossiblyLeafFrame->IsLeaf()) {
    9559                 :     // :before/:after content should have the same style context parent
    9560                 :     // as normal kids.
    9561                 :     // Note that we don't use this style context for looking up things like
    9562                 :     // special block styles because in some cases involving table pseudo-frames
    9563                 :     // it has nothing to do with the parent frame's desired behavior.
    9564                 :     nsStyleContext* styleContext;
    9565                 : 
    9566               0 :     if (aCanHaveGeneratedContent) {
    9567                 :       styleContext =
    9568               0 :         nsFrame::CorrectStyleParentFrame(aFrame, nsnull)->GetStyleContext();
    9569                 :       // Probe for generated content before
    9570                 :       CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
    9571                 :                                  nsCSSPseudoElements::ePseudo_before,
    9572               0 :                                  itemsToConstruct);
    9573                 :     }
    9574                 : 
    9575               0 :     ChildIterator iter, last;
    9576               0 :     for (ChildIterator::Init(aContent, &iter, &last);
    9577                 :          iter != last;
    9578                 :          ++iter) {
    9579               0 :       nsIContent* child = *iter;
    9580                 :       // Frame construction item construction should not post
    9581                 :       // restyles, so removing restyle flags here is safe.
    9582               0 :       if (child->IsElement()) {
    9583               0 :         child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
    9584                 :       }
    9585               0 :       AddFrameConstructionItems(aState, child, iter.XBLInvolved(), aFrame,
    9586               0 :                                 itemsToConstruct);
    9587                 :     }
    9588               0 :     itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
    9589                 : 
    9590               0 :     if (aCanHaveGeneratedContent) {
    9591                 :       // Probe for generated content after
    9592                 :       CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
    9593                 :                                  nsCSSPseudoElements::ePseudo_after,
    9594               0 :                                  itemsToConstruct);
    9595                 :     }
    9596                 :   } else {
    9597               0 :     ClearLazyBits(aContent->GetFirstChild(), nsnull);
    9598                 :   }
    9599                 : 
    9600                 :   rv = ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
    9601               0 :                                    aFrameItems);
    9602               0 :   NS_ENSURE_SUCCESS(rv, rv);
    9603                 : 
    9604               0 :   NS_ASSERTION(!aAllowBlockStyles || !aFrame->IsBoxFrame(),
    9605                 :                "can't be both block and box");
    9606                 : 
    9607               0 :   if (haveFirstLetterStyle) {
    9608               0 :     rv = WrapFramesInFirstLetterFrame(aContent, aFrame, aFrameItems);
    9609                 :   }
    9610               0 :   if (haveFirstLineStyle) {
    9611                 :     rv = WrapFramesInFirstLineFrame(aState, aContent, aFrame, nsnull,
    9612               0 :                                     aFrameItems);
    9613                 :   }
    9614                 : 
    9615                 :   // We might end up with first-line frames that change
    9616                 :   // AnyKidsNeedBlockParent() without changing itemsToConstruct, but that
    9617                 :   // should never happen for cases whan aFrame->IsBoxFrame().
    9618               0 :   NS_ASSERTION(!haveFirstLineStyle || !aFrame->IsBoxFrame(),
    9619                 :                "Shouldn't have first-line style if we're a box");
    9620               0 :   NS_ASSERTION(!aFrame->IsBoxFrame() ||
    9621                 :                itemsToConstruct.AnyItemsNeedBlockParent() ==
    9622                 :                  (AnyKidsNeedBlockParent(aFrameItems.FirstChild()) != nsnull),
    9623                 :                "Something went awry in our block parent calculations");
    9624                 : 
    9625               0 :   if (aFrame->IsBoxFrame() && itemsToConstruct.AnyItemsNeedBlockParent()) {
    9626                 :     // XXXbz we could do this on the FrameConstructionItemList level,
    9627                 :     // no?  And if we cared we could look through the item list
    9628                 :     // instead of groveling through the framelist here..
    9629               0 :     nsIContent *badKid = AnyKidsNeedBlockParent(aFrameItems.FirstChild());
    9630               0 :     nsDependentAtomString parentTag(aContent->Tag()), kidTag(badKid->Tag());
    9631               0 :     const PRUnichar* params[] = { parentTag.get(), kidTag.get() };
    9632               0 :     nsStyleContext *frameStyleContext = aFrame->GetStyleContext();
    9633               0 :     const nsStyleDisplay *display = frameStyleContext->GetStyleDisplay();
    9634                 :     const char *message =
    9635                 :       (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX)
    9636               0 :         ? "NeededToWrapXULInlineBox" : "NeededToWrapXUL";
    9637                 :     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    9638                 :                                     "FrameConstructor", mDocument,
    9639                 :                                     nsContentUtils::eXUL_PROPERTIES,
    9640                 :                                     message,
    9641               0 :                                     params, ArrayLength(params));
    9642                 : 
    9643                 :     nsRefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()->
    9644                 :       ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock,
    9645               0 :                                frameStyleContext);
    9646               0 :     nsIFrame *blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
    9647                 :     // We might, in theory, want to set NS_BLOCK_FLOAT_MGR and
    9648                 :     // NS_BLOCK_MARGIN_ROOT, but I think it's a bad idea given that
    9649                 :     // a real block placed here wouldn't get those set on it.
    9650                 : 
    9651                 :     InitAndRestoreFrame(aState, aContent, aFrame, nsnull,
    9652               0 :                         blockFrame, false);
    9653                 : 
    9654               0 :     NS_ASSERTION(!blockFrame->HasView(), "need to do view reparenting");
    9655               0 :     ReparentFrames(this, blockFrame, aFrameItems);
    9656                 : 
    9657               0 :     blockFrame->SetInitialChildList(kPrincipalList, aFrameItems);
    9658               0 :     NS_ASSERTION(aFrameItems.IsEmpty(), "How did that happen?");
    9659               0 :     aFrameItems.Clear();
    9660               0 :     aFrameItems.AddChild(blockFrame);
    9661                 : 
    9662               0 :     aFrame->AddStateBits(NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK);
    9663                 :   }
    9664                 : 
    9665               0 :   return rv;
    9666                 : }
    9667                 : 
    9668                 : //----------------------------------------------------------------------
    9669                 : 
    9670                 : // Support for :first-line style
    9671                 : 
    9672                 : // Special routine to handle placing a list of frames into a block
    9673                 : // frame that has first-line style. The routine ensures that the first
    9674                 : // collection of inline frames end up in a first-line frame.
    9675                 : // NOTE: aState may have containing block information related to a
    9676                 : // different part of the frame tree than where the first line occurs.
    9677                 : // In particular aState may be set up for where ContentInserted or
    9678                 : // ContentAppended is inserting content, which may be some
    9679                 : // non-first-in-flow continuation of the block to which the first-line
    9680                 : // belongs. So this function needs to be careful about how it uses
    9681                 : // aState.
    9682                 : nsresult
    9683               0 : nsCSSFrameConstructor::WrapFramesInFirstLineFrame(
    9684                 :   nsFrameConstructorState& aState,
    9685                 :   nsIContent*              aBlockContent,
    9686                 :   nsIFrame*                aBlockFrame,
    9687                 :   nsIFrame*                aLineFrame,
    9688                 :   nsFrameItems&            aFrameItems)
    9689                 : {
    9690               0 :   nsresult rv = NS_OK;
    9691                 : 
    9692                 :   // Find the part of aFrameItems that we want to put in the first-line
    9693               0 :   nsFrameList::FrameLinkEnumerator link(aFrameItems);
    9694               0 :   while (!link.AtEnd() && IsInlineOutside(link.NextFrame())) {
    9695               0 :     link.Next();
    9696                 :   }
    9697                 : 
    9698               0 :   nsFrameList firstLineChildren = aFrameItems.ExtractHead(link);
    9699                 : 
    9700               0 :   if (firstLineChildren.IsEmpty()) {
    9701                 :     // Nothing is supposed to go into the first-line; nothing to do
    9702               0 :     return NS_OK;
    9703                 :   }
    9704                 : 
    9705               0 :   if (!aLineFrame) {
    9706                 :     // Create line frame
    9707                 :     nsStyleContext* parentStyle =
    9708                 :       nsFrame::CorrectStyleParentFrame(aBlockFrame,
    9709                 :                                        nsCSSPseudoElements::firstLine)->
    9710               0 :         GetStyleContext();
    9711                 :     nsRefPtr<nsStyleContext> firstLineStyle = GetFirstLineStyle(aBlockContent,
    9712               0 :                                                                 parentStyle);
    9713                 : 
    9714               0 :     aLineFrame = NS_NewFirstLineFrame(mPresShell, firstLineStyle);
    9715                 : 
    9716               0 :     if (aLineFrame) {
    9717                 :       // Initialize the line frame
    9718                 :       rv = InitAndRestoreFrame(aState, aBlockContent, aBlockFrame, nsnull,
    9719               0 :                                aLineFrame);
    9720                 : 
    9721                 :       // The lineFrame will be the block's first child; the rest of the
    9722                 :       // frame list (after lastInlineFrame) will be the second and
    9723                 :       // subsequent children; insert lineFrame into aFrameItems.
    9724               0 :       aFrameItems.InsertFrame(nsnull, nsnull, aLineFrame);
    9725                 : 
    9726               0 :       NS_ASSERTION(aLineFrame->GetStyleContext() == firstLineStyle,
    9727                 :                    "Bogus style context on line frame");
    9728                 :     }
    9729                 :   }
    9730                 : 
    9731               0 :   if (aLineFrame) {
    9732                 :     // Give the inline frames to the lineFrame <b>after</b> reparenting them
    9733               0 :     ReparentFrames(this, aLineFrame, firstLineChildren);
    9734               0 :     if (aLineFrame->PrincipalChildList().IsEmpty() &&
    9735               0 :         (aLineFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    9736               0 :       aLineFrame->SetInitialChildList(kPrincipalList, firstLineChildren);
    9737                 :     } else {
    9738               0 :       AppendFrames(aLineFrame, kPrincipalList, firstLineChildren);
    9739                 :     }
    9740                 :   }
    9741                 :   else {
    9742               0 :     rv = NS_ERROR_OUT_OF_MEMORY;
    9743                 :   }
    9744                 : 
    9745               0 :   return rv;
    9746                 : }
    9747                 : 
    9748                 : // Special routine to handle appending a new frame to a block frame's
    9749                 : // child list. Takes care of placing the new frame into the right
    9750                 : // place when first-line style is present.
    9751                 : nsresult
    9752               0 : nsCSSFrameConstructor::AppendFirstLineFrames(
    9753                 :   nsFrameConstructorState& aState,
    9754                 :   nsIContent*              aBlockContent,
    9755                 :   nsIFrame*                aBlockFrame,
    9756                 :   nsFrameItems&            aFrameItems)
    9757                 : {
    9758                 :   // It's possible that aBlockFrame needs to have a first-line frame
    9759                 :   // created because it doesn't currently have any children.
    9760               0 :   const nsFrameList& blockKids = aBlockFrame->PrincipalChildList();
    9761               0 :   if (blockKids.IsEmpty()) {
    9762                 :     return WrapFramesInFirstLineFrame(aState, aBlockContent,
    9763               0 :                                       aBlockFrame, nsnull, aFrameItems);
    9764                 :   }
    9765                 : 
    9766                 :   // Examine the last block child - if it's a first-line frame then
    9767                 :   // appended frames need special treatment.
    9768               0 :   nsIFrame* lastBlockKid = blockKids.LastChild();
    9769               0 :   if (lastBlockKid->GetType() != nsGkAtoms::lineFrame) {
    9770                 :     // No first-line frame at the end of the list, therefore there is
    9771                 :     // an intervening block between any first-line frame the frames
    9772                 :     // we are appending. Therefore, we don't need any special
    9773                 :     // treatment of the appended frames.
    9774               0 :     return NS_OK;
    9775                 :   }
    9776                 : 
    9777                 :   return WrapFramesInFirstLineFrame(aState, aBlockContent, aBlockFrame,
    9778               0 :                                     lastBlockKid, aFrameItems);
    9779                 : }
    9780                 : 
    9781                 : // Special routine to handle inserting a new frame into a block
    9782                 : // frame's child list. Takes care of placing the new frame into the
    9783                 : // right place when first-line style is present.
    9784                 : nsresult
    9785               0 : nsCSSFrameConstructor::InsertFirstLineFrames(
    9786                 :   nsFrameConstructorState& aState,
    9787                 :   nsIContent*              aContent,
    9788                 :   nsIFrame*                aBlockFrame,
    9789                 :   nsIFrame**               aParentFrame,
    9790                 :   nsIFrame*                aPrevSibling,
    9791                 :   nsFrameItems&            aFrameItems)
    9792                 : {
    9793               0 :   nsresult rv = NS_OK;
    9794                 :   // XXXbz If you make this method actually do something, check to
    9795                 :   // make sure that the caller is passing what you expect.  In
    9796                 :   // particular, which content is aContent?  And audit the rest of
    9797                 :   // this code too; it makes bogus assumptions and may not build.
    9798                 : #if 0
    9799                 :   nsIFrame* parentFrame = *aParentFrame;
    9800                 :   nsIFrame* newFrame = aFrameItems.childList;
    9801                 :   bool isInline = IsInlineOutside(newFrame);
    9802                 : 
    9803                 :   if (!aPrevSibling) {
    9804                 :     // Insertion will become the first frame. Two cases: we either
    9805                 :     // already have a first-line frame or we don't.
    9806                 :     nsIFrame* firstBlockKid = aBlockFrame->GetFirstPrincipalChild();
    9807                 :     if (firstBlockKid->GetType() == nsGkAtoms::lineFrame) {
    9808                 :       // We already have a first-line frame
    9809                 :       nsIFrame* lineFrame = firstBlockKid;
    9810                 : 
    9811                 :       if (isInline) {
    9812                 :         // Easy case: the new inline frame will go into the lineFrame.
    9813                 :         ReparentFrame(this, lineFrame, newFrame);
    9814                 :         InsertFrames(lineFrame, kPrincipalList, nsnull, newFrame);
    9815                 : 
    9816                 :         // Since the frame is going into the lineFrame, don't let it
    9817                 :         // go into the block too.
    9818                 :         aFrameItems.childList = nsnull;
    9819                 :         aFrameItems.lastChild = nsnull;
    9820                 :       }
    9821                 :       else {
    9822                 :         // Harder case: We are about to insert a block level element
    9823                 :         // before the first-line frame.
    9824                 :         // XXX need a method to steal away frames from the line-frame
    9825                 :       }
    9826                 :     }
    9827                 :     else {
    9828                 :       // We do not have a first-line frame
    9829                 :       if (isInline) {
    9830                 :         // We now need a first-line frame to contain the inline frame.
    9831                 :         nsIFrame* lineFrame = NS_NewFirstLineFrame(firstLineStyle);
    9832                 :         if (!lineFrame) {
    9833                 :           rv = NS_ERROR_OUT_OF_MEMORY;
    9834                 :         }
    9835                 : 
    9836                 :         if (NS_SUCCEEDED(rv)) {
    9837                 :           // Lookup first-line style context
    9838                 :           nsStyleContext* parentStyle =
    9839                 :             nsFrame::CorrectStyleParentFrame(aBlockFrame,
    9840                 :                                              nsCSSPseudoElements::firstLine)->
    9841                 :               GetStyleContext();
    9842                 :           nsRefPtr<nsStyleContext> firstLineStyle =
    9843                 :             GetFirstLineStyle(aContent, parentStyle);
    9844                 : 
    9845                 :           // Initialize the line frame
    9846                 :           rv = InitAndRestoreFrame(aState, aContent, aBlockFrame,
    9847                 :                                    nsnull, lineFrame);
    9848                 : 
    9849                 :           // Make sure the caller inserts the lineFrame into the
    9850                 :           // blocks list of children.
    9851                 :           aFrameItems.childList = lineFrame;
    9852                 :           aFrameItems.lastChild = lineFrame;
    9853                 : 
    9854                 :           // Give the inline frames to the lineFrame <b>after</b>
    9855                 :           // reparenting them
    9856                 :           NS_ASSERTION(lineFrame->GetStyleContext() == firstLineStyle,
    9857                 :                        "Bogus style context on line frame");
    9858                 :           ReparentFrame(aPresContext, lineFrame, newFrame);
    9859                 :           lineFrame->SetInitialChildList(kPrincipalList, newFrame);
    9860                 :         }
    9861                 :       }
    9862                 :       else {
    9863                 :         // Easy case: the regular insertion logic can insert the new
    9864                 :         // frame because it's a block frame.
    9865                 :       }
    9866                 :     }
    9867                 :   }
    9868                 :   else {
    9869                 :     // Insertion will not be the first frame.
    9870                 :     nsIFrame* prevSiblingParent = aPrevSibling->GetParent();
    9871                 :     if (prevSiblingParent == aBlockFrame) {
    9872                 :       // Easy case: The prev-siblings parent is the block
    9873                 :       // frame. Therefore the prev-sibling is not currently in a
    9874                 :       // line-frame. Therefore the new frame which is going after it,
    9875                 :       // regardless of type, is not going into a line-frame.
    9876                 :     }
    9877                 :     else {
    9878                 :       // If the prevSiblingParent is not the block-frame then it must
    9879                 :       // be a line-frame (if it were a letter-frame, that logic would
    9880                 :       // already have adjusted the prev-sibling to be the
    9881                 :       // letter-frame).
    9882                 :       if (isInline) {
    9883                 :         // Easy case: the insertion can go where the caller thinks it
    9884                 :         // should go (which is into prevSiblingParent).
    9885                 :       }
    9886                 :       else {
    9887                 :         // Block elements don't end up in line-frames, therefore
    9888                 :         // change the insertion point to aBlockFrame. However, there
    9889                 :         // might be more inline elements following aPrevSibling that
    9890                 :         // need to be pulled out of the line-frame and become children
    9891                 :         // of the block.
    9892                 :         nsIFrame* nextSibling = aPrevSibling->GetNextSibling();
    9893                 :         nsIFrame* nextLineFrame = prevSiblingParent->GetNextInFlow();
    9894                 :         if (nextSibling || nextLineFrame) {
    9895                 :           // Oy. We have work to do. Create a list of the new frames
    9896                 :           // that are going into the block by stripping them away from
    9897                 :           // the line-frame(s).
    9898                 :           if (nextSibling) {
    9899                 :             nsLineFrame* lineFrame = (nsLineFrame*) prevSiblingParent;
    9900                 :             nsFrameList tail = lineFrame->StealFramesAfter(aPrevSibling);
    9901                 :             // XXX do something with 'tail'
    9902                 :           }
    9903                 : 
    9904                 :           nsLineFrame* nextLineFrame = (nsLineFrame*) lineFrame;
    9905                 :           for (;;) {
    9906                 :             nextLineFrame = nextLineFrame->GetNextInFlow();
    9907                 :             if (!nextLineFrame) {
    9908                 :               break;
    9909                 :             }
    9910                 :             nsIFrame* kids = nextLineFrame->GetFirstPrincipalChild();
    9911                 :           }
    9912                 :         }
    9913                 :         else {
    9914                 :           // We got lucky: aPrevSibling was the last inline frame in
    9915                 :           // the line-frame.
    9916                 :           ReparentFrame(this, aBlockFrame, newFrame);
    9917                 :           InsertFrames(aBlockFrame, kPrincipalList,
    9918                 :                        prevSiblingParent, newFrame);
    9919                 :           aFrameItems.childList = nsnull;
    9920                 :           aFrameItems.lastChild = nsnull;
    9921                 :         }
    9922                 :       }
    9923                 :     }
    9924                 :   }
    9925                 : 
    9926                 : #endif
    9927               0 :   return rv;
    9928                 : }
    9929                 : 
    9930                 : //----------------------------------------------------------------------
    9931                 : 
    9932                 : // First-letter support
    9933                 : 
    9934                 : // Determine how many characters in the text fragment apply to the
    9935                 : // first letter
    9936                 : static PRInt32
    9937               0 : FirstLetterCount(const nsTextFragment* aFragment)
    9938                 : {
    9939               0 :   PRInt32 count = 0;
    9940               0 :   PRInt32 firstLetterLength = 0;
    9941                 : 
    9942               0 :   PRInt32 i, n = aFragment->GetLength();
    9943               0 :   for (i = 0; i < n; i++) {
    9944               0 :     PRUnichar ch = aFragment->CharAt(i);
    9945               0 :     if (XP_IS_SPACE(ch)) {
    9946               0 :       if (firstLetterLength) {
    9947               0 :         break;
    9948                 :       }
    9949               0 :       count++;
    9950               0 :       continue;
    9951                 :     }
    9952                 :     // XXX I18n
    9953               0 :     if ((ch == '\'') || (ch == '\"')) {
    9954               0 :       if (firstLetterLength) {
    9955               0 :         break;
    9956                 :       }
    9957                 :       // keep looping
    9958               0 :       firstLetterLength = 1;
    9959                 :     }
    9960                 :     else {
    9961               0 :       count++;
    9962               0 :       break;
    9963                 :     }
    9964                 :   }
    9965                 : 
    9966               0 :   return count;
    9967                 : }
    9968                 : 
    9969                 : static bool
    9970               0 : NeedFirstLetterContinuation(nsIContent* aContent)
    9971                 : {
    9972               0 :   NS_PRECONDITION(aContent, "null ptr");
    9973                 : 
    9974               0 :   bool result = false;
    9975               0 :   if (aContent) {
    9976               0 :     const nsTextFragment* frag = aContent->GetText();
    9977               0 :     if (frag) {
    9978               0 :       PRInt32 flc = FirstLetterCount(frag);
    9979               0 :       PRInt32 tl = frag->GetLength();
    9980               0 :       if (flc < tl) {
    9981               0 :         result = true;
    9982                 :       }
    9983                 :     }
    9984                 :   }
    9985               0 :   return result;
    9986                 : }
    9987                 : 
    9988               0 : static bool IsFirstLetterContent(nsIContent* aContent)
    9989                 : {
    9990               0 :   return aContent->TextLength() &&
    9991               0 :          !aContent->TextIsOnlyWhitespace();
    9992                 : }
    9993                 : 
    9994                 : /**
    9995                 :  * Create a letter frame, only make it a floating frame.
    9996                 :  */
    9997                 : void
    9998               0 : nsCSSFrameConstructor::CreateFloatingLetterFrame(
    9999                 :   nsFrameConstructorState& aState,
   10000                 :   nsIFrame* aBlockFrame,
   10001                 :   nsIContent* aTextContent,
   10002                 :   nsIFrame* aTextFrame,
   10003                 :   nsIContent* aBlockContent,
   10004                 :   nsIFrame* aParentFrame,
   10005                 :   nsStyleContext* aStyleContext,
   10006                 :   nsFrameItems& aResult)
   10007                 : {
   10008                 :   // Create the first-letter-frame
   10009                 :   nsresult rv;
   10010                 :   nsIFrame* letterFrame;
   10011               0 :   nsStyleSet *styleSet = mPresShell->StyleSet();
   10012                 : 
   10013               0 :   letterFrame = NS_NewFirstLetterFrame(mPresShell, aStyleContext);
   10014                 :   // We don't want to use a text content for a non-text frame (because we want
   10015                 :   // its primary frame to be a text frame).  So use its parent for the
   10016                 :   // first-letter.
   10017               0 :   nsIContent* letterContent = aTextContent->GetParent();
   10018                 :   nsIFrame* containingBlock = aState.GetGeometricParent(
   10019               0 :     aStyleContext->GetStyleDisplay(), aParentFrame);
   10020                 :   InitAndRestoreFrame(aState, letterContent, containingBlock, nsnull,
   10021               0 :                       letterFrame);
   10022                 : 
   10023                 :   // Init the text frame to refer to the letter frame. Make sure we
   10024                 :   // get a proper style context for it (the one passed in is for the
   10025                 :   // letter frame and will have the float property set on it; the text
   10026                 :   // frame shouldn't have that set).
   10027               0 :   nsRefPtr<nsStyleContext> textSC;
   10028               0 :   textSC = styleSet->ResolveStyleForNonElement(aStyleContext);
   10029               0 :   aTextFrame->SetStyleContextWithoutNotification(textSC);
   10030               0 :   InitAndRestoreFrame(aState, aTextContent, letterFrame, nsnull, aTextFrame);
   10031                 : 
   10032                 :   // And then give the text frame to the letter frame
   10033               0 :   SetInitialSingleChild(letterFrame, aTextFrame);
   10034                 : 
   10035                 :   // See if we will need to continue the text frame (does it contain
   10036                 :   // more than just the first-letter text or not?) If it does, then we
   10037                 :   // create (in advance) a continuation frame for it.
   10038               0 :   nsIFrame* nextTextFrame = nsnull;
   10039               0 :   if (NeedFirstLetterContinuation(aTextContent)) {
   10040                 :     // Create continuation
   10041                 :     rv = CreateContinuingFrame(aState.mPresContext, aTextFrame, aParentFrame,
   10042               0 :                                &nextTextFrame);
   10043               0 :     if (NS_FAILED(rv)) {
   10044               0 :       letterFrame->Destroy();
   10045                 :       return;
   10046                 :     }
   10047                 :     // Repair the continuations style context
   10048               0 :     nsStyleContext* parentStyleContext = aStyleContext->GetParent();
   10049               0 :     if (parentStyleContext) {
   10050               0 :       nsRefPtr<nsStyleContext> newSC;
   10051               0 :       newSC = styleSet->ResolveStyleForNonElement(parentStyleContext);
   10052               0 :       if (newSC) {
   10053               0 :         nextTextFrame->SetStyleContext(newSC);
   10054                 :       }
   10055                 :     }
   10056                 :   }
   10057                 : 
   10058               0 :   NS_ASSERTION(aResult.IsEmpty(), "aResult should be an empty nsFrameItems!");
   10059                 :   // Put the new float before any of the floats in the block we're doing
   10060                 :   // first-letter for, that is, before any floats whose parent is
   10061                 :   // containingBlock.
   10062               0 :   nsFrameList::FrameLinkEnumerator link(aState.mFloatedItems);
   10063               0 :   while (!link.AtEnd() && link.NextFrame()->GetParent() != containingBlock) {
   10064               0 :     link.Next();
   10065                 :   }
   10066                 : 
   10067                 :   rv = aState.AddChild(letterFrame, aResult, letterContent, aStyleContext,
   10068                 :                        aParentFrame, false, true, false, true,
   10069               0 :                        link.PrevFrame());
   10070                 : 
   10071               0 :   if (nextTextFrame) {
   10072               0 :     if (NS_FAILED(rv)) {
   10073               0 :       nextTextFrame->Destroy();
   10074                 :     } else {
   10075               0 :       aResult.AddChild(nextTextFrame);
   10076                 :     }
   10077                 :   }
   10078                 : }
   10079                 : 
   10080                 : /**
   10081                 :  * Create a new letter frame for aTextFrame. The letter frame will be
   10082                 :  * a child of aParentFrame.
   10083                 :  */
   10084                 : nsresult
   10085               0 : nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
   10086                 :                                          nsIFrame* aBlockContinuation,
   10087                 :                                          nsIContent* aTextContent,
   10088                 :                                          nsIFrame* aParentFrame,
   10089                 :                                          nsFrameItems& aResult)
   10090                 : {
   10091               0 :   NS_PRECONDITION(aTextContent->IsNodeOfType(nsINode::eTEXT),
   10092                 :                   "aTextContent isn't text");
   10093               0 :   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
   10094                 :                  "Not a block frame?");
   10095                 : 
   10096                 :   // Get style context for the first-letter-frame
   10097                 :   nsStyleContext* parentStyleContext =
   10098                 :     nsFrame::CorrectStyleParentFrame(aParentFrame,
   10099                 :                                      nsCSSPseudoElements::firstLetter)->
   10100               0 :       GetStyleContext();
   10101                 : 
   10102                 :   // Use content from containing block so that we can actually
   10103                 :   // find a matching style rule.
   10104               0 :   nsIContent* blockContent = aBlockFrame->GetContent();
   10105                 : 
   10106                 :   // Create first-letter style rule
   10107                 :   nsRefPtr<nsStyleContext> sc = GetFirstLetterStyle(blockContent,
   10108               0 :                                                     parentStyleContext);
   10109               0 :   if (sc) {
   10110               0 :     nsRefPtr<nsStyleContext> textSC;
   10111               0 :     textSC = mPresShell->StyleSet()->ResolveStyleForNonElement(sc);
   10112                 :     
   10113                 :     // Create a new text frame (the original one will be discarded)
   10114                 :     // pass a temporary stylecontext, the correct one will be set
   10115                 :     // later.  Start off by unsetting the primary frame for
   10116                 :     // aTextContent, so it's no longer pointing to the to-be-destroyed
   10117                 :     // frame.
   10118                 :     // XXXbz it would be really nice to destroy the old frame _first_,
   10119                 :     // then create the new one, so we could avoid this hack.
   10120               0 :     aTextContent->SetPrimaryFrame(nsnull);
   10121               0 :     nsIFrame* textFrame = NS_NewTextFrame(mPresShell, textSC);
   10122                 : 
   10123               0 :     NS_ASSERTION(aBlockContinuation == GetFloatContainingBlock(aParentFrame),
   10124                 :                  "Containing block is confused");
   10125                 :     nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
   10126                 :                                   GetAbsoluteContainingBlock(aParentFrame),
   10127               0 :                                   aBlockContinuation);
   10128                 : 
   10129                 :     // Create the right type of first-letter frame
   10130               0 :     const nsStyleDisplay* display = sc->GetStyleDisplay();
   10131               0 :     if (display->IsFloating()) {
   10132                 :       // Make a floating first-letter frame
   10133                 :       CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
   10134               0 :                                 blockContent, aParentFrame, sc, aResult);
   10135                 :     }
   10136                 :     else {
   10137                 :       // Make an inflow first-letter frame
   10138               0 :       nsIFrame* letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
   10139                 : 
   10140               0 :       if (letterFrame) {
   10141                 :         // Initialize the first-letter-frame.  We don't want to use a text
   10142                 :         // content for a non-text frame (because we want its primary frame to
   10143                 :         // be a text frame).  So use its parent for the first-letter.
   10144               0 :         nsIContent* letterContent = aTextContent->GetParent();
   10145               0 :         letterFrame->Init(letterContent, aParentFrame, nsnull);
   10146                 : 
   10147                 :         InitAndRestoreFrame(state, aTextContent, letterFrame, nsnull,
   10148               0 :                             textFrame);
   10149                 : 
   10150               0 :         SetInitialSingleChild(letterFrame, textFrame);
   10151               0 :         aResult.Clear();
   10152               0 :         aResult.AddChild(letterFrame);
   10153               0 :         NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   10154                 :                      "should have the first continuation here");
   10155               0 :         aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   10156                 :       }
   10157                 :     }
   10158               0 :     aTextContent->SetPrimaryFrame(textFrame);
   10159                 :   }
   10160                 : 
   10161               0 :   return NS_OK;
   10162                 : }
   10163                 : 
   10164                 : nsresult
   10165               0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   10166                 :   nsIContent*              aBlockContent,
   10167                 :   nsIFrame*                aBlockFrame,
   10168                 :   nsFrameItems&            aBlockFrames)
   10169                 : {
   10170               0 :   nsresult rv = NS_OK;
   10171                 : 
   10172               0 :   aBlockFrame->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   10173                 : 
   10174               0 :   nsIFrame* parentFrame = nsnull;
   10175               0 :   nsIFrame* textFrame = nsnull;
   10176               0 :   nsIFrame* prevFrame = nsnull;
   10177               0 :   nsFrameItems letterFrames;
   10178               0 :   bool stopLooking = false;
   10179                 :   rv = WrapFramesInFirstLetterFrame(aBlockFrame, aBlockFrame, aBlockFrame,
   10180                 :                                     aBlockFrames.FirstChild(),
   10181                 :                                     &parentFrame, &textFrame, &prevFrame,
   10182               0 :                                     letterFrames, &stopLooking);
   10183               0 :   if (NS_FAILED(rv)) {
   10184               0 :     return rv;
   10185                 :   }
   10186               0 :   if (parentFrame) {
   10187               0 :     if (parentFrame == aBlockFrame) {
   10188                 :       // Take textFrame out of the block's frame list and substitute the
   10189                 :       // letter frame(s) instead.
   10190               0 :       aBlockFrames.DestroyFrame(textFrame);
   10191               0 :       aBlockFrames.InsertFrames(nsnull, prevFrame, letterFrames);
   10192                 :     }
   10193                 :     else {
   10194                 :       // Take the old textFrame out of the inline parent's child list
   10195               0 :       RemoveFrame(kPrincipalList, textFrame);
   10196                 : 
   10197                 :       // Insert in the letter frame(s)
   10198               0 :       parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   10199                 :     }
   10200                 :   }
   10201                 : 
   10202               0 :   return rv;
   10203                 : }
   10204                 : 
   10205                 : nsresult
   10206               0 : nsCSSFrameConstructor::WrapFramesInFirstLetterFrame(
   10207                 :   nsIFrame*                aBlockFrame,
   10208                 :   nsIFrame*                aBlockContinuation,
   10209                 :   nsIFrame*                aParentFrame,
   10210                 :   nsIFrame*                aParentFrameList,
   10211                 :   nsIFrame**               aModifiedParent,
   10212                 :   nsIFrame**               aTextFrame,
   10213                 :   nsIFrame**               aPrevFrame,
   10214                 :   nsFrameItems&            aLetterFrames,
   10215                 :   bool*                  aStopLooking)
   10216                 : {
   10217               0 :   nsresult rv = NS_OK;
   10218                 : 
   10219               0 :   nsIFrame* prevFrame = nsnull;
   10220               0 :   nsIFrame* frame = aParentFrameList;
   10221                 : 
   10222               0 :   while (frame) {
   10223               0 :     nsIFrame* nextFrame = frame->GetNextSibling();
   10224                 : 
   10225               0 :     nsIAtom* frameType = frame->GetType();
   10226               0 :     if (nsGkAtoms::textFrame == frameType) {
   10227                 :       // Wrap up first-letter content in a letter frame
   10228               0 :       nsIContent* textContent = frame->GetContent();
   10229               0 :       if (IsFirstLetterContent(textContent)) {
   10230                 :         // Create letter frame to wrap up the text
   10231                 :         rv = CreateLetterFrame(aBlockFrame, aBlockContinuation, textContent,
   10232               0 :                                aParentFrame, aLetterFrames);
   10233               0 :         if (NS_FAILED(rv)) {
   10234               0 :           return rv;
   10235                 :         }
   10236                 : 
   10237                 :         // Provide adjustment information for parent
   10238               0 :         *aModifiedParent = aParentFrame;
   10239               0 :         *aTextFrame = frame;
   10240               0 :         *aPrevFrame = prevFrame;
   10241               0 :         *aStopLooking = true;
   10242               0 :         return NS_OK;
   10243                 :       }
   10244                 :     }
   10245               0 :     else if (IsInlineFrame(frame) && frameType != nsGkAtoms::brFrame) {
   10246               0 :       nsIFrame* kids = frame->GetFirstPrincipalChild();
   10247                 :       WrapFramesInFirstLetterFrame(aBlockFrame, aBlockContinuation, frame,
   10248                 :                                    kids, aModifiedParent, aTextFrame,
   10249               0 :                                    aPrevFrame, aLetterFrames, aStopLooking);
   10250               0 :       if (*aStopLooking) {
   10251               0 :         return NS_OK;
   10252                 :       }
   10253                 :     }
   10254                 :     else {
   10255                 :       // This will stop us looking to create more letter frames. For
   10256                 :       // example, maybe the frame-type is "letterFrame" or
   10257                 :       // "placeholderFrame". This keeps us from creating extra letter
   10258                 :       // frames, and also prevents us from creating letter frames when
   10259                 :       // the first real content child of a block is not text (e.g. an
   10260                 :       // image, hr, etc.)
   10261               0 :       *aStopLooking = true;
   10262               0 :       break;
   10263                 :     }
   10264                 : 
   10265               0 :     prevFrame = frame;
   10266               0 :     frame = nextFrame;
   10267                 :   }
   10268                 : 
   10269               0 :   return rv;
   10270                 : }
   10271                 : 
   10272                 : nsresult
   10273               0 : nsCSSFrameConstructor::RemoveFloatingFirstLetterFrames(
   10274                 :   nsPresContext* aPresContext,
   10275                 :   nsIPresShell* aPresShell,
   10276                 :   nsIFrame* aBlockFrame,
   10277                 :   bool* aStopLooking)
   10278                 : {
   10279                 :   // First look for the float frame that is a letter frame
   10280               0 :   nsIFrame* floatFrame = aBlockFrame->GetFirstChild(nsIFrame::kFloatList);
   10281               0 :   while (floatFrame) {
   10282                 :     // See if we found a floating letter frame
   10283               0 :     if (nsGkAtoms::letterFrame == floatFrame->GetType()) {
   10284               0 :       break;
   10285                 :     }
   10286               0 :     floatFrame = floatFrame->GetNextSibling();
   10287                 :   }
   10288               0 :   if (!floatFrame) {
   10289                 :     // No such frame
   10290               0 :     return NS_OK;
   10291                 :   }
   10292                 : 
   10293                 :   // Take the text frame away from the letter frame (so it isn't
   10294                 :   // destroyed when we destroy the letter frame).
   10295               0 :   nsIFrame* textFrame = floatFrame->GetFirstPrincipalChild();
   10296               0 :   if (!textFrame) {
   10297               0 :     return NS_OK;
   10298                 :   }
   10299                 : 
   10300                 :   // Discover the placeholder frame for the letter frame
   10301                 :   nsIFrame* parentFrame;
   10302               0 :   nsPlaceholderFrame* placeholderFrame = GetPlaceholderFrameFor(floatFrame);
   10303                 : 
   10304               0 :   if (!placeholderFrame) {
   10305                 :     // Somethings really wrong
   10306               0 :     return NS_OK;
   10307                 :   }
   10308               0 :   parentFrame = placeholderFrame->GetParent();
   10309               0 :   if (!parentFrame) {
   10310                 :     // Somethings really wrong
   10311               0 :     return NS_OK;
   10312                 :   }
   10313                 : 
   10314                 :   // Create a new text frame with the right style context that maps
   10315                 :   // all of the content that was previously part of the letter frame
   10316                 :   // (and probably continued elsewhere).
   10317               0 :   nsStyleContext* parentSC = parentFrame->GetStyleContext();
   10318               0 :   if (!parentSC) {
   10319               0 :     return NS_OK;
   10320                 :   }
   10321               0 :   nsIContent* textContent = textFrame->GetContent();
   10322               0 :   if (!textContent) {
   10323               0 :     return NS_OK;
   10324                 :   }
   10325               0 :   nsRefPtr<nsStyleContext> newSC;
   10326               0 :   newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
   10327               0 :   if (!newSC) {
   10328               0 :     return NS_OK;
   10329                 :   }
   10330               0 :   nsIFrame* newTextFrame = NS_NewTextFrame(aPresShell, newSC);
   10331               0 :   if (NS_UNLIKELY(!newTextFrame)) {
   10332               0 :     return NS_ERROR_OUT_OF_MEMORY;;
   10333                 :   }
   10334               0 :   newTextFrame->Init(textContent, parentFrame, nsnull);
   10335                 : 
   10336                 :   // Destroy the old text frame's continuations (the old text frame
   10337                 :   // will be destroyed when its letter frame is destroyed).
   10338               0 :   nsIFrame* frameToDelete = textFrame->GetLastContinuation();
   10339               0 :   while (frameToDelete != textFrame) {
   10340               0 :     nsIFrame* nextFrameToDelete = frameToDelete->GetPrevContinuation();
   10341               0 :     RemoveFrame(kPrincipalList, frameToDelete);
   10342               0 :     frameToDelete = nextFrameToDelete;
   10343                 :   }
   10344                 : 
   10345               0 :   nsIFrame* prevSibling = placeholderFrame->GetPrevSibling();
   10346                 : 
   10347                 :   // Now that everything is set...
   10348                 : #ifdef NOISY_FIRST_LETTER
   10349                 :   printf("RemoveFloatingFirstLetterFrames: textContent=%p oldTextFrame=%p newTextFrame=%p\n",
   10350                 :          textContent.get(), textFrame, newTextFrame);
   10351                 : #endif
   10352                 : 
   10353                 :   // Remove placeholder frame and the float
   10354               0 :   RemoveFrame(kPrincipalList, placeholderFrame);
   10355                 : 
   10356                 :   // Now that the old frames are gone, we can start pointing to our
   10357                 :   // new primary frame.
   10358               0 :   textContent->SetPrimaryFrame(newTextFrame);
   10359                 : 
   10360                 :   // Insert text frame in its place
   10361               0 :   nsFrameList textList(newTextFrame, newTextFrame);
   10362               0 :   InsertFrames(parentFrame, kPrincipalList, prevSibling, textList);
   10363                 : 
   10364               0 :   return NS_OK;
   10365                 : }
   10366                 : 
   10367                 : nsresult
   10368               0 : nsCSSFrameConstructor::RemoveFirstLetterFrames(nsPresContext* aPresContext,
   10369                 :                                                nsIPresShell* aPresShell,
   10370                 :                                                nsIFrame* aFrame,
   10371                 :                                                nsIFrame* aBlockFrame,
   10372                 :                                                bool* aStopLooking)
   10373                 : {
   10374               0 :   nsIFrame* prevSibling = nsnull;
   10375               0 :   nsIFrame* kid = aFrame->GetFirstPrincipalChild();
   10376                 : 
   10377               0 :   while (kid) {
   10378               0 :     if (nsGkAtoms::letterFrame == kid->GetType()) {
   10379                 :       // Bingo. Found it. First steal away the text frame.
   10380               0 :       nsIFrame* textFrame = kid->GetFirstPrincipalChild();
   10381               0 :       if (!textFrame) {
   10382               0 :         break;
   10383                 :       }
   10384                 : 
   10385                 :       // Create a new textframe
   10386               0 :       nsStyleContext* parentSC = aFrame->GetStyleContext();
   10387               0 :       if (!parentSC) {
   10388               0 :         break;
   10389                 :       }
   10390               0 :       nsIContent* textContent = textFrame->GetContent();
   10391               0 :       if (!textContent) {
   10392               0 :         break;
   10393                 :       }
   10394               0 :       nsRefPtr<nsStyleContext> newSC;
   10395               0 :       newSC = aPresShell->StyleSet()->ResolveStyleForNonElement(parentSC);
   10396               0 :       if (!newSC) {
   10397                 :         break;
   10398                 :       }
   10399               0 :       textFrame = NS_NewTextFrame(aPresShell, newSC);
   10400               0 :       textFrame->Init(textContent, aFrame, nsnull);
   10401                 : 
   10402                 :       // Next rip out the kid and replace it with the text frame
   10403               0 :       RemoveFrame(kPrincipalList, kid);
   10404                 : 
   10405                 :       // Now that the old frames are gone, we can start pointing to our
   10406                 :       // new primary frame.
   10407               0 :       textContent->SetPrimaryFrame(textFrame);
   10408                 : 
   10409                 :       // Insert text frame in its place
   10410               0 :       nsFrameList textList(textFrame, textFrame);
   10411               0 :       InsertFrames(aFrame, kPrincipalList, prevSibling, textList);
   10412                 : 
   10413               0 :       *aStopLooking = true;
   10414               0 :       NS_ASSERTION(!aBlockFrame->GetPrevContinuation(),
   10415                 :                    "should have the first continuation here");
   10416               0 :       aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_CHILD);
   10417                 :       break;
   10418                 :     }
   10419               0 :     else if (IsInlineFrame(kid)) {
   10420                 :       // Look inside child inline frame for the letter frame
   10421                 :       RemoveFirstLetterFrames(aPresContext, aPresShell,
   10422               0 :                               kid, aBlockFrame, aStopLooking);
   10423               0 :       if (*aStopLooking) {
   10424               0 :         break;
   10425                 :       }
   10426                 :     }
   10427               0 :     prevSibling = kid;
   10428               0 :     kid = kid->GetNextSibling();
   10429                 :   }
   10430                 : 
   10431               0 :   return NS_OK;
   10432                 : }
   10433                 : 
   10434                 : nsresult
   10435               0 : nsCSSFrameConstructor::RemoveLetterFrames(nsPresContext* aPresContext,
   10436                 :                                           nsIPresShell* aPresShell,
   10437                 :                                           nsIFrame* aBlockFrame)
   10438                 : {
   10439               0 :   aBlockFrame = aBlockFrame->GetFirstContinuation();
   10440               0 :   nsIFrame* continuation = aBlockFrame;
   10441                 : 
   10442               0 :   bool stopLooking = false;
   10443                 :   nsresult rv;
   10444               0 :   do {
   10445                 :     rv = RemoveFloatingFirstLetterFrames(aPresContext, aPresShell,
   10446               0 :                                          continuation, &stopLooking);
   10447               0 :     if (NS_SUCCEEDED(rv) && !stopLooking) {
   10448                 :       rv = RemoveFirstLetterFrames(aPresContext, aPresShell,
   10449               0 :                                    continuation, aBlockFrame, &stopLooking);
   10450                 :     }
   10451               0 :     if (stopLooking) {
   10452               0 :       break;
   10453                 :     }
   10454               0 :     continuation = continuation->GetNextContinuation();
   10455                 :   }  while (continuation);
   10456               0 :   return rv;
   10457                 : }
   10458                 : 
   10459                 : // Fixup the letter frame situation for the given block
   10460                 : nsresult
   10461               0 : nsCSSFrameConstructor::RecoverLetterFrames(nsIFrame* aBlockFrame)
   10462                 : {
   10463               0 :   aBlockFrame = aBlockFrame->GetFirstContinuation();
   10464               0 :   nsIFrame* continuation = aBlockFrame;
   10465                 : 
   10466               0 :   nsIFrame* parentFrame = nsnull;
   10467               0 :   nsIFrame* textFrame = nsnull;
   10468               0 :   nsIFrame* prevFrame = nsnull;
   10469               0 :   nsFrameItems letterFrames;
   10470               0 :   bool stopLooking = false;
   10471                 :   nsresult rv;
   10472               0 :   do {
   10473                 :     // XXX shouldn't this bit be set already (bug 408493), assert instead?
   10474               0 :     continuation->AddStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);
   10475                 :     rv = WrapFramesInFirstLetterFrame(aBlockFrame, continuation, continuation,
   10476                 :                                       continuation->GetFirstPrincipalChild(),
   10477                 :                                       &parentFrame, &textFrame, &prevFrame,
   10478               0 :                                       letterFrames, &stopLooking);
   10479               0 :     if (NS_FAILED(rv)) {
   10480               0 :       return rv;
   10481                 :     }
   10482               0 :     if (stopLooking) {
   10483               0 :       break;
   10484                 :     }
   10485               0 :     continuation = continuation->GetNextContinuation();
   10486                 :   } while (continuation);
   10487                 : 
   10488               0 :   if (parentFrame) {
   10489                 :     // Take the old textFrame out of the parents child list
   10490               0 :     RemoveFrame(kPrincipalList, textFrame);
   10491                 : 
   10492                 :     // Insert in the letter frame(s)
   10493               0 :     parentFrame->InsertFrames(kPrincipalList, prevFrame, letterFrames);
   10494                 :   }
   10495               0 :   return rv;
   10496                 : }
   10497                 : 
   10498                 : //----------------------------------------------------------------------
   10499                 : 
   10500                 : // listbox Widget Routines
   10501                 : 
   10502                 : nsresult
   10503               0 : nsCSSFrameConstructor::CreateListBoxContent(nsPresContext* aPresContext,
   10504                 :                                             nsIFrame*       aParentFrame,
   10505                 :                                             nsIFrame*       aPrevFrame,
   10506                 :                                             nsIContent*     aChild,
   10507                 :                                             nsIFrame**      aNewFrame,
   10508                 :                                             bool            aIsAppend,
   10509                 :                                             bool            aIsScrollbar,
   10510                 :                                             nsILayoutHistoryState* aFrameState)
   10511                 : {
   10512                 : #ifdef MOZ_XUL
   10513               0 :   nsresult rv = NS_OK;
   10514                 : 
   10515                 :   // Construct a new frame
   10516               0 :   if (nsnull != aParentFrame) {
   10517               0 :     nsFrameItems            frameItems;
   10518                 :     nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
   10519                 :                                   GetAbsoluteContainingBlock(aParentFrame),
   10520                 :                                   GetFloatContainingBlock(aParentFrame), 
   10521               0 :                                   mTempFrameTreeState);
   10522                 : 
   10523                 :     // If we ever initialize the ancestor filter on |state|, make sure
   10524                 :     // to push the right parent!
   10525                 : 
   10526               0 :     nsRefPtr<nsStyleContext> styleContext;
   10527               0 :     styleContext = ResolveStyleContext(aParentFrame, aChild, &state);
   10528                 : 
   10529                 :     // Pre-check for display "none" - only if we find that, do we create
   10530                 :     // any frame at all
   10531               0 :     const nsStyleDisplay* display = styleContext->GetStyleDisplay();
   10532                 : 
   10533               0 :     if (NS_STYLE_DISPLAY_NONE == display->mDisplay) {
   10534               0 :       *aNewFrame = nsnull;
   10535               0 :       return NS_OK;
   10536                 :     }
   10537                 : 
   10538               0 :     BeginUpdate();
   10539                 : 
   10540               0 :     FrameConstructionItemList items;
   10541                 :     AddFrameConstructionItemsInternal(state, aChild, aParentFrame,
   10542                 :                                       aChild->Tag(), aChild->GetNameSpaceID(),
   10543                 :                                       true, styleContext,
   10544               0 :                                       ITEM_ALLOW_XBL_BASE, items);
   10545               0 :     ConstructFramesFromItemList(state, items, aParentFrame, frameItems);
   10546                 : 
   10547               0 :     nsIFrame* newFrame = frameItems.FirstChild();
   10548               0 :     *aNewFrame = newFrame;
   10549                 : 
   10550               0 :     if (newFrame) {
   10551                 :       // Notify the parent frame
   10552               0 :       if (aIsAppend)
   10553               0 :         rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxAppendFrames(frameItems);
   10554                 :       else
   10555               0 :         rv = ((nsListBoxBodyFrame*)aParentFrame)->ListBoxInsertFrames(aPrevFrame, frameItems);
   10556                 :     }
   10557                 : 
   10558               0 :     EndUpdate();
   10559                 : 
   10560                 : #ifdef ACCESSIBILITY
   10561               0 :     if (newFrame) {
   10562               0 :       nsAccessibilityService* accService = nsIPresShell::AccService();
   10563               0 :       if (accService) {
   10564                 :         accService->ContentRangeInserted(mPresShell, aChild->GetParent(),
   10565               0 :                                          aChild, aChild->GetNextSibling());
   10566                 :       }
   10567                 :     }
   10568                 : #endif
   10569                 :   }
   10570                 : 
   10571               0 :   return rv;
   10572                 : #else
   10573                 :   return NS_ERROR_FAILURE;
   10574                 : #endif
   10575                 : }
   10576                 : 
   10577                 : //----------------------------------------
   10578                 : 
   10579                 : nsresult
   10580               0 : nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState,
   10581                 :                                       const nsStyleDisplay*    aDisplay,
   10582                 :                                       nsIContent*              aContent,
   10583                 :                                       nsIFrame*                aParentFrame,
   10584                 :                                       nsIFrame*                aContentParentFrame,
   10585                 :                                       nsStyleContext*          aStyleContext,
   10586                 :                                       nsIFrame**               aNewFrame,
   10587                 :                                       nsFrameItems&            aFrameItems,
   10588                 :                                       bool                     aAbsPosContainer,
   10589                 :                                       PendingBinding*          aPendingBinding)
   10590                 : {
   10591                 :   // Create column wrapper if necessary
   10592               0 :   nsIFrame* blockFrame = *aNewFrame;
   10593               0 :   NS_ASSERTION(blockFrame->GetType() == nsGkAtoms::blockFrame, "not a block frame?");
   10594               0 :   nsIFrame* parent = aParentFrame;
   10595               0 :   nsRefPtr<nsStyleContext> blockStyle = aStyleContext;
   10596               0 :   const nsStyleColumn* columns = aStyleContext->GetStyleColumn();
   10597                 : 
   10598               0 :   if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO
   10599               0 :       || columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
   10600               0 :     nsIFrame* columnSetFrame = nsnull;
   10601               0 :     columnSetFrame = NS_NewColumnSetFrame(mPresShell, aStyleContext, 0);
   10602               0 :     if (!columnSetFrame) {
   10603               0 :       return NS_ERROR_OUT_OF_MEMORY;
   10604                 :     }
   10605                 : 
   10606               0 :     InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, columnSetFrame);
   10607                 :     blockStyle = mPresShell->StyleSet()->
   10608               0 :       ResolveAnonymousBoxStyle(nsCSSAnonBoxes::columnContent, aStyleContext);
   10609               0 :     parent = columnSetFrame;
   10610               0 :     *aNewFrame = columnSetFrame;
   10611                 : 
   10612               0 :     SetInitialSingleChild(columnSetFrame, blockFrame);
   10613                 :   }
   10614                 : 
   10615               0 :   blockFrame->SetStyleContextWithoutNotification(blockStyle);
   10616               0 :   InitAndRestoreFrame(aState, aContent, parent, nsnull, blockFrame);
   10617                 : 
   10618                 :   nsresult rv = aState.AddChild(*aNewFrame, aFrameItems, aContent,
   10619                 :                                 aStyleContext,
   10620                 :                                 aContentParentFrame ? aContentParentFrame :
   10621               0 :                                                       aParentFrame);
   10622               0 :   if (NS_FAILED(rv)) {
   10623               0 :     return rv;
   10624                 :   }
   10625                 : 
   10626               0 :   if (!mRootElementFrame) {
   10627                 :     // The frame we're constructing will be the root element frame.
   10628                 :     // Set mRootElementFrame before processing children.
   10629               0 :     mRootElementFrame = *aNewFrame;
   10630                 :   }
   10631                 : 
   10632                 :   // We should make the outer frame be the absolute containing block,
   10633                 :   // if one is required. We have to do this because absolute
   10634                 :   // positioning must be computed with respect to the CSS dimensions
   10635                 :   // of the element, which are the dimensions of the outer block. But
   10636                 :   // we can't really do that because only blocks can have absolute
   10637                 :   // children. So use the block and try to compensate with hacks
   10638                 :   // in nsBlockFrame::CalculateContainingBlockSizeForAbsolutes.
   10639               0 :   nsFrameConstructorSaveState absoluteSaveState;
   10640               0 :   if (aAbsPosContainer) {
   10641                 :     //    NS_ASSERTION(aRelPos, "should have made area frame for this");
   10642               0 :     aState.PushAbsoluteContainingBlock(*aNewFrame, absoluteSaveState);
   10643                 :   }
   10644                 : 
   10645                 :   // Process the child content
   10646               0 :   nsFrameItems childItems;
   10647                 :   rv = ProcessChildren(aState, aContent, aStyleContext, blockFrame, true,
   10648               0 :                        childItems, true, aPendingBinding);
   10649                 : 
   10650                 :   // Set the frame's initial child list
   10651               0 :   blockFrame->SetInitialChildList(kPrincipalList, childItems);
   10652                 : 
   10653               0 :   return rv;
   10654                 : }
   10655                 : 
   10656                 : nsresult
   10657               0 : nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState,
   10658                 :                                        FrameConstructionItem&   aItem,
   10659                 :                                        nsIFrame*                aParentFrame,
   10660                 :                                        const nsStyleDisplay*    aDisplay,
   10661                 :                                        nsFrameItems&            aFrameItems,
   10662                 :                                        nsIFrame**               aNewFrame)
   10663                 : {
   10664                 :   // If an inline frame has non-inline kids, then we chop up the child list
   10665                 :   // into runs of blocks and runs of inlines, create anonymous block frames to
   10666                 :   // contain the runs of blocks, inline frames with our style context for the
   10667                 :   // runs of inlines, and put all these frames, in order, into aFrameItems.  We
   10668                 :   // put the first one into *aNewFrame.  The whole setup is called an {ib}
   10669                 :   // split; in what follows "frames in the split" refers to the anonymous blocks
   10670                 :   // and inlines that contain our children.
   10671                 :   //
   10672                 :   // {ib} splits maintain the following invariants:
   10673                 :   // 1) All frames in the split have the NS_FRAME_IS_SPECIAL bit set.
   10674                 :   // 2) Each frame in the split has the nsIFrame::IBSplitSpecialSibling
   10675                 :   //    property pointing to the next frame in the split, except for the last
   10676                 :   //    one, which does not have it set.
   10677                 :   // 3) Each frame in the split has the nsIFrame::IBSplitSpecialPrevSibling
   10678                 :   //    property pointing to the previous frame in the split, except for the
   10679                 :   //    first one, which does not have it set.
   10680                 :   // 4) The first and last frame in the split are always inlines.
   10681                 :   //
   10682                 :   // An invariant that is NOT maintained is that the wrappers are actually
   10683                 :   // linked via GetNextSibling linkage.  A simple example is an inline
   10684                 :   // containing an inline that contains a block.  The three parts of the inner
   10685                 :   // inline end up with three different parents.
   10686                 :   //
   10687                 :   // For example, this HTML:
   10688                 :   // <span>
   10689                 :   //   <div>a</div>
   10690                 :   //   <span>
   10691                 :   //     b
   10692                 :   //     <div>c</div>
   10693                 :   //   </span>
   10694                 :   //   d
   10695                 :   //   <div>e</div>
   10696                 :   //   f
   10697                 :   //  </span>
   10698                 :   // Gives the following frame tree:
   10699                 :   //
   10700                 :   // Inline (outer span)
   10701                 :   // Block (anonymous, outer span)
   10702                 :   //   Block (div)
   10703                 :   //     Text("a")
   10704                 :   // Inline (outer span)
   10705                 :   //   Inline (inner span)
   10706                 :   //     Text("b")
   10707                 :   // Block (anonymous, outer span)
   10708                 :   //   Block (anonymous, inner span)
   10709                 :   //     Block (div)
   10710                 :   //       Text("c")
   10711                 :   // Inline (outer span)
   10712                 :   //   Inline (inner span)
   10713                 :   //   Text("d")
   10714                 :   // Block (anonymous, outer span)
   10715                 :   //   Block (div)
   10716                 :   //     Text("e")
   10717                 :   // Inline (outer span)
   10718                 :   //   Text("f")
   10719                 : 
   10720               0 :   nsIContent* const content = aItem.mContent;
   10721               0 :   nsStyleContext* const styleContext = aItem.mStyleContext;
   10722                 : 
   10723                 :   nsIFrame *newFrame;
   10724                 : 
   10725                 :   bool positioned =
   10726                 :     NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay &&
   10727                 :     (NS_STYLE_POSITION_RELATIVE == aDisplay->mPosition ||
   10728               0 :      aDisplay->HasTransform());
   10729               0 :   newFrame = NS_NewInlineFrame(mPresShell, styleContext);
   10730                 : 
   10731                 :   // Initialize the frame
   10732               0 :   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
   10733                 : 
   10734               0 :   nsFrameConstructorSaveState absoluteSaveState;  // definition cannot be inside next block
   10735                 :                                                   // because the object's destructor is significant
   10736                 :                                                   // this is part of the fix for bug 42372
   10737                 : 
   10738               0 :   if (positioned) {
   10739                 :     // Relatively positioned frames becomes a container for child
   10740                 :     // frames that are positioned
   10741               0 :     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   10742                 :   }
   10743                 : 
   10744                 :   // Process the child content
   10745               0 :   nsFrameItems childItems;
   10746                 :   nsresult rv = ConstructFramesFromItemList(aState, aItem.mChildItems, newFrame,
   10747               0 :                                             childItems);
   10748               0 :   if (NS_FAILED(rv)) {
   10749                 :     // Clean up?
   10750               0 :     return rv;
   10751                 :   }
   10752                 : 
   10753               0 :   nsFrameList::FrameLinkEnumerator firstBlockEnumerator(childItems);
   10754               0 :   if (!aItem.mIsAllInline) {
   10755               0 :     FindFirstBlock(firstBlockEnumerator);
   10756                 :   }
   10757                 : 
   10758               0 :   if (aItem.mIsAllInline || firstBlockEnumerator.AtEnd()) { 
   10759                 :     // This part is easy.  We either already know we have no non-inline kids,
   10760                 :     // or haven't found any when constructing actual frames (the latter can
   10761                 :     // happen only if out-of-flows that we thought had no containing block
   10762                 :     // acquired one when ancestor inline frames and {ib} splits got
   10763                 :     // constructed).  Just put all the kids into the single inline frame and
   10764                 :     // bail.
   10765               0 :     newFrame->SetInitialChildList(kPrincipalList, childItems);
   10766               0 :     if (NS_SUCCEEDED(rv)) {
   10767               0 :       aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame);
   10768               0 :       *aNewFrame = newFrame;
   10769                 :     }
   10770               0 :     return rv;
   10771                 :   }
   10772                 : 
   10773                 :   // This inline frame contains several types of children. Therefore this frame
   10774                 :   // has to be chopped into several pieces, as described above.
   10775                 : 
   10776                 :   // Grab the first inline's kids
   10777               0 :   nsFrameList firstInlineKids = childItems.ExtractHead(firstBlockEnumerator);
   10778               0 :   newFrame->SetInitialChildList(kPrincipalList, firstInlineKids);
   10779                 : 
   10780               0 :   aFrameItems.AddChild(newFrame);
   10781                 : 
   10782               0 :   CreateIBSiblings(aState, newFrame, positioned, childItems, aFrameItems);
   10783                 : 
   10784               0 :   *aNewFrame = newFrame;
   10785               0 :   return NS_OK;
   10786                 : }
   10787                 : 
   10788                 : void
   10789               0 : nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState,
   10790                 :                                         nsIFrame* aInitialInline,
   10791                 :                                         bool aIsPositioned,
   10792                 :                                         nsFrameItems& aChildItems,
   10793                 :                                         nsFrameItems& aSiblings)
   10794                 : {
   10795               0 :   nsIContent* content = aInitialInline->GetContent();
   10796               0 :   nsStyleContext* styleContext = aInitialInline->GetStyleContext();
   10797               0 :   nsIFrame* parentFrame = aInitialInline->GetParent();
   10798                 : 
   10799                 :   // Resolve the right style context for our anonymous blocks.
   10800                 :   // The distinction in styles is needed because of CSS 2.1, section
   10801                 :   // 9.2.1.1, which says:
   10802                 :   //   When such an inline box is affected by relative positioning, any
   10803                 :   //   resulting translation also affects the block-level box contained
   10804                 :   //   in the inline box.
   10805                 :   nsRefPtr<nsStyleContext> blockSC =
   10806                 :     mPresShell->StyleSet()->
   10807                 :       ResolveAnonymousBoxStyle(aIsPositioned ?
   10808                 :                                  nsCSSAnonBoxes::mozAnonymousPositionedBlock :
   10809                 :                                  nsCSSAnonBoxes::mozAnonymousBlock,
   10810               0 :                                styleContext);
   10811                 : 
   10812               0 :   nsIFrame* lastNewInline = aInitialInline->GetFirstContinuation();
   10813               0 :   do {
   10814                 :     // On entry to this loop aChildItems is not empty and the first frame in it
   10815                 :     // is block-level.
   10816               0 :     NS_PRECONDITION(aChildItems.NotEmpty(), "Should have child items");
   10817               0 :     NS_PRECONDITION(!IsInlineOutside(aChildItems.FirstChild()),
   10818                 :                     "Must have list starting with block");
   10819                 : 
   10820                 :     // The initial run of blocks belongs to an anonymous block that we create
   10821                 :     // right now. The anonymous block will be the parent of these block
   10822                 :     // children of the inline.
   10823                 :     nsIFrame* blockFrame;
   10824               0 :     blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
   10825                 : 
   10826                 :     InitAndRestoreFrame(aState, content, parentFrame, nsnull, blockFrame,
   10827               0 :                         false);
   10828                 : 
   10829                 :     // Find the first non-block child which defines the end of our block kids
   10830                 :     // and the start of our next inline's kids
   10831                 :     nsFrameList::FrameLinkEnumerator firstNonBlock =
   10832               0 :       FindFirstNonBlock(aChildItems);
   10833               0 :     nsFrameList blockKids = aChildItems.ExtractHead(firstNonBlock);
   10834                 : 
   10835               0 :     MoveChildrenTo(aState.mPresContext, aInitialInline, blockFrame, blockKids);
   10836                 : 
   10837               0 :     SetFrameIsSpecial(lastNewInline, blockFrame);
   10838               0 :     aSiblings.AddChild(blockFrame);
   10839                 : 
   10840                 :     // Now grab the initial inlines in aChildItems and put them into an inline
   10841                 :     // frame
   10842               0 :     nsIFrame* inlineFrame = NS_NewInlineFrame(mPresShell, styleContext);
   10843                 : 
   10844                 :     InitAndRestoreFrame(aState, content, parentFrame, nsnull, inlineFrame,
   10845               0 :                         false);
   10846                 : 
   10847               0 :     if (aIsPositioned) {
   10848               0 :       inlineFrame->MarkAsAbsoluteContainingBlock();
   10849                 :     }
   10850                 : 
   10851               0 :     if (aChildItems.NotEmpty()) {
   10852               0 :       nsFrameList::FrameLinkEnumerator firstBlock(aChildItems);
   10853               0 :       FindFirstBlock(firstBlock);
   10854               0 :       nsFrameList inlineKids = aChildItems.ExtractHead(firstBlock);
   10855                 : 
   10856                 :       MoveChildrenTo(aState.mPresContext, aInitialInline, inlineFrame,
   10857               0 :                      inlineKids);
   10858                 :     }
   10859                 : 
   10860               0 :     SetFrameIsSpecial(blockFrame, inlineFrame);
   10861               0 :     aSiblings.AddChild(inlineFrame);
   10862               0 :     lastNewInline = inlineFrame;
   10863               0 :   } while (aChildItems.NotEmpty());
   10864                 : 
   10865               0 :   SetFrameIsSpecial(lastNewInline, nsnull);
   10866               0 : }
   10867                 : 
   10868                 : void
   10869               0 : nsCSSFrameConstructor::BuildInlineChildItems(nsFrameConstructorState& aState,
   10870                 :                                              FrameConstructionItem& aParentItem)
   10871                 : {
   10872                 :   // XXXbz should we preallocate aParentItem.mChildItems to some sane
   10873                 :   // length?  Maybe even to parentContent->GetChildCount()?
   10874                 :   nsFrameConstructorState::PendingBindingAutoPusher
   10875               0 :     pusher(aState, aParentItem.mPendingBinding);
   10876                 : 
   10877                 :   // Probe for generated content before
   10878               0 :   nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
   10879               0 :   nsIContent* const parentContent = aParentItem.mContent;
   10880                 : 
   10881                 :   AncestorFilter::AutoAncestorPusher
   10882               0 :     ancestorPusher(aState.mTreeMatchContext.mAncestorFilter.HasFilter(),
   10883                 :                    aState.mTreeMatchContext.mAncestorFilter,
   10884               0 :                    parentContent->AsElement());
   10885                 :   
   10886                 :   CreateGeneratedContentItem(aState, nsnull, parentContent, parentStyleContext,
   10887                 :                              nsCSSPseudoElements::ePseudo_before,
   10888               0 :                              aParentItem.mChildItems);
   10889                 : 
   10890               0 :   ChildIterator iter, last;
   10891               0 :   for (ChildIterator::Init(parentContent, &iter, &last);
   10892                 :        iter != last;
   10893                 :        ++iter) {
   10894                 :     // Manually check for comments/PIs, since we don't have a frame to pass to
   10895                 :     // AddFrameConstructionItems.  We know our parent is a non-replaced inline,
   10896                 :     // so there is no need to do the NeedFrameFor check.
   10897               0 :     nsIContent* content = *iter;
   10898               0 :     content->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
   10899               0 :     if (content->IsNodeOfType(nsINode::eCOMMENT) ||
   10900               0 :         content->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
   10901               0 :       continue;
   10902                 :     }
   10903               0 :     if (content->IsElement()) {
   10904                 :       // See comment explaining why we need to remove the "is possible
   10905                 :       // restyle root" flags in AddFrameConstructionItems.  But note
   10906                 :       // that we can remove all restyle flags, just like in
   10907                 :       // ProcessChildren and for the same reason.
   10908               0 :       content->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
   10909                 :     }
   10910                 : 
   10911                 :     nsRefPtr<nsStyleContext> childContext =
   10912               0 :       ResolveStyleContext(parentStyleContext, content, &aState);
   10913                 : 
   10914                 :     AddFrameConstructionItemsInternal(aState, content, nsnull, content->Tag(),
   10915                 :                                       content->GetNameSpaceID(),
   10916               0 :                                       iter.XBLInvolved(), childContext,
   10917                 :                                       ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK,
   10918               0 :                                       aParentItem.mChildItems);
   10919                 :   }
   10920                 : 
   10921                 :   // Probe for generated content after
   10922                 :   CreateGeneratedContentItem(aState, nsnull, parentContent, parentStyleContext,
   10923                 :                              nsCSSPseudoElements::ePseudo_after,
   10924               0 :                              aParentItem.mChildItems);
   10925                 : 
   10926               0 :   aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
   10927               0 : }
   10928                 : 
   10929                 : // return whether it's ok to append (in the AppendFrames sense) to
   10930                 : // aParentFrame if our nextSibling is aNextSibling.  aParentFrame must
   10931                 : // be an {ib} special inline.
   10932                 : static bool
   10933               0 : IsSafeToAppendToSpecialInline(nsIFrame* aParentFrame, nsIFrame* aNextSibling)
   10934                 : {
   10935               0 :   NS_PRECONDITION(IsInlineFrame(aParentFrame),
   10936                 :                   "Must have an inline parent here");
   10937               0 :   do {
   10938               0 :     NS_ASSERTION(IsFrameSpecial(aParentFrame), "How is this not special?");
   10939               0 :     if (aNextSibling || aParentFrame->GetNextContinuation() ||
   10940               0 :         GetSpecialSibling(aParentFrame)) {
   10941               0 :       return false;
   10942                 :     }
   10943                 : 
   10944               0 :     aNextSibling = aParentFrame->GetNextSibling();
   10945               0 :     aParentFrame = aParentFrame->GetParent();
   10946                 :   } while (IsInlineFrame(aParentFrame));
   10947                 : 
   10948               0 :   return true;
   10949                 : }
   10950                 : 
   10951                 : bool
   10952               0 : nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
   10953                 :                                            nsIFrame* aContainingBlock,
   10954                 :                                            nsIFrame* aFrame,
   10955                 :                                            FrameConstructionItemList& aItems,
   10956                 :                                            bool aIsAppend,
   10957                 :                                            nsIFrame* aPrevSibling)
   10958                 : {
   10959               0 :   if (aItems.IsEmpty()) {
   10960               0 :     return false;
   10961                 :   }
   10962                 :   
   10963                 :   // Before we go and append the frames, we must check for several
   10964                 :   // special situations.
   10965                 : 
   10966                 :   // Situation #1 is a XUL frame that contains frames that are required
   10967                 :   // to be wrapped in blocks.
   10968               0 :   if (aFrame->IsBoxFrame() &&
   10969               0 :       !(aFrame->GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK) &&
   10970               0 :       aItems.AnyItemsNeedBlockParent()) {
   10971               0 :     RecreateFramesForContent(aFrame->GetContent(), true);
   10972               0 :     return true;
   10973                 :   }
   10974                 : 
   10975               0 :   nsIFrame* nextSibling = ::GetInsertNextSibling(aFrame, aPrevSibling);
   10976                 : 
   10977                 :   // Situation #2 is a case when table pseudo-frames don't work out right
   10978               0 :   ParentType parentType = GetParentType(aFrame);
   10979                 :   // If all the kids want a parent of the type that aFrame is, then we're all
   10980                 :   // set to go.  Indeed, there won't be any table pseudo-frames created between
   10981                 :   // aFrame and the kids, so those won't need to be merged with any table
   10982                 :   // pseudo-frames that might already be kids of aFrame.  If aFrame itself is a
   10983                 :   // table pseudo-frame, then all the kids in this list would have wanted a
   10984                 :   // frame of that type wrapping them anyway, so putting them inside it is ok.
   10985               0 :   if (!aItems.AllWantParentType(parentType)) {
   10986                 :     // Don't give up yet.  If parentType is not eTypeBlock and the parent is
   10987                 :     // not a generated content frame, then try filtering whitespace out of the
   10988                 :     // list.
   10989               0 :     if (parentType != eTypeBlock && !aFrame->IsGeneratedContentFrame()) {
   10990                 :       // For leading whitespace followed by a kid that wants our parent type,
   10991                 :       // there are four cases:
   10992                 :       // 1) We have a previous sibling which is not a table pseudo.  That means
   10993                 :       //    that previous sibling wanted a (non-block) parent of the type we're
   10994                 :       //    looking at.  Then the whitespace comes between two table-internal
   10995                 :       //    elements, so should be collapsed out.
   10996                 :       // 2) We have a previous sibling which is a table pseudo.  It might have
   10997                 :       //    kids who want this whitespace, so we need to reframe.
   10998                 :       // 3) We have no previous sibling and our parent frame is not a table
   10999                 :       //    pseudo.  That means that we'll be at the beginning of our actual
   11000                 :       //    non-block-type parent, and the whitespace is OK to collapse out.
   11001                 :       //    If something is ever inserted before us, it'll find our own parent
   11002                 :       //    as its parent and if it's something that would care about the
   11003                 :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   11004                 :       //    that point.
   11005                 :       // 4) We have no previous sibling and our parent frame is a table pseudo.
   11006                 :       //    Need to reframe.
   11007                 :       // All that is predicated on finding the correct previous sibling.  We
   11008                 :       // might have to walk backwards along continuations from aFrame to do so.
   11009                 :       //
   11010                 :       // It's always OK to drop whitespace between any two items that want a
   11011                 :       // parent of type parentType.
   11012                 :       //
   11013                 :       // For trailing whitespace preceded by a kid that wants our parent type,
   11014                 :       // there are four cases:
   11015                 :       // 1) We have a next sibling which is not a table pseudo.  That means
   11016                 :       //    that next sibling wanted a (non-block) parent of the type we're
   11017                 :       //    looking at.  Then the whitespace comes between two table-internal
   11018                 :       //    elements, so should be collapsed out.
   11019                 :       // 2) We have a next sibling which is a table pseudo.  It might have
   11020                 :       //    kids who want this whitespace, so we need to reframe.
   11021                 :       // 3) We have no next sibling and our parent frame is not a table
   11022                 :       //    pseudo.  That means that we'll be at the end of our actual
   11023                 :       //    non-block-type parent, and the whitespace is OK to collapse out.
   11024                 :       //    If something is ever inserted after us, it'll find our own parent
   11025                 :       //    as its parent and if it's something that would care about the
   11026                 :       //    whitespace it'll want a block parent, so it'll trigger a reframe at
   11027                 :       //    that point.
   11028                 :       // 4) We have no next sibling and our parent frame is a table pseudo.
   11029                 :       //    Need to reframe.
   11030                 :       // All that is predicated on finding the correct next sibling.  We might
   11031                 :       // have to walk forward along continuations from aFrame to do so.  That
   11032                 :       // said, in the case when nextSibling is null at this point and aIsAppend
   11033                 :       // is true, we know we're in case 3.  Furthermore, in that case we don't
   11034                 :       // even have to worry about the table pseudo situation; we know our
   11035                 :       // parent is not a table pseudo there.
   11036               0 :       FCItemIterator iter(aItems);
   11037               0 :       FCItemIterator start(iter);
   11038               0 :       do {
   11039               0 :         if (iter.SkipItemsWantingParentType(parentType)) {
   11040               0 :           break;
   11041                 :         }
   11042                 : 
   11043                 :         // iter points to an item that wants a different parent.  If it's not
   11044                 :         // whitespace, we're done; no more point scanning the list.
   11045               0 :         if (!iter.item().IsWhitespace(aState)) {
   11046               0 :           break;
   11047                 :         }
   11048                 : 
   11049               0 :         if (iter == start) {
   11050                 :           // Leading whitespace.  How to handle this depends on our
   11051                 :           // previous sibling and aFrame.  See the long comment above.
   11052               0 :           nsIFrame* prevSibling = aPrevSibling;
   11053               0 :           if (!prevSibling) {
   11054                 :             // Try to find one after all
   11055               0 :             nsIFrame* parentPrevCont = aFrame->GetPrevContinuation();
   11056               0 :             while (parentPrevCont) {
   11057               0 :               prevSibling = parentPrevCont->GetLastChild(kPrincipalList);
   11058               0 :               if (prevSibling) {
   11059               0 :                 break;
   11060                 :               }
   11061               0 :               parentPrevCont = parentPrevCont->GetPrevContinuation();
   11062                 :             }
   11063                 :           };
   11064               0 :           if (prevSibling) {
   11065               0 :             if (IsTablePseudo(prevSibling)) {
   11066                 :               // need to reframe
   11067               0 :               break;
   11068                 :             }
   11069               0 :           } else if (IsTablePseudo(aFrame)) {
   11070                 :             // need to reframe
   11071               0 :             break;
   11072                 :           }
   11073                 :         }
   11074                 : 
   11075               0 :         FCItemIterator spaceEndIter(iter);
   11076                 :         // Advance spaceEndIter past any whitespace
   11077               0 :         bool trailingSpaces = spaceEndIter.SkipWhitespace(aState);
   11078                 : 
   11079                 :         bool okToDrop;
   11080               0 :         if (trailingSpaces) {
   11081                 :           // Trailing whitespace.  How to handle this depeds on aIsAppend, our
   11082                 :           // next sibling and aFrame.  See the long comment above.
   11083               0 :           okToDrop = aIsAppend && !nextSibling;
   11084               0 :           if (!okToDrop) {
   11085               0 :             if (!nextSibling) {
   11086                 :               // Try to find one after all
   11087               0 :               nsIFrame* parentNextCont = aFrame->GetNextContinuation();
   11088               0 :               while (parentNextCont) {
   11089               0 :                 nextSibling = parentNextCont->GetFirstPrincipalChild();
   11090               0 :                 if (nextSibling) {
   11091               0 :                   break;
   11092                 :                 }
   11093               0 :                 parentNextCont = parentNextCont->GetNextContinuation();
   11094                 :               }
   11095                 :             }
   11096                 : 
   11097               0 :             okToDrop = (nextSibling && !IsTablePseudo(nextSibling)) ||
   11098               0 :                        (!nextSibling && !IsTablePseudo(aFrame));
   11099                 :           }
   11100                 : #ifdef DEBUG
   11101                 :           else {
   11102               0 :             NS_ASSERTION(!IsTablePseudo(aFrame), "How did that happen?");
   11103                 :           }
   11104                 : #endif
   11105                 :         } else {
   11106               0 :           okToDrop = (spaceEndIter.item().DesiredParentType() == parentType);
   11107                 :         }
   11108                 : 
   11109               0 :         if (okToDrop) {
   11110               0 :           iter.DeleteItemsTo(spaceEndIter);
   11111                 :         } else {
   11112                 :           // We're done: we don't want to drop the whitespace, and it has the
   11113                 :           // wrong parent type.
   11114               0 :           break;
   11115                 :         }
   11116                 : 
   11117                 :         // Now loop, since |iter| points to item right after the whitespace we
   11118                 :         // removed.
   11119               0 :       } while (!iter.IsDone());
   11120                 :     }
   11121                 : 
   11122                 :     // We might be able to figure out some sort of optimizations here, but they
   11123                 :     // would have to depend on having a correct aPrevSibling and a correct next
   11124                 :     // sibling.  For example, we can probably avoid reframing if none of
   11125                 :     // aFrame, aPrevSibling, and next sibling are table pseudo-frames.  But it
   11126                 :     // doesn't seem worth it to worry about that for now, especially since we
   11127                 :     // in fact do not have a reliable aPrevSibling, nor any next sibling, in
   11128                 :     // this method.
   11129                 : 
   11130                 :     // aItems might have changed, so recheck the parent type thing.  In fact,
   11131                 :     // it might be empty, so recheck that too.
   11132               0 :     if (aItems.IsEmpty()) {
   11133               0 :       return false;
   11134                 :     }
   11135                 : 
   11136               0 :     if (!aItems.AllWantParentType(parentType)) {
   11137                 :       // Reframing aFrame->GetContent() is good enough, since the content of
   11138                 :       // table pseudo-frames is the ancestor content.
   11139               0 :       RecreateFramesForContent(aFrame->GetContent(), true);
   11140               0 :       return true;
   11141                 :     }
   11142                 :   }
   11143                 : 
   11144                 :   // Now we have several cases involving {ib} splits.  Put them all in a
   11145                 :   // do/while with breaks to take us to the "go and reconstruct" code.
   11146                 :   do {
   11147               0 :     if (IsInlineFrame(aFrame)) {
   11148               0 :       if (aItems.AreAllItemsInline()) {
   11149                 :         // We can just put the kids in.
   11150               0 :         return false;
   11151                 :       }
   11152                 : 
   11153               0 :       if (!IsFrameSpecial(aFrame)) {
   11154                 :         // Need to go ahead and reconstruct.
   11155               0 :         break;
   11156                 :       }
   11157                 : 
   11158                 :       // Now we're adding kids including some blocks to an inline part of an
   11159                 :       // {ib} split.  If we plan to call AppendFrames, and don't have a next
   11160                 :       // sibling for the new frames, and our parent is the last continuation of
   11161                 :       // the last part of the {ib} split, and the same is true of all our
   11162                 :       // ancestor inlines (they have no following continuations and they're the
   11163                 :       // last part of their {ib} splits and we'd be adding to the end for all
   11164                 :       // of them), then AppendFrames will handle things for us.  Bail out in
   11165                 :       // that case.
   11166               0 :       if (aIsAppend && IsSafeToAppendToSpecialInline(aFrame, nextSibling)) {
   11167               0 :         return false;
   11168                 :       }
   11169                 : 
   11170                 :       // Need to reconstruct.
   11171               0 :       break;
   11172                 :     }
   11173                 : 
   11174                 :     // Now we know we have a block parent.  If it's not special, we're all set.
   11175               0 :     if (!IsFrameSpecial(aFrame)) {
   11176               0 :       return false;
   11177                 :     }
   11178                 : 
   11179                 :     // We're adding some kids to a block part of an {ib} split.  If all the
   11180                 :     // kids are blocks, we don't need to reconstruct.
   11181               0 :     if (aItems.AreAllItemsBlock()) {
   11182               0 :       return false;
   11183                 :     }
   11184                 : 
   11185                 :     // We might have some inline kids for this block.  Just reconstruct.
   11186               0 :     break;
   11187                 :   } while (0);
   11188                 : 
   11189                 :   // If we don't have a containing block, start with aFrame and look for one.
   11190               0 :   if (!aContainingBlock) {
   11191               0 :     aContainingBlock = aFrame;
   11192                 :   }
   11193                 :   
   11194                 :   // To find the right block to reframe, just walk up the tree until we find a
   11195                 :   // frame that is:
   11196                 :   // 1)  Not part of an IB split (not special)
   11197                 :   // 2)  Not a pseudo-frame
   11198                 :   // 3)  Not an inline frame
   11199                 :   // We're guaranteed to find one, since nsStyleContext::ApplyStyleFixups
   11200                 :   // enforces that the root is display:none, display:table, or display:block.
   11201                 :   // Note that walking up "too far" is OK in terms of correctness, even if it
   11202                 :   // might be a little inefficient.  This is why we walk out of all
   11203                 :   // pseudo-frames -- telling which ones are or are not OK to walk out of is
   11204                 :   // too hard (and I suspect that we do in fact need to walk out of all of
   11205                 :   // them).
   11206               0 :   while (IsFrameSpecial(aContainingBlock) || IsInlineOutside(aContainingBlock) ||
   11207               0 :          aContainingBlock->GetStyleContext()->GetPseudo()) {
   11208               0 :     aContainingBlock = aContainingBlock->GetParent();
   11209               0 :     NS_ASSERTION(aContainingBlock,
   11210                 :                  "Must have non-inline, non-special, non-pseudo frame as root "
   11211                 :                  "(or child of root, for a table root)!");
   11212                 :   }
   11213                 : 
   11214                 :   // Tell parent of the containing block to reformulate the
   11215                 :   // entire block. This is painful and definitely not optimal
   11216                 :   // but it will *always* get the right answer.
   11217                 : 
   11218               0 :   nsIContent *blockContent = aContainingBlock->GetContent();
   11219                 : #ifdef DEBUG
   11220               0 :   if (gNoisyContentUpdates) {
   11221                 :     printf("nsCSSFrameConstructor::WipeContainingBlock: blockContent=%p\n",
   11222               0 :            static_cast<void*>(blockContent));
   11223                 :   }
   11224                 : #endif
   11225               0 :   RecreateFramesForContent(blockContent, true);
   11226               0 :   return true;
   11227                 : }
   11228                 : 
   11229                 : nsresult
   11230               0 : nsCSSFrameConstructor::ReframeContainingBlock(nsIFrame* aFrame)
   11231                 : {
   11232                 : 
   11233                 : #ifdef DEBUG
   11234                 :   // ReframeContainingBlock is a NASTY routine, it causes terrible performance problems
   11235                 :   // so I want to see when it is happening!  Unfortunately, it is happening way to often because
   11236                 :   // so much content on the web causes 'special' block-in-inline frame situations and we handle them
   11237                 :   // very poorly
   11238               0 :   if (gNoisyContentUpdates) {
   11239                 :     printf("nsCSSFrameConstructor::ReframeContainingBlock frame=%p\n",
   11240               0 :            static_cast<void*>(aFrame));
   11241                 :   }
   11242                 : #endif
   11243                 : 
   11244                 :   // XXXbz how exactly would we get here while isReflowing anyway?  Should this
   11245                 :   // whole test be ifdef DEBUG?
   11246               0 :   if (mPresShell->IsReflowLocked()) {
   11247                 :     // don't ReframeContainingBlock, this will result in a crash
   11248                 :     // if we remove a tree that's in reflow - see bug 121368 for testcase
   11249               0 :     NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!");
   11250               0 :     return NS_OK;
   11251                 :   }
   11252                 : 
   11253                 :   // Get the first "normal" ancestor of the target frame.
   11254               0 :   nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
   11255               0 :   if (containingBlock) {
   11256                 :     // From here we look for the containing block in case the target
   11257                 :     // frame is already a block (which can happen when an inline frame
   11258                 :     // wraps some of its content in an anonymous block; see
   11259                 :     // ConstructInline)
   11260                 :    
   11261                 :     // NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
   11262                 :     // GetIBContainingBlock works much better and provides the correct container in all cases
   11263                 :     // so GetFloatContainingBlock(aFrame) has been removed
   11264                 : 
   11265                 :     // And get the containingBlock's content
   11266               0 :     nsCOMPtr<nsIContent> blockContent = containingBlock->GetContent();
   11267               0 :     if (blockContent) {
   11268                 : #ifdef DEBUG
   11269               0 :       if (gNoisyContentUpdates) {
   11270               0 :         printf("  ==> blockContent=%p\n", static_cast<void*>(blockContent));
   11271                 :       }
   11272                 : #endif
   11273               0 :       return RecreateFramesForContent(blockContent, true);
   11274                 :     }
   11275                 :   }
   11276                 : 
   11277                 :   // If we get here, we're screwed!
   11278               0 :   return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
   11279               0 :                                   true);
   11280                 : }
   11281                 : 
   11282                 : void
   11283               0 : nsCSSFrameConstructor::RestyleForEmptyChange(Element* aContainer)
   11284                 : {
   11285                 :   // In some cases (:empty + E, :empty ~ E), a change if the content of
   11286                 :   // an element requires restyling its parent's siblings.
   11287               0 :   nsRestyleHint hint = eRestyle_Subtree;
   11288               0 :   nsIContent* grandparent = aContainer->GetParent();
   11289               0 :   if (grandparent &&
   11290               0 :       (grandparent->GetFlags() & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS)) {
   11291               0 :     hint = nsRestyleHint(hint | eRestyle_LaterSiblings);
   11292                 :   }
   11293               0 :   PostRestyleEvent(aContainer, hint, NS_STYLE_HINT_NONE);
   11294               0 : }
   11295                 : 
   11296                 : void
   11297               0 : nsCSSFrameConstructor::RestyleForAppend(Element* aContainer,
   11298                 :                                         nsIContent* aFirstNewContent)
   11299                 : {
   11300               0 :   NS_ASSERTION(aContainer, "must have container for append");
   11301                 : #ifdef DEBUG
   11302                 :   {
   11303               0 :     for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
   11304               0 :       NS_ASSERTION(!cur->IsRootOfAnonymousSubtree(),
   11305                 :                    "anonymous nodes should not be in child lists");
   11306                 :     }
   11307                 :   }
   11308                 : #endif
   11309                 :   PRUint32 selectorFlags =
   11310               0 :     aContainer->GetFlags() & (NODE_ALL_SELECTOR_FLAGS &
   11311               0 :                               ~NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
   11312               0 :   if (selectorFlags == 0)
   11313               0 :     return;
   11314                 : 
   11315               0 :   if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
   11316                 :     // see whether we need to restyle the container
   11317               0 :     bool wasEmpty = true; // :empty or :-moz-only-whitespace
   11318               0 :     for (nsIContent* cur = aContainer->GetFirstChild();
   11319                 :          cur != aFirstNewContent;
   11320               0 :          cur = cur->GetNextSibling()) {
   11321                 :       // We don't know whether we're testing :empty or :-moz-only-whitespace,
   11322                 :       // so be conservative and assume :-moz-only-whitespace (i.e., make
   11323                 :       // IsSignificantChild less likely to be true, and thus make us more
   11324                 :       // likely to restyle).
   11325               0 :       if (nsStyleUtil::IsSignificantChild(cur, true, false)) {
   11326               0 :         wasEmpty = false;
   11327               0 :         break;
   11328                 :       }
   11329                 :     }
   11330               0 :     if (wasEmpty) {
   11331               0 :       RestyleForEmptyChange(aContainer);
   11332               0 :       return;
   11333                 :     }
   11334                 :   }
   11335                 : 
   11336               0 :   if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
   11337               0 :     PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
   11338                 :     // Restyling the container is the most we can do here, so we're done.
   11339               0 :     return;
   11340                 :   }
   11341                 : 
   11342               0 :   if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
   11343                 :     // restyle the last element child before this node
   11344               0 :     for (nsIContent* cur = aFirstNewContent->GetPreviousSibling();
   11345                 :          cur;
   11346               0 :          cur = cur->GetPreviousSibling()) {
   11347               0 :       if (cur->IsElement()) {
   11348               0 :         PostRestyleEvent(cur->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
   11349               0 :         break;
   11350                 :       }
   11351                 :     }
   11352                 :   }
   11353                 : }
   11354                 : 
   11355                 : // Needed since we can't use PostRestyleEvent on non-elements (with
   11356                 : // eRestyle_LaterSiblings or nsRestyleHint(eRestyle_Subtree |
   11357                 : // eRestyle_LaterSiblings) as appropriate).
   11358                 : static void
   11359               0 : RestyleSiblingsStartingWith(nsCSSFrameConstructor *aFrameConstructor,
   11360                 :                             nsIContent *aStartingSibling /* may be null */)
   11361                 : {
   11362               0 :   for (nsIContent *sibling = aStartingSibling; sibling;
   11363               0 :        sibling = sibling->GetNextSibling()) {
   11364               0 :     if (sibling->IsElement()) {
   11365                 :       aFrameConstructor->
   11366                 :         PostRestyleEvent(sibling->AsElement(),
   11367                 :                          nsRestyleHint(eRestyle_Subtree | eRestyle_LaterSiblings),
   11368               0 :                          NS_STYLE_HINT_NONE);
   11369               0 :       break;
   11370                 :     }
   11371                 :   }
   11372               0 : }
   11373                 : 
   11374                 : // Restyling for a ContentInserted or CharacterDataChanged notification.
   11375                 : // This could be used for ContentRemoved as well if we got the
   11376                 : // notification before the removal happened (and sometimes
   11377                 : // CharacterDataChanged is more like a removal than an addition).
   11378                 : // The comments are written and variables are named in terms of it being
   11379                 : // a ContentInserted notification.
   11380                 : void
   11381               0 : nsCSSFrameConstructor::RestyleForInsertOrChange(Element* aContainer,
   11382                 :                                                 nsIContent* aChild)
   11383                 : {
   11384               0 :   NS_ASSERTION(!aChild->IsRootOfAnonymousSubtree(),
   11385                 :                "anonymous nodes should not be in child lists");
   11386                 :   PRUint32 selectorFlags =
   11387               0 :     aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
   11388               0 :   if (selectorFlags == 0)
   11389               0 :     return;
   11390                 : 
   11391               0 :   if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
   11392                 :     // see whether we need to restyle the container
   11393               0 :     bool wasEmpty = true; // :empty or :-moz-only-whitespace
   11394               0 :     for (nsIContent* child = aContainer->GetFirstChild();
   11395                 :          child;
   11396               0 :          child = child->GetNextSibling()) {
   11397               0 :       if (child == aChild)
   11398               0 :         continue;
   11399                 :       // We don't know whether we're testing :empty or :-moz-only-whitespace,
   11400                 :       // so be conservative and assume :-moz-only-whitespace (i.e., make
   11401                 :       // IsSignificantChild less likely to be true, and thus make us more
   11402                 :       // likely to restyle).
   11403               0 :       if (nsStyleUtil::IsSignificantChild(child, true, false)) {
   11404               0 :         wasEmpty = false;
   11405               0 :         break;
   11406                 :       }
   11407                 :     }
   11408               0 :     if (wasEmpty) {
   11409               0 :       RestyleForEmptyChange(aContainer);
   11410               0 :       return;
   11411                 :     }
   11412                 :   }
   11413                 : 
   11414               0 :   if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
   11415               0 :     PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
   11416                 :     // Restyling the container is the most we can do here, so we're done.
   11417               0 :     return;
   11418                 :   }
   11419                 : 
   11420               0 :   if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
   11421                 :     // Restyle all later siblings.
   11422               0 :     RestyleSiblingsStartingWith(this, aChild->GetNextSibling());
   11423                 :   }
   11424                 : 
   11425               0 :   if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
   11426                 :     // restyle the previously-first element child if it is after this node
   11427               0 :     bool passedChild = false;
   11428               0 :     for (nsIContent* content = aContainer->GetFirstChild();
   11429                 :          content;
   11430               0 :          content = content->GetNextSibling()) {
   11431               0 :       if (content == aChild) {
   11432               0 :         passedChild = true;
   11433               0 :         continue;
   11434                 :       }
   11435               0 :       if (content->IsElement()) {
   11436               0 :         if (passedChild) {
   11437                 :           PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
   11438               0 :                            NS_STYLE_HINT_NONE);
   11439                 :         }
   11440               0 :         break;
   11441                 :       }
   11442                 :     }
   11443                 :     // restyle the previously-last element child if it is before this node
   11444               0 :     passedChild = false;
   11445               0 :     for (nsIContent* content = aContainer->GetLastChild();
   11446                 :          content;
   11447               0 :          content = content->GetPreviousSibling()) {
   11448               0 :       if (content == aChild) {
   11449               0 :         passedChild = true;
   11450               0 :         continue;
   11451                 :       }
   11452               0 :       if (content->IsElement()) {
   11453               0 :         if (passedChild) {
   11454                 :           PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
   11455               0 :                            NS_STYLE_HINT_NONE);
   11456                 :         }
   11457               0 :         break;
   11458                 :       }
   11459                 :     }
   11460                 :   }
   11461                 : }
   11462                 : 
   11463                 : void
   11464               0 : nsCSSFrameConstructor::RestyleForRemove(Element* aContainer,
   11465                 :                                         nsIContent* aOldChild,
   11466                 :                                         nsIContent* aFollowingSibling)
   11467                 : {
   11468               0 :   NS_ASSERTION(!aOldChild->IsRootOfAnonymousSubtree(),
   11469                 :                "anonymous nodes should not be in child lists");
   11470                 :   PRUint32 selectorFlags =
   11471               0 :     aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
   11472               0 :   if (selectorFlags == 0)
   11473               0 :     return;
   11474                 : 
   11475               0 :   if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
   11476                 :     // see whether we need to restyle the container
   11477               0 :     bool isEmpty = true; // :empty or :-moz-only-whitespace
   11478               0 :     for (nsIContent* child = aContainer->GetFirstChild();
   11479                 :          child;
   11480               0 :          child = child->GetNextSibling()) {
   11481                 :       // We don't know whether we're testing :empty or :-moz-only-whitespace,
   11482                 :       // so be conservative and assume :-moz-only-whitespace (i.e., make
   11483                 :       // IsSignificantChild less likely to be true, and thus make us more
   11484                 :       // likely to restyle).
   11485               0 :       if (nsStyleUtil::IsSignificantChild(child, true, false)) {
   11486               0 :         isEmpty = false;
   11487               0 :         break;
   11488                 :       }
   11489                 :     }
   11490               0 :     if (isEmpty) {
   11491               0 :       RestyleForEmptyChange(aContainer);
   11492               0 :       return;
   11493                 :     }
   11494                 :   }
   11495                 : 
   11496               0 :   if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
   11497               0 :     PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
   11498                 :     // Restyling the container is the most we can do here, so we're done.
   11499               0 :     return;
   11500                 :   }
   11501                 : 
   11502               0 :   if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
   11503                 :     // Restyle all later siblings.
   11504               0 :     RestyleSiblingsStartingWith(this, aFollowingSibling);
   11505                 :   }
   11506                 : 
   11507               0 :   if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
   11508                 :     // restyle the now-first element child if it was after aOldChild
   11509               0 :     bool reachedFollowingSibling = false;
   11510               0 :     for (nsIContent* content = aContainer->GetFirstChild();
   11511                 :          content;
   11512               0 :          content = content->GetNextSibling()) {
   11513               0 :       if (content == aFollowingSibling) {
   11514               0 :         reachedFollowingSibling = true;
   11515                 :         // do NOT continue here; we might want to restyle this node
   11516                 :       }
   11517               0 :       if (content->IsElement()) {
   11518               0 :         if (reachedFollowingSibling) {
   11519                 :           PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
   11520               0 :                            NS_STYLE_HINT_NONE);
   11521                 :         }
   11522               0 :         break;
   11523                 :       }
   11524                 :     }
   11525                 :     // restyle the now-last element child if it was before aOldChild
   11526               0 :     reachedFollowingSibling = (aFollowingSibling == nsnull);
   11527               0 :     for (nsIContent* content = aContainer->GetLastChild();
   11528                 :          content;
   11529               0 :          content = content->GetPreviousSibling()) {
   11530               0 :       if (content->IsElement()) {
   11531               0 :         if (reachedFollowingSibling) {
   11532               0 :           PostRestyleEvent(content->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
   11533                 :         }
   11534               0 :         break;
   11535                 :       }
   11536               0 :       if (content == aFollowingSibling) {
   11537               0 :         reachedFollowingSibling = true;
   11538                 :       }
   11539                 :     }
   11540                 :   }
   11541                 : }
   11542                 : 
   11543                 : 
   11544                 : void
   11545               0 : nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
   11546                 : {
   11547               0 :   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
   11548                 :                "Should not reconstruct the root of the frame tree.  "
   11549                 :                "Use ReconstructDocElementHierarchy instead.");
   11550                 : 
   11551               0 :   mRebuildAllStyleData = false;
   11552               0 :   NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
   11553               0 :   mRebuildAllExtraHint = nsChangeHint(0);
   11554                 : 
   11555               0 :   if (!mPresShell || !mPresShell->GetRootFrame())
   11556               0 :     return;
   11557                 : 
   11558                 :   // Make sure that the viewmanager will outlive the presshell
   11559               0 :   nsCOMPtr<nsIViewManager> vm = mPresShell->GetViewManager();
   11560                 : 
   11561                 :   // Processing the style changes could cause a flush that propagates to
   11562                 :   // the parent frame and thus destroys the pres shell.
   11563               0 :   nsCOMPtr<nsIPresShell> kungFuDeathGrip(mPresShell);
   11564                 : 
   11565                 :   // We may reconstruct frames below and hence process anything that is in the
   11566                 :   // tree. We don't want to get notified to process those items again after.
   11567               0 :   mPresShell->GetDocument()->FlushPendingNotifications(Flush_ContentAndNotify);
   11568                 : 
   11569               0 :   nsAutoScriptBlocker scriptBlocker;
   11570                 : 
   11571                 :   // Tell the style set to get the old rule tree out of the way
   11572                 :   // so we can recalculate while maintaining rule tree immutability
   11573               0 :   nsresult rv = mPresShell->StyleSet()->BeginReconstruct();
   11574               0 :   if (NS_FAILED(rv)) {
   11575                 :     return;
   11576                 :   }
   11577                 : 
   11578               0 :   nsPresContext *presContext = mPresShell->GetPresContext();
   11579               0 :   presContext->SetProcessingRestyles(true);
   11580                 :   // Recalculate all of the style contexts for the document
   11581                 :   // Note that we can ignore the return value of ComputeStyleChangeFor
   11582                 :   // because we never need to reframe the root frame
   11583                 :   // XXX This could be made faster by not rerunning rule matching
   11584                 :   // (but note that nsPresShell::SetPreferenceStyleRules currently depends
   11585                 :   // on us re-running rule matching here
   11586               0 :   nsStyleChangeList changeList;
   11587                 :   // XXX Does it matter that we're passing aExtraHint to the real root
   11588                 :   // frame and not the root node's primary frame?
   11589                 :   // Note: The restyle tracker we pass in here doesn't matter.
   11590                 :   ComputeStyleChangeFor(mPresShell->GetRootFrame(),
   11591                 :                         &changeList, aExtraHint,
   11592               0 :                         mPendingRestyles, true);
   11593                 :   // Process the required changes
   11594               0 :   ProcessRestyledFrames(changeList);
   11595               0 :   presContext->SetProcessingRestyles(false);
   11596                 : 
   11597                 :   // Make sure that we process any pending animation restyles from the
   11598                 :   // above style change.  Note that we can *almost* implement the above
   11599                 :   // by just posting a style change -- except we really need to restyle
   11600                 :   // the root frame rather than the root element's primary frame.
   11601               0 :   ProcessPendingRestyles();
   11602                 : 
   11603                 :   // Tell the style set it's safe to destroy the old rule tree.  We
   11604                 :   // must do this after the ProcessRestyledFrames call in case the
   11605                 :   // change list has frame reconstructs in it (since frames to be
   11606                 :   // reconstructed will still have their old style context pointers
   11607                 :   // until they are destroyed).
   11608               0 :   mPresShell->StyleSet()->EndReconstruct();
   11609                 : }
   11610                 : 
   11611                 : void
   11612               0 : nsCSSFrameConstructor::ProcessPendingRestyles()
   11613                 : {
   11614               0 :   NS_PRECONDITION(mDocument, "No document?  Pshaw!");
   11615               0 :   NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
   11616                 :                   "Missing a script blocker!");
   11617                 : 
   11618                 :   // Process non-animation restyles...
   11619               0 :   nsPresContext *presContext = mPresShell->GetPresContext();
   11620               0 :   NS_ABORT_IF_FALSE(!presContext->IsProcessingRestyles(),
   11621                 :                     "Nesting calls to ProcessPendingRestyles?");
   11622               0 :   presContext->SetProcessingRestyles(true);
   11623                 : 
   11624               0 :   mPendingRestyles.ProcessRestyles();
   11625                 : 
   11626                 : #ifdef DEBUG
   11627               0 :   PRUint32 oldPendingRestyleCount = mPendingRestyles.Count();
   11628                 : #endif
   11629                 : 
   11630                 :   // ...and then process animation restyles.  This needs to happen
   11631                 :   // second because we need to start animations that resulted from the
   11632                 :   // first set of restyles (e.g., CSS transitions with negative
   11633                 :   // transition-delay), and because we need to immediately
   11634                 :   // restyle-with-animation any just-restyled elements that are
   11635                 :   // mid-transition (since processing the non-animation restyle ignores
   11636                 :   // the running transition so it can check for a new change on the same
   11637                 :   // property, and then posts an immediate animation style change).
   11638               0 :   presContext->SetProcessingAnimationStyleChange(true);
   11639               0 :   mPendingAnimationRestyles.ProcessRestyles();
   11640               0 :   presContext->SetProcessingAnimationStyleChange(false);
   11641                 : 
   11642               0 :   presContext->SetProcessingRestyles(false);
   11643               0 :   NS_POSTCONDITION(mPendingRestyles.Count() == oldPendingRestyleCount,
   11644                 :                    "We should not have posted new non-animation restyles while "
   11645                 :                    "processing animation restyles");
   11646                 : 
   11647               0 :   if (mRebuildAllStyleData) {
   11648                 :     // We probably wasted a lot of work up above, but this seems safest
   11649                 :     // and it should be rarely used.
   11650                 :     // This might add us as a refresh observer again; that's ok.
   11651               0 :     RebuildAllStyleData(nsChangeHint(0));
   11652                 :   }
   11653               0 : }
   11654                 : 
   11655                 : void
   11656               0 : nsCSSFrameConstructor::PostRestyleEventCommon(Element* aElement,
   11657                 :                                               nsRestyleHint aRestyleHint,
   11658                 :                                               nsChangeHint aMinChangeHint,
   11659                 :                                               bool aForAnimation)
   11660                 : {
   11661               0 :   if (NS_UNLIKELY(mPresShell->IsDestroying())) {
   11662               0 :     return;
   11663                 :   }
   11664                 : 
   11665               0 :   if (aRestyleHint == 0 && !aMinChangeHint) {
   11666                 :     // Nothing to do here
   11667               0 :     return;
   11668                 :   }
   11669                 : 
   11670                 :   RestyleTracker& tracker =
   11671               0 :     aForAnimation ? mPendingAnimationRestyles : mPendingRestyles;
   11672               0 :   tracker.AddPendingRestyle(aElement, aRestyleHint, aMinChangeHint);
   11673                 : 
   11674               0 :   PostRestyleEventInternal(false);
   11675                 : }
   11676                 :     
   11677                 : void
   11678               0 : nsCSSFrameConstructor::PostRestyleEventInternal(bool aForLazyConstruction)
   11679                 : {
   11680                 :   // Make sure we're not in a style refresh; if we are, we still have
   11681                 :   // a call to ProcessPendingRestyles coming and there's no need to
   11682                 :   // add ourselves as a refresh observer until then.
   11683               0 :   bool inRefresh = !aForLazyConstruction && mInStyleRefresh;
   11684               0 :   if (!mObservingRefreshDriver && !inRefresh) {
   11685                 :     mObservingRefreshDriver = mPresShell->GetPresContext()->RefreshDriver()->
   11686               0 :       AddStyleFlushObserver(mPresShell);
   11687                 :   }
   11688                 : 
   11689                 :   // Unconditionally flag our document as needing a flush.  The other
   11690                 :   // option here would be a dedicated boolean to track whether we need
   11691                 :   // to do so (set here and unset in ProcessPendingRestyles).
   11692               0 :   mPresShell->GetDocument()->SetNeedStyleFlush();
   11693               0 : }
   11694                 : 
   11695                 : void
   11696               0 : nsCSSFrameConstructor::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint)
   11697                 : {
   11698               0 :   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
   11699                 :                "Should not reconstruct the root of the frame tree.  "
   11700                 :                "Use ReconstructDocElementHierarchy instead.");
   11701                 : 
   11702               0 :   mRebuildAllStyleData = true;
   11703               0 :   NS_UpdateHint(mRebuildAllExtraHint, aExtraHint);
   11704                 :   // Get a restyle event posted if necessary
   11705               0 :   PostRestyleEventInternal(false);
   11706               0 : }
   11707                 : 
   11708                 : nsresult
   11709               0 : nsCSSFrameConstructor::GenerateChildFrames(nsIFrame* aFrame)
   11710                 : {
   11711                 :   {
   11712               0 :     nsAutoScriptBlocker scriptBlocker;
   11713               0 :     BeginUpdate();
   11714                 : 
   11715               0 :     nsFrameItems childItems;
   11716               0 :     nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
   11717                 :     // We don't have a parent frame with a pending binding constructor here,
   11718                 :     // so no need to worry about ordering of the kids' constructors with it.
   11719                 :     // Pass null for the PendingBinding.
   11720                 :     nsresult rv = ProcessChildren(state, aFrame->GetContent(), aFrame->GetStyleContext(),
   11721                 :                                   aFrame, false, childItems, false,
   11722               0 :                                   nsnull);
   11723               0 :     if (NS_FAILED(rv)) {
   11724               0 :       EndUpdate();
   11725               0 :       return rv;
   11726                 :     }
   11727                 : 
   11728               0 :     aFrame->SetInitialChildList(kPrincipalList, childItems);
   11729                 : 
   11730               0 :     EndUpdate();
   11731                 :   }
   11732                 : 
   11733                 : #ifdef ACCESSIBILITY
   11734               0 :   nsAccessibilityService* accService = nsIPresShell::AccService();
   11735               0 :   if (accService) {
   11736               0 :     nsIContent* container = aFrame->GetContent();
   11737               0 :     nsIContent* child = container->GetFirstChild();
   11738               0 :     if (child) {
   11739               0 :       accService->ContentRangeInserted(mPresShell, container, child, nsnull);
   11740                 :     }
   11741                 :   }
   11742                 : #endif
   11743                 : 
   11744                 :   // call XBL constructors after the frames are created
   11745               0 :   mPresShell->GetDocument()->BindingManager()->ProcessAttachedQueue();
   11746                 : 
   11747               0 :   return NS_OK;
   11748                 : }
   11749                 : 
   11750                 : //////////////////////////////////////////////////////////
   11751                 : // nsCSSFrameConstructor::FrameConstructionItem methods //
   11752                 : //////////////////////////////////////////////////////////
   11753                 : bool
   11754               0 : nsCSSFrameConstructor::
   11755                 : FrameConstructionItem::IsWhitespace(nsFrameConstructorState& aState) const
   11756                 : {
   11757               0 :   NS_PRECONDITION(aState.mCreatingExtraFrames ||
   11758                 :                   !mContent->GetPrimaryFrame(), "How did that happen?");
   11759               0 :   if (!mIsText) {
   11760               0 :     return false;
   11761                 :   }
   11762                 :   mContent->SetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
   11763               0 :                      NS_REFRAME_IF_WHITESPACE);
   11764               0 :   return mContent->TextIsOnlyWhitespace();
   11765                 : }
   11766                 : 
   11767                 : //////////////////////////////////////////////////////////////
   11768                 : // nsCSSFrameConstructor::FrameConstructionItemList methods //
   11769                 : //////////////////////////////////////////////////////////////
   11770                 : void
   11771               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11772                 : AdjustCountsForItem(FrameConstructionItem* aItem, PRInt32 aDelta)
   11773                 : {
   11774               0 :   NS_PRECONDITION(aDelta == 1 || aDelta == -1, "Unexpected delta");
   11775               0 :   mItemCount += aDelta;
   11776               0 :   if (aItem->mIsAllInline) {
   11777               0 :     mInlineCount += aDelta;
   11778                 :   }
   11779               0 :   if (aItem->mIsBlock) {
   11780               0 :     mBlockCount += aDelta;
   11781                 :   }
   11782               0 :   if (aItem->mIsLineParticipant) {
   11783               0 :     mLineParticipantCount += aDelta;
   11784                 :   }
   11785               0 :   mDesiredParentCounts[aItem->DesiredParentType()] += aDelta;
   11786               0 : }
   11787                 : 
   11788                 : ////////////////////////////////////////////////////////////////////////
   11789                 : // nsCSSFrameConstructor::FrameConstructionItemList::Iterator methods //
   11790                 : ////////////////////////////////////////////////////////////////////////
   11791                 : inline bool
   11792               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11793                 : Iterator::SkipItemsWantingParentType(ParentType aParentType)
   11794                 : {
   11795               0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   11796               0 :   while (item().DesiredParentType() == aParentType) {
   11797               0 :     Next();
   11798               0 :     if (IsDone()) {
   11799               0 :       return true;
   11800                 :     }
   11801                 :   }
   11802               0 :   return false;
   11803                 : }
   11804                 : 
   11805                 : inline bool
   11806               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11807                 : Iterator::SkipWhitespace(nsFrameConstructorState& aState)
   11808                 : {
   11809               0 :   NS_PRECONDITION(!IsDone(), "Shouldn't be done yet");
   11810               0 :   NS_PRECONDITION(item().IsWhitespace(aState), "Not pointing to whitespace?");
   11811               0 :   do {
   11812               0 :     Next();
   11813               0 :     if (IsDone()) {
   11814               0 :       return true;
   11815                 :     }
   11816               0 :   } while (item().IsWhitespace(aState));
   11817                 : 
   11818               0 :   return false;
   11819                 : }
   11820                 : 
   11821                 : void
   11822               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11823                 : Iterator::AppendItemToList(FrameConstructionItemList& aTargetList)
   11824                 : {
   11825               0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   11826               0 :   NS_PRECONDITION(!IsDone(), "should not be done");
   11827                 : 
   11828               0 :   FrameConstructionItem* item = ToItem(mCurrent);
   11829               0 :   Next();
   11830               0 :   PR_REMOVE_LINK(item);
   11831               0 :   PR_APPEND_LINK(item, &aTargetList.mItems);
   11832                 : 
   11833               0 :   mList.AdjustCountsForItem(item, -1);
   11834               0 :   aTargetList.AdjustCountsForItem(item, 1);
   11835               0 : }
   11836                 : 
   11837                 : void
   11838               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11839                 : Iterator::AppendItemsToList(const Iterator& aEnd,
   11840                 :                             FrameConstructionItemList& aTargetList)
   11841                 : {
   11842               0 :   NS_ASSERTION(&aTargetList != &mList, "Unexpected call");
   11843               0 :   NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
   11844                 : 
   11845               0 :   if (!AtStart() || !aEnd.IsDone() || !aTargetList.IsEmpty()) {
   11846               0 :     do {
   11847               0 :       AppendItemToList(aTargetList);
   11848                 :     } while (*this != aEnd);
   11849               0 :     return;
   11850                 :   }
   11851                 : 
   11852                 :   // move over the list of items
   11853               0 :   PR_INSERT_AFTER(&aTargetList.mItems, &mList.mItems);
   11854               0 :   PR_REMOVE_LINK(&mList.mItems);
   11855                 : 
   11856                 :   // Copy over the various counters
   11857               0 :   aTargetList.mInlineCount = mList.mInlineCount;
   11858               0 :   aTargetList.mBlockCount = mList.mBlockCount;
   11859               0 :   aTargetList.mLineParticipantCount = mList.mLineParticipantCount;
   11860               0 :   aTargetList.mItemCount = mList.mItemCount;
   11861                 :   memcpy(aTargetList.mDesiredParentCounts, mList.mDesiredParentCounts,
   11862               0 :          sizeof(aTargetList.mDesiredParentCounts));
   11863                 : 
   11864                 :   // reset mList
   11865               0 :   new (&mList) FrameConstructionItemList();
   11866                 : 
   11867                 :   // Point ourselves to aEnd, as advertised
   11868               0 :   mCurrent = mEnd = &mList.mItems;
   11869               0 :   NS_POSTCONDITION(*this == aEnd, "How did that happen?");
   11870                 : }
   11871                 : 
   11872                 : void
   11873               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11874                 : Iterator::InsertItem(FrameConstructionItem* aItem)
   11875                 : {
   11876                 :   // Just insert the item before us.  There's no magic here.
   11877               0 :   PR_INSERT_BEFORE(aItem, mCurrent);
   11878               0 :   mList.AdjustCountsForItem(aItem, 1);
   11879                 : 
   11880               0 :   NS_POSTCONDITION(PR_NEXT_LINK(aItem) == mCurrent, "How did that happen?");
   11881               0 : }
   11882                 : 
   11883                 : void
   11884               0 : nsCSSFrameConstructor::FrameConstructionItemList::
   11885                 : Iterator::DeleteItemsTo(const Iterator& aEnd)
   11886                 : {
   11887               0 :   NS_PRECONDITION(mEnd == aEnd.mEnd, "end iterator for some other list?");
   11888               0 :   NS_PRECONDITION(*this != aEnd, "Shouldn't be at aEnd yet");
   11889                 : 
   11890               0 :   do {
   11891               0 :     NS_ASSERTION(!IsDone(), "Ran off end of list?");
   11892               0 :     FrameConstructionItem* item = ToItem(mCurrent);
   11893               0 :     Next();
   11894               0 :     PR_REMOVE_LINK(item);
   11895               0 :     mList.AdjustCountsForItem(item, -1);
   11896               0 :     delete item;
   11897                 :   } while (*this != aEnd);
   11898               0 : }

Generated by: LCOV version 1.7