diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 68dc3d8e98b..7f2ee3e321b 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -652,13 +652,290 @@ GetChildListNameFor(nsIPresContext* aPresContext, *aListName = listName; } +class GeneratedContentIterator : public nsIContentIterator +{ +public: + GeneratedContentIterator(nsIPresContext* aPresContext, nsIFrame* aFrame); + virtual ~GeneratedContentIterator(); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIContentIterator + NS_IMETHOD Init(nsIContent* aRoot); + NS_IMETHOD Init(nsIDOMRange* aRange); + + NS_IMETHOD First(); + NS_IMETHOD Last(); + NS_IMETHOD Next(); + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + NS_IMETHOD IsDone(); + NS_IMETHOD PositionAt(nsIContent* aCurNode); + + NS_IMETHOD MakePre(); + NS_IMETHOD MakePost(); + +private: + nsCOMPtr mPresContext; + nsIFrame* mParentFrame; + nsIFrame* mCurrentChild; + PRBool mIsDone; +}; + +GeneratedContentIterator::GeneratedContentIterator(nsIPresContext* aPresContext, + nsIFrame* aFrame) + : mPresContext(aPresContext), mParentFrame(aFrame), mIsDone(PR_FALSE) +{ + NS_INIT_REFCNT(); + First(); +} + +NS_IMPL_ISUPPORTS(GeneratedContentIterator, NS_GET_IID(nsIContentIterator)); + +GeneratedContentIterator::~GeneratedContentIterator() +{ +} + +NS_IMETHODIMP +GeneratedContentIterator::Init(nsIContent* aRoot) +{ + return NS_ERROR_ALREADY_INITIALIZED; +} + +NS_IMETHODIMP +GeneratedContentIterator::Init(nsIDOMRange* aRange) +{ + return NS_ERROR_ALREADY_INITIALIZED; +} + +NS_IMETHODIMP +GeneratedContentIterator::First() +{ + // Get the first child frame and make it the current node + mParentFrame->FirstChild(mPresContext, nsnull, &mCurrentChild); + if (!mCurrentChild) { + return NS_ERROR_FAILURE; + } + mIsDone = PR_FALSE; + return NS_OK; +} + +static nsIFrame* +GetNextChildFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null pointer"); + + // Get the last-in-flow + while (PR_TRUE) { + nsIFrame* nextInFlow; + aFrame->GetNextInFlow(&nextInFlow); + if (nextInFlow) { + aFrame = nextInFlow; + } else { + break; + } + } + + // Get its next sibling + nsIFrame* nextSibling; + aFrame->GetNextSibling(&nextSibling); + + // If there's no next sibling, then check if the parent frame + // has a next-in-flow and look there + if (!nextSibling) { + nsIFrame* parent; + aFrame->GetParent(&parent); + parent->GetNextInFlow(&parent); + + if (parent) { + parent->FirstChild(aPresContext, nsnull, &nextSibling); + } + } + + return nextSibling; +} + +NS_IMETHODIMP +GeneratedContentIterator::Last() +{ + nsIFrame* nextChild; + + // Starting with the first child walk and find the last child + mCurrentChild = nsnull; + mParentFrame->FirstChild(mPresContext, nsnull, &nextChild); + while (nextChild) { + mCurrentChild = nextChild; + nextChild = ::GetNextChildFrame(mPresContext, nextChild); + } + + if (!mCurrentChild) { + return NS_ERROR_FAILURE; + } + mIsDone = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +GeneratedContentIterator::Next() +{ + nsIFrame* nextChild = ::GetNextChildFrame(mPresContext, mCurrentChild); + + if (nextChild) { + // Advance to the next child + mCurrentChild = nextChild; + + // If we're at the end then the collection is at the end + mIsDone = (nsnull == ::GetNextChildFrame(mPresContext, mCurrentChild)); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +static nsIFrame* +GetPrevChildFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null pointer"); + + // Get its previous sibling. Because we have a singly linked list we + // need to search from the first child + nsIFrame* parent; + nsIFrame* firstChild; + nsIFrame* prevSibling; + + aFrame->GetParent(&parent); + parent->FirstChild(aPresContext, nsnull, &firstChild); + + NS_ASSERTION(firstChild, "parent has no first child"); + nsFrameList frameList(firstChild); + prevSibling = frameList.GetPrevSiblingFor(aFrame); + + // If there's no previous sibling, then check if the parent frame + // has a prev-in-flow and look there + if (!prevSibling) { + parent->GetPrevInFlow(&parent); + + if (parent) { + parent->FirstChild(aPresContext, nsnull, &firstChild); + frameList.SetFrames(firstChild); + prevSibling = frameList.LastChild(); + } + } + + // Get the first-in-flow + while (PR_TRUE) { + nsIFrame* prevInFlow; + prevSibling->GetPrevInFlow(&prevInFlow); + if (prevInFlow) { + prevSibling = prevInFlow; + } else { + break; + } + } + + return prevSibling; +} + +NS_IMETHODIMP +GeneratedContentIterator::Prev() +{ + nsIFrame* prevChild = ::GetPrevChildFrame(mPresContext, mCurrentChild); + + if (prevChild) { + // Make the previous child the current child + mCurrentChild = prevChild; + + // If we're at the beginning then the collection is at the end + mIsDone = (nsnull == ::GetPrevChildFrame(mPresContext, mCurrentChild)); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +GeneratedContentIterator::CurrentNode(nsIContent **aNode) +{ + if (mCurrentChild) { + mCurrentChild->GetContent(aNode); + return NS_OK; + + } else { + *aNode = nsnull; + return NS_ERROR_FAILURE; + } +} + +NS_IMETHODIMP +GeneratedContentIterator::IsDone() +{ + return mIsDone ? NS_OK : NS_ENUMERATOR_FALSE; +} + +NS_IMETHODIMP +GeneratedContentIterator::PositionAt(nsIContent* aCurNode) +{ + nsIFrame* child; + + // Starting with the first child frame search for the child frame + // with the matching content object + mParentFrame->FirstChild(mPresContext, nsnull, &child); + while (child) { + nsCOMPtr content; + + child->GetContent(getter_AddRefs(content)); + if (content.get() == aCurNode) { + break; + } + child = ::GetNextChildFrame(mPresContext, child); + } + + if (child) { + // Make it the current child + mCurrentChild = child; + mIsDone = PR_FALSE; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +GeneratedContentIterator::MakePre() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GeneratedContentIterator::MakePost() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + nsresult NS_NewGeneratedContentIterator(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIContentIterator** aIterator) { - *aIterator = nsnull; - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_ARG_POINTER(aIterator); + if (!aIterator) { + return NS_ERROR_NULL_POINTER; + } + + // Make sure the frame corresponds to generated content +#ifdef DEBUG + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + NS_ASSERTION(frameState & NS_FRAME_GENERATED_CONTENT, "unexpected frame"); +#endif + + GeneratedContentIterator* it = new GeneratedContentIterator(aPresContext, aFrame); + if (!it) { + return NS_ERROR_OUT_OF_MEMORY; + } + return it->QueryInterface(NS_GET_IID(nsIContentIterator), (void **)aIterator); } nsresult diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 68dc3d8e98b..7f2ee3e321b 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -652,13 +652,290 @@ GetChildListNameFor(nsIPresContext* aPresContext, *aListName = listName; } +class GeneratedContentIterator : public nsIContentIterator +{ +public: + GeneratedContentIterator(nsIPresContext* aPresContext, nsIFrame* aFrame); + virtual ~GeneratedContentIterator(); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIContentIterator + NS_IMETHOD Init(nsIContent* aRoot); + NS_IMETHOD Init(nsIDOMRange* aRange); + + NS_IMETHOD First(); + NS_IMETHOD Last(); + NS_IMETHOD Next(); + NS_IMETHOD Prev(); + + NS_IMETHOD CurrentNode(nsIContent **aNode); + NS_IMETHOD IsDone(); + NS_IMETHOD PositionAt(nsIContent* aCurNode); + + NS_IMETHOD MakePre(); + NS_IMETHOD MakePost(); + +private: + nsCOMPtr mPresContext; + nsIFrame* mParentFrame; + nsIFrame* mCurrentChild; + PRBool mIsDone; +}; + +GeneratedContentIterator::GeneratedContentIterator(nsIPresContext* aPresContext, + nsIFrame* aFrame) + : mPresContext(aPresContext), mParentFrame(aFrame), mIsDone(PR_FALSE) +{ + NS_INIT_REFCNT(); + First(); +} + +NS_IMPL_ISUPPORTS(GeneratedContentIterator, NS_GET_IID(nsIContentIterator)); + +GeneratedContentIterator::~GeneratedContentIterator() +{ +} + +NS_IMETHODIMP +GeneratedContentIterator::Init(nsIContent* aRoot) +{ + return NS_ERROR_ALREADY_INITIALIZED; +} + +NS_IMETHODIMP +GeneratedContentIterator::Init(nsIDOMRange* aRange) +{ + return NS_ERROR_ALREADY_INITIALIZED; +} + +NS_IMETHODIMP +GeneratedContentIterator::First() +{ + // Get the first child frame and make it the current node + mParentFrame->FirstChild(mPresContext, nsnull, &mCurrentChild); + if (!mCurrentChild) { + return NS_ERROR_FAILURE; + } + mIsDone = PR_FALSE; + return NS_OK; +} + +static nsIFrame* +GetNextChildFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null pointer"); + + // Get the last-in-flow + while (PR_TRUE) { + nsIFrame* nextInFlow; + aFrame->GetNextInFlow(&nextInFlow); + if (nextInFlow) { + aFrame = nextInFlow; + } else { + break; + } + } + + // Get its next sibling + nsIFrame* nextSibling; + aFrame->GetNextSibling(&nextSibling); + + // If there's no next sibling, then check if the parent frame + // has a next-in-flow and look there + if (!nextSibling) { + nsIFrame* parent; + aFrame->GetParent(&parent); + parent->GetNextInFlow(&parent); + + if (parent) { + parent->FirstChild(aPresContext, nsnull, &nextSibling); + } + } + + return nextSibling; +} + +NS_IMETHODIMP +GeneratedContentIterator::Last() +{ + nsIFrame* nextChild; + + // Starting with the first child walk and find the last child + mCurrentChild = nsnull; + mParentFrame->FirstChild(mPresContext, nsnull, &nextChild); + while (nextChild) { + mCurrentChild = nextChild; + nextChild = ::GetNextChildFrame(mPresContext, nextChild); + } + + if (!mCurrentChild) { + return NS_ERROR_FAILURE; + } + mIsDone = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +GeneratedContentIterator::Next() +{ + nsIFrame* nextChild = ::GetNextChildFrame(mPresContext, mCurrentChild); + + if (nextChild) { + // Advance to the next child + mCurrentChild = nextChild; + + // If we're at the end then the collection is at the end + mIsDone = (nsnull == ::GetNextChildFrame(mPresContext, mCurrentChild)); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +static nsIFrame* +GetPrevChildFrame(nsIPresContext* aPresContext, nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "null pointer"); + + // Get its previous sibling. Because we have a singly linked list we + // need to search from the first child + nsIFrame* parent; + nsIFrame* firstChild; + nsIFrame* prevSibling; + + aFrame->GetParent(&parent); + parent->FirstChild(aPresContext, nsnull, &firstChild); + + NS_ASSERTION(firstChild, "parent has no first child"); + nsFrameList frameList(firstChild); + prevSibling = frameList.GetPrevSiblingFor(aFrame); + + // If there's no previous sibling, then check if the parent frame + // has a prev-in-flow and look there + if (!prevSibling) { + parent->GetPrevInFlow(&parent); + + if (parent) { + parent->FirstChild(aPresContext, nsnull, &firstChild); + frameList.SetFrames(firstChild); + prevSibling = frameList.LastChild(); + } + } + + // Get the first-in-flow + while (PR_TRUE) { + nsIFrame* prevInFlow; + prevSibling->GetPrevInFlow(&prevInFlow); + if (prevInFlow) { + prevSibling = prevInFlow; + } else { + break; + } + } + + return prevSibling; +} + +NS_IMETHODIMP +GeneratedContentIterator::Prev() +{ + nsIFrame* prevChild = ::GetPrevChildFrame(mPresContext, mCurrentChild); + + if (prevChild) { + // Make the previous child the current child + mCurrentChild = prevChild; + + // If we're at the beginning then the collection is at the end + mIsDone = (nsnull == ::GetPrevChildFrame(mPresContext, mCurrentChild)); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +GeneratedContentIterator::CurrentNode(nsIContent **aNode) +{ + if (mCurrentChild) { + mCurrentChild->GetContent(aNode); + return NS_OK; + + } else { + *aNode = nsnull; + return NS_ERROR_FAILURE; + } +} + +NS_IMETHODIMP +GeneratedContentIterator::IsDone() +{ + return mIsDone ? NS_OK : NS_ENUMERATOR_FALSE; +} + +NS_IMETHODIMP +GeneratedContentIterator::PositionAt(nsIContent* aCurNode) +{ + nsIFrame* child; + + // Starting with the first child frame search for the child frame + // with the matching content object + mParentFrame->FirstChild(mPresContext, nsnull, &child); + while (child) { + nsCOMPtr content; + + child->GetContent(getter_AddRefs(content)); + if (content.get() == aCurNode) { + break; + } + child = ::GetNextChildFrame(mPresContext, child); + } + + if (child) { + // Make it the current child + mCurrentChild = child; + mIsDone = PR_FALSE; + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +GeneratedContentIterator::MakePre() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +GeneratedContentIterator::MakePost() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + nsresult NS_NewGeneratedContentIterator(nsIPresContext* aPresContext, nsIFrame* aFrame, nsIContentIterator** aIterator) { - *aIterator = nsnull; - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_ARG_POINTER(aIterator); + if (!aIterator) { + return NS_ERROR_NULL_POINTER; + } + + // Make sure the frame corresponds to generated content +#ifdef DEBUG + nsFrameState frameState; + aFrame->GetFrameState(&frameState); + NS_ASSERTION(frameState & NS_FRAME_GENERATED_CONTENT, "unexpected frame"); +#endif + + GeneratedContentIterator* it = new GeneratedContentIterator(aPresContext, aFrame); + if (!it) { + return NS_ERROR_OUT_OF_MEMORY; + } + return it->QueryInterface(NS_GET_IID(nsIContentIterator), (void **)aIterator); } nsresult