From dced08401d8bd78722ef8415012838703fcf55f1 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Thu, 21 Oct 1999 05:11:43 +0000 Subject: [PATCH] r=kipp@netscape.com Added API to get/set properties on frames. Also changed nsContainerFrame to use a property to implement the frame overflow list. This saves 4 bytes per container frames git-svn-id: svn://10.0.0.236/trunk@51358 18797224-902f-48f8-a5cc-f745e15eee43 --- .../content/shared/public/nsLayoutAtomList.h | 3 + mozilla/layout/base/nsFrameManager.cpp | 137 +++++++------ mozilla/layout/base/nsLayoutAtomList.h | 3 + mozilla/layout/base/public/nsIFrameManager.h | 83 +++++--- mozilla/layout/base/public/nsLayoutAtomList.h | 3 + mozilla/layout/generic/nsContainerFrame.cpp | 92 ++++++++- mozilla/layout/generic/nsContainerFrame.h | 19 +- mozilla/layout/generic/nsFirstLetterFrame.cpp | 18 +- mozilla/layout/generic/nsInlineFrame.cpp | 40 ++-- .../layout/html/base/src/nsContainerFrame.cpp | 92 ++++++++- .../layout/html/base/src/nsContainerFrame.h | 19 +- mozilla/layout/html/base/src/nsDST.cpp | 182 +++++++++--------- mozilla/layout/html/base/src/nsDST.h | 23 ++- .../html/base/src/nsFirstLetterFrame.cpp | 18 +- .../layout/html/base/src/nsFrameManager.cpp | 137 +++++++------ .../layout/html/base/src/nsInlineFrame.cpp | 40 ++-- .../layout/html/table/src/nsTableFrame.cpp | 34 ++-- mozilla/layout/html/table/src/nsTableFrame.h | 6 +- .../html/table/src/nsTableOuterFrame.cpp | 2 +- .../html/table/src/nsTableRowGroupFrame.cpp | 14 +- mozilla/layout/tables/nsTableFrame.cpp | 34 ++-- mozilla/layout/tables/nsTableFrame.h | 6 +- mozilla/layout/tables/nsTableOuterFrame.cpp | 2 +- .../layout/tables/nsTableRowGroupFrame.cpp | 14 +- 24 files changed, 658 insertions(+), 363 deletions(-) diff --git a/mozilla/content/shared/public/nsLayoutAtomList.h b/mozilla/content/shared/public/nsLayoutAtomList.h index e975d14b5a6..29ef10cd00b 100644 --- a/mozilla/content/shared/public/nsLayoutAtomList.h +++ b/mozilla/content/shared/public/nsLayoutAtomList.h @@ -99,6 +99,9 @@ LAYOUT_ATOM(tableRowFrame, "TableRowFrame") LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") + // Alphabetical list of frame property names +LAYOUT_ATOM(overflowProperty, "OverflowProperty") + #ifdef DEBUG // Alphabetical list of atoms used by debugging code LAYOUT_ATOM(cellMap, "TableCellMap") diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index 905375ee3c3..b2dd9bf9c60 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -230,10 +230,10 @@ public: nsIAtom* aPropertyName, PRUint32 aOptions, void** aPropertyValue); - NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue, - FMPropertyDtorFunc aPropDtorFunc); + NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue, + NSFMPropertyDtorFunc aPropDtorFunc); NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName); @@ -243,22 +243,22 @@ public: private: struct PropertyList { - nsCOMPtr mName; // property name - nsDST* mFrameValueMap; // map of frame/value pairs - FMPropertyDtorFunc mDtorFunc; // property specific value dtor function - PropertyList* mNext; + nsCOMPtr mName; // property name + nsDST* mFrameValueMap; // map of frame/value pairs + NSFMPropertyDtorFunc mDtorFunc; // property specific value dtor function + PropertyList* mNext; - PropertyList(nsIAtom* aName, - FMPropertyDtorFunc aDtorFunc, - nsDST::NodeArena* aDSTNodeArena); + PropertyList(nsIAtom* aName, + NSFMPropertyDtorFunc aDtorFunc, + nsDST::NodeArena* aDSTNodeArena); ~PropertyList(); // Removes the property associated with the given frame, and destroys // the property value - void RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame); + PRBool RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame); // Remove and destroy all remaining properties - void RemoveAllProperties(nsIPresContext* aPresContext); + void RemoveAllProperties(nsIPresContext* aPresContext); }; nsIPresShell* mPresShell; // weak link, because the pres shell owns us @@ -298,7 +298,7 @@ private: NS_LAYOUT nsresult NS_NewFrameManager(nsIFrameManager** aInstancePtrResult) { - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); + NS_ENSURE_ARG_POINTER(aInstancePtrResult); if (!aInstancePtrResult) { return NS_ERROR_NULL_POINTER; } @@ -392,14 +392,14 @@ FrameManager::SetRootFrame(nsIFrame* aRootFrame) NS_IMETHODIMP FrameManager::GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aResult) { - NS_PRECONDITION(aResult, "null ptr"); - NS_PRECONDITION(aContent, "no content object"); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_ARG_POINTER(aContent); if (!aResult) { return NS_ERROR_NULL_POINTER; } if (mPrimaryFrameMap) { - *aResult = (nsIFrame*)mPrimaryFrameMap->Search(aContent); + mPrimaryFrameMap->Search(aContent, 0, (void**)aResult); if (!*aResult) { nsCOMPtr styleSet; nsCOMPtr presContext; @@ -421,7 +421,7 @@ NS_IMETHODIMP FrameManager::SetPrimaryFrameFor(nsIContent* aContent, nsIFrame* aPrimaryFrame) { - NS_PRECONDITION(aContent, "no content object"); + NS_ENSURE_ARG_POINTER(aContent); // If aPrimaryFrame is NULL, then remove the mapping if (!aPrimaryFrame) { @@ -438,7 +438,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent, } // Add a mapping to the hash table - mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame); + mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame, nsnull); } return NS_OK; } @@ -457,8 +457,8 @@ NS_IMETHODIMP FrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame** aResult) const { - NS_PRECONDITION(aResult, "null ptr"); - NS_PRECONDITION(aFrame, "no frame"); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_ARG_POINTER(aFrame); if (!aResult || !aFrame) { return NS_ERROR_NULL_POINTER; } @@ -476,7 +476,7 @@ NS_IMETHODIMP FrameManager::SetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame* aPlaceholderFrame) { - NS_PRECONDITION(aFrame, "no frame"); + NS_ENSURE_ARG_POINTER(aFrame); #ifdef NS_DEBUG // Verify that the placeholder frame is of the correct type if (aPlaceholderFrame) { @@ -1597,31 +1597,30 @@ FrameManager::GetFrameProperty(nsIFrame* aFrame, PRUint32 aOptions, void** aPropertyValue) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result; if (propertyList) { - // See if we should also remove the property - if (aOptions & NS_IFRAME_MGR_REMOVE_PROPERTY) { - *aPropertyValue = propertyList->mFrameValueMap->Remove(aFrame); - } else { - *aPropertyValue = propertyList->mFrameValueMap->Search(aFrame); - } + result = propertyList->mFrameValueMap->Search(aFrame, aOptions, aPropertyValue); + } else { *aPropertyValue = 0; + result = NS_IFRAME_MGR_PROP_NOT_THERE; } - return NS_OK; + return result; } NS_IMETHODIMP -FrameManager::SetFrameProperty(nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue, - FMPropertyDtorFunc aPropDtorFunc) +FrameManager::SetFrameProperty(nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue, + NSFMPropertyDtorFunc aPropDtorFunc) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result = NS_OK; if (propertyList) { // Make sure the dtor function matches @@ -1641,34 +1640,38 @@ FrameManager::SetFrameProperty(nsIFrame* aFrame, // The current property value (if there is one) is replaced and the current // value is destroyed - void* aOldValue; - - aOldValue = propertyList->mFrameValueMap->Insert(aFrame, aPropertyValue); - if (aOldValue && propertyList->mDtorFunc) { - nsCOMPtr presContext; - mPresShell->GetPresContext(getter_AddRefs(presContext)); - - propertyList->mDtorFunc(presContext, aFrame, aPropertyName, aOldValue); + void* oldValue; + result = propertyList->mFrameValueMap->Insert(aFrame, aPropertyValue, &oldValue); + if (NS_DST_VALUE_OVERWRITTEN == result) { + if (propertyList->mDtorFunc) { + nsCOMPtr presContext; + mPresShell->GetPresContext(getter_AddRefs(presContext)); + + propertyList->mDtorFunc(presContext, aFrame, aPropertyName, oldValue); + } } - return NS_OK; + return result; } NS_IMETHODIMP FrameManager::RemoveFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result = NS_IFRAME_MGR_PROP_NOT_THERE; if (propertyList) { nsCOMPtr presContext; mPresShell->GetPresContext(getter_AddRefs(presContext)); - propertyList->RemovePropertyForFrame(presContext, aFrame); + if (propertyList->RemovePropertyForFrame(presContext, aFrame)) { + result = NS_OK; + } } - return NS_OK; + return result; } //---------------------------------------------------------------------- @@ -1825,9 +1828,9 @@ UndisplayedMap::Clear(void) //---------------------------------------------------------------------- -FrameManager::PropertyList::PropertyList(nsIAtom* aName, - FMPropertyDtorFunc aDtorFunc, - nsDST::NodeArena* aDSTNodeArena) +FrameManager::PropertyList::PropertyList(nsIAtom* aName, + NSFMPropertyDtorFunc aDtorFunc, + nsDST::NodeArena* aDSTNodeArena) : mName(aName), mFrameValueMap(new nsDST(aDSTNodeArena)), mDtorFunc(aDtorFunc), mNext(nsnull) { @@ -1840,18 +1843,18 @@ FrameManager::PropertyList::~PropertyList() class DestroyPropertyValuesFunctor : public nsDSTNodeFunctor { public: - DestroyPropertyValuesFunctor(nsIPresContext* aPresContext, - nsIAtom* aPropertyName, - FMPropertyDtorFunc aDtorFunc) + DestroyPropertyValuesFunctor(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + NSFMPropertyDtorFunc aDtorFunc) : mPresContext(aPresContext), mPropertyName(aPropertyName), mDtorFunc(aDtorFunc) {} virtual void operator () (void *aKey, void *aValue) { mDtorFunc(mPresContext, (nsIFrame*)aKey, mPropertyName, aValue); } - nsIPresContext* mPresContext; - nsIAtom* mPropertyName; - FMPropertyDtorFunc mDtorFunc; + nsIPresContext* mPresContext; + nsIAtom* mPropertyName; + NSFMPropertyDtorFunc mDtorFunc; }; void @@ -1865,15 +1868,27 @@ FrameManager::PropertyList::RemoveAllProperties(nsIPresContext* aPresContext) } } -void +PRBool FrameManager::PropertyList::RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) { - void* value = mFrameValueMap->Remove(aFrame); + void* value; + nsresult result; + + // If the property exists, then we need to run the dtor function so + // do a search with the option to remove the key/value pair + result = mFrameValueMap->Search(aFrame, NS_DST_REMOVE_KEY_VALUE, &value); - if (value && mDtorFunc) { - // Destroy the property value - mDtorFunc(aPresContext, aFrame, mName, value); + if (NS_OK == result) { + // The property was set + if (mDtorFunc) { + // Destroy the property value + mDtorFunc(aPresContext, aFrame, mName, value); + } + + return PR_TRUE; } + + return PR_FALSE; } diff --git a/mozilla/layout/base/nsLayoutAtomList.h b/mozilla/layout/base/nsLayoutAtomList.h index e975d14b5a6..29ef10cd00b 100644 --- a/mozilla/layout/base/nsLayoutAtomList.h +++ b/mozilla/layout/base/nsLayoutAtomList.h @@ -99,6 +99,9 @@ LAYOUT_ATOM(tableRowFrame, "TableRowFrame") LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") + // Alphabetical list of frame property names +LAYOUT_ATOM(overflowProperty, "OverflowProperty") + #ifdef DEBUG // Alphabetical list of atoms used by debugging code LAYOUT_ATOM(cellMap, "TableCellMap") diff --git a/mozilla/layout/base/public/nsIFrameManager.h b/mozilla/layout/base/public/nsIFrameManager.h index 67871d3d283..9d1b501908e 100644 --- a/mozilla/layout/base/public/nsIFrameManager.h +++ b/mozilla/layout/base/public/nsIFrameManager.h @@ -38,13 +38,20 @@ class nsStyleChangeList; // Calback function used to destroy the value associated with a // given property. used by RemoveFrameProperty() typedef void -(*FMPropertyDtorFunc)(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue); +(*NSFMPropertyDtorFunc)(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue); // Option flags for GetFrameProperty() member function -#define NS_IFRAME_MGR_REMOVE_PROPERTY 0x0001 +#define NS_IFRAME_MGR_REMOVE_PROP 0x0001 + +// nsresult error codes for frame property functions +#define NS_IFRAME_MGR_PROP_NOT_THERE \ + NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 1) + +#define NS_IFRAME_MGR_PROP_OVERWRITTEN \ + NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 2) /** * Frame manager interface. The frame manager serves two purposes: @@ -143,32 +150,58 @@ public: NS_IMETHOD CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) = 0; NS_IMETHOD RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) = 0; - // Gets a property value on a given frame. Returns 0 if the property is - // not set + /** + * Gets a property value for a given frame. + * + * @param aFrame the frame with the property + * @param aPropertyName property name as an atom + * @param aOptions optional flags + * NS_IFRAME_MGR_REMOVE_PROP removes the property + * @param aPropertyValue the property value or 0 if the property is not set + * @return NS_OK if the property is set, + * NS_IFRAME_MGR_PROP_NOT_THERE if the property is not set + */ NS_IMETHOD GetFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName, PRUint32 aOptions, void** aPropertyValue) = 0; - // Sets the property value - // - // A frame may only have one property value at a time for a given property - // name. The current property value (if there is one) is replaced and the - // current value is destroyed - // - // When setting a property you may specify the dtor function (can be - // NULL) that will be used to destroy the property value. There can be - // only one dtor function for a given property atom, and the set call - // will fail with error NS_ERROR_INVALID_ARG if the dtor function does - // not match the existing dtor function - NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue, - FMPropertyDtorFunc aPropDtorFunc) = 0; + /** + * Sets the property value for a given frame. + * + * A frame may only have one property value at a time for a given property + * name. The existing property value (if there is one) is overwritten, and the + * old value destroyed + * + * @param aFrame the frame to set the property on + * @param aPropertyName property name as an atom + * @param aPropertyValue the property value + * @param aPropertyDtorFunc when setting a property you can specify the + * dtor function (can be NULL) that will be used + * to destroy the property value. There can be only + * one dtor function for a given property name + * @return NS_OK if successful, + * NS_IFRAME_MGR_PROP_OVERWRITTEN if there is an existing property + * value that was overwritten, + * NS_ERROR_INVALID_ARG if the dtor function does not match the + * existing dtor function + */ + NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue, + NSFMPropertyDtorFunc aPropertyDtorFunc) = 0; - // Removes a property and destroys its property value by calling the dtor - // function associated with the property name. When a frame is destroyed any - // remaining properties are automatically removed + /** + * Removes a property and destroys its property value by calling the dtor + * function associated with the property name. + * + * When a frame is destroyed any remaining properties are automatically removed + * + * @param aFrame the frame to set the property on + * @param aPropertyName property name as an atom + * @return NS_OK if the property is successfully removed, + * NS_IFRAME_MGR_PROP_NOT_THERE if the property is not set + */ NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName) = 0; diff --git a/mozilla/layout/base/public/nsLayoutAtomList.h b/mozilla/layout/base/public/nsLayoutAtomList.h index e975d14b5a6..29ef10cd00b 100644 --- a/mozilla/layout/base/public/nsLayoutAtomList.h +++ b/mozilla/layout/base/public/nsLayoutAtomList.h @@ -99,6 +99,9 @@ LAYOUT_ATOM(tableRowFrame, "TableRowFrame") LAYOUT_ATOM(textFrame, "TextFrame") LAYOUT_ATOM(viewportFrame, "ViewportFrame") + // Alphabetical list of frame property names +LAYOUT_ATOM(overflowProperty, "OverflowProperty") + #ifdef DEBUG // Alphabetical list of atoms used by debugging code LAYOUT_ATOM(cellMap, "TableCellMap") diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 8e88c244ea2..12e6df95e75 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -31,6 +31,10 @@ #include "nsIReflowCommand.h" #include "nsHTMLIIDs.h" #include "nsHTMLContainerFrame.h" +#include "nsIFrameManager.h" +#include "nsIPresShell.h" +#include "nsCOMPtr.h" +#include "nsLayoutAtoms.h" #ifdef NS_DEBUG #undef NOISY @@ -453,6 +457,72 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, #endif } +nsIFrame* +nsContainerFrame::GetOverflowFrames(nsIPresContext* aPresContext, + PRBool aRemoveProperty) +{ + nsCOMPtr presShell; + nsCOMPtr frameManager; + + aPresContext->GetShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + PRUint32 options = 0; + void* value; + + if (aRemoveProperty) { + options |= NS_IFRAME_MGR_REMOVE_PROP; + } + frameManager->GetFrameProperty(this, nsLayoutAtoms::overflowProperty, + options, &value); + return (nsIFrame*)value; + } + } + + return nsnull; +} + +// Destructor function for the overflow frame property +static void +DestroyOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue) +{ + if (aPropertyValue) { + nsFrameList frames((nsIFrame*)aPropertyValue); + + frames.DestroyFrames(*aPresContext); + } +} + +nsresult +nsContainerFrame::SetOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aOverflowFrames) +{ + nsCOMPtr presShell; + nsCOMPtr frameManager; + nsresult rv = NS_ERROR_FAILURE; + + aPresContext->GetShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::overflowProperty, + aOverflowFrames, DestroyOverflowFrames); + + // Verify that we didn't overwrite an existing overflow list + NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, + "existing overflow list"); + } + } + + return rv; +} + /** * Push aFromChild and its next siblings to the next-in-flow. Change the * geometric parent of each frame that's pushed. If there is no next-in-flow @@ -468,7 +538,9 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, * an error to push a parent's first child frame */ void -nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) +nsContainerFrame::PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling) { NS_PRECONDITION(nsnull != aFromChild, "null pointer"); NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child"); @@ -495,8 +567,7 @@ nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) } else { // Add the frames to our overflow list - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } } @@ -509,29 +580,32 @@ nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) * @return PR_TRUE if any frames were moved and PR_FALSE otherwise */ PRBool -nsContainerFrame::MoveOverflowToChildList() +nsContainerFrame::MoveOverflowToChildList(nsIPresContext* aPresContext) { PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow nsContainerFrame* prevInFlow = (nsContainerFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, + PR_TRUE); + if (prevOverflowFrames) { NS_ASSERTION(mFrames.IsEmpty(), "bad overflow list"); // When pushing and pulling frames we need to check for whether any // views need to be reparented. - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); result = PR_TRUE; } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); result = PR_TRUE; } return result; diff --git a/mozilla/layout/generic/nsContainerFrame.h b/mozilla/layout/generic/nsContainerFrame.h index 710407bc6ed..a7a2d221455 100644 --- a/mozilla/layout/generic/nsContainerFrame.h +++ b/mozilla/layout/generic/nsContainerFrame.h @@ -93,6 +93,18 @@ protected: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + /** + * Get the frames on the overflow list + */ + nsIFrame* GetOverflowFrames(nsIPresContext* aPresContext, + PRBool aRemoveProperty); + + /** + * Set the overflow list + */ + nsresult SetOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aOverflowFrames); + /** * Moves any frames on both the prev-in-flow's overflow list and the * receiver's overflow to the receiver's child list. @@ -102,7 +114,7 @@ protected: * * @return PR_TRUE if any frames were moved and PR_FALSE otherwise */ - PRBool MoveOverflowToChildList(); + PRBool MoveOverflowToChildList(nsIPresContext* aPresContext); /** * Push aFromChild and its next siblings to the next-in-flow. Change @@ -118,10 +130,11 @@ protected: * @param aPrevSibling aFromChild's previous sibling. Must not be null. * It's an error to push a parent's first child frame */ - void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling); + void PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling); nsFrameList mFrames; - nsFrameList mOverflowFrames; }; #endif /* nsContainerFrame_h___ */ diff --git a/mozilla/layout/generic/nsFirstLetterFrame.cpp b/mozilla/layout/generic/nsFirstLetterFrame.cpp index dd24b144921..d424ef07859 100644 --- a/mozilla/layout/generic/nsFirstLetterFrame.cpp +++ b/mozilla/layout/generic/nsFirstLetterFrame.cpp @@ -247,14 +247,14 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, // And then push it to our overflow list if (nextInFlow) { kid->SetNextSibling(nsnull); - mOverflowFrames.SetFrames(nextInFlow); + SetOverflowFrames(&aPresContext, nextInFlow); } else { nsIFrame* nextSib; kid->GetNextSibling(&nextSib); if (nextSib) { kid->SetNextSibling(nsnull); - mOverflowFrames.SetFrames(nextSib); + SetOverflowFrames(&aPresContext, nextSib); } } } @@ -265,27 +265,31 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, void nsFirstLetterFrame::DrainOverflowFrames(nsIPresContext* aPresContext) { + nsIFrame* overflowFrames; + // Check for an overflow list with our prev-in-flow nsFirstLetterFrame* prevInFlow = (nsFirstLetterFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + overflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.IsEmpty(), "bad overflow list"); // When pushing and pulling frames we need to check for whether any // views need to be reparented. - nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); + nsIFrame* f = overflowFrames; while (f) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); f->GetNextSibling(&f); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, overflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); } // Now repair our first frames style context XXX only first frame? diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 5ce31c5547f..a22d279056d 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -1348,23 +1348,26 @@ nsInlineFrame::DrainOverflow(nsIPresContext* aPresContext) // Check for an overflow list with our prev-in-flow nsInlineFrame* prevInFlow = (nsInlineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + + if (prevOverflowFrames) { // When pushing and pulling frames we need to check for whether any // views need to be reparented. // XXX Doing it this way means an extra pass over the frames. We could // change InsertFrames() to do this, but that's a general purpose // function and it doesn't seem like this functionality belongs there... - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); } } @@ -1441,7 +1444,8 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, #ifdef DEBUG if (NS_FRAME_COMPLETE == aStatus) { // We can't be complete AND have overflow frames! - NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops"); + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_FALSE); + NS_ASSERTION(!overflowFrames, "whoops"); } #endif @@ -1682,8 +1686,7 @@ nsInlineFrame::PushFrames(nsIPresContext* aPresContext, // Add the frames to our overflow list (let our next in flow drain // our overflow list when it is ready) - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } nsresult @@ -1781,7 +1784,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext* aPresContext, nsInlineFrame* nextInFlow = (nsInlineFrame*) mNextInFlow; while (nsnull != nextInFlow) { if (nextInFlow->mFrames.NotEmpty() || - nextInFlow->mOverflowFrames.NotEmpty()) { + nextInFlow->GetOverflowFrames(aPresContext, PR_FALSE)) { aStatus |= NS_FRAME_NOT_COMPLETE; break; } @@ -2013,18 +2016,23 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) // Check for an overflow list with our prev-in-flow nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { - ReParentChildListStyle(aPresContext, mStyleContext, - prevInFlow->mOverflowFrames); - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (prevOverflowFrames) { + nsFrameList frames(prevOverflowFrames); + + ReParentChildListStyle(aPresContext, mStyleContext, frames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - ReParentChildListStyle(aPresContext, mStyleContext, mOverflowFrames); - mFrames.AppendFrames(nsnull, mOverflowFrames); + nsFrameList frames(overflowFrames); + + ReParentChildListStyle(aPresContext, mStyleContext, frames); + mFrames.AppendFrames(nsnull, overflowFrames); } } diff --git a/mozilla/layout/html/base/src/nsContainerFrame.cpp b/mozilla/layout/html/base/src/nsContainerFrame.cpp index 8e88c244ea2..12e6df95e75 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsContainerFrame.cpp @@ -31,6 +31,10 @@ #include "nsIReflowCommand.h" #include "nsHTMLIIDs.h" #include "nsHTMLContainerFrame.h" +#include "nsIFrameManager.h" +#include "nsIPresShell.h" +#include "nsCOMPtr.h" +#include "nsLayoutAtoms.h" #ifdef NS_DEBUG #undef NOISY @@ -453,6 +457,72 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, #endif } +nsIFrame* +nsContainerFrame::GetOverflowFrames(nsIPresContext* aPresContext, + PRBool aRemoveProperty) +{ + nsCOMPtr presShell; + nsCOMPtr frameManager; + + aPresContext->GetShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + PRUint32 options = 0; + void* value; + + if (aRemoveProperty) { + options |= NS_IFRAME_MGR_REMOVE_PROP; + } + frameManager->GetFrameProperty(this, nsLayoutAtoms::overflowProperty, + options, &value); + return (nsIFrame*)value; + } + } + + return nsnull; +} + +// Destructor function for the overflow frame property +static void +DestroyOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue) +{ + if (aPropertyValue) { + nsFrameList frames((nsIFrame*)aPropertyValue); + + frames.DestroyFrames(*aPresContext); + } +} + +nsresult +nsContainerFrame::SetOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aOverflowFrames) +{ + nsCOMPtr presShell; + nsCOMPtr frameManager; + nsresult rv = NS_ERROR_FAILURE; + + aPresContext->GetShell(getter_AddRefs(presShell)); + if (presShell) { + presShell->GetFrameManager(getter_AddRefs(frameManager)); + + if (frameManager) { + rv = frameManager->SetFrameProperty(this, nsLayoutAtoms::overflowProperty, + aOverflowFrames, DestroyOverflowFrames); + + // Verify that we didn't overwrite an existing overflow list + NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, + "existing overflow list"); + } + } + + return rv; +} + /** * Push aFromChild and its next siblings to the next-in-flow. Change the * geometric parent of each frame that's pushed. If there is no next-in-flow @@ -468,7 +538,9 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext& aPresContext, * an error to push a parent's first child frame */ void -nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) +nsContainerFrame::PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling) { NS_PRECONDITION(nsnull != aFromChild, "null pointer"); NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child"); @@ -495,8 +567,7 @@ nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) } else { // Add the frames to our overflow list - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } } @@ -509,29 +580,32 @@ nsContainerFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) * @return PR_TRUE if any frames were moved and PR_FALSE otherwise */ PRBool -nsContainerFrame::MoveOverflowToChildList() +nsContainerFrame::MoveOverflowToChildList(nsIPresContext* aPresContext) { PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow nsContainerFrame* prevInFlow = (nsContainerFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, + PR_TRUE); + if (prevOverflowFrames) { NS_ASSERTION(mFrames.IsEmpty(), "bad overflow list"); // When pushing and pulling frames we need to check for whether any // views need to be reparented. - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); result = PR_TRUE; } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); result = PR_TRUE; } return result; diff --git a/mozilla/layout/html/base/src/nsContainerFrame.h b/mozilla/layout/html/base/src/nsContainerFrame.h index 710407bc6ed..a7a2d221455 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.h +++ b/mozilla/layout/html/base/src/nsContainerFrame.h @@ -93,6 +93,18 @@ protected: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + /** + * Get the frames on the overflow list + */ + nsIFrame* GetOverflowFrames(nsIPresContext* aPresContext, + PRBool aRemoveProperty); + + /** + * Set the overflow list + */ + nsresult SetOverflowFrames(nsIPresContext* aPresContext, + nsIFrame* aOverflowFrames); + /** * Moves any frames on both the prev-in-flow's overflow list and the * receiver's overflow to the receiver's child list. @@ -102,7 +114,7 @@ protected: * * @return PR_TRUE if any frames were moved and PR_FALSE otherwise */ - PRBool MoveOverflowToChildList(); + PRBool MoveOverflowToChildList(nsIPresContext* aPresContext); /** * Push aFromChild and its next siblings to the next-in-flow. Change @@ -118,10 +130,11 @@ protected: * @param aPrevSibling aFromChild's previous sibling. Must not be null. * It's an error to push a parent's first child frame */ - void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling); + void PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling); nsFrameList mFrames; - nsFrameList mOverflowFrames; }; #endif /* nsContainerFrame_h___ */ diff --git a/mozilla/layout/html/base/src/nsDST.cpp b/mozilla/layout/html/base/src/nsDST.cpp index e2de805bb57..a3b76761563 100644 --- a/mozilla/layout/html/base/src/nsDST.cpp +++ b/mozilla/layout/html/base/src/nsDST.cpp @@ -18,7 +18,8 @@ #define PL_ARENA_CONST_ALIGN_MASK 3 #include "nslayout.h" #include "nsDST.h" -#include "nsISupports.h" +#include "plarena.h" +#include "nsISupportsUtils.h" #ifdef NS_DEBUG #include #endif @@ -346,18 +347,20 @@ keepLooping: } // Removes all nodes from the tree -void +nsresult nsDST::Clear() { mArena->FreeArenaPool(); mRoot = 0; + return NS_OK; } // Enumerate all the nodes in the tree -void +nsresult nsDST::Enumerate(nsDSTNodeFunctor& aFunctor) const { EnumTree(mRoot, aFunctor); + return NS_OK; } void @@ -400,67 +403,46 @@ nsDST::ConvertToTwoNode(LeafNode** aLeafNode) // Searches the tree for a node with the specified key. Return the value // or NULL if the key is not in the tree -void* -nsDST::Search(void* aKey) const +nsresult +nsDST::Search(void* aKey, unsigned aOptions, void** aValue) { - NS_PRECONDITION(0 == (PtrBits(aKey) & (mLevelZeroBit - 1)), - "ignored low-order bits are not zero"); - - if (mRoot) { - LeafNode* node = mRoot; - PtrBits bitMask = mLevelZeroBit; - - while (1) { - // Check if the key matches - if (node->Key() == aKey) { - return node->mValue; - } - - // See if this is a leaf node - if (node->IsLeaf()) { - // We didn't find a matching key - break; - } - - // Check whether we search the left branch or the right branch - if (DST_BRANCHES_LEFT(aKey, bitMask)) { - node = ((TwoNode*)node)->mLeft; - } else { - node = ((TwoNode*)node)->mRight; - } - - if (!node) { - break; // we reached a null link - } - - // Move to the next bit in the key - bitMask <<= 1; - } + NS_ENSURE_ARG_POINTER(aValue); + *aValue = 0; // initialize OUT parameter + + nsresult result = SearchTree(aKey, aOptions, aValue); #ifdef DEBUG_troy - // We didn't find a matching node. Use an alternative algorithm to verify - // that the key is not in the tree - NS_POSTCONDITION(!DepthFirstSearch(mRoot, aKey), "DST search failed"); -#endif + if (NS_DST_KEY_NOT_THERE == result) { + // Use an alternative algorithm to verify that there's really + // no node with a matching key + DepthFirstSearch(mRoot, aKey); } - - return 0; +#endif + return result; } // Adds a new key to the tree. If the specified key is already in the // tree, then the existing value is replaced by the new value. Returns -// the old value, or NULL if this is a new key -void* -nsDST::Insert(void* aKey, void* aValue) +// NS_DST_VALUE_OVERWRITTEN if there is an existing value that is +// overwritten +nsresult +nsDST::Insert(void* aKey, void* aValue, void** aOldValue) { NS_PRECONDITION(0 == (PtrBits(aKey) & (mLevelZeroBit - 1)), "ignored low-order bits are not zero"); + NS_ENSURE_ARG_POINTER(aValue); + // Initialize OUT parameter + if (aOldValue) { + *aOldValue = 0; + } + + // See if there's an existing node with a matching key LeafNode** node = (LeafNode**)&mRoot; void* previousValue = 0; TwoNode* branchReduction = 0; + nsresult result = NS_OK; - // See if there's an existing node with a matching key if (*node) { PtrBits bitMask = mLevelZeroBit; @@ -544,8 +526,11 @@ nsDST::Insert(void* aKey, void* aValue) } else if (*node) { // We found an existing node with a matching key. Replace the current // value with the new value - previousValue = (*node)->mValue; + if (aOldValue) { + *aOldValue = (*node)->mValue; + } (*node)->mValue = aValue; + result = NS_DST_VALUE_OVERWRITTEN; } else { // Allocate a new leaf node and insert it into the tree @@ -555,7 +540,7 @@ nsDST::Insert(void* aKey, void* aValue) #ifdef DEBUG_troy VerifyTree(mRoot); #endif - return previousValue; + return result; } // Helper function that removes and returns the left most leaf node @@ -619,13 +604,14 @@ keepLooking: goto keepLooking; } -// Removes a key from the tree. Returns the current value, or NULL if -// the key is not in the tree -void* -nsDST::Remove(void* aKey) +// Returns NS_OK if there is a matching key and NS_DST_KEY_NOT_THERE +// otherwise +nsresult +nsDST::SearchTree(void* aKey, unsigned aOptions, void** aValue) { NS_PRECONDITION(0 == (PtrBits(aKey) & (mLevelZeroBit - 1)), "ignored low-order bits are not zero"); + if (mRoot) { LeafNode** node; TwoNode** parentNode = 0; @@ -635,7 +621,7 @@ nsDST::Remove(void* aKey) node = (LeafNode**)&mRoot; } else if (mRoot->IsLeaf()) { - return 0; // no node with a matching key + return NS_DST_KEY_NOT_THERE; // no node with a matching key } else { // Look for a node with a matching key @@ -653,7 +639,7 @@ nsDST::Remove(void* aKey) if (!*node) { // We found a NULL link which means no node with a matching key - return 0; + return NS_DST_KEY_NOT_THERE; } // Check if the key matches @@ -664,7 +650,7 @@ nsDST::Remove(void* aKey) // The key doesn't match. If this is a leaf node that means no // node with a matching key if ((*node)->IsLeaf()) { - return 0; + return NS_DST_KEY_NOT_THERE; } // Move to the next bit in the key @@ -673,49 +659,61 @@ nsDST::Remove(void* aKey) } // We found a matching node - void* value = (*node)->mValue; + *aValue = (*node)->mValue; - if ((*node)->IsLeaf()) { - // Delete the leaf node - DestroyNode(*node); - - // Disconnect the node from its parent node - *node = 0; - - // If the parent now has no child nodes, then convert it to a - // leaf frame - if (parentNode && !(*parentNode)->mLeft && !(*parentNode)->mRight) { - ConvertToLeafNode(parentNode); - } - - } else { - // We can't just move the left or right subtree up one level, because - // then we would have to re-sort the tree. Instead replace the node's - // key and value with that of its left most leaf node (any leaf frame - // would do) - LeafNode* leaf = RemoveLeftMostLeafNode((TwoNode**)node); - - // Copy over the leaf's key and value - // Note: RemoveLeftMostLeafNode() may have converted "node" to a - // leaf node so don't make any assumptions here + // Should we remove the key/value pair? + if (aOptions & NS_DST_REMOVE_KEY_VALUE) { if ((*node)->IsLeaf()) { - (*node)->mKey = DST_GET_LEAF_KEY(leaf); + // Delete the leaf node + DestroyNode(*node); + + // Disconnect the node from its parent node + *node = 0; + + // If the parent now has no child nodes, then convert it to a + // leaf frame + if (parentNode && !(*parentNode)->mLeft && !(*parentNode)->mRight) { + ConvertToLeafNode(parentNode); + } + } else { - (*node)->mKey = (void*)(PtrBits(DST_GET_LEAF_KEY(leaf)) | 0x01); + // We can't just move the left or right subtree up one level, because + // then we would have to re-sort the tree. Instead replace the node's + // key and value with that of its left most leaf node (any leaf frame + // would do) + LeafNode* leaf = RemoveLeftMostLeafNode((TwoNode**)node); + + // Copy over the leaf's key and value + // Note: RemoveLeftMostLeafNode() may have converted "node" to a + // leaf node so don't make any assumptions here + if ((*node)->IsLeaf()) { + (*node)->mKey = DST_GET_LEAF_KEY(leaf); + } else { + (*node)->mKey = (void*)(PtrBits(DST_GET_LEAF_KEY(leaf)) | 0x01); + } + (*node)->mValue = leaf->mValue; + + // Delete the leaf node + DestroyNode(leaf); } - (*node)->mValue = leaf->mValue; - - // Delete the leaf node - DestroyNode(leaf); +#ifdef DEBUG_troy + VerifyTree(mRoot); +#endif } -#ifdef DEBUG_troy - VerifyTree(mRoot); -#endif - return value; + return NS_OK; } - return 0; + return NS_DST_KEY_NOT_THERE; +} + +// Removes a key from the tree. Returns NS_OK if successful and +// NS_DST_KEY_NOT_THERE if there is no node with a matching key +nsresult +nsDST::Remove(void* aKey) +{ + void* value; + return SearchTree(aKey, NS_DST_REMOVE_KEY_VALUE, &value); } #ifdef NS_DEBUG diff --git a/mozilla/layout/html/base/src/nsDST.h b/mozilla/layout/html/base/src/nsDST.h index b7f31314033..0f3b9da4e55 100644 --- a/mozilla/layout/html/base/src/nsDST.h +++ b/mozilla/layout/html/base/src/nsDST.h @@ -21,7 +21,7 @@ #ifdef HAVE_MEMORY_H #include #endif -#include "plarena.h" +#include "nsError.h" #ifdef NS_DEBUG #include #endif @@ -34,6 +34,16 @@ public: virtual void operator() (void* aKey, void* aValue) = 0; // call operator }; +// Option flags for Search() member function +#define NS_DST_REMOVE_KEY_VALUE 0x0001 + +// nsresult error codes +#define NS_DST_KEY_NOT_THERE \ + NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 1) + +#define NS_DST_VALUE_OVERWRITTEN \ + NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 2) + /** * Digital search tree for doing a radix-search of pointer-based keys */ @@ -57,11 +67,11 @@ public: nsDST(NodeArena* aArena, PtrBits aLevelZeroBit = 0x04); ~nsDST(); - void* Search(void* aKey) const; - void* Insert(void* aKey, void* aValue); // returns the previous value (or 0) - void* Remove(void* aKey); // returns the current value (or 0) - void Clear(); - void Enumerate(nsDSTNodeFunctor& aFunctor) const; + nsresult Search(void* aKey, unsigned aOptions, void** aValue); + nsresult Insert(void* aKey, void* aValue, void** aOldValue); + nsresult Remove(void* aKey); + nsresult Clear(); + nsresult Enumerate(nsDSTNodeFunctor& aFunctor) const; #ifdef NS_DEBUG void Dump(FILE*) const; @@ -90,6 +100,7 @@ private: TwoNode* ConvertToTwoNode(LeafNode** aLeafNode); void EnumTree(LeafNode* aNode, nsDSTNodeFunctor& aFunctor) const; void FreeTree(LeafNode* aNode); + nsresult SearchTree(void* aKey, unsigned aOptions, void** aValue); #ifdef NS_DEBUG // Diagnostic functions diff --git a/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp b/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp index dd24b144921..d424ef07859 100644 --- a/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp +++ b/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp @@ -247,14 +247,14 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, // And then push it to our overflow list if (nextInFlow) { kid->SetNextSibling(nsnull); - mOverflowFrames.SetFrames(nextInFlow); + SetOverflowFrames(&aPresContext, nextInFlow); } else { nsIFrame* nextSib; kid->GetNextSibling(&nextSib); if (nextSib) { kid->SetNextSibling(nsnull); - mOverflowFrames.SetFrames(nextSib); + SetOverflowFrames(&aPresContext, nextSib); } } } @@ -265,27 +265,31 @@ nsFirstLetterFrame::Reflow(nsIPresContext& aPresContext, void nsFirstLetterFrame::DrainOverflowFrames(nsIPresContext* aPresContext) { + nsIFrame* overflowFrames; + // Check for an overflow list with our prev-in-flow nsFirstLetterFrame* prevInFlow = (nsFirstLetterFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + overflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.IsEmpty(), "bad overflow list"); // When pushing and pulling frames we need to check for whether any // views need to be reparented. - nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); + nsIFrame* f = overflowFrames; while (f) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); f->GetNextSibling(&f); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, overflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); } // Now repair our first frames style context XXX only first frame? diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index 905375ee3c3..b2dd9bf9c60 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -230,10 +230,10 @@ public: nsIAtom* aPropertyName, PRUint32 aOptions, void** aPropertyValue); - NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue, - FMPropertyDtorFunc aPropDtorFunc); + NS_IMETHOD SetFrameProperty(nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue, + NSFMPropertyDtorFunc aPropDtorFunc); NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName); @@ -243,22 +243,22 @@ public: private: struct PropertyList { - nsCOMPtr mName; // property name - nsDST* mFrameValueMap; // map of frame/value pairs - FMPropertyDtorFunc mDtorFunc; // property specific value dtor function - PropertyList* mNext; + nsCOMPtr mName; // property name + nsDST* mFrameValueMap; // map of frame/value pairs + NSFMPropertyDtorFunc mDtorFunc; // property specific value dtor function + PropertyList* mNext; - PropertyList(nsIAtom* aName, - FMPropertyDtorFunc aDtorFunc, - nsDST::NodeArena* aDSTNodeArena); + PropertyList(nsIAtom* aName, + NSFMPropertyDtorFunc aDtorFunc, + nsDST::NodeArena* aDSTNodeArena); ~PropertyList(); // Removes the property associated with the given frame, and destroys // the property value - void RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame); + PRBool RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame); // Remove and destroy all remaining properties - void RemoveAllProperties(nsIPresContext* aPresContext); + void RemoveAllProperties(nsIPresContext* aPresContext); }; nsIPresShell* mPresShell; // weak link, because the pres shell owns us @@ -298,7 +298,7 @@ private: NS_LAYOUT nsresult NS_NewFrameManager(nsIFrameManager** aInstancePtrResult) { - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); + NS_ENSURE_ARG_POINTER(aInstancePtrResult); if (!aInstancePtrResult) { return NS_ERROR_NULL_POINTER; } @@ -392,14 +392,14 @@ FrameManager::SetRootFrame(nsIFrame* aRootFrame) NS_IMETHODIMP FrameManager::GetPrimaryFrameFor(nsIContent* aContent, nsIFrame** aResult) { - NS_PRECONDITION(aResult, "null ptr"); - NS_PRECONDITION(aContent, "no content object"); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_ARG_POINTER(aContent); if (!aResult) { return NS_ERROR_NULL_POINTER; } if (mPrimaryFrameMap) { - *aResult = (nsIFrame*)mPrimaryFrameMap->Search(aContent); + mPrimaryFrameMap->Search(aContent, 0, (void**)aResult); if (!*aResult) { nsCOMPtr styleSet; nsCOMPtr presContext; @@ -421,7 +421,7 @@ NS_IMETHODIMP FrameManager::SetPrimaryFrameFor(nsIContent* aContent, nsIFrame* aPrimaryFrame) { - NS_PRECONDITION(aContent, "no content object"); + NS_ENSURE_ARG_POINTER(aContent); // If aPrimaryFrame is NULL, then remove the mapping if (!aPrimaryFrame) { @@ -438,7 +438,7 @@ FrameManager::SetPrimaryFrameFor(nsIContent* aContent, } // Add a mapping to the hash table - mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame); + mPrimaryFrameMap->Insert(aContent, (void*)aPrimaryFrame, nsnull); } return NS_OK; } @@ -457,8 +457,8 @@ NS_IMETHODIMP FrameManager::GetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame** aResult) const { - NS_PRECONDITION(aResult, "null ptr"); - NS_PRECONDITION(aFrame, "no frame"); + NS_ENSURE_ARG_POINTER(aResult); + NS_ENSURE_ARG_POINTER(aFrame); if (!aResult || !aFrame) { return NS_ERROR_NULL_POINTER; } @@ -476,7 +476,7 @@ NS_IMETHODIMP FrameManager::SetPlaceholderFrameFor(nsIFrame* aFrame, nsIFrame* aPlaceholderFrame) { - NS_PRECONDITION(aFrame, "no frame"); + NS_ENSURE_ARG_POINTER(aFrame); #ifdef NS_DEBUG // Verify that the placeholder frame is of the correct type if (aPlaceholderFrame) { @@ -1597,31 +1597,30 @@ FrameManager::GetFrameProperty(nsIFrame* aFrame, PRUint32 aOptions, void** aPropertyValue) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result; if (propertyList) { - // See if we should also remove the property - if (aOptions & NS_IFRAME_MGR_REMOVE_PROPERTY) { - *aPropertyValue = propertyList->mFrameValueMap->Remove(aFrame); - } else { - *aPropertyValue = propertyList->mFrameValueMap->Search(aFrame); - } + result = propertyList->mFrameValueMap->Search(aFrame, aOptions, aPropertyValue); + } else { *aPropertyValue = 0; + result = NS_IFRAME_MGR_PROP_NOT_THERE; } - return NS_OK; + return result; } NS_IMETHODIMP -FrameManager::SetFrameProperty(nsIFrame* aFrame, - nsIAtom* aPropertyName, - void* aPropertyValue, - FMPropertyDtorFunc aPropDtorFunc) +FrameManager::SetFrameProperty(nsIFrame* aFrame, + nsIAtom* aPropertyName, + void* aPropertyValue, + NSFMPropertyDtorFunc aPropDtorFunc) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result = NS_OK; if (propertyList) { // Make sure the dtor function matches @@ -1641,34 +1640,38 @@ FrameManager::SetFrameProperty(nsIFrame* aFrame, // The current property value (if there is one) is replaced and the current // value is destroyed - void* aOldValue; - - aOldValue = propertyList->mFrameValueMap->Insert(aFrame, aPropertyValue); - if (aOldValue && propertyList->mDtorFunc) { - nsCOMPtr presContext; - mPresShell->GetPresContext(getter_AddRefs(presContext)); - - propertyList->mDtorFunc(presContext, aFrame, aPropertyName, aOldValue); + void* oldValue; + result = propertyList->mFrameValueMap->Insert(aFrame, aPropertyValue, &oldValue); + if (NS_DST_VALUE_OVERWRITTEN == result) { + if (propertyList->mDtorFunc) { + nsCOMPtr presContext; + mPresShell->GetPresContext(getter_AddRefs(presContext)); + + propertyList->mDtorFunc(presContext, aFrame, aPropertyName, oldValue); + } } - return NS_OK; + return result; } NS_IMETHODIMP FrameManager::RemoveFrameProperty(nsIFrame* aFrame, nsIAtom* aPropertyName) { - NS_PRECONDITION(aPropertyName, "null property name atom"); + NS_ENSURE_ARG_POINTER(aPropertyName); PropertyList* propertyList = GetPropertyListFor(aPropertyName); + nsresult result = NS_IFRAME_MGR_PROP_NOT_THERE; if (propertyList) { nsCOMPtr presContext; mPresShell->GetPresContext(getter_AddRefs(presContext)); - propertyList->RemovePropertyForFrame(presContext, aFrame); + if (propertyList->RemovePropertyForFrame(presContext, aFrame)) { + result = NS_OK; + } } - return NS_OK; + return result; } //---------------------------------------------------------------------- @@ -1825,9 +1828,9 @@ UndisplayedMap::Clear(void) //---------------------------------------------------------------------- -FrameManager::PropertyList::PropertyList(nsIAtom* aName, - FMPropertyDtorFunc aDtorFunc, - nsDST::NodeArena* aDSTNodeArena) +FrameManager::PropertyList::PropertyList(nsIAtom* aName, + NSFMPropertyDtorFunc aDtorFunc, + nsDST::NodeArena* aDSTNodeArena) : mName(aName), mFrameValueMap(new nsDST(aDSTNodeArena)), mDtorFunc(aDtorFunc), mNext(nsnull) { @@ -1840,18 +1843,18 @@ FrameManager::PropertyList::~PropertyList() class DestroyPropertyValuesFunctor : public nsDSTNodeFunctor { public: - DestroyPropertyValuesFunctor(nsIPresContext* aPresContext, - nsIAtom* aPropertyName, - FMPropertyDtorFunc aDtorFunc) + DestroyPropertyValuesFunctor(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + NSFMPropertyDtorFunc aDtorFunc) : mPresContext(aPresContext), mPropertyName(aPropertyName), mDtorFunc(aDtorFunc) {} virtual void operator () (void *aKey, void *aValue) { mDtorFunc(mPresContext, (nsIFrame*)aKey, mPropertyName, aValue); } - nsIPresContext* mPresContext; - nsIAtom* mPropertyName; - FMPropertyDtorFunc mDtorFunc; + nsIPresContext* mPresContext; + nsIAtom* mPropertyName; + NSFMPropertyDtorFunc mDtorFunc; }; void @@ -1865,15 +1868,27 @@ FrameManager::PropertyList::RemoveAllProperties(nsIPresContext* aPresContext) } } -void +PRBool FrameManager::PropertyList::RemovePropertyForFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) { - void* value = mFrameValueMap->Remove(aFrame); + void* value; + nsresult result; + + // If the property exists, then we need to run the dtor function so + // do a search with the option to remove the key/value pair + result = mFrameValueMap->Search(aFrame, NS_DST_REMOVE_KEY_VALUE, &value); - if (value && mDtorFunc) { - // Destroy the property value - mDtorFunc(aPresContext, aFrame, mName, value); + if (NS_OK == result) { + // The property was set + if (mDtorFunc) { + // Destroy the property value + mDtorFunc(aPresContext, aFrame, mName, value); + } + + return PR_TRUE; } + + return PR_FALSE; } diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index 5ce31c5547f..a22d279056d 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -1348,23 +1348,26 @@ nsInlineFrame::DrainOverflow(nsIPresContext* aPresContext) // Check for an overflow list with our prev-in-flow nsInlineFrame* prevInFlow = (nsInlineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + + if (prevOverflowFrames) { // When pushing and pulling frames we need to check for whether any // views need to be reparented. // XXX Doing it this way means an extra pass over the frames. We could // change InsertFrames() to do this, but that's a general purpose // function and it doesn't seem like this functionality belongs there... - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - mFrames.AppendFrames(nsnull, mOverflowFrames); + mFrames.AppendFrames(nsnull, overflowFrames); } } @@ -1441,7 +1444,8 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext, #ifdef DEBUG if (NS_FRAME_COMPLETE == aStatus) { // We can't be complete AND have overflow frames! - NS_ASSERTION(mOverflowFrames.IsEmpty(), "whoops"); + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_FALSE); + NS_ASSERTION(!overflowFrames, "whoops"); } #endif @@ -1682,8 +1686,7 @@ nsInlineFrame::PushFrames(nsIPresContext* aPresContext, // Add the frames to our overflow list (let our next in flow drain // our overflow list when it is ready) - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } nsresult @@ -1781,7 +1784,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext* aPresContext, nsInlineFrame* nextInFlow = (nsInlineFrame*) mNextInFlow; while (nsnull != nextInFlow) { if (nextInFlow->mFrames.NotEmpty() || - nextInFlow->mOverflowFrames.NotEmpty()) { + nextInFlow->GetOverflowFrames(aPresContext, PR_FALSE)) { aStatus |= NS_FRAME_NOT_COMPLETE; break; } @@ -2013,18 +2016,23 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) // Check for an overflow list with our prev-in-flow nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { - ReParentChildListStyle(aPresContext, mStyleContext, - prevInFlow->mOverflowFrames); - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (prevOverflowFrames) { + nsFrameList frames(prevOverflowFrames); + + ReParentChildListStyle(aPresContext, mStyleContext, frames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - ReParentChildListStyle(aPresContext, mStyleContext, mOverflowFrames); - mFrames.AppendFrames(nsnull, mOverflowFrames); + nsFrameList frames(overflowFrames); + + ReParentChildListStyle(aPresContext, mStyleContext, frames); + mFrames.AppendFrames(nsnull, overflowFrames); } } diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index e713d000e7b..b91854d4aaf 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -2457,7 +2457,9 @@ nsTableFrame::GetFirstBodyRowGroupFrame() // Table specific version that takes into account repeated header and footer // frames when continuing table frames void -nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) +nsTableFrame::PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling) { NS_PRECONDITION(nsnull != aFromChild, "null pointer"); NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child"); @@ -2488,8 +2490,7 @@ nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) } else { // Add the frames to our overflow list - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } } @@ -2501,27 +2502,29 @@ nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) // the child list is empty (it may not be empty, because there may be repeated // header/footer frames) PRBool -nsTableFrame::MoveOverflowToChildList() +nsTableFrame::MoveOverflowToChildList(nsIPresContext* aPresContext) { PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow nsTableFrame* prevInFlow = (nsTableFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (prevOverflowFrames) { // When pushing and pulling frames we need to check for whether any // views need to be reparented. - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); result = PR_TRUE; } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { - mFrames.AppendFrames(nsnull, mOverflowFrames); + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { + mFrames.AppendFrames(nsnull, overflowFrames); result = PR_TRUE; } return result; @@ -2559,7 +2562,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext, // Check for an overflow list, and append any row group frames being // pushed - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Reflow the existing frames if (mFrames.NotEmpty()) { @@ -3581,7 +3584,7 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, if (aReflowState.firstBodySection && (kidFrame != aReflowState.firstBodySection)) { // The child is too tall to fit at all in the available space, and it's // not a header/footer or our first row group frame - PushChildren(kidFrame, prevKidFrame); + PushChildren(&aPresContext, kidFrame, prevKidFrame); aStatus = NS_FRAME_NOT_COMPLETE; break; } @@ -3635,7 +3638,7 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, kidFrame->GetNextSibling(&nextSibling); if (nsnull != nextSibling) { - PushChildren(nextSibling, kidFrame); + PushChildren(&aPresContext, nextSibling, kidFrame); } break; } @@ -3688,9 +3691,10 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, // Any more child frames? if (nsnull == kidFrame) { // No. Any frames on its overflow list? - if (nextInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* nextOverflowFrames = nextInFlow->GetOverflowFrames(&aPresContext, PR_TRUE); + if (nextOverflowFrames) { // Move the overflow list to become the child list - nextInFlow->mFrames.AppendFrames(nsnull, nextInFlow->mOverflowFrames); + nextInFlow->mFrames.AppendFrames(nsnull, nextOverflowFrames); kidFrame = nextInFlow->mFrames.FirstChild(); } else { // We've pulled up all the children, so move to the next-in-flow. @@ -3777,7 +3781,7 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, // we pass PR_TRUE into PushChidren kidFrame->SetNextSibling(continuingFrame); - PushChildren(continuingFrame, kidFrame); + PushChildren(&aPresContext, continuingFrame, kidFrame); } break; } diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index b527dff44f3..2ace8cc115c 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -659,8 +659,10 @@ protected: virtual PRBool IsColumnWidthsValid() const; nsIFrame* GetFirstBodyRowGroupFrame(); - PRBool MoveOverflowToChildList(); - void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling); + PRBool MoveOverflowToChildList(nsIPresContext* aPresContext); + void PushChildren(nsIPresContext *aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling); public: // Returns PR_TRUE if there are any cells above the row at diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp index a731a37812d..2b3a35c7d6e 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp @@ -855,7 +855,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Initial == aReflowState.reason) { // Set up our kids. They're already present, on an overflow list, // or there are none so we'll create them now - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Lay out the caption and get its maximum element size if (nsnull != mCaptionFrame) { diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp index 267c602100b..2555443bafc 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -523,9 +523,11 @@ NS_METHOD nsTableRowGroupFrame::PullUpAllRowFrames(nsIPresContext& aPresContext) while (nsnull != nextInFlow) { // Any frames on the next-in-flow's overflow list? - if (nextInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* nextOverflowFrames = nextInFlow->GetOverflowFrames(&aPresContext, + PR_TRUE); + if (nextOverflowFrames) { // Yes, append them to its child list - nextInFlow->mFrames.AppendFrames(nextInFlow, nextInFlow->mOverflowFrames); + nextInFlow->mFrames.AppendFrames(nextInFlow, nextOverflowFrames); } // Any row frames? @@ -901,7 +903,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, GetNextFrame(rowFrame, &contRowFrame); // Push the continuing row frame and the frames that follow - PushChildren(contRowFrame, rowFrame); + PushChildren(&aPresContext, contRowFrame, rowFrame); aStatus = NS_FRAME_NOT_COMPLETE; } else { @@ -913,7 +915,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, GetNextFrame(rowFrame, &nextRowFrame); if (nextRowFrame) { - PushChildren(nextRowFrame, rowFrame); + PushChildren(&aPresContext, nextRowFrame, rowFrame); } aStatus = nextRowFrame ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; } @@ -971,7 +973,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, } // Push this row frame and those that follow to the next-in-flow - PushChildren(rowFrame, prevRowFrame); + PushChildren(&aPresContext, rowFrame, prevRowFrame); aStatus = NS_FRAME_NOT_COMPLETE; aDesiredSize.height = bounds.y; } @@ -1019,7 +1021,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, aStatus = NS_FRAME_COMPLETE; // Check for an overflow list - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Reflow the existing frames. Before we do, pull-up any row frames from // our next-in-flow. diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index e713d000e7b..b91854d4aaf 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -2457,7 +2457,9 @@ nsTableFrame::GetFirstBodyRowGroupFrame() // Table specific version that takes into account repeated header and footer // frames when continuing table frames void -nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) +nsTableFrame::PushChildren(nsIPresContext* aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling) { NS_PRECONDITION(nsnull != aFromChild, "null pointer"); NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child"); @@ -2488,8 +2490,7 @@ nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) } else { // Add the frames to our overflow list - NS_ASSERTION(mOverflowFrames.IsEmpty(), "bad overflow list"); - mOverflowFrames.SetFrames(aFromChild); + SetOverflowFrames(aPresContext, aFromChild); } } @@ -2501,27 +2502,29 @@ nsTableFrame::PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling) // the child list is empty (it may not be empty, because there may be repeated // header/footer frames) PRBool -nsTableFrame::MoveOverflowToChildList() +nsTableFrame::MoveOverflowToChildList(nsIPresContext* aPresContext) { PRBool result = PR_FALSE; // Check for an overflow list with our prev-in-flow nsTableFrame* prevInFlow = (nsTableFrame*)mPrevInFlow; if (nsnull != prevInFlow) { - if (prevInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* prevOverflowFrames = prevInFlow->GetOverflowFrames(aPresContext, PR_TRUE); + if (prevOverflowFrames) { // When pushing and pulling frames we need to check for whether any // views need to be reparented. - for (nsIFrame* f = prevInFlow->mOverflowFrames.FirstChild(); f; f->GetNextSibling(&f)) { + for (nsIFrame* f = prevOverflowFrames; f; f->GetNextSibling(&f)) { nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this); } - mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); + mFrames.InsertFrames(this, nsnull, prevOverflowFrames); result = PR_TRUE; } } // It's also possible that we have an overflow list for ourselves - if (mOverflowFrames.NotEmpty()) { - mFrames.AppendFrames(nsnull, mOverflowFrames); + nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE); + if (overflowFrames) { + mFrames.AppendFrames(nsnull, overflowFrames); result = PR_TRUE; } return result; @@ -2559,7 +2562,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext, // Check for an overflow list, and append any row group frames being // pushed - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Reflow the existing frames if (mFrames.NotEmpty()) { @@ -3581,7 +3584,7 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, if (aReflowState.firstBodySection && (kidFrame != aReflowState.firstBodySection)) { // The child is too tall to fit at all in the available space, and it's // not a header/footer or our first row group frame - PushChildren(kidFrame, prevKidFrame); + PushChildren(&aPresContext, kidFrame, prevKidFrame); aStatus = NS_FRAME_NOT_COMPLETE; break; } @@ -3635,7 +3638,7 @@ NS_METHOD nsTableFrame::ReflowMappedChildren(nsIPresContext& aPresContext, kidFrame->GetNextSibling(&nextSibling); if (nsnull != nextSibling) { - PushChildren(nextSibling, kidFrame); + PushChildren(&aPresContext, nextSibling, kidFrame); } break; } @@ -3688,9 +3691,10 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, // Any more child frames? if (nsnull == kidFrame) { // No. Any frames on its overflow list? - if (nextInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* nextOverflowFrames = nextInFlow->GetOverflowFrames(&aPresContext, PR_TRUE); + if (nextOverflowFrames) { // Move the overflow list to become the child list - nextInFlow->mFrames.AppendFrames(nsnull, nextInFlow->mOverflowFrames); + nextInFlow->mFrames.AppendFrames(nsnull, nextOverflowFrames); kidFrame = nextInFlow->mFrames.FirstChild(); } else { // We've pulled up all the children, so move to the next-in-flow. @@ -3777,7 +3781,7 @@ NS_METHOD nsTableFrame::PullUpChildren(nsIPresContext& aPresContext, // we pass PR_TRUE into PushChidren kidFrame->SetNextSibling(continuingFrame); - PushChildren(continuingFrame, kidFrame); + PushChildren(&aPresContext, continuingFrame, kidFrame); } break; } diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index b527dff44f3..2ace8cc115c 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -659,8 +659,10 @@ protected: virtual PRBool IsColumnWidthsValid() const; nsIFrame* GetFirstBodyRowGroupFrame(); - PRBool MoveOverflowToChildList(); - void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling); + PRBool MoveOverflowToChildList(nsIPresContext* aPresContext); + void PushChildren(nsIPresContext *aPresContext, + nsIFrame* aFromChild, + nsIFrame* aPrevSibling); public: // Returns PR_TRUE if there are any cells above the row at diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp index a731a37812d..2b3a35c7d6e 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.cpp +++ b/mozilla/layout/tables/nsTableOuterFrame.cpp @@ -855,7 +855,7 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Initial == aReflowState.reason) { // Set up our kids. They're already present, on an overflow list, // or there are none so we'll create them now - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Lay out the caption and get its maximum element size if (nsnull != mCaptionFrame) { diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index 267c602100b..2555443bafc 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -523,9 +523,11 @@ NS_METHOD nsTableRowGroupFrame::PullUpAllRowFrames(nsIPresContext& aPresContext) while (nsnull != nextInFlow) { // Any frames on the next-in-flow's overflow list? - if (nextInFlow->mOverflowFrames.NotEmpty()) { + nsIFrame* nextOverflowFrames = nextInFlow->GetOverflowFrames(&aPresContext, + PR_TRUE); + if (nextOverflowFrames) { // Yes, append them to its child list - nextInFlow->mFrames.AppendFrames(nextInFlow, nextInFlow->mOverflowFrames); + nextInFlow->mFrames.AppendFrames(nextInFlow, nextOverflowFrames); } // Any row frames? @@ -901,7 +903,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, GetNextFrame(rowFrame, &contRowFrame); // Push the continuing row frame and the frames that follow - PushChildren(contRowFrame, rowFrame); + PushChildren(&aPresContext, contRowFrame, rowFrame); aStatus = NS_FRAME_NOT_COMPLETE; } else { @@ -913,7 +915,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, GetNextFrame(rowFrame, &nextRowFrame); if (nextRowFrame) { - PushChildren(nextRowFrame, rowFrame); + PushChildren(&aPresContext, nextRowFrame, rowFrame); } aStatus = nextRowFrame ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE; } @@ -971,7 +973,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext& aPresContext, } // Push this row frame and those that follow to the next-in-flow - PushChildren(rowFrame, prevRowFrame); + PushChildren(&aPresContext, rowFrame, prevRowFrame); aStatus = NS_FRAME_NOT_COMPLETE; aDesiredSize.height = bounds.y; } @@ -1019,7 +1021,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext, aStatus = NS_FRAME_COMPLETE; // Check for an overflow list - MoveOverflowToChildList(); + MoveOverflowToChildList(&aPresContext); // Reflow the existing frames. Before we do, pull-up any row frames from // our next-in-flow.