diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
index 7712953e951..2f034b8c497 100644
--- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
+++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.cpp
@@ -233,7 +233,8 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
- PRInt32 aNumCols)
+ PRInt32 aNumCols,
+ nscoord aMaxWidth)
{
#ifdef NS_DEBUG
nsIFrame* tablePIF = nsnull;
@@ -251,7 +252,7 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// Step 1 - assign the width of all fixed-width columns
- AssignPreliminaryColumnWidths();
+ AssignPreliminaryColumnWidths(aMaxWidth);
// set aMaxElementSize here because we compute mMinTableWidth in AssignPreliminaryColumnWidths
if (nsnull != aMaxElementSize) {
@@ -389,7 +390,7 @@ nscoord BasicTableLayoutStrategy::CalcHorizontalPadding(PRInt32 aColX)
// Step 1 - assign the width of all fixed-width columns, all other columns get there max,
// and calculate min/max table width
-PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
+PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth)
{
TDBG_SP("** %p: AssignPreliminaryColumnWidths **\n", mTableFrame);
nsVoidArray *spanList = nsnull;
diff --git a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
index 375d82ae4fc..55c207a995a 100644
--- a/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
+++ b/mozilla/layout/html/table/src/BasicTableLayoutStrategy.h
@@ -91,7 +91,7 @@ public:
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
- virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols);
+ virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols, nscoord aMaxSize);
/** compute the max element size of the table.
* assumes that Initialize has been called
@@ -123,10 +123,12 @@ protected:
* Computes the minimum and maximum table widths.
* Set column width information in each column frame and in the table frame.
*
+ * @param aMaxWidth - the computed width of the table or
+ * UNCONSTRAINED_SIZE if an auto width table
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
*/
- virtual PRBool AssignPreliminaryColumnWidths();
+ virtual PRBool AssignPreliminaryColumnWidths(nscoord aComputedWidth);
/** compute the min and max width of this table. Assumes AssignPreliminaryColumnWidths
* has been called. Sets mMinTableWidth and mMaxTableWidth as a side effect.
diff --git a/mozilla/layout/html/table/src/FixedTableLayoutStrategy.cpp b/mozilla/layout/html/table/src/FixedTableLayoutStrategy.cpp
index 1febd8256c5..31c01d07342 100644
--- a/mozilla/layout/html/table/src/FixedTableLayoutStrategy.cpp
+++ b/mozilla/layout/html/table/src/FixedTableLayoutStrategy.cpp
@@ -73,109 +73,135 @@ PRBool FixedTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext *aTableStyl
return result;
}
-/* assign the width of all columns
+/*
+ * assign the width of all columns
* if there is a colframe with a width attribute, use it as the column width
* otherwise if there is a cell in the first row and it has a width attribute, use it
* if this cell includes a colspan, width is divided equally among spanned columns
* otherwise the cell get a proportion of the remaining space
* as determined by the table width attribute. If no table width attribute, it gets 0 width
*/
-PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths()
+PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputedWidth)
{
+ NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
if (gsDebug==PR_TRUE) printf ("** %p: AssignPreliminaryColumnWidths **\n", mTableFrame);
-
- PRInt32 colIndex;
- PRInt32 specifiedColumns=0; // the number of columns whose width is given
- nscoord totalWidth = 0; // the sum of the widths of the columns whose width is given
- PRBool * autoWidthColumns = new PRBool[mNumCols];
- nsCRT::memset(autoWidthColumns, PR_TRUE, mNumCols*sizeof(PRBool));
+ const nsStylePosition* tablePosition;
+ mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
+ PRBool tableIsFixedWidth = eStyleUnit_Coord == tablePosition->mWidth.GetUnit() ||
+ eStyleUnit_Percent == tablePosition->mWidth.GetUnit();
+
+ const nsStyleSpacing* tableSpacing;
+ mTableFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)tableSpacing);
+ nsMargin borderPadding;
+ tableSpacing->CalcBorderPaddingFor(mTableFrame, borderPadding);
+
+ PRInt32 colX;
+ // availWidth is used as the basis for percentage width columns. It is aComputedWidth
+ // minus table border, padding, & cellspacing
+ nscoord availWidth = aComputedWidth - borderPadding.left - borderPadding.right -
+ ((mNumCols + 1) * mTableFrame->GetCellSpacingX());
+
+ PRInt32 specifiedCols = 0; // the number of columns whose width is given
+ nscoord totalColWidth = 0; // the sum of the widths of the columns
+
+ nscoord* colWidths = new PRBool[mNumCols];
+ nsCRT::memset(colWidths, -1, mNumCols*sizeof(nscoord));
// for every column, determine it's specified width
- for (colIndex = 0; colIndexGetColFrame(colIndex);
- NS_ASSERTION(nsnull!=colFrame, "bad col frame");
+ nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
+ NS_ASSERTION(nsnull != colFrame, "bad col frame");
// Get the columns's style
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
- // Get fixed column width if it has one
- if (eStyleUnit_Coord==colPosition->mWidth.GetUnit())
- {
- nscoord colWidth = colPosition->mWidth.GetCoordValue();
- mTableFrame->SetColumnWidth(colIndex, colWidth);
- totalWidth += colWidth;
- specifiedColumns++;
- autoWidthColumns[colIndex]=PR_FALSE;
- if (PR_TRUE==gsDebug)
- printf ("from col, col %d set to width %d\n", colIndex, colWidth);
+ // get the fixed width if available
+ if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
+ colWidths[colX] = colPosition->mWidth.GetCoordValue();
+ } // get the percentage width
+ else if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
+ float percent = colPosition->mWidth.GetPercentValue();
+ colWidths[colX] = NSToCoordRound(percent * (float)availWidth);
}
- else
- {
- nsTableCellFrame *cellFrame = mTableFrame->GetCellFrameAt(0, colIndex);
- if (nsnull!=cellFrame)
- {
+ else { // get width from the cell
+ nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
+ if (nsnull != cellFrame) {
// Get the cell's style
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
- // Get fixed column width if it has one
- if (eStyleUnit_Coord==cellPosition->mWidth.GetUnit())
- {
- PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colIndex, cellFrame);
- nscoord effectiveWidth = cellPosition->mWidth.GetCoordValue()/colSpan;
- mTableFrame->SetColumnWidth(colIndex, effectiveWidth);
- totalWidth += effectiveWidth;
- specifiedColumns++;
- autoWidthColumns[colIndex]=PR_FALSE;
- if (PR_TRUE==gsDebug)
- printf ("from cell, col %d set to width %d\n", colIndex, effectiveWidth);
+ PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colX, cellFrame);
+ // Get fixed cell width if available
+ if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
+ colWidths[colX] = cellPosition->mWidth.GetCoordValue() / colSpan;
+ }
+ else if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
+ float percent = cellPosition->mWidth.GetPercentValue();
+ colWidths[colX] = NSToCoordRound(percent * (float)availWidth / (float)colSpan);
}
}
}
+ if (colWidths[colX] >= 0) {
+ totalColWidth += colWidths[colX];
+ specifiedCols++;
+ if (PR_TRUE==gsDebug) printf ("col %d set to width %d\n", colX, colWidths[colX]);
+ }
}
-
- // for every column that did not have a specified width, compute its width from the remaining space
- if (mNumCols > specifiedColumns)
- {
- // Get the table's style
- const nsStylePosition* tablePosition;
- mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
- if (eStyleUnit_Coord==tablePosition->mWidth.GetUnit())
- {
- nscoord specifiedTableWidth = tablePosition->mWidth.GetCoordValue();
- nscoord remainingTableWidth = specifiedTableWidth - totalWidth;
- if (PR_TRUE==gsDebug)
- printf ("%p: specifiedTW=%d, remainingTW=%d\n",
- mTableFrame, specifiedTableWidth, remainingTableWidth);
- if (0SetColumnWidth(colIndex, widthPerColumn);
- totalWidth += widthPerColumn;
- if (PR_TRUE==gsDebug)
- printf ("auto col %d set to width %d\n", colIndex, widthPerColumn);
- }
+
+ nscoord lastColAllocated = -1;
+ nscoord remainingWidth = availWidth - totalColWidth;
+ if (tableIsFixedWidth && (0 < remainingWidth)) {
+ if (mNumCols > specifiedCols) {
+ // allocate the extra space to the columns which have no width specified
+ if (PR_TRUE == gsDebug) printf ("%p: remainingTW=%d\n", mTableFrame, remainingWidth);
+ nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)mNumCols) - ((float)specifiedCols)));
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (-1 == colWidths[colX]) {
+ colWidths[colX] = colAlloc;
+ totalColWidth += colAlloc;
+ lastColAllocated = colX;
+ if (PR_TRUE == gsDebug) printf ("auto col %d set to width %d\n", colX, colAlloc);
}
}
}
+ else { // allocate the extra space to the columns which have width specified
+ float divisor = (float)totalColWidth;
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (colWidths[colX] > 0) {
+ nscoord colAlloc = NSToCoordRound(remainingWidth * colWidths[colX] / divisor);
+ colWidths[colX] += colAlloc;
+ totalColWidth += colAlloc;
+ lastColAllocated = colX;
+ if (PR_TRUE == gsDebug) printf ("col %d set to width %d\n", colX, colWidths[colX]);
+ }
+ }
+ }
}
- // min/MaxTW is max of (specified table width, sum of specified column(cell) widths)
- mMinTableWidth = mMaxTableWidth = totalWidth;
- if (PR_TRUE==gsDebug)
- printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, mMinTableWidth, mMaxTableWidth);
+
+ nscoord overAllocation = (availWidth >= 0)
+ ? totalColWidth - availWidth : 0;
+ // set the column widths
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (colWidths[colX] < 0)
+ colWidths[colX] = 0;
+ // if there was too much allocated due to rounding, remove it from the last col
+ if ((colX == lastColAllocated) && (overAllocation != 0)) {
+ colWidths[colX] += overAllocation;
+ colWidths[colX] = PR_MAX(0, colWidths[colX]);
+ }
+ mTableFrame->SetColumnWidth(colX, colWidths[colX]);
+ }
+
+ // min/max TW is min/max of (specified table width, sum of specified column(cell) widths)
+ mMinTableWidth = mMaxTableWidth = totalColWidth;
+ if (PR_TRUE == gsDebug) printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, mMinTableWidth, mMaxTableWidth);
// clean up
- if (nsnull!=autoWidthColumns)
- {
- delete [] autoWidthColumns;
+ if (nsnull != colWidths) {
+ delete [] colWidths;
}
return PR_TRUE;
diff --git a/mozilla/layout/html/table/src/FixedTableLayoutStrategy.h b/mozilla/layout/html/table/src/FixedTableLayoutStrategy.h
index 5dc239b197b..d012b2a86de 100644
--- a/mozilla/layout/html/table/src/FixedTableLayoutStrategy.h
+++ b/mozilla/layout/html/table/src/FixedTableLayoutStrategy.h
@@ -72,7 +72,7 @@ protected:
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
*/
- virtual PRBool AssignPreliminaryColumnWidths();
+ virtual PRBool AssignPreliminaryColumnWidths(nscoord aComputedWidth);
};
diff --git a/mozilla/layout/html/table/src/nsITableLayoutStrategy.h b/mozilla/layout/html/table/src/nsITableLayoutStrategy.h
index 0e4df637a33..4221ccd187b 100644
--- a/mozilla/layout/html/table/src/nsITableLayoutStrategy.h
+++ b/mozilla/layout/html/table/src/nsITableLayoutStrategy.h
@@ -32,8 +32,9 @@ public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
+ * @param aComputedWidth the computed size of the table
*/
- virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)=0;
+ virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols, nscoord aComputedWidth)=0;
/** compute the max-element-size for the table
* @param aMaxElementSize [OUT] width field set to the min legal width of the table
diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp
index 20726aed9fa..7c43d94931f 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableFrame.cpp
@@ -2497,7 +2497,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
- mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE; //so we don't do this a second time below
}
}
@@ -2506,7 +2506,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (nsnull!=mTableLayoutStrategy)
{
- mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE;
}
}
@@ -3972,17 +3972,22 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
this, maxWidth, aMaxSize.width, aMaxSize.height);
// based on the compatibility mode, create a table layout strategy
- if (nsnull==mTableLayoutStrategy)
- {
+ if (nsnull == mTableLayoutStrategy) {
nsCompatibility mode;
aPresContext.GetCompatibilityMode(&mode);
if (PR_FALSE==RequiresPass1Layout())
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
mTableLayoutStrategy = new BasicTableLayoutStrategy(this, eCompatibility_NavQuirks == mode);
- mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE;
}
+ // fixed-layout tables need to reinitialize the layout strategy. When there are scroll bars
+ // reflow gets called twice and the 2nd time has the correct space available.
+ else if (!RequiresPass1Layout()) {
+ mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount(), aReflowState.computedWidth);
+ }
+
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
mColumnWidthsSet=PR_TRUE;
diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
index 7712953e951..2f034b8c497 100644
--- a/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/mozilla/layout/tables/BasicTableLayoutStrategy.cpp
@@ -233,7 +233,8 @@ BasicTableLayoutStrategy::~BasicTableLayoutStrategy()
}
PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
- PRInt32 aNumCols)
+ PRInt32 aNumCols,
+ nscoord aMaxWidth)
{
#ifdef NS_DEBUG
nsIFrame* tablePIF = nsnull;
@@ -251,7 +252,7 @@ PRBool BasicTableLayoutStrategy::Initialize(nsSize* aMaxElementSize,
mCols = mTableFrame->GetEffectiveCOLSAttribute();
// Step 1 - assign the width of all fixed-width columns
- AssignPreliminaryColumnWidths();
+ AssignPreliminaryColumnWidths(aMaxWidth);
// set aMaxElementSize here because we compute mMinTableWidth in AssignPreliminaryColumnWidths
if (nsnull != aMaxElementSize) {
@@ -389,7 +390,7 @@ nscoord BasicTableLayoutStrategy::CalcHorizontalPadding(PRInt32 aColX)
// Step 1 - assign the width of all fixed-width columns, all other columns get there max,
// and calculate min/max table width
-PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths()
+PRBool BasicTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aMaxWidth)
{
TDBG_SP("** %p: AssignPreliminaryColumnWidths **\n", mTableFrame);
nsVoidArray *spanList = nsnull;
diff --git a/mozilla/layout/tables/BasicTableLayoutStrategy.h b/mozilla/layout/tables/BasicTableLayoutStrategy.h
index 375d82ae4fc..55c207a995a 100644
--- a/mozilla/layout/tables/BasicTableLayoutStrategy.h
+++ b/mozilla/layout/tables/BasicTableLayoutStrategy.h
@@ -91,7 +91,7 @@ public:
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
*/
- virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols);
+ virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols, nscoord aMaxSize);
/** compute the max element size of the table.
* assumes that Initialize has been called
@@ -123,10 +123,12 @@ protected:
* Computes the minimum and maximum table widths.
* Set column width information in each column frame and in the table frame.
*
+ * @param aMaxWidth - the computed width of the table or
+ * UNCONSTRAINED_SIZE if an auto width table
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
*/
- virtual PRBool AssignPreliminaryColumnWidths();
+ virtual PRBool AssignPreliminaryColumnWidths(nscoord aComputedWidth);
/** compute the min and max width of this table. Assumes AssignPreliminaryColumnWidths
* has been called. Sets mMinTableWidth and mMaxTableWidth as a side effect.
diff --git a/mozilla/layout/tables/FixedTableLayoutStrategy.cpp b/mozilla/layout/tables/FixedTableLayoutStrategy.cpp
index 1febd8256c5..31c01d07342 100644
--- a/mozilla/layout/tables/FixedTableLayoutStrategy.cpp
+++ b/mozilla/layout/tables/FixedTableLayoutStrategy.cpp
@@ -73,109 +73,135 @@ PRBool FixedTableLayoutStrategy::BalanceColumnWidths(nsIStyleContext *aTableStyl
return result;
}
-/* assign the width of all columns
+/*
+ * assign the width of all columns
* if there is a colframe with a width attribute, use it as the column width
* otherwise if there is a cell in the first row and it has a width attribute, use it
* if this cell includes a colspan, width is divided equally among spanned columns
* otherwise the cell get a proportion of the remaining space
* as determined by the table width attribute. If no table width attribute, it gets 0 width
*/
-PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths()
+PRBool FixedTableLayoutStrategy::AssignPreliminaryColumnWidths(nscoord aComputedWidth)
{
+ NS_ASSERTION(aComputedWidth != NS_UNCONSTRAINEDSIZE, "bad computed width");
if (gsDebug==PR_TRUE) printf ("** %p: AssignPreliminaryColumnWidths **\n", mTableFrame);
-
- PRInt32 colIndex;
- PRInt32 specifiedColumns=0; // the number of columns whose width is given
- nscoord totalWidth = 0; // the sum of the widths of the columns whose width is given
- PRBool * autoWidthColumns = new PRBool[mNumCols];
- nsCRT::memset(autoWidthColumns, PR_TRUE, mNumCols*sizeof(PRBool));
+ const nsStylePosition* tablePosition;
+ mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
+ PRBool tableIsFixedWidth = eStyleUnit_Coord == tablePosition->mWidth.GetUnit() ||
+ eStyleUnit_Percent == tablePosition->mWidth.GetUnit();
+
+ const nsStyleSpacing* tableSpacing;
+ mTableFrame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)tableSpacing);
+ nsMargin borderPadding;
+ tableSpacing->CalcBorderPaddingFor(mTableFrame, borderPadding);
+
+ PRInt32 colX;
+ // availWidth is used as the basis for percentage width columns. It is aComputedWidth
+ // minus table border, padding, & cellspacing
+ nscoord availWidth = aComputedWidth - borderPadding.left - borderPadding.right -
+ ((mNumCols + 1) * mTableFrame->GetCellSpacingX());
+
+ PRInt32 specifiedCols = 0; // the number of columns whose width is given
+ nscoord totalColWidth = 0; // the sum of the widths of the columns
+
+ nscoord* colWidths = new PRBool[mNumCols];
+ nsCRT::memset(colWidths, -1, mNumCols*sizeof(nscoord));
// for every column, determine it's specified width
- for (colIndex = 0; colIndexGetColFrame(colIndex);
- NS_ASSERTION(nsnull!=colFrame, "bad col frame");
+ nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX);
+ NS_ASSERTION(nsnull != colFrame, "bad col frame");
// Get the columns's style
const nsStylePosition* colPosition;
colFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)colPosition);
- // Get fixed column width if it has one
- if (eStyleUnit_Coord==colPosition->mWidth.GetUnit())
- {
- nscoord colWidth = colPosition->mWidth.GetCoordValue();
- mTableFrame->SetColumnWidth(colIndex, colWidth);
- totalWidth += colWidth;
- specifiedColumns++;
- autoWidthColumns[colIndex]=PR_FALSE;
- if (PR_TRUE==gsDebug)
- printf ("from col, col %d set to width %d\n", colIndex, colWidth);
+ // get the fixed width if available
+ if (eStyleUnit_Coord == colPosition->mWidth.GetUnit()) {
+ colWidths[colX] = colPosition->mWidth.GetCoordValue();
+ } // get the percentage width
+ else if (eStyleUnit_Percent == colPosition->mWidth.GetUnit()) {
+ float percent = colPosition->mWidth.GetPercentValue();
+ colWidths[colX] = NSToCoordRound(percent * (float)availWidth);
}
- else
- {
- nsTableCellFrame *cellFrame = mTableFrame->GetCellFrameAt(0, colIndex);
- if (nsnull!=cellFrame)
- {
+ else { // get width from the cell
+ nsTableCellFrame* cellFrame = mTableFrame->GetCellFrameAt(0, colX);
+ if (nsnull != cellFrame) {
// Get the cell's style
const nsStylePosition* cellPosition;
cellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)cellPosition);
- // Get fixed column width if it has one
- if (eStyleUnit_Coord==cellPosition->mWidth.GetUnit())
- {
- PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colIndex, cellFrame);
- nscoord effectiveWidth = cellPosition->mWidth.GetCoordValue()/colSpan;
- mTableFrame->SetColumnWidth(colIndex, effectiveWidth);
- totalWidth += effectiveWidth;
- specifiedColumns++;
- autoWidthColumns[colIndex]=PR_FALSE;
- if (PR_TRUE==gsDebug)
- printf ("from cell, col %d set to width %d\n", colIndex, effectiveWidth);
+ PRInt32 colSpan = mTableFrame->GetEffectiveColSpan(colX, cellFrame);
+ // Get fixed cell width if available
+ if (eStyleUnit_Coord == cellPosition->mWidth.GetUnit()) {
+ colWidths[colX] = cellPosition->mWidth.GetCoordValue() / colSpan;
+ }
+ else if (eStyleUnit_Percent == cellPosition->mWidth.GetUnit()) {
+ float percent = cellPosition->mWidth.GetPercentValue();
+ colWidths[colX] = NSToCoordRound(percent * (float)availWidth / (float)colSpan);
}
}
}
+ if (colWidths[colX] >= 0) {
+ totalColWidth += colWidths[colX];
+ specifiedCols++;
+ if (PR_TRUE==gsDebug) printf ("col %d set to width %d\n", colX, colWidths[colX]);
+ }
}
-
- // for every column that did not have a specified width, compute its width from the remaining space
- if (mNumCols > specifiedColumns)
- {
- // Get the table's style
- const nsStylePosition* tablePosition;
- mTableFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)tablePosition);
- if (eStyleUnit_Coord==tablePosition->mWidth.GetUnit())
- {
- nscoord specifiedTableWidth = tablePosition->mWidth.GetCoordValue();
- nscoord remainingTableWidth = specifiedTableWidth - totalWidth;
- if (PR_TRUE==gsDebug)
- printf ("%p: specifiedTW=%d, remainingTW=%d\n",
- mTableFrame, specifiedTableWidth, remainingTableWidth);
- if (0SetColumnWidth(colIndex, widthPerColumn);
- totalWidth += widthPerColumn;
- if (PR_TRUE==gsDebug)
- printf ("auto col %d set to width %d\n", colIndex, widthPerColumn);
- }
+
+ nscoord lastColAllocated = -1;
+ nscoord remainingWidth = availWidth - totalColWidth;
+ if (tableIsFixedWidth && (0 < remainingWidth)) {
+ if (mNumCols > specifiedCols) {
+ // allocate the extra space to the columns which have no width specified
+ if (PR_TRUE == gsDebug) printf ("%p: remainingTW=%d\n", mTableFrame, remainingWidth);
+ nscoord colAlloc = NSToCoordRound( ((float)remainingWidth) / (((float)mNumCols) - ((float)specifiedCols)));
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (-1 == colWidths[colX]) {
+ colWidths[colX] = colAlloc;
+ totalColWidth += colAlloc;
+ lastColAllocated = colX;
+ if (PR_TRUE == gsDebug) printf ("auto col %d set to width %d\n", colX, colAlloc);
}
}
}
+ else { // allocate the extra space to the columns which have width specified
+ float divisor = (float)totalColWidth;
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (colWidths[colX] > 0) {
+ nscoord colAlloc = NSToCoordRound(remainingWidth * colWidths[colX] / divisor);
+ colWidths[colX] += colAlloc;
+ totalColWidth += colAlloc;
+ lastColAllocated = colX;
+ if (PR_TRUE == gsDebug) printf ("col %d set to width %d\n", colX, colWidths[colX]);
+ }
+ }
+ }
}
- // min/MaxTW is max of (specified table width, sum of specified column(cell) widths)
- mMinTableWidth = mMaxTableWidth = totalWidth;
- if (PR_TRUE==gsDebug)
- printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, mMinTableWidth, mMaxTableWidth);
+
+ nscoord overAllocation = (availWidth >= 0)
+ ? totalColWidth - availWidth : 0;
+ // set the column widths
+ for (colX = 0; colX < mNumCols; colX++) {
+ if (colWidths[colX] < 0)
+ colWidths[colX] = 0;
+ // if there was too much allocated due to rounding, remove it from the last col
+ if ((colX == lastColAllocated) && (overAllocation != 0)) {
+ colWidths[colX] += overAllocation;
+ colWidths[colX] = PR_MAX(0, colWidths[colX]);
+ }
+ mTableFrame->SetColumnWidth(colX, colWidths[colX]);
+ }
+
+ // min/max TW is min/max of (specified table width, sum of specified column(cell) widths)
+ mMinTableWidth = mMaxTableWidth = totalColWidth;
+ if (PR_TRUE == gsDebug) printf ("%p: aMinTW=%d, aMaxTW=%d\n", mTableFrame, mMinTableWidth, mMaxTableWidth);
// clean up
- if (nsnull!=autoWidthColumns)
- {
- delete [] autoWidthColumns;
+ if (nsnull != colWidths) {
+ delete [] colWidths;
}
return PR_TRUE;
diff --git a/mozilla/layout/tables/FixedTableLayoutStrategy.h b/mozilla/layout/tables/FixedTableLayoutStrategy.h
index 5dc239b197b..d012b2a86de 100644
--- a/mozilla/layout/tables/FixedTableLayoutStrategy.h
+++ b/mozilla/layout/tables/FixedTableLayoutStrategy.h
@@ -72,7 +72,7 @@ protected:
* @return PR_TRUE if all is well, PR_FALSE if there was an unrecoverable error
*
*/
- virtual PRBool AssignPreliminaryColumnWidths();
+ virtual PRBool AssignPreliminaryColumnWidths(nscoord aComputedWidth);
};
diff --git a/mozilla/layout/tables/nsITableLayoutStrategy.h b/mozilla/layout/tables/nsITableLayoutStrategy.h
index 0e4df637a33..4221ccd187b 100644
--- a/mozilla/layout/tables/nsITableLayoutStrategy.h
+++ b/mozilla/layout/tables/nsITableLayoutStrategy.h
@@ -32,8 +32,9 @@ public:
/** call once every time any table thing changes (content, structure, or style)
* @param aMaxElementSize [OUT] if not null, the max element size is computed and returned in this param
* @param aNumCols the total number of columns in the table
+ * @param aComputedWidth the computed size of the table
*/
- virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols)=0;
+ virtual PRBool Initialize(nsSize* aMaxElementSize, PRInt32 aNumCols, nscoord aComputedWidth)=0;
/** compute the max-element-size for the table
* @param aMaxElementSize [OUT] width field set to the min legal width of the table
diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp
index 20726aed9fa..7c43d94931f 100644
--- a/mozilla/layout/tables/nsTableFrame.cpp
+++ b/mozilla/layout/tables/nsTableFrame.cpp
@@ -2497,7 +2497,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (nsnull!=mTableLayoutStrategy)
{
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
- mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE; //so we don't do this a second time below
}
}
@@ -2506,7 +2506,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext& aPresContext,
if (PR_TRUE==gsDebug || PR_TRUE==gsDebugIR) printf("TIF Reflow: Re-init layout strategy\n");
if (nsnull!=mTableLayoutStrategy)
{
- mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aDesiredSize.maxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE;
}
}
@@ -3972,17 +3972,22 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
this, maxWidth, aMaxSize.width, aMaxSize.height);
// based on the compatibility mode, create a table layout strategy
- if (nsnull==mTableLayoutStrategy)
- {
+ if (nsnull == mTableLayoutStrategy) {
nsCompatibility mode;
aPresContext.GetCompatibilityMode(&mode);
if (PR_FALSE==RequiresPass1Layout())
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
else
mTableLayoutStrategy = new BasicTableLayoutStrategy(this, eCompatibility_NavQuirks == mode);
- mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount());
+ mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount(), aReflowState.computedWidth);
mColumnWidthsValid=PR_TRUE;
}
+ // fixed-layout tables need to reinitialize the layout strategy. When there are scroll bars
+ // reflow gets called twice and the 2nd time has the correct space available.
+ else if (!RequiresPass1Layout()) {
+ mTableLayoutStrategy->Initialize(aMaxElementSize, GetColCount(), aReflowState.computedWidth);
+ }
+
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
mColumnWidthsSet=PR_TRUE;