bug 28800 remove support for scrollable rowgroups moa=roc r=bzbarsky
authorBernd <bmlk@gmx.de>
Sat, 16 Jan 2010 17:05:46 +0100
changeset 37262 e8350654c9bca73cd0919ad563517ab739eadffb
parent 37261 0fdec1dfd30b207cf9ee5d72bc19dffd06822284
child 37263 4bb9868650a813db4d2e39474049e25abbfeb04b
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs28800
milestone1.9.3a1pre
bug 28800 remove support for scrollable rowgroups moa=roc r=bzbarsky
layout/base/nsCSSFrameConstructor.cpp
layout/reftests/bugs/reftest.list
layout/reftests/table-background/reftest.list
layout/tables/nsCellMap.cpp
layout/tables/nsCellMap.h
layout/tables/nsTableFrame.cpp
layout/tables/nsTableFrame.h
layout/tables/nsTablePainter.cpp
layout/tables/nsTableRowGroupFrame.cpp
layout/tables/nsTableRowGroupFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -4378,27 +4378,27 @@ nsCSSFrameConstructor::FindDisplayData(c
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructTable) },
     { NS_STYLE_DISPLAY_TABLE_CAPTION,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_ALLOW_BLOCK_STYLES |
                   FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableCaptionFrame) },
     { NS_STYLE_DISPLAY_TABLE_ROW_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
-                  FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
+                  FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_HEADER_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
-                  FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
+                  FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
-                  FCDATA_MAY_NEED_SCROLLFRAME | FCDATA_SKIP_ABSPOS_PUSH |
+                  FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableRowGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP,
       FCDATA_DECL(FCDATA_IS_TABLE_PART | FCDATA_DISALLOW_OUT_OF_FLOW |
                   FCDATA_SKIP_ABSPOS_PUSH |
                   FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeTable),
                   NS_NewTableColGroupFrame) },
     { NS_STYLE_DISPLAY_TABLE_COLUMN,
@@ -7883,50 +7883,46 @@ nsCSSFrameConstructor::CreateContinuingT
     nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
 
     // Replicate any header/footer frames
     nsFrameItems  childFrames;
     nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
     for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
       // See if it's a header/footer, possibly wrapped in a scroll frame.
       nsTableRowGroupFrame* rowGroupFrame =
-        nsTableFrame::GetRowGroupFrame(childFrame);
-      if (rowGroupFrame) {
-        // If the row group was continued, then don't replicate it.
-        nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
-        if (rgNextInFlow) {
-          rowGroupFrame->SetRepeatable(PR_FALSE);
-        }
-        else if (rowGroupFrame->IsRepeatable()) {        
-          // Replicate the header/footer frame.
-          nsTableRowGroupFrame*   headerFooterFrame;
-          nsFrameItems            childItems;
-          nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
-                                        GetAbsoluteContainingBlock(newFrame),
-                                        nsnull);
-
-          headerFooterFrame = static_cast<nsTableRowGroupFrame*>
-                                         (NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
-          nsIContent* headerFooter = rowGroupFrame->GetContent();
-          headerFooterFrame->Init(headerFooter, newFrame, nsnull);
-          // No ancestor bindings to worry about ordering with, so null pending
-          // binding is ok.
-          ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
-                          headerFooterFrame, PR_TRUE, childItems, PR_FALSE,
-                          nsnull);
-          NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
-          headerFooterFrame->SetInitialChildList(nsnull, childItems);
-          headerFooterFrame->SetRepeatable(PR_TRUE);
-
-          // Table specific initialization
-          headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
-
-          // XXX Deal with absolute and fixed frames...
-          childFrames.AddChild(headerFooterFrame);
-        }
+        static_cast<nsTableRowGroupFrame*>(childFrame);
+      // If the row group was continued, then don't replicate it.
+      nsIFrame* rgNextInFlow = rowGroupFrame->GetNextInFlow();
+      if (rgNextInFlow) {
+        rowGroupFrame->SetRepeatable(PR_FALSE);
+      }
+      else if (rowGroupFrame->IsRepeatable()) {
+        // Replicate the header/footer frame.
+        nsTableRowGroupFrame*   headerFooterFrame;
+        nsFrameItems            childItems;
+        nsFrameConstructorState state(mPresShell, mFixedContainingBlock,
+                                      GetAbsoluteContainingBlock(newFrame),
+                                      nsnull);
+
+        headerFooterFrame = static_cast<nsTableRowGroupFrame*>
+                                       (NS_NewTableRowGroupFrame(aPresShell, rowGroupFrame->GetStyleContext()));
+        nsIContent* headerFooter = rowGroupFrame->GetContent();
+        headerFooterFrame->Init(headerFooter, newFrame, nsnull);
+        ProcessChildren(state, headerFooter, rowGroupFrame->GetStyleContext(),
+                        headerFooterFrame, PR_TRUE, childItems, PR_FALSE,
+                        nsnull);
+        NS_ASSERTION(state.mFloatedItems.IsEmpty(), "unexpected floated element");
+        headerFooterFrame->SetInitialChildList(nsnull, childItems);
+        headerFooterFrame->SetRepeatable(PR_TRUE);
+
+        // Table specific initialization
+        headerFooterFrame->InitRepeatedFrame(aPresContext, rowGroupFrame);
+
+        // XXX Deal with absolute and fixed frames...
+        childFrames.AddChild(headerFooterFrame);
       }
     }
     
     // Set the table frame's initial child list
     newFrame->SetInitialChildList(nsnull, childFrames);
     
     *aContinuingFrame = newFrame;
     return NS_OK;
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -697,17 +697,17 @@ fails == 386147-1.html 386147-1-ref.html
 == 386470-1b.html 386470-1-ref.html
 == 386470-1c.html 386470-1-ref.html
 == 386920-1.html 386920-1-ref.html
 == 387201-1.html 387201-1-ref.html
 == 387201-2.html about:blank  # Really an assertion test rather than a rendering test
 == 387201-3.html about:blank  # Really an assertion test rather than a rendering test
 == 387227-1.html 387227-1-ref.html
 == 387227-2.html 387227-2-ref.html
-== 387344-1.html 387344-1-ref.html
+fails == 387344-1.html 387344-1-ref.html # scrolling rowgroups removed bug 28800
 == 387876-1.html 387876-1-ref.html
 random == 387876-2.html 387876-2-ref.html # bug 471630
 == 387876-3a.html 387876-3-ref.html
 == 387876-3b.html 387876-3-ref.html
 == 388026-1.html 388026-1-ref.html
 == 388367-1.html about:blank
 == 388980-1.html 388980-1-ref.html
 == 389074-1.html 389074-1-ref.html
@@ -951,17 +951,17 @@ skip-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 
 == 421955-1.html 421955-1-ref.html
 == 422249-1.html 422249-1-ref.html
 == 422394-1.html 422394-1-ref.html
 == 422678-1.html 422678-1-ref.html
 == 423130-1.html 423130-1-ref.html
 == 423385-1.html 423385-1-ref.html
 == 423599-1.html 423599-1-ref.html
 == 423676-1.html 423676-1-ref.html
-== 423823-1.html 423823-1-ref.html
+fails == 423823-1.html 423823-1-ref.html # scrolling rowgroups removed bug 28800
 == 424074-1.xul 424074-1-ref.xul
 != 424074-1.xul 424074-1-ref2.xul
 fails-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 424074-1-ref2.xul 424074-1-ref3.xul
 == 424236-1.html 424236-1-ref.html
 == 424236-2.html 424236-2-ref.html
 == 424236-3.html 424236-3-ref.html
 == 424236-4.html 424236-4-ref.html
 == 424236-5.html 424236-5-ref.html
--- a/layout/reftests/table-background/reftest.list
+++ b/layout/reftests/table-background/reftest.list
@@ -46,12 +46,12 @@ fails == border-collapse-opacity-table-c
 == border-collapse-opacity-table-row.html border-collapse-opacity-table-row-ref.html
 == border-collapse-opacity-table.html border-collapse-opacity-table-ref.html
 == border-separate-opacity-table-cell.html border-separate-opacity-table-cell-ref.html
 fails == border-separate-opacity-table-column-group.html border-separate-opacity-table-column-group-ref.html # bug 424274
 fails == border-separate-opacity-table-column.html border-separate-opacity-table-column-ref.html # bug 424274
 == border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group-ref.html
 == border-separate-opacity-table-row.html border-separate-opacity-table-row-ref.html
 == border-separate-opacity-table.html border-separate-opacity-table-ref.html
-!= scrollable-rowgroup-collapse-background.html scrollable-rowgroup-collapse-notref.html
-!= scrollable-rowgroup-collapse-border.html scrollable-rowgroup-collapse-notref.html
+!= scrollable-rowgroup-collapse-background.html scrollable-rowgroup-collapse-notref.html 
+!= scrollable-rowgroup-collapse-border.html scrollable-rowgroup-collapse-notref.html     
 != scrollable-rowgroup-separate-background.html scrollable-rowgroup-separate-notref.html
-!= scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-notref.html
+== scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-notref.html # bug 28800
--- a/layout/tables/nsCellMap.cpp
+++ b/layout/tables/nsCellMap.cpp
@@ -77,17 +77,17 @@ nsTableCellMap::nsTableCellMap(nsTableFr
   MOZ_COUNT_CTOR(nsTableCellMap);
 
   nsTableFrame::RowGroupArray orderedRowGroups;
   aTableFrame.OrderRowGroups(orderedRowGroups);
 
   nsTableRowGroupFrame* prior = nsnull;
   for (PRUint32 rgX = 0; rgX < orderedRowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgX];
-    InsertGroupCellMap(*rgFrame, prior);
+    InsertGroupCellMap(rgFrame, prior);
     prior = rgFrame;
   }
   if (aBorderCollapse) {
     mBCInfo = new BCInfo();
   }
 }
 
 nsTableCellMap::~nsTableCellMap()
@@ -160,17 +160,17 @@ nsTableCellMap::InsertGroupCellMap(nsCel
   }
   else {
     next = mFirstMap;
     mFirstMap = &aNewMap;
   }
   aNewMap.SetNextSibling(next);
 }
 
-void nsTableCellMap::InsertGroupCellMap(nsTableRowGroupFrame&  aNewGroup,
+void nsTableCellMap::InsertGroupCellMap(nsTableRowGroupFrame*  aNewGroup,
                                         nsTableRowGroupFrame*& aPrevGroup)
 {
   nsCellMap* newMap = new nsCellMap(aNewGroup, mBCInfo != nsnull);
   if (newMap) {
     nsCellMap* prevMap = nsnull;
     nsCellMap* lastMap = mFirstMap;
     if (aPrevGroup) {
       nsCellMap* map = mFirstMap;
@@ -466,30 +466,30 @@ nsTableCellMap::RemoveColsAtEnd()
 void 
 nsTableCellMap::ClearCols()
 {
   mCols.Clear();
   if (mBCInfo)
     mBCInfo->mBottomBorders.Clear();
 }
 void
-nsTableCellMap::InsertRows(nsTableRowGroupFrame&       aParent,
+nsTableCellMap::InsertRows(nsTableRowGroupFrame*       aParent,
                            nsTArray<nsTableRowFrame*>& aRows,
                            PRInt32                     aFirstRowIndex,
                            PRBool                      aConsiderSpans,
                            nsRect&                     aDamageArea)
 {
   PRInt32 numNewRows = aRows.Length();
   if ((numNewRows <= 0) || (aFirstRowIndex < 0)) ABORT0(); 
 
   PRInt32 rowIndex = aFirstRowIndex;
   nsCellMap* cellMap = mFirstMap;
   while (cellMap) {
     nsTableRowGroupFrame* rg = cellMap->GetRowGroup();
-    if (rg == &aParent) {
+    if (rg == aParent) {
       cellMap->InsertRows(*this, aRows, rowIndex, aConsiderSpans, aDamageArea);
       aDamageArea.y = NS_MIN(aFirstRowIndex, aDamageArea.y);
       aDamageArea.height = NS_MAX(0, GetRowCount() - aDamageArea.y);
 #ifdef DEBUG_TABLE_CELLMAP 
       Dump("after InsertRows");
 #endif
       if (mBCInfo) {
         PRInt32 count = mBCInfo->mRightBorders.Length();
@@ -1170,20 +1170,20 @@ nsTableCellMap::SetBCBorderCorner(Corner
     bcData = &cellData->mData;
   }
   if (bcData) {
     bcData->SetCorner(aSubSize, aOwner, aBevel);
   }
   else NS_ERROR("program error: Corner not found");
 }
 
-nsCellMap::nsCellMap(nsTableRowGroupFrame& aRowGroup, PRBool aIsBC)
-  : mRows(8), mContentRowCount(0), mRowGroupFrame(&aRowGroup),
+nsCellMap::nsCellMap(nsTableRowGroupFrame* aRowGroup, PRBool aIsBC)
+  : mRows(8), mContentRowCount(0), mRowGroupFrame(aRowGroup),
     mNextSibling(nsnull), mIsBC(aIsBC),
-    mPresContext(aRowGroup.PresContext())
+    mPresContext(aRowGroup->PresContext())
 {
   MOZ_COUNT_CTOR(nsCellMap);
   NS_ASSERTION(mPresContext, "Must have prescontext");
 }
 
 nsCellMap::~nsCellMap()
 {
   MOZ_COUNT_DTOR(nsCellMap);
--- a/layout/tables/nsCellMap.h
+++ b/layout/tables/nsCellMap.h
@@ -89,17 +89,17 @@ public:
 
   /** destructor
     * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED  
     */
   ~nsTableCellMap();
   
   void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
 
-  void InsertGroupCellMap(nsTableRowGroupFrame&  aNewRowGroup,
+  void InsertGroupCellMap(nsTableRowGroupFrame*  aNewRowGroup,
                           nsTableRowGroupFrame*& aPrevRowGroup);
 
   /**
    * Get the nsCellMap for the given row group.  If aStartHint is non-null,
    * will start looking with that cellmap and only fall back to starting at the
    * beginning of the list if that doesn't find us the right nsCellMap.
    * Otherwise, just start at the beginning.
    *
@@ -135,17 +135,17 @@ public:
                    PRInt32                      aColIndexBefore,
                    nsRect&                      aDamageArea);
 
   void RemoveCell(nsTableCellFrame* aCellFrame,
                   PRInt32           aRowIndex,
                   nsRect&           aDamageArea);
   /** Remove the previously gathered column information */
   void ClearCols();
-  void InsertRows(nsTableRowGroupFrame&       aRowGroup,
+  void InsertRows(nsTableRowGroupFrame*       aRowGroup,
                   nsTArray<nsTableRowFrame*>& aRows,
                   PRInt32                     aFirstRowIndex,
                   PRBool                      aConsiderSpans,
                   nsRect&                     aDamageArea);
 
   void RemoveRows(PRInt32         aFirstRowIndex,
                   PRInt32         aNumRowsToRemove,
                   PRBool          aConsiderSpans,
@@ -301,17 +301,17 @@ protected:
   */
 class nsCellMap
 {
 public:
   /** constructor 
     * @param aRowGroupFrame the row group frame this is a cellmap for
     * @param aIsBC whether the table is doing border-collapse
     */
-  nsCellMap(nsTableRowGroupFrame& aRowGroupFrame, PRBool aIsBC);
+  nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, PRBool aIsBC);
 
   /** destructor
     * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED  
     */
   ~nsCellMap();
 
   static nsresult Init();
   static void Shutdown();
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -60,17 +60,16 @@
 #include "nsCSSRendering.h"
 #include "nsStyleConsts.h"
 #include "nsGkAtoms.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsIPresShell.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLBodyElement.h"
-#include "nsIScrollableFrame.h"
 #include "nsFrameManager.h"
 #include "nsCSSRendering.h"
 #include "nsLayoutErrors.h"
 #include "nsAutoPtr.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsStyleSet.h"
 #include "nsDisplayList.h"
 #include "nsIScrollableFrame.h"
@@ -517,40 +516,34 @@ void nsTableFrame::AdjustRowIndices(PRIn
   }
 }
 
 
 void nsTableFrame::ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude)
 {
   // Iterate over the row groups and adjust the row indices of all rows
   // omit the rowgroups that will be inserted later
-  // XXXbz this code seems to assume that the row groups handed out by
-  // aRowGroupsToExclude are already in OrderRowGroups() order.
-  // There's no reason that would be true!
   RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
 
   PRInt32 rowIndex = 0;
-  nsTableRowGroupFrame* newRgFrame = nsnull;
+  nsTHashtable<nsPtrHashKey<nsTableRowGroupFrame> > excludeRowGroups;
+  if (!excludeRowGroups.Init()) {
+    NS_ERROR("Failed to initialize excludeRowGroups hash.");
+    return;
+  }
   nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
-  if (!excludeRowGroupsEnumerator.AtEnd()) {
-    newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
+  while (!excludeRowGroupsEnumerator.AtEnd()) {
+    excludeRowGroups.PutEntry(static_cast<nsTableRowGroupFrame*>(excludeRowGroupsEnumerator.get()));
     excludeRowGroupsEnumerator.Next();
   }
 
   for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
-    if (rgFrame == newRgFrame) {
-      // omit the new rowgroup and move our iterator along
-      if (!excludeRowGroupsEnumerator.AtEnd()) {
-        newRgFrame = GetRowGroupFrame(excludeRowGroupsEnumerator.get());
-        excludeRowGroupsEnumerator.Next();
-      }
-    }
-    else {
+    if (!excludeRowGroups.GetEntry(rgFrame)) {
       const nsFrameList& rowFrames = rgFrame->GetChildList(nsnull);
       for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
         if (NS_STYLE_DISPLAY_TABLE_ROW==rows.get()->GetStyleDisplay()->mDisplay) {
           ((nsTableRowFrame *)rows.get())->SetRowIndex(rowIndex);
           rowIndex++;
         }
       }
     }
@@ -876,59 +869,48 @@ void nsTableFrame::RemoveCell(nsTableCel
     MatchCellMapToColCache(cellMap);
     if (IsBorderCollapse()) {
       SetBCDamageArea(damageArea);
     }
   }
 }
 
 PRInt32
-nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame)
+nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame)
 {
   RowGroupArray orderedRowGroups;
   OrderRowGroups(orderedRowGroups);
 
   PRInt32 rowIndex = 0;
   for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
     nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
-    if (rgFrame == &aRowGroupFrame) {
+    if (rgFrame == aRowGroupFrame) {
       break;
     }
     PRInt32 numRows = rgFrame->GetRowCount();
     rowIndex += numRows;
   }
   return rowIndex;
 }
 
 // this cannot extend beyond a single row group
-void nsTableFrame::AppendRows(nsTableRowGroupFrame&       aRowGroupFrame,
+void nsTableFrame::AppendRows(nsTableRowGroupFrame*       aRowGroupFrame,
                               PRInt32                     aRowIndex,
                               nsTArray<nsTableRowFrame*>& aRowFrames)
 {
   nsTableCellMap* cellMap = GetCellMap();
   if (cellMap) {
     PRInt32 absRowIndex = GetStartRowIndex(aRowGroupFrame) + aRowIndex;
     InsertRows(aRowGroupFrame, aRowFrames, absRowIndex, PR_TRUE);
   }
 }
 
-PRInt32
-nsTableFrame::InsertRow(nsTableRowGroupFrame& aRowGroupFrame,
-                        nsIFrame&             aRowFrame,
-                        PRInt32               aRowIndex,
-                        PRBool                aConsiderSpans)
-{
-  nsAutoTArray<nsTableRowFrame*, 1> rows;
-  rows.AppendElement((nsTableRowFrame*)&aRowFrame);
-  return InsertRows(aRowGroupFrame, rows, aRowIndex, aConsiderSpans);
-}
-
 // this cannot extend beyond a single row group
 PRInt32
-nsTableFrame::InsertRows(nsTableRowGroupFrame&       aRowGroupFrame,
+nsTableFrame::InsertRows(nsTableRowGroupFrame*       aRowGroupFrame,
                          nsTArray<nsTableRowFrame*>& aRowFrames,
                          PRInt32                     aRowIndex,
                          PRBool                      aConsiderSpans)
 {
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== insertRowsBefore firstRow=%d \n", aRowIndex);
   Dump(PR_TRUE, PR_FALSE, PR_TRUE);
 #endif
@@ -999,63 +981,28 @@ void nsTableFrame::RemoveRows(nsTableRow
   }
   AdjustRowIndices(firstRowIndex, -aNumRowsToRemove);
 #ifdef DEBUG_TABLE_CELLMAP
   printf("=== removeRowsAfter\n");
   Dump(PR_TRUE, PR_TRUE, PR_TRUE);
 #endif
 }
 
-nsTableRowGroupFrame*
-nsTableFrame::GetRowGroupFrame(nsIFrame* aFrame,
-                               nsIAtom*  aFrameTypeIn)
-{
-  nsIFrame* rgFrame = nsnull;
-  nsIAtom* frameType = aFrameTypeIn;
-  if (!aFrameTypeIn) {
-    frameType = aFrame->GetType();
-  }
-  if (nsGkAtoms::tableRowGroupFrame == frameType) {
-    rgFrame = aFrame;
-  }
-  else if (nsGkAtoms::scrollFrame == frameType) {
-    nsIScrollableFrame* scrollable = do_QueryFrame(aFrame);
-    if (scrollable) {
-      nsIFrame* scrolledFrame = scrollable->GetScrolledFrame();
-      if (scrolledFrame) {
-        if (nsGkAtoms::tableRowGroupFrame == scrolledFrame->GetType()) {
-          rgFrame = scrolledFrame;
-        }
-      }
-    }
-  }
-  return (nsTableRowGroupFrame*)rgFrame;
-}
-
 // collect the rows ancestors of aFrame
 PRInt32
 nsTableFrame::CollectRows(nsIFrame*                   aFrame,
                           nsTArray<nsTableRowFrame*>& aCollection)
 {
-  if (!aFrame) return 0;
+  NS_PRECONDITION(aFrame, "null frame");
   PRInt32 numRows = 0;
-  nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aFrame);
-  if (rgFrame) {
-    nsIFrame* childFrame = rgFrame->GetFirstChild(nsnull);
-    while (childFrame) {
-      nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
-      if (rowFrame) {
-        aCollection.AppendElement(rowFrame);
-        numRows++;
-      }
-      else {
-        numRows += CollectRows(childFrame, aCollection);
-      }
-      childFrame = childFrame->GetNextSibling();
-    }
+  nsIFrame* childFrame = aFrame->GetFirstChild(nsnull);
+  while (childFrame) {
+    aCollection.AppendElement(static_cast<nsTableRowFrame*>(childFrame));
+    numRows++;
+    childFrame = childFrame->GetNextSibling();
   }
   return numRows;
 }
 
 void
 nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
 {
 #ifdef DEBUG_TABLE_CELLMAP
@@ -1071,49 +1018,45 @@ nsTableFrame::InsertRowGroups(const nsFr
     // Loop over the rowgroups and check if some of them are new, if they are
     // insert cellmaps in the order that is predefined by OrderRowGroups,
     // XXXbz this code is O(N*M) where N is number of new rowgroups
     // and M is number of rowgroups we have!
     PRUint32 rgIndex;
     for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
       for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
            rowgroups.Next()) {
-        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
-
-        if (orderedRowGroups[rgIndex] == rgFrame) {
+        if (orderedRowGroups[rgIndex] == rowgroups.get()) {
           nsTableRowGroupFrame* priorRG =
             (0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1]; 
           // create and add the cell map for the row group
-          cellMap->InsertGroupCellMap(*rgFrame, priorRG);
+          cellMap->InsertGroupCellMap(orderedRowGroups[rgIndex], priorRG);
         
           break;
         }
       }
     }
     cellMap->Synchronize(this);
     ResetRowIndices(aRowGroups);
 
     //now that the cellmaps are reordered too insert the rows
     for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
       for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
            rowgroups.Next()) {
-        nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(rowgroups.get());
-
-        if (orderedRowGroups[rgIndex] == rgFrame) {
+        if (orderedRowGroups[rgIndex] == rowgroups.get()) {
           nsTableRowGroupFrame* priorRG =
             (0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1]; 
           // collect the new row frames in an array and add them to the table
           PRInt32 numRows = CollectRows(rowgroups.get(), rows);
           if (numRows > 0) {
             PRInt32 rowIndex = 0;
             if (priorRG) {
               PRInt32 priorNumRows = priorRG->GetRowCount();
               rowIndex = priorRG->GetStartRowIndex() + priorNumRows;
             }
-            InsertRows(*rgFrame, rows, rowIndex, PR_TRUE);
+            InsertRows(orderedRowGroups[rgIndex], rows, rowIndex, PR_TRUE);
             rows.Clear();
           }
           break;
         }
       }
     }    
     
   }
@@ -1692,17 +1635,16 @@ void
 nsTableFrame::RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState)
 {
   // notify the frame and its ancestors of the special reflow, stopping at the containing table
   for (const nsHTMLReflowState* rs = &aReflowState; rs && rs->frame; rs = rs->parentReflowState) {
     nsIAtom* frameType = rs->frame->GetType();
     NS_ASSERTION(IS_TABLE_CELL(frameType) ||
                  nsGkAtoms::tableRowFrame == frameType ||
                  nsGkAtoms::tableRowGroupFrame == frameType ||
-                 nsGkAtoms::scrollFrame == frameType ||
                  nsGkAtoms::tableFrame == frameType,
                  "unexpected frame type");
                  
     rs->frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
     if (nsGkAtoms::tableFrame == frameType) {
       NS_ASSERTION(rs != &aReflowState,
                    "should not request special height reflow for table");
       // always stop when we reach a table
@@ -1988,35 +1930,29 @@ nsTableFrame::GetFirstBodyRowGroupFrame(
   }
 
   return nsnull;
 }
 
 // Table specific version that takes into account repeated header and footer
 // frames when continuing table frames
 void
-nsTableFrame::PushChildren(const FrameArray& aFrames,
+nsTableFrame::PushChildren(const RowGroupArray& aRowGroups,
                            PRInt32 aPushFrom)
 {
   NS_PRECONDITION(aPushFrom > 0, "pushing first child");
 
   // extract the frames from the array into a sibling list
   nsFrameList frames;
   PRUint32 childX;
-  for (childX = aPushFrom; childX < aFrames.Length(); ++childX) {
-    nsIFrame* f = aFrames[childX];
-    // Don't push repeatable frames, do push non-rowgroup frames.
-    // XXXbz Need to push the non-rowgroup frames, even though we don't reflow
-    // them, so that we don't lose them.  Of course there shouldn't be any
-    // non-rowgroup frames here...
-    nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(f);
-    NS_ASSERTION(rgFrame, "Unexpected non-row-group frame");
+  for (childX = aPushFrom; childX < aRowGroups.Length(); ++childX) {
+    nsTableRowGroupFrame* rgFrame = aRowGroups[childX];
     if (!rgFrame || !rgFrame->IsRepeatable()) {
-      mFrames.RemoveFrame(f);
-      frames.AppendFrame(nsnull, f);
+      mFrames.RemoveFrame(rgFrame);
+      frames.AppendFrame(nsnull, rgFrame);
     }
   }
 
   if (nsnull != GetNextInFlow()) {
     nsTableFrame* nextInFlow = (nsTableFrame*)GetNextInFlow();
 
     // Insert the frames after any repeated header and footer frames
     nsIFrame* firstBodyFrame = nextInFlow->GetFirstBodyRowGroupFrame();
@@ -2346,44 +2282,40 @@ nsTableFrame::RemoveFrame(nsIAtom*      
     PRInt32 numAnonymousColsToAdd = GetColCount() - mColFrames.Length();
     if (numAnonymousColsToAdd > 0) {
       // this sets the child list, updates the col cache and cell map
       AppendAnonymousColFrames(numAnonymousColsToAdd);
     }
 
   } else {
     NS_ASSERTION(!aListName, "unexpected child list");
-    nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aOldFrame);
-    if (rgFrame) {
-      // remove the row group from the cell map
-      nsTableCellMap* cellMap = GetCellMap();
-      if (cellMap) {
-        cellMap->RemoveGroupCellMap(rgFrame);
-      }
-
-       // remove the row group frame from the sibling chain
-      mFrames.DestroyFrame(aOldFrame);
-     
-      // XXXldb [reflow branch merging 20060830] do we still need this?
-      if (cellMap) {
-        cellMap->Synchronize(this);
-        // Create an empty slice
-        ResetRowIndices(nsFrameList::Slice(mFrames, nsnull, nsnull));
-        nsRect damageArea;
-        cellMap->RebuildConsideringCells(nsnull, nsnull, 0, 0, PR_FALSE, damageArea);
-      }
-
-      MatchCellMapToColCache(cellMap);
-    } else {
-      // Just remove the frame
-      mFrames.DestroyFrame(aOldFrame);
-    }
+    nsTableRowGroupFrame* rgFrame =
+      static_cast<nsTableRowGroupFrame*>(aOldFrame);
+    // remove the row group from the cell map
+    nsTableCellMap* cellMap = GetCellMap();
+    if (cellMap) {
+      cellMap->RemoveGroupCellMap(rgFrame);
+    }
+
+    // remove the row group frame from the sibling chain
+    mFrames.DestroyFrame(aOldFrame);
+
+    // the removal of a row group changes the cellmap, the columns might change
+    if (cellMap) {
+      cellMap->Synchronize(this);
+      // Create an empty slice
+      ResetRowIndices(nsFrameList::Slice(mFrames, nsnull, nsnull));
+      nsRect damageArea;
+      cellMap->RebuildConsideringCells(nsnull, nsnull, 0, 0, PR_FALSE, damageArea);
+    }
+
+    MatchCellMapToColCache(cellMap);
   }
   // for now, just bail and recalc all of the collapsing borders
-  // XXXldb [reflow branch merging 20060830] do we still need this?
+  // as the cellmap changes we need to recalc
   if (IsBorderCollapse()) {
     nsRect damageArea(0, 0, NS_MAX(1, GetColCount()), NS_MAX(1, GetRowCount()));
     SetBCDamageArea(damageArea);
   }
   PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                                                NS_FRAME_HAS_DIRTY_CHILDREN);
   SetGeometryDirty();
 #ifdef DEBUG_TABLE_CELLMAP
@@ -2497,20 +2429,19 @@ nsTableFrame::GetChildAreaOffset(const n
 void
 nsTableFrame::InitChildReflowState(nsHTMLReflowState& aReflowState)                                    
 {
   nsMargin collapseBorder;
   nsMargin padding(0,0,0,0);
   nsMargin* pCollapseBorder = nsnull;
   nsPresContext* presContext = PresContext();
   if (IsBorderCollapse()) {
-    nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aReflowState.frame);
-    if (rgFrame) {
-      pCollapseBorder = rgFrame->GetBCBorderWidth(collapseBorder);
-    }
+    nsTableRowGroupFrame* rgFrame =
+       static_cast<nsTableRowGroupFrame*>(aReflowState.frame);
+    pCollapseBorder = rgFrame->GetBCBorderWidth(collapseBorder);
   }
   aReflowState.Init(presContext, -1, -1, pCollapseBorder, &padding);
 
   NS_ASSERTION(!mBits.mResizedColumns ||
                !aReflowState.parentReflowState->mFlags.mSpecialHeightReflow,
                "should not resize columns on special height reflow");
   if (mBits.mResizedColumns) {
     aReflowState.mFlags.mHResize = PR_TRUE;
@@ -2540,162 +2471,87 @@ void nsTableFrame::PlaceChild(nsTableRef
 
   // If our height is constrained, then update the available height
   if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
     aReflowState.availSize.height -= aKidDesiredSize.height;
   }
 }
 
 void
-nsTableFrame::OrderRowGroups(RowGroupArray& aChildren) const
+nsTableFrame::OrderRowGroups(RowGroupArray& aChildren,
+                             nsTableRowGroupFrame** aHead,
+                             nsTableRowGroupFrame** aFoot) const
 {
   aChildren.Clear();
   nsTableRowGroupFrame* head = nsnull;
   nsTableRowGroupFrame* foot = nsnull;
   
   nsIFrame* kidFrame = mFrames.FirstChild();
   while (kidFrame) {
     const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
-    nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
-    if (NS_LIKELY(rowGroup)) {
-      switch(kidDisplay->mDisplay) {
-      case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
-        if (head) { // treat additional thead like tbody
-          aChildren.AppendElement(rowGroup);
-        }
-        else {
-          head = rowGroup;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
-        if (foot) { // treat additional tfoot like tbody
-          aChildren.AppendElement(rowGroup);
-        }
-        else {
-          foot = rowGroup;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
+    nsTableRowGroupFrame* rowGroup =
+      static_cast<nsTableRowGroupFrame*>(kidFrame);
+
+    switch (kidDisplay->mDisplay) {
+    case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
+      if (head) { // treat additional thead like tbody
         aChildren.AppendElement(rowGroup);
-        break;
-      default:
-        NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
-        // Just ignore it
-        break;
+      }
+      else {
+        head = rowGroup;
+      }
+      break;
+    case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
+      if (foot) { // treat additional tfoot like tbody
+        aChildren.AppendElement(rowGroup);
       }
+      else {
+        foot = rowGroup;
+      }
+      break;
+    case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
+      aChildren.AppendElement(rowGroup);
+      break;
+    default:
+      NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
+      // Just ignore it
+      break;
     }
     // Get the next sibling but skip it if it's also the next-in-flow, since
     // a next-in-flow will not be part of the current table.
     while (kidFrame) {
       nsIFrame* nif = kidFrame->GetNextInFlow();
       kidFrame = kidFrame->GetNextSibling();
       if (kidFrame != nif) 
         break;
     }
   }
 
   // put the thead first
   if (head) {
     aChildren.InsertElementAt(0, head);
   }
-
+  if (aHead)
+    *aHead = head;
   // put the tfoot after the last tbody
   if (foot) {
     aChildren.AppendElement(foot);
   }
-}
-
-PRUint32
-nsTableFrame::OrderRowGroups(FrameArray& aChildren,
-                             nsTableRowGroupFrame** aHead,
-                             nsTableRowGroupFrame** aFoot) const
-{
-  aChildren.Clear();
-  // initialize out parameters
-  *aHead = nsnull;
-  *aFoot = nsnull;
-
-  FrameArray nonRowGroups;
-
-  nsIFrame* head = nsnull;
-  nsIFrame* foot = nsnull;
-  
-  nsIFrame* kidFrame = mFrames.FirstChild();
-  while (kidFrame) {
-    const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
-    nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
-    if (NS_LIKELY(rowGroup)) {
-      switch(kidDisplay->mDisplay) {
-      case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
-        if (head) { // treat additional thead like tbody
-          aChildren.AppendElement(kidFrame);
-        }
-        else {
-          head = kidFrame;
-          *aHead = rowGroup;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
-        if (foot) { // treat additional tfoot like tbody
-          aChildren.AppendElement(kidFrame);
-        }
-        else {
-          foot = kidFrame;
-          *aFoot = rowGroup;
-        }
-        break;
-      case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
-        aChildren.AppendElement(kidFrame);
-        break;
-      default:
-        break;
-      }
-    } else {
-      NS_NOTREACHED("Non-row-group primary frame list child of an "
-                    "nsTableFrame?  How come?");
-      nonRowGroups.AppendElement(kidFrame);
-    }
-
-    // Get the next sibling but skip it if it's also the next-in-flow, since
-    // a next-in-flow will not be part of the current table.
-    while (kidFrame) {
-      nsIFrame* nif = kidFrame->GetNextInFlow();
-      kidFrame = kidFrame->GetNextSibling();
-      if (kidFrame != nif) 
-        break;
-    }
-  }
-  
-  // put the thead first
-  if (head) {
-    aChildren.InsertElementAt(0, head);
-  }
-
-  // put the tfoot after the last tbody
-  if (foot) {
-    aChildren.AppendElement(foot);
-  }
-
-  PRUint32 rowGroupCount = aChildren.Length();
-  aChildren.AppendElements(nonRowGroups);
-
-  return rowGroupCount;
+  if (aFoot)
+    *aFoot = foot;
 }
 
 nsTableRowGroupFrame*
 nsTableFrame::GetTHead() const
 {
   nsIFrame* kidFrame = mFrames.FirstChild();
   while (kidFrame) {
     if (kidFrame->GetStyleDisplay()->mDisplay ==
           NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) {
-      nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
-      if (rg) {
-        return rg;
-      }
+      return static_cast<nsTableRowGroupFrame*>(kidFrame);
     }
 
     // Get the next sibling but skip it if it's also the next-in-flow, since
     // a next-in-flow will not be part of the current table.
     while (kidFrame) {
       nsIFrame* nif = kidFrame->GetNextInFlow();
       kidFrame = kidFrame->GetNextSibling();
       if (kidFrame != nif) 
@@ -2708,20 +2564,17 @@ nsTableFrame::GetTHead() const
 
 nsTableRowGroupFrame*
 nsTableFrame::GetTFoot() const
 {
   nsIFrame* kidFrame = mFrames.FirstChild();
   while (kidFrame) {
     if (kidFrame->GetStyleDisplay()->mDisplay ==
           NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) {
-      nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
-      if (rg) {
-        return rg;
-      }
+      return static_cast<nsTableRowGroupFrame*>(kidFrame);
     }
 
     // Get the next sibling but skip it if it's also the next-in-flow, since
     // a next-in-flow will not be part of the current table.
     while (kidFrame) {
       nsIFrame* nif = kidFrame->GetNextInFlow();
       kidFrame = kidFrame->GetNextSibling();
       if (kidFrame != nif) 
@@ -2741,23 +2594,16 @@ IsRepeatable(nscoord aFrameHeight, nscoo
 nsresult
 nsTableFrame::SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
                                      nsTableRowGroupFrame* aFrame,
                                      nscoord* aDesiredHeight)
 {
   nsPresContext* presContext = PresContext();
   nscoord pageHeight = presContext->GetPageSize().height;
 
-  if (aFrame->GetParent() != this || pageHeight == NS_UNCONSTRAINEDSIZE) {
-    // Must be a scrollable head/footer (we don't allow those to repeat), or
-    // page has unconstrained height for some reason.
-    *aDesiredHeight = 0;
-    return NS_OK;
-  }
-
   // Reflow the child with unconstrainted height
   nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
                                    aFrame,
                                    nsSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE),
                                    -1, -1, PR_FALSE);
   InitChildReflowState(kidReflowState);
   kidReflowState.mFlags.mIsTopOfPage = PR_TRUE;
   nsHTMLReflowMetrics desiredSize;
@@ -2793,19 +2639,19 @@ nsTableFrame::ReflowChildren(nsTableRefl
   PRBool isPaginated = presContext->IsPaginated();
 
   aOverflowArea = nsRect (0, 0, 0, 0);
 
   PRBool reflowAllKids = aReflowState.reflowState.ShouldReflowAllKids() ||
                          mBits.mResizedColumns ||
                          IsGeometryDirty();
 
-  FrameArray rowGroups;
+  RowGroupArray rowGroups;
   nsTableRowGroupFrame *thead, *tfoot;
-  PRUint32 numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
+  OrderRowGroups(rowGroups, &thead, &tfoot);
   PRBool pageBreak = PR_FALSE;
   nscoord footerHeight = 0;
 
   // Determine the repeatablility of headers and footers, and also the desired
   // height of any repeatable footer.
   // The repeatability of headers on continued tables is handled
   // when they are created in nsCSSFrameConstructor::CreateContinuingTableFrame.
   // We handle the repeatability of footers again here because we need to
@@ -2821,17 +2667,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
     }
     if (tfoot) {
       rv = SetupHeaderFooterChild(aReflowState, tfoot, &footerHeight);
       if (NS_FAILED(rv))
         return rv;
     }
   }
 
-  for (PRUint32 childX = 0; childX < numRowGroups; childX++) {
+  for (PRUint32 childX = 0; childX < rowGroups.Length(); childX++) {
     nsIFrame* kidFrame = rowGroups[childX];
     // Get the frame state bits
     // See if we should only reflow the dirty child frames
     if (reflowAllKids ||
         NS_SUBTREE_DIRTY(kidFrame) ||
         (aReflowState.reflowState.mFlags.mSpecialHeightReflow &&
          (isPaginated || (kidFrame->GetStateBits() &
                           NS_FRAME_CONTAINS_RELATIVE_HEIGHT)))) {
@@ -2840,17 +2686,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
         aStatus = NS_FRAME_NOT_COMPLETE;
         break;
       }
 
       nsSize kidAvailSize(aReflowState.availSize);
       // if the child is a tbody in paginated mode reduce the height by a repeated footer
       PRBool allowRepeatedFooter = PR_FALSE;
       if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
-        nsTableRowGroupFrame* kidRG = GetRowGroupFrame(kidFrame);
+        nsTableRowGroupFrame* kidRG =
+          static_cast<nsTableRowGroupFrame*>(kidFrame);
         if (kidRG != thead && kidRG != tfoot && tfoot && tfoot->IsRepeatable()) {
           // the child is a tbody and there is a repeatable footer
           NS_ASSERTION(tfoot == rowGroups[rowGroups.Length() - 1], "Missing footer!");
           if (footerHeight + cellSpacingY < kidAvailSize.height) {
             allowRepeatedFooter = PR_TRUE;
             kidAvailSize.height -= footerHeight + cellSpacingY;
           }
         }
@@ -2889,21 +2736,21 @@ nsTableFrame::ReflowChildren(nsTableRefl
         reorder = PR_TRUE;
 
       rv = ReflowChild(kidFrame, presContext, desiredSize, kidReflowState,
                        aReflowState.x, aReflowState.y,
                        NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
 
       if (reorder) {
         // reorder row groups the reflow may have changed the nextinflows
-        numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
+        OrderRowGroups(rowGroups, &thead, &tfoot);
         childX = rowGroups.IndexOf(kidFrame);
         if (childX == RowGroupArray::NoIndex) {
           // XXXbz can this happen?
-          childX = numRowGroups;
+          childX = rowGroups.Length();
         }
       }
       // see if the rowgroup did not fit on this page might be pushed on
       // the next page
       if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
           (NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight) &&
           kidReflowState.availableHeight < desiredSize.height) {
         // if we are on top of the page place with dataloss
@@ -2933,17 +2780,17 @@ nsTableFrame::ReflowChildren(nsTableRefl
 
       aLastChildReflowed   = kidFrame;
 
       pageBreak = PR_FALSE;
       // see if there is a page break after this row group or before the next one
       if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated && 
           (NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
         nsIFrame* nextKid =
-          (childX + 1 < numRowGroups) ? rowGroups[childX + 1] : nsnull;
+          (childX + 1 < rowGroups.Length()) ? rowGroups[childX + 1] : nsnull;
         pageBreak = PageBreakAfter(*kidFrame, nextKid);
       }
 
       // Place the child
       PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
                  oldKidOverflowRect);
 
       // Remember where we just were in case we end up pushing children
@@ -2967,17 +2814,18 @@ nsTableFrame::ReflowChildren(nsTableRefl
 
           // Fall through and update |rowGroups| with the new rowgroup, just as
           // it would have been if we had called OrderRowGroups again.
           // Note that rowGroups doesn't get used again after we PushChildren
           // below, anyway.
         }
 
         // Put the nextinflow so that it will get pushed
-        rowGroups.InsertElementAt(childX + 1, kidNextInFlow);
+        rowGroups.InsertElementAt(childX + 1,
+                           static_cast <nsTableRowGroupFrame*>(kidNextInFlow));
 
         // We've used up all of our available space so push the remaining
         // children to the next-in-flow
         nsIFrame* nextSibling = kidFrame->GetNextSibling();
         if (nsnull != nextSibling) {
           PushChildren(rowGroups, childX + 1);
         }
         if (allowRepeatedFooter) {
@@ -3061,25 +2909,20 @@ nsTableFrame::CalcDesiredHeight(const ns
   if (!cellMap) {
     NS_ASSERTION(PR_FALSE, "never ever call me until the cell map is built!");
     aDesiredSize.height = 0;
     return;
   }
   nscoord  cellSpacingY = GetCellSpacingY();
   nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
 
-  // get the natural height based on the last child's (row group or scroll frame) rect
-  FrameArray rowGroups;
-  PRUint32 numRowGroups;
-  {
-    // Scope for the dummies so we don't use them by accident
-    nsTableRowGroupFrame *dummy1, *dummy2;
-    numRowGroups = OrderRowGroups(rowGroups, &dummy1, &dummy2);
-  }
-  if (numRowGroups == 0) {
+  // get the natural height based on the last child's (row group) rect
+  RowGroupArray rowGroups;
+  OrderRowGroups(rowGroups);
+  if (rowGroups.IsEmpty()) {
     // tables can be used as rectangular items without content
     nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
     if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
         (tableSpecifiedHeight > 0) &&
         eCompatibility_NavQuirks != PresContext()->CompatibilityMode()) {
           // empty tables should not have a size in quirks mode
       aDesiredSize.height = tableSpecifiedHeight;
     } 
@@ -3087,17 +2930,17 @@ nsTableFrame::CalcDesiredHeight(const ns
       aDesiredSize.height = 0;
     return;
   }
   PRInt32 rowCount = cellMap->GetRowCount();
   PRInt32 colCount = cellMap->GetColCount();
   nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
   if (rowCount > 0 && colCount > 0) {
     desiredHeight += cellSpacingY;
-    for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
+    for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
       desiredHeight += rowGroups[rgX]->GetSize().height + cellSpacingY;
     }
   }
 
   // see if a specified table height requires dividing additional space to rows
   if (!GetPrevInFlow()) {
     nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
     if ((tableSpecifiedHeight > 0) && 
@@ -3383,17 +3226,16 @@ nsTableFrame::DistributeHeightToRows(con
         
         rgFrame->SetRect(nsRect(rgRect.x, yOriginRG, rgRect.width,
                                 rgRect.height + amountUsedByRG));
 
         nsTableFrame::InvalidateFrame(rgFrame, rgRect, rgOverflowRect,
                                       PR_FALSE);
       }
       // Make sure child views are properly positioned
-      // XXX what happens if childFrame is a scroll frame and this gets skipped? see also below
     }
     else if (amountUsed > 0 && yOriginRG != rgRect.y) {
       rgFrame->InvalidateOverflowRect();
       rgFrame->SetPosition(nsPoint(rgRect.x, yOriginRG));
       // Make sure child views are properly positioned
       nsTableFrame::RePositionViews(rgFrame);
       rgFrame->InvalidateOverflowRect();
     }
@@ -3473,18 +3315,16 @@ nscoord nsTableFrame::GetCellSpacingY()
 /* virtual */ nscoord
 nsTableFrame::GetBaseline() const
 {
   nscoord ascent = 0;
   RowGroupArray orderedRowGroups;
   OrderRowGroups(orderedRowGroups);
   nsTableRowFrame* firstRow = nsnull;
   for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
-    // XXXbz Do we really want to just let through the scrollable
-    // rowgroups and use their ascent?
     nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
     if (rgFrame->GetRowCount()) {
       firstRow = rgFrame->GetFirstRow(); 
       ascent = rgFrame->GetRect().y + firstRow->GetRect().y + firstRow->GetRowBaseline();
       break;
     }
   }
   if (!firstRow)
@@ -3620,40 +3460,40 @@ nsTableFrame::GetFrameAtOrBefore(nsIFram
   }
   return lastMatchingFrame;
 }
 
 #ifdef DEBUG
 void 
 nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
 {
-  nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aKidFrame);
-  if (rgFrame) {
-    nsIFrame* cFrame = rgFrame->GetFirstChild(nsnull);
-    while (cFrame) {
-      nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
-      if (rowFrame) {
-        printf("row(%d)=%p ", rowFrame->GetRowIndex(), rowFrame);
-        nsIFrame* childFrame = cFrame->GetFirstChild(nsnull);
-        while (childFrame) {
-          nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
-          if (cellFrame) {
-            PRInt32 colIndex;
-            cellFrame->GetColIndex(colIndex);
-            printf("cell(%d)=%p ", colIndex, childFrame);
-          }
-          childFrame = childFrame->GetNextSibling();
+  if (!aKidFrame)
+    return;
+
+  nsIFrame* cFrame = aKidFrame->GetFirstChild(nsnull);
+  while (cFrame) {
+    nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
+    if (rowFrame) {
+      printf("row(%d)=%p ", rowFrame->GetRowIndex(), rowFrame);
+      nsIFrame* childFrame = cFrame->GetFirstChild(nsnull);
+      while (childFrame) {
+        nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
+        if (cellFrame) {
+          PRInt32 colIndex;
+          cellFrame->GetColIndex(colIndex);
+          printf("cell(%d)=%p ", colIndex, childFrame);
         }
-        printf("\n");
+        childFrame = childFrame->GetNextSibling();
       }
-      else {
-        DumpRowGroup(rowFrame);
-      }
-      cFrame = cFrame->GetNextSibling();
-    }
+      printf("\n");
+    }
+    else {
+      DumpRowGroup(rowFrame);
+    }
+    cFrame = cFrame->GetNextSibling();
   }
 }
 
 void 
 nsTableFrame::Dump(PRBool          aDumpRows,
                    PRBool          aDumpCols, 
                    PRBool          aDumpCellMap)
 {
@@ -4322,17 +4162,17 @@ BCMapCellInfo::SetInfo(nsTableRowFrame* 
     }
   }
   // row group frame info
   // try to reuse the rgStart and rgEnd from the iterator as calls to
   // GetRowCount() are computationally expensive and should be avoided if
   // possible
   PRUint32 rgStart  = aIter->mRowGroupStart;
   PRUint32 rgEnd    = aIter->mRowGroupEnd;
-  mRowGroup = mTableFrame->GetRowGroupFrame(mTopRow->GetParent());
+  mRowGroup = static_cast<nsTableRowGroupFrame*>(mTopRow->GetParent());
   if (mRowGroup != aIter->GetCurrentRowGroup()) {
     rgStart = mRowGroup->GetStartRowIndex();
     rgEnd   = rgStart + mRowGroup->GetRowCount() - 1;
   }
   PRUint32 rowIndex = mTopRow->GetRowIndex();
   mRgAtTop    = (rgStart == rowIndex);
   mRgAtBottom = (rgEnd == rowIndex + mRowSpan - 1);
   
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -475,26 +475,21 @@ public:
 
   virtual void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
                            PRInt32                      aRowIndex,
                            PRInt32                      aColIndexBefore);
 
   virtual void RemoveCell(nsTableCellFrame* aCellFrame,
                           PRInt32           aRowIndex);
 
-  void AppendRows(nsTableRowGroupFrame&       aRowGroupFrame,
+  void AppendRows(nsTableRowGroupFrame*       aRowGroupFrame,
                   PRInt32                     aRowIndex,
                   nsTArray<nsTableRowFrame*>& aRowFrames);
 
-  PRInt32 InsertRow(nsTableRowGroupFrame& aRowGroupFrame,
-                    nsIFrame&             aFrame,
-                    PRInt32               aRowIndex,
-                    PRBool                aConsiderSpans);
-
-  PRInt32 InsertRows(nsTableRowGroupFrame&       aRowGroupFrame,
+  PRInt32 InsertRows(nsTableRowGroupFrame*       aRowGroupFrame,
                      nsTArray<nsTableRowFrame*>& aFrames,
                      PRInt32                     aRowIndex,
                      PRBool                      aConsiderSpans);
 
   virtual void RemoveRows(nsTableRowFrame& aFirstRowFrame,
                           PRInt32          aNumRowsToRemove,
                           PRBool           aConsiderSpans);
 
@@ -624,58 +619,43 @@ protected:
 
   void PlaceChild(nsTableReflowState&  aReflowState,
                   nsIFrame*            aKidFrame,
                   nsHTMLReflowMetrics& aKidDesiredSize,
                   const nsRect&        aOriginalKidRect,
                   const nsRect&        aOriginalKidOverflowRect);
 
   nsIFrame* GetFirstBodyRowGroupFrame();
+public:
+  typedef nsAutoTPtrArray<nsTableRowGroupFrame, 8> RowGroupArray;
   /**
-   * Push all our child frames from the aFrames array, in order, starting from the
-   * frame at aPushFrom to the end of the array. The frames are put on our overflow
-   * list or moved directly to our next-in-flow if one exists.
+   * Push all our child frames from the aRowGroups array, in order, starting
+   * from the frame at aPushFrom to the end of the array. The frames are put on
+   * our overflow list or moved directly to our next-in-flow if one exists.
    */
-  typedef nsAutoTPtrArray<nsIFrame, 8> FrameArray;
-  void PushChildren(const FrameArray& aFrames, PRInt32 aPushFrom);
+protected:
+  void PushChildren(const RowGroupArray& aRowGroups, PRInt32 aPushFrom);
 
 public:
   // put the children frames in the display order (e.g. thead before tbodies
   // before tfoot). This will handle calling GetRowGroupFrame() on the
   // children, and not append nulls, so the array is guaranteed to contain
   // nsTableRowGroupFrames.  If there are multiple theads or tfoots, all but
   // the first one are treated as tbodies instead.
-  typedef nsAutoTPtrArray<nsTableRowGroupFrame, 8> RowGroupArray;
-  void OrderRowGroups(RowGroupArray& aChildren) const;
+
+  void OrderRowGroups(RowGroupArray& aChildren,
+                      nsTableRowGroupFrame** aHead = nsnull,
+                      nsTableRowGroupFrame** aFoot = nsnull) const;
 
   // Return the thead, if any
   nsTableRowGroupFrame* GetTHead() const;
 
   // Return the tfoot, if any
   nsTableRowGroupFrame* GetTFoot() const;
 
-protected:
-  // As above, but does NOT actually call GetRowGroupFrame() on the kids, so
-  // returns an array of nsIFrames.  This is to be used when you really want
-  // the flowable kids of the table, not the rowgroups.  This outputs the thead
-  // and tfoot if they happen to be rowgroups.  All the child nsIFrames of the
-  // table that return null if you call GetRowGroupFrame() on them will appear
-  // at the end of the array, after the tfoot, if any.
-  //
-  // aHead and aFoot must not be null.
-  //
-  // @return the number of frames in aChildren which return non-null if you
-  // call GetRowGroupFrame() on them.
-  //
-  // XXXbz why do we really care about the non-rowgroup kids?
-  PRUint32 OrderRowGroups(FrameArray& aChildren,
-                          nsTableRowGroupFrame** aHead,
-                          nsTableRowGroupFrame** aFoot) const;
-
-public:
   // Returns PR_TRUE if there are any cells above the row at
   // aRowIndex and spanning into the row at aRowIndex, the number of
   // effective columns limits the search up to that column
   PRBool RowIsSpannedInto(PRInt32 aRowIndex, PRInt32 aNumEffCols);
 
   // Returns PR_TRUE if there is a cell originating in aRowIndex
   // which spans into the next row,  the number of effective
   // columns limits the search up to that column
@@ -737,38 +717,33 @@ public:
     * reordering but are not yet inserted into the cellmap
     * @param aRowGroupsToExclude - an iterator that will produce the row groups
     *                              to exclude.
     */
   void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
 
   nsTArray<nsTableColFrame*>& GetColCache();
 
-  /** Return aFrame's child if aFrame is an nsScrollFrame, otherwise return aFrame
-    */
-  static nsTableRowGroupFrame* GetRowGroupFrame(nsIFrame* aFrame,
-                                                nsIAtom*  aFrameTypeIn = nsnull);
-
 protected:
 
   void SetBorderCollapse(PRBool aValue);
 
   void CalcBCBorders();
 
   void ExpandBCDamageArea(nsRect& aRect) const;
 
   void SetColumnDimensions(nscoord         aHeight,
                            const nsMargin& aReflowState);
 
   PRInt32 CollectRows(nsIFrame*                   aFrame,
                       nsTArray<nsTableRowFrame*>& aCollection);
 
 public: /* ----- Cell Map public methods ----- */
 
-  PRInt32 GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame);
+  PRInt32 GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
 
   /** returns the number of rows in this table.
     */
   PRInt32 GetRowCount () const
   {
     return GetCellMap()->GetRowCount();
   }
 
--- a/layout/tables/nsTablePainter.cpp
+++ b/layout/tables/nsTablePainter.cpp
@@ -449,18 +449,17 @@ TableBackgroundPainter::PaintTable(nsTab
 
   for (PRUint32 i = 0; i < rowGroups.Length(); i++) {
     nsTableRowGroupFrame* rg = rowGroups[i];
     mRowGroup.SetFrame(rg);
     // Need to compute the right rect via GetOffsetTo, since the row
     // group may not be a child of the table.
     mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
     if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) {
-      nsresult rv = PaintRowGroup(rg,
-              rg->IsPseudoStackingContextFromStyle() || rg->IsScrolled());
+      nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle());
       if (NS_FAILED(rv)) return rv;
     }
   }
   return NS_OK;
 }
 
 nsresult
 TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
--- a/layout/tables/nsTableRowGroupFrame.cpp
+++ b/layout/tables/nsTableRowGroupFrame.cpp
@@ -97,17 +97,17 @@ PRInt32 nsTableRowGroupFrame::GetStartRo
     NS_ASSERTION(mFrames.FirstChild()->GetType() == nsGkAtoms::tableRowFrame,
                  "Unexpected frame type");
     result = static_cast<nsTableRowFrame*>(mFrames.FirstChild())->GetRowIndex();
   }
   // if the row group doesn't have any children, get it the hard way
   if (-1 == result) {
     nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     if (tableFrame) {
-      return tableFrame->GetStartRowIndex(*this);
+      return tableFrame->GetStartRowIndex(this);
     }
   }
       
   return result;
 }
 
 void  nsTableRowGroupFrame::AdjustRowIndices(PRInt32 aRowIndex,
                                              PRInt32 anAdjustment)
@@ -248,17 +248,17 @@ DisplayRows(nsDisplayListBuilder* aBuild
 NS_IMETHODIMP
 nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                        const nsRect&           aDirtyRect,
                                        const nsDisplayListSet& aLists)
 {
   if (!IsVisibleInSelection(aBuilder))
     return NS_OK;
 
-  PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext() || IsScrolled();
+  PRBool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
   nsDisplayTableItem* item = nsnull;
   if (isRoot) {
     // This background is created regardless of whether this frame is
     // visible or not. Visibility decisions are delegated to the
     // table background painter.
     item = new (aBuilder) nsDisplayTableRowGroupBackground(this);
     nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -1404,17 +1404,17 @@ nsTableRowGroupFrame::AppendFrames(nsIAt
 
   PRInt32 rowIndex = GetRowCount();
   // Append the frames to the sibling chain
   mFrames.AppendFrames(nsnull, aFrameList);
 
   if (rows.Length() > 0) {
     nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
     if (tableFrame) {
-      tableFrame->AppendRows(*this, rowIndex, rows);
+      tableFrame->AppendRows(this, rowIndex, rows);
       PresContext()->PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
       tableFrame->SetGeometryDirty();
     }
   }
 
   return NS_OK;
@@ -1458,17 +1458,17 @@ nsTableRowGroupFrame::InsertFrames(nsIAt
   PRInt32 startRowIndex = GetStartRowIndex();
   // Insert the frames in the sibling chain
   mFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
 
   PRInt32 numRows = rows.Length();
   if (numRows > 0) {
     nsTableRowFrame* prevRow = (nsTableRowFrame *)nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame, nsGkAtoms::tableRowFrame);
     PRInt32 rowIndex = (prevRow) ? prevRow->GetRowIndex() + 1 : startRowIndex;
-    tableFrame->InsertRows(*this, rows, rowIndex, PR_TRUE);
+    tableFrame->InsertRows(this, rows, rowIndex, PR_TRUE);
 
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                        NS_FRAME_HAS_DIRTY_CHILDREN);
     tableFrame->SetGeometryDirty();
   }
   return NS_OK;
 }
--- a/layout/tables/nsTableRowGroupFrame.h
+++ b/layout/tables/nsTableRowGroupFrame.h
@@ -38,17 +38,16 @@
 #define nsTableRowGroupFrame_h__
 
 #include "nscore.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsIAtom.h"
 #include "nsILineIterator.h"
 #include "nsTablePainter.h"
 #include "nsTArray.h"
-#include "nsCSSAnonBoxes.h"
 
 class nsTableFrame;
 class nsTableRowFrame;
 class nsTableCellFrame;
 
 struct nsRowGroupReflowState {
   const nsHTMLReflowState& reflowState;  // Our reflow state
 
@@ -354,23 +353,16 @@ public:
   /**
    * Set up the row cursor. After this, call AppendFrame for every
    * child frame in sibling order. Ensure that the child frame y and YMost values
    * form non-decreasing sequences (should always be true for table rows);
    * if this is violated, call ClearRowCursor(). If we return nsnull, then we
    * decided not to use a cursor or we already have one set up.
    */
   FrameCursorData* SetupRowCursor();
-  
-  PRBool IsScrolled() {
-    // Note that if mOverflowY is CLIP, so is mOverflowX, and we need to clip the background
-    // as if the rowgroup is scrollable.
-    return GetStyleContext()->GetPseudo() == nsCSSAnonBoxes::scrolledContent ||
-           GetStyleDisplay()->mOverflowY == NS_STYLE_OVERFLOW_CLIP;
-  }
 
   virtual nsILineIterator* GetLineIterator() { return this; }
 
 protected:
   nsTableRowGroupFrame(nsStyleContext* aContext);
 
   void InitChildReflowState(nsPresContext&     aPresContext, 
                             PRBool             aBorderCollapse,