From 4a9bcccc016042288d648077bc944bc55d69c1e2 Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Wed, 14 Oct 1998 16:32:45 +0000 Subject: [PATCH] lots of work for incremental reflow when the target frame is a table frame git-svn-id: svn://10.0.0.236/trunk@12807 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/html/table/src/nsCellMap.h | 9 + .../html/table/src/nsTableColGroupFrame.cpp | 243 +++--- .../layout/html/table/src/nsTableFrame.cpp | 604 +++++++++----- mozilla/layout/html/table/src/nsTableFrame.h | 39 +- .../html/table/src/nsTableOuterFrame.cpp | 4 +- .../layout/html/table/src/nsTableOuterFrame.h | 2 +- .../layout/html/table/src/nsTableRowFrame.cpp | 744 ++++++++++++------ .../layout/html/table/src/nsTableRowFrame.h | 75 +- .../html/table/src/nsTableRowGroupFrame.cpp | 378 +++++++-- .../html/table/src/nsTableRowGroupFrame.h | 76 +- mozilla/layout/tables/nsCellMap.h | 9 + .../layout/tables/nsTableColGroupFrame.cpp | 243 +++--- mozilla/layout/tables/nsTableFrame.cpp | 604 +++++++++----- mozilla/layout/tables/nsTableFrame.h | 39 +- mozilla/layout/tables/nsTableOuterFrame.cpp | 4 +- mozilla/layout/tables/nsTableOuterFrame.h | 2 +- mozilla/layout/tables/nsTableRowFrame.cpp | 744 ++++++++++++------ mozilla/layout/tables/nsTableRowFrame.h | 75 +- .../layout/tables/nsTableRowGroupFrame.cpp | 378 +++++++-- mozilla/layout/tables/nsTableRowGroupFrame.h | 76 +- 20 files changed, 3152 insertions(+), 1196 deletions(-) diff --git a/mozilla/layout/html/table/src/nsCellMap.h b/mozilla/layout/html/table/src/nsCellMap.h index e5e9a23f71b..723536e3aad 100644 --- a/mozilla/layout/html/table/src/nsCellMap.h +++ b/mozilla/layout/html/table/src/nsCellMap.h @@ -119,6 +119,9 @@ public: */ void AppendColumnFrame(nsTableColFrame *aColFrame); + /** empty the column frame cache */ + void ClearColumnCache(); + /** returns PR_TRUE if the row at aRowIndex has any cells that are the result * of a row-spanning cell above it. So, given this table:
*
@@ -227,5 +230,11 @@ inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
   mColFrames->AppendElement(aColFrame);
 }
 
+inline void nsCellMap::ClearColumnCache()
+{
+  if (nsnull!=mColFrames)
+    mColFrames->Clear();
+}
+
 
 #endif
diff --git a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
index c7a676ddc00..ffd056193bd 100644
--- a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
@@ -52,87 +52,89 @@ nsresult
 nsTableColGroupFrame::InitNewFrames(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
   nsresult rv=NS_OK;
-  nsIFrame* tableFrame=nsnull;
-  GetGeometricParent(tableFrame);
-  // Process the newly added column frames
-  for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) {
-    // Set the preliminary values for the column frame
-    nsIContent* kid;
-    kidFrame->GetContent(kid);
-    // should use style to get this value
-    PRInt32 repeat=1;
-    nsIHTMLTableColElement* colContent = nsnull;
-    rv = kid->QueryInterface(kIHTMLTableColElementIID, 
-                     (void**) &colContent); // colContent: ADDREF++
-    NS_RELEASE(kid);
-    if (rv==NS_OK)
-    {
-      colContent->GetSpanValue(&repeat);
-      NS_RELEASE(colContent);
-    }
-    PRInt32 colIndex = mStartColIndex + mColCount;
-    ((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex, repeat);
-    mColCount+= repeat;
-    ((nsTableColFrame *)kidFrame)->SetColumnIndex(colIndex);
-    ((nsTableFrame *)tableFrame)->AddColumnFrame((nsTableColFrame *)kidFrame);
-  }
-  // colgroup's span attribute is how many columns the group represents
-  // in the absence of any COL children
-  if (0==mColCount)
+  nsTableFrame* tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
   {
-    nsIFrame *firstImplicitColFrame=nsnull;
-    nsIFrame *prevColFrame=nsnull;
-    nsAutoString colTag;
-    nsHTMLAtoms::col->ToString(colTag);
-    mColCount = GetSpan();
-    for (PRInt32 colIndex=0; colIndexAppendChildTo((nsIContent*)col, PR_FALSE);
-
-      // Create a new col frame
-      nsIFrame* colFrame;
-      NS_NewTableColFrame(col, this, colFrame);
-
-      // Set its style context
-      nsIStyleContextPtr colStyleContext =
-        aPresContext.ResolveStyleContextFor(col, this, PR_TRUE);
-      colFrame->SetStyleContext(&aPresContext, colStyleContext);
-      colFrame->Init(aPresContext, nsnull);
-
-      // Set nsColFrame-specific information
-      PRInt32 absColIndex = mStartColIndex + colIndex;
-      ((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex, 1);
-      ((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
-      ((nsTableFrame *)tableFrame)->AddColumnFrame((nsTableColFrame *)colFrame);
-
-      //hook into list of children
-      if (nsnull==firstImplicitColFrame)
-        firstImplicitColFrame = colFrame;
-      else
-        prevColFrame->SetNextSibling(colFrame);
-      prevColFrame = colFrame;
-    }
-    // hook new columns into col group child list
-    if (nsnull==mFirstChild)
-      mFirstChild = firstImplicitColFrame;
-    else
-    {
-      nsIFrame *lastChild = mFirstChild;
-      nsIFrame *nextChild = lastChild;
-      while (nsnull!=nextChild)
+    // Process the newly added column frames
+    for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) {
+      // Set the preliminary values for the column frame
+      nsIContent* kid;
+      kidFrame->GetContent(kid);
+      // should use style to get this value
+      PRInt32 repeat=1;
+      nsIHTMLTableColElement* colContent = nsnull;
+      rv = kid->QueryInterface(kIHTMLTableColElementIID, 
+                       (void**) &colContent); // colContent: ADDREF++
+      NS_RELEASE(kid);
+      if (rv==NS_OK)
       {
-        lastChild = nextChild;
-        nextChild->GetNextSibling(nextChild);
+        colContent->GetSpanValue(&repeat);
+        NS_RELEASE(colContent);
       }
-      lastChild->SetNextSibling(firstImplicitColFrame);
+      PRInt32 colIndex = mStartColIndex + mColCount;
+      ((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex, repeat);
+      mColCount+= repeat;
+      ((nsTableColFrame *)kidFrame)->SetColumnIndex(colIndex);
+      tableFrame->AddColumnFrame((nsTableColFrame *)kidFrame);
     }
-  }
-  SetStyleContextForFirstPass(aPresContext);
+    // colgroup's span attribute is how many columns the group represents
+    // in the absence of any COL children
+    if (0==mColCount)
+    {
+      nsIFrame *firstImplicitColFrame=nsnull;
+      nsIFrame *prevColFrame=nsnull;
+      nsAutoString colTag;
+      nsHTMLAtoms::col->ToString(colTag);
+      mColCount = GetSpan();
+      for (PRInt32 colIndex=0; colIndexAppendChildTo((nsIContent*)col, PR_FALSE);
 
+        // Create a new col frame
+        nsIFrame* colFrame;
+        NS_NewTableColFrame(col, this, colFrame);
+
+        // Set its style context
+        nsIStyleContextPtr colStyleContext =
+          aPresContext.ResolveStyleContextFor(col, this, PR_TRUE);
+        colFrame->SetStyleContext(&aPresContext, colStyleContext);
+        colFrame->Init(aPresContext, nsnull);
+
+        // Set nsColFrame-specific information
+        PRInt32 absColIndex = mStartColIndex + colIndex;
+        ((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex, 1);
+        ((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
+        tableFrame->AddColumnFrame((nsTableColFrame *)colFrame);
+
+        //hook into list of children
+        if (nsnull==firstImplicitColFrame)
+          firstImplicitColFrame = colFrame;
+        else
+          prevColFrame->SetNextSibling(colFrame);
+        prevColFrame = colFrame;
+      }
+      // hook new columns into col group child list
+      if (nsnull==mFirstChild)
+        mFirstChild = firstImplicitColFrame;
+      else
+      {
+        nsIFrame *lastChild = mFirstChild;
+        nsIFrame *nextChild = lastChild;
+        while (nsnull!=nextChild)
+        {
+          lastChild = nextChild;
+          nextChild->GetNextSibling(nextChild);
+        }
+        lastChild->SetNextSibling(firstImplicitColFrame);
+      }
+    }
+    SetStyleContextForFirstPass(aPresContext);
+  }
   return rv;
 }
 
@@ -233,54 +235,55 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext&          aPresContext,
 NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext& aPresContext)
 {
   // get the table frame
-  nsIFrame* tableFrame=nsnull;
-  GetGeometricParent(tableFrame);
-  
-  // get the style for the table frame
-  nsStyleTable *tableStyle;
-  tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
+  nsTableFrame* tableFrame=nsnull;
+  nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
+  {  
+    // get the style for the table frame
+    nsStyleTable *tableStyle;
+    tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
 
-  // if COLS is set, then map it into the COL frames
-  if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
-  {
-    // set numCols to the number of columns effected by the COLS attribute
-    PRInt32 numCols=0;
-    if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
-      numCols = LengthOf(mFirstChild);
-    else 
-      numCols = tableStyle->mCols;
-
-    // for every column effected, set its width style
-    PRInt32 colIndex=0;
-    nsIFrame *colFrame=mFirstChild;
-    while (nsnull!=colFrame)
+    // if COLS is set, then map it into the COL frames
+    if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
     {
-      nsStyleDisplay * colDisplay=nsnull;
-      colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
-      {
-        nsIStyleContextPtr colStyleContext;
-        nsStylePosition * colPosition=nsnull;
-        colFrame->GetStyleContext(&aPresContext, colStyleContext.AssignRef());
-        colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
-        if (colIndexmWidth = width;
-        }
-        else
-        {
-          colPosition->mWidth.SetCoordValue(0);
-        }
-        colStyleContext->RecalcAutomaticData(&aPresContext);
-        colIndex++;
-      }
-      colFrame->GetNextSibling(colFrame);
-    }
+      // set numCols to the number of columns effected by the COLS attribute
+      PRInt32 numCols=0;
+      if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
+        numCols = LengthOf(mFirstChild);
+      else 
+        numCols = tableStyle->mCols;
 
-    mStyleContext->RecalcAutomaticData(&aPresContext);
+      // for every column effected, set its width style
+      PRInt32 colIndex=0;
+      nsIFrame *colFrame=mFirstChild;
+      while (nsnull!=colFrame)
+      {
+        nsStyleDisplay * colDisplay=nsnull;
+        colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        {
+          nsIStyleContextPtr colStyleContext;
+          nsStylePosition * colPosition=nsnull;
+          colFrame->GetStyleContext(&aPresContext, colStyleContext.AssignRef());
+          colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
+          if (colIndexmWidth = width;
+          }
+          else
+          {
+            colPosition->mWidth.SetCoordValue(0);
+          }
+          colStyleContext->RecalcAutomaticData(&aPresContext);
+          colIndex++;
+        }
+        colFrame->GetNextSibling(colFrame);
+      }
+      mStyleContext->RecalcAutomaticData(&aPresContext);
+    }
   }
-  return NS_OK;
+  return rv;
 }
 
 
diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp
index dcf88de6ec8..64e775c30a1 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableFrame.cpp
@@ -270,6 +270,7 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
     mColCache(nsnull),
     mTableLayoutStrategy(nsnull),
     mFirstPassValid(PR_FALSE),
+    mCellMapValid(PR_TRUE),
     mIsInvariantWidth(PR_FALSE)
 {
   mEffectiveColCount = -1;  // -1 means uninitialized
@@ -298,11 +299,44 @@ nsTableFrame::~nsTableFrame()
 NS_IMETHODIMP
 nsTableFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
+  nsresult rv=NS_OK;
   mFirstChild = aChildList;
-  EnsureColumns(aPresContext);
-  return NS_OK;
+  // I know now that I have all my children, so build the cell map
+  nsIFrame *nextRowGroup=mFirstChild;
+  for ( ; nsnull!=nextRowGroup; nextRowGroup->GetNextSibling(nextRowGroup))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    nextRowGroup->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      rv = DidAppendRowGroup((nsTableRowGroupFrame*)nextRowGroup);
+    }
+  }
+  if (NS_SUCCEEDED(rv))
+    EnsureColumns(aPresContext);
+  return rv;
 }
 
+NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame)
+{
+  nsresult rv=NS_OK;
+  nsIFrame *nextRow=nsnull;
+  aRowGroupFrame->FirstChild(nextRow);
+  for ( ; nsnull!=nextRow; nextRow->GetNextSibling(nextRow))
+  {
+    const nsStyleDisplay *rowDisplay;
+    nextRow->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+    if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+    {
+      rv = ((nsTableRowFrame *)nextRow)->InitChildren();
+      if (NS_FAILED(rv))
+        return rv;
+    }
+  }
+  return rv;
+}
+
+
 /* ****** CellMap methods ******* */
 
 /* return the next row group frame after aRowGroupFrame */
@@ -322,14 +356,12 @@ nsTableRowGroupFrame* nsTableFrame::NextRowGroupFrame(nsTableRowGroupFrame* aRow
     const nsStyleDisplay *display;
     aRowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
     if (PR_TRUE==IsRowGroup(display->mDisplay))
-    { //XXX: assumes content order
+    { 
       break;
     }
-
     // Get the next frame
     aRowGroupFrame->GetNextSibling((nsIFrame*&)aRowGroupFrame);
   }
-
   return aRowGroupFrame;
 }
 
@@ -346,10 +378,6 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
     {
       mColCount += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
     }
-    else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    { //XXX: assumes content order
-      break;
-    }
     childFrame->GetNextSibling(childFrame);
   }    
   return mColCount;
@@ -358,24 +386,10 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
 PRInt32 nsTableFrame::GetRowCount ()
 {
   PRInt32 rowCount = 0;
-
   nsCellMap *cellMap = GetCellMap();
-  if (nsnull != cellMap)
-    return cellMap->GetRowCount();
-
-  nsIFrame *child=mFirstChild;
-  while (nsnull!=child)
-  {
-    const nsStyleDisplay *childDisplay;
-    child->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
-    if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    {
-      PRInt32 thisRowCount=0;
-      ((nsTableRowGroupFrame *)child)->GetRowCount(thisRowCount);
-      rowCount += thisRowCount;
-    }
-    child->GetNextSibling(child);
-  }
+  NS_ASSERTION(nsnull!=cellMap, "GetRowCount null cellmap");
+  if (nsnull!=cellMap)
+    rowCount = cellMap->GetRowCount();
   return rowCount;
 }
 
@@ -383,7 +397,7 @@ PRInt32 nsTableFrame::GetRowCount ()
 PRInt32 nsTableFrame::GetColCount ()
 {
   nsCellMap *cellMap = GetCellMap();
-  NS_ASSERTION(nsnull!=cellMap, "GetColCount can only be called after cellmap has been created");
+  NS_ASSERTION(nsnull!=cellMap, "GetColCount null cellmap");
 
   if (nsnull!=cellMap)
   {
@@ -396,6 +410,7 @@ PRInt32 nsTableFrame::GetColCount ()
 void nsTableFrame::SetEffectiveColCount()
 {
   nsCellMap *cellMap = GetCellMap();
+  NS_ASSERTION(nsnull!=cellMap, "SetEffectiveColCount null cellmap");
   if (nsnull!=cellMap)
   {
     PRInt32 colCount = cellMap->GetColCount();
@@ -589,7 +604,7 @@ NS_ASSERTION(0mDisplay))
-    { // XXX: assumes content order
-      firstRowGroupFrame = childFrame;
-      if (PR_TRUE==gsDebug) printf("EC: found a row group %p\n", firstRowGroupFrame);
-      break;
+    {
+      if (nsnull==firstRowGroupFrame)
+      {
+        firstRowGroupFrame = childFrame;
+        if (PR_TRUE==gsDebug) printf("EC: found a row group %p\n", firstRowGroupFrame);
+      }
     }
-    prevSibFrame = childFrame;
+    if (nsnull==firstRowGroupFrame)
+      prevSibFrame = childFrame;
     childFrame->GetNextSibling(childFrame);
   }
   PRInt32 colCount = GetColCount();
@@ -666,7 +674,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext)
       nsAutoString colGroupTag;
       nsHTMLAtoms::colgroup->ToString(colGroupTag);
       rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag);  // ADDREF a: lastColGroup++
-      //XXX mark it as implicit!
+      //XXX: make synthetic
       mContent->AppendChildTo(lastColGroup, PR_FALSE);  // add the implicit colgroup to my content
       // Resolve style for the child
       nsIStyleContext* colGroupStyleContext =
@@ -716,7 +724,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext)
       nsIHTMLContent *col=nsnull;
       // create an implicit col
       rv = NS_CreateHTMLElement(&col, colTag);  // ADDREF: col++
-      //XXX mark the col implicit
+      //XXX: make synthetic
       lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
 
       // Create a new col frame
@@ -759,7 +767,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
   PRInt32 actualColumns = 0;
   nsTableColGroupFrame *lastColGroupFrame = nsnull;
   nsIFrame * firstRowGroupFrame=nsnull;
-  nsIFrame * prevSibFrame=nsnull;
+  nsIFrame * prevSibFrame=nsnull; // this is the child just before the first row group frame
   nsIFrame * childFrame=mFirstChild;
   while (nsnull!=childFrame)
   {
@@ -774,11 +782,12 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
         break;  // we have enough col frames at this point
     }
     else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    { // XXX: assumes content order
-      firstRowGroupFrame = childFrame;
-      break;
+    {
+      if (nsnull==firstRowGroupFrame)
+        firstRowGroupFrame = childFrame;
     }
-    prevSibFrame = childFrame;
+    if (nsnull==firstRowGroupFrame)
+      prevSibFrame = childFrame;
     childFrame->GetNextSibling(childFrame);
   }    
   if (actualColumns <= aColIndex)
@@ -790,6 +799,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
       nsAutoString colGroupTag;
       nsHTMLAtoms::colgroup->ToString(colGroupTag);
       rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag);  // ADDREF a: lastColGroup++
+      //XXX: make synthetic
       //XXX mark it as implicit!
       mContent->AppendChildTo(lastColGroup, PR_FALSE);  // add the implicit colgroup to my content
       // Resolve style for the child
@@ -837,7 +847,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
       nsIHTMLContent *col=nsnull;
       // create an implicit col
       rv = NS_CreateHTMLElement(&col, colTag);  // ADDREF: col++
-      //XXX mark the col implicit
+      //XXX: make synthetic
       lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
 
       // Create a new col frame
@@ -868,17 +878,22 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
 
 void nsTableFrame::AddColumnFrame (nsTableColFrame *aColFrame)
 {
-  mCellMap->AppendColumnFrame(aColFrame);
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
+    cellMap->AppendColumnFrame(aColFrame);
 }
 
 /** return the index of the next row that is not yet assigned */
 PRInt32 nsTableFrame::GetNextAvailRowIndex() const
 {
   PRInt32 result=0;
-  if (nsnull!=mCellMap)
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
   {
-    result = mCellMap->GetRowCount(); // the next index is the current count
-    mCellMap->GrowToRow(result+1);    // expand the cell map to include this new row
+    result = cellMap->GetRowCount(); // the next index is the current count
+    cellMap->GrowToRow(result+1);    // expand the cell map to include this new row
   }
   return result;
 }
@@ -887,15 +902,17 @@ PRInt32 nsTableFrame::GetNextAvailRowIndex() const
 PRInt32 nsTableFrame::GetNextAvailColIndex(PRInt32 aRowIndex, PRInt32 aColIndex) const
 {
   PRInt32 result=0;
-  if (nsnull!=mCellMap)
-    result = mCellMap->GetNextAvailColIndex(aRowIndex, aColIndex);
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
+    result = cellMap->GetNextAvailColIndex(aRowIndex, aColIndex);
   return result;
 }
 
 /** Get the cell map for this table frame.  It is not always mCellMap.
   * Only the firstInFlow has a legit cell map
   */
-nsCellMap * nsTableFrame::GetCellMap()
+nsCellMap * nsTableFrame::GetCellMap() const
 {
   nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
   if (this!=firstInFlow)
@@ -951,7 +968,6 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
   }
 
   PRInt32 rowIndex;
-  // If we have a cell map reset it; otherwise allocate a new cell map
   // also determine the index of aRowFrame and set it if necessary
   if (0==mCellMap->GetRowCount())
   { // this is the first time we've ever been called
@@ -979,6 +995,34 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
     DumpCellMap ();
 }
 
+NS_METHOD nsTableFrame::ReBuildCellMap()
+{
+  nsresult rv=NS_OK;
+  nsIFrame *rowGroupFrame=mFirstChild;
+  for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      nsIFrame *rowFrame;
+      rowGroupFrame->FirstChild(rowFrame);
+      for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
+      {
+        const nsStyleDisplay *rowDisplay;
+        rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+        if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+        {
+          rv = ((nsTableRowFrame *)rowFrame)->InitChildren();
+          if (NS_FAILED(rv))
+            return rv;
+        }
+      }
+    }
+  }
+  return rv;
+}
+
 /**
   */
 void nsTableFrame::DumpCellMap () 
@@ -1054,20 +1098,20 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   // Setup CellMap for this cell
   int rowSpan = aCell->GetRowSpan();
   int colSpan = aCell->GetColSpan();
-  if (gsDebug==PR_TRUE) printf("        BuildCellIntoMap. rowSpan = %d, colSpan = %d\n", rowSpan, colSpan);
+  if (gsDebug==PR_TRUE) printf("BCIM: rowSpan = %d, colSpan = %d\n", rowSpan, colSpan);
 
   // Grow the mCellMap array if we will end up addressing
   // some new columns.
   if (mCellMap->GetColCount() < (aColIndex + colSpan))
   {
     if (gsDebug==PR_TRUE) 
-      printf("        calling GrowCellMap(%d)\n", aColIndex+colSpan);
+      printf("BCIM: calling GrowCellMap(%d)\n", aColIndex+colSpan);
     GrowCellMap (aColIndex + colSpan);
   }
 
   if (mCellMap->GetRowCount() < (aRowIndex+1))
   {
-    printf("*********************************************** calling GrowToRow(%d)\n", aRowIndex+1);
+    printf("BCIM: calling GrowToRow(%d)\n", aRowIndex+1);
     mCellMap->GrowToRow(aRowIndex+1);
   }
 
@@ -1075,7 +1119,7 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   CellData *data = new CellData ();
   data->mCell = aCell;
   data->mRealCell = data;
-  if (gsDebug==PR_TRUE) printf("        calling mCellMap->SetCellAt(data, %d, %d)\n", aRowIndex, aColIndex);
+  if (gsDebug==PR_TRUE) printf("BCIM: calling mCellMap->SetCellAt(data, %d, %d)\n", aRowIndex, aColIndex);
   mCellMap->SetCellAt(data, aRowIndex, aColIndex);
 
   // Create CellData objects for the rows that this cell spans. Set
@@ -1084,28 +1128,28 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   // CellData object for each row that we span...
   if ((1 < rowSpan) || (1 < colSpan))
   {
-    if (gsDebug==PR_TRUE) printf("        spans\n");
+    if (gsDebug==PR_TRUE) printf("BCIM: spans\n");
     for (int rowIndex = 0; rowIndex < rowSpan; rowIndex++)
     {
-      if (gsDebug==PR_TRUE) printf("          rowIndex = %d\n", rowIndex);
+      if (gsDebug==PR_TRUE) printf("BCIM: rowIndex = %d\n", rowIndex);
       int workRow = aRowIndex + rowIndex;
-      if (gsDebug==PR_TRUE) printf("          workRow = %d\n", workRow);
+      if (gsDebug==PR_TRUE) printf("BCIM: workRow = %d\n", workRow);
       for (int colIndex = 0; colIndex < colSpan; colIndex++)
       {
-        if (gsDebug==PR_TRUE) printf("            colIndex = %d\n", colIndex);
+        if (gsDebug==PR_TRUE) printf("BCIM: colIndex = %d\n", colIndex);
         int workCol = aColIndex + colIndex;
-        if (gsDebug==PR_TRUE) printf("            workCol = %d\n", workCol);
+        if (gsDebug==PR_TRUE) printf("BCIM: workCol = %d\n", workCol);
         CellData *testData = mCellMap->GetCellAt(workRow, workCol);
         if (nsnull == testData)
         {
           CellData *spanData = new CellData ();
           spanData->mRealCell = data;
-          if (gsDebug==PR_TRUE) printf("            null GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
+          if (gsDebug==PR_TRUE) printf("BCIM: null GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
           mCellMap->SetCellAt(spanData, workRow, workCol);
         }
         else if ((0 < rowIndex) || (0 < colIndex))
         { // we overlap, replace existing data, it might be shared
-          if (gsDebug==PR_TRUE) printf("            overlapping Cell from GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
+          if (gsDebug==PR_TRUE) printf("BCIM: overlapping Cell from GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
           CellData *overlap = new CellData ();
           overlap->mCell = testData->mCell;
           overlap->mRealCell = testData->mRealCell;
@@ -1414,12 +1458,15 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
   return NS_OK;
 }
 
-PRBool nsTableFrame::NeedsReflow(const nsSize& aMaxSize)
+PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
 {
   PRBool result = PR_TRUE;
-  if (PR_TRUE==mIsInvariantWidth)
-    result = PR_FALSE;
-  // TODO: other cases...
+  if (eReflowReason_Incremental != aReflowState.reason) 
+  { // incremental reflows always need to be reflowed (for now)
+    if (PR_TRUE==mIsInvariantWidth)
+      result = PR_FALSE;
+    // XXX TODO: other optimization cases...
+  }
   return result;
 }
 
@@ -1509,20 +1556,44 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
     rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
   }
 
-  if (PR_TRUE==NeedsReflow(aReflowState.maxSize))
+  // NeedsReflow and IsFirstPassValid take into account reflow type = Initial_Reflow
+  if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
   {
+    PRBool needsRecalc=PR_FALSE;
+    if (PR_TRUE==gsDebug) printf("TF Reflow: needs reflow\n");
+    if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
+    {
+      if (PR_TRUE==gsDebug) printf("TF Reflow: not initial reflow, so resetting cell map.\n");
+      if (nsnull!=mCellMap)
+        delete mCellMap;
+      mCellMap = new nsCellMap(0,0);
+      ReBuildCellMap();
+      needsRecalc=PR_TRUE;
+    }
     if (PR_FALSE==IsFirstPassValid())
     {
-      // XXX TROY:  we used to rebuild the cellmap here for incremental reflow.
-      //            now that the cellmap is built in the constructor 
-      //            we need to reset the cellmap during incremental reflow before we get here
+      if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TF Reflow: first pass is invalid\n");
       rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus);
       if (NS_FAILED(rv))
         return rv;
+      needsRecalc=PR_TRUE;
+    }
+    if (PR_TRUE==needsRecalc)
+    {
+      if (PR_TRUE==gsDebugIR) printf("TF Reflow: needs recalc.\n");
+      // if we need to recalc, the data stored in the layout strategy is invalid
+      if (nsnull!=mTableLayoutStrategy)
+      {
+        if (PR_TRUE==gsDebugIR) printf("TF Reflow: Re-init layout strategy\n");
+        mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
+      }
+      BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
+      RecalcLayoutData();  // Recalculate Layout Dependencies
     }
 
+
     if (nsnull==mPrevInFlow)
-    {
+    { // only do this for a first-in-flow table frame
       // assign column widths, and assign aMaxElementSize->width
       BalanceColumnWidths(aPresContext, aReflowState, aReflowState.maxSize,
                           aDesiredSize.maxElementSize);
@@ -1656,10 +1727,6 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
     }
   }
 
-  BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
-  // Recalculate Layout Dependencies
-  RecalcLayoutData();
-
   aDesiredSize.width = kidSize.width;
   mFirstPassValid = PR_TRUE;
 
@@ -1756,6 +1823,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext&          aPresContext,
   return rv;
 
 }
+
 NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
                                           nsHTMLReflowMetrics& aDesiredSize,
                                           const nsHTMLReflowState& aReflowState,
@@ -1776,7 +1844,10 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
   rv = aReflowState.reflowCommand->GetTarget(target);
   if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
   {
-    if (this==target)
+    // this is the target if target is either this or the outer table frame containing this inner frame
+    nsIFrame *outerTableFrame=nsnull;
+    GetGeometricParent(outerTableFrame);
+    if ((this==target) || (outerTableFrame==target))
       rv = IR_TargetIsMe(aPresContext, aDesiredSize, state, aStatus);
     else
     {
@@ -1802,14 +1873,12 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
   aReflowState.reflowState.reflowCommand->GetType(type);
   nsIFrame *objectFrame;
   aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
   if (PR_TRUE==gsDebugIR) printf("TIF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
   switch (type)
   {
-  case nsIReflowCommand::FrameAppended :
   case nsIReflowCommand::FrameInserted :
-  {
-    const nsStyleDisplay *childDisplay;
-    objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
     if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
     {
       rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
@@ -1826,7 +1895,22 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
                                    objectFrame, PR_FALSE);
     }
     break;
-  }
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    {
+      rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else if (IsRowGroup(childDisplay->mDisplay))
+    {
+      rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
 
   /*
   case nsIReflowCommand::FrameReplaced :
@@ -1834,9 +1918,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
   */
 
   case nsIReflowCommand::FrameRemoved :
-  {
-    const nsStyleDisplay *childDisplay;
-    objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
     if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
     {
       rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
@@ -1854,7 +1935,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
                               objectFrame);
     }
     break;
-  }
 
   case nsIReflowCommand::StyleChanged :
     NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
@@ -1898,6 +1978,80 @@ NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext&        aPresContext,
   return rv;
 }
 
+NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext&        aPresContext,
+                                            nsHTMLReflowMetrics&   aDesiredSize,
+                                            InnerTableReflowState& aReflowState,
+                                            nsReflowStatus&        aStatus,
+                                            nsIFrame *             aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  /*
+  find where to place colgroup (skipping implicit children?)
+  for every col in the colgroup (including implicit cols due to span attribute)
+    an implicit col from the first implicit colgroup is removed 
+    when an implicit colgroups col count goes to 0, it is removed
+  */
+  /* need to really verify that issynthetic is specified on implicit colgroups and cols */
+
+
+  // build a vector of colgroups.  XXX might want to do this as a class thing, so we don't have to rebuild it each time
+  nsVoidArray colGroupList;
+  nsIFrame *childFrame=mFirstChild;
+  nsIFrame *lastChild=mFirstChild;
+  while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
+  {
+    const nsStyleDisplay *display;
+    childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
+    {
+      colGroupList.AppendElement((void*)childFrame);
+    }
+    lastChild=childFrame;
+    rv = childFrame->GetNextSibling(childFrame);
+  }
+  // append aAppendedFrame
+  if (nsnull!=lastChild)
+    lastChild->SetNextSibling(aAppendedFrame);
+  else
+    mFirstChild = aAppendedFrame;
+
+  /* go through the list of colgroups, sucking out implicit columns that are not the result of a span attribute
+   * and replacing them with columns in aAppendedFrame
+   * if the column had an attribute from a cell, be sure to preserve that
+   * if any implicit colgroup becomes empty, destroy it
+   * if any real colgroup becomes empty, we have to keep it
+   * factor the new cols into the column cache
+   *   this means having a flag that says whether the col cache needs to be rebuilt or not
+   */
+  PRInt32 colGroupCount = colGroupList.Count();
+  if (0FirstChild(childFrame);
+    while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
+    {
+      const nsStyleDisplay *colDisplay;
+      childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)colDisplay);
+      if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+      { // find an implicit column that is not from a span attribute if there is one and remove it
+        for (PRInt32 colGroupIndex=0; colGroupIndexInitialize(aMaxElementSize);
+  mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
+  //XXX: what we want to do here is determine if the new COL information changes anything about layout
+  //     if not, skip invalidating the first passs
+  //     if so, and we can fix the first pass info
+  return rv;
+}
+
+
 NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext&        aPresContext,
                                            nsHTMLReflowMetrics&   aDesiredSize,
                                            InnerTableReflowState& aReflowState,
@@ -1921,6 +2075,39 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext&        aPresContext,
                                             PRBool                 aReplace)
 {
   nsresult rv;
+  // inserting the rowgroup only effects reflow if the rowgroup includes at least one row
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext&        aPresContext,
+                                            nsHTMLReflowMetrics&   aDesiredSize,
+                                            InnerTableReflowState& aReflowState,
+                                            nsReflowStatus&        aStatus,
+                                            nsIFrame *             aAppendedFrame)
+{
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  while (nsnull!=nextChild)
+  {
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  // account for the cells in the rows that are children of aAppendedFrame
+  nsresult rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame);
+
+  // do a pass-1 layout of all the cells in all the rows of the rowgroup
+  InvalidateFirstPassCache();
+
+  // if any column widths have to change due to this, re-init the layout strategy
+  // mTableLayoutStrategy->Initialize(aDesiredSize.aMaxElementSize);  //XXX for now, we're just doing the whole enchelada
+
   return rv;
 }
 
@@ -2032,7 +2219,7 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext&        aPresContext,
                                    aReflowState.reflowState,
                                    aReflowState.reflowState.maxSize);
 
-  ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+  rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
 
   // Resize the row group frame
   nsRect  kidRect;
@@ -2160,8 +2347,6 @@ void nsTableFrame::PlaceChild(nsIPresContext&    aPresContext,
   {
     nsMargin borderPadding;
     const nsStyleSpacing* tableSpacing;
-    // begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
-    nsIFrame * parent = nsnull;
     GetStyleData(eStyleStruct_Spacing , ((nsStyleStruct *&)tableSpacing));
     tableSpacing->CalcBorderPaddingFor(this, borderPadding);
     nscoord cellSpacing = GetCellSpacing();
@@ -2753,95 +2938,95 @@ void nsTableFrame::BuildColumnCache( nsIPresContext&      aPresContext,
                                      nsReflowStatus&      aStatus
                                     )
 {
-  // probably want this assertion : NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
+  NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
   NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
   nsStyleTable* tableStyle;
   GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
   EnsureColumns(aPresContext);
-  if (nsnull==mColCache)
+  if (nsnull!=mColCache)
   {
-    mColCache = new ColumnInfoCache(mColCount);
-    nsIFrame * childFrame = mFirstChild;
-    while (nsnull!=childFrame)
-    { // in this loop, we cache column info and set column style info from cells in first row
-      const nsStyleDisplay *childDisplay;
-      childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (PR_TRUE==gsDebugIR) printf("TIF BCB: clearing column cache and cell map column frame cache.\n");
+    mCellMap->ClearColumnCache();
+    delete mColCache;
+  }
 
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
-      { // if it's a col group then get the columns and cache them in the CellMap
-        nsTableColFrame *colFrame=nsnull;
-        childFrame->FirstChild((nsIFrame *&)colFrame);
-        while (nsnull!=colFrame)
-        { 
-          mCellMap->AppendColumnFrame(colFrame);
-          colFrame->GetNextSibling((nsIFrame *&)colFrame);
-        }
+  mColCache = new ColumnInfoCache(mColCount);
+  nsIFrame * childFrame = mFirstChild;
+  while (nsnull!=childFrame)
+  { // in this loop, we cache column info and set column style info from cells in first row
+    const nsStyleDisplay *childDisplay;
+    childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    { // if it's a col group then get the columns and cache them in the CellMap
+      nsTableColFrame *colFrame=nsnull;
+      childFrame->FirstChild((nsIFrame *&)colFrame);
+      while (nsnull!=colFrame)
+      { 
+        mCellMap->AppendColumnFrame(colFrame);
+        colFrame->GetNextSibling((nsIFrame *&)colFrame);
       }
-      else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-      { // if it's a row group, get the cells and set the column style if appropriate
-        if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
-        {
-          nsIFrame *rowFrame;
-          childFrame->FirstChild(rowFrame);
-          while (nsnull!=rowFrame)
-          {
-            const nsStyleDisplay *rowDisplay;
-            rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay));
-            if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay)
-            {
-              nsIFrame *cellFrame;
-              rowFrame->FirstChild(cellFrame);
-              while (nsnull!=cellFrame)
-              {
-                /* this is the first time we are guaranteed to have both the cell frames
-                 * and the column frames, so it's a good time to 
-                 * set the column style from the cell's width attribute (if this is the first row)
-                 */
-                const nsStyleDisplay *cellDisplay;
-                cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)cellDisplay));
-                if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
-                  SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
-                cellFrame->GetNextSibling(cellFrame);
-              }
-            }
-            rowFrame->GetNextSibling(rowFrame);
-          }
-        }
-      }
-      childFrame->GetNextSibling(childFrame);
     }
-
-    // second time through, set column cache info for each column
-    // we can't do this until the loop above has set the column style info from the cells in the first row
-    childFrame = mFirstChild;
-    while (nsnull!=childFrame)
-    { // for every child, if it's a col group then get the columns
-      const nsStyleDisplay *childDisplay;
-      childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
+    { // if it's a row group, get the cells and set the column style if appropriate
+      if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
       {
-        nsTableColFrame *colFrame=nsnull;
-        childFrame->FirstChild((nsIFrame *&)colFrame);
-        while (nsnull!=colFrame)
-        { // for every column, create an entry in the column cache
-          // assumes that the col style has been twiddled to account for first cell width attribute
-          const nsStyleDisplay *colDisplay;
-          colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
-          if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        nsIFrame *rowFrame;
+        childFrame->FirstChild(rowFrame);
+        while (nsnull!=rowFrame)
+        {
+          const nsStyleDisplay *rowDisplay;
+          rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay));
+          if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay)
           {
-            const nsStylePosition* colPosition;
-            colFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)colPosition));
-            mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
+            nsIFrame *cellFrame;
+            rowFrame->FirstChild(cellFrame);
+            while (nsnull!=cellFrame)
+            {
+              /* this is the first time we are guaranteed to have both the cell frames
+               * and the column frames, so it's a good time to 
+               * set the column style from the cell's width attribute (if this is the first row)
+               */
+              const nsStyleDisplay *cellDisplay;
+              cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)cellDisplay));
+              if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
+                SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
+              cellFrame->GetNextSibling(cellFrame);
+            }
           }
-          colFrame->GetNextSibling((nsIFrame *&)colFrame);
+          rowFrame->GetNextSibling(rowFrame);
         }
       }
-      else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-      { // XXX: assumes content order
-        break;  // once we hit a row group, we're done
-      }
-      childFrame->GetNextSibling(childFrame);
     }
+    childFrame->GetNextSibling(childFrame);
+  }
+
+  // second time through, set column cache info for each column
+  // we can't do this until the loop above has set the column style info from the cells in the first row
+  childFrame = mFirstChild;
+  while (nsnull!=childFrame)
+  { // for every child, if it's a col group then get the columns
+    const nsStyleDisplay *childDisplay;
+    childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    {
+      nsTableColFrame *colFrame=nsnull;
+      childFrame->FirstChild((nsIFrame *&)colFrame);
+      while (nsnull!=colFrame)
+      { // for every column, create an entry in the column cache
+        // assumes that the col style has been twiddled to account for first cell width attribute
+        const nsStyleDisplay *colDisplay;
+        colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        {
+          const nsStylePosition* colPosition;
+          colFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)colPosition));
+          mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
+        }
+        colFrame->GetNextSibling((nsIFrame *&)colFrame);
+      }
+    }
+    childFrame->GetNextSibling(childFrame);
   }
 }
 
@@ -2852,6 +3037,48 @@ PRBool nsTableFrame::IsFirstPassValid() const
   return firstInFlow->mFirstPassValid;
 }
 
+void nsTableFrame::InvalidateFirstPassCache()
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  firstInFlow->mFirstPassValid=PR_FALSE;
+}
+
+PRBool nsTableFrame::IsCellMapValid() const
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  return firstInFlow->mCellMapValid;
+}
+
+void nsTableFrame::InvalidateCellMap()
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  firstInFlow->mCellMapValid=PR_FALSE;
+  // reset the state in each row
+  nsIFrame *rowGroupFrame=mFirstChild;
+  for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      nsIFrame *rowFrame;
+      rowGroupFrame->FirstChild(rowFrame);
+      for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
+      {
+        const nsStyleDisplay *rowDisplay;
+        rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+        if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+        {
+          ((nsTableRowFrame *)rowFrame)->ResetInitChildren();
+        }
+      }
+    }
+  }
+}
+
 NS_METHOD
 nsTableFrame::CreateContinuingFrame(nsIPresContext&  aPresContext,
                                     nsIFrame*        aParent,
@@ -3148,25 +3375,44 @@ NS_NewTableFrame(nsIContent* aContent,
   return NS_OK;
 }
 
-NS_METHOD nsTableFrame::GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aOutFrame)
+NS_METHOD nsTableFrame::GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame)
 {
   nsresult result = NS_OK;
-  aOutFrame = nsnull;   // initialize out-param
+  aTableFrame = nsnull;   // initialize out-param
   if (nsnull!=aSourceFrame)
   {
-    nsresult result = aSourceFrame->GetContentParent((nsIFrame *&)aOutFrame);
-    while ((NS_OK==result) && (nsnull!=aOutFrame))
+    nsresult result = aSourceFrame->GetContentParent((nsIFrame *&)aTableFrame);
+    while ((NS_OK==result) && (nsnull!=aTableFrame))
     {
       const nsStyleDisplay *display;
-      aOutFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
+      aTableFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
       if (NS_STYLE_DISPLAY_TABLE == display->mDisplay)
+      {
+        // at this point, aTableFrame could be an outer frame, 
+        // to find out, scan it's children for another frame with a table display type
+        // if found, the childFrame must be the inner frame
+        nsresult rv;
+        nsIFrame *childFrame=nsnull;
+        rv = aTableFrame->FirstChild(childFrame);
+        while ((NS_OK==rv) && (nsnull!=childFrame))
+        {
+          const nsStyleDisplay *childDisplay;
+          childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)childDisplay);
+          if (NS_STYLE_DISPLAY_TABLE == childDisplay->mDisplay)
+          {
+            aTableFrame = (nsTableFrame *)childFrame;
+            break;
+          }
+          rv = childFrame->GetNextSibling(childFrame);
+        }
         break;
-      result = aOutFrame->GetContentParent((nsIFrame *&)aOutFrame);
+      }
+      result = aTableFrame->GetContentParent((nsIFrame *&)aTableFrame);
     }
   }
   else
     result = NS_ERROR_UNEXPECTED; // bad source param
-  NS_POSTCONDITION(nsnull!=aOutFrame, "unable to find table parent. aOutFrame null.");
+  NS_POSTCONDITION(nsnull!=aTableFrame, "unable to find table parent. aTableFrame null.");
   NS_POSTCONDITION(NS_OK==result, "unable to find table parent. result!=NS_OK");
   return result;
 }
diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h
index db2c20038a2..af7c9a5bb8f 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.h
+++ b/mozilla/layout/html/table/src/nsTableFrame.h
@@ -79,7 +79,7 @@ public:
   PRBool IsNested(const nsHTMLReflowState& aReflowState, nsStylePosition *& aPosition) const;
 
   /** helper method to find the table parent of any table frame object */
-  static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aOutFrame);
+  static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame);
 
   /** helper method for getting the width of the table's containing block */
   static nscoord GetTableContainerWidth(const nsHTMLReflowState& aState);
@@ -97,6 +97,11 @@ public:
 
   NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
 
+  /** complete the append of aRowGroupFrame to the table
+    * this builds the cell map
+    */
+  NS_IMETHOD DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame);
+
   /** @see nsIFrame::Paint */
   NS_IMETHOD Paint(nsIPresContext& aPresContext,
                    nsIRenderingContext& aRenderingContext,
@@ -315,6 +320,12 @@ protected:
                                  nsIFrame *             aInsertedFrame,
                                  PRBool                 aReplace);
 
+    NS_IMETHOD IR_ColGroupAppended(nsIPresContext&        aPresContext,
+                                 nsHTMLReflowMetrics&   aDesiredSize,
+                                 InnerTableReflowState& aReflowState,
+                                 nsReflowStatus&        aStatus,
+                                 nsIFrame *             aAppendedFrame); 
+
   NS_IMETHOD IR_ColGroupRemoved(nsIPresContext&        aPresContext,
                                 nsHTMLReflowMetrics&   aDesiredSize,
                                 InnerTableReflowState& aReflowState,
@@ -328,6 +339,12 @@ protected:
                                  nsIFrame *             aInsertedFrame,
                                  PRBool                 aReplace);
 
+  NS_IMETHOD IR_RowGroupAppended(nsIPresContext&        aPresContext,
+                                 nsHTMLReflowMetrics&   aDesiredSize,
+                                 InnerTableReflowState& aReflowState,
+                                 nsReflowStatus&        aStatus,
+                                 nsIFrame *             aAppendedFrame);
+
   NS_IMETHOD IR_RowGroupRemoved(nsIPresContext&        aPresContext,
                                 nsHTMLReflowMetrics&   aDesiredSize,
                                 InnerTableReflowState& aReflowState,
@@ -414,11 +431,16 @@ protected:
                                         nscoord aMaxHeight);
 
   /** given the new parent size, do I really need to do a reflow? */
-  virtual PRBool NeedsReflow(const nsSize& aMaxSize);
+  virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, 
+                             const nsSize&            aMaxSize);
 
   /** returns PR_TRUE if the cached pass 1 data is still valid */
   virtual PRBool IsFirstPassValid() const;
 
+public:
+  virtual void InvalidateFirstPassCache();
+
+protected:
   /** do post processing to setting up style information for the frame */
   NS_IMETHOD DidSetStyleContext(nsIPresContext& aPresContext);
 
@@ -431,16 +453,24 @@ protected:
     */
   virtual void GrowCellMap(PRInt32 aColCount);
 
+  /** returns PR_TRUE if the cached pass 1 data is still valid */
+  virtual PRBool IsCellMapValid() const;
+
+public:
   /** ResetCellMap is called when the cell structure of the table is changed.
     * Call with caution, only when changing the structure of the table such as 
     * inserting or removing rows, changing the rowspan or colspan attribute of a cell, etc.
     */
-  virtual void ResetCellMap ();
+  virtual void InvalidateCellMap();
+    
+protected:
+  /** iterates all child frames and creates a new cell map */
+  NS_IMETHOD ReBuildCellMap();
 
   /** Get the cell map for this table frame.  It is not always mCellMap.
     * Only the firstInFlow has a legit cell map
     */
-  virtual nsCellMap *GetCellMap();
+  virtual nsCellMap *GetCellMap() const;
 
   /** for debugging only
     * prints out information about the cell map
@@ -559,6 +589,7 @@ private:
   PRInt32      mColumnWidthsLength; // the number of column lengths this frame has allocated
   PRBool       mColumnWidthsSet;    // PR_TRUE if column widths have been set at least once
   PRBool       mFirstPassValid;     // PR_TRUE if first pass data is still legit
+  PRBool       mCellMapValid;       // PR_TRUE if cell map data is still legit
   PRBool       mIsInvariantWidth;   // PR_TRUE if table width cannot change
   PRInt32      mColCount;           // the number of columns in this table
   PRInt32      mEffectiveColCount;  // the number of columns in this table adjusted for weird table attributes
diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
index fa7585144e5..f002487dfdb 100644
--- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
@@ -132,11 +132,11 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext& aPresContext,
   return NS_OK;
 }
 
-PRBool nsTableOuterFrame::NeedsReflow(const nsSize& aMaxSize)
+PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
 {
   PRBool result=PR_TRUE;
   if (nsnull!=mInnerTableFrame)
-    result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aMaxSize);
+    result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState, aMaxSize);
   return result;
 }
 
diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.h b/mozilla/layout/html/table/src/nsTableOuterFrame.h
index 539d6013569..316601f159e 100644
--- a/mozilla/layout/html/table/src/nsTableOuterFrame.h
+++ b/mozilla/layout/html/table/src/nsTableOuterFrame.h
@@ -85,7 +85,7 @@ protected:
     * or if the table style attributes or parent max height/width have
     * changed.
     */
-  PRBool NeedsReflow(const nsSize& aMaxSize);
+  PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize);
 
   void PlaceChild(OuterTableReflowState& aReflowState,
                   nsIFrame*              aKidFrame,
diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
index 22742db37c0..14d07ef3cec 100644
--- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
@@ -39,10 +39,10 @@ NS_DEF_PTR(nsIStyleContext);
 
 #ifdef NS_DEBUG
 static PRBool gsDebug = PR_FALSE;
-//#define NOISY
-//#define NOISY_FLOW
+static PRBool gsDebugIR = PR_FALSE;
 #else
 static const PRBool gsDebug = PR_FALSE;
+static const PRBool gsDebugIR = PR_FALSE;
 #endif
 
 /* ----------- RowReflowState ---------- */
@@ -88,7 +88,8 @@ nsTableRowFrame::nsTableRowFrame(nsIContent* aContent,
     mTallestCell(0),
     mCellMaxTopMargin(0),
     mCellMaxBottomMargin(0),
-    mMinRowSpan(1)
+    mMinRowSpan(1),
+    mInitializedChildren(PR_FALSE)
 {
 }
 
@@ -100,45 +101,62 @@ NS_IMETHODIMP
 nsTableRowFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
   mFirstChild = aChildList;
-  nsTableFrame* table = nsnull;
-  nsresult  result;
+  return NS_OK;
+}
 
-  result = nsTableFrame::GetTableFrame(this, table);
-  if ((NS_OK==result) && (table != nsnull))
+NS_IMETHODIMP
+nsTableRowFrame::InitChildren(PRInt32 aRowIndex)
+{
+  nsTableFrame* table = nsnull;
+  nsresult  result=NS_OK;
+
+  // each child cell can only be added to the table one time.
+  // for now, we remember globally whether we've added all or none
+  if (PR_FALSE==mInitializedChildren)
   {
-    SetRowIndex(table->GetNextAvailRowIndex());
-    PRInt32   colIndex = 0;
-    for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) 
+    result = nsTableFrame::GetTableFrame(this, table);
+    if ((NS_OK==result) && (table != nsnull))
     {
-      const nsStyleDisplay *kidDisplay;
-      kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
+      mInitializedChildren=PR_TRUE;
+      PRInt32 rowIndex;
+      if (-1==aRowIndex)
+        rowIndex = table->GetNextAvailRowIndex();
+      else
+        rowIndex = aRowIndex;
+      SetRowIndex(rowIndex);
+      PRInt32   colIndex = 0;
+      for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) 
       {
-        // what column does this cell belong to?
-        colIndex = table->GetNextAvailColIndex(mRowIndex, colIndex);
-        /* for style context optimization, set the content's column index if possible.
-         * this can only be done if we really have an nsTableCell.  
-         * other tags mapped to table cell display won't benefit from this optimization
-         * see nsHTMLStyleSheet::RulesMatching
-         */
-        nsIContent* cell;
-        kidFrame->GetContent(cell);
-        nsIHTMLTableCellElement *cellContent = nsnull;
-        nsresult rv = cell->QueryInterface(kIHTMLTableCellElementIID, 
-                                           (void **)&cellContent);  // cellContent: REFCNT++
-        NS_RELEASE(cell);
-        if (NS_SUCCEEDED(rv))
-        { // we know it's a table cell
-          cellContent->SetColIndex(colIndex);
-          if (gsDebug) printf("%p : set cell content %p to col index = %d\n", this, cellContent, colIndex);
-          NS_RELEASE(cellContent);
-        }
+        const nsStyleDisplay *kidDisplay;
+        kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
+        {
+          // what column does this cell belong to?
+          colIndex = table->GetNextAvailColIndex(mRowIndex, colIndex);
+          /* for style context optimization, set the content's column index if possible.
+           * this can only be done if we really have an nsTableCell.  
+           * other tags mapped to table cell display won't benefit from this optimization
+           * see nsHTMLStyleSheet::RulesMatching
+           */
+          nsIContent* cell;
+          kidFrame->GetContent(cell);
+          nsIHTMLTableCellElement *cellContent = nsnull;
+          nsresult rv = cell->QueryInterface(kIHTMLTableCellElementIID, 
+                                             (void **)&cellContent);  // cellContent: REFCNT++
+          NS_RELEASE(cell);
+          if (NS_SUCCEEDED(rv))
+          { // we know it's a table cell
+            cellContent->SetColIndex(colIndex);
+            if (gsDebug) printf("%p : set cell content %p to col index = %d\n", this, cellContent, colIndex);
+            NS_RELEASE(cellContent);
+          }
       
-        // this sets the frame's notion of it's column index
-        ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
-        if (gsDebug) printf("%p : set cell frame %p to col index = %d\n", this, kidFrame, colIndex);
-        // add the cell frame to the table's cell map
-        table->AddCellToTable(this, (nsTableCellFrame *)kidFrame, kidFrame == mFirstChild);
+          // this sets the frame's notion of it's column index
+          ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
+          if (gsDebug) printf("%p : set cell frame %p to col index = %d\n", this, kidFrame, colIndex);
+          // add the cell frame to the table's cell map
+          table->AddCellToTable(this, (nsTableCellFrame *)kidFrame, kidFrame == mFirstChild);
+        }
       }
     }
   }
@@ -346,7 +364,7 @@ void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame)
 // aKidRect is relative to the upper-left origin of our frame, and includes
 // any left/top margin.
 void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
-																 RowReflowState&    aState,
+																 RowReflowState&    aReflowState,
 																 nsIFrame*          aKidFrame,
 																 const nsRect&      aKidRect,
 																 nsSize*            aMaxElementSize,
@@ -360,10 +378,10 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
   aKidFrame->SetRect(aKidRect);
 
   // update the running total for the row width
-  aState.x += aKidRect.width;
+  aReflowState.x += aKidRect.width;
 
   // Update the maximum element size
-  PRInt32 rowSpan = aState.tableFrame->GetEffectiveRowSpan(mRowIndex, 
+  PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan(mRowIndex, 
                     ((nsTableCellFrame*)aKidFrame));
   if (nsnull != aMaxElementSize) 
   {
@@ -377,18 +395,18 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
   if (mMinRowSpan == rowSpan)
   {
     // Update maxCellHeight
-    if (aKidRect.height > aState.maxCellHeight)
-      aState.maxCellHeight = aKidRect.height;
+    if (aKidRect.height > aReflowState.maxCellHeight)
+      aReflowState.maxCellHeight = aKidRect.height;
 
     // Update maxCellVertSpace
     nsMargin margin;
 
-    if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK)
+    if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK)
     {
       nscoord height = aKidRect.height + margin.top + margin.bottom;
   
-      if (height > aState.maxCellVertSpace)
-        aState.maxCellVertSpace = height;
+      if (height > aReflowState.maxCellVertSpace)
+        aReflowState.maxCellVertSpace = height;
     }
   }
 }
@@ -398,7 +416,7 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
  * changed. Reflows all the existing table cell frames
  */
 nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
-                                       RowReflowState&  aState,
+                                       RowReflowState&  aReflowState,
                                        nsHTMLReflowMetrics& aDesiredSize)
 {
   if (nsnull == mFirstChild)
@@ -410,7 +428,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
                                      &kidMaxElementSize : nsnull;
   nscoord     maxCellTopMargin = 0;
   nscoord     maxCellBottomMargin = 0;
-  nscoord cellSpacing = aState.tableFrame->GetCellSpacing();
+  nscoord cellSpacing = aReflowState.tableFrame->GetCellSpacing();
   PRInt32 cellColSpan=1;  // must be defined here so it's set properly for non-cell kids
   if (PR_TRUE==gsDebug) printf("%p: RR\n", this);
   // Reflow each of our existing cell frames
@@ -421,7 +439,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
     if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
     {
       nsMargin kidMargin;
-      aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
+      aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
       if (kidMargin.top > maxCellTopMargin)
         maxCellTopMargin = kidMargin.top;
       if (kidMargin.bottom > maxCellBottomMargin)
@@ -434,31 +452,31 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
       { // if this cell is not immediately adjacent to the previous cell, factor in missing col info
         for (PRInt32 colIndex=prevColIndex+1; colIndexGetColumnWidth(colIndex);
-          aState.x += cellSpacing;
+          aReflowState.x += aReflowState.tableFrame->GetColumnWidth(colIndex);
+          aReflowState.x += cellSpacing;
           if (PR_TRUE==gsDebug)
-            printf("  in loop, aState.x set to %d from cellSpacing %d and col width\n", 
-                    aState.x, aState.tableFrame->GetColumnWidth(colIndex), cellSpacing);
+            printf("  in loop, aReflowState.x set to %d from cellSpacing %d and col width\n", 
+                    aReflowState.x, aReflowState.tableFrame->GetColumnWidth(colIndex), cellSpacing);
         }
       }
-      aState.x += cellSpacing;
-      if (PR_TRUE==gsDebug) printf("  past loop, aState.x set to %d\n", aState.x);
+      aReflowState.x += cellSpacing;
+      if (PR_TRUE==gsDebug) printf("  past loop, aReflowState.x set to %d\n", aReflowState.x);
 
       // at this point, we know the column widths.  
       // so we get the avail width from the known column widths
-      cellColSpan = aState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
+      cellColSpan = aReflowState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
                                                                    ((nsTableCellFrame *)kidFrame));
       nscoord availWidth = 0;
       for (PRInt32 numColSpan=0; numColSpanGetColumnWidth(cellColIndex+numColSpan);
+        availWidth += aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
         if (numColSpan != 0)
         {
           availWidth += cellSpacing;
         }
         if (PR_TRUE==gsDebug) 
           printf("  in loop, availWidth set to %d from colIndex %d width %d and cellSpacing\n", 
-                  availWidth, cellColIndex, aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan), cellSpacing);
+                  availWidth, cellColIndex, aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan), cellSpacing);
       }
       if (PR_TRUE==gsDebug) printf("  availWidth for this cell is %d\n", availWidth);
 
@@ -478,7 +496,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
 
         // Reflow the child
         nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
-                                         aState.reflowState, kidAvailSize,
+                                         aReflowState.reflowState, kidAvailSize,
                                          eReflowReason_Resize);
         if (gsDebug) printf ("%p RR: avail=%d\n", this, availWidth);
         nsReflowStatus status;
@@ -545,12 +563,12 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
       // end special Nav4 compatibility code
 
       // Place the child
-      nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
+      nsRect kidRect (aReflowState.x, kidMargin.top, cellWidth, cellHeight);
 
-      PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
+      PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
                  pKidMaxElementSize);
 
-      if (PR_TRUE==gsDebug) printf("  past PlaceChild, aState.x set to %d\n", aState.x);
+      if (PR_TRUE==gsDebug) printf("  past PlaceChild, aReflowState.x set to %d\n", aReflowState.x);
     }
 
     // Get the next child
@@ -558,27 +576,27 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
     // if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan
     // if the last kid wasn't a colspan, then we still have the colspan of the last real cell
     if ((nsnull==kidFrame) && (cellColSpan>1))
-      aState.x += cellSpacing;
+      aReflowState.x += cellSpacing;
   }
 
-  SetMaxChildHeight(aState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin);  // remember height of tallest child who doesn't have a row span
+  SetMaxChildHeight(aReflowState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin);  // remember height of tallest child who doesn't have a row span
 
   // Return our desired size. Note that our desired width is just whatever width
   // we were given by the row group frame
-  aDesiredSize.width = aState.x;
-  aDesiredSize.height = aState.maxCellVertSpace;  
+  aDesiredSize.width = aReflowState.x;
+  aDesiredSize.height = aReflowState.maxCellVertSpace;  
 
   if (gsDebug)
     printf("rr -- row %p width = %d from maxSize %d\n", 
-           this, aDesiredSize.width, aState.reflowState.maxSize.width);
+           this, aDesiredSize.width, aReflowState.reflowState.maxSize.width);
   
-  if (aDesiredSize.width > aState.reflowState.maxSize.width) 
+  if (aDesiredSize.width > aReflowState.reflowState.maxSize.width) 
   {
     printf ("%p error case, desired width = %d, maxSize=%d\n",
-            this, aDesiredSize.width, aState.reflowState.maxSize.width);
+            this, aDesiredSize.width, aReflowState.reflowState.maxSize.width);
     fflush (stdout);
   }
-  NS_ASSERTION(aDesiredSize.width <= aState.reflowState.maxSize.width, "row calculated to be too wide.");
+  NS_ASSERTION(aDesiredSize.width <= aReflowState.reflowState.maxSize.width, "row calculated to be too wide.");
   return NS_OK;
 }
 
@@ -588,7 +606,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
  */
 nsresult
 nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
-                               RowReflowState&  aState,
+                               RowReflowState&  aReflowState,
                                nsHTMLReflowMetrics& aDesiredSize)
 {
   // Place our children, one at a time, until we are out of children
@@ -622,7 +640,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       nsMargin  margin;
       nscoord   topMargin = 0;
 
-      if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
+      if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
       {
         topMargin = margin.top;
       }
@@ -647,7 +665,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       }
 
       nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
-                                       aState.reflowState, kidAvailSize,
+                                       aReflowState.reflowState, kidAvailSize,
                                        eReflowReason_Initial);
 
       if (gsDebug) printf ("%p InitR: avail=%d\n", this, kidAvailSize.width);
@@ -677,17 +695,17 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       // Place the child
       x += margin.left;
       nsRect kidRect(x, topMargin, kidSize.width, kidSize.height);
-      PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
+      PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
                  &kidMaxElementSize);
       x += kidSize.width + margin.right;
     }
   }
 
-  SetMaxChildHeight(aState.maxCellHeight, maxTopMargin, maxBottomMargin);  // remember height of tallest child who doesn't have a row span
+  SetMaxChildHeight(aReflowState.maxCellHeight, maxTopMargin, maxBottomMargin);  // remember height of tallest child who doesn't have a row span
 
   // Return our desired size
   aDesiredSize.width = x;
-  aDesiredSize.height = aState.maxCellVertSpace;   
+  aDesiredSize.height = aReflowState.maxCellVertSpace;   
 
   return result;
 }
@@ -700,7 +718,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
 // - maxVertCellSpace
 // - x
 nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
-                                       RowReflowState& aState,
+                                       RowReflowState& aReflowState,
                                        nsIFrame*       aKidFrame,
                                        nscoord&        aMaxCellTopMargin,
                                        nscoord&        aMaxCellBottomMargin)
@@ -710,8 +728,8 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
   // Walk the list of children looking for aKidFrame. While we're at
   // it get the maxCellHeight and maxVertCellSpace for all the
   // frames except aKidFrame
-//  nsIFrame* prevKidFrame = nsnull;
-  for (nsIFrame* frame = mFirstChild; nsnull != frame;) {
+  for (nsIFrame* frame = mFirstChild; nsnull != frame;) 
+  {
     const nsStyleDisplay *kidDisplay;
     frame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
     if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
@@ -719,13 +737,13 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
       if (frame != aKidFrame) {
         // Update the max top and bottom margins
         nsMargin       kidMargin;
-        aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, kidMargin);
+        aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, kidMargin);
         if (kidMargin.top > aMaxCellTopMargin)
           aMaxCellTopMargin = kidMargin.top;
         if (kidMargin.bottom > aMaxCellBottomMargin)
           aMaxCellBottomMargin = kidMargin.bottom;
 
-        PRInt32 rowSpan = aState.tableFrame->GetEffectiveRowSpan(mRowIndex, ((nsTableCellFrame *)frame));
+        PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan(mRowIndex, ((nsTableCellFrame *)frame));
         if (mMinRowSpan == rowSpan) {
           // Get the cell's desired height the last time it was reflowed
           nsSize  desiredSize = ((nsTableCellFrame *)frame)->GetDesiredSize();
@@ -751,18 +769,18 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
             desiredSize.height = specifiedHeight;
         
           // Update maxCellHeight
-          if (desiredSize.height > aState.maxCellHeight) {
-            aState.maxCellHeight = desiredSize.height;
+          if (desiredSize.height > aReflowState.maxCellHeight) {
+            aReflowState.maxCellHeight = desiredSize.height;
           }
   
           // Update maxCellVertHeight
           nsMargin margin;
     
-          if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
+          if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
           {
             nscoord height = desiredSize.height + margin.top + margin.bottom;
-            if (height > aState.maxCellVertSpace) {
-              aState.maxCellVertSpace = height;
+            if (height > aReflowState.maxCellVertSpace) {
+              aReflowState.maxCellVertSpace = height;
             }
           }
         }
@@ -775,162 +793,417 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
       }
     }
 
-    // Remember the frame that precedes aKidFrame
-//    prevKidFrame = frame;
     frame->GetNextSibling(frame);
   }
 
   // Update the running x-offset based on the frame's current x-origin
   nsPoint origin;
   aKidFrame->GetOrigin(origin);
-  aState.x = origin.x;
+  aReflowState.x = origin.x;
 
   return NS_OK;
 }
 
-nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext&  aPresContext,
-                                            RowReflowState&  aState,
-                                            nsHTMLReflowMetrics& aDesiredSize)
+
+
+NS_METHOD nsTableRowFrame::IncrementalReflow(nsIPresContext&       aPresContext,
+                                             nsHTMLReflowMetrics&  aDesiredSize,
+                                             RowReflowState& aReflowState,
+                                             nsReflowStatus&       aStatus)
 {
-  nsresult  status;
+  if (PR_TRUE==gsDebugIR) printf("\nTRF IR: IncrementalReflow\n");
+  nsresult  rv = NS_OK;
 
-  // XXX Deal with the case where the reflow command is targeted at us
-  nsIFrame* target;
-  aState.reflowState.reflowCommand->GetTarget(target);
-  if (this == target) {
-    NS_NOTYETIMPLEMENTED("unexpected reflow command");
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  // Get the next frame in the reflow chain
-  nsIFrame* kidFrame;
-  aState.reflowState.reflowCommand->GetNext(kidFrame);
-
-  // Recover our reflow state
-  nscoord maxCellTopMargin, maxCellBottomMargin;
-  RecoverState(aPresContext, aState, kidFrame, maxCellTopMargin, maxCellBottomMargin);
-
-  // Get the frame's margins
-  nsMargin  kidMargin;
-  aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, kidMargin);
-  if (kidMargin.top > maxCellTopMargin)
-    maxCellTopMargin = kidMargin.top;
-  if (kidMargin.bottom > maxCellBottomMargin)
-    maxCellBottomMargin = kidMargin.bottom;
-
-  // At this point, we know the column widths. Get the available width
-  // from the known column widths
-  PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
-  PRInt32 cellColSpan = aState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
-                                                                 ((nsTableCellFrame *)kidFrame));
-  nscoord availWidth = 0;
-  for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
+  // determine if this frame is the target or not
+  nsIFrame *target=nsnull;
+  rv = aReflowState.reflowState.reflowCommand->GetTarget(target);
+  if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
   {
-    availWidth += aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
-    if (0GetNext(nextFrame);
+      rv = IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, nextFrame);
     }
   }
-
-  // Always let the cell be as high as it wants. We ignore the height that's
-  // passed in and always place the entire row. Let the row group decide
-  // whether we fit or wehther the entire row is pushed
-  nsSize  kidAvailSize(availWidth, NS_UNCONSTRAINEDSIZE);
-
-  // Pass along the reflow command
-  nsSize          kidMaxElementSize;
-  nsHTMLReflowMetrics desiredSize(&kidMaxElementSize);
-  nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aState.reflowState,
-                                   kidAvailSize);
-
-  // XXX Unfortunately we need to reflow the child several times.
-  // The first time is for the incremental reflow command. We can't pass in
-  // a max width of NS_UNCONSTRAINEDSIZE, because the max width must match
-  // the width of the previous reflow...
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-
-  // Now do the regular pass 1 reflow and gather the max width and max element
-  // size.
-  // XXX It would be nice if we could skip this step and the next step if the
-  // column width isn't dependent on the max cell width...
-  kidReflowState.reason = eReflowReason_Resize;
-  kidReflowState.reflowCommand = nsnull;
-  kidReflowState.maxSize.width = NS_UNCONSTRAINEDSIZE;
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-  if (gsDebug) 
-      printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n", 
-             this, kidFrame, desiredSize.width, kidMaxElementSize.width);
-  // Update the cell layout data.
-  //XXX: this is a hack, shouldn't it be the case that a min size is 
-  //     never larger than a desired size?
-  if (kidMaxElementSize.width>desiredSize.width)
-    desiredSize.width = kidMaxElementSize.width;
-  if (kidMaxElementSize.height>desiredSize.height)
-    desiredSize.height = kidMaxElementSize.height;
-  ((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(desiredSize);
-  ((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
-  
-  // Now reflow the cell again this time constraining the width
-  // XXX Ignore for now the possibility that the column width has changed...
-  kidReflowState.maxSize.width = availWidth;
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-  
-  // Place the child after taking into account it's margin and attributes
-  // XXX We need to ask the table (or the table layout strategy) if the column
-  // widths have changed. If so, we just bail and return a status indicating
-  // what happened and let the table reflow all the table cells...
-  nscoord specifiedHeight = 0;
-  nscoord cellHeight = desiredSize.height;
-  nsIStyleContextPtr kidSC;
-  kidFrame->GetStyleContext(&aPresContext, kidSC.AssignRef());
-  const nsStylePosition* kidPosition = (const nsStylePosition*)
-    kidSC->GetStyleData(eStyleStruct_Position);
-  switch (kidPosition->mHeight.GetUnit()) {
-  case eStyleUnit_Coord:
-    specifiedHeight = kidPosition->mHeight.GetCoordValue();
-    break;
-
-  case eStyleUnit_Inherit:
-    // XXX for now, do nothing
-  default:
-  case eStyleUnit_Auto:
-    break;
-  }
-  if (specifiedHeight>cellHeight)
-    cellHeight = specifiedHeight;
-
-  nscoord cellWidth = desiredSize.width;
-  // begin special Nav4 compatibility code
-  if (0==cellWidth)
-  {
-    cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
-  }
-  // end special Nav4 compatibility code
-
-  // Now place the child
-  nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
-
-  PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
-             &kidMaxElementSize);
-
-  SetMaxChildHeight(aState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
-
-  // Return our desired size. Note that our desired width is just whatever width
-  // we were given by the row group frame
-  aDesiredSize.width = aState.availSize.width;
-  aDesiredSize.height = aState.maxCellVertSpace;   
-
-  if (gsDebug)
-    printf("incr -- row %p width = %d MES=%d from maxSize %d\n", 
-           this, aDesiredSize.width, aDesiredSize.maxElementSize->width,
-           aState.reflowState.maxSize.width);
-
-  return status;
+  return rv;
 }
 
+NS_METHOD nsTableRowFrame::IR_TargetIsMe(nsIPresContext&      aPresContext,
+                                         nsHTMLReflowMetrics& aDesiredSize,
+                                         RowReflowState&      aReflowState,
+                                         nsReflowStatus&      aStatus)
+{
+  nsresult rv = NS_FRAME_COMPLETE;
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  nsIFrame *objectFrame;
+  aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (PR_TRUE==gsDebugIR) printf("TRF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
+  switch (type)
+  {
+  case nsIReflowCommand::FrameInserted :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                           objectFrame, PR_FALSE);
+    }
+    else
+    {
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+
+  /*
+  case nsIReflowCommand::FrameReplaced :
+
+  */
+
+  case nsIReflowCommand::FrameRemoved :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                          objectFrame);
+    }
+    else
+    {
+      rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                  objectFrame);
+    }
+    break;
+
+  case nsIReflowCommand::StyleChanged :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: StyleChanged not implemented.\n");
+    break;
+
+  case nsIReflowCommand::ContentChanged :
+    NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
+    rv = NS_ERROR_ILLEGAL_VALUE;
+    break;
+  
+  case nsIReflowCommand::PullupReflow:
+  case nsIReflowCommand::PushReflow:
+  case nsIReflowCommand::CheckPullupReflow :
+  case nsIReflowCommand::UserDefined :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: reflow command not implemented.\n");
+    break;
+  }
+
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_CellInserted(nsIPresContext&      aPresContext,
+                                           nsHTMLReflowMetrics& aDesiredSize,
+                                           RowReflowState&      aReflowState,
+                                           nsReflowStatus&      aStatus,
+                                           nsIFrame *           aInsertedFrame,
+                                           PRBool               aReplace)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_DidAppendCell(nsTableRowFrame *aRowFrame)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableRowFrame::IR_CellAppended(nsIPresContext&      aPresContext,
+                                           nsHTMLReflowMetrics& aDesiredSize,
+                                           RowReflowState&      aReflowState,
+                                           nsReflowStatus&      aStatus,
+                                           nsIFrame *           aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  nsIFrame *lastRow = nsnull;
+  while (nsnull!=nextChild)
+  {
+    // remember the last child that is really a cell
+    const nsStyleDisplay *childDisplay;
+    nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+      lastRow = nextChild;
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  aReflowState.tableFrame->InvalidateFirstPassCache();
+  // the table will see that it's cached info is bogus and rebuild the cell map,
+  // and do a reflow
+
+#if 0
+  // find the col index of the new cell
+  
+  // account for the new cell 
+  nsresult rv = DidAppendCell((nsTableCellFrame*)aAppendedFrame);
+
+  // need to increment the row index of all subsequent rows
+#endif 
+
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_CellRemoved(nsIPresContext&      aPresContext,
+                                          nsHTMLReflowMetrics& aDesiredSize,
+                                          RowReflowState&      aReflowState,
+                                          nsReflowStatus&      aStatus,
+                                          nsIFrame *           aDeletedFrame)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+//XXX: handle aReplace
+NS_METHOD nsTableRowFrame::IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                                   nsHTMLReflowMetrics& aDesiredSize,
+                                                   RowReflowState& aReflowState,
+                                                   nsReflowStatus&      aStatus,
+                                                   nsIFrame *           aInsertedFrame,
+                                                   PRBool               aReplace)
+{
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  // we have a generic frame that gets inserted but doesn't effect reflow
+  // hook it up then ignore it
+  if (nsIReflowCommand::FrameAppended==type)
+  { // frameAppended reflow -- find the last child and make aInsertedFrame its next sibling
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameAppended adding unknown frame type.\n");
+    nsIFrame *lastChild=mFirstChild;
+    nsIFrame *nextChild=mFirstChild;
+    while (nsnull!=nextChild)
+    {
+      lastChild=nextChild;
+      nextChild->GetNextSibling(nextChild);
+    }
+    if (nsnull==lastChild)
+      mFirstChild = aInsertedFrame;
+    else
+      lastChild->SetNextSibling(aInsertedFrame);
+  }
+  else
+  { // frameInserted reflow -- hook up aInsertedFrame as prevSibling's next sibling, 
+    // and be sure to hook in aInsertedFrame's nextSibling (from prevSibling)
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameInserted adding unknown frame type.\n");
+    nsIFrame *prevSibling=nsnull;
+    nsresult rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
+    if (NS_SUCCEEDED(rv) && (nsnull!=prevSibling))
+    {
+      nsIFrame *nextSibling=nsnull;
+      prevSibling->GetNextSibling(nextSibling);
+      prevSibling->SetNextSibling(aInsertedFrame);
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+    else
+    {
+      nsIFrame *nextSibling=nsnull;
+      if (nsnull!=mFirstChild)
+        mFirstChild->GetNextSibling(nextSibling);
+      mFirstChild = aInsertedFrame;
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+  }
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowFrame::IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                                  nsHTMLReflowMetrics& aDesiredSize,
+                                                  RowReflowState&      aReflowState,
+                                                  nsReflowStatus&      aStatus,
+                                                  nsIFrame *           aRemovedFrame)
+{
+  // we have a generic frame that gets removed but doesn't effect reflow
+  // unhook it then ignore it
+  if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameRemoved removing unknown frame type.\n");
+  nsIFrame *prevChild=nsnull;
+  nsIFrame *nextChild=mFirstChild;
+  while (nextChild!=aRemovedFrame)
+  {
+    prevChild=nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }  
+  nextChild=nsnull;
+  aRemovedFrame->GetNextSibling(nextChild);
+  if (nsnull==prevChild)  // objectFrame was first child
+    mFirstChild = nextChild;
+  else
+    prevChild->SetNextSibling(nextChild);
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext&      aPresContext,
+                                            nsHTMLReflowMetrics& aDesiredSize,
+                                            RowReflowState&      aReflowState,
+                                            nsReflowStatus&      aStatus,
+                                            nsIFrame *           aNextFrame)
+
+{
+  nsresult  rv;
+
+  const nsStyleDisplay *childDisplay;
+  aNextFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+  {
+    // Recover our reflow state
+    nscoord maxCellTopMargin, maxCellBottomMargin;
+    RecoverState(aPresContext, aReflowState, aNextFrame, maxCellTopMargin, maxCellBottomMargin);
+
+    // Get the frame's margins
+    nsMargin  kidMargin;
+    aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aNextFrame, kidMargin);
+    if (kidMargin.top > maxCellTopMargin)
+      maxCellTopMargin = kidMargin.top;
+    if (kidMargin.bottom > maxCellBottomMargin)
+      maxCellBottomMargin = kidMargin.bottom;
+
+    // At this point, we know the column widths. Get the available width
+    // from the known column widths
+    PRInt32 cellColIndex = ((nsTableCellFrame *)aNextFrame)->GetColIndex();
+    PRInt32 cellColSpan = aReflowState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)aNextFrame)->GetColIndex(),
+                                                                   ((nsTableCellFrame *)aNextFrame));
+    nscoord availWidth = 0;
+    for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
+    {
+      availWidth += aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
+      if (0desiredSize.width)
+      desiredSize.width = kidMaxElementSize.width;
+    if (kidMaxElementSize.height>desiredSize.height)
+      desiredSize.height = kidMaxElementSize.height;
+    ((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
+    ((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
+  
+    // Now reflow the cell again this time constraining the width
+    // XXX Ignore for now the possibility that the column width has changed...
+    kidReflowState.maxSize.width = availWidth;
+    rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+  
+    // Place the child after taking into account it's margin and attributes
+    // XXX We need to ask the table (or the table layout strategy) if the column
+    // widths have changed. If so, we just bail and return a status indicating
+    // what happened and let the table reflow all the table cells...
+    nscoord specifiedHeight = 0;
+    nscoord cellHeight = desiredSize.height;
+    nsIStyleContextPtr kidSC;
+    aNextFrame->GetStyleContext(&aPresContext, kidSC.AssignRef());
+    const nsStylePosition* kidPosition = (const nsStylePosition*)
+      kidSC->GetStyleData(eStyleStruct_Position);
+    switch (kidPosition->mHeight.GetUnit()) {
+    case eStyleUnit_Coord:
+      specifiedHeight = kidPosition->mHeight.GetCoordValue();
+      break;
+
+    case eStyleUnit_Inherit:
+      // XXX for now, do nothing
+    default:
+    case eStyleUnit_Auto:
+      break;
+    }
+    if (specifiedHeight>cellHeight)
+      cellHeight = specifiedHeight;
+
+    nscoord cellWidth = desiredSize.width;
+    // begin special Nav4 compatibility code
+    if (0==cellWidth)
+    {
+      cellWidth = aReflowState.tableFrame->GetColumnWidth(cellColIndex);
+    }
+    // end special Nav4 compatibility code
+
+    // Now place the child
+    nsRect kidRect (aReflowState.x, kidMargin.top, cellWidth, cellHeight);
+
+    PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, aDesiredSize.maxElementSize,
+               &kidMaxElementSize);
+
+    SetMaxChildHeight(aReflowState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
+
+    // Return our desired size. Note that our desired width is just whatever width
+    // we were given by the row group frame
+    aDesiredSize.width = aReflowState.availSize.width;
+    aDesiredSize.height = aReflowState.maxCellVertSpace;   
+
+    if (gsDebug)
+      printf("incr -- row %p width = %d MES=%d from maxSize %d\n", 
+             this, aDesiredSize.width, aDesiredSize.maxElementSize->width,
+             aReflowState.reflowState.maxSize.width);
+  }
+  else
+  { // pass reflow to unknown frame child
+    // aDesiredSize does not change
+  }
+  return rv;
+}
+
+
 /** Layout the entire row.
   * This method stacks cells horizontally according to HTML 4.0 rules.
   */
@@ -940,45 +1213,46 @@ nsTableRowFrame::Reflow(nsIPresContext&          aPresContext,
                         const nsHTMLReflowState& aReflowState,
                         nsReflowStatus&          aStatus)
 {
+  nsresult rv=NS_OK;
   if (gsDebug==PR_TRUE)
     printf("nsTableRowFrame::Reflow - aMaxSize = %d, %d\n",
             aReflowState.maxSize.width, aReflowState.maxSize.height);
 
-  // Initialize 'out' parameters
+  // Initialize 'out' parameters (aStatus set below, undefined if rv returns an error)
   if (nsnull != aDesiredSize.maxElementSize) {
     aDesiredSize.maxElementSize->width = 0;
     aDesiredSize.maxElementSize->height = 0;
   }
-  aStatus = NS_FRAME_COMPLETE;  // we're never continued
 
   // Initialize our internal data
   ResetMaxChildHeight();
 
-  // Initialize our automatic state object
-  nsTableFrame* tableFrame;
-  mContentParent->GetContentParent((nsIFrame*&)tableFrame);
+  // Create a reflow state
+  nsTableFrame *tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if (NS_FAILED(rv) || nsnull==tableFrame)
+    return rv;
   RowReflowState state(aReflowState, tableFrame);
 
   // Do the reflow
-  nsresult  result;
-
   switch (aReflowState.reason) {
   case eReflowReason_Initial:
-    result = InitialReflow(aPresContext, state, aDesiredSize);
+    rv = InitialReflow(aPresContext, state, aDesiredSize);
     GetMinRowSpan(tableFrame);
     FixMinCellHeight(tableFrame);
     break;
 
   case eReflowReason_Resize:
-    result = ResizeReflow(aPresContext, state, aDesiredSize);
+    rv = ResizeReflow(aPresContext, state, aDesiredSize);
     break;
 
   case eReflowReason_Incremental:
-    result = IncrementalReflow(aPresContext, state, aDesiredSize);
+    rv = IncrementalReflow(aPresContext, aDesiredSize, state, aStatus);
     break;
-
   }
 
+  aStatus = NS_FRAME_COMPLETE;  // we're never continued
+
   if (gsDebug==PR_TRUE) 
   {
     if (nsnull!=aDesiredSize.maxElementSize)
@@ -992,7 +1266,7 @@ nsTableRowFrame::Reflow(nsIPresContext&          aPresContext,
              aDesiredSize.width, aDesiredSize.height);
   }
 
-  return result;
+  return rv;
 }
 
 NS_METHOD
diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.h b/mozilla/layout/html/table/src/nsTableRowFrame.h
index 43e6d0cd3f8..51d6d09debc 100644
--- a/mozilla/layout/html/table/src/nsTableRowFrame.h
+++ b/mozilla/layout/html/table/src/nsTableRowFrame.h
@@ -38,8 +38,13 @@ struct RowReflowState;
 class nsTableRowFrame : public nsContainerFrame
 {
 public:
-  /** Initialization procedure */
-  void Init(PRInt32 aRowIndex);
+  /** Initialization of frame as a row */
+  void InitRowData(PRInt32 aRowIndex);
+
+  /** Initialization of data */
+  NS_IMETHOD InitChildren(PRInt32 aRowIndex=-1);
+
+  void ResetInitChildren();
 
   /** instantiate a new instance of nsTableRowFrame.
     * @param aResult    the new object is returned in this out-param
@@ -126,6 +131,64 @@ protected:
   /** destructor */
   virtual ~nsTableRowFrame();
 
+  /** Incremental Reflow attempts to do column balancing with the minimum number of reflow
+    * commands to child elements.  This is done by processing the reflow command,
+    * rebalancing column widths (if necessary), then comparing the resulting column widths
+    * to the prior column widths and reflowing only those cells that require a reflow.
+    *
+    * @see Reflow
+    */
+  NS_IMETHOD IncrementalReflow(nsIPresContext&       aPresContext,
+                               nsHTMLReflowMetrics&  aDesiredSize,
+                               RowReflowState&       aReflowState,
+                               nsReflowStatus&       aStatus);
+
+  NS_IMETHOD IR_TargetIsChild(nsIPresContext&      aPresContext,
+                              nsHTMLReflowMetrics& aDesiredSize,
+                              RowReflowState&      aReflowState,
+                              nsReflowStatus&      aStatus,
+                              nsIFrame *           aNextFrame);
+
+  NS_IMETHOD IR_TargetIsMe(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowReflowState&      aReflowState,
+                           nsReflowStatus&      aStatus);
+
+  NS_IMETHOD IR_CellInserted(nsIPresContext&     aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowReflowState&      aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aInsertedFrame,
+                            PRBool               aReplace);
+
+  NS_IMETHOD IR_CellAppended(nsIPresContext&     aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowReflowState&      aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aAppendedFrame);
+
+  NS_IMETHOD IR_DidAppendCell(nsTableRowFrame *aRowFrame);
+
+  NS_IMETHOD IR_CellRemoved(nsIPresContext&     aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowReflowState&      aReflowState,
+                           nsReflowStatus&      aStatus,
+                           nsIFrame *           aDeletedFrame);
+  
+  NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                     nsHTMLReflowMetrics& aDesiredSize,
+                                     RowReflowState&      aReflowState,
+                                     nsReflowStatus&      aStatus,
+                                     nsIFrame *           aInsertedFrame,
+                                     PRBool               aReplace);
+
+  NS_IMETHOD IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                    nsHTMLReflowMetrics& aDesiredSize,
+                                    RowReflowState&      aReflowState,
+                                    nsReflowStatus&      aStatus,
+                                    nsIFrame *           aDeletedFrame);
+
+
   // row-specific methods
 
   void GetMinRowSpan(nsTableFrame *aTableFrame);
@@ -180,11 +243,14 @@ private:
   nscoord  mCellMaxTopMargin;
   nscoord  mCellMaxBottomMargin;
   PRInt32  mMinRowSpan;           // the smallest row span among all my child cells
+  PRBool   mInitializedChildren;  // PR_TRUE if child cells have been initialized 
+                                  // (for now, that means "added to the table", and
+                                  // is NOT the same as having nsIFrame::Init() called.)
 
 };
 
 
-inline void nsTableRowFrame::Init(PRInt32 aRowIndex)
+inline void nsTableRowFrame::InitRowData(PRInt32 aRowIndex)
 {
   NS_ASSERTION(0<=aRowIndex, "bad param row index");
   mRowIndex = aRowIndex;
@@ -196,4 +262,7 @@ inline PRInt32 nsTableRowFrame::GetRowIndex() const
   return (mRowIndex);
 }
 
+inline void nsTableRowFrame::ResetInitChildren()
+{ mInitializedChildren=PR_FALSE; } 
+
 #endif
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
index b485bfec9c6..09df6333da1 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
@@ -30,10 +30,10 @@
 
 #ifdef NS_DEBUG
 static PRBool gsDebug = PR_FALSE;
-//#define NOISY
-//#define NOISY_FLOW
+static PRBool gsDebugIR = PR_FALSE;
 #else
 static const PRBool gsDebug = PR_FALSE;
+static const PRBool gsDebugIR = PR_FALSE;
 #endif
 
 NS_DEF_PTR(nsIStyleContext);
@@ -42,8 +42,8 @@ NS_DEF_PTR(nsIContent);
 /* ----------- RowGroupReflowState ---------- */
 
 struct RowGroupReflowState {
-  // Our reflow state
-  const nsHTMLReflowState& reflowState;
+  nsIPresContext& mPresContext;  // Our pres context
+  const nsHTMLReflowState& reflowState;  // Our reflow state
 
   // The body's available size (computed from the body's parent)
   nsSize availSize;
@@ -65,9 +65,10 @@ struct RowGroupReflowState {
   // Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
   nscoord firstRowHeight;
 
-  RowGroupReflowState(nsIPresContext*          aPresContext,
+  RowGroupReflowState(nsIPresContext&          aPresContext,
                       const nsHTMLReflowState& aReflowState)
-    : reflowState(aReflowState)
+    : mPresContext(aPresContext),
+      reflowState(aReflowState)
   {
     availSize.width = reflowState.maxSize.width;
     availSize.height = reflowState.maxSize.height;
@@ -686,7 +687,7 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
   delete []rowHeights;
 }
 
-nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext*      aPresContext,
+nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext&      aPresContext,
                                                          RowGroupReflowState& aState,
                                                          nsIFrame*            aKidFrame,
                                                          nscoord              aDeltaY)
@@ -708,7 +709,7 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext*      aP
       // XXX We need to send move notifications to the frame...
       nsIHTMLReflow* htmlReflow;
       if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
-        htmlReflow->WillReflow(*aPresContext);
+        htmlReflow->WillReflow(aPresContext);
       }
       kidFrame->MoveTo(origin.x, origin.y);
 
@@ -742,6 +743,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
                              const nsHTMLReflowState& aReflowState,
                              nsReflowStatus&          aStatus)
 {
+  nsresult rv=NS_OK;
   if (gsDebug==PR_TRUE)
     printf("nsTableRowGroupFrame::Reflow - aMaxSize = %d, %d\n",
             aReflowState.maxSize.width, aReflowState.maxSize.height);
@@ -752,45 +754,10 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
     aDesiredSize.maxElementSize->height = 0;
   }
 
-  RowGroupReflowState state(&aPresContext, aReflowState);
+  RowGroupReflowState state(aPresContext, aReflowState);
 
   if (eReflowReason_Incremental == aReflowState.reason) {
-    nsIFrame* target;
-    aReflowState.reflowCommand->GetTarget(target);
-    if (this == target) {
-      NS_NOTYETIMPLEMENTED("unexpected reflow command");
-    }
-
-    // XXX Recover state
-    // XXX Deal with the case where the reflow command is targeted at us
-    nsIFrame* kidFrame;
-    aReflowState.reflowCommand->GetNext(kidFrame);
-
-    // Remember the old rect
-    nsRect  oldKidRect;
-    kidFrame->GetRect(oldKidRect);
-
-    // Pass along the reflow command
-    // XXX Correctly compute the available space...
-    nsHTMLReflowState   kidReflowState(aPresContext, kidFrame,
-                                       aReflowState, aReflowState.maxSize);
-    nsHTMLReflowMetrics desiredSize(nsnull);
-
-    ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
-
-    // Resize the row frame
-    nsRect  kidRect;
-    kidFrame->GetRect(kidRect);
-    kidFrame->SizeTo(desiredSize.width, desiredSize.height);
-
-    // Adjust the frames that follow...
-    AdjustSiblingsAfterReflow(&aPresContext, state, kidFrame, desiredSize.height -
-                              oldKidRect.height);
-
-    // Return of desired size
-    aDesiredSize.width = aReflowState.maxSize.width;
-    aDesiredSize.height = state.y;
-
+    rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
   } else {
     PRBool reflowMappedOK = PR_TRUE;
   
@@ -855,10 +822,329 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
              aDesiredSize.width, aDesiredSize.height);
   }
 
-  return NS_OK;
+  return rv;
 
 }
 
+
+NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
+                                                  nsHTMLReflowMetrics& aDesiredSize,
+                                                  const nsHTMLReflowState& aReflowState,
+                                                  nsReflowStatus& aStatus)
+{
+  if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IncrementalReflow\n");
+  nsresult  rv = NS_OK;
+
+  // create an inner table reflow state
+  RowGroupReflowState state(aPresContext, aReflowState);
+
+  // determine if this frame is the target or not
+  nsIFrame *target=nsnull;
+  rv = aReflowState.reflowCommand->GetTarget(target);
+  if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
+  {
+    if (this==target)
+      rv = IR_TargetIsMe(aPresContext, aDesiredSize, state, aStatus);
+    else
+    {
+      // Get the next frame in the reflow chain
+      nsIFrame* nextFrame;
+      aReflowState.reflowCommand->GetNext(nextFrame);
+
+      // Recover our reflow state
+      //RecoverState(state, nextFrame);
+      rv = IR_TargetIsChild(aPresContext, aDesiredSize, state, aStatus, nextFrame);
+    }
+  }
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext&      aPresContext,
+                                              nsHTMLReflowMetrics& aDesiredSize,
+                                              RowGroupReflowState& aReflowState,
+                                              nsReflowStatus&      aStatus)
+{
+  nsresult rv = NS_FRAME_COMPLETE;
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  nsIFrame *objectFrame;
+  aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (PR_TRUE==gsDebugIR) printf("TRGF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
+  switch (type)
+  {
+  case nsIReflowCommand::FrameInserted :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                          objectFrame, PR_FALSE);
+    }
+    else
+    {
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+
+  /*
+  case nsIReflowCommand::FrameReplaced :
+
+  */
+
+  case nsIReflowCommand::FrameRemoved :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                         objectFrame);
+    }
+    else
+    {
+      rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                  objectFrame);
+    }
+    break;
+
+  case nsIReflowCommand::StyleChanged :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: StyleChanged not implemented.\n");
+    break;
+
+  case nsIReflowCommand::ContentChanged :
+    NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
+    rv = NS_ERROR_ILLEGAL_VALUE;
+    break;
+  
+  case nsIReflowCommand::PullupReflow:
+  case nsIReflowCommand::PushReflow:
+  case nsIReflowCommand::CheckPullupReflow :
+  case nsIReflowCommand::UserDefined :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: reflow command not implemented.\n");
+    break;
+  }
+
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_RowInserted(nsIPresContext&      aPresContext,
+                                               nsHTMLReflowMetrics& aDesiredSize,
+                                               RowGroupReflowState& aReflowState,
+                                               nsReflowStatus&      aStatus,
+                                               nsIFrame *           aInsertedFrame,
+                                               PRBool               aReplace)
+{
+  nsresult rv=NS_OK;
+  // inserting the rowgroup only effects reflow if the rowgroup includes at least one row
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
+{
+  nsresult rv=NS_OK;
+  /* need to make space in the cell map.  Remeber that row spans can't cross row groups
+     once the space is made, tell the row to initizalize its children.  
+     it will automatically find the row to initialize into.
+     but this is tough because a cell in aInsertedFrame could have a rowspan
+     which must be respected if a subsequent row is appended.
+  */
+  rv = aRowFrame->InitChildren();
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableRowGroupFrame::IR_RowAppended(nsIPresContext&      aPresContext,
+                                               nsHTMLReflowMetrics& aDesiredSize,
+                                               RowGroupReflowState& aReflowState,
+                                               nsReflowStatus&      aStatus,
+                                               nsIFrame *           aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  nsIFrame *lastRow = nsnull;
+  while (nsnull!=nextChild)
+  {
+    // remember the last child that is really a row
+    const nsStyleDisplay *childDisplay;
+    nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+      lastRow = nextChild;
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  nsTableFrame *tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if (NS_FAILED(rv) || nsnull==tableFrame)
+    return rv;
+  tableFrame->InvalidateFirstPassCache();
+  // the table will see that it's cached info is bogus and rebuild the cell map,
+  // and do a reflow
+
+#if 0
+  // find the row index of the new row
+  PRInt32 newRowIndex=-1;
+  if (nsnull!=
+
+  lastChild=mFirstChild;
+  nextChild=lastChild;
+  while (nsnull!=nextChild)
+  {
+  }
+  // account for the cells in aAppendedFrame
+  nsresult rv = DidAppendRow((nsTableRowFrame*)aAppendedFrame, newRowIndex);
+
+  // need to increment the row index of all subsequent rows
+#endif 
+
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_RowRemoved(nsIPresContext&      aPresContext,
+                                              nsHTMLReflowMetrics& aDesiredSize,
+                                              RowGroupReflowState& aReflowState,
+                                              nsReflowStatus&      aStatus,
+                                              nsIFrame *           aDeletedFrame)
+{
+  nsresult rv;
+  return rv;
+}
+
+//XXX: handle aReplace
+NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                                        nsHTMLReflowMetrics& aDesiredSize,
+                                                        RowGroupReflowState& aReflowState,
+                                                        nsReflowStatus&      aStatus,
+                                                        nsIFrame *           aInsertedFrame,
+                                                        PRBool               aReplace)
+{
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  // we have a generic frame that gets inserted but doesn't effect reflow
+  // hook it up then ignore it
+  if (nsIReflowCommand::FrameAppended==type)
+  { // frameAppended reflow -- find the last child and make aInsertedFrame its next sibling
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameAppended adding unknown frame type.\n");
+    nsIFrame *lastChild=mFirstChild;
+    nsIFrame *nextChild=mFirstChild;
+    while (nsnull!=nextChild)
+    {
+      lastChild=nextChild;
+      nextChild->GetNextSibling(nextChild);
+    }
+    if (nsnull==lastChild)
+      mFirstChild = aInsertedFrame;
+    else
+      lastChild->SetNextSibling(aInsertedFrame);
+  }
+  else
+  { // frameInserted reflow -- hook up aInsertedFrame as prevSibling's next sibling, 
+    // and be sure to hook in aInsertedFrame's nextSibling (from prevSibling)
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameInserted adding unknown frame type.\n");
+    nsIFrame *prevSibling=nsnull;
+    nsresult rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
+    if (NS_SUCCEEDED(rv) && (nsnull!=prevSibling))
+    {
+      nsIFrame *nextSibling=nsnull;
+      prevSibling->GetNextSibling(nextSibling);
+      prevSibling->SetNextSibling(aInsertedFrame);
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+    else
+    {
+      nsIFrame *nextSibling=nsnull;
+      if (nsnull!=mFirstChild)
+        mFirstChild->GetNextSibling(nextSibling);
+      mFirstChild = aInsertedFrame;
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+  }
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                                       nsHTMLReflowMetrics& aDesiredSize,
+                                                       RowGroupReflowState& aReflowState,
+                                                       nsReflowStatus&      aStatus,
+                                                       nsIFrame *           aRemovedFrame)
+{
+  // we have a generic frame that gets removed but doesn't effect reflow
+  // unhook it then ignore it
+  if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameRemoved removing unknown frame type.\n");
+  nsIFrame *prevChild=nsnull;
+  nsIFrame *nextChild=mFirstChild;
+  while (nextChild!=aRemovedFrame)
+  {
+    prevChild=nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }  
+  nextChild=nsnull;
+  aRemovedFrame->GetNextSibling(nextChild);
+  if (nsnull==prevChild)  // objectFrame was first child
+    mFirstChild = nextChild;
+  else
+    prevChild->SetNextSibling(nextChild);
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext&      aPresContext,
+                                                 nsHTMLReflowMetrics& aDesiredSize,
+                                                 RowGroupReflowState& aReflowState,
+                                                 nsReflowStatus&      aStatus,
+                                                 nsIFrame *           aNextFrame)
+
+{
+  nsresult rv;
+  if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_TargetIsChild\n");
+  // XXX Recover state
+
+  // Remember the old rect
+  nsRect  oldKidRect;
+  aNextFrame->GetRect(oldKidRect);
+
+  // Pass along the reflow command
+  // XXX Correctly compute the available space...
+  nsHTMLReflowState   kidReflowState(aPresContext, aNextFrame, aReflowState.reflowState, aReflowState.reflowState.maxSize);
+  nsHTMLReflowMetrics desiredSize(nsnull);
+
+  rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+
+  // Resize the row frame
+  nsRect  kidRect;
+  aNextFrame->GetRect(kidRect);
+  aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
+
+  // Adjust the frames that follow...
+  AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
+                            oldKidRect.height);
+
+  // Return of desired size
+  aDesiredSize.width = aReflowState.reflowState.maxSize.width;
+  aDesiredSize.height = aReflowState.y;
+
+  return rv;
+}
+
 NS_METHOD
 nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext&  aPresContext,
                                             nsIFrame*        aParent,
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
index 309f7afa04a..302619e9315 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
@@ -22,6 +22,7 @@
 #include "nsContainerFrame.h"
 #include "nsIAtom.h"
 
+class nsTableRowFrame;
 struct RowGroupReflowState;
 
 /**
@@ -79,6 +80,65 @@ public:
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus& aStatus);
 
+  /** Incremental Reflow attempts to do column balancing with the minimum number of reflow
+    * commands to child elements.  This is done by processing the reflow command,
+    * rebalancing column widths (if necessary), then comparing the resulting column widths
+    * to the prior column widths and reflowing only those cells that require a reflow.
+    *
+    * @see Reflow
+    */
+  NS_IMETHOD IncrementalReflow(nsIPresContext&          aPresContext,
+                               nsHTMLReflowMetrics&     aDesiredSize,
+                               const nsHTMLReflowState& aReflowState,
+                               nsReflowStatus&          aStatus);
+
+  NS_IMETHOD IR_TargetIsChild(nsIPresContext&      aPresContext,
+                              nsHTMLReflowMetrics& aDesiredSize,
+                              RowGroupReflowState& aReflowState,
+                              nsReflowStatus&      aStatus,
+                              nsIFrame *           aNextFrame);
+
+  NS_IMETHOD IR_TargetIsMe(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowGroupReflowState& aReflowState,
+                           nsReflowStatus&      aStatus);
+
+  NS_IMETHOD IR_RowInserted(nsIPresContext&      aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowGroupReflowState& aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aInsertedFrame,
+                            PRBool               aReplace);
+
+  NS_IMETHOD IR_RowAppended(nsIPresContext&      aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowGroupReflowState& aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aAppendedFrame);
+
+  NS_IMETHOD IR_DidAppendRow(nsTableRowFrame *aRowFrame);
+
+  NS_IMETHOD IR_RowRemoved(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowGroupReflowState& aReflowState,
+                           nsReflowStatus&      aStatus,
+                           nsIFrame *           aDeletedFrame);
+  
+  NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                     nsHTMLReflowMetrics& aDesiredSize,
+                                     RowGroupReflowState& aReflowState,
+                                     nsReflowStatus&      aStatus,
+                                     nsIFrame *           aInsertedFrame,
+                                     PRBool               aReplace);
+
+  NS_IMETHOD IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                    nsHTMLReflowMetrics& aDesiredSize,
+                                    RowGroupReflowState& aReflowState,
+                                    nsReflowStatus&      aStatus,
+                                    nsIFrame *           aDeletedFrame);
+
+
+
   /** @see nsContainerFrame::CreateContinuingFrame */
   NS_IMETHOD CreateContinuingFrame(nsIPresContext&  aPresContext,
                                    nsIFrame*        aParent,
@@ -111,11 +171,11 @@ protected:
   ~nsTableRowGroupFrame();
 
   nscoord GetTopMarginFor(nsIPresContext*      aCX,
-                          RowGroupReflowState& aState,
+                          RowGroupReflowState& aReflowState,
                           const nsMargin&      aKidMargin);
 
   void          PlaceChild( nsIPresContext*      aPresContext,
-                            RowGroupReflowState& aState,
+                            RowGroupReflowState& aReflowState,
                             nsIFrame*            aKidFrame,
                             const nsRect&        aKidRect,
                             nsSize*              aMaxElementSize,
@@ -124,8 +184,8 @@ protected:
   void ShrinkWrapChildren(nsIPresContext* aPresContext, 
                           nsHTMLReflowMetrics& aDesiredSize);
 
-  nsresult AdjustSiblingsAfterReflow(nsIPresContext*      aPresContext,
-                                     RowGroupReflowState& aState,
+  nsresult AdjustSiblingsAfterReflow(nsIPresContext&      aPresContext,
+                                     RowGroupReflowState& aReflowState,
                                      nsIFrame*            aKidFrame,
                                      nscoord              aDeltaY);
 
@@ -133,24 +193,24 @@ protected:
    * Reflow the frames we've already created
    *
    * @param   aPresContext presentation context to use
-   * @param   aState current inline state
+   * @param   aReflowState current inline state
    * @return  true if we successfully reflowed all the mapped children and false
    *            otherwise, e.g. we pushed children to the next in flow
    */
   PRBool        ReflowMappedChildren(nsIPresContext*      aPresContext,
-                                     RowGroupReflowState& aState,
+                                     RowGroupReflowState& aReflowState,
                                      nsSize*              aMaxElementSize);
 
   /**
    * Try and pull-up frames from our next-in-flow
    *
    * @param   aPresContext presentation context to use
-   * @param   aState current inline state
+   * @param   aReflowState current inline state
    * @return  true if we successfully pulled-up all the children and false
    *            otherwise, e.g. child didn't fit
    */
   PRBool        PullUpChildren(nsIPresContext*      aPresContext,
-                               RowGroupReflowState& aState,
+                               RowGroupReflowState& aReflowState,
                                nsSize*              aMaxElementSize);
 
 private:
diff --git a/mozilla/layout/tables/nsCellMap.h b/mozilla/layout/tables/nsCellMap.h
index e5e9a23f71b..723536e3aad 100644
--- a/mozilla/layout/tables/nsCellMap.h
+++ b/mozilla/layout/tables/nsCellMap.h
@@ -119,6 +119,9 @@ public:
 		*/
   void AppendColumnFrame(nsTableColFrame *aColFrame);
 
+  /** empty the column frame cache */
+  void ClearColumnCache();
+
 	/** returns PR_TRUE if the row at aRowIndex has any cells that are the result
 		* of a row-spanning cell above it.  So, given this table:
*
@@ -227,5 +230,11 @@ inline void nsCellMap::AppendColumnFrame(nsTableColFrame *aColFrame)
   mColFrames->AppendElement(aColFrame);
 }
 
+inline void nsCellMap::ClearColumnCache()
+{
+  if (nsnull!=mColFrames)
+    mColFrames->Clear();
+}
+
 
 #endif
diff --git a/mozilla/layout/tables/nsTableColGroupFrame.cpp b/mozilla/layout/tables/nsTableColGroupFrame.cpp
index c7a676ddc00..ffd056193bd 100644
--- a/mozilla/layout/tables/nsTableColGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableColGroupFrame.cpp
@@ -52,87 +52,89 @@ nsresult
 nsTableColGroupFrame::InitNewFrames(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
   nsresult rv=NS_OK;
-  nsIFrame* tableFrame=nsnull;
-  GetGeometricParent(tableFrame);
-  // Process the newly added column frames
-  for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) {
-    // Set the preliminary values for the column frame
-    nsIContent* kid;
-    kidFrame->GetContent(kid);
-    // should use style to get this value
-    PRInt32 repeat=1;
-    nsIHTMLTableColElement* colContent = nsnull;
-    rv = kid->QueryInterface(kIHTMLTableColElementIID, 
-                     (void**) &colContent); // colContent: ADDREF++
-    NS_RELEASE(kid);
-    if (rv==NS_OK)
-    {
-      colContent->GetSpanValue(&repeat);
-      NS_RELEASE(colContent);
-    }
-    PRInt32 colIndex = mStartColIndex + mColCount;
-    ((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex, repeat);
-    mColCount+= repeat;
-    ((nsTableColFrame *)kidFrame)->SetColumnIndex(colIndex);
-    ((nsTableFrame *)tableFrame)->AddColumnFrame((nsTableColFrame *)kidFrame);
-  }
-  // colgroup's span attribute is how many columns the group represents
-  // in the absence of any COL children
-  if (0==mColCount)
+  nsTableFrame* tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
   {
-    nsIFrame *firstImplicitColFrame=nsnull;
-    nsIFrame *prevColFrame=nsnull;
-    nsAutoString colTag;
-    nsHTMLAtoms::col->ToString(colTag);
-    mColCount = GetSpan();
-    for (PRInt32 colIndex=0; colIndexAppendChildTo((nsIContent*)col, PR_FALSE);
-
-      // Create a new col frame
-      nsIFrame* colFrame;
-      NS_NewTableColFrame(col, this, colFrame);
-
-      // Set its style context
-      nsIStyleContextPtr colStyleContext =
-        aPresContext.ResolveStyleContextFor(col, this, PR_TRUE);
-      colFrame->SetStyleContext(&aPresContext, colStyleContext);
-      colFrame->Init(aPresContext, nsnull);
-
-      // Set nsColFrame-specific information
-      PRInt32 absColIndex = mStartColIndex + colIndex;
-      ((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex, 1);
-      ((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
-      ((nsTableFrame *)tableFrame)->AddColumnFrame((nsTableColFrame *)colFrame);
-
-      //hook into list of children
-      if (nsnull==firstImplicitColFrame)
-        firstImplicitColFrame = colFrame;
-      else
-        prevColFrame->SetNextSibling(colFrame);
-      prevColFrame = colFrame;
-    }
-    // hook new columns into col group child list
-    if (nsnull==mFirstChild)
-      mFirstChild = firstImplicitColFrame;
-    else
-    {
-      nsIFrame *lastChild = mFirstChild;
-      nsIFrame *nextChild = lastChild;
-      while (nsnull!=nextChild)
+    // Process the newly added column frames
+    for (nsIFrame* kidFrame = aChildList; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) {
+      // Set the preliminary values for the column frame
+      nsIContent* kid;
+      kidFrame->GetContent(kid);
+      // should use style to get this value
+      PRInt32 repeat=1;
+      nsIHTMLTableColElement* colContent = nsnull;
+      rv = kid->QueryInterface(kIHTMLTableColElementIID, 
+                       (void**) &colContent); // colContent: ADDREF++
+      NS_RELEASE(kid);
+      if (rv==NS_OK)
       {
-        lastChild = nextChild;
-        nextChild->GetNextSibling(nextChild);
+        colContent->GetSpanValue(&repeat);
+        NS_RELEASE(colContent);
       }
-      lastChild->SetNextSibling(firstImplicitColFrame);
+      PRInt32 colIndex = mStartColIndex + mColCount;
+      ((nsTableColFrame *)(kidFrame))->InitColFrame (colIndex, repeat);
+      mColCount+= repeat;
+      ((nsTableColFrame *)kidFrame)->SetColumnIndex(colIndex);
+      tableFrame->AddColumnFrame((nsTableColFrame *)kidFrame);
     }
-  }
-  SetStyleContextForFirstPass(aPresContext);
+    // colgroup's span attribute is how many columns the group represents
+    // in the absence of any COL children
+    if (0==mColCount)
+    {
+      nsIFrame *firstImplicitColFrame=nsnull;
+      nsIFrame *prevColFrame=nsnull;
+      nsAutoString colTag;
+      nsHTMLAtoms::col->ToString(colTag);
+      mColCount = GetSpan();
+      for (PRInt32 colIndex=0; colIndexAppendChildTo((nsIContent*)col, PR_FALSE);
 
+        // Create a new col frame
+        nsIFrame* colFrame;
+        NS_NewTableColFrame(col, this, colFrame);
+
+        // Set its style context
+        nsIStyleContextPtr colStyleContext =
+          aPresContext.ResolveStyleContextFor(col, this, PR_TRUE);
+        colFrame->SetStyleContext(&aPresContext, colStyleContext);
+        colFrame->Init(aPresContext, nsnull);
+
+        // Set nsColFrame-specific information
+        PRInt32 absColIndex = mStartColIndex + colIndex;
+        ((nsTableColFrame *)(colFrame))->InitColFrame (absColIndex, 1);
+        ((nsTableColFrame *)colFrame)->SetColumnIndex(absColIndex);
+        tableFrame->AddColumnFrame((nsTableColFrame *)colFrame);
+
+        //hook into list of children
+        if (nsnull==firstImplicitColFrame)
+          firstImplicitColFrame = colFrame;
+        else
+          prevColFrame->SetNextSibling(colFrame);
+        prevColFrame = colFrame;
+      }
+      // hook new columns into col group child list
+      if (nsnull==mFirstChild)
+        mFirstChild = firstImplicitColFrame;
+      else
+      {
+        nsIFrame *lastChild = mFirstChild;
+        nsIFrame *nextChild = lastChild;
+        while (nsnull!=nextChild)
+        {
+          lastChild = nextChild;
+          nextChild->GetNextSibling(nextChild);
+        }
+        lastChild->SetNextSibling(firstImplicitColFrame);
+      }
+    }
+    SetStyleContextForFirstPass(aPresContext);
+  }
   return rv;
 }
 
@@ -233,54 +235,55 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext&          aPresContext,
 NS_METHOD nsTableColGroupFrame::SetStyleContextForFirstPass(nsIPresContext& aPresContext)
 {
   // get the table frame
-  nsIFrame* tableFrame=nsnull;
-  GetGeometricParent(tableFrame);
-  
-  // get the style for the table frame
-  nsStyleTable *tableStyle;
-  tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
+  nsTableFrame* tableFrame=nsnull;
+  nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
+  {  
+    // get the style for the table frame
+    nsStyleTable *tableStyle;
+    tableFrame->GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
 
-  // if COLS is set, then map it into the COL frames
-  if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
-  {
-    // set numCols to the number of columns effected by the COLS attribute
-    PRInt32 numCols=0;
-    if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
-      numCols = LengthOf(mFirstChild);
-    else 
-      numCols = tableStyle->mCols;
-
-    // for every column effected, set its width style
-    PRInt32 colIndex=0;
-    nsIFrame *colFrame=mFirstChild;
-    while (nsnull!=colFrame)
+    // if COLS is set, then map it into the COL frames
+    if (NS_STYLE_TABLE_COLS_NONE != tableStyle->mCols)
     {
-      nsStyleDisplay * colDisplay=nsnull;
-      colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
-      {
-        nsIStyleContextPtr colStyleContext;
-        nsStylePosition * colPosition=nsnull;
-        colFrame->GetStyleContext(&aPresContext, colStyleContext.AssignRef());
-        colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
-        if (colIndexmWidth = width;
-        }
-        else
-        {
-          colPosition->mWidth.SetCoordValue(0);
-        }
-        colStyleContext->RecalcAutomaticData(&aPresContext);
-        colIndex++;
-      }
-      colFrame->GetNextSibling(colFrame);
-    }
+      // set numCols to the number of columns effected by the COLS attribute
+      PRInt32 numCols=0;
+      if (NS_STYLE_TABLE_COLS_ALL == tableStyle->mCols)
+        numCols = LengthOf(mFirstChild);
+      else 
+        numCols = tableStyle->mCols;
 
-    mStyleContext->RecalcAutomaticData(&aPresContext);
+      // for every column effected, set its width style
+      PRInt32 colIndex=0;
+      nsIFrame *colFrame=mFirstChild;
+      while (nsnull!=colFrame)
+      {
+        nsStyleDisplay * colDisplay=nsnull;
+        colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        {
+          nsIStyleContextPtr colStyleContext;
+          nsStylePosition * colPosition=nsnull;
+          colFrame->GetStyleContext(&aPresContext, colStyleContext.AssignRef());
+          colPosition = (nsStylePosition*)colStyleContext->GetMutableStyleData(eStyleStruct_Position);
+          if (colIndexmWidth = width;
+          }
+          else
+          {
+            colPosition->mWidth.SetCoordValue(0);
+          }
+          colStyleContext->RecalcAutomaticData(&aPresContext);
+          colIndex++;
+        }
+        colFrame->GetNextSibling(colFrame);
+      }
+      mStyleContext->RecalcAutomaticData(&aPresContext);
+    }
   }
-  return NS_OK;
+  return rv;
 }
 
 
diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp
index dcf88de6ec8..64e775c30a1 100644
--- a/mozilla/layout/tables/nsTableFrame.cpp
+++ b/mozilla/layout/tables/nsTableFrame.cpp
@@ -270,6 +270,7 @@ nsTableFrame::nsTableFrame(nsIContent* aContent, nsIFrame* aParentFrame)
     mColCache(nsnull),
     mTableLayoutStrategy(nsnull),
     mFirstPassValid(PR_FALSE),
+    mCellMapValid(PR_TRUE),
     mIsInvariantWidth(PR_FALSE)
 {
   mEffectiveColCount = -1;  // -1 means uninitialized
@@ -298,11 +299,44 @@ nsTableFrame::~nsTableFrame()
 NS_IMETHODIMP
 nsTableFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
+  nsresult rv=NS_OK;
   mFirstChild = aChildList;
-  EnsureColumns(aPresContext);
-  return NS_OK;
+  // I know now that I have all my children, so build the cell map
+  nsIFrame *nextRowGroup=mFirstChild;
+  for ( ; nsnull!=nextRowGroup; nextRowGroup->GetNextSibling(nextRowGroup))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    nextRowGroup->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      rv = DidAppendRowGroup((nsTableRowGroupFrame*)nextRowGroup);
+    }
+  }
+  if (NS_SUCCEEDED(rv))
+    EnsureColumns(aPresContext);
+  return rv;
 }
 
+NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame)
+{
+  nsresult rv=NS_OK;
+  nsIFrame *nextRow=nsnull;
+  aRowGroupFrame->FirstChild(nextRow);
+  for ( ; nsnull!=nextRow; nextRow->GetNextSibling(nextRow))
+  {
+    const nsStyleDisplay *rowDisplay;
+    nextRow->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+    if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+    {
+      rv = ((nsTableRowFrame *)nextRow)->InitChildren();
+      if (NS_FAILED(rv))
+        return rv;
+    }
+  }
+  return rv;
+}
+
+
 /* ****** CellMap methods ******* */
 
 /* return the next row group frame after aRowGroupFrame */
@@ -322,14 +356,12 @@ nsTableRowGroupFrame* nsTableFrame::NextRowGroupFrame(nsTableRowGroupFrame* aRow
     const nsStyleDisplay *display;
     aRowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
     if (PR_TRUE==IsRowGroup(display->mDisplay))
-    { //XXX: assumes content order
+    { 
       break;
     }
-
     // Get the next frame
     aRowGroupFrame->GetNextSibling((nsIFrame*&)aRowGroupFrame);
   }
-
   return aRowGroupFrame;
 }
 
@@ -346,10 +378,6 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
     {
       mColCount += ((nsTableColGroupFrame *)childFrame)->GetColumnCount();
     }
-    else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    { //XXX: assumes content order
-      break;
-    }
     childFrame->GetNextSibling(childFrame);
   }    
   return mColCount;
@@ -358,24 +386,10 @@ PRInt32 nsTableFrame::GetSpecifiedColumnCount ()
 PRInt32 nsTableFrame::GetRowCount ()
 {
   PRInt32 rowCount = 0;
-
   nsCellMap *cellMap = GetCellMap();
-  if (nsnull != cellMap)
-    return cellMap->GetRowCount();
-
-  nsIFrame *child=mFirstChild;
-  while (nsnull!=child)
-  {
-    const nsStyleDisplay *childDisplay;
-    child->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
-    if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    {
-      PRInt32 thisRowCount=0;
-      ((nsTableRowGroupFrame *)child)->GetRowCount(thisRowCount);
-      rowCount += thisRowCount;
-    }
-    child->GetNextSibling(child);
-  }
+  NS_ASSERTION(nsnull!=cellMap, "GetRowCount null cellmap");
+  if (nsnull!=cellMap)
+    rowCount = cellMap->GetRowCount();
   return rowCount;
 }
 
@@ -383,7 +397,7 @@ PRInt32 nsTableFrame::GetRowCount ()
 PRInt32 nsTableFrame::GetColCount ()
 {
   nsCellMap *cellMap = GetCellMap();
-  NS_ASSERTION(nsnull!=cellMap, "GetColCount can only be called after cellmap has been created");
+  NS_ASSERTION(nsnull!=cellMap, "GetColCount null cellmap");
 
   if (nsnull!=cellMap)
   {
@@ -396,6 +410,7 @@ PRInt32 nsTableFrame::GetColCount ()
 void nsTableFrame::SetEffectiveColCount()
 {
   nsCellMap *cellMap = GetCellMap();
+  NS_ASSERTION(nsnull!=cellMap, "SetEffectiveColCount null cellmap");
   if (nsnull!=cellMap)
   {
     PRInt32 colCount = cellMap->GetColCount();
@@ -589,7 +604,7 @@ NS_ASSERTION(0mDisplay))
-    { // XXX: assumes content order
-      firstRowGroupFrame = childFrame;
-      if (PR_TRUE==gsDebug) printf("EC: found a row group %p\n", firstRowGroupFrame);
-      break;
+    {
+      if (nsnull==firstRowGroupFrame)
+      {
+        firstRowGroupFrame = childFrame;
+        if (PR_TRUE==gsDebug) printf("EC: found a row group %p\n", firstRowGroupFrame);
+      }
     }
-    prevSibFrame = childFrame;
+    if (nsnull==firstRowGroupFrame)
+      prevSibFrame = childFrame;
     childFrame->GetNextSibling(childFrame);
   }
   PRInt32 colCount = GetColCount();
@@ -666,7 +674,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext)
       nsAutoString colGroupTag;
       nsHTMLAtoms::colgroup->ToString(colGroupTag);
       rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag);  // ADDREF a: lastColGroup++
-      //XXX mark it as implicit!
+      //XXX: make synthetic
       mContent->AppendChildTo(lastColGroup, PR_FALSE);  // add the implicit colgroup to my content
       // Resolve style for the child
       nsIStyleContext* colGroupStyleContext =
@@ -716,7 +724,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext)
       nsIHTMLContent *col=nsnull;
       // create an implicit col
       rv = NS_CreateHTMLElement(&col, colTag);  // ADDREF: col++
-      //XXX mark the col implicit
+      //XXX: make synthetic
       lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
 
       // Create a new col frame
@@ -759,7 +767,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
   PRInt32 actualColumns = 0;
   nsTableColGroupFrame *lastColGroupFrame = nsnull;
   nsIFrame * firstRowGroupFrame=nsnull;
-  nsIFrame * prevSibFrame=nsnull;
+  nsIFrame * prevSibFrame=nsnull; // this is the child just before the first row group frame
   nsIFrame * childFrame=mFirstChild;
   while (nsnull!=childFrame)
   {
@@ -774,11 +782,12 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
         break;  // we have enough col frames at this point
     }
     else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-    { // XXX: assumes content order
-      firstRowGroupFrame = childFrame;
-      break;
+    {
+      if (nsnull==firstRowGroupFrame)
+        firstRowGroupFrame = childFrame;
     }
-    prevSibFrame = childFrame;
+    if (nsnull==firstRowGroupFrame)
+      prevSibFrame = childFrame;
     childFrame->GetNextSibling(childFrame);
   }    
   if (actualColumns <= aColIndex)
@@ -790,6 +799,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
       nsAutoString colGroupTag;
       nsHTMLAtoms::colgroup->ToString(colGroupTag);
       rv = NS_CreateHTMLElement(&lastColGroup, colGroupTag);  // ADDREF a: lastColGroup++
+      //XXX: make synthetic
       //XXX mark it as implicit!
       mContent->AppendChildTo(lastColGroup, PR_FALSE);  // add the implicit colgroup to my content
       // Resolve style for the child
@@ -837,7 +847,7 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
       nsIHTMLContent *col=nsnull;
       // create an implicit col
       rv = NS_CreateHTMLElement(&col, colTag);  // ADDREF: col++
-      //XXX mark the col implicit
+      //XXX: make synthetic
       lastColGroup->AppendChildTo((nsIContent*)col, PR_FALSE);
 
       // Create a new col frame
@@ -868,17 +878,22 @@ void nsTableFrame::EnsureColumnFrameAt(PRInt32              aColIndex,
 
 void nsTableFrame::AddColumnFrame (nsTableColFrame *aColFrame)
 {
-  mCellMap->AppendColumnFrame(aColFrame);
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
+    cellMap->AppendColumnFrame(aColFrame);
 }
 
 /** return the index of the next row that is not yet assigned */
 PRInt32 nsTableFrame::GetNextAvailRowIndex() const
 {
   PRInt32 result=0;
-  if (nsnull!=mCellMap)
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
   {
-    result = mCellMap->GetRowCount(); // the next index is the current count
-    mCellMap->GrowToRow(result+1);    // expand the cell map to include this new row
+    result = cellMap->GetRowCount(); // the next index is the current count
+    cellMap->GrowToRow(result+1);    // expand the cell map to include this new row
   }
   return result;
 }
@@ -887,15 +902,17 @@ PRInt32 nsTableFrame::GetNextAvailRowIndex() const
 PRInt32 nsTableFrame::GetNextAvailColIndex(PRInt32 aRowIndex, PRInt32 aColIndex) const
 {
   PRInt32 result=0;
-  if (nsnull!=mCellMap)
-    result = mCellMap->GetNextAvailColIndex(aRowIndex, aColIndex);
+  nsCellMap *cellMap = GetCellMap();
+  NS_PRECONDITION (nsnull!=cellMap, "null cellMap.");
+  if (nsnull!=cellMap)
+    result = cellMap->GetNextAvailColIndex(aRowIndex, aColIndex);
   return result;
 }
 
 /** Get the cell map for this table frame.  It is not always mCellMap.
   * Only the firstInFlow has a legit cell map
   */
-nsCellMap * nsTableFrame::GetCellMap()
+nsCellMap * nsTableFrame::GetCellMap() const
 {
   nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
   if (this!=firstInFlow)
@@ -951,7 +968,6 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
   }
 
   PRInt32 rowIndex;
-  // If we have a cell map reset it; otherwise allocate a new cell map
   // also determine the index of aRowFrame and set it if necessary
   if (0==mCellMap->GetRowCount())
   { // this is the first time we've ever been called
@@ -979,6 +995,34 @@ void nsTableFrame::AddCellToTable (nsTableRowFrame *aRowFrame,
     DumpCellMap ();
 }
 
+NS_METHOD nsTableFrame::ReBuildCellMap()
+{
+  nsresult rv=NS_OK;
+  nsIFrame *rowGroupFrame=mFirstChild;
+  for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      nsIFrame *rowFrame;
+      rowGroupFrame->FirstChild(rowFrame);
+      for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
+      {
+        const nsStyleDisplay *rowDisplay;
+        rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+        if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+        {
+          rv = ((nsTableRowFrame *)rowFrame)->InitChildren();
+          if (NS_FAILED(rv))
+            return rv;
+        }
+      }
+    }
+  }
+  return rv;
+}
+
 /**
   */
 void nsTableFrame::DumpCellMap () 
@@ -1054,20 +1098,20 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   // Setup CellMap for this cell
   int rowSpan = aCell->GetRowSpan();
   int colSpan = aCell->GetColSpan();
-  if (gsDebug==PR_TRUE) printf("        BuildCellIntoMap. rowSpan = %d, colSpan = %d\n", rowSpan, colSpan);
+  if (gsDebug==PR_TRUE) printf("BCIM: rowSpan = %d, colSpan = %d\n", rowSpan, colSpan);
 
   // Grow the mCellMap array if we will end up addressing
   // some new columns.
   if (mCellMap->GetColCount() < (aColIndex + colSpan))
   {
     if (gsDebug==PR_TRUE) 
-      printf("        calling GrowCellMap(%d)\n", aColIndex+colSpan);
+      printf("BCIM: calling GrowCellMap(%d)\n", aColIndex+colSpan);
     GrowCellMap (aColIndex + colSpan);
   }
 
   if (mCellMap->GetRowCount() < (aRowIndex+1))
   {
-    printf("*********************************************** calling GrowToRow(%d)\n", aRowIndex+1);
+    printf("BCIM: calling GrowToRow(%d)\n", aRowIndex+1);
     mCellMap->GrowToRow(aRowIndex+1);
   }
 
@@ -1075,7 +1119,7 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   CellData *data = new CellData ();
   data->mCell = aCell;
   data->mRealCell = data;
-  if (gsDebug==PR_TRUE) printf("        calling mCellMap->SetCellAt(data, %d, %d)\n", aRowIndex, aColIndex);
+  if (gsDebug==PR_TRUE) printf("BCIM: calling mCellMap->SetCellAt(data, %d, %d)\n", aRowIndex, aColIndex);
   mCellMap->SetCellAt(data, aRowIndex, aColIndex);
 
   // Create CellData objects for the rows that this cell spans. Set
@@ -1084,28 +1128,28 @@ void nsTableFrame::BuildCellIntoMap (nsTableCellFrame *aCell, PRInt32 aRowIndex,
   // CellData object for each row that we span...
   if ((1 < rowSpan) || (1 < colSpan))
   {
-    if (gsDebug==PR_TRUE) printf("        spans\n");
+    if (gsDebug==PR_TRUE) printf("BCIM: spans\n");
     for (int rowIndex = 0; rowIndex < rowSpan; rowIndex++)
     {
-      if (gsDebug==PR_TRUE) printf("          rowIndex = %d\n", rowIndex);
+      if (gsDebug==PR_TRUE) printf("BCIM: rowIndex = %d\n", rowIndex);
       int workRow = aRowIndex + rowIndex;
-      if (gsDebug==PR_TRUE) printf("          workRow = %d\n", workRow);
+      if (gsDebug==PR_TRUE) printf("BCIM: workRow = %d\n", workRow);
       for (int colIndex = 0; colIndex < colSpan; colIndex++)
       {
-        if (gsDebug==PR_TRUE) printf("            colIndex = %d\n", colIndex);
+        if (gsDebug==PR_TRUE) printf("BCIM: colIndex = %d\n", colIndex);
         int workCol = aColIndex + colIndex;
-        if (gsDebug==PR_TRUE) printf("            workCol = %d\n", workCol);
+        if (gsDebug==PR_TRUE) printf("BCIM: workCol = %d\n", workCol);
         CellData *testData = mCellMap->GetCellAt(workRow, workCol);
         if (nsnull == testData)
         {
           CellData *spanData = new CellData ();
           spanData->mRealCell = data;
-          if (gsDebug==PR_TRUE) printf("            null GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
+          if (gsDebug==PR_TRUE) printf("BCIM: null GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
           mCellMap->SetCellAt(spanData, workRow, workCol);
         }
         else if ((0 < rowIndex) || (0 < colIndex))
         { // we overlap, replace existing data, it might be shared
-          if (gsDebug==PR_TRUE) printf("            overlapping Cell from GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
+          if (gsDebug==PR_TRUE) printf("BCIM: overlapping Cell from GetCellFrameAt(%d, %d) so setting to spanData\n", workRow, workCol);
           CellData *overlap = new CellData ();
           overlap->mCell = testData->mCell;
           overlap->mRealCell = testData->mRealCell;
@@ -1414,12 +1458,15 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
   return NS_OK;
 }
 
-PRBool nsTableFrame::NeedsReflow(const nsSize& aMaxSize)
+PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
 {
   PRBool result = PR_TRUE;
-  if (PR_TRUE==mIsInvariantWidth)
-    result = PR_FALSE;
-  // TODO: other cases...
+  if (eReflowReason_Incremental != aReflowState.reason) 
+  { // incremental reflows always need to be reflowed (for now)
+    if (PR_TRUE==mIsInvariantWidth)
+      result = PR_FALSE;
+    // XXX TODO: other optimization cases...
+  }
   return result;
 }
 
@@ -1509,20 +1556,44 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
     rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
   }
 
-  if (PR_TRUE==NeedsReflow(aReflowState.maxSize))
+  // NeedsReflow and IsFirstPassValid take into account reflow type = Initial_Reflow
+  if (PR_TRUE==NeedsReflow(aReflowState, aReflowState.maxSize))
   {
+    PRBool needsRecalc=PR_FALSE;
+    if (PR_TRUE==gsDebug) printf("TF Reflow: needs reflow\n");
+    if (eReflowReason_Initial!=aReflowState.reason && PR_FALSE==IsCellMapValid())
+    {
+      if (PR_TRUE==gsDebug) printf("TF Reflow: not initial reflow, so resetting cell map.\n");
+      if (nsnull!=mCellMap)
+        delete mCellMap;
+      mCellMap = new nsCellMap(0,0);
+      ReBuildCellMap();
+      needsRecalc=PR_TRUE;
+    }
     if (PR_FALSE==IsFirstPassValid())
     {
-      // XXX TROY:  we used to rebuild the cellmap here for incremental reflow.
-      //            now that the cellmap is built in the constructor 
-      //            we need to reset the cellmap during incremental reflow before we get here
+      if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TF Reflow: first pass is invalid\n");
       rv = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, aStatus);
       if (NS_FAILED(rv))
         return rv;
+      needsRecalc=PR_TRUE;
+    }
+    if (PR_TRUE==needsRecalc)
+    {
+      if (PR_TRUE==gsDebugIR) printf("TF Reflow: needs recalc.\n");
+      // if we need to recalc, the data stored in the layout strategy is invalid
+      if (nsnull!=mTableLayoutStrategy)
+      {
+        if (PR_TRUE==gsDebugIR) printf("TF Reflow: Re-init layout strategy\n");
+        mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
+      }
+      BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
+      RecalcLayoutData();  // Recalculate Layout Dependencies
     }
 
+
     if (nsnull==mPrevInFlow)
-    {
+    { // only do this for a first-in-flow table frame
       // assign column widths, and assign aMaxElementSize->width
       BalanceColumnWidths(aPresContext, aReflowState, aReflowState.maxSize,
                           aDesiredSize.maxElementSize);
@@ -1656,10 +1727,6 @@ NS_METHOD nsTableFrame::ResizeReflowPass1(nsIPresContext& aPresContext,
     }
   }
 
-  BuildColumnCache(aPresContext, aDesiredSize, aReflowState, aStatus);
-  // Recalculate Layout Dependencies
-  RecalcLayoutData();
-
   aDesiredSize.width = kidSize.width;
   mFirstPassValid = PR_TRUE;
 
@@ -1756,6 +1823,7 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext&          aPresContext,
   return rv;
 
 }
+
 NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
                                           nsHTMLReflowMetrics& aDesiredSize,
                                           const nsHTMLReflowState& aReflowState,
@@ -1776,7 +1844,10 @@ NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
   rv = aReflowState.reflowCommand->GetTarget(target);
   if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
   {
-    if (this==target)
+    // this is the target if target is either this or the outer table frame containing this inner frame
+    nsIFrame *outerTableFrame=nsnull;
+    GetGeometricParent(outerTableFrame);
+    if ((this==target) || (outerTableFrame==target))
       rv = IR_TargetIsMe(aPresContext, aDesiredSize, state, aStatus);
     else
     {
@@ -1802,14 +1873,12 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
   aReflowState.reflowState.reflowCommand->GetType(type);
   nsIFrame *objectFrame;
   aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
   if (PR_TRUE==gsDebugIR) printf("TIF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
   switch (type)
   {
-  case nsIReflowCommand::FrameAppended :
   case nsIReflowCommand::FrameInserted :
-  {
-    const nsStyleDisplay *childDisplay;
-    objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
     if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
     {
       rv = IR_ColGroupInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
@@ -1826,7 +1895,22 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
                                    objectFrame, PR_FALSE);
     }
     break;
-  }
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    {
+      rv = IR_ColGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else if (IsRowGroup(childDisplay->mDisplay))
+    {
+      rv = IR_RowGroupAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
 
   /*
   case nsIReflowCommand::FrameReplaced :
@@ -1834,9 +1918,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
   */
 
   case nsIReflowCommand::FrameRemoved :
-  {
-    const nsStyleDisplay *childDisplay;
-    objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
     if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
     {
       rv = IR_ColGroupRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
@@ -1854,7 +1935,6 @@ NS_METHOD nsTableFrame::IR_TargetIsMe(nsIPresContext&        aPresContext,
                               objectFrame);
     }
     break;
-  }
 
   case nsIReflowCommand::StyleChanged :
     NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
@@ -1898,6 +1978,80 @@ NS_METHOD nsTableFrame::IR_ColGroupInserted(nsIPresContext&        aPresContext,
   return rv;
 }
 
+NS_METHOD nsTableFrame::IR_ColGroupAppended(nsIPresContext&        aPresContext,
+                                            nsHTMLReflowMetrics&   aDesiredSize,
+                                            InnerTableReflowState& aReflowState,
+                                            nsReflowStatus&        aStatus,
+                                            nsIFrame *             aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  /*
+  find where to place colgroup (skipping implicit children?)
+  for every col in the colgroup (including implicit cols due to span attribute)
+    an implicit col from the first implicit colgroup is removed 
+    when an implicit colgroups col count goes to 0, it is removed
+  */
+  /* need to really verify that issynthetic is specified on implicit colgroups and cols */
+
+
+  // build a vector of colgroups.  XXX might want to do this as a class thing, so we don't have to rebuild it each time
+  nsVoidArray colGroupList;
+  nsIFrame *childFrame=mFirstChild;
+  nsIFrame *lastChild=mFirstChild;
+  while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
+  {
+    const nsStyleDisplay *display;
+    childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay)
+    {
+      colGroupList.AppendElement((void*)childFrame);
+    }
+    lastChild=childFrame;
+    rv = childFrame->GetNextSibling(childFrame);
+  }
+  // append aAppendedFrame
+  if (nsnull!=lastChild)
+    lastChild->SetNextSibling(aAppendedFrame);
+  else
+    mFirstChild = aAppendedFrame;
+
+  /* go through the list of colgroups, sucking out implicit columns that are not the result of a span attribute
+   * and replacing them with columns in aAppendedFrame
+   * if the column had an attribute from a cell, be sure to preserve that
+   * if any implicit colgroup becomes empty, destroy it
+   * if any real colgroup becomes empty, we have to keep it
+   * factor the new cols into the column cache
+   *   this means having a flag that says whether the col cache needs to be rebuilt or not
+   */
+  PRInt32 colGroupCount = colGroupList.Count();
+  if (0FirstChild(childFrame);
+    while ((NS_SUCCEEDED(rv)) && (nsnull!=childFrame))
+    {
+      const nsStyleDisplay *colDisplay;
+      childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)colDisplay);
+      if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+      { // find an implicit column that is not from a span attribute if there is one and remove it
+        for (PRInt32 colGroupIndex=0; colGroupIndexInitialize(aMaxElementSize);
+  mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize);
+  //XXX: what we want to do here is determine if the new COL information changes anything about layout
+  //     if not, skip invalidating the first passs
+  //     if so, and we can fix the first pass info
+  return rv;
+}
+
+
 NS_METHOD nsTableFrame::IR_ColGroupRemoved(nsIPresContext&        aPresContext,
                                            nsHTMLReflowMetrics&   aDesiredSize,
                                            InnerTableReflowState& aReflowState,
@@ -1921,6 +2075,39 @@ NS_METHOD nsTableFrame::IR_RowGroupInserted(nsIPresContext&        aPresContext,
                                             PRBool                 aReplace)
 {
   nsresult rv;
+  // inserting the rowgroup only effects reflow if the rowgroup includes at least one row
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableFrame::IR_RowGroupAppended(nsIPresContext&        aPresContext,
+                                            nsHTMLReflowMetrics&   aDesiredSize,
+                                            InnerTableReflowState& aReflowState,
+                                            nsReflowStatus&        aStatus,
+                                            nsIFrame *             aAppendedFrame)
+{
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  while (nsnull!=nextChild)
+  {
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  // account for the cells in the rows that are children of aAppendedFrame
+  nsresult rv = DidAppendRowGroup((nsTableRowGroupFrame*)aAppendedFrame);
+
+  // do a pass-1 layout of all the cells in all the rows of the rowgroup
+  InvalidateFirstPassCache();
+
+  // if any column widths have to change due to this, re-init the layout strategy
+  // mTableLayoutStrategy->Initialize(aDesiredSize.aMaxElementSize);  //XXX for now, we're just doing the whole enchelada
+
   return rv;
 }
 
@@ -2032,7 +2219,7 @@ NS_METHOD nsTableFrame::IR_TargetIsChild(nsIPresContext&        aPresContext,
                                    aReflowState.reflowState,
                                    aReflowState.reflowState.maxSize);
 
-  ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+  rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
 
   // Resize the row group frame
   nsRect  kidRect;
@@ -2160,8 +2347,6 @@ void nsTableFrame::PlaceChild(nsIPresContext&    aPresContext,
   {
     nsMargin borderPadding;
     const nsStyleSpacing* tableSpacing;
-    // begin REMOVE_ME_WHEN_TABLE_STYLE_IS_RESOLVED!
-    nsIFrame * parent = nsnull;
     GetStyleData(eStyleStruct_Spacing , ((nsStyleStruct *&)tableSpacing));
     tableSpacing->CalcBorderPaddingFor(this, borderPadding);
     nscoord cellSpacing = GetCellSpacing();
@@ -2753,95 +2938,95 @@ void nsTableFrame::BuildColumnCache( nsIPresContext&      aPresContext,
                                      nsReflowStatus&      aStatus
                                     )
 {
-  // probably want this assertion : NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
+  NS_ASSERTION(nsnull==mPrevInFlow, "never ever call me on a continuing frame!");
   NS_ASSERTION(nsnull!=mCellMap, "never ever call me until the cell map is built!");
   nsStyleTable* tableStyle;
   GetStyleData(eStyleStruct_Table, (nsStyleStruct *&)tableStyle);
   EnsureColumns(aPresContext);
-  if (nsnull==mColCache)
+  if (nsnull!=mColCache)
   {
-    mColCache = new ColumnInfoCache(mColCount);
-    nsIFrame * childFrame = mFirstChild;
-    while (nsnull!=childFrame)
-    { // in this loop, we cache column info and set column style info from cells in first row
-      const nsStyleDisplay *childDisplay;
-      childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (PR_TRUE==gsDebugIR) printf("TIF BCB: clearing column cache and cell map column frame cache.\n");
+    mCellMap->ClearColumnCache();
+    delete mColCache;
+  }
 
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
-      { // if it's a col group then get the columns and cache them in the CellMap
-        nsTableColFrame *colFrame=nsnull;
-        childFrame->FirstChild((nsIFrame *&)colFrame);
-        while (nsnull!=colFrame)
-        { 
-          mCellMap->AppendColumnFrame(colFrame);
-          colFrame->GetNextSibling((nsIFrame *&)colFrame);
-        }
+  mColCache = new ColumnInfoCache(mColCount);
+  nsIFrame * childFrame = mFirstChild;
+  while (nsnull!=childFrame)
+  { // in this loop, we cache column info and set column style info from cells in first row
+    const nsStyleDisplay *childDisplay;
+    childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    { // if it's a col group then get the columns and cache them in the CellMap
+      nsTableColFrame *colFrame=nsnull;
+      childFrame->FirstChild((nsIFrame *&)colFrame);
+      while (nsnull!=colFrame)
+      { 
+        mCellMap->AppendColumnFrame(colFrame);
+        colFrame->GetNextSibling((nsIFrame *&)colFrame);
       }
-      else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-      { // if it's a row group, get the cells and set the column style if appropriate
-        if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
-        {
-          nsIFrame *rowFrame;
-          childFrame->FirstChild(rowFrame);
-          while (nsnull!=rowFrame)
-          {
-            const nsStyleDisplay *rowDisplay;
-            rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay));
-            if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay)
-            {
-              nsIFrame *cellFrame;
-              rowFrame->FirstChild(cellFrame);
-              while (nsnull!=cellFrame)
-              {
-                /* this is the first time we are guaranteed to have both the cell frames
-                 * and the column frames, so it's a good time to 
-                 * set the column style from the cell's width attribute (if this is the first row)
-                 */
-                const nsStyleDisplay *cellDisplay;
-                cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)cellDisplay));
-                if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
-                  SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
-                cellFrame->GetNextSibling(cellFrame);
-              }
-            }
-            rowFrame->GetNextSibling(rowFrame);
-          }
-        }
-      }
-      childFrame->GetNextSibling(childFrame);
     }
-
-    // second time through, set column cache info for each column
-    // we can't do this until the loop above has set the column style info from the cells in the first row
-    childFrame = mFirstChild;
-    while (nsnull!=childFrame)
-    { // for every child, if it's a col group then get the columns
-      const nsStyleDisplay *childDisplay;
-      childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
+    { // if it's a row group, get the cells and set the column style if appropriate
+      if (NS_STYLE_TABLE_LAYOUT_FIXED!=tableStyle->mLayoutStrategy)
       {
-        nsTableColFrame *colFrame=nsnull;
-        childFrame->FirstChild((nsIFrame *&)colFrame);
-        while (nsnull!=colFrame)
-        { // for every column, create an entry in the column cache
-          // assumes that the col style has been twiddled to account for first cell width attribute
-          const nsStyleDisplay *colDisplay;
-          colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
-          if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        nsIFrame *rowFrame;
+        childFrame->FirstChild(rowFrame);
+        while (nsnull!=rowFrame)
+        {
+          const nsStyleDisplay *rowDisplay;
+          rowFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)rowDisplay));
+          if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay)
           {
-            const nsStylePosition* colPosition;
-            colFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)colPosition));
-            mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
+            nsIFrame *cellFrame;
+            rowFrame->FirstChild(cellFrame);
+            while (nsnull!=cellFrame)
+            {
+              /* this is the first time we are guaranteed to have both the cell frames
+               * and the column frames, so it's a good time to 
+               * set the column style from the cell's width attribute (if this is the first row)
+               */
+              const nsStyleDisplay *cellDisplay;
+              cellFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)cellDisplay));
+              if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
+                SetColumnStyleFromCell(aPresContext, (nsTableCellFrame *)cellFrame, (nsTableRowFrame *)rowFrame);
+              cellFrame->GetNextSibling(cellFrame);
+            }
           }
-          colFrame->GetNextSibling((nsIFrame *&)colFrame);
+          rowFrame->GetNextSibling(rowFrame);
         }
       }
-      else if (PR_TRUE==IsRowGroup(childDisplay->mDisplay))
-      { // XXX: assumes content order
-        break;  // once we hit a row group, we're done
-      }
-      childFrame->GetNextSibling(childFrame);
     }
+    childFrame->GetNextSibling(childFrame);
+  }
+
+  // second time through, set column cache info for each column
+  // we can't do this until the loop above has set the column style info from the cells in the first row
+  childFrame = mFirstChild;
+  while (nsnull!=childFrame)
+  { // for every child, if it's a col group then get the columns
+    const nsStyleDisplay *childDisplay;
+    childFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay)
+    {
+      nsTableColFrame *colFrame=nsnull;
+      childFrame->FirstChild((nsIFrame *&)colFrame);
+      while (nsnull!=colFrame)
+      { // for every column, create an entry in the column cache
+        // assumes that the col style has been twiddled to account for first cell width attribute
+        const nsStyleDisplay *colDisplay;
+        colFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)colDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay)
+        {
+          const nsStylePosition* colPosition;
+          colFrame->GetStyleData(eStyleStruct_Position, ((nsStyleStruct *&)colPosition));
+          mColCache->AddColumnInfo(colPosition->mWidth.GetUnit(), colFrame->GetColumnIndex());
+        }
+        colFrame->GetNextSibling((nsIFrame *&)colFrame);
+      }
+    }
+    childFrame->GetNextSibling(childFrame);
   }
 }
 
@@ -2852,6 +3037,48 @@ PRBool nsTableFrame::IsFirstPassValid() const
   return firstInFlow->mFirstPassValid;
 }
 
+void nsTableFrame::InvalidateFirstPassCache()
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  firstInFlow->mFirstPassValid=PR_FALSE;
+}
+
+PRBool nsTableFrame::IsCellMapValid() const
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  return firstInFlow->mCellMapValid;
+}
+
+void nsTableFrame::InvalidateCellMap()
+{
+  nsTableFrame * firstInFlow = (nsTableFrame *)GetFirstInFlow();
+  NS_ASSERTION(nsnull!=firstInFlow, "illegal state -- no first in flow");
+  firstInFlow->mCellMapValid=PR_FALSE;
+  // reset the state in each row
+  nsIFrame *rowGroupFrame=mFirstChild;
+  for ( ; nsnull!=rowGroupFrame; rowGroupFrame->GetNextSibling(rowGroupFrame))
+  {
+    const nsStyleDisplay *rowGroupDisplay;
+    rowGroupFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowGroupDisplay);
+    if (PR_TRUE==IsRowGroup(rowGroupDisplay->mDisplay))
+    {
+      nsIFrame *rowFrame;
+      rowGroupFrame->FirstChild(rowFrame);
+      for ( ; nsnull!=rowFrame; rowFrame->GetNextSibling(rowFrame))
+      {
+        const nsStyleDisplay *rowDisplay;
+        rowFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)rowDisplay);
+        if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
+        {
+          ((nsTableRowFrame *)rowFrame)->ResetInitChildren();
+        }
+      }
+    }
+  }
+}
+
 NS_METHOD
 nsTableFrame::CreateContinuingFrame(nsIPresContext&  aPresContext,
                                     nsIFrame*        aParent,
@@ -3148,25 +3375,44 @@ NS_NewTableFrame(nsIContent* aContent,
   return NS_OK;
 }
 
-NS_METHOD nsTableFrame::GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aOutFrame)
+NS_METHOD nsTableFrame::GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame)
 {
   nsresult result = NS_OK;
-  aOutFrame = nsnull;   // initialize out-param
+  aTableFrame = nsnull;   // initialize out-param
   if (nsnull!=aSourceFrame)
   {
-    nsresult result = aSourceFrame->GetContentParent((nsIFrame *&)aOutFrame);
-    while ((NS_OK==result) && (nsnull!=aOutFrame))
+    nsresult result = aSourceFrame->GetContentParent((nsIFrame *&)aTableFrame);
+    while ((NS_OK==result) && (nsnull!=aTableFrame))
     {
       const nsStyleDisplay *display;
-      aOutFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
+      aTableFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)display);
       if (NS_STYLE_DISPLAY_TABLE == display->mDisplay)
+      {
+        // at this point, aTableFrame could be an outer frame, 
+        // to find out, scan it's children for another frame with a table display type
+        // if found, the childFrame must be the inner frame
+        nsresult rv;
+        nsIFrame *childFrame=nsnull;
+        rv = aTableFrame->FirstChild(childFrame);
+        while ((NS_OK==rv) && (nsnull!=childFrame))
+        {
+          const nsStyleDisplay *childDisplay;
+          childFrame->GetStyleData(eStyleStruct_Display, (nsStyleStruct *&)childDisplay);
+          if (NS_STYLE_DISPLAY_TABLE == childDisplay->mDisplay)
+          {
+            aTableFrame = (nsTableFrame *)childFrame;
+            break;
+          }
+          rv = childFrame->GetNextSibling(childFrame);
+        }
         break;
-      result = aOutFrame->GetContentParent((nsIFrame *&)aOutFrame);
+      }
+      result = aTableFrame->GetContentParent((nsIFrame *&)aTableFrame);
     }
   }
   else
     result = NS_ERROR_UNEXPECTED; // bad source param
-  NS_POSTCONDITION(nsnull!=aOutFrame, "unable to find table parent. aOutFrame null.");
+  NS_POSTCONDITION(nsnull!=aTableFrame, "unable to find table parent. aTableFrame null.");
   NS_POSTCONDITION(NS_OK==result, "unable to find table parent. result!=NS_OK");
   return result;
 }
diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h
index db2c20038a2..af7c9a5bb8f 100644
--- a/mozilla/layout/tables/nsTableFrame.h
+++ b/mozilla/layout/tables/nsTableFrame.h
@@ -79,7 +79,7 @@ public:
   PRBool IsNested(const nsHTMLReflowState& aReflowState, nsStylePosition *& aPosition) const;
 
   /** helper method to find the table parent of any table frame object */
-  static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aOutFrame);
+  static NS_METHOD GetTableFrame(nsIFrame *aSourceFrame, nsTableFrame *& aTableFrame);
 
   /** helper method for getting the width of the table's containing block */
   static nscoord GetTableContainerWidth(const nsHTMLReflowState& aState);
@@ -97,6 +97,11 @@ public:
 
   NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
 
+  /** complete the append of aRowGroupFrame to the table
+    * this builds the cell map
+    */
+  NS_IMETHOD DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFrame);
+
   /** @see nsIFrame::Paint */
   NS_IMETHOD Paint(nsIPresContext& aPresContext,
                    nsIRenderingContext& aRenderingContext,
@@ -315,6 +320,12 @@ protected:
                                  nsIFrame *             aInsertedFrame,
                                  PRBool                 aReplace);
 
+    NS_IMETHOD IR_ColGroupAppended(nsIPresContext&        aPresContext,
+                                 nsHTMLReflowMetrics&   aDesiredSize,
+                                 InnerTableReflowState& aReflowState,
+                                 nsReflowStatus&        aStatus,
+                                 nsIFrame *             aAppendedFrame); 
+
   NS_IMETHOD IR_ColGroupRemoved(nsIPresContext&        aPresContext,
                                 nsHTMLReflowMetrics&   aDesiredSize,
                                 InnerTableReflowState& aReflowState,
@@ -328,6 +339,12 @@ protected:
                                  nsIFrame *             aInsertedFrame,
                                  PRBool                 aReplace);
 
+  NS_IMETHOD IR_RowGroupAppended(nsIPresContext&        aPresContext,
+                                 nsHTMLReflowMetrics&   aDesiredSize,
+                                 InnerTableReflowState& aReflowState,
+                                 nsReflowStatus&        aStatus,
+                                 nsIFrame *             aAppendedFrame);
+
   NS_IMETHOD IR_RowGroupRemoved(nsIPresContext&        aPresContext,
                                 nsHTMLReflowMetrics&   aDesiredSize,
                                 InnerTableReflowState& aReflowState,
@@ -414,11 +431,16 @@ protected:
                                         nscoord aMaxHeight);
 
   /** given the new parent size, do I really need to do a reflow? */
-  virtual PRBool NeedsReflow(const nsSize& aMaxSize);
+  virtual PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, 
+                             const nsSize&            aMaxSize);
 
   /** returns PR_TRUE if the cached pass 1 data is still valid */
   virtual PRBool IsFirstPassValid() const;
 
+public:
+  virtual void InvalidateFirstPassCache();
+
+protected:
   /** do post processing to setting up style information for the frame */
   NS_IMETHOD DidSetStyleContext(nsIPresContext& aPresContext);
 
@@ -431,16 +453,24 @@ protected:
     */
   virtual void GrowCellMap(PRInt32 aColCount);
 
+  /** returns PR_TRUE if the cached pass 1 data is still valid */
+  virtual PRBool IsCellMapValid() const;
+
+public:
   /** ResetCellMap is called when the cell structure of the table is changed.
     * Call with caution, only when changing the structure of the table such as 
     * inserting or removing rows, changing the rowspan or colspan attribute of a cell, etc.
     */
-  virtual void ResetCellMap ();
+  virtual void InvalidateCellMap();
+    
+protected:
+  /** iterates all child frames and creates a new cell map */
+  NS_IMETHOD ReBuildCellMap();
 
   /** Get the cell map for this table frame.  It is not always mCellMap.
     * Only the firstInFlow has a legit cell map
     */
-  virtual nsCellMap *GetCellMap();
+  virtual nsCellMap *GetCellMap() const;
 
   /** for debugging only
     * prints out information about the cell map
@@ -559,6 +589,7 @@ private:
   PRInt32      mColumnWidthsLength; // the number of column lengths this frame has allocated
   PRBool       mColumnWidthsSet;    // PR_TRUE if column widths have been set at least once
   PRBool       mFirstPassValid;     // PR_TRUE if first pass data is still legit
+  PRBool       mCellMapValid;       // PR_TRUE if cell map data is still legit
   PRBool       mIsInvariantWidth;   // PR_TRUE if table width cannot change
   PRInt32      mColCount;           // the number of columns in this table
   PRInt32      mEffectiveColCount;  // the number of columns in this table adjusted for weird table attributes
diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp
index fa7585144e5..f002487dfdb 100644
--- a/mozilla/layout/tables/nsTableOuterFrame.cpp
+++ b/mozilla/layout/tables/nsTableOuterFrame.cpp
@@ -132,11 +132,11 @@ NS_METHOD nsTableOuterFrame::Paint(nsIPresContext& aPresContext,
   return NS_OK;
 }
 
-PRBool nsTableOuterFrame::NeedsReflow(const nsSize& aMaxSize)
+PRBool nsTableOuterFrame::NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize)
 {
   PRBool result=PR_TRUE;
   if (nsnull!=mInnerTableFrame)
-    result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aMaxSize);
+    result = ((nsTableFrame *)mInnerTableFrame)->NeedsReflow(aReflowState, aMaxSize);
   return result;
 }
 
diff --git a/mozilla/layout/tables/nsTableOuterFrame.h b/mozilla/layout/tables/nsTableOuterFrame.h
index 539d6013569..316601f159e 100644
--- a/mozilla/layout/tables/nsTableOuterFrame.h
+++ b/mozilla/layout/tables/nsTableOuterFrame.h
@@ -85,7 +85,7 @@ protected:
     * or if the table style attributes or parent max height/width have
     * changed.
     */
-  PRBool NeedsReflow(const nsSize& aMaxSize);
+  PRBool NeedsReflow(const nsHTMLReflowState& aReflowState, const nsSize& aMaxSize);
 
   void PlaceChild(OuterTableReflowState& aReflowState,
                   nsIFrame*              aKidFrame,
diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp
index 22742db37c0..14d07ef3cec 100644
--- a/mozilla/layout/tables/nsTableRowFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowFrame.cpp
@@ -39,10 +39,10 @@ NS_DEF_PTR(nsIStyleContext);
 
 #ifdef NS_DEBUG
 static PRBool gsDebug = PR_FALSE;
-//#define NOISY
-//#define NOISY_FLOW
+static PRBool gsDebugIR = PR_FALSE;
 #else
 static const PRBool gsDebug = PR_FALSE;
+static const PRBool gsDebugIR = PR_FALSE;
 #endif
 
 /* ----------- RowReflowState ---------- */
@@ -88,7 +88,8 @@ nsTableRowFrame::nsTableRowFrame(nsIContent* aContent,
     mTallestCell(0),
     mCellMaxTopMargin(0),
     mCellMaxBottomMargin(0),
-    mMinRowSpan(1)
+    mMinRowSpan(1),
+    mInitializedChildren(PR_FALSE)
 {
 }
 
@@ -100,45 +101,62 @@ NS_IMETHODIMP
 nsTableRowFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList)
 {
   mFirstChild = aChildList;
-  nsTableFrame* table = nsnull;
-  nsresult  result;
+  return NS_OK;
+}
 
-  result = nsTableFrame::GetTableFrame(this, table);
-  if ((NS_OK==result) && (table != nsnull))
+NS_IMETHODIMP
+nsTableRowFrame::InitChildren(PRInt32 aRowIndex)
+{
+  nsTableFrame* table = nsnull;
+  nsresult  result=NS_OK;
+
+  // each child cell can only be added to the table one time.
+  // for now, we remember globally whether we've added all or none
+  if (PR_FALSE==mInitializedChildren)
   {
-    SetRowIndex(table->GetNextAvailRowIndex());
-    PRInt32   colIndex = 0;
-    for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) 
+    result = nsTableFrame::GetTableFrame(this, table);
+    if ((NS_OK==result) && (table != nsnull))
     {
-      const nsStyleDisplay *kidDisplay;
-      kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
-      if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
+      mInitializedChildren=PR_TRUE;
+      PRInt32 rowIndex;
+      if (-1==aRowIndex)
+        rowIndex = table->GetNextAvailRowIndex();
+      else
+        rowIndex = aRowIndex;
+      SetRowIndex(rowIndex);
+      PRInt32   colIndex = 0;
+      for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; kidFrame->GetNextSibling(kidFrame)) 
       {
-        // what column does this cell belong to?
-        colIndex = table->GetNextAvailColIndex(mRowIndex, colIndex);
-        /* for style context optimization, set the content's column index if possible.
-         * this can only be done if we really have an nsTableCell.  
-         * other tags mapped to table cell display won't benefit from this optimization
-         * see nsHTMLStyleSheet::RulesMatching
-         */
-        nsIContent* cell;
-        kidFrame->GetContent(cell);
-        nsIHTMLTableCellElement *cellContent = nsnull;
-        nsresult rv = cell->QueryInterface(kIHTMLTableCellElementIID, 
-                                           (void **)&cellContent);  // cellContent: REFCNT++
-        NS_RELEASE(cell);
-        if (NS_SUCCEEDED(rv))
-        { // we know it's a table cell
-          cellContent->SetColIndex(colIndex);
-          if (gsDebug) printf("%p : set cell content %p to col index = %d\n", this, cellContent, colIndex);
-          NS_RELEASE(cellContent);
-        }
+        const nsStyleDisplay *kidDisplay;
+        kidFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
+        if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
+        {
+          // what column does this cell belong to?
+          colIndex = table->GetNextAvailColIndex(mRowIndex, colIndex);
+          /* for style context optimization, set the content's column index if possible.
+           * this can only be done if we really have an nsTableCell.  
+           * other tags mapped to table cell display won't benefit from this optimization
+           * see nsHTMLStyleSheet::RulesMatching
+           */
+          nsIContent* cell;
+          kidFrame->GetContent(cell);
+          nsIHTMLTableCellElement *cellContent = nsnull;
+          nsresult rv = cell->QueryInterface(kIHTMLTableCellElementIID, 
+                                             (void **)&cellContent);  // cellContent: REFCNT++
+          NS_RELEASE(cell);
+          if (NS_SUCCEEDED(rv))
+          { // we know it's a table cell
+            cellContent->SetColIndex(colIndex);
+            if (gsDebug) printf("%p : set cell content %p to col index = %d\n", this, cellContent, colIndex);
+            NS_RELEASE(cellContent);
+          }
       
-        // this sets the frame's notion of it's column index
-        ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
-        if (gsDebug) printf("%p : set cell frame %p to col index = %d\n", this, kidFrame, colIndex);
-        // add the cell frame to the table's cell map
-        table->AddCellToTable(this, (nsTableCellFrame *)kidFrame, kidFrame == mFirstChild);
+          // this sets the frame's notion of it's column index
+          ((nsTableCellFrame *)kidFrame)->InitCellFrame(colIndex);
+          if (gsDebug) printf("%p : set cell frame %p to col index = %d\n", this, kidFrame, colIndex);
+          // add the cell frame to the table's cell map
+          table->AddCellToTable(this, (nsTableCellFrame *)kidFrame, kidFrame == mFirstChild);
+        }
       }
     }
   }
@@ -346,7 +364,7 @@ void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame)
 // aKidRect is relative to the upper-left origin of our frame, and includes
 // any left/top margin.
 void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
-																 RowReflowState&    aState,
+																 RowReflowState&    aReflowState,
 																 nsIFrame*          aKidFrame,
 																 const nsRect&      aKidRect,
 																 nsSize*            aMaxElementSize,
@@ -360,10 +378,10 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
   aKidFrame->SetRect(aKidRect);
 
   // update the running total for the row width
-  aState.x += aKidRect.width;
+  aReflowState.x += aKidRect.width;
 
   // Update the maximum element size
-  PRInt32 rowSpan = aState.tableFrame->GetEffectiveRowSpan(mRowIndex, 
+  PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan(mRowIndex, 
                     ((nsTableCellFrame*)aKidFrame));
   if (nsnull != aMaxElementSize) 
   {
@@ -377,18 +395,18 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
   if (mMinRowSpan == rowSpan)
   {
     // Update maxCellHeight
-    if (aKidRect.height > aState.maxCellHeight)
-      aState.maxCellHeight = aKidRect.height;
+    if (aKidRect.height > aReflowState.maxCellHeight)
+      aReflowState.maxCellHeight = aKidRect.height;
 
     // Update maxCellVertSpace
     nsMargin margin;
 
-    if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK)
+    if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aKidFrame, margin) == NS_OK)
     {
       nscoord height = aKidRect.height + margin.top + margin.bottom;
   
-      if (height > aState.maxCellVertSpace)
-        aState.maxCellVertSpace = height;
+      if (height > aReflowState.maxCellVertSpace)
+        aReflowState.maxCellVertSpace = height;
     }
   }
 }
@@ -398,7 +416,7 @@ void nsTableRowFrame::PlaceChild(nsIPresContext&    aPresContext,
  * changed. Reflows all the existing table cell frames
  */
 nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
-                                       RowReflowState&  aState,
+                                       RowReflowState&  aReflowState,
                                        nsHTMLReflowMetrics& aDesiredSize)
 {
   if (nsnull == mFirstChild)
@@ -410,7 +428,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
                                      &kidMaxElementSize : nsnull;
   nscoord     maxCellTopMargin = 0;
   nscoord     maxCellBottomMargin = 0;
-  nscoord cellSpacing = aState.tableFrame->GetCellSpacing();
+  nscoord cellSpacing = aReflowState.tableFrame->GetCellSpacing();
   PRInt32 cellColSpan=1;  // must be defined here so it's set properly for non-cell kids
   if (PR_TRUE==gsDebug) printf("%p: RR\n", this);
   // Reflow each of our existing cell frames
@@ -421,7 +439,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
     if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
     {
       nsMargin kidMargin;
-      aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
+      aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame,kidMargin);
       if (kidMargin.top > maxCellTopMargin)
         maxCellTopMargin = kidMargin.top;
       if (kidMargin.bottom > maxCellBottomMargin)
@@ -434,31 +452,31 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
       { // if this cell is not immediately adjacent to the previous cell, factor in missing col info
         for (PRInt32 colIndex=prevColIndex+1; colIndexGetColumnWidth(colIndex);
-          aState.x += cellSpacing;
+          aReflowState.x += aReflowState.tableFrame->GetColumnWidth(colIndex);
+          aReflowState.x += cellSpacing;
           if (PR_TRUE==gsDebug)
-            printf("  in loop, aState.x set to %d from cellSpacing %d and col width\n", 
-                    aState.x, aState.tableFrame->GetColumnWidth(colIndex), cellSpacing);
+            printf("  in loop, aReflowState.x set to %d from cellSpacing %d and col width\n", 
+                    aReflowState.x, aReflowState.tableFrame->GetColumnWidth(colIndex), cellSpacing);
         }
       }
-      aState.x += cellSpacing;
-      if (PR_TRUE==gsDebug) printf("  past loop, aState.x set to %d\n", aState.x);
+      aReflowState.x += cellSpacing;
+      if (PR_TRUE==gsDebug) printf("  past loop, aReflowState.x set to %d\n", aReflowState.x);
 
       // at this point, we know the column widths.  
       // so we get the avail width from the known column widths
-      cellColSpan = aState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
+      cellColSpan = aReflowState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
                                                                    ((nsTableCellFrame *)kidFrame));
       nscoord availWidth = 0;
       for (PRInt32 numColSpan=0; numColSpanGetColumnWidth(cellColIndex+numColSpan);
+        availWidth += aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
         if (numColSpan != 0)
         {
           availWidth += cellSpacing;
         }
         if (PR_TRUE==gsDebug) 
           printf("  in loop, availWidth set to %d from colIndex %d width %d and cellSpacing\n", 
-                  availWidth, cellColIndex, aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan), cellSpacing);
+                  availWidth, cellColIndex, aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan), cellSpacing);
       }
       if (PR_TRUE==gsDebug) printf("  availWidth for this cell is %d\n", availWidth);
 
@@ -478,7 +496,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
 
         // Reflow the child
         nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
-                                         aState.reflowState, kidAvailSize,
+                                         aReflowState.reflowState, kidAvailSize,
                                          eReflowReason_Resize);
         if (gsDebug) printf ("%p RR: avail=%d\n", this, availWidth);
         nsReflowStatus status;
@@ -545,12 +563,12 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
       // end special Nav4 compatibility code
 
       // Place the child
-      nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
+      nsRect kidRect (aReflowState.x, kidMargin.top, cellWidth, cellHeight);
 
-      PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
+      PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
                  pKidMaxElementSize);
 
-      if (PR_TRUE==gsDebug) printf("  past PlaceChild, aState.x set to %d\n", aState.x);
+      if (PR_TRUE==gsDebug) printf("  past PlaceChild, aReflowState.x set to %d\n", aReflowState.x);
     }
 
     // Get the next child
@@ -558,27 +576,27 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
     // if this was the last child, and it had a colspan>1, add in the cellSpacing for the colspan
     // if the last kid wasn't a colspan, then we still have the colspan of the last real cell
     if ((nsnull==kidFrame) && (cellColSpan>1))
-      aState.x += cellSpacing;
+      aReflowState.x += cellSpacing;
   }
 
-  SetMaxChildHeight(aState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin);  // remember height of tallest child who doesn't have a row span
+  SetMaxChildHeight(aReflowState.maxCellHeight,maxCellTopMargin, maxCellBottomMargin);  // remember height of tallest child who doesn't have a row span
 
   // Return our desired size. Note that our desired width is just whatever width
   // we were given by the row group frame
-  aDesiredSize.width = aState.x;
-  aDesiredSize.height = aState.maxCellVertSpace;  
+  aDesiredSize.width = aReflowState.x;
+  aDesiredSize.height = aReflowState.maxCellVertSpace;  
 
   if (gsDebug)
     printf("rr -- row %p width = %d from maxSize %d\n", 
-           this, aDesiredSize.width, aState.reflowState.maxSize.width);
+           this, aDesiredSize.width, aReflowState.reflowState.maxSize.width);
   
-  if (aDesiredSize.width > aState.reflowState.maxSize.width) 
+  if (aDesiredSize.width > aReflowState.reflowState.maxSize.width) 
   {
     printf ("%p error case, desired width = %d, maxSize=%d\n",
-            this, aDesiredSize.width, aState.reflowState.maxSize.width);
+            this, aDesiredSize.width, aReflowState.reflowState.maxSize.width);
     fflush (stdout);
   }
-  NS_ASSERTION(aDesiredSize.width <= aState.reflowState.maxSize.width, "row calculated to be too wide.");
+  NS_ASSERTION(aDesiredSize.width <= aReflowState.reflowState.maxSize.width, "row calculated to be too wide.");
   return NS_OK;
 }
 
@@ -588,7 +606,7 @@ nsresult nsTableRowFrame::ResizeReflow(nsIPresContext&  aPresContext,
  */
 nsresult
 nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
-                               RowReflowState&  aState,
+                               RowReflowState&  aReflowState,
                                nsHTMLReflowMetrics& aDesiredSize)
 {
   // Place our children, one at a time, until we are out of children
@@ -622,7 +640,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       nsMargin  margin;
       nscoord   topMargin = 0;
 
-      if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
+      if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, margin) == NS_OK)
       {
         topMargin = margin.top;
       }
@@ -647,7 +665,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       }
 
       nsHTMLReflowState kidReflowState(aPresContext, kidFrame,
-                                       aState.reflowState, kidAvailSize,
+                                       aReflowState.reflowState, kidAvailSize,
                                        eReflowReason_Initial);
 
       if (gsDebug) printf ("%p InitR: avail=%d\n", this, kidAvailSize.width);
@@ -677,17 +695,17 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
       // Place the child
       x += margin.left;
       nsRect kidRect(x, topMargin, kidSize.width, kidSize.height);
-      PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
+      PlaceChild(aPresContext, aReflowState, kidFrame, kidRect, aDesiredSize.maxElementSize,
                  &kidMaxElementSize);
       x += kidSize.width + margin.right;
     }
   }
 
-  SetMaxChildHeight(aState.maxCellHeight, maxTopMargin, maxBottomMargin);  // remember height of tallest child who doesn't have a row span
+  SetMaxChildHeight(aReflowState.maxCellHeight, maxTopMargin, maxBottomMargin);  // remember height of tallest child who doesn't have a row span
 
   // Return our desired size
   aDesiredSize.width = x;
-  aDesiredSize.height = aState.maxCellVertSpace;   
+  aDesiredSize.height = aReflowState.maxCellVertSpace;   
 
   return result;
 }
@@ -700,7 +718,7 @@ nsTableRowFrame::InitialReflow(nsIPresContext&  aPresContext,
 // - maxVertCellSpace
 // - x
 nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
-                                       RowReflowState& aState,
+                                       RowReflowState& aReflowState,
                                        nsIFrame*       aKidFrame,
                                        nscoord&        aMaxCellTopMargin,
                                        nscoord&        aMaxCellBottomMargin)
@@ -710,8 +728,8 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
   // Walk the list of children looking for aKidFrame. While we're at
   // it get the maxCellHeight and maxVertCellSpace for all the
   // frames except aKidFrame
-//  nsIFrame* prevKidFrame = nsnull;
-  for (nsIFrame* frame = mFirstChild; nsnull != frame;) {
+  for (nsIFrame* frame = mFirstChild; nsnull != frame;) 
+  {
     const nsStyleDisplay *kidDisplay;
     frame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)kidDisplay));
     if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
@@ -719,13 +737,13 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
       if (frame != aKidFrame) {
         // Update the max top and bottom margins
         nsMargin       kidMargin;
-        aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, kidMargin);
+        aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, kidMargin);
         if (kidMargin.top > aMaxCellTopMargin)
           aMaxCellTopMargin = kidMargin.top;
         if (kidMargin.bottom > aMaxCellBottomMargin)
           aMaxCellBottomMargin = kidMargin.bottom;
 
-        PRInt32 rowSpan = aState.tableFrame->GetEffectiveRowSpan(mRowIndex, ((nsTableCellFrame *)frame));
+        PRInt32 rowSpan = aReflowState.tableFrame->GetEffectiveRowSpan(mRowIndex, ((nsTableCellFrame *)frame));
         if (mMinRowSpan == rowSpan) {
           // Get the cell's desired height the last time it was reflowed
           nsSize  desiredSize = ((nsTableCellFrame *)frame)->GetDesiredSize();
@@ -751,18 +769,18 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
             desiredSize.height = specifiedHeight;
         
           // Update maxCellHeight
-          if (desiredSize.height > aState.maxCellHeight) {
-            aState.maxCellHeight = desiredSize.height;
+          if (desiredSize.height > aReflowState.maxCellHeight) {
+            aReflowState.maxCellHeight = desiredSize.height;
           }
   
           // Update maxCellVertHeight
           nsMargin margin;
     
-          if (aState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
+          if (aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)frame, margin) == NS_OK)
           {
             nscoord height = desiredSize.height + margin.top + margin.bottom;
-            if (height > aState.maxCellVertSpace) {
-              aState.maxCellVertSpace = height;
+            if (height > aReflowState.maxCellVertSpace) {
+              aReflowState.maxCellVertSpace = height;
             }
           }
         }
@@ -775,162 +793,417 @@ nsresult nsTableRowFrame::RecoverState(nsIPresContext& aPresContext,
       }
     }
 
-    // Remember the frame that precedes aKidFrame
-//    prevKidFrame = frame;
     frame->GetNextSibling(frame);
   }
 
   // Update the running x-offset based on the frame's current x-origin
   nsPoint origin;
   aKidFrame->GetOrigin(origin);
-  aState.x = origin.x;
+  aReflowState.x = origin.x;
 
   return NS_OK;
 }
 
-nsresult nsTableRowFrame::IncrementalReflow(nsIPresContext&  aPresContext,
-                                            RowReflowState&  aState,
-                                            nsHTMLReflowMetrics& aDesiredSize)
+
+
+NS_METHOD nsTableRowFrame::IncrementalReflow(nsIPresContext&       aPresContext,
+                                             nsHTMLReflowMetrics&  aDesiredSize,
+                                             RowReflowState& aReflowState,
+                                             nsReflowStatus&       aStatus)
 {
-  nsresult  status;
+  if (PR_TRUE==gsDebugIR) printf("\nTRF IR: IncrementalReflow\n");
+  nsresult  rv = NS_OK;
 
-  // XXX Deal with the case where the reflow command is targeted at us
-  nsIFrame* target;
-  aState.reflowState.reflowCommand->GetTarget(target);
-  if (this == target) {
-    NS_NOTYETIMPLEMENTED("unexpected reflow command");
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  // Get the next frame in the reflow chain
-  nsIFrame* kidFrame;
-  aState.reflowState.reflowCommand->GetNext(kidFrame);
-
-  // Recover our reflow state
-  nscoord maxCellTopMargin, maxCellBottomMargin;
-  RecoverState(aPresContext, aState, kidFrame, maxCellTopMargin, maxCellBottomMargin);
-
-  // Get the frame's margins
-  nsMargin  kidMargin;
-  aState.tableFrame->GetCellMarginData((nsTableCellFrame *)kidFrame, kidMargin);
-  if (kidMargin.top > maxCellTopMargin)
-    maxCellTopMargin = kidMargin.top;
-  if (kidMargin.bottom > maxCellBottomMargin)
-    maxCellBottomMargin = kidMargin.bottom;
-
-  // At this point, we know the column widths. Get the available width
-  // from the known column widths
-  PRInt32 cellColIndex = ((nsTableCellFrame *)kidFrame)->GetColIndex();
-  PRInt32 cellColSpan = aState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)kidFrame)->GetColIndex(),
-                                                                 ((nsTableCellFrame *)kidFrame));
-  nscoord availWidth = 0;
-  for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
+  // determine if this frame is the target or not
+  nsIFrame *target=nsnull;
+  rv = aReflowState.reflowState.reflowCommand->GetTarget(target);
+  if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
   {
-    availWidth += aState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
-    if (0GetNext(nextFrame);
+      rv = IR_TargetIsChild(aPresContext, aDesiredSize, aReflowState, aStatus, nextFrame);
     }
   }
-
-  // Always let the cell be as high as it wants. We ignore the height that's
-  // passed in and always place the entire row. Let the row group decide
-  // whether we fit or wehther the entire row is pushed
-  nsSize  kidAvailSize(availWidth, NS_UNCONSTRAINEDSIZE);
-
-  // Pass along the reflow command
-  nsSize          kidMaxElementSize;
-  nsHTMLReflowMetrics desiredSize(&kidMaxElementSize);
-  nsHTMLReflowState kidReflowState(aPresContext, kidFrame, aState.reflowState,
-                                   kidAvailSize);
-
-  // XXX Unfortunately we need to reflow the child several times.
-  // The first time is for the incremental reflow command. We can't pass in
-  // a max width of NS_UNCONSTRAINEDSIZE, because the max width must match
-  // the width of the previous reflow...
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-
-  // Now do the regular pass 1 reflow and gather the max width and max element
-  // size.
-  // XXX It would be nice if we could skip this step and the next step if the
-  // column width isn't dependent on the max cell width...
-  kidReflowState.reason = eReflowReason_Resize;
-  kidReflowState.reflowCommand = nsnull;
-  kidReflowState.maxSize.width = NS_UNCONSTRAINEDSIZE;
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-  if (gsDebug) 
-      printf ("TR %p for cell %p Incremental Reflow: desired=%d, MES=%d\n", 
-             this, kidFrame, desiredSize.width, kidMaxElementSize.width);
-  // Update the cell layout data.
-  //XXX: this is a hack, shouldn't it be the case that a min size is 
-  //     never larger than a desired size?
-  if (kidMaxElementSize.width>desiredSize.width)
-    desiredSize.width = kidMaxElementSize.width;
-  if (kidMaxElementSize.height>desiredSize.height)
-    desiredSize.height = kidMaxElementSize.height;
-  ((nsTableCellFrame *)kidFrame)->SetPass1DesiredSize(desiredSize);
-  ((nsTableCellFrame *)kidFrame)->SetPass1MaxElementSize(kidMaxElementSize);
-  
-  // Now reflow the cell again this time constraining the width
-  // XXX Ignore for now the possibility that the column width has changed...
-  kidReflowState.maxSize.width = availWidth;
-  ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, status);
-  
-  // Place the child after taking into account it's margin and attributes
-  // XXX We need to ask the table (or the table layout strategy) if the column
-  // widths have changed. If so, we just bail and return a status indicating
-  // what happened and let the table reflow all the table cells...
-  nscoord specifiedHeight = 0;
-  nscoord cellHeight = desiredSize.height;
-  nsIStyleContextPtr kidSC;
-  kidFrame->GetStyleContext(&aPresContext, kidSC.AssignRef());
-  const nsStylePosition* kidPosition = (const nsStylePosition*)
-    kidSC->GetStyleData(eStyleStruct_Position);
-  switch (kidPosition->mHeight.GetUnit()) {
-  case eStyleUnit_Coord:
-    specifiedHeight = kidPosition->mHeight.GetCoordValue();
-    break;
-
-  case eStyleUnit_Inherit:
-    // XXX for now, do nothing
-  default:
-  case eStyleUnit_Auto:
-    break;
-  }
-  if (specifiedHeight>cellHeight)
-    cellHeight = specifiedHeight;
-
-  nscoord cellWidth = desiredSize.width;
-  // begin special Nav4 compatibility code
-  if (0==cellWidth)
-  {
-    cellWidth = aState.tableFrame->GetColumnWidth(cellColIndex);
-  }
-  // end special Nav4 compatibility code
-
-  // Now place the child
-  nsRect kidRect (aState.x, kidMargin.top, cellWidth, cellHeight);
-
-  PlaceChild(aPresContext, aState, kidFrame, kidRect, aDesiredSize.maxElementSize,
-             &kidMaxElementSize);
-
-  SetMaxChildHeight(aState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
-
-  // Return our desired size. Note that our desired width is just whatever width
-  // we were given by the row group frame
-  aDesiredSize.width = aState.availSize.width;
-  aDesiredSize.height = aState.maxCellVertSpace;   
-
-  if (gsDebug)
-    printf("incr -- row %p width = %d MES=%d from maxSize %d\n", 
-           this, aDesiredSize.width, aDesiredSize.maxElementSize->width,
-           aState.reflowState.maxSize.width);
-
-  return status;
+  return rv;
 }
 
+NS_METHOD nsTableRowFrame::IR_TargetIsMe(nsIPresContext&      aPresContext,
+                                         nsHTMLReflowMetrics& aDesiredSize,
+                                         RowReflowState&      aReflowState,
+                                         nsReflowStatus&      aStatus)
+{
+  nsresult rv = NS_FRAME_COMPLETE;
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  nsIFrame *objectFrame;
+  aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (PR_TRUE==gsDebugIR) printf("TRF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
+  switch (type)
+  {
+  case nsIReflowCommand::FrameInserted :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                           objectFrame, PR_FALSE);
+    }
+    else
+    {
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+
+  /*
+  case nsIReflowCommand::FrameReplaced :
+
+  */
+
+  case nsIReflowCommand::FrameRemoved :
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+    {
+      rv = IR_CellRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                          objectFrame);
+    }
+    else
+    {
+      rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                  objectFrame);
+    }
+    break;
+
+  case nsIReflowCommand::StyleChanged :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: StyleChanged not implemented.\n");
+    break;
+
+  case nsIReflowCommand::ContentChanged :
+    NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
+    rv = NS_ERROR_ILLEGAL_VALUE;
+    break;
+  
+  case nsIReflowCommand::PullupReflow:
+  case nsIReflowCommand::PushReflow:
+  case nsIReflowCommand::CheckPullupReflow :
+  case nsIReflowCommand::UserDefined :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: reflow command not implemented.\n");
+    break;
+  }
+
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_CellInserted(nsIPresContext&      aPresContext,
+                                           nsHTMLReflowMetrics& aDesiredSize,
+                                           RowReflowState&      aReflowState,
+                                           nsReflowStatus&      aStatus,
+                                           nsIFrame *           aInsertedFrame,
+                                           PRBool               aReplace)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_DidAppendCell(nsTableRowFrame *aRowFrame)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableRowFrame::IR_CellAppended(nsIPresContext&      aPresContext,
+                                           nsHTMLReflowMetrics& aDesiredSize,
+                                           RowReflowState&      aReflowState,
+                                           nsReflowStatus&      aStatus,
+                                           nsIFrame *           aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  nsIFrame *lastRow = nsnull;
+  while (nsnull!=nextChild)
+  {
+    // remember the last child that is really a cell
+    const nsStyleDisplay *childDisplay;
+    nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+      lastRow = nextChild;
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  aReflowState.tableFrame->InvalidateFirstPassCache();
+  // the table will see that it's cached info is bogus and rebuild the cell map,
+  // and do a reflow
+
+#if 0
+  // find the col index of the new cell
+  
+  // account for the new cell 
+  nsresult rv = DidAppendCell((nsTableCellFrame*)aAppendedFrame);
+
+  // need to increment the row index of all subsequent rows
+#endif 
+
+  return rv;
+}
+
+NS_METHOD nsTableRowFrame::IR_CellRemoved(nsIPresContext&      aPresContext,
+                                          nsHTMLReflowMetrics& aDesiredSize,
+                                          RowReflowState&      aReflowState,
+                                          nsReflowStatus&      aStatus,
+                                          nsIFrame *           aDeletedFrame)
+{
+  nsresult rv=NS_OK;
+  return rv;
+}
+
+//XXX: handle aReplace
+NS_METHOD nsTableRowFrame::IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                                   nsHTMLReflowMetrics& aDesiredSize,
+                                                   RowReflowState& aReflowState,
+                                                   nsReflowStatus&      aStatus,
+                                                   nsIFrame *           aInsertedFrame,
+                                                   PRBool               aReplace)
+{
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  // we have a generic frame that gets inserted but doesn't effect reflow
+  // hook it up then ignore it
+  if (nsIReflowCommand::FrameAppended==type)
+  { // frameAppended reflow -- find the last child and make aInsertedFrame its next sibling
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameAppended adding unknown frame type.\n");
+    nsIFrame *lastChild=mFirstChild;
+    nsIFrame *nextChild=mFirstChild;
+    while (nsnull!=nextChild)
+    {
+      lastChild=nextChild;
+      nextChild->GetNextSibling(nextChild);
+    }
+    if (nsnull==lastChild)
+      mFirstChild = aInsertedFrame;
+    else
+      lastChild->SetNextSibling(aInsertedFrame);
+  }
+  else
+  { // frameInserted reflow -- hook up aInsertedFrame as prevSibling's next sibling, 
+    // and be sure to hook in aInsertedFrame's nextSibling (from prevSibling)
+    if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameInserted adding unknown frame type.\n");
+    nsIFrame *prevSibling=nsnull;
+    nsresult rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
+    if (NS_SUCCEEDED(rv) && (nsnull!=prevSibling))
+    {
+      nsIFrame *nextSibling=nsnull;
+      prevSibling->GetNextSibling(nextSibling);
+      prevSibling->SetNextSibling(aInsertedFrame);
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+    else
+    {
+      nsIFrame *nextSibling=nsnull;
+      if (nsnull!=mFirstChild)
+        mFirstChild->GetNextSibling(nextSibling);
+      mFirstChild = aInsertedFrame;
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+  }
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowFrame::IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                                  nsHTMLReflowMetrics& aDesiredSize,
+                                                  RowReflowState&      aReflowState,
+                                                  nsReflowStatus&      aStatus,
+                                                  nsIFrame *           aRemovedFrame)
+{
+  // we have a generic frame that gets removed but doesn't effect reflow
+  // unhook it then ignore it
+  if (PR_TRUE==gsDebugIR) printf("TRF IR: FrameRemoved removing unknown frame type.\n");
+  nsIFrame *prevChild=nsnull;
+  nsIFrame *nextChild=mFirstChild;
+  while (nextChild!=aRemovedFrame)
+  {
+    prevChild=nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }  
+  nextChild=nsnull;
+  aRemovedFrame->GetNextSibling(nextChild);
+  if (nsnull==prevChild)  // objectFrame was first child
+    mFirstChild = nextChild;
+  else
+    prevChild->SetNextSibling(nextChild);
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowFrame::IR_TargetIsChild(nsIPresContext&      aPresContext,
+                                            nsHTMLReflowMetrics& aDesiredSize,
+                                            RowReflowState&      aReflowState,
+                                            nsReflowStatus&      aStatus,
+                                            nsIFrame *           aNextFrame)
+
+{
+  nsresult  rv;
+
+  const nsStyleDisplay *childDisplay;
+  aNextFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (NS_STYLE_DISPLAY_TABLE_CELL == childDisplay->mDisplay)
+  {
+    // Recover our reflow state
+    nscoord maxCellTopMargin, maxCellBottomMargin;
+    RecoverState(aPresContext, aReflowState, aNextFrame, maxCellTopMargin, maxCellBottomMargin);
+
+    // Get the frame's margins
+    nsMargin  kidMargin;
+    aReflowState.tableFrame->GetCellMarginData((nsTableCellFrame *)aNextFrame, kidMargin);
+    if (kidMargin.top > maxCellTopMargin)
+      maxCellTopMargin = kidMargin.top;
+    if (kidMargin.bottom > maxCellBottomMargin)
+      maxCellBottomMargin = kidMargin.bottom;
+
+    // At this point, we know the column widths. Get the available width
+    // from the known column widths
+    PRInt32 cellColIndex = ((nsTableCellFrame *)aNextFrame)->GetColIndex();
+    PRInt32 cellColSpan = aReflowState.tableFrame->GetEffectiveColSpan(((nsTableCellFrame *)aNextFrame)->GetColIndex(),
+                                                                   ((nsTableCellFrame *)aNextFrame));
+    nscoord availWidth = 0;
+    for (PRInt32 numColSpan = 0; numColSpan < cellColSpan; numColSpan++)
+    {
+      availWidth += aReflowState.tableFrame->GetColumnWidth(cellColIndex+numColSpan);
+      if (0desiredSize.width)
+      desiredSize.width = kidMaxElementSize.width;
+    if (kidMaxElementSize.height>desiredSize.height)
+      desiredSize.height = kidMaxElementSize.height;
+    ((nsTableCellFrame *)aNextFrame)->SetPass1DesiredSize(desiredSize);
+    ((nsTableCellFrame *)aNextFrame)->SetPass1MaxElementSize(kidMaxElementSize);
+  
+    // Now reflow the cell again this time constraining the width
+    // XXX Ignore for now the possibility that the column width has changed...
+    kidReflowState.maxSize.width = availWidth;
+    rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+  
+    // Place the child after taking into account it's margin and attributes
+    // XXX We need to ask the table (or the table layout strategy) if the column
+    // widths have changed. If so, we just bail and return a status indicating
+    // what happened and let the table reflow all the table cells...
+    nscoord specifiedHeight = 0;
+    nscoord cellHeight = desiredSize.height;
+    nsIStyleContextPtr kidSC;
+    aNextFrame->GetStyleContext(&aPresContext, kidSC.AssignRef());
+    const nsStylePosition* kidPosition = (const nsStylePosition*)
+      kidSC->GetStyleData(eStyleStruct_Position);
+    switch (kidPosition->mHeight.GetUnit()) {
+    case eStyleUnit_Coord:
+      specifiedHeight = kidPosition->mHeight.GetCoordValue();
+      break;
+
+    case eStyleUnit_Inherit:
+      // XXX for now, do nothing
+    default:
+    case eStyleUnit_Auto:
+      break;
+    }
+    if (specifiedHeight>cellHeight)
+      cellHeight = specifiedHeight;
+
+    nscoord cellWidth = desiredSize.width;
+    // begin special Nav4 compatibility code
+    if (0==cellWidth)
+    {
+      cellWidth = aReflowState.tableFrame->GetColumnWidth(cellColIndex);
+    }
+    // end special Nav4 compatibility code
+
+    // Now place the child
+    nsRect kidRect (aReflowState.x, kidMargin.top, cellWidth, cellHeight);
+
+    PlaceChild(aPresContext, aReflowState, aNextFrame, kidRect, aDesiredSize.maxElementSize,
+               &kidMaxElementSize);
+
+    SetMaxChildHeight(aReflowState.maxCellHeight, maxCellTopMargin, maxCellBottomMargin);
+
+    // Return our desired size. Note that our desired width is just whatever width
+    // we were given by the row group frame
+    aDesiredSize.width = aReflowState.availSize.width;
+    aDesiredSize.height = aReflowState.maxCellVertSpace;   
+
+    if (gsDebug)
+      printf("incr -- row %p width = %d MES=%d from maxSize %d\n", 
+             this, aDesiredSize.width, aDesiredSize.maxElementSize->width,
+             aReflowState.reflowState.maxSize.width);
+  }
+  else
+  { // pass reflow to unknown frame child
+    // aDesiredSize does not change
+  }
+  return rv;
+}
+
+
 /** Layout the entire row.
   * This method stacks cells horizontally according to HTML 4.0 rules.
   */
@@ -940,45 +1213,46 @@ nsTableRowFrame::Reflow(nsIPresContext&          aPresContext,
                         const nsHTMLReflowState& aReflowState,
                         nsReflowStatus&          aStatus)
 {
+  nsresult rv=NS_OK;
   if (gsDebug==PR_TRUE)
     printf("nsTableRowFrame::Reflow - aMaxSize = %d, %d\n",
             aReflowState.maxSize.width, aReflowState.maxSize.height);
 
-  // Initialize 'out' parameters
+  // Initialize 'out' parameters (aStatus set below, undefined if rv returns an error)
   if (nsnull != aDesiredSize.maxElementSize) {
     aDesiredSize.maxElementSize->width = 0;
     aDesiredSize.maxElementSize->height = 0;
   }
-  aStatus = NS_FRAME_COMPLETE;  // we're never continued
 
   // Initialize our internal data
   ResetMaxChildHeight();
 
-  // Initialize our automatic state object
-  nsTableFrame* tableFrame;
-  mContentParent->GetContentParent((nsIFrame*&)tableFrame);
+  // Create a reflow state
+  nsTableFrame *tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if (NS_FAILED(rv) || nsnull==tableFrame)
+    return rv;
   RowReflowState state(aReflowState, tableFrame);
 
   // Do the reflow
-  nsresult  result;
-
   switch (aReflowState.reason) {
   case eReflowReason_Initial:
-    result = InitialReflow(aPresContext, state, aDesiredSize);
+    rv = InitialReflow(aPresContext, state, aDesiredSize);
     GetMinRowSpan(tableFrame);
     FixMinCellHeight(tableFrame);
     break;
 
   case eReflowReason_Resize:
-    result = ResizeReflow(aPresContext, state, aDesiredSize);
+    rv = ResizeReflow(aPresContext, state, aDesiredSize);
     break;
 
   case eReflowReason_Incremental:
-    result = IncrementalReflow(aPresContext, state, aDesiredSize);
+    rv = IncrementalReflow(aPresContext, aDesiredSize, state, aStatus);
     break;
-
   }
 
+  aStatus = NS_FRAME_COMPLETE;  // we're never continued
+
   if (gsDebug==PR_TRUE) 
   {
     if (nsnull!=aDesiredSize.maxElementSize)
@@ -992,7 +1266,7 @@ nsTableRowFrame::Reflow(nsIPresContext&          aPresContext,
              aDesiredSize.width, aDesiredSize.height);
   }
 
-  return result;
+  return rv;
 }
 
 NS_METHOD
diff --git a/mozilla/layout/tables/nsTableRowFrame.h b/mozilla/layout/tables/nsTableRowFrame.h
index 43e6d0cd3f8..51d6d09debc 100644
--- a/mozilla/layout/tables/nsTableRowFrame.h
+++ b/mozilla/layout/tables/nsTableRowFrame.h
@@ -38,8 +38,13 @@ struct RowReflowState;
 class nsTableRowFrame : public nsContainerFrame
 {
 public:
-  /** Initialization procedure */
-  void Init(PRInt32 aRowIndex);
+  /** Initialization of frame as a row */
+  void InitRowData(PRInt32 aRowIndex);
+
+  /** Initialization of data */
+  NS_IMETHOD InitChildren(PRInt32 aRowIndex=-1);
+
+  void ResetInitChildren();
 
   /** instantiate a new instance of nsTableRowFrame.
     * @param aResult    the new object is returned in this out-param
@@ -126,6 +131,64 @@ protected:
   /** destructor */
   virtual ~nsTableRowFrame();
 
+  /** Incremental Reflow attempts to do column balancing with the minimum number of reflow
+    * commands to child elements.  This is done by processing the reflow command,
+    * rebalancing column widths (if necessary), then comparing the resulting column widths
+    * to the prior column widths and reflowing only those cells that require a reflow.
+    *
+    * @see Reflow
+    */
+  NS_IMETHOD IncrementalReflow(nsIPresContext&       aPresContext,
+                               nsHTMLReflowMetrics&  aDesiredSize,
+                               RowReflowState&       aReflowState,
+                               nsReflowStatus&       aStatus);
+
+  NS_IMETHOD IR_TargetIsChild(nsIPresContext&      aPresContext,
+                              nsHTMLReflowMetrics& aDesiredSize,
+                              RowReflowState&      aReflowState,
+                              nsReflowStatus&      aStatus,
+                              nsIFrame *           aNextFrame);
+
+  NS_IMETHOD IR_TargetIsMe(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowReflowState&      aReflowState,
+                           nsReflowStatus&      aStatus);
+
+  NS_IMETHOD IR_CellInserted(nsIPresContext&     aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowReflowState&      aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aInsertedFrame,
+                            PRBool               aReplace);
+
+  NS_IMETHOD IR_CellAppended(nsIPresContext&     aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowReflowState&      aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aAppendedFrame);
+
+  NS_IMETHOD IR_DidAppendCell(nsTableRowFrame *aRowFrame);
+
+  NS_IMETHOD IR_CellRemoved(nsIPresContext&     aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowReflowState&      aReflowState,
+                           nsReflowStatus&      aStatus,
+                           nsIFrame *           aDeletedFrame);
+  
+  NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                     nsHTMLReflowMetrics& aDesiredSize,
+                                     RowReflowState&      aReflowState,
+                                     nsReflowStatus&      aStatus,
+                                     nsIFrame *           aInsertedFrame,
+                                     PRBool               aReplace);
+
+  NS_IMETHOD IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                    nsHTMLReflowMetrics& aDesiredSize,
+                                    RowReflowState&      aReflowState,
+                                    nsReflowStatus&      aStatus,
+                                    nsIFrame *           aDeletedFrame);
+
+
   // row-specific methods
 
   void GetMinRowSpan(nsTableFrame *aTableFrame);
@@ -180,11 +243,14 @@ private:
   nscoord  mCellMaxTopMargin;
   nscoord  mCellMaxBottomMargin;
   PRInt32  mMinRowSpan;           // the smallest row span among all my child cells
+  PRBool   mInitializedChildren;  // PR_TRUE if child cells have been initialized 
+                                  // (for now, that means "added to the table", and
+                                  // is NOT the same as having nsIFrame::Init() called.)
 
 };
 
 
-inline void nsTableRowFrame::Init(PRInt32 aRowIndex)
+inline void nsTableRowFrame::InitRowData(PRInt32 aRowIndex)
 {
   NS_ASSERTION(0<=aRowIndex, "bad param row index");
   mRowIndex = aRowIndex;
@@ -196,4 +262,7 @@ inline PRInt32 nsTableRowFrame::GetRowIndex() const
   return (mRowIndex);
 }
 
+inline void nsTableRowFrame::ResetInitChildren()
+{ mInitializedChildren=PR_FALSE; } 
+
 #endif
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
index b485bfec9c6..09df6333da1 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
@@ -30,10 +30,10 @@
 
 #ifdef NS_DEBUG
 static PRBool gsDebug = PR_FALSE;
-//#define NOISY
-//#define NOISY_FLOW
+static PRBool gsDebugIR = PR_FALSE;
 #else
 static const PRBool gsDebug = PR_FALSE;
+static const PRBool gsDebugIR = PR_FALSE;
 #endif
 
 NS_DEF_PTR(nsIStyleContext);
@@ -42,8 +42,8 @@ NS_DEF_PTR(nsIContent);
 /* ----------- RowGroupReflowState ---------- */
 
 struct RowGroupReflowState {
-  // Our reflow state
-  const nsHTMLReflowState& reflowState;
+  nsIPresContext& mPresContext;  // Our pres context
+  const nsHTMLReflowState& reflowState;  // Our reflow state
 
   // The body's available size (computed from the body's parent)
   nsSize availSize;
@@ -65,9 +65,10 @@ struct RowGroupReflowState {
   // Remember the height of the first row, because it's our maxElementHeight (plus header/footers)
   nscoord firstRowHeight;
 
-  RowGroupReflowState(nsIPresContext*          aPresContext,
+  RowGroupReflowState(nsIPresContext&          aPresContext,
                       const nsHTMLReflowState& aReflowState)
-    : reflowState(aReflowState)
+    : mPresContext(aPresContext),
+      reflowState(aReflowState)
   {
     availSize.width = reflowState.maxSize.width;
     availSize.height = reflowState.maxSize.height;
@@ -686,7 +687,7 @@ void nsTableRowGroupFrame::ShrinkWrapChildren(nsIPresContext* aPresContext,
   delete []rowHeights;
 }
 
-nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext*      aPresContext,
+nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext&      aPresContext,
                                                          RowGroupReflowState& aState,
                                                          nsIFrame*            aKidFrame,
                                                          nscoord              aDeltaY)
@@ -708,7 +709,7 @@ nsresult nsTableRowGroupFrame::AdjustSiblingsAfterReflow(nsIPresContext*      aP
       // XXX We need to send move notifications to the frame...
       nsIHTMLReflow* htmlReflow;
       if (NS_OK == kidFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) {
-        htmlReflow->WillReflow(*aPresContext);
+        htmlReflow->WillReflow(aPresContext);
       }
       kidFrame->MoveTo(origin.x, origin.y);
 
@@ -742,6 +743,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
                              const nsHTMLReflowState& aReflowState,
                              nsReflowStatus&          aStatus)
 {
+  nsresult rv=NS_OK;
   if (gsDebug==PR_TRUE)
     printf("nsTableRowGroupFrame::Reflow - aMaxSize = %d, %d\n",
             aReflowState.maxSize.width, aReflowState.maxSize.height);
@@ -752,45 +754,10 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
     aDesiredSize.maxElementSize->height = 0;
   }
 
-  RowGroupReflowState state(&aPresContext, aReflowState);
+  RowGroupReflowState state(aPresContext, aReflowState);
 
   if (eReflowReason_Incremental == aReflowState.reason) {
-    nsIFrame* target;
-    aReflowState.reflowCommand->GetTarget(target);
-    if (this == target) {
-      NS_NOTYETIMPLEMENTED("unexpected reflow command");
-    }
-
-    // XXX Recover state
-    // XXX Deal with the case where the reflow command is targeted at us
-    nsIFrame* kidFrame;
-    aReflowState.reflowCommand->GetNext(kidFrame);
-
-    // Remember the old rect
-    nsRect  oldKidRect;
-    kidFrame->GetRect(oldKidRect);
-
-    // Pass along the reflow command
-    // XXX Correctly compute the available space...
-    nsHTMLReflowState   kidReflowState(aPresContext, kidFrame,
-                                       aReflowState, aReflowState.maxSize);
-    nsHTMLReflowMetrics desiredSize(nsnull);
-
-    ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, aStatus);
-
-    // Resize the row frame
-    nsRect  kidRect;
-    kidFrame->GetRect(kidRect);
-    kidFrame->SizeTo(desiredSize.width, desiredSize.height);
-
-    // Adjust the frames that follow...
-    AdjustSiblingsAfterReflow(&aPresContext, state, kidFrame, desiredSize.height -
-                              oldKidRect.height);
-
-    // Return of desired size
-    aDesiredSize.width = aReflowState.maxSize.width;
-    aDesiredSize.height = state.y;
-
+    rv = IncrementalReflow(aPresContext, aDesiredSize, aReflowState, aStatus);
   } else {
     PRBool reflowMappedOK = PR_TRUE;
   
@@ -855,10 +822,329 @@ nsTableRowGroupFrame::Reflow(nsIPresContext&          aPresContext,
              aDesiredSize.width, aDesiredSize.height);
   }
 
-  return NS_OK;
+  return rv;
 
 }
 
+
+NS_METHOD nsTableRowGroupFrame::IncrementalReflow(nsIPresContext& aPresContext,
+                                                  nsHTMLReflowMetrics& aDesiredSize,
+                                                  const nsHTMLReflowState& aReflowState,
+                                                  nsReflowStatus& aStatus)
+{
+  if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IncrementalReflow\n");
+  nsresult  rv = NS_OK;
+
+  // create an inner table reflow state
+  RowGroupReflowState state(aPresContext, aReflowState);
+
+  // determine if this frame is the target or not
+  nsIFrame *target=nsnull;
+  rv = aReflowState.reflowCommand->GetTarget(target);
+  if ((PR_TRUE==NS_SUCCEEDED(rv)) && (nsnull!=target))
+  {
+    if (this==target)
+      rv = IR_TargetIsMe(aPresContext, aDesiredSize, state, aStatus);
+    else
+    {
+      // Get the next frame in the reflow chain
+      nsIFrame* nextFrame;
+      aReflowState.reflowCommand->GetNext(nextFrame);
+
+      // Recover our reflow state
+      //RecoverState(state, nextFrame);
+      rv = IR_TargetIsChild(aPresContext, aDesiredSize, state, aStatus, nextFrame);
+    }
+  }
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext&      aPresContext,
+                                              nsHTMLReflowMetrics& aDesiredSize,
+                                              RowGroupReflowState& aReflowState,
+                                              nsReflowStatus&      aStatus)
+{
+  nsresult rv = NS_FRAME_COMPLETE;
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  nsIFrame *objectFrame;
+  aReflowState.reflowState.reflowCommand->GetChildFrame(objectFrame); 
+  const nsStyleDisplay *childDisplay;
+  objectFrame->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+  if (PR_TRUE==gsDebugIR) printf("TRGF IR: IncrementalReflow_TargetIsMe with type=%d\n", type);
+  switch (type)
+  {
+  case nsIReflowCommand::FrameInserted :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                          objectFrame, PR_FALSE);
+    }
+    else
+    {
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+  
+  case nsIReflowCommand::FrameAppended :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowAppended(aPresContext, aDesiredSize, aReflowState, aStatus, objectFrame);
+    }
+    else
+    { // no optimization to be done for Unknown frame types, so just reuse the Inserted method
+      rv = IR_UnknownFrameInserted(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                   objectFrame, PR_FALSE);
+    }
+    break;
+
+  /*
+  case nsIReflowCommand::FrameReplaced :
+
+  */
+
+  case nsIReflowCommand::FrameRemoved :
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+    {
+      rv = IR_RowRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                         objectFrame);
+    }
+    else
+    {
+      rv = IR_UnknownFrameRemoved(aPresContext, aDesiredSize, aReflowState, aStatus, 
+                                  objectFrame);
+    }
+    break;
+
+  case nsIReflowCommand::StyleChanged :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: StyleChanged not implemented.\n");
+    break;
+
+  case nsIReflowCommand::ContentChanged :
+    NS_ASSERTION(PR_FALSE, "illegal reflow type: ContentChanged");
+    rv = NS_ERROR_ILLEGAL_VALUE;
+    break;
+  
+  case nsIReflowCommand::PullupReflow:
+  case nsIReflowCommand::PushReflow:
+  case nsIReflowCommand::CheckPullupReflow :
+  case nsIReflowCommand::UserDefined :
+    NS_NOTYETIMPLEMENTED("unimplemented reflow command type");
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: reflow command not implemented.\n");
+    break;
+  }
+
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_RowInserted(nsIPresContext&      aPresContext,
+                                               nsHTMLReflowMetrics& aDesiredSize,
+                                               RowGroupReflowState& aReflowState,
+                                               nsReflowStatus&      aStatus,
+                                               nsIFrame *           aInsertedFrame,
+                                               PRBool               aReplace)
+{
+  nsresult rv=NS_OK;
+  // inserting the rowgroup only effects reflow if the rowgroup includes at least one row
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_DidAppendRow(nsTableRowFrame *aRowFrame)
+{
+  nsresult rv=NS_OK;
+  /* need to make space in the cell map.  Remeber that row spans can't cross row groups
+     once the space is made, tell the row to initizalize its children.  
+     it will automatically find the row to initialize into.
+     but this is tough because a cell in aInsertedFrame could have a rowspan
+     which must be respected if a subsequent row is appended.
+  */
+  rv = aRowFrame->InitChildren();
+  return rv;
+}
+
+// since we know we're doing an append here, we can optimize
+NS_METHOD nsTableRowGroupFrame::IR_RowAppended(nsIPresContext&      aPresContext,
+                                               nsHTMLReflowMetrics& aDesiredSize,
+                                               RowGroupReflowState& aReflowState,
+                                               nsReflowStatus&      aStatus,
+                                               nsIFrame *           aAppendedFrame)
+{
+  nsresult rv=NS_OK;
+  // hook aAppendedFrame into the child list
+  nsIFrame *lastChild = mFirstChild;
+  nsIFrame *nextChild = lastChild;
+  nsIFrame *lastRow = nsnull;
+  while (nsnull!=nextChild)
+  {
+    // remember the last child that is really a row
+    const nsStyleDisplay *childDisplay;
+    nextChild->GetStyleData(eStyleStruct_Display, ((nsStyleStruct *&)childDisplay));
+    if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
+      lastRow = nextChild;
+    lastChild = nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }
+  if (nsnull==lastChild)
+    mFirstChild = aAppendedFrame;
+  else
+    lastChild->SetNextSibling(aAppendedFrame);
+
+  nsTableFrame *tableFrame=nsnull;
+  rv = nsTableFrame::GetTableFrame(this, tableFrame);
+  if (NS_FAILED(rv) || nsnull==tableFrame)
+    return rv;
+  tableFrame->InvalidateFirstPassCache();
+  // the table will see that it's cached info is bogus and rebuild the cell map,
+  // and do a reflow
+
+#if 0
+  // find the row index of the new row
+  PRInt32 newRowIndex=-1;
+  if (nsnull!=
+
+  lastChild=mFirstChild;
+  nextChild=lastChild;
+  while (nsnull!=nextChild)
+  {
+  }
+  // account for the cells in aAppendedFrame
+  nsresult rv = DidAppendRow((nsTableRowFrame*)aAppendedFrame, newRowIndex);
+
+  // need to increment the row index of all subsequent rows
+#endif 
+
+  return rv;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_RowRemoved(nsIPresContext&      aPresContext,
+                                              nsHTMLReflowMetrics& aDesiredSize,
+                                              RowGroupReflowState& aReflowState,
+                                              nsReflowStatus&      aStatus,
+                                              nsIFrame *           aDeletedFrame)
+{
+  nsresult rv;
+  return rv;
+}
+
+//XXX: handle aReplace
+NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                                        nsHTMLReflowMetrics& aDesiredSize,
+                                                        RowGroupReflowState& aReflowState,
+                                                        nsReflowStatus&      aStatus,
+                                                        nsIFrame *           aInsertedFrame,
+                                                        PRBool               aReplace)
+{
+  nsIReflowCommand::ReflowType type;
+  aReflowState.reflowState.reflowCommand->GetType(type);
+  // we have a generic frame that gets inserted but doesn't effect reflow
+  // hook it up then ignore it
+  if (nsIReflowCommand::FrameAppended==type)
+  { // frameAppended reflow -- find the last child and make aInsertedFrame its next sibling
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameAppended adding unknown frame type.\n");
+    nsIFrame *lastChild=mFirstChild;
+    nsIFrame *nextChild=mFirstChild;
+    while (nsnull!=nextChild)
+    {
+      lastChild=nextChild;
+      nextChild->GetNextSibling(nextChild);
+    }
+    if (nsnull==lastChild)
+      mFirstChild = aInsertedFrame;
+    else
+      lastChild->SetNextSibling(aInsertedFrame);
+  }
+  else
+  { // frameInserted reflow -- hook up aInsertedFrame as prevSibling's next sibling, 
+    // and be sure to hook in aInsertedFrame's nextSibling (from prevSibling)
+    if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameInserted adding unknown frame type.\n");
+    nsIFrame *prevSibling=nsnull;
+    nsresult rv = aReflowState.reflowState.reflowCommand->GetPrevSiblingFrame(prevSibling);
+    if (NS_SUCCEEDED(rv) && (nsnull!=prevSibling))
+    {
+      nsIFrame *nextSibling=nsnull;
+      prevSibling->GetNextSibling(nextSibling);
+      prevSibling->SetNextSibling(aInsertedFrame);
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+    else
+    {
+      nsIFrame *nextSibling=nsnull;
+      if (nsnull!=mFirstChild)
+        mFirstChild->GetNextSibling(nextSibling);
+      mFirstChild = aInsertedFrame;
+      aInsertedFrame->SetNextSibling(nextSibling);
+    }
+  }
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                                       nsHTMLReflowMetrics& aDesiredSize,
+                                                       RowGroupReflowState& aReflowState,
+                                                       nsReflowStatus&      aStatus,
+                                                       nsIFrame *           aRemovedFrame)
+{
+  // we have a generic frame that gets removed but doesn't effect reflow
+  // unhook it then ignore it
+  if (PR_TRUE==gsDebugIR) printf("TRGF IR: FrameRemoved removing unknown frame type.\n");
+  nsIFrame *prevChild=nsnull;
+  nsIFrame *nextChild=mFirstChild;
+  while (nextChild!=aRemovedFrame)
+  {
+    prevChild=nextChild;
+    nextChild->GetNextSibling(nextChild);
+  }  
+  nextChild=nsnull;
+  aRemovedFrame->GetNextSibling(nextChild);
+  if (nsnull==prevChild)  // objectFrame was first child
+    mFirstChild = nextChild;
+  else
+    prevChild->SetNextSibling(nextChild);
+  return NS_FRAME_COMPLETE;
+}
+
+NS_METHOD nsTableRowGroupFrame::IR_TargetIsChild(nsIPresContext&      aPresContext,
+                                                 nsHTMLReflowMetrics& aDesiredSize,
+                                                 RowGroupReflowState& aReflowState,
+                                                 nsReflowStatus&      aStatus,
+                                                 nsIFrame *           aNextFrame)
+
+{
+  nsresult rv;
+  if (PR_TRUE==gsDebugIR) printf("\nTRGF IR: IR_TargetIsChild\n");
+  // XXX Recover state
+
+  // Remember the old rect
+  nsRect  oldKidRect;
+  aNextFrame->GetRect(oldKidRect);
+
+  // Pass along the reflow command
+  // XXX Correctly compute the available space...
+  nsHTMLReflowState   kidReflowState(aPresContext, aNextFrame, aReflowState.reflowState, aReflowState.reflowState.maxSize);
+  nsHTMLReflowMetrics desiredSize(nsnull);
+
+  rv = ReflowChild(aNextFrame, aPresContext, desiredSize, kidReflowState, aStatus);
+
+  // Resize the row frame
+  nsRect  kidRect;
+  aNextFrame->GetRect(kidRect);
+  aNextFrame->SizeTo(desiredSize.width, desiredSize.height);
+
+  // Adjust the frames that follow...
+  AdjustSiblingsAfterReflow(aPresContext, aReflowState, aNextFrame, desiredSize.height -
+                            oldKidRect.height);
+
+  // Return of desired size
+  aDesiredSize.width = aReflowState.reflowState.maxSize.width;
+  aDesiredSize.height = aReflowState.y;
+
+  return rv;
+}
+
 NS_METHOD
 nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext&  aPresContext,
                                             nsIFrame*        aParent,
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.h b/mozilla/layout/tables/nsTableRowGroupFrame.h
index 309f7afa04a..302619e9315 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.h
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.h
@@ -22,6 +22,7 @@
 #include "nsContainerFrame.h"
 #include "nsIAtom.h"
 
+class nsTableRowFrame;
 struct RowGroupReflowState;
 
 /**
@@ -79,6 +80,65 @@ public:
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus& aStatus);
 
+  /** Incremental Reflow attempts to do column balancing with the minimum number of reflow
+    * commands to child elements.  This is done by processing the reflow command,
+    * rebalancing column widths (if necessary), then comparing the resulting column widths
+    * to the prior column widths and reflowing only those cells that require a reflow.
+    *
+    * @see Reflow
+    */
+  NS_IMETHOD IncrementalReflow(nsIPresContext&          aPresContext,
+                               nsHTMLReflowMetrics&     aDesiredSize,
+                               const nsHTMLReflowState& aReflowState,
+                               nsReflowStatus&          aStatus);
+
+  NS_IMETHOD IR_TargetIsChild(nsIPresContext&      aPresContext,
+                              nsHTMLReflowMetrics& aDesiredSize,
+                              RowGroupReflowState& aReflowState,
+                              nsReflowStatus&      aStatus,
+                              nsIFrame *           aNextFrame);
+
+  NS_IMETHOD IR_TargetIsMe(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowGroupReflowState& aReflowState,
+                           nsReflowStatus&      aStatus);
+
+  NS_IMETHOD IR_RowInserted(nsIPresContext&      aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowGroupReflowState& aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aInsertedFrame,
+                            PRBool               aReplace);
+
+  NS_IMETHOD IR_RowAppended(nsIPresContext&      aPresContext,
+                            nsHTMLReflowMetrics& aDesiredSize,
+                            RowGroupReflowState& aReflowState,
+                            nsReflowStatus&      aStatus,
+                            nsIFrame *           aAppendedFrame);
+
+  NS_IMETHOD IR_DidAppendRow(nsTableRowFrame *aRowFrame);
+
+  NS_IMETHOD IR_RowRemoved(nsIPresContext&      aPresContext,
+                           nsHTMLReflowMetrics& aDesiredSize,
+                           RowGroupReflowState& aReflowState,
+                           nsReflowStatus&      aStatus,
+                           nsIFrame *           aDeletedFrame);
+  
+  NS_IMETHOD IR_UnknownFrameInserted(nsIPresContext&      aPresContext,
+                                     nsHTMLReflowMetrics& aDesiredSize,
+                                     RowGroupReflowState& aReflowState,
+                                     nsReflowStatus&      aStatus,
+                                     nsIFrame *           aInsertedFrame,
+                                     PRBool               aReplace);
+
+  NS_IMETHOD IR_UnknownFrameRemoved(nsIPresContext&      aPresContext,
+                                    nsHTMLReflowMetrics& aDesiredSize,
+                                    RowGroupReflowState& aReflowState,
+                                    nsReflowStatus&      aStatus,
+                                    nsIFrame *           aDeletedFrame);
+
+
+
   /** @see nsContainerFrame::CreateContinuingFrame */
   NS_IMETHOD CreateContinuingFrame(nsIPresContext&  aPresContext,
                                    nsIFrame*        aParent,
@@ -111,11 +171,11 @@ protected:
   ~nsTableRowGroupFrame();
 
   nscoord GetTopMarginFor(nsIPresContext*      aCX,
-                          RowGroupReflowState& aState,
+                          RowGroupReflowState& aReflowState,
                           const nsMargin&      aKidMargin);
 
   void          PlaceChild( nsIPresContext*      aPresContext,
-                            RowGroupReflowState& aState,
+                            RowGroupReflowState& aReflowState,
                             nsIFrame*            aKidFrame,
                             const nsRect&        aKidRect,
                             nsSize*              aMaxElementSize,
@@ -124,8 +184,8 @@ protected:
   void ShrinkWrapChildren(nsIPresContext* aPresContext, 
                           nsHTMLReflowMetrics& aDesiredSize);
 
-  nsresult AdjustSiblingsAfterReflow(nsIPresContext*      aPresContext,
-                                     RowGroupReflowState& aState,
+  nsresult AdjustSiblingsAfterReflow(nsIPresContext&      aPresContext,
+                                     RowGroupReflowState& aReflowState,
                                      nsIFrame*            aKidFrame,
                                      nscoord              aDeltaY);
 
@@ -133,24 +193,24 @@ protected:
    * Reflow the frames we've already created
    *
    * @param   aPresContext presentation context to use
-   * @param   aState current inline state
+   * @param   aReflowState current inline state
    * @return  true if we successfully reflowed all the mapped children and false
    *            otherwise, e.g. we pushed children to the next in flow
    */
   PRBool        ReflowMappedChildren(nsIPresContext*      aPresContext,
-                                     RowGroupReflowState& aState,
+                                     RowGroupReflowState& aReflowState,
                                      nsSize*              aMaxElementSize);
 
   /**
    * Try and pull-up frames from our next-in-flow
    *
    * @param   aPresContext presentation context to use
-   * @param   aState current inline state
+   * @param   aReflowState current inline state
    * @return  true if we successfully pulled-up all the children and false
    *            otherwise, e.g. child didn't fit
    */
   PRBool        PullUpChildren(nsIPresContext*      aPresContext,
-                               RowGroupReflowState& aState,
+                               RowGroupReflowState& aReflowState,
                                nsSize*              aMaxElementSize);
 
 private: