diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp index 479f937abac..6ca032e720d 100644 --- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp +++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp @@ -306,7 +306,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths() PRBool cellGrantingWidth=PR_TRUE; for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; @@ -704,7 +704,7 @@ void BasicTableLayoutStrategy::SetMinAndMaxTableWidths() for (colIndex = 0; colIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); rowMinWidth += colInset; rowMaxWidth += colInset; if (nsnull==cellFrame) @@ -1053,7 +1053,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR { for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; @@ -1770,7 +1770,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState& { for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; diff --git a/mozilla/layout/html/table/src/nsCellMap.cpp b/mozilla/layout/html/table/src/nsCellMap.cpp index f782abc281f..d0238a36502 100644 --- a/mozilla/layout/html/table/src/nsCellMap.cpp +++ b/mozilla/layout/html/table/src/nsCellMap.cpp @@ -19,6 +19,7 @@ #include "nsVoidArray.h" #include "nsCellMap.h" #include "nsTableFrame.h" +#include "nsTableCellFrame.h" #ifdef NS_DEBUG static PRBool gsDebug = PR_FALSE; @@ -226,4 +227,187 @@ PRInt32 nsCellMap::GetNextAvailColIndex(PRInt32 aRowIndex, PRInt32 aColIndex) co return result; } +/** 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:
+ *
+  * TABLE
+  *   TR
+  *    TD ROWSPAN=2
+  *    TD
+  *   TR
+  *    TD
+  * 
+ * RowIsSpannedInto(0) returns PR_FALSE, and RowIsSpannedInto(1) returns PR_TRUE. + * @see RowHasSpanningCells + */ +// if computing this and related info gets expensive, we can easily +// cache it. The only thing to remember is to rebuild the cache +// whenever a row|col|cell is added/deleted, or a span attribute is changed. +PRBool nsCellMap::RowIsSpannedInto(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexmCell) + { // the cell at (aRowIndex, colIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realRowIndex = cell->GetRowIndex (); + if (realRowIndex!=aRowIndex) + { // the span is caused by a rowspan + result = PR_TRUE; + break; + } + } + } + } + return result; +} + +/** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD ROWSPAN=2
+  *    TD
+  *   TR
+  *    TD
+  * 
+ * RowHasSpanningCells(0) returns PR_TRUE, and RowHasSpanningCells(1) returns PR_FALSE. + * @see RowIsSpannedInto + */ +PRBool nsCellMap::RowHasSpanningCells(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexmCell) + { // the cell at (nextRowIndex, colIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realRowIndex = cell->GetRowIndex (); + if (realRowIndex!=nextRowIndex) + { // the span is caused by a rowspan + CellData *spanningCell = GetCellAt(aRowIndex, colIndex); + if (nsnull!=spanningCell) + { // there's really a cell at (aRowIndex, colIndex) + if (nsnull!=spanningCell->mCell) + { // aRowIndex is where the rowspan originated + result = PR_TRUE; + break; + } + } + } + } + } + } + } + return result; +} + + +/** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD COLSPAN=2
+  *    TD
+  *    TD
+  * 
+ * ColIsSpannedInto(0) returns PR_FALSE, ColIsSpannedInto(1) returns PR_TRUE, + * and ColIsSpannedInto(2) returns PR_FALSE. + * @see ColHasSpanningCells + */ +PRBool nsCellMap::ColIsSpannedInto(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexmCell) + { // the cell at (rowIndex, aColIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realColIndex = cell->GetColIndex (); + if (realColIndex!=aColIndex) + { // the span is caused by a colspan + result = PR_TRUE; + break; + } + } + } + } + return result; +} + +/** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD COLSPAN=2
+  *    TD
+  * 
+ * ColHasSpanningCells(0) returns PR_TRUE, and ColHasSpanningCells(1) returns PR_FALSE. + * @see ColIsSpannedInto + */ +PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexmCell) + { // the cell at (rowIndex, nextColIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realColIndex = cell->GetColIndex (); + if (realColIndex!=nextColIndex) + { // the span is caused by a colspan + CellData *spanningCell =GetCellAt(rowIndex, aColIndex); + if (nsnull!=spanningCell) + { // there's really a cell at (rowIndex, aColIndex) + if (nsnull!=spanningCell->mCell) + { // aCowIndex is where the cowspan originated + result = PR_TRUE; + break; + } + } + } + } + } + } + } + return result; +} + + diff --git a/mozilla/layout/html/table/src/nsCellMap.h b/mozilla/layout/html/table/src/nsCellMap.h index f83136f801d..e5e9a23f71b 100644 --- a/mozilla/layout/html/table/src/nsCellMap.h +++ b/mozilla/layout/html/table/src/nsCellMap.h @@ -44,7 +44,10 @@ protected: /** storage for rows */ nsVoidArray *mRows; - /** storage for CellData pointers */ + /** storage for min col span info, just an int that gives the smallest + * colspan for all cells originating in each column. If allocated, + * each entry must be >= 1. + */ PRInt32 *mMinColSpans; /** a cache of the column frames, by col index */ @@ -62,8 +65,8 @@ protected: public: /** constructor * @param aRows - initial number of rows - * @param aColumns - initial number of columns - */ + * @param aColumns - initial number of columns + */ nsCellMap(PRInt32 aRows, PRInt32 aColumns); /** destructor @@ -113,22 +116,69 @@ public: /** add a column frame to the list of column frames * column frames must be added in order - */ + */ void AppendColumnFrame(nsTableColFrame *aColFrame); - /** return PR_TRUE if aRowIndex has any cells with rowspan>1 contained - * within it (not just cells that are in the row, but cells that span - * into the row as well. - */ - PRBool RowImpactedBySpanningCell(PRInt32 aRowIndex); + /** 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:
+ *
+		* TABLE
+		*   TR
+		*    TD ROWSPAN=2
+		*    TD
+		*   TR
+		*    TD
+		* 
+ * RowIsSpannedInto(0) returns PR_FALSE, and RowIsSpannedInto(1) returns PR_TRUE. + * @see RowHasSpanningCells + */ + PRBool RowIsSpannedInto(PRInt32 aRowIndex); - /** return PR_TRUE if aColIndex has any cells with colspan>1 contained - * within it (not just cells that are in the col, but cells that span - * into the col as well. - */ - PRBool ColumnImpactedBySpanningCell(PRInt32 aColIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD ROWSPAN=2
+		*    TD
+		*   TR
+		*    TD
+		* 
+ * RowHasSpanningCells(0) returns PR_TRUE, and RowHasSpanningCells(1) returns PR_FALSE. + * @see RowIsSpannedInto + */ + PRBool RowHasSpanningCells(PRInt32 aRowIndex); - /** for debugging */ + /** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD COLSPAN=2
+		*    TD
+		*    TD
+		* 
+ * ColIsSpannedInto(0) returns PR_FALSE, ColIsSpannedInto(1) returns PR_TRUE, + * and ColIsSpannedInto(2) returns PR_FALSE. + * @see ColHasSpanningCells + */ + PRBool ColIsSpannedInto(PRInt32 aColIndex); + + /** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD COLSPAN=2
+		*    TD
+		* 
+ * ColHasSpanningCells(0) returns PR_TRUE, and ColHasSpanningCells(1) returns PR_FALSE. + * @see ColIsSpannedInto + */ + PRBool ColHasSpanningCells(PRInt32 aColIndex); + + + /** dump a representation of the cell map to stdout for debugging */ void DumpCellMap() const; }; diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index 108f3ae1dfb..89bcd8b5e6b 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -429,7 +429,7 @@ nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex) } // can return nsnull -nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) +nsTableCellFrame * nsTableFrame::GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) { nsTableCellFrame *result = nsnull; nsCellMap *cellMap = GetCellMap(); @@ -446,6 +446,73 @@ nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) return result; } +/** returns PR_TRUE if the row at aRowIndex has any cells that are the result + * of a row-spanning cell. + * @see nsCellMap::RowIsSpannedInto + */ +PRBool nsTableFrame::RowIsSpannedInto(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexRowIsSpannedInto(aRowIndex); + } + return result; +} + +/** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * @see nsCellMap::RowHasSpanningCells + */ +PRBool nsTableFrame::RowHasSpanningCells(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexRowHasSpanningCells(aRowIndex); + } + return result; +} + + +/** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. + * @see nsCellMap::ColIsSpannedInto + */ +PRBool nsTableFrame::ColIsSpannedInto(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexColIsSpannedInto(aColIndex); + } + return result; +} + +/** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * @see nsCellMap::ColHasSpanningCells + */ +PRBool nsTableFrame::ColHasSpanningCells(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexColHasSpanningCells(aColIndex); + } + return result; +} + // return the number of rows spanned by aCell starting at aRowIndex // note that this is different from just the rowspan of aCell // (that would be GetEffectiveRowSpan (indexOfRowThatContains_aCell, aCell) @@ -499,7 +566,17 @@ PRInt32 nsTableFrame::GetEffectiveColSpan (PRInt32 aColIndex, nsTableCellFrame * result -= (minColSpanForCol - 1); // minColSpanForCol is always at least 1 // and we want to treat default as 0 (no effect) } - +#ifdef NS_DEBUG + if (0>=result) + { + printf("ERROR!\n"); + DumpCellMap(); + printf("aColIndex=%d, cell->colIndex=%d\n", aColIndex, aCell->GetColIndex()); + printf("aCell->colSpan=%d\n", aCell->GetColSpan()); + printf("colCount=%d\n", mCellMap->GetColCount()); + } +#endif +NS_ASSERTION(0GetRowCount(); - PRInt32 cols = mCellMap->GetColCount(); - for (PRInt32 r = 0; r < rowCount; r++) + PRInt32 colCount = mCellMap->GetColCount(); + for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) { if (gsDebug==PR_TRUE) - { printf("row %d", r); + { printf("row %d", rowIndex); printf(": "); } - for (PRInt32 c = 0; c < cols; c++) + for (PRInt32 colIndex = 0; colIndex < colCount; colIndex++) { - CellData *cd =mCellMap->GetCellAt(r, c); + CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex); if (cd != nsnull) { if (cd->mCell != nsnull) { - printf("C%d,%d ", r, c); + printf("C%d,%d ", rowIndex, colIndex); printf(" "); } else @@ -931,8 +1008,18 @@ void nsTableFrame::DumpCellMap () else printf("---- "); } - printf("\n"); + PRBool spanners = RowHasSpanningCells(rowIndex); + PRBool spannedInto = RowIsSpannedInto(rowIndex); + printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F"); } + // output colspan info + for (PRInt32 colIndex=0; colIndexmRealCell = data; - if (gsDebug==PR_TRUE) printf(" null GetCellAt(%d, %d) so setting to spanData\n", workRow, workCol); + if (gsDebug==PR_TRUE) printf(" 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 GetCellAt(%d, %d) so setting to spanData\n", workRow, workCol); + if (gsDebug==PR_TRUE) printf(" 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; @@ -1623,6 +1710,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth) { + //DumpCellMap(); NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, "bad parent reflow state"); diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 32d0172386c..bd697b7852e 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -436,6 +436,7 @@ public: /* ----- Cell Map public methods ----- */ */ virtual PRInt32 GetRowCount(); + /** returns the number of columns in this table. */ virtual PRInt32 GetColCount(); /** adjust the col count for screwy table attributes. @@ -443,11 +444,39 @@ public: /* ----- Cell Map public methods ----- */ */ virtual void SetEffectiveColCount(); + /** return the column frame at colIndex. + * returns nsnull if the col frame has not yet been allocated, or if aColIndex is out of range + */ nsTableColFrame * GetColFrame(PRInt32 aColIndex); - nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex); + /** return the cell frame at aRowIndex, aColIndex. + * returns nsnull if the cell frame has not yet been allocated, + * or if aRowIndex or aColIndex is out of range + */ + nsTableCellFrame * GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that are the result + * of a row-spanning cell above it. + * @see nsCellMap::RowIsSpannedInto + */ + PRBool RowIsSpannedInto(PRInt32 aRowIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * that originate in aRowIndex. + * @see nsCellMap::RowHasSpanningCells + */ + PRBool RowHasSpanningCells(PRInt32 aRowIndex); + + /** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. + * @see nsCellMap::ColIsSpannedInto + */ + PRBool ColIsSpannedInto(PRInt32 aColIndex); + + /** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * @see nsCellMap::ColHasSpanningCells + */ + PRBool ColHasSpanningCells(PRInt32 aColIndex); private: void DebugPrintCount() const; // Debugging routine diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index 80188421cf5..76d49faca70 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -114,6 +114,11 @@ nsTableRowFrame::DidReflow(nsIPresContext& aPresContext, if (NS_FRAME_REFLOW_FINISHED == aStatus) { // Resize and re-align the cell frames based on our row height nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; + +// XXX + // every place in this module where we cast to nsTableCellFrame, + // we first have to check the display-type of the frame and skip non-cells. + nsTableCellFrame *cellFrame = (nsTableCellFrame*)mFirstChild; nsTableFrame* tableFrame; mContentParent->GetContentParent((nsIFrame*&)tableFrame); diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp index 479f937abac..6ca032e720d 100644 --- a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp +++ b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp @@ -306,7 +306,7 @@ PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths() PRBool cellGrantingWidth=PR_TRUE; for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; @@ -704,7 +704,7 @@ void BasicTableLayoutStrategy::SetMinAndMaxTableWidths() for (colIndex = 0; colIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); rowMinWidth += colInset; rowMaxWidth += colInset; if (nsnull==cellFrame) @@ -1053,7 +1053,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsTableFits(const nsReflowState& aR { for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; @@ -1770,7 +1770,7 @@ PRBool BasicTableLayoutStrategy::BalanceColumnsConstrained( const nsReflowState& { for (rowIndex = 0; rowIndexGetCellAt(rowIndex, colIndex); + nsTableCellFrame * cellFrame = mTableFrame->GetCellFrameAt(rowIndex, colIndex); if (nsnull==cellFrame) { // there is no cell in this row that corresponds to this column continue; diff --git a/mozilla/layout/tables/nsCellMap.cpp b/mozilla/layout/tables/nsCellMap.cpp index f782abc281f..d0238a36502 100644 --- a/mozilla/layout/tables/nsCellMap.cpp +++ b/mozilla/layout/tables/nsCellMap.cpp @@ -19,6 +19,7 @@ #include "nsVoidArray.h" #include "nsCellMap.h" #include "nsTableFrame.h" +#include "nsTableCellFrame.h" #ifdef NS_DEBUG static PRBool gsDebug = PR_FALSE; @@ -226,4 +227,187 @@ PRInt32 nsCellMap::GetNextAvailColIndex(PRInt32 aRowIndex, PRInt32 aColIndex) co return result; } +/** 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:
+ *
+  * TABLE
+  *   TR
+  *    TD ROWSPAN=2
+  *    TD
+  *   TR
+  *    TD
+  * 
+ * RowIsSpannedInto(0) returns PR_FALSE, and RowIsSpannedInto(1) returns PR_TRUE. + * @see RowHasSpanningCells + */ +// if computing this and related info gets expensive, we can easily +// cache it. The only thing to remember is to rebuild the cache +// whenever a row|col|cell is added/deleted, or a span attribute is changed. +PRBool nsCellMap::RowIsSpannedInto(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexmCell) + { // the cell at (aRowIndex, colIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realRowIndex = cell->GetRowIndex (); + if (realRowIndex!=aRowIndex) + { // the span is caused by a rowspan + result = PR_TRUE; + break; + } + } + } + } + return result; +} + +/** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD ROWSPAN=2
+  *    TD
+  *   TR
+  *    TD
+  * 
+ * RowHasSpanningCells(0) returns PR_TRUE, and RowHasSpanningCells(1) returns PR_FALSE. + * @see RowIsSpannedInto + */ +PRBool nsCellMap::RowHasSpanningCells(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexmCell) + { // the cell at (nextRowIndex, colIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realRowIndex = cell->GetRowIndex (); + if (realRowIndex!=nextRowIndex) + { // the span is caused by a rowspan + CellData *spanningCell = GetCellAt(aRowIndex, colIndex); + if (nsnull!=spanningCell) + { // there's really a cell at (aRowIndex, colIndex) + if (nsnull!=spanningCell->mCell) + { // aRowIndex is where the rowspan originated + result = PR_TRUE; + break; + } + } + } + } + } + } + } + return result; +} + + +/** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD COLSPAN=2
+  *    TD
+  *    TD
+  * 
+ * ColIsSpannedInto(0) returns PR_FALSE, ColIsSpannedInto(1) returns PR_TRUE, + * and ColIsSpannedInto(2) returns PR_FALSE. + * @see ColHasSpanningCells + */ +PRBool nsCellMap::ColIsSpannedInto(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexmCell) + { // the cell at (rowIndex, aColIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realColIndex = cell->GetColIndex (); + if (realColIndex!=aColIndex) + { // the span is caused by a colspan + result = PR_TRUE; + break; + } + } + } + } + return result; +} + +/** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * So, given this table:
+ *
+  * TABLE
+  *   TR
+  *    TD COLSPAN=2
+  *    TD
+  * 
+ * ColHasSpanningCells(0) returns PR_TRUE, and ColHasSpanningCells(1) returns PR_FALSE. + * @see ColIsSpannedInto + */ +PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexmCell) + { // the cell at (rowIndex, nextColIndex) is the result of a span + nsTableCellFrame *cell = cd->mRealCell->mCell; + NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell"); + const PRInt32 realColIndex = cell->GetColIndex (); + if (realColIndex!=nextColIndex) + { // the span is caused by a colspan + CellData *spanningCell =GetCellAt(rowIndex, aColIndex); + if (nsnull!=spanningCell) + { // there's really a cell at (rowIndex, aColIndex) + if (nsnull!=spanningCell->mCell) + { // aCowIndex is where the cowspan originated + result = PR_TRUE; + break; + } + } + } + } + } + } + } + return result; +} + + diff --git a/mozilla/layout/tables/nsCellMap.h b/mozilla/layout/tables/nsCellMap.h index f83136f801d..e5e9a23f71b 100644 --- a/mozilla/layout/tables/nsCellMap.h +++ b/mozilla/layout/tables/nsCellMap.h @@ -44,7 +44,10 @@ protected: /** storage for rows */ nsVoidArray *mRows; - /** storage for CellData pointers */ + /** storage for min col span info, just an int that gives the smallest + * colspan for all cells originating in each column. If allocated, + * each entry must be >= 1. + */ PRInt32 *mMinColSpans; /** a cache of the column frames, by col index */ @@ -62,8 +65,8 @@ protected: public: /** constructor * @param aRows - initial number of rows - * @param aColumns - initial number of columns - */ + * @param aColumns - initial number of columns + */ nsCellMap(PRInt32 aRows, PRInt32 aColumns); /** destructor @@ -113,22 +116,69 @@ public: /** add a column frame to the list of column frames * column frames must be added in order - */ + */ void AppendColumnFrame(nsTableColFrame *aColFrame); - /** return PR_TRUE if aRowIndex has any cells with rowspan>1 contained - * within it (not just cells that are in the row, but cells that span - * into the row as well. - */ - PRBool RowImpactedBySpanningCell(PRInt32 aRowIndex); + /** 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:
+ *
+		* TABLE
+		*   TR
+		*    TD ROWSPAN=2
+		*    TD
+		*   TR
+		*    TD
+		* 
+ * RowIsSpannedInto(0) returns PR_FALSE, and RowIsSpannedInto(1) returns PR_TRUE. + * @see RowHasSpanningCells + */ + PRBool RowIsSpannedInto(PRInt32 aRowIndex); - /** return PR_TRUE if aColIndex has any cells with colspan>1 contained - * within it (not just cells that are in the col, but cells that span - * into the col as well. - */ - PRBool ColumnImpactedBySpanningCell(PRInt32 aColIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD ROWSPAN=2
+		*    TD
+		*   TR
+		*    TD
+		* 
+ * RowHasSpanningCells(0) returns PR_TRUE, and RowHasSpanningCells(1) returns PR_FALSE. + * @see RowIsSpannedInto + */ + PRBool RowHasSpanningCells(PRInt32 aRowIndex); - /** for debugging */ + /** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD COLSPAN=2
+		*    TD
+		*    TD
+		* 
+ * ColIsSpannedInto(0) returns PR_FALSE, ColIsSpannedInto(1) returns PR_TRUE, + * and ColIsSpannedInto(2) returns PR_FALSE. + * @see ColHasSpanningCells + */ + PRBool ColIsSpannedInto(PRInt32 aColIndex); + + /** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * So, given this table:
+ *
+		* TABLE
+		*   TR
+		*    TD COLSPAN=2
+		*    TD
+		* 
+ * ColHasSpanningCells(0) returns PR_TRUE, and ColHasSpanningCells(1) returns PR_FALSE. + * @see ColIsSpannedInto + */ + PRBool ColHasSpanningCells(PRInt32 aColIndex); + + + /** dump a representation of the cell map to stdout for debugging */ void DumpCellMap() const; }; diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index 108f3ae1dfb..89bcd8b5e6b 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -429,7 +429,7 @@ nsTableColFrame * nsTableFrame::GetColFrame(PRInt32 aColIndex) } // can return nsnull -nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) +nsTableCellFrame * nsTableFrame::GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex) { nsTableCellFrame *result = nsnull; nsCellMap *cellMap = GetCellMap(); @@ -446,6 +446,73 @@ nsTableCellFrame * nsTableFrame::GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex) return result; } +/** returns PR_TRUE if the row at aRowIndex has any cells that are the result + * of a row-spanning cell. + * @see nsCellMap::RowIsSpannedInto + */ +PRBool nsTableFrame::RowIsSpannedInto(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexRowIsSpannedInto(aRowIndex); + } + return result; +} + +/** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * @see nsCellMap::RowHasSpanningCells + */ +PRBool nsTableFrame::RowHasSpanningCells(PRInt32 aRowIndex) +{ + NS_PRECONDITION (0<=aRowIndex && aRowIndexRowHasSpanningCells(aRowIndex); + } + return result; +} + + +/** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. + * @see nsCellMap::ColIsSpannedInto + */ +PRBool nsTableFrame::ColIsSpannedInto(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexColIsSpannedInto(aColIndex); + } + return result; +} + +/** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * @see nsCellMap::ColHasSpanningCells + */ +PRBool nsTableFrame::ColHasSpanningCells(PRInt32 aColIndex) +{ + NS_PRECONDITION (0<=aColIndex && aColIndexColHasSpanningCells(aColIndex); + } + return result; +} + // return the number of rows spanned by aCell starting at aRowIndex // note that this is different from just the rowspan of aCell // (that would be GetEffectiveRowSpan (indexOfRowThatContains_aCell, aCell) @@ -499,7 +566,17 @@ PRInt32 nsTableFrame::GetEffectiveColSpan (PRInt32 aColIndex, nsTableCellFrame * result -= (minColSpanForCol - 1); // minColSpanForCol is always at least 1 // and we want to treat default as 0 (no effect) } - +#ifdef NS_DEBUG + if (0>=result) + { + printf("ERROR!\n"); + DumpCellMap(); + printf("aColIndex=%d, cell->colIndex=%d\n", aColIndex, aCell->GetColIndex()); + printf("aCell->colSpan=%d\n", aCell->GetColSpan()); + printf("colCount=%d\n", mCellMap->GetColCount()); + } +#endif +NS_ASSERTION(0GetRowCount(); - PRInt32 cols = mCellMap->GetColCount(); - for (PRInt32 r = 0; r < rowCount; r++) + PRInt32 colCount = mCellMap->GetColCount(); + for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) { if (gsDebug==PR_TRUE) - { printf("row %d", r); + { printf("row %d", rowIndex); printf(": "); } - for (PRInt32 c = 0; c < cols; c++) + for (PRInt32 colIndex = 0; colIndex < colCount; colIndex++) { - CellData *cd =mCellMap->GetCellAt(r, c); + CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex); if (cd != nsnull) { if (cd->mCell != nsnull) { - printf("C%d,%d ", r, c); + printf("C%d,%d ", rowIndex, colIndex); printf(" "); } else @@ -931,8 +1008,18 @@ void nsTableFrame::DumpCellMap () else printf("---- "); } - printf("\n"); + PRBool spanners = RowHasSpanningCells(rowIndex); + PRBool spannedInto = RowIsSpannedInto(rowIndex); + printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F"); } + // output colspan info + for (PRInt32 colIndex=0; colIndexmRealCell = data; - if (gsDebug==PR_TRUE) printf(" null GetCellAt(%d, %d) so setting to spanData\n", workRow, workCol); + if (gsDebug==PR_TRUE) printf(" 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 GetCellAt(%d, %d) so setting to spanData\n", workRow, workCol); + if (gsDebug==PR_TRUE) printf(" 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; @@ -1623,6 +1710,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth) { + //DumpCellMap(); NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, "bad parent reflow state"); diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 32d0172386c..bd697b7852e 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -436,6 +436,7 @@ public: /* ----- Cell Map public methods ----- */ */ virtual PRInt32 GetRowCount(); + /** returns the number of columns in this table. */ virtual PRInt32 GetColCount(); /** adjust the col count for screwy table attributes. @@ -443,11 +444,39 @@ public: /* ----- Cell Map public methods ----- */ */ virtual void SetEffectiveColCount(); + /** return the column frame at colIndex. + * returns nsnull if the col frame has not yet been allocated, or if aColIndex is out of range + */ nsTableColFrame * GetColFrame(PRInt32 aColIndex); - nsTableCellFrame * GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex); + /** return the cell frame at aRowIndex, aColIndex. + * returns nsnull if the cell frame has not yet been allocated, + * or if aRowIndex or aColIndex is out of range + */ + nsTableCellFrame * GetCellFrameAt(PRInt32 aRowIndex, PRInt32 aColIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that are the result + * of a row-spanning cell above it. + * @see nsCellMap::RowIsSpannedInto + */ + PRBool RowIsSpannedInto(PRInt32 aRowIndex); + /** returns PR_TRUE if the row at aRowIndex has any cells that have a rowspan>1 + * that originate in aRowIndex. + * @see nsCellMap::RowHasSpanningCells + */ + PRBool RowHasSpanningCells(PRInt32 aRowIndex); + + /** returns PR_TRUE if the col at aColIndex has any cells that are the result + * of a col-spanning cell. + * @see nsCellMap::ColIsSpannedInto + */ + PRBool ColIsSpannedInto(PRInt32 aColIndex); + + /** returns PR_TRUE if the row at aColIndex has any cells that have a colspan>1 + * @see nsCellMap::ColHasSpanningCells + */ + PRBool ColHasSpanningCells(PRInt32 aColIndex); private: void DebugPrintCount() const; // Debugging routine diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index 80188421cf5..76d49faca70 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -114,6 +114,11 @@ nsTableRowFrame::DidReflow(nsIPresContext& aPresContext, if (NS_FRAME_REFLOW_FINISHED == aStatus) { // Resize and re-align the cell frames based on our row height nscoord cellHeight = mRect.height - mCellMaxTopMargin - mCellMaxBottomMargin; + +// XXX + // every place in this module where we cast to nsTableCellFrame, + // we first have to check the display-type of the frame and skip non-cells. + nsTableCellFrame *cellFrame = (nsTableCellFrame*)mFirstChild; nsTableFrame* tableFrame; mContentParent->GetContentParent((nsIFrame*&)tableFrame);