diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index cb77658aea2..5cd1bf8a503 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -698,6 +698,8 @@ struct nsFrameItems { // Appends the frame to the end of the list void AddChild(nsIFrame* aChild); + // Remove the frame from the list, return PR_FALSE if not found. + PRBool RemoveChild(nsIFrame* aChild); }; nsFrameItems::nsFrameItems(nsIFrame* aFrame) @@ -730,6 +732,30 @@ nsFrameItems::AddChild(nsIFrame* aChild) } } +PRBool +nsFrameItems::RemoveChild(nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null ptr"); + nsIFrame* prev = nsnull; + nsIFrame* sib = childList; + for (; sib && sib != aFrame; sib = sib->GetNextSibling()) { + prev = sib; + } + if (!sib) { + return PR_FALSE; + } + if (sib == childList) { + childList = sib->GetNextSibling(); + } else { + prev->SetNextSibling(sib->GetNextSibling()); + } + if (sib == lastChild) { + lastChild = prev; + } + sib->SetNextSibling(nsnull); + return PR_TRUE; +} + // ----------------------------------------------------------- // Structure used when constructing formatting object trees. Contains @@ -1556,33 +1582,40 @@ PRBool IsBorderCollapse(nsIFrame* aFrame) */ static void AdjustFloatParentPtrs(nsIFrame* aFrame, - nsFrameConstructorState& aState) + nsFrameConstructorState& aState, + nsFrameConstructorState& aOuterState) { + NS_PRECONDITION(aFrame, "must have frame to work with"); + nsIFrame *outOfFlowFrame = nsPlaceholderFrame::GetRealFrameFor(aFrame); - - if (outOfFlowFrame && outOfFlowFrame != aFrame) { - - // Get the display data for the outOfFlowFrame so we can - // figure out if it is a float. - + if (outOfFlowFrame != aFrame) { if (outOfFlowFrame->GetStyleDisplay()->IsFloating()) { - // Update the parent pointer for outOfFlowFrame if it's - // containing block has changed as the result of reparenting, + // Update the parent pointer for outOfFlowFrame since its + // containing block has changed as the result of reparenting + // and move it from the outer state to the inner, bug 307277. nsIFrame *parent = aState.mFloatedItems.containingBlock; NS_ASSERTION(parent, "Should have float containing block here!"); + NS_ASSERTION(outOfFlowFrame->GetParent() == aOuterState.mFloatedItems.containingBlock, + "expected the float to be a child of the outer CB"); + + if (aOuterState.mFloatedItems.RemoveChild(outOfFlowFrame)) { + aState.mFloatedItems.AddChild(outOfFlowFrame); + } else { + NS_NOTREACHED("float wasn't in the outer state float list"); + } + outOfFlowFrame->SetParent(parent); if (outOfFlowFrame->GetStateBits() & (NS_FRAME_HAS_VIEW | NS_FRAME_HAS_CHILD_WITH_VIEW)) { // We don't need to walk up the tree, since each level of - // recursion of the SplitToContainingBlock will propagate the - // bit. + // recursion of the SplitToContainingBlock will propagate the bit. parent->AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW); } } // All out-of-flows are automatically float containing blocks, so we're - // done here + // done here. return; } @@ -1594,14 +1627,11 @@ AdjustFloatParentPtrs(nsIFrame* aFrame, // Dive down into children to see if any of their // placeholders need adjusting. - nsIFrame *childFrame = aFrame->GetFirstChild(nsnull); - - while (childFrame) - { + while (childFrame) { // XXX_kin: Do we need to prevent descent into anonymous content here? - AdjustFloatParentPtrs(childFrame, aState); + AdjustFloatParentPtrs(childFrame, aState, aOuterState); childFrame = childFrame->GetNextSibling(); } } @@ -1618,7 +1648,8 @@ MoveChildrenTo(nsFrameManager* aFrameManager, nsStyleContext* aNewParentSC, nsIFrame* aNewParent, nsIFrame* aFrameList, - nsFrameConstructorState* aState) + nsFrameConstructorState* aState, + nsFrameConstructorState* aOuterState) { PRBool setHasChildWithView = PR_FALSE; @@ -1633,8 +1664,10 @@ MoveChildrenTo(nsFrameManager* aFrameManager, // If aState is not null, the caller expects us to make adjustments so that // floats whose placeholders are descendants of frames in aFrameList point // to the correct parent. - if (aState) - AdjustFloatParentPtrs(aFrameList, *aState); + if (aState) { + NS_ASSERTION(aOuterState, "need an outer state too"); + AdjustFloatParentPtrs(aFrameList, *aState, *aOuterState); + } #if 0 // XXX When this is used with {ib} frame hierarchies, it seems @@ -12981,13 +13014,12 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, GetAbsoluteContainingBlock(blockFrame), GetFloatContainingBlock(blockFrame)); - // XXXbz MoveChildrenTo just sets parent pointers on the out-of-flows! - // Shouldn't it move the frames to the right child list too? Right now, if - // we have an inline between two blocks all inside an inline and the inner + // If we have an inline between two blocks all inside an inline and the inner // inline contains a float, the float will end up in the float list of the // parent block of the inline, but its parent pointer will be the anonymous - // block we create.... - MoveChildrenTo(state.mFrameManager, blockSC, blockFrame, list2, &state); + // block we create... AdjustFloatParentPtrs() deals with this by moving the + // float from the outer state |aState| to the inner |state|. + MoveChildrenTo(state.mFrameManager, blockSC, blockFrame, list2, &state, &aState); // list3's frames belong to another inline frame nsIFrame* inlineFrame = nsnull; @@ -13016,7 +13048,7 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, // Reparent (cheaply) the frames in list3 - we don't have to futz // with their style context because they already have the right one. inlineFrame->SetInitialChildList(aState.mPresContext, nsnull, list3); - MoveChildrenTo(aState.mFrameManager, nsnull, inlineFrame, list3, nsnull); + MoveChildrenTo(aState.mFrameManager, nsnull, inlineFrame, list3, nsnull, nsnull); } // Mark the 3 frames as special. That way if any of the @@ -13396,7 +13428,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsFrameConstructorState& aState, blockFrame->SetInitialChildList(aState.mPresContext, nsnull, aBlockChildFrame); MoveChildrenTo(aState.mFrameManager, blockSC, blockFrame, aBlockChildFrame, - nsnull); + nsnull, nsnull); // Create an anonymous inline frame that will parent // aRightInlineChildFrame. The new frame won't have a parent yet: @@ -13413,7 +13445,7 @@ nsCSSFrameConstructor::SplitToContainingBlock(nsFrameConstructorState& aState, inlineFrame->SetInitialChildList(aState.mPresContext, nsnull, aRightInlineChildFrame); MoveChildrenTo(aState.mFrameManager, nsnull, inlineFrame, - aRightInlineChildFrame, nsnull); + aRightInlineChildFrame, nsnull, nsnull); // Make the "special" inline-block linkage between aFrame and the // newly created anonymous frames. We need to create the linkage