diff --git a/mozilla/content/html/content/src/nsHTMLTableElement.cpp b/mozilla/content/html/content/src/nsHTMLTableElement.cpp index 4b45e6f5dd1..35b74089c2a 100644 --- a/mozilla/content/html/content/src/nsHTMLTableElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTableElement.cpp @@ -1117,11 +1117,17 @@ MapAttributesInto(const nsIHTMLMappedAttributes* aAttributes, aContext->GetMutableStyleData(eStyleStruct_Position); switch (value.GetUnit()) { case eHTMLUnit_Percent: - position->mWidth.SetPercentValue(value.GetPercentValue()); + // 0 width remains default auto + //if (value.GetPercentValue() > 0.0f) { + position->mWidth.SetPercentValue(value.GetPercentValue()); + //} break; case eHTMLUnit_Pixel: - position->mWidth.SetCoordValue(NSIntPixelsToTwips(value.GetPixelValue(), sp2t)); + // 0 width remains default auto + //if (value.GetPixelValue() > 0) { + position->mWidth.SetCoordValue(NSIntPixelsToTwips(value.GetPixelValue(), sp2t)); + //} break; default: break; diff --git a/mozilla/content/shared/public/nsLayoutAtomList.h b/mozilla/content/shared/public/nsLayoutAtomList.h index c584e5b8552..6c416edadba 100644 --- a/mozilla/content/shared/public/nsLayoutAtomList.h +++ b/mozilla/content/shared/public/nsLayoutAtomList.h @@ -59,6 +59,7 @@ LAYOUT_ATOM(xmlnsNameSpace, "xmlns") // Alphabetical list of frame additional child list names LAYOUT_ATOM(absoluteList, "Absolute-list") LAYOUT_ATOM(bulletList, "Bullet-list") +LAYOUT_ATOM(captionList, "Caption-list") LAYOUT_ATOM(colGroupList, "ColGroup-list") LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List") LAYOUT_ATOM(fixedList, "Fixed-list") @@ -96,6 +97,7 @@ LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame") LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame") LAYOUT_ATOM(rootFrame, "RootFrame") LAYOUT_ATOM(scrollFrame, "ScrollFrame") +LAYOUT_ATOM(tableCaptionFrame, "TableCaptionFrame") LAYOUT_ATOM(tableCellFrame, "TableCellFrame") LAYOUT_ATOM(tableColFrame, "TableColFrame") LAYOUT_ATOM(tableColGroupFrame, "TableColGroupFrame") diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 65f9d146b1c..6c8021bc224 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -518,6 +518,19 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame) // ----------------------------------------------------------- +// return the child list that aFrame belongs on. does not ADDREF +nsIAtom* GetChildListFor(const nsIFrame* aFrame) +{ + nsIAtom* childList = nsnull; + nsIAtom* frameType; + aFrame->GetFrameType(&frameType); + if (nsLayoutAtoms::tableCaptionFrame == frameType) { + childList = nsLayoutAtoms::captionList; + } + NS_IF_RELEASE(frameType); + return childList; +} + nsCSSFrameConstructor::nsCSSFrameConstructor(void) : nsIStyleFrameConstruction(), mDocument(nsnull), @@ -1067,15 +1080,6 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, #endif // Create the inner table frame aTableCreator.CreateTableFrame(&innerFrame); - - // This gets reset later, since there may also be a caption. - // It allows descendants to get at the inner frame before that - // XXX This is very wrong. You cannot call SetInitialChildList() more - // than once (see the nsIFrame header file). Either call it once only, - // _or_ move the caption out into a separate named child list... - // XXX The other things that's wrong here is that the calls to - // SetInitialChildList() are bottom-up, and the order is wrong... - aNewFrame->SetInitialChildList(aPresContext, nsnull, innerFrame); childList = innerFrame; InitAndRestoreFrame(aPresContext, aState, aContent, @@ -1164,11 +1168,14 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, } } - // Set the inner table frame's list of initial child frames + // Set the inner table frame's initial primary list innerFrame->SetInitialChildList(aPresContext, nsnull, innerChildList); - // Set the anonymous table outer frame's initial child list + // Set the outer table frame's primary and option lists aNewFrame->SetInitialChildList(aPresContext, nsnull, childList); + if (captionFrame) { + aNewFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::captionList, captionFrame); + } return rv; } @@ -1287,7 +1294,7 @@ nsCSSFrameConstructor::ConstructAnonymousTableFrame(nsIPresShell* aPresSh InitAndRestoreFrame(aPresContext, aState, aContent, aOuterFrame, innerStyleContext, nsnull, aInnerFrame); - //XXX duplicated call here + //XXX when bug 2479 is fixed this may be a duplicate call aOuterFrame->SetInitialChildList(aPresContext, nsnull, aInnerFrame); if (cellIsParent) { @@ -1315,28 +1322,17 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres if (NS_FAILED(rv)) return rv; const nsStyleDisplay* parentDisplay = GetDisplay(aParentFrame); - nsIFrame* innerFrame; + nsIFrame* outerFrame = aParentFrame; if (NS_STYLE_DISPLAY_TABLE == parentDisplay->mDisplay) { // parent is an outer table - // determine the inner table frame, it is either aParentFrame or its first child - nsIFrame* parFrame = aParentFrame; - aParentFrame->FirstChild(aPresContext, nsnull, &innerFrame); - const nsStyleDisplay* innerDisplay; - innerFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)innerDisplay); - if (NS_STYLE_DISPLAY_TABLE != innerDisplay->mDisplay) { - innerFrame = aParentFrame; - innerFrame->GetParent(&parFrame); - } - InitAndRestoreFrame(aPresContext, aState, aContent, - parFrame, aStyleContext, nsnull, aNewCaptionFrame); + aParentFrame, aStyleContext, nsnull, aNewCaptionFrame); - innerFrame->SetNextSibling(aNewCaptionFrame); - // the caller is responsible for calling SetInitialChildList on the outer, inner frames + // the caller is responsible for calling SetInitialChildList aNewTopFrame = aNewCaptionFrame; } else { // parent is not a table, need to create a new table //NS_WARNING("a non table contains a table caption child. \n"); - nsIFrame* outerFrame; + nsIFrame* innerFrame; ConstructAnonymousTableFrame(aPresShell, aPresContext, aState, aContent, aParentFrame, aNewTopFrame, outerFrame, innerFrame, aTableCreator); nsCOMPtr outerStyleContext; @@ -1346,9 +1342,6 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres PR_FALSE, getter_AddRefs(adjStyleContext)); InitAndRestoreFrame(aPresContext, aState, aContent, outerFrame, adjStyleContext, nsnull, aNewCaptionFrame); - innerFrame->SetNextSibling(aNewCaptionFrame); - //XXX duplicated call here - outerFrame->SetInitialChildList(aPresContext, nsnull, innerFrame); } // The caption frame is a floater container @@ -1372,6 +1365,11 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres aState.mFloatedItems.childList); } + if (outerFrame) { + outerFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::captionList, + aNewCaptionFrame); + } + return rv; } @@ -1601,13 +1599,13 @@ nsCSSFrameConstructor::ConstructTableRowFrame(nsIPresShell* aPresShell, contentDisplayIsRow, aNewRowFrame, aTableCreator); if (NS_FAILED(rv)) return rv; + //XXX when bug 2479 is fixed this may be a duplicate call groupFrame->SetInitialChildList(aPresContext, nsnull, aNewRowFrame); if (contentDisplayIsRow) { // called from above // set the primary frame to avoid getting the anonymous row group frame aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewRowFrame); } - groupFrame->SetInitialChildList(aPresContext, nsnull, aNewRowFrame); if (contentDisplayIsRow) { // called from above TableProcessTableList(aPresContext, *toDo); } @@ -1680,6 +1678,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel styleContext, aNewColFrame, aTableCreator); if (NS_FAILED(rv)) return rv; aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewColFrame); + //XXX when bug 2479 is fixed this may be a duplicate call groupFrame->SetInitialChildList(aPresContext, nsnull, aNewColFrame); // if an anoymous table got created, then set its initial child list @@ -1776,6 +1775,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShell, styleContext, aNewCellFrame, aNewCellBodyFrame, aTableCreator, aProcessChildren); if (NS_FAILED(rv)) return rv; + //XXX when bug 2479 is fixed this may be a duplicate call rowFrame->SetInitialChildList(aPresContext, nsnull, aNewCellFrame); TableProcessTableList(aPresContext, toDo); } @@ -5755,6 +5755,8 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, aFrameList); } + nsresult rv = NS_OK; + // a col group or col appended to a table may result in an insert rather than an append nsIAtom* parentType; aParentFrame->GetFrameType(&parentType); @@ -5763,30 +5765,45 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, nsIAtom* childType; aFrameList->GetFrameType(&childType); if (nsLayoutAtoms::tableColFrame == childType) { + // table column nsIFrame* parentFrame = aParentFrame; aFrameList->GetParent(&parentFrame); - return aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame, - nsLayoutAtoms::colGroupList, aFrameList); + NS_RELEASE(childType); + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame, + nsLayoutAtoms::colGroupList, aFrameList); } else if (nsLayoutAtoms::tableColGroupFrame == childType) { + // table col group nsIFrame* prevSibling; PRBool doAppend = nsTableColGroupFrame::GetLastRealColGroup(tableFrame, &prevSibling); if (doAppend) { - return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, - nsLayoutAtoms::colGroupList, aFrameList); + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::colGroupList, aFrameList); } else { - return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, - nsLayoutAtoms::colGroupList, prevSibling, aFrameList); + rv = aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::colGroupList, prevSibling, aFrameList); } } + else if (nsLayoutAtoms::tableCaptionFrame == childType) { + // table caption + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::captionList, aFrameList); + } + else { + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, aFrameList); + } NS_IF_RELEASE(childType); } + else { + // Append the frames to the end of the parent's child list + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, aFrameList); + } NS_IF_RELEASE(parentType); - // Append the frames to the end of the parent's child list - return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, - nsnull, aFrameList); + return rv; } static nsIFrame* @@ -6529,10 +6546,11 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, prevSibling = firstChild; } } - + // check for a table caption which goes on an additional child list + nsIAtom* childList = GetChildListFor(newFrame); rv = state.mFrameManager->InsertFrames(aPresContext, *shell, parentFrame, - nsnull, prevSibling, + childList, prevSibling, newFrame); } @@ -7021,8 +7039,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, } else { // Notify the parent frame that it should delete the frame + nsIAtom* childList = GetChildListFor(childFrame); rv = frameManager->RemoveFrame(aPresContext, *shell, parentFrame, - nsnull, childFrame); + childList, childFrame); } } diff --git a/mozilla/layout/base/nsLayoutAtomList.h b/mozilla/layout/base/nsLayoutAtomList.h index c584e5b8552..6c416edadba 100644 --- a/mozilla/layout/base/nsLayoutAtomList.h +++ b/mozilla/layout/base/nsLayoutAtomList.h @@ -59,6 +59,7 @@ LAYOUT_ATOM(xmlnsNameSpace, "xmlns") // Alphabetical list of frame additional child list names LAYOUT_ATOM(absoluteList, "Absolute-list") LAYOUT_ATOM(bulletList, "Bullet-list") +LAYOUT_ATOM(captionList, "Caption-list") LAYOUT_ATOM(colGroupList, "ColGroup-list") LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List") LAYOUT_ATOM(fixedList, "Fixed-list") @@ -96,6 +97,7 @@ LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame") LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame") LAYOUT_ATOM(rootFrame, "RootFrame") LAYOUT_ATOM(scrollFrame, "ScrollFrame") +LAYOUT_ATOM(tableCaptionFrame, "TableCaptionFrame") LAYOUT_ATOM(tableCellFrame, "TableCellFrame") LAYOUT_ATOM(tableColFrame, "TableColFrame") LAYOUT_ATOM(tableColGroupFrame, "TableColGroupFrame") diff --git a/mozilla/layout/base/public/nsLayoutAtomList.h b/mozilla/layout/base/public/nsLayoutAtomList.h index c584e5b8552..6c416edadba 100644 --- a/mozilla/layout/base/public/nsLayoutAtomList.h +++ b/mozilla/layout/base/public/nsLayoutAtomList.h @@ -59,6 +59,7 @@ LAYOUT_ATOM(xmlnsNameSpace, "xmlns") // Alphabetical list of frame additional child list names LAYOUT_ATOM(absoluteList, "Absolute-list") LAYOUT_ATOM(bulletList, "Bullet-list") +LAYOUT_ATOM(captionList, "Caption-list") LAYOUT_ATOM(colGroupList, "ColGroup-list") LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List") LAYOUT_ATOM(fixedList, "Fixed-list") @@ -96,6 +97,7 @@ LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame") LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame") LAYOUT_ATOM(rootFrame, "RootFrame") LAYOUT_ATOM(scrollFrame, "ScrollFrame") +LAYOUT_ATOM(tableCaptionFrame, "TableCaptionFrame") LAYOUT_ATOM(tableCellFrame, "TableCellFrame") LAYOUT_ATOM(tableColFrame, "TableColFrame") LAYOUT_ATOM(tableColGroupFrame, "TableColGroupFrame") diff --git a/mozilla/layout/generic/nsHTMLParts.h b/mozilla/layout/generic/nsHTMLParts.h index 7e631aca51e..dd31d3f80a8 100644 --- a/mozilla/layout/generic/nsHTMLParts.h +++ b/mozilla/layout/generic/nsHTMLParts.h @@ -280,9 +280,6 @@ extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, inline nsresult NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { return NS_NewBlockFrame(aPresShell, aNewFrame, NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); } -inline nsresult NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { - return NS_NewBlockFrame(aPresShell, aNewFrame, NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); -} // This type of AreaFrame is the document root, a margin root, and the // initial containing block for absolutely positioned elements @@ -359,6 +356,8 @@ extern nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** // Table frame factories extern nsresult NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableFrame(nsIPresShell* aPresShell, nsIFrame** aResult); +extern nsresult NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + extern nsresult NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableRowFrame(nsIPresShell* aPresShell, nsIFrame** aResult); diff --git a/mozilla/layout/html/base/src/nsHTMLParts.h b/mozilla/layout/html/base/src/nsHTMLParts.h index 7e631aca51e..dd31d3f80a8 100644 --- a/mozilla/layout/html/base/src/nsHTMLParts.h +++ b/mozilla/layout/html/base/src/nsHTMLParts.h @@ -280,9 +280,6 @@ extern nsresult NS_NewAreaFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, inline nsresult NS_NewTableCellInnerFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { return NS_NewBlockFrame(aPresShell, aNewFrame, NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); } -inline nsresult NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { - return NS_NewBlockFrame(aPresShell, aNewFrame, NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); -} // This type of AreaFrame is the document root, a margin root, and the // initial containing block for absolutely positioned elements @@ -359,6 +356,8 @@ extern nsresult NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsIFrame** // Table frame factories extern nsresult NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableFrame(nsIPresShell* aPresShell, nsIFrame** aResult); +extern nsresult NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame); + extern nsresult NS_NewTableColFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsIFrame** aResult); extern nsresult NS_NewTableRowFrame(nsIPresShell* aPresShell, nsIFrame** aResult); diff --git a/mozilla/layout/html/content/src/nsHTMLTableElement.cpp b/mozilla/layout/html/content/src/nsHTMLTableElement.cpp index 4b45e6f5dd1..35b74089c2a 100644 --- a/mozilla/layout/html/content/src/nsHTMLTableElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLTableElement.cpp @@ -1117,11 +1117,17 @@ MapAttributesInto(const nsIHTMLMappedAttributes* aAttributes, aContext->GetMutableStyleData(eStyleStruct_Position); switch (value.GetUnit()) { case eHTMLUnit_Percent: - position->mWidth.SetPercentValue(value.GetPercentValue()); + // 0 width remains default auto + //if (value.GetPercentValue() > 0.0f) { + position->mWidth.SetPercentValue(value.GetPercentValue()); + //} break; case eHTMLUnit_Pixel: - position->mWidth.SetCoordValue(NSIntPixelsToTwips(value.GetPixelValue(), sp2t)); + // 0 width remains default auto + //if (value.GetPixelValue() > 0) { + position->mWidth.SetCoordValue(NSIntPixelsToTwips(value.GetPixelValue(), sp2t)); + //} break; default: break; diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 65f9d146b1c..6c8021bc224 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -518,6 +518,19 @@ nsMathMLmtableCreator::CreateTableCellInnerFrame(nsIFrame** aNewFrame) // ----------------------------------------------------------- +// return the child list that aFrame belongs on. does not ADDREF +nsIAtom* GetChildListFor(const nsIFrame* aFrame) +{ + nsIAtom* childList = nsnull; + nsIAtom* frameType; + aFrame->GetFrameType(&frameType); + if (nsLayoutAtoms::tableCaptionFrame == frameType) { + childList = nsLayoutAtoms::captionList; + } + NS_IF_RELEASE(frameType); + return childList; +} + nsCSSFrameConstructor::nsCSSFrameConstructor(void) : nsIStyleFrameConstruction(), mDocument(nsnull), @@ -1067,15 +1080,6 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, #endif // Create the inner table frame aTableCreator.CreateTableFrame(&innerFrame); - - // This gets reset later, since there may also be a caption. - // It allows descendants to get at the inner frame before that - // XXX This is very wrong. You cannot call SetInitialChildList() more - // than once (see the nsIFrame header file). Either call it once only, - // _or_ move the caption out into a separate named child list... - // XXX The other things that's wrong here is that the calls to - // SetInitialChildList() are bottom-up, and the order is wrong... - aNewFrame->SetInitialChildList(aPresContext, nsnull, innerFrame); childList = innerFrame; InitAndRestoreFrame(aPresContext, aState, aContent, @@ -1164,11 +1168,14 @@ nsCSSFrameConstructor::ConstructTableFrame(nsIPresShell* aPresShell, } } - // Set the inner table frame's list of initial child frames + // Set the inner table frame's initial primary list innerFrame->SetInitialChildList(aPresContext, nsnull, innerChildList); - // Set the anonymous table outer frame's initial child list + // Set the outer table frame's primary and option lists aNewFrame->SetInitialChildList(aPresContext, nsnull, childList); + if (captionFrame) { + aNewFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::captionList, captionFrame); + } return rv; } @@ -1287,7 +1294,7 @@ nsCSSFrameConstructor::ConstructAnonymousTableFrame(nsIPresShell* aPresSh InitAndRestoreFrame(aPresContext, aState, aContent, aOuterFrame, innerStyleContext, nsnull, aInnerFrame); - //XXX duplicated call here + //XXX when bug 2479 is fixed this may be a duplicate call aOuterFrame->SetInitialChildList(aPresContext, nsnull, aInnerFrame); if (cellIsParent) { @@ -1315,28 +1322,17 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres if (NS_FAILED(rv)) return rv; const nsStyleDisplay* parentDisplay = GetDisplay(aParentFrame); - nsIFrame* innerFrame; + nsIFrame* outerFrame = aParentFrame; if (NS_STYLE_DISPLAY_TABLE == parentDisplay->mDisplay) { // parent is an outer table - // determine the inner table frame, it is either aParentFrame or its first child - nsIFrame* parFrame = aParentFrame; - aParentFrame->FirstChild(aPresContext, nsnull, &innerFrame); - const nsStyleDisplay* innerDisplay; - innerFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)innerDisplay); - if (NS_STYLE_DISPLAY_TABLE != innerDisplay->mDisplay) { - innerFrame = aParentFrame; - innerFrame->GetParent(&parFrame); - } - InitAndRestoreFrame(aPresContext, aState, aContent, - parFrame, aStyleContext, nsnull, aNewCaptionFrame); + aParentFrame, aStyleContext, nsnull, aNewCaptionFrame); - innerFrame->SetNextSibling(aNewCaptionFrame); - // the caller is responsible for calling SetInitialChildList on the outer, inner frames + // the caller is responsible for calling SetInitialChildList aNewTopFrame = aNewCaptionFrame; } else { // parent is not a table, need to create a new table //NS_WARNING("a non table contains a table caption child. \n"); - nsIFrame* outerFrame; + nsIFrame* innerFrame; ConstructAnonymousTableFrame(aPresShell, aPresContext, aState, aContent, aParentFrame, aNewTopFrame, outerFrame, innerFrame, aTableCreator); nsCOMPtr outerStyleContext; @@ -1346,9 +1342,6 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres PR_FALSE, getter_AddRefs(adjStyleContext)); InitAndRestoreFrame(aPresContext, aState, aContent, outerFrame, adjStyleContext, nsnull, aNewCaptionFrame); - innerFrame->SetNextSibling(aNewCaptionFrame); - //XXX duplicated call here - outerFrame->SetInitialChildList(aPresContext, nsnull, innerFrame); } // The caption frame is a floater container @@ -1372,6 +1365,11 @@ nsCSSFrameConstructor::ConstructTableCaptionFrame(nsIPresShell* aPres aState.mFloatedItems.childList); } + if (outerFrame) { + outerFrame->SetInitialChildList(aPresContext, nsLayoutAtoms::captionList, + aNewCaptionFrame); + } + return rv; } @@ -1601,13 +1599,13 @@ nsCSSFrameConstructor::ConstructTableRowFrame(nsIPresShell* aPresShell, contentDisplayIsRow, aNewRowFrame, aTableCreator); if (NS_FAILED(rv)) return rv; + //XXX when bug 2479 is fixed this may be a duplicate call groupFrame->SetInitialChildList(aPresContext, nsnull, aNewRowFrame); if (contentDisplayIsRow) { // called from above // set the primary frame to avoid getting the anonymous row group frame aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewRowFrame); } - groupFrame->SetInitialChildList(aPresContext, nsnull, aNewRowFrame); if (contentDisplayIsRow) { // called from above TableProcessTableList(aPresContext, *toDo); } @@ -1680,6 +1678,7 @@ nsCSSFrameConstructor::ConstructTableColFrame(nsIPresShell* aPresShel styleContext, aNewColFrame, aTableCreator); if (NS_FAILED(rv)) return rv; aState.mFrameManager->SetPrimaryFrameFor(aContent, aNewColFrame); + //XXX when bug 2479 is fixed this may be a duplicate call groupFrame->SetInitialChildList(aPresContext, nsnull, aNewColFrame); // if an anoymous table got created, then set its initial child list @@ -1776,6 +1775,7 @@ nsCSSFrameConstructor::ConstructTableCellFrame(nsIPresShell* aPresShell, styleContext, aNewCellFrame, aNewCellBodyFrame, aTableCreator, aProcessChildren); if (NS_FAILED(rv)) return rv; + //XXX when bug 2479 is fixed this may be a duplicate call rowFrame->SetInitialChildList(aPresContext, nsnull, aNewCellFrame); TableProcessTableList(aPresContext, toDo); } @@ -5755,6 +5755,8 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, aFrameList); } + nsresult rv = NS_OK; + // a col group or col appended to a table may result in an insert rather than an append nsIAtom* parentType; aParentFrame->GetFrameType(&parentType); @@ -5763,30 +5765,45 @@ nsCSSFrameConstructor::AppendFrames(nsIPresContext* aPresContext, nsIAtom* childType; aFrameList->GetFrameType(&childType); if (nsLayoutAtoms::tableColFrame == childType) { + // table column nsIFrame* parentFrame = aParentFrame; aFrameList->GetParent(&parentFrame); - return aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame, - nsLayoutAtoms::colGroupList, aFrameList); + NS_RELEASE(childType); + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, parentFrame, + nsLayoutAtoms::colGroupList, aFrameList); } else if (nsLayoutAtoms::tableColGroupFrame == childType) { + // table col group nsIFrame* prevSibling; PRBool doAppend = nsTableColGroupFrame::GetLastRealColGroup(tableFrame, &prevSibling); if (doAppend) { - return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, - nsLayoutAtoms::colGroupList, aFrameList); + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::colGroupList, aFrameList); } else { - return aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, - nsLayoutAtoms::colGroupList, prevSibling, aFrameList); + rv = aFrameManager->InsertFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::colGroupList, prevSibling, aFrameList); } } + else if (nsLayoutAtoms::tableCaptionFrame == childType) { + // table caption + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsLayoutAtoms::captionList, aFrameList); + } + else { + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, aFrameList); + } NS_IF_RELEASE(childType); } + else { + // Append the frames to the end of the parent's child list + rv = aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, + nsnull, aFrameList); + } NS_IF_RELEASE(parentType); - // Append the frames to the end of the parent's child list - return aFrameManager->AppendFrames(aPresContext, *aPresShell, aParentFrame, - nsnull, aFrameList); + return rv; } static nsIFrame* @@ -6529,10 +6546,11 @@ nsCSSFrameConstructor::ContentInserted(nsIPresContext* aPresContext, prevSibling = firstChild; } } - + // check for a table caption which goes on an additional child list + nsIAtom* childList = GetChildListFor(newFrame); rv = state.mFrameManager->InsertFrames(aPresContext, *shell, parentFrame, - nsnull, prevSibling, + childList, prevSibling, newFrame); } @@ -7021,8 +7039,9 @@ nsCSSFrameConstructor::ContentRemoved(nsIPresContext* aPresContext, } else { // Notify the parent frame that it should delete the frame + nsIAtom* childList = GetChildListFor(childFrame); rv = frameManager->RemoveFrame(aPresContext, *shell, parentFrame, - nsnull, childFrame); + childList, childFrame); } } diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index ab088eeafe6..eeeac9c2ba3 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -691,22 +691,20 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, DebugCheckChildSize(firstKid, kidSize, availSize, (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)); #endif - PRBool useInsets = PR_TRUE; // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode // see testcase "emptyCells.html" - if (NS_UNCONSTRAINEDSIZE == kidReflowState.availableWidth) { - if ((0 == kidSize.width) || (0 == kidSize.height)) { - //if ((0 == kidSize.width) && (0 == kidSize.height)) { // XXX why was this && - SetContentEmpty(PR_TRUE); - useInsets = PR_FALSE; + if ((0 == kidSize.width) || (0 == kidSize.height)) { // XXX why was this && + SetContentEmpty(PR_TRUE); + if (NS_UNCONSTRAINEDSIZE == kidReflowState.availableWidth) { // need to reduce the insets by border if the cell is empty leftInset -= border.left; rightInset -= border.right; topInset -= border.top; bottomInset -= border.bottom; } - else - SetContentEmpty(PR_FALSE); + } + else { + SetContentEmpty(PR_FALSE); } const nsStylePosition* pos; diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index a280179bd91..83575485286 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -58,6 +58,7 @@ #include "nsIDOMHTMLBodyElement.h" #include "nsISizeOfHandler.h" #include "nsIScrollableFrame.h" +#include "nsHTMLReflowCommand.h" NS_DEF_PTR(nsIStyleContext); NS_DEF_PTR(nsIContent); @@ -84,6 +85,8 @@ PRBool nsDebugTable::gRflRow = PR_TRUE; PRBool nsDebugTable::gRflCell = PR_TRUE; PRBool nsDebugTable::gRflArea = PR_TRUE; #endif +static PRInt32 gRflCount = 0; + /* ----------- InnerTableReflowState ---------- */ struct InnerTableReflowState { @@ -4678,7 +4681,11 @@ void nsTableFrame::DebugReflow(char* aMessage, printf("rea=%d av=(%s,%s) ", aState->reason, width, height); PrettyUC(aState->mComputedWidth, width); PrettyUC(aState->mComputedHeight, height); - printf("comp=(%s,%s) \n", width, height); + printf("comp=(%s,%s) count=%d \n", width, height, gRflCount); + gRflCount++; + //if (32 == gRflCount) { + // NS_ASSERTION(PR_FALSE, "stop"); + //} } if (aMetrics) { if (aState) { diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp index d8082427efb..abfe42508a5 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp @@ -36,6 +36,42 @@ #include "nsHTMLParts.h" #include "nsIPresShell.h" +#define NS_TABLE_FRAME_CAPTION_LIST_INDEX 0 + +// caption frame +nsTableCaptionFrame::nsTableCaptionFrame() +{ + // shrink wrap + SetFlags(NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); +} + +NS_IMETHODIMP +nsTableCaptionFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::tableCaptionFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +nsresult +NS_NewTableCaptionFrame(nsIPresShell* aPresShell, + nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsTableCaptionFrame* it = new (aPresShell) nsTableCaptionFrame; + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aNewFrame = it; + return NS_OK; +} + +// OuterTableReflowState + struct OuterTableReflowState { // The presentation context @@ -101,28 +137,81 @@ nsresult nsTableOuterFrame::QueryInterface(const nsIID& aIID, void** aInstancePt } } -NS_IMETHODIMP nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext, - nsIAtom* aListName, - nsIFrame* aChildList) +NS_IMETHODIMP +nsTableOuterFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { - mFrames.SetFrames(aChildList); + nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + if (NS_FAILED(rv) || !mStyleContext) return rv; - // Set our internal member data - mInnerTableFrame = aChildList; - //XXX this should go through the child list looking for a displaytype==caption - if (1 < mFrames.GetLength()) { - nsIFrame *child; - nsresult result = aChildList->GetNextSibling(&child); - while ((NS_SUCCEEDED(result)) && (nsnull!=child)) { - const nsStyleDisplay* childDisplay; - child->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)childDisplay); - if (NS_STYLE_DISPLAY_TABLE_CAPTION==childDisplay->mDisplay) { - mCaptionFrame = child; - break; - } - result = child->GetNextSibling(&child); +#if 0 + // a 0 width table becomes auto + PRBool makeAuto = PR_FALSE; + nsStylePosition* position = (nsStylePosition*)mStyleContext->GetMutableStyleData(eStyleStruct_Position); + if (position->mWidth.GetUnit() == eStyleUnit_Coord) { + if (0 >= position->mWidth.GetCoordValue()) { + makeAuto= PR_TRUE; } } + else if (position->mWidth.GetUnit() == eStyleUnit_Percent) { + if (0.0f >= position->mWidth.GetPercentValue()) { + makeAuto= PR_TRUE; + } + } + + if (makeAuto) { + position->mWidth = nsStyleCoord(eStyleUnit_Auto); + } +#endif + return rv; +} + +NS_IMETHODIMP +nsTableOuterFrame::FirstChild(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame** aFirstChild) const +{ + NS_PRECONDITION(nsnull != aFirstChild, "null OUT parameter pointer"); + *aFirstChild = (nsLayoutAtoms::captionList == aListName) + ? mCaptionFrame : mFrames.FirstChild(); + return NS_OK; +} + +NS_IMETHODIMP +nsTableOuterFrame::GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const +{ + NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer"); + if (aIndex < 0) { + return NS_ERROR_INVALID_ARG; + } + *aListName = nsnull; + switch (aIndex) { + case NS_TABLE_FRAME_CAPTION_LIST_INDEX: + *aListName = nsLayoutAtoms::captionList; + NS_ADDREF(*aListName); + break; + } + return NS_OK; +} + +NS_IMETHODIMP +nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + if (nsLayoutAtoms::captionList == aListName) { + // the frame constructor already checked for table-caption display type + mCaptionFrame = aChildList; + } + else { + mFrames.SetFrames(aChildList); + mInnerTableFrame = aChildList; + } return NS_OK; } @@ -133,22 +222,18 @@ nsTableOuterFrame::AppendFrames(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - const nsStyleDisplay* display; - nsresult rv; + nsresult rv; // We only have two child frames: the inner table and one caption frame. // The inner frame is provided when we're initialized, and it cannot change - aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); - if (NS_STYLE_DISPLAY_TABLE_CAPTION == display->mDisplay) { + if (nsLayoutAtoms::captionList == aListName) { NS_PRECONDITION(!mCaptionFrame, "already have a caption frame"); // We only support having a single caption frame if (mCaptionFrame || (LengthOf(aFrameList) > 1)) { rv = NS_ERROR_UNEXPECTED; - } else { // Insert the caption frame into the child list mCaptionFrame = aFrameList; - mInnerTableFrame->SetNextSibling(aFrameList); // Reflow the new caption frame. It's already marked dirty, so generate a reflow // command that tells us to reflow our dirty child frames @@ -186,14 +271,12 @@ nsTableOuterFrame::RemoveFrame(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - const nsStyleDisplay* display; - nsresult rv; + nsresult rv; // We only have two child frames: the inner table and one caption frame. // The inner frame can't be removed so this should be the caption - aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); - NS_PRECONDITION(NS_STYLE_DISPLAY_TABLE_CAPTION == display->mDisplay, - "can't remove inner frame"); + NS_PRECONDITION(nsLayoutAtoms::captionList == aListName, "can't remove inner frame"); + NS_PRECONDITION(aOldFrame == mCaptionFrame, "invalid caption frame"); // See if the caption's minimum width impacted the inner table if (mMinCaptionWidth > mRect.width) { @@ -205,10 +288,12 @@ nsTableOuterFrame::RemoveFrame(nsIPresContext* aPresContext, mInnerTableFrame->SetFrameState(frameState); } - // Remove the caption frame from the child list and destroy it - mFrames.DestroyFrame(aPresContext, aOldFrame); - mCaptionFrame = nsnull; - mMinCaptionWidth = 0; + // Remove the caption frame and destroy it + if (mCaptionFrame && (mCaptionFrame == aOldFrame)) { + mCaptionFrame->Destroy(aPresContext); + mCaptionFrame = nsnull; + mMinCaptionWidth = 0; + } // Generate a reflow command so we get reflowed nsIReflowCommand* reflowCmd; @@ -235,7 +320,37 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext* aPresContext, } #endif - PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + // the remaining code was copied from nsContainerFrame::PaintChildren since + // it only paints the primary child list + + const nsStyleDisplay* disp = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + + // Child elements have the opportunity to override the visibility property + // of their parent and display even if the parent is hidden + PRBool clipState; + + // If overflow is hidden then set the clip rect so that children + // don't leak out of us + if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(nsRect(0, 0, mRect.width, mRect.height), + nsClipCombine_kIntersect, clipState); + } + + if (mCaptionFrame) { + PaintChild(aPresContext, aRenderingContext, aDirtyRect, mCaptionFrame, aWhichLayer); + } + nsIFrame* kid = mFrames.FirstChild(); + while (nsnull != kid) { + PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid, aWhichLayer); + kid->GetNextSibling(&kid); + } + + if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + aRenderingContext.PopState(clipState); + } + return NS_OK; } @@ -344,8 +459,11 @@ nsresult nsTableOuterFrame::IR_TargetIsChild(nsIPresContext* aPresContext nsIFrame* aNextFrame) { nsresult rv; - if (!aNextFrame) + if (!aNextFrame) { + // this will force Reflow to return the height of the last reflow rather than 0 + aReflowState.y = mRect.height; return NS_OK; + } if (aNextFrame == mInnerTableFrame) { rv = IR_TargetIsInnerTableFrame(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -825,7 +943,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, { if (nsDebugTable::gRflTableOuter) nsTableFrame::DebugReflow("TO::Rfl en", this, &aReflowState, nsnull); nsresult rv = NS_OK; - // Initialize out parameters aDesiredSize.width = 0; aDesiredSize.height = 0; diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.h b/mozilla/layout/html/table/src/nsTableOuterFrame.h index 221b3c4e1a5..6a0a54f6caa 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.h +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.h @@ -24,11 +24,21 @@ #include "nscore.h" #include "nsHTMLContainerFrame.h" +#include "nsBlockFrame.h" #include "nsITableLayout.h" struct OuterTableReflowState; struct nsStyleTable; +class nsTableCaptionFrame : public nsBlockFrame +{ + public: + // nsISupports + nsTableCaptionFrame(); + NS_IMETHOD GetFrameType(nsIAtom** aType) const; +}; + + /* TODO 1. decide if we'll allow subclassing. If so, decide which methods really need to be virtual. */ @@ -53,11 +63,24 @@ public: friend nsresult NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsIFrame** aResult); + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); + /** @see nsIFrame::SetInitialChildList */ NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); + NS_IMETHOD FirstChild(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame** aFirstChild) const; + + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const; + NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -237,7 +260,7 @@ protected: private: /** used to keep track of this frame's children */ - nsIFrame *mInnerTableFrame; + nsIFrame *mInnerTableFrame; // XXX this is redundant, mFrames holds the same nsIFrame *mCaptionFrame; /** used to track caption max element size */ diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index c3c210af812..7a70fd82e52 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -803,10 +803,14 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext, // Newly inserted frame reason = eReflowReason_Initial; - // Use an unconstrained width so we can get the child's maximum - // width + // Use an unconstrained width so we can get the child's maximum width // XXX What about fixed layout tables? kidAvailSize.SizeTo(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // request to get the max element size if not already so + if (!kidMaxElementSize) { + kidMaxElementSize = &localKidMaxElementSize; + desiredSize.maxElementSize = kidMaxElementSize; + } } } diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index ab088eeafe6..eeeac9c2ba3 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -691,22 +691,20 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, DebugCheckChildSize(firstKid, kidSize, availSize, (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)); #endif - PRBool useInsets = PR_TRUE; // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode // see testcase "emptyCells.html" - if (NS_UNCONSTRAINEDSIZE == kidReflowState.availableWidth) { - if ((0 == kidSize.width) || (0 == kidSize.height)) { - //if ((0 == kidSize.width) && (0 == kidSize.height)) { // XXX why was this && - SetContentEmpty(PR_TRUE); - useInsets = PR_FALSE; + if ((0 == kidSize.width) || (0 == kidSize.height)) { // XXX why was this && + SetContentEmpty(PR_TRUE); + if (NS_UNCONSTRAINEDSIZE == kidReflowState.availableWidth) { // need to reduce the insets by border if the cell is empty leftInset -= border.left; rightInset -= border.right; topInset -= border.top; bottomInset -= border.bottom; } - else - SetContentEmpty(PR_FALSE); + } + else { + SetContentEmpty(PR_FALSE); } const nsStylePosition* pos; diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index a280179bd91..83575485286 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -58,6 +58,7 @@ #include "nsIDOMHTMLBodyElement.h" #include "nsISizeOfHandler.h" #include "nsIScrollableFrame.h" +#include "nsHTMLReflowCommand.h" NS_DEF_PTR(nsIStyleContext); NS_DEF_PTR(nsIContent); @@ -84,6 +85,8 @@ PRBool nsDebugTable::gRflRow = PR_TRUE; PRBool nsDebugTable::gRflCell = PR_TRUE; PRBool nsDebugTable::gRflArea = PR_TRUE; #endif +static PRInt32 gRflCount = 0; + /* ----------- InnerTableReflowState ---------- */ struct InnerTableReflowState { @@ -4678,7 +4681,11 @@ void nsTableFrame::DebugReflow(char* aMessage, printf("rea=%d av=(%s,%s) ", aState->reason, width, height); PrettyUC(aState->mComputedWidth, width); PrettyUC(aState->mComputedHeight, height); - printf("comp=(%s,%s) \n", width, height); + printf("comp=(%s,%s) count=%d \n", width, height, gRflCount); + gRflCount++; + //if (32 == gRflCount) { + // NS_ASSERTION(PR_FALSE, "stop"); + //} } if (aMetrics) { if (aState) { diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp index d8082427efb..abfe42508a5 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.cpp +++ b/mozilla/layout/tables/nsTableOuterFrame.cpp @@ -36,6 +36,42 @@ #include "nsHTMLParts.h" #include "nsIPresShell.h" +#define NS_TABLE_FRAME_CAPTION_LIST_INDEX 0 + +// caption frame +nsTableCaptionFrame::nsTableCaptionFrame() +{ + // shrink wrap + SetFlags(NS_BLOCK_SPACE_MGR|NS_BLOCK_WRAP_SIZE); +} + +NS_IMETHODIMP +nsTableCaptionFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = nsLayoutAtoms::tableCaptionFrame; + NS_ADDREF(*aType); + return NS_OK; +} + +nsresult +NS_NewTableCaptionFrame(nsIPresShell* aPresShell, + nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsTableCaptionFrame* it = new (aPresShell) nsTableCaptionFrame; + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aNewFrame = it; + return NS_OK; +} + +// OuterTableReflowState + struct OuterTableReflowState { // The presentation context @@ -101,28 +137,81 @@ nsresult nsTableOuterFrame::QueryInterface(const nsIID& aIID, void** aInstancePt } } -NS_IMETHODIMP nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext, - nsIAtom* aListName, - nsIFrame* aChildList) +NS_IMETHODIMP +nsTableOuterFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) { - mFrames.SetFrames(aChildList); + nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, + aContext, aPrevInFlow); + if (NS_FAILED(rv) || !mStyleContext) return rv; - // Set our internal member data - mInnerTableFrame = aChildList; - //XXX this should go through the child list looking for a displaytype==caption - if (1 < mFrames.GetLength()) { - nsIFrame *child; - nsresult result = aChildList->GetNextSibling(&child); - while ((NS_SUCCEEDED(result)) && (nsnull!=child)) { - const nsStyleDisplay* childDisplay; - child->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)childDisplay); - if (NS_STYLE_DISPLAY_TABLE_CAPTION==childDisplay->mDisplay) { - mCaptionFrame = child; - break; - } - result = child->GetNextSibling(&child); +#if 0 + // a 0 width table becomes auto + PRBool makeAuto = PR_FALSE; + nsStylePosition* position = (nsStylePosition*)mStyleContext->GetMutableStyleData(eStyleStruct_Position); + if (position->mWidth.GetUnit() == eStyleUnit_Coord) { + if (0 >= position->mWidth.GetCoordValue()) { + makeAuto= PR_TRUE; } } + else if (position->mWidth.GetUnit() == eStyleUnit_Percent) { + if (0.0f >= position->mWidth.GetPercentValue()) { + makeAuto= PR_TRUE; + } + } + + if (makeAuto) { + position->mWidth = nsStyleCoord(eStyleUnit_Auto); + } +#endif + return rv; +} + +NS_IMETHODIMP +nsTableOuterFrame::FirstChild(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame** aFirstChild) const +{ + NS_PRECONDITION(nsnull != aFirstChild, "null OUT parameter pointer"); + *aFirstChild = (nsLayoutAtoms::captionList == aListName) + ? mCaptionFrame : mFrames.FirstChild(); + return NS_OK; +} + +NS_IMETHODIMP +nsTableOuterFrame::GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const +{ + NS_PRECONDITION(nsnull != aListName, "null OUT parameter pointer"); + if (aIndex < 0) { + return NS_ERROR_INVALID_ARG; + } + *aListName = nsnull; + switch (aIndex) { + case NS_TABLE_FRAME_CAPTION_LIST_INDEX: + *aListName = nsLayoutAtoms::captionList; + NS_ADDREF(*aListName); + break; + } + return NS_OK; +} + +NS_IMETHODIMP +nsTableOuterFrame::SetInitialChildList(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + if (nsLayoutAtoms::captionList == aListName) { + // the frame constructor already checked for table-caption display type + mCaptionFrame = aChildList; + } + else { + mFrames.SetFrames(aChildList); + mInnerTableFrame = aChildList; + } return NS_OK; } @@ -133,22 +222,18 @@ nsTableOuterFrame::AppendFrames(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aFrameList) { - const nsStyleDisplay* display; - nsresult rv; + nsresult rv; // We only have two child frames: the inner table and one caption frame. // The inner frame is provided when we're initialized, and it cannot change - aFrameList->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); - if (NS_STYLE_DISPLAY_TABLE_CAPTION == display->mDisplay) { + if (nsLayoutAtoms::captionList == aListName) { NS_PRECONDITION(!mCaptionFrame, "already have a caption frame"); // We only support having a single caption frame if (mCaptionFrame || (LengthOf(aFrameList) > 1)) { rv = NS_ERROR_UNEXPECTED; - } else { // Insert the caption frame into the child list mCaptionFrame = aFrameList; - mInnerTableFrame->SetNextSibling(aFrameList); // Reflow the new caption frame. It's already marked dirty, so generate a reflow // command that tells us to reflow our dirty child frames @@ -186,14 +271,12 @@ nsTableOuterFrame::RemoveFrame(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aOldFrame) { - const nsStyleDisplay* display; - nsresult rv; + nsresult rv; // We only have two child frames: the inner table and one caption frame. // The inner frame can't be removed so this should be the caption - aOldFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); - NS_PRECONDITION(NS_STYLE_DISPLAY_TABLE_CAPTION == display->mDisplay, - "can't remove inner frame"); + NS_PRECONDITION(nsLayoutAtoms::captionList == aListName, "can't remove inner frame"); + NS_PRECONDITION(aOldFrame == mCaptionFrame, "invalid caption frame"); // See if the caption's minimum width impacted the inner table if (mMinCaptionWidth > mRect.width) { @@ -205,10 +288,12 @@ nsTableOuterFrame::RemoveFrame(nsIPresContext* aPresContext, mInnerTableFrame->SetFrameState(frameState); } - // Remove the caption frame from the child list and destroy it - mFrames.DestroyFrame(aPresContext, aOldFrame); - mCaptionFrame = nsnull; - mMinCaptionWidth = 0; + // Remove the caption frame and destroy it + if (mCaptionFrame && (mCaptionFrame == aOldFrame)) { + mCaptionFrame->Destroy(aPresContext); + mCaptionFrame = nsnull; + mMinCaptionWidth = 0; + } // Generate a reflow command so we get reflowed nsIReflowCommand* reflowCmd; @@ -235,7 +320,37 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext* aPresContext, } #endif - PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + // the remaining code was copied from nsContainerFrame::PaintChildren since + // it only paints the primary child list + + const nsStyleDisplay* disp = (const nsStyleDisplay*) + mStyleContext->GetStyleData(eStyleStruct_Display); + + // Child elements have the opportunity to override the visibility property + // of their parent and display even if the parent is hidden + PRBool clipState; + + // If overflow is hidden then set the clip rect so that children + // don't leak out of us + if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(nsRect(0, 0, mRect.width, mRect.height), + nsClipCombine_kIntersect, clipState); + } + + if (mCaptionFrame) { + PaintChild(aPresContext, aRenderingContext, aDirtyRect, mCaptionFrame, aWhichLayer); + } + nsIFrame* kid = mFrames.FirstChild(); + while (nsnull != kid) { + PaintChild(aPresContext, aRenderingContext, aDirtyRect, kid, aWhichLayer); + kid->GetNextSibling(&kid); + } + + if (NS_STYLE_OVERFLOW_HIDDEN == disp->mOverflow) { + aRenderingContext.PopState(clipState); + } + return NS_OK; } @@ -344,8 +459,11 @@ nsresult nsTableOuterFrame::IR_TargetIsChild(nsIPresContext* aPresContext nsIFrame* aNextFrame) { nsresult rv; - if (!aNextFrame) + if (!aNextFrame) { + // this will force Reflow to return the height of the last reflow rather than 0 + aReflowState.y = mRect.height; return NS_OK; + } if (aNextFrame == mInnerTableFrame) { rv = IR_TargetIsInnerTableFrame(aPresContext, aDesiredSize, aReflowState, aStatus); @@ -825,7 +943,6 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, { if (nsDebugTable::gRflTableOuter) nsTableFrame::DebugReflow("TO::Rfl en", this, &aReflowState, nsnull); nsresult rv = NS_OK; - // Initialize out parameters aDesiredSize.width = 0; aDesiredSize.height = 0; diff --git a/mozilla/layout/tables/nsTableOuterFrame.h b/mozilla/layout/tables/nsTableOuterFrame.h index 221b3c4e1a5..6a0a54f6caa 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.h +++ b/mozilla/layout/tables/nsTableOuterFrame.h @@ -24,11 +24,21 @@ #include "nscore.h" #include "nsHTMLContainerFrame.h" +#include "nsBlockFrame.h" #include "nsITableLayout.h" struct OuterTableReflowState; struct nsStyleTable; +class nsTableCaptionFrame : public nsBlockFrame +{ + public: + // nsISupports + nsTableCaptionFrame(); + NS_IMETHOD GetFrameType(nsIAtom** aType) const; +}; + + /* TODO 1. decide if we'll allow subclassing. If so, decide which methods really need to be virtual. */ @@ -53,11 +63,24 @@ public: friend nsresult NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsIFrame** aResult); + NS_IMETHOD Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow); + /** @see nsIFrame::SetInitialChildList */ NS_IMETHOD SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList); + NS_IMETHOD FirstChild(nsIPresContext* aPresContext, + nsIAtom* aListName, + nsIFrame** aFirstChild) const; + + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, + nsIAtom** aListName) const; + NS_IMETHOD AppendFrames(nsIPresContext* aPresContext, nsIPresShell& aPresShell, nsIAtom* aListName, @@ -237,7 +260,7 @@ protected: private: /** used to keep track of this frame's children */ - nsIFrame *mInnerTableFrame; + nsIFrame *mInnerTableFrame; // XXX this is redundant, mFrames holds the same nsIFrame *mCaptionFrame; /** used to track caption max element size */ diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index c3c210af812..7a70fd82e52 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -803,10 +803,14 @@ NS_METHOD nsTableRowFrame::ResizeReflow(nsIPresContext* aPresContext, // Newly inserted frame reason = eReflowReason_Initial; - // Use an unconstrained width so we can get the child's maximum - // width + // Use an unconstrained width so we can get the child's maximum width // XXX What about fixed layout tables? kidAvailSize.SizeTo(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); + // request to get the max element size if not already so + if (!kidMaxElementSize) { + kidMaxElementSize = &localKidMaxElementSize; + desiredSize.maxElementSize = kidMaxElementSize; + } } }