Refactor and improve sibling frame finding, especially for popups. Bug 386642, r+sr=roc, a=vlad
authorbzbarsky@mit.edu
Wed, 07 Nov 2007 09:04:16 -0800
changeset 7655 4b973556562c578b83e6e5ac34f068bbfcda6e1b
parent 7654 01f5785ccd9790904ea79ea8045de44ec41f168c
child 7656 db9be2d12403c8eaa9bedeb09afe39e67c69632b
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs386642
milestone1.9a9pre
Refactor and improve sibling frame finding, especially for popups. Bug 386642, r+sr=roc, a=vlad
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8207,29 +8207,23 @@ nsCSSFrameConstructor::AppendFrames(nsFr
     // It all got eaten by the special inline
     return NS_OK;
   }
   
   return frameManager->AppendFrames(aParentFrame, nsnull,
                                     aFrameList.childList);
 }
 
-/**
- * Find the ``rightmost'' frame for the anonymous content immediately
- * preceding aChild, following continuation if necessary.
- */
-static nsIFrame*
-FindPreviousAnonymousSibling(nsIPresShell* aPresShell,
-                             nsIDocument*  aDocument,
-                             nsIContent*   aContainer,
-                             nsIContent*   aChild)
-{
-  NS_PRECONDITION(aDocument, "null document from content element in FindNextAnonymousSibling");
-
-  nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(aDocument));
+#define UNSET_DISPLAY 255
+
+nsIFrame*
+nsCSSFrameConstructor::FindPreviousAnonymousSibling(nsIContent*   aContainer,
+                                                    nsIContent*   aChild)
+{
+  nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(mDocument));
   NS_ASSERTION(xblDoc, "null xblDoc for content element in FindNextAnonymousSibling");
   if (! xblDoc)
     return nsnull;
 
   // Grovel through the anonymous elements looking for aChild. We'll
   // start our search for a previous frame there.
   nsCOMPtr<nsIDOMNodeList> nodeList;
   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aContainer));
@@ -8248,70 +8242,45 @@ FindPreviousAnonymousSibling(nsIPresShel
 
     nsCOMPtr<nsIContent> child = do_QueryInterface(node);
     if (child == aChild)
       break;
   }
 
   // We want the node immediately before aChild. Keep going until we
   // run off the beginning of the nodeList, or we find a frame.
+  PRUint8 childDisplay = UNSET_DISPLAY;
   while (--index >= 0) {
     nsCOMPtr<nsIDOMNode> node;
     nodeList->Item(PRUint32(index), getter_AddRefs(node));
 
     nsCOMPtr<nsIContent> child = do_QueryInterface(node);
 
     // Get its frame. If it doesn't have one, continue on to the
     // anonymous element that preceded it.
-    nsIFrame* prevSibling = aPresShell->GetPrimaryFrameFor(child);
+    nsIFrame* prevSibling = FindFrameForContentSibling(child, aChild,
+                                                       childDisplay, PR_TRUE);
     if (prevSibling) {
-      // The frame may be a special frame (a split inline frame that
-      // contains a block).  Get the last part of that split.
-      if (IsFrameSpecial(prevSibling)) {
-        prevSibling = GetLastSpecialSibling(prevSibling);
-      }
-
-      // If the frame is out-of-flow, GPFF() will have returned the
-      // out-of-flow frame; we want the placeholder.
-      if (prevSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
-        nsIFrame *placeholderFrame;
-        aPresShell->GetPlaceholderFrameFor(prevSibling, &placeholderFrame);
-        NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
-        prevSibling = placeholderFrame;
-      }
-
-      // The frame may have a continuation. If so, we want the
-      // last non-overflow-container continuation as our previous sibling.
-      prevSibling = prevSibling->GetLastContinuation();
-      while (prevSibling->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
-        prevSibling = prevSibling->GetPrevInFlow();
-        NS_ASSERTION(prevSibling, "first-in-flow can't be overflow container");
-      }
-
       // Found a previous sibling, we're done!
       return prevSibling;
     }
   }
 
   return nsnull;
 }
 
 /**
  * Find the frame for the anonymous content immediately following
  * aChild.
  */
-static nsIFrame*
-FindNextAnonymousSibling(nsIPresShell* aPresShell,
-                         nsIDocument*  aDocument,
-                         nsIContent*   aContainer,
-                         nsIContent*   aChild)
-{
-  NS_PRECONDITION(aDocument, "null document from content element in FindNextAnonymousSibling");
-
-  nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(aDocument));
+nsIFrame*
+nsCSSFrameConstructor::FindNextAnonymousSibling(nsIContent*   aContainer,
+                                                nsIContent*   aChild)
+{
+  nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(mDocument));
   NS_ASSERTION(xblDoc, "null xblDoc for content element in FindNextAnonymousSibling");
   if (! xblDoc)
     return nsnull;
 
   // Grovel through the anonymous elements looking for aChild
   nsCOMPtr<nsIDOMNodeList> nodeList;
   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aContainer));
   xblDoc->GetAnonymousNodes(elt, getter_AddRefs(nodeList));
@@ -8329,163 +8298,176 @@ FindNextAnonymousSibling(nsIPresShell* a
 
     nsCOMPtr<nsIContent> child = do_QueryInterface(node);
     if (child == aChild)
       break;
   }
 
   // We want the node immediately after aChild. Keep going until we
   // run off the end of the nodeList, or we find a next sibling.
+  PRUint8 childDisplay = UNSET_DISPLAY;
   while (++index < PRInt32(length)) {
     nsCOMPtr<nsIDOMNode> node;
     nodeList->Item(PRUint32(index), getter_AddRefs(node));
 
     nsCOMPtr<nsIContent> child = do_QueryInterface(node);
 
     // Get its frame
-    nsIFrame* nextSibling = aPresShell->GetPrimaryFrameFor(child);
+    nsIFrame* nextSibling = FindFrameForContentSibling(child, aChild,
+                                                       childDisplay, PR_FALSE);
     if (nextSibling) {
-      // The primary frame should never be a continuation
-      NS_ASSERTION(!nextSibling->GetPrevInFlow(),
-                   "primary frame is a continuation!?");
-
-      // If the frame is out-of-flow, GPFF() will have returned the
-      // out-of-flow frame; we want the placeholder.
-      if (nextSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
-        nsIFrame* placeholderFrame;
-        aPresShell->GetPlaceholderFrameFor(nextSibling, &placeholderFrame);
-        NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
-        nextSibling = placeholderFrame;
-      }
-
       // Found a next sibling, we're done!
       return nextSibling;
     }
   }
 
   return nsnull;
 }
 
-#define UNSET_DISPLAY 255
 // This gets called to see if the frames corresponding to aSiblingDisplay and aDisplay
 // should be siblings in the frame tree. Although (1) rows and cols, (2) row groups 
-// and col groups, (3) row groups and captions (4) legends and content inside fieldsets
+// and col groups, (3) row groups and captions, (4) legends and content inside fieldsets, (5) popups and other kids of the menu
 // are siblings from a content perspective, they are not considered siblings in the 
 // frame tree.
 PRBool
-nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aParentFrame,
-                                      nsIFrame*              aSibling,
-                                      PRUint8                aSiblingDisplay,
-                                      nsIContent&            aContent,
+nsCSSFrameConstructor::IsValidSibling(nsIFrame*              aSibling,
+                                      nsIContent*            aContent,
                                       PRUint8&               aDisplay)
 {
-  if ((NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == aSiblingDisplay) ||
-      (NS_STYLE_DISPLAY_TABLE_COLUMN       == aSiblingDisplay) ||
-      (NS_STYLE_DISPLAY_TABLE_CAPTION      == aSiblingDisplay) ||
-      (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aSiblingDisplay) ||
-      (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == aSiblingDisplay) ||
-      (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aSiblingDisplay)) {
+  nsIAtom* parentType = aSibling->GetParent()->GetType();
+  PRUint8 siblingDisplay = aSibling->GetStyleDisplay()->mDisplay;
+  if ((NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == siblingDisplay) ||
+      (NS_STYLE_DISPLAY_TABLE_COLUMN       == siblingDisplay) ||
+      (NS_STYLE_DISPLAY_TABLE_CAPTION      == siblingDisplay) ||
+      (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == siblingDisplay) ||
+      (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == siblingDisplay) ||
+      (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == siblingDisplay) ||
+      nsGkAtoms::menuFrame == parentType) {
     // if we haven't already, construct a style context to find the display type of aContent
     if (UNSET_DISPLAY == aDisplay) {
       nsRefPtr<nsStyleContext> styleContext;
       nsIFrame* styleParent;
       PRBool providerIsChild;
       if (NS_FAILED(aSibling->
                       GetParentStyleContextFrame(aSibling->PresContext(),
                                                  &styleParent,
                                                  &providerIsChild)) ||
           !styleParent) {
         NS_NOTREACHED("Shouldn't happen");
         return PR_FALSE;
       }
-      styleContext = ResolveStyleContext(styleParent, &aContent);
+      styleContext = ResolveStyleContext(styleParent, aContent);
       if (!styleContext) return PR_FALSE;
       const nsStyleDisplay* display = styleContext->GetStyleDisplay();
       aDisplay = display->mDisplay;
     }
-    switch (aSiblingDisplay) {
+    if (nsGkAtoms::menuFrame == parentType) {
+      return
+        (NS_STYLE_DISPLAY_POPUP == aDisplay) ==
+        (NS_STYLE_DISPLAY_POPUP == siblingDisplay);
+    }
+    switch (siblingDisplay) {
     case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
       return (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == aDisplay);
     case NS_STYLE_DISPLAY_TABLE_COLUMN:
       return (NS_STYLE_DISPLAY_TABLE_COLUMN == aDisplay);
     case NS_STYLE_DISPLAY_TABLE_CAPTION:
       return (NS_STYLE_DISPLAY_TABLE_CAPTION == aDisplay);
     default: // all of the row group types
       return (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplay) ||
              (NS_STYLE_DISPLAY_TABLE_ROW_GROUP    == aDisplay) ||
              (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplay) ||
              (NS_STYLE_DISPLAY_TABLE_CAPTION      == aDisplay);
     }
   }
-  else if (nsGkAtoms::fieldSetFrame == aParentFrame->GetType()) {
+  else if (nsGkAtoms::fieldSetFrame == parentType) {
     // Legends can be sibling of legends but not of other content in the fieldset
     nsIAtom* sibType = aSibling->GetType();
-    nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(&aContent));
+    nsCOMPtr<nsIDOMHTMLLegendElement> legendContent(do_QueryInterface(aContent));
 
     if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
         (!legendContent && (nsGkAtoms::legendFrame == sibType)))
       return PR_FALSE;
   }
 
   return PR_TRUE;
 }
 
+nsIFrame*
+nsCSSFrameConstructor::FindFrameForContentSibling(nsIContent* aContent,
+                                                  nsIContent* aTargetContent,
+                                                  PRUint8& aTargetContentDisplay,
+                                                  PRBool aPrevSibling)
+{
+  nsIFrame* sibling = mPresShell->GetPrimaryFrameFor(aContent);
+  if (!sibling) {
+    return nsnull;
+  }
+
+  // If the frame is out-of-flow, GPFF() will have returned the
+  // out-of-flow frame; we want the placeholder.
+  if (sibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
+    nsIFrame* placeholderFrame;
+    mPresShell->GetPlaceholderFrameFor(sibling, &placeholderFrame);
+    NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
+    sibling = placeholderFrame;
+  }
+
+  // The frame we have now should never be a continuation
+  NS_ASSERTION(!sibling->GetPrevContinuation(), "How did that happen?");
+
+  if (aPrevSibling) {
+    // The frame may be a special frame (a split inline frame that
+    // contains a block).  Get the last part of that split.
+    if (IsFrameSpecial(sibling)) {
+      sibling = GetLastSpecialSibling(sibling);
+    }
+
+    // The frame may have a continuation. If so, we want the last
+    // non-overflow-container continuation as our previous sibling.
+    sibling = sibling->GetLastContinuation();
+    while (sibling->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
+      sibling = sibling->GetPrevInFlow();
+      NS_ASSERTION(sibling, "first-in-flow can't be overflow container");
+    }
+  }
+
+  if (aTargetContent &&
+      !IsValidSibling(sibling, aTargetContent, aTargetContentDisplay)) {
+    sibling = nsnull;
+  }
+
+  return sibling;
+}
+
 /**
  * Find the ``rightmost'' frame for the content immediately preceding
  * aIndexInContainer, following continuations if necessary.
  */
 nsIFrame*
-nsCSSFrameConstructor::FindPreviousSibling(nsIContent*       aContainer,
-                                           nsIFrame*         aContainerFrame,
-                                           PRInt32           aIndexInContainer,
-                                           const nsIContent* aChild)
+nsCSSFrameConstructor::FindPreviousSibling(nsIContent* aContainer,
+                                           PRInt32     aIndexInContainer,
+                                           nsIContent* aChild)
 {
   NS_ASSERTION(aContainer, "null argument");
 
   ChildIterator first, iter;
   nsresult rv = ChildIterator::Init(aContainer, &first, &iter);
   NS_ENSURE_SUCCESS(rv, nsnull);
   iter.seek(aIndexInContainer);
 
   PRUint8 childDisplay = UNSET_DISPLAY;
   // Note: not all content objects are associated with a frame (e.g., if it's
-  // `display: hidden') so keep looking until we find a previous frame
+  // `display: none') so keep looking until we find a previous frame
   while (iter-- != first) {
-    nsIFrame* prevSibling = mPresShell->GetPrimaryFrameFor(nsCOMPtr<nsIContent>(*iter));
+    nsIFrame* prevSibling =
+      FindFrameForContentSibling(nsCOMPtr<nsIContent>(*iter), aChild,
+                                 childDisplay, PR_TRUE);
 
     if (prevSibling) {
-      // The frame may be a special frame (a split inline frame that
-      // contains a block).  Get the last part of that split.
-      if (IsFrameSpecial(prevSibling)) {
-        prevSibling = GetLastSpecialSibling(prevSibling);
-      }
-
-      // If the frame is out-of-flow, GPFF() will have returned the
-      // out-of-flow frame; we want the placeholder.
-      if (prevSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
-        nsIFrame* placeholderFrame;
-        mPresShell->GetPlaceholderFrameFor(prevSibling, &placeholderFrame);
-        NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
-        prevSibling = placeholderFrame;
-      }
-
-      // The frame may have a continuation. if so get the last
-      // non-overflow-container continuation.
-      prevSibling = prevSibling->GetLastContinuation();
-      while (prevSibling->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
-        prevSibling = prevSibling->GetPrevInFlow();
-        NS_ASSERTION(prevSibling, "first-in-flow can't be overflow container");
-      }
-
-      const nsStyleDisplay* display = prevSibling->GetStyleDisplay();
-      if (aChild && !IsValidSibling(aContainerFrame, prevSibling,
-                                    display->mDisplay, (nsIContent&)*aChild,
-                                    childDisplay))
-        continue;
-
 #ifdef DEBUG
       nsIFrame* containerFrame = nsnull;
       containerFrame = mPresShell->GetPrimaryFrameFor(aContainer);
       NS_ASSERTION(prevSibling != containerFrame, "Previous Sibling is the Container's frame");
 #endif
       // Found a previous sibling, we're done!
       return prevSibling;
     }
@@ -8494,60 +8476,37 @@ nsCSSFrameConstructor::FindPreviousSibli
   return nsnull;
 }
 
 /**
  * Find the frame for the content node immediately following
  * aIndexInContainer.
  */
 nsIFrame*
-nsCSSFrameConstructor::FindNextSibling(nsIContent*       aContainer,
-                                       nsIFrame*         aContainerFrame,
-                                       PRInt32           aIndexInContainer,
-                                       const nsIContent* aChild)
+nsCSSFrameConstructor::FindNextSibling(nsIContent* aContainer,
+                                       PRInt32     aIndexInContainer,
+                                       nsIContent* aChild)
 {
   ChildIterator iter, last;
   nsresult rv = ChildIterator::Init(aContainer, &iter, &last);
   NS_ENSURE_SUCCESS(rv, nsnull);
   iter.seek(aIndexInContainer);
 
   // Catch the case where someone tries to append
   if (iter == last)
     return nsnull;
 
   PRUint8 childDisplay = UNSET_DISPLAY;
 
   while (++iter != last) {
     nsIFrame* nextSibling =
-      mPresShell->GetPrimaryFrameFor(nsCOMPtr<nsIContent>(*iter));
+      FindFrameForContentSibling(nsCOMPtr<nsIContent>(*iter), aChild,
+                                 childDisplay, PR_FALSE);
 
     if (nextSibling) {
-      // The frame primary frame should never be a continuation
-      NS_ASSERTION(!nextSibling->GetPrevInFlow(),
-                   "primary frame is a continuation!?");
-
-      // XXXbz should the IsValidSibling check be after we get the
-      // placeholder for out-of-flows?
-      const nsStyleDisplay* display = nextSibling->GetStyleDisplay();
-
-      if (aChild && !IsValidSibling(aContainerFrame, nextSibling, 
-                                    display->mDisplay, (nsIContent&)*aChild,
-                                    childDisplay))
-        continue;
-
-      // If the frame is out-of-flow, GPFF() will have returned the
-      // out-of-flow frame; we want the placeholder.
-      if (nextSibling->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
-        // Nope. Get the place-holder instead
-        nsIFrame* placeholderFrame;
-        mPresShell->GetPlaceholderFrameFor(nextSibling, &placeholderFrame);
-        NS_ASSERTION(placeholderFrame, "no placeholder for out-of-flow frame");
-        nextSibling = placeholderFrame;
-      }
-
       // We found a next sibling, we're done!
       return nextSibling;
     }
   }
 
   return nsnull;
 }
 
@@ -9100,28 +9059,28 @@ nsCSSFrameConstructor::ContentInserted(n
   // XXX if the insertionPoint was different from the original
   // parentFrame, then aIndexInContainer is most likely completely
   // wrong. What we need to do here is remember the original index,
   // then as we insert, search the child list where we're about to put
   // the new frame to make sure that it appears after any siblings
   // with a lower index, and before any siblings with a higher
   // index. Same with FindNextSibling(), below.
   nsIFrame* prevSibling = (aIndexInContainer >= 0)
-    ? FindPreviousSibling(container, parentFrame, aIndexInContainer, aChild)
-    : FindPreviousAnonymousSibling(mPresShell, mDocument, aContainer, aChild);
+    ? FindPreviousSibling(container, aIndexInContainer, aChild)
+    : FindPreviousAnonymousSibling(aContainer, aChild);
 
   PRBool    isAppend = PR_FALSE;
   nsIFrame* appendAfterFrame;  // This is only looked at when isAppend is true
   nsIFrame* nextSibling = nsnull;
     
   // If there is no previous sibling, then find the frame that follows
   if (! prevSibling) {
     nextSibling = (aIndexInContainer >= 0)
-      ? FindNextSibling(container, parentFrame, aIndexInContainer, aChild)
-      : FindNextAnonymousSibling(mPresShell, mDocument, aContainer, aChild);
+      ? FindNextSibling(container, aIndexInContainer, aChild)
+      : FindNextAnonymousSibling(aContainer, aChild);
   }
 
   // Now, find the geometric parent so that we can handle
   // continuations properly. Use the prev sibling if we have it;
   // otherwise use the next sibling.
   if (prevSibling) {
     parentFrame = prevSibling->GetParent()->GetContentInsertionFrame();
   }
@@ -9204,26 +9163,24 @@ nsCSSFrameConstructor::ContentInserted(n
       RemoveLetterFrames(state.mPresContext, mPresShell,
                          state.mFrameManager,
                          state.mFloatedItems.containingBlock);
 
       // Removing the letterframes messes around with the frame tree, removing
       // and creating frames.  We need to reget our prevsibling.
       // See XXX comment the first time we do this in this method....
       prevSibling = (aIndexInContainer >= 0)
-        ? FindPreviousSibling(container, parentFrame, aIndexInContainer,
-                              aChild)
-        : FindPreviousAnonymousSibling(mPresShell, mDocument, aContainer,
-                                       aChild);
+        ? FindPreviousSibling(container, aIndexInContainer, aChild)
+        : FindPreviousAnonymousSibling(aContainer, aChild);
 
       // If there is no previous sibling, then find the frame that follows
       if (! prevSibling) {
         nextSibling = (aIndexInContainer >= 0)
-          ? FindNextSibling(container, parentFrame, aIndexInContainer, aChild)
-          : FindNextAnonymousSibling(mPresShell, mDocument, aContainer, aChild);
+          ? FindNextSibling(container, aIndexInContainer, aChild)
+          : FindNextAnonymousSibling(aContainer, aChild);
       }
     }
   }
 
   // if the container is a table and a caption will be appended, it needs to be
   // put in the outer table frame's additional child list.
   
   nsFrameItems frameItems, captionItems;
@@ -9810,17 +9767,17 @@ UpdateViewsForTree(nsIFrame* aFrame, nsI
   PRInt32 listIndex = 0;
   nsIAtom* childList = nsnull;
 
   do {
     nsIFrame* child = aFrame->GetFirstChild(childList);
     while (child) {
       if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
           || (child->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
-        // only do frames that are in flow
+        // only do frames that don't have placeholders
         if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
           // get out of flow frame and start over there
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
 
           DoApplyRenderingChangeToTree(outOfFlowFrame, aViewManager,
                                        aFrameManager, aChange);
         }
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -1002,40 +1002,62 @@ private:
                                  nsIContent*              aContent,
                                  nsIFrame*                aBlockFrame,
                                  nsIFrame**               aParentFrame,
                                  nsIFrame*                aPrevSibling,
                                  nsFrameItems&            aFrameItems);
 
   nsresult RemoveFixedItems(const nsFrameConstructorState& aState);
 
+  // Find the right frame to use for aContent when looking for sibling
+  // frames for aTargetContent.  If aPrevSibling is true, this
+  // will look for last continuations, etc, as necessary.  This calls
+  // IsValidSibling as needed; if that returns false it returns null.
+  //
+  // @param aTargetContentDisplay the CSS display enum for aTargetContent if
+  // already known, UNSET_DISPLAY otherwise.
+  nsIFrame* FindFrameForContentSibling(nsIContent* aContent,
+                                       nsIContent* aTargetContent,
+                                       PRUint8& aTargetContentDisplay,
+                                       PRBool aPrevSibling);
+
   // Find the ``rightmost'' frame for the content immediately preceding
-  // aIndexInContainer, following continuations if necessary. If aChild is
-  // not null, make sure it passes the call to IsValidSibling
-  nsIFrame* FindPreviousSibling(nsIContent*       aContainer,
-                                nsIFrame*         aContainerFrame,
-                                PRInt32           aIndexInContainer,
-                                const nsIContent* aChild = nsnull);
+  // aIndexInContainer, following continuations if necessary.
+  nsIFrame* FindPreviousSibling(nsIContent* aContainer,
+                                PRInt32     aIndexInContainer,
+                                nsIContent* aChild);
 
   // Find the frame for the content node immediately following aIndexInContainer.
-  // If aChild is not null, make sure it passes the call to IsValidSibling
-  nsIFrame* FindNextSibling(nsIContent*       aContainer,
-                            nsIFrame*         aContainerFrame,
-                            PRInt32           aIndexInContainer,
-                            const nsIContent* aChild = nsnull);
+  nsIFrame* FindNextSibling(nsIContent* aContainer,
+                            PRInt32     aIndexInContainer,
+                            nsIContent* aChild);
 
   // see if aContent and aSibling are legitimate siblings due to restrictions
   // imposed by table columns
   // XXXbz this code is generally wrong, since the frame for aContent
   // may be constructed based on tag, not based on aDisplay!
-  PRBool IsValidSibling(nsIFrame*              aParentFrame,
-                        nsIFrame*              aSibling,
-                        PRUint8                aSiblingDisplay,
-                        nsIContent&            aContent,
+  PRBool IsValidSibling(nsIFrame*              aSibling,
+                        nsIContent*            aContent,
                         PRUint8&               aDisplay);
+  
+  /**
+   * Find the ``rightmost'' frame for the anonymous content immediately
+   * preceding aChild, following continuation if necessary.
+   */
+  nsIFrame*
+  FindPreviousAnonymousSibling(nsIContent*   aContainer,
+                               nsIContent*   aChild);
+
+  /**
+   * Find the frame for the anonymous content immediately following
+   * aChild.
+   */
+  nsIFrame*
+  FindNextAnonymousSibling(nsIContent*   aContainer,
+                           nsIContent*   aChild);
 
   void QuotesDirty() {
     NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
     mQuotesDirty = PR_TRUE;
   }
 
   void CountersDirty() {
     NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");