/*
 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *           (C) 1997 Torben Weis (weis@kde.org)
 *           (C) 1998 Waldo Bastian (bastian@kde.org)
 *           (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "RenderTableSection.h"

#include "CachedImage.h"
#include "Document.h"
#include "HTMLNames.h"
#include "RenderTableCell.h"
#include "RenderTableCol.h"
#include "RenderTableRow.h"
#include "RenderView.h"
#include "TextStream.h"
#include <limits>
#include <wtf/Vector.h>

using namespace std;

namespace WebCore {

using namespace HTMLNames;

RenderTableSection::RenderTableSection(Node* node)
    : RenderContainer(node)
    , m_gridRows(0)
    , m_cCol(0)
    , m_cRow(-1)
    , m_needsCellRecalc(false)
    , m_outerBorderLeft(0)
    , m_outerBorderRight(0)
    , m_outerBorderTop(0)
    , m_outerBorderBottom(0)
    , m_overflowLeft(0)
    , m_overflowWidth(0)
    , m_overflowTop(0)
    , m_overflowHeight(0)
    , m_hasOverflowingCell(false)
{
    // init RenderObject attributes
    setInline(false);   // our object is not Inline
}

RenderTableSection::~RenderTableSection()
{
    clearGrid();
}

void RenderTableSection::destroy()
{
    RenderTable* recalcTable = table();
    
    RenderContainer::destroy();
    
    // recalc cell info because RenderTable has unguarded pointers
    // stored that point to this RenderTableSection.
    if (recalcTable)
        recalcTable->setNeedsSectionRecalc();
}

void RenderTableSection::setStyle(RenderStyle* newStyle)
{
    // we don't allow changing this one
    if (style())
        newStyle->setDisplay(style()->display());
    else if (newStyle->display() != TABLE_FOOTER_GROUP && newStyle->display() != TABLE_HEADER_GROUP)
        newStyle->setDisplay(TABLE_ROW_GROUP);

    RenderContainer::setStyle(newStyle);
}

void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
{
    // Make sure we don't append things after :after-generated content if we have it.
    if (!beforeChild && isAfterContent(lastChild()))
        beforeChild = lastChild();

    bool isTableSection = element() && (element()->hasTagName(theadTag) || element()->hasTagName(tbodyTag) || element()->hasTagName(tfootTag));

    if (!child->isTableRow()) {
        if (isTableSection && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
            RenderContainer::addChild(child, beforeChild);
            return;
        }

        RenderObject* last = beforeChild;
        if (!last)
            last = lastChild();
        if (last && last->isAnonymous()) {
            last->addChild(child);
            return;
        }

        // If beforeChild is inside an anonymous cell/row, insert into the cell or into
        // the anonymous row containing it, if there is one.
        RenderObject* lastBox = last;
        while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
            lastBox = lastBox->parent();
        if (lastBox && lastBox->isAnonymous()) {
            lastBox->addChild(child, beforeChild);
            return;
        }

        RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
        RenderStyle* newStyle = new (renderArena()) RenderStyle();
        newStyle->inheritFrom(style());
        newStyle->setDisplay(TABLE_ROW);
        row->setStyle(newStyle);
        addChild(row, beforeChild);
        row->addChild(child);
        return;
    }

    if (beforeChild)
        setNeedsCellRecalc();

    ++m_cRow;
    m_cCol = 0;

    // make sure we have enough rows
    if (!ensureRows(m_cRow + 1))
        return;

    m_grid[m_cRow].rowRenderer = child;

    if (!beforeChild) {
        m_grid[m_cRow].height = child->style()->height();
        if (m_grid[m_cRow].height.isRelative())
            m_grid[m_cRow].height = Length();
    }

    // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
    while (beforeChild && beforeChild->parent() != this)
        beforeChild = beforeChild->parent();

    ASSERT(!beforeChild || beforeChild->isTableRow() || isTableSection && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
    RenderContainer::addChild(child, beforeChild);
}

bool RenderTableSection::ensureRows(int numRows)
{
    int nRows = m_gridRows;
    if (numRows > nRows) {
        if (numRows > static_cast<int>(m_grid.size())) {
            size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);
            if (static_cast<size_t>(numRows) > maxSize)
                return false;
            m_grid.grow(numRows);
        }
        m_gridRows = numRows;
        int nCols = table()->numEffCols();
        CellStruct emptyCellStruct;
        emptyCellStruct.cell = 0;
        emptyCellStruct.inColSpan = false;
        for (int r = nRows; r < numRows; r++) {
            m_grid[r].row = new Row(nCols);
            m_grid[r].row->fill(emptyCellStruct);
            m_grid[r].rowRenderer = 0;
            m_grid[r].baseline = 0;
            m_grid[r].height = Length();
        }
    }

    return true;
}

void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
{
    int rSpan = cell->rowSpan();
    int cSpan = cell->colSpan();
    Vector<RenderTable::ColumnStruct>& columns = table()->columns();
    int nCols = columns.size();

    // ### mozilla still seems to do the old HTML way, even for strict DTD
    // (see the annotation on table cell layouting in the CSS specs and the testcase below:
    // <TABLE border>
    // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
    // <TR><TD colspan="2">5
    // </TABLE>

    while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).cell || cellAt(m_cRow, m_cCol).inColSpan))
        m_cCol++;

    if (rSpan == 1) {
        // we ignore height settings on rowspan cells
        Length height = cell->style()->height();
        if (height.isPositive() || (height.isRelative() && height.value() >= 0)) {
            Length cRowHeight = m_grid[m_cRow].height;
            switch (height.type()) {
                case Percent:
                    if (!(cRowHeight.isPercent()) ||
                        (cRowHeight.isPercent() && cRowHeight.rawValue() < height.rawValue()))
                        m_grid[m_cRow].height = height;
                        break;
                case Fixed:
                    if (cRowHeight.type() < Percent ||
                        (cRowHeight.isFixed() && cRowHeight.value() < height.value()))
                        m_grid[m_cRow].height = height;
                    break;
                case Relative:
                default:
                    break;
            }
        }
    }

    // make sure we have enough rows
    if (!ensureRows(m_cRow + rSpan))
        return;

    m_grid[m_cRow].rowRenderer = row;

    int col = m_cCol;
    // tell the cell where it is
    CellStruct currentCell;
    currentCell.cell = cell;
    currentCell.inColSpan = false;
    while (cSpan) {
        int currentSpan;
        if (m_cCol >= nCols) {
            table()->appendColumn(cSpan);
            currentSpan = cSpan;
        } else {
            if (cSpan < columns[m_cCol].span)
                table()->splitColumn(m_cCol, cSpan);
            currentSpan = columns[m_cCol].span;
        }

        for (int r = 0; r < rSpan; r++) {
            CellStruct& c = cellAt(m_cRow + r, m_cCol);
            if (currentCell.cell && !c.cell)
                c.cell = currentCell.cell;
            if (currentCell.inColSpan)
                c.inColSpan = true;
        }
        m_cCol++;
        cSpan -= currentSpan;
        currentCell.cell = 0;
        currentCell.inColSpan = true;
    }
    if (cell) {
        cell->setRow(m_cRow);
        cell->setCol(table()->effColToCol(col));
    }
}

void RenderTableSection::setCellWidths()
{
    Vector<int>& columnPos = table()->columnPositions();
    bool pushedLayoutState = false;

    for (int i = 0; i < m_gridRows; i++) {
        Row& row = *m_grid[i].row;
        int cols = row.size();
        for (int j = 0; j < cols; j++) {
            CellStruct current = row[j];
            RenderTableCell* cell = current.cell;

            if (!cell)
                continue;
            int endCol = j;
            int cspan = cell->colSpan();
            while (cspan && endCol < cols) {
                cspan -= table()->columns()[endCol].span;
                endCol++;
            }
            int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
            int oldWidth = cell->width();
            if (w != oldWidth) {
                cell->setNeedsLayout(true);
                if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
                    if (!pushedLayoutState) {
                        // Technically, we should also push state for the row, but since
                        // rows don't push a coordinate transform, that's not necessary.
                        view()->pushLayoutState(this, IntSize(m_x, m_y));
                        pushedLayoutState = true;
                    }
                    cell->repaint();
                }
                cell->setWidth(w);
            }
        }
    }
    
    if (pushedLayoutState)
        view()->popLayoutState();
}

void RenderTableSection::calcRowHeight()
{
    RenderTableCell* cell;

    int spacing = table()->vBorderSpacing();
    bool pushedLayoutState = false;

    m_rowPos.resize(m_gridRows + 1);
    m_rowPos[0] = spacing;

    for (int r = 0; r < m_gridRows; r++) {
        m_rowPos[r + 1] = 0;
        m_grid[r].baseline = 0;
        int baseline = 0;
        int bdesc = 0;
        int ch = m_grid[r].height.calcMinValue(0);
        int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);

        m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);

        Row* row = m_grid[r].row;
        int totalCols = row->size();

        for (int c = 0; c < totalCols; c++) {
            CellStruct current = cellAt(r, c);
            cell = current.cell;
            if (!cell || current.inColSpan)
                continue;
            if (r < m_gridRows - 1 && cellAt(r + 1, c).cell == cell)
                continue;

            int indx = max(r - cell->rowSpan() + 1, 0);

            if (cell->overrideSize() != -1) {
                if (!pushedLayoutState) {
                    // Technically, we should also push state for the row, but since
                    // rows don't push a coordinate transform, that's not necessary.
                    view()->pushLayoutState(this, IntSize(m_x, m_y));
                    pushedLayoutState = true;
                }
                cell->setOverrideSize(-1);
                cell->setChildNeedsLayout(true, false);
                cell->layoutIfNeeded();
            }
            
            // Explicit heights use the border box in quirks mode.  In strict mode do the right
            // thing and actually add in the border and padding.
            ch = cell->style()->height().calcValue(0) + 
                (cell->style()->htmlHacks() ? 0 : (cell->paddingTop() + cell->paddingBottom() +
                                                   cell->borderTop() + cell->borderBottom()));
            ch = max(ch, cell->height());

            pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);

            m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);

            // find out the baseline
            EVerticalAlign va = cell->style()->verticalAlign();
            if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
                int b = cell->baselinePosition();
                if (b > cell->borderTop() + cell->paddingTop()) {
                    baseline = max(baseline, b);
                    bdesc = max(bdesc, m_rowPos[indx] + ch - b);
                }
            }
        }

        //do we have baseline aligned elements?
        if (baseline) {
            // increase rowheight if baseline requires
            m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));
            m_grid[r].baseline = baseline;
        }

        m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
    }

    if (pushedLayoutState)
        view()->popLayoutState();
}

int RenderTableSection::layoutRows(int toAdd)
{
    int rHeight;
    int rindx;
    int totalRows = m_gridRows;
    
    // Set the width of our section now.  The rows will also be this width.
    m_width = table()->contentWidth();
    m_overflowLeft = 0;
    m_overflowWidth = m_width;
    m_overflowTop = 0;
    m_overflowHeight = 0;
    m_hasOverflowingCell = false;

    if (table()->collapseBorders())
        recalcOuterBorder();
    
    if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) {
        int totalHeight = m_rowPos[totalRows] + toAdd;

        int dh = toAdd;
        int totalPercent = 0;
        int numAuto = 0;
        for (int r = 0; r < totalRows; r++) {
            if (m_grid[r].height.isAuto())
                numAuto++;
            else if (m_grid[r].height.isPercent())
                totalPercent += m_grid[r].height.rawValue();
        }
        if (totalPercent) {
            // try to satisfy percent
            int add = 0;
            totalPercent = min(totalPercent, 100 * percentScaleFactor);
            int rh = m_rowPos[1] - m_rowPos[0];
            for (int r = 0; r < totalRows; r++) {
                if (totalPercent > 0 && m_grid[r].height.isPercent()) {
                    int toAdd = min(dh, (totalHeight * m_grid[r].height.rawValue() / (100 * percentScaleFactor)) - rh);
                    // If toAdd is negative, then we don't want to shrink the row (this bug
                    // affected Outlook Web Access).
                    toAdd = max(0, toAdd);
                    add += toAdd;
                    dh -= toAdd;
                    totalPercent -= m_grid[r].height.rawValue();
                }
                if (r < totalRows - 1)
                    rh = m_rowPos[r + 2] - m_rowPos[r + 1];
                m_rowPos[r + 1] += add;
            }
        }
        if (numAuto) {
            // distribute over variable cols
            int add = 0;
            for (int r = 0; r < totalRows; r++) {
                if (numAuto > 0 && m_grid[r].height.isAuto()) {
                    int toAdd = dh / numAuto;
                    add += toAdd;
                    dh -= toAdd;
                    numAuto--;
                }
                m_rowPos[r + 1] += add;
            }
        }
        if (dh > 0 && m_rowPos[totalRows]) {
            // if some left overs, distribute equally.
            int tot = m_rowPos[totalRows];
            int add = 0;
            int prev = m_rowPos[0];
            for (int r = 0; r < totalRows; r++) {
                //weight with the original height
                add += dh * (m_rowPos[r + 1] - prev) / tot;
                prev = m_rowPos[r + 1];
                m_rowPos[r + 1] += add;
            }
        }
    }

    int hspacing = table()->hBorderSpacing();
    int vspacing = table()->vBorderSpacing();
    int nEffCols = table()->numEffCols();

    view()->pushLayoutState(this, IntSize(m_x, m_y));

    for (int r = 0; r < totalRows; r++) {
        // Set the row's x/y position and width/height.
        if (RenderObject* rowRenderer = m_grid[r].rowRenderer) {
            rowRenderer->setPos(0, m_rowPos[r]);
            rowRenderer->setWidth(m_width);
            rowRenderer->setHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
        }

        for (int c = 0; c < nEffCols; c++) {
            RenderTableCell* cell = cellAt(r, c).cell;
            
            if (!cell)
                continue;
            if (r < totalRows - 1 && cell == cellAt(r + 1, c).cell)
                continue;

            rindx = max(0, r - cell->rowSpan() + 1);

            rHeight = m_rowPos[r + 1] - m_rowPos[rindx] - vspacing;
            
            // Force percent height children to lay themselves out again.
            // This will cause these children to grow to fill the cell.
            // FIXME: There is still more work to do here to fully match WinIE (should
            // it become necessary to do so).  In quirks mode, WinIE behaves like we
            // do, but it will clip the cells that spill out of the table section.  In
            // strict mode, Mozilla and WinIE both regrow the table to accommodate the
            // new height of the cell (thus letting the percentages cause growth one
            // time only).  We may also not be handling row-spanning cells correctly.
            //
            // Note also the oddity where replaced elements always flex, and yet blocks/tables do
            // not necessarily flex.  WinIE is crazy and inconsistent, and we can't hope to
            // match the behavior perfectly, but we'll continue to refine it as we discover new
            // bugs. :)
            bool cellChildrenFlex = false;
            bool flexAllChildren = cell->style()->height().isFixed() || 
                (!table()->style()->height().isAuto() && rHeight != cell->height());

            for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
                if (!o->isText() && o->style()->height().isPercent() && (o->isReplaced() || o->scrollsOverflow() || flexAllChildren)) {
                    // Tables with no sections do not flex.
                    if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
                        o->setNeedsLayout(true, false);
                        cell->setChildNeedsLayout(true, false);
                        cellChildrenFlex = true;
                    }
                }
            }
            if (cellChildrenFlex) {
                // Alignment within a cell is based off the calculated
                // height, which becomes irrelevant once the cell has
                // been resized based off its percentage. -dwh
                cell->setOverrideSize(max(0, 
                                           rHeight - cell->borderTop() - cell->paddingTop() - 
                                                     cell->borderBottom() - cell->paddingBottom()));
                cell->layoutIfNeeded();
                
                // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
                EVerticalAlign va = cell->style()->verticalAlign();
                if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
                    int b = cell->baselinePosition();
                    if (b > cell->borderTop() + cell->paddingTop())
                        m_grid[r].baseline = max(m_grid[r].baseline, b);
                }
            }
            
            int te = 0;
            switch (cell->style()->verticalAlign()) {
                case SUB:
                case SUPER:
                case TEXT_TOP:
                case TEXT_BOTTOM:
                case BASELINE:
                    te = getBaseline(r) - cell->baselinePosition();
                    break;
                case TOP:
                    te = 0;
                    break;
                case MIDDLE:
                    te = (rHeight - cell->height()) / 2;
                    break;
                case BOTTOM:
                    te = rHeight - cell->height();
                    break;
                default:
                    break;
            }
                
            int oldTe = cell->borderTopExtra();
            int oldBe = cell->borderBottomExtra();
                
            int be = rHeight - cell->height() - te;
            cell->setCellTopExtra(te);
            cell->setCellBottomExtra(be);
            if ((te != oldTe || be > oldBe) && !table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
                cell->repaint();
            
            IntRect oldCellRect(cell->xPos(), cell->yPos() - cell->borderTopExtra() , cell->width(), cell->height());
        
            if (style()->direction() == RTL) {
                cell->setPos(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
            } else
                cell->setPos(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);

            m_overflowLeft = min(m_overflowLeft, cell->xPos() + cell->overflowLeft(false));
            m_overflowWidth = max(m_overflowWidth, cell->xPos() + cell->overflowWidth(false));
            m_overflowTop = min(m_overflowTop, cell->yPos() + cell->overflowTop(false));
            m_overflowHeight = max(m_overflowHeight, cell->yPos() + cell->overflowHeight(false));
            m_hasOverflowingCell |= cell->overflowLeft(false) || cell->overflowWidth(false) > cell->width() || cell->overflowTop(false) || cell->overflowHeight(false) > cell->height();

            // If the cell moved, we have to repaint it as well as any floating/positioned
            // descendants.  An exception is if we need a layout.  In this case, we know we're going to
            // repaint ourselves (and the cell) anyway.
            if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
                cell->repaintDuringLayoutIfMoved(oldCellRect);
        }
    }

    view()->popLayoutState();

    m_height = m_rowPos[totalRows];
    m_overflowHeight = max(m_overflowHeight, m_height);
    return m_height;
}

int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
    int bottom = RenderContainer::lowestPosition(includeOverflowInterior, includeSelf);
    if (!includeOverflowInterior && hasOverflowClip())
        return bottom;

    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
            if (cell->isTableCell())
                bottom = max(bottom, cell->yPos() + cell->lowestPosition(false));
        }
    }
    
    return bottom;
}

int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
    int right = RenderContainer::rightmostPosition(includeOverflowInterior, includeSelf);
    if (!includeOverflowInterior && hasOverflowClip())
        return right;

    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
            if (cell->isTableCell())
                right = max(right, cell->xPos() + cell->rightmostPosition(false));
        }
    }
    
    return right;
}

int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
    int left = RenderContainer::leftmostPosition(includeOverflowInterior, includeSelf);
    if (!includeOverflowInterior && hasOverflowClip())
        return left;
    
    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
        for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
            if (cell->isTableCell())
                left = min(left, cell->xPos() + cell->leftmostPosition(false));
        }
    }
    
    return left;
}

int RenderTableSection::calcOuterBorderTop() const
{
    int totalCols = table()->numEffCols();
    if (!m_gridRows || !totalCols)
        return 0;

    unsigned borderWidth = 0;

    const BorderValue& sb = style()->borderTop();
    if (sb.style() == BHIDDEN)
        return -1;
    if (sb.style() > BHIDDEN)
        borderWidth = sb.width;

    const BorderValue& rb = firstChild()->style()->borderTop();
    if (rb.style() == BHIDDEN)
        return -1;
    if (rb.style() > BHIDDEN && rb.width > borderWidth)
        borderWidth = rb.width;

    bool allHidden = true;
    for (int c = 0; c < totalCols; c++) {
        const CellStruct& current = cellAt(0, c);
        if (current.inColSpan || !current.cell)
            continue;
        const BorderValue& cb = current.cell->style()->borderTop();
        // FIXME: Don't repeat for the same col group
        RenderTableCol* colGroup = table()->colElement(c);
        if (colGroup) {
            const BorderValue& gb = colGroup->style()->borderTop();
            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
                continue;
            else
                allHidden = false;
            if (gb.style() > BHIDDEN && gb.width > borderWidth)
                borderWidth = gb.width;
            if (cb.style() > BHIDDEN && cb.width > borderWidth)
                borderWidth = cb.width;
        } else {
            if (cb.style() == BHIDDEN)
                continue;
            else
                allHidden = false;
            if (cb.style() > BHIDDEN && cb.width > borderWidth)
                borderWidth = cb.width;
        }
    }
    if (allHidden)
        return -1;

    return borderWidth / 2;
}

int RenderTableSection::calcOuterBorderBottom() const
{
    int totalCols = table()->numEffCols();
    if (!m_gridRows || !totalCols)
        return 0;

    unsigned borderWidth = 0;

    const BorderValue& sb = style()->borderBottom();
    if (sb.style() == BHIDDEN)
        return -1;
    if (sb.style() > BHIDDEN)
        borderWidth = sb.width;

    const BorderValue& rb = lastChild()->style()->borderBottom();
    if (rb.style() == BHIDDEN)
        return -1;
    if (rb.style() > BHIDDEN && rb.width > borderWidth)
        borderWidth = rb.width;

    bool allHidden = true;
    for (int c = 0; c < totalCols; c++) {
        const CellStruct& current = cellAt(m_gridRows - 1, c);
        if (current.inColSpan || !current.cell)
            continue;
        const BorderValue& cb = current.cell->style()->borderBottom();
        // FIXME: Don't repeat for the same col group
        RenderTableCol* colGroup = table()->colElement(c);
        if (colGroup) {
            const BorderValue& gb = colGroup->style()->borderBottom();
            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
                continue;
            else
                allHidden = false;
            if (gb.style() > BHIDDEN && gb.width > borderWidth)
                borderWidth = gb.width;
            if (cb.style() > BHIDDEN && cb.width > borderWidth)
                borderWidth = cb.width;
        } else {
            if (cb.style() == BHIDDEN)
                continue;
            else
                allHidden = false;
            if (cb.style() > BHIDDEN && cb.width > borderWidth)
                borderWidth = cb.width;
        }
    }
    if (allHidden)
        return -1;

    return (borderWidth + 1) / 2;
}

int RenderTableSection::calcOuterBorderLeft(bool rtl) const
{
    int totalCols = table()->numEffCols();
    if (!m_gridRows || !totalCols)
        return 0;

    unsigned borderWidth = 0;

    const BorderValue& sb = style()->borderLeft();
    if (sb.style() == BHIDDEN)
        return -1;
    if (sb.style() > BHIDDEN)
        borderWidth = sb.width;

    int leftmostColumn = rtl ? totalCols - 1 : 0;
    RenderTableCol* colGroup = table()->colElement(leftmostColumn);
    if (colGroup) {
        const BorderValue& gb = colGroup->style()->borderLeft();
        if (gb.style() == BHIDDEN)
            return -1;
        if (gb.style() > BHIDDEN && gb.width > borderWidth)
            borderWidth = gb.width;
    }

    bool allHidden = true;
    for (int r = 0; r < m_gridRows; r++) {
        const CellStruct& current = cellAt(r, leftmostColumn);
        if (!current.cell)
            continue;
        // FIXME: Don't repeat for the same cell
        const BorderValue& cb = current.cell->style()->borderLeft();
        const BorderValue& rb = current.cell->parent()->style()->borderLeft();
        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
            continue;
        else
            allHidden = false;
        if (cb.style() > BHIDDEN && cb.width > borderWidth)
            borderWidth = cb.width;
        if (rb.style() > BHIDDEN && rb.width > borderWidth)
            borderWidth = rb.width;
    }
    if (allHidden)
        return -1;

    return borderWidth / 2;
}

int RenderTableSection::calcOuterBorderRight(bool rtl) const
{
    int totalCols = table()->numEffCols();
    if (!m_gridRows || !totalCols)
        return 0;

    unsigned borderWidth = 0;

    const BorderValue& sb = style()->borderRight();
    if (sb.style() == BHIDDEN)
        return -1;
    if (sb.style() > BHIDDEN)
        borderWidth = sb.width;

    int rightmostColumn = rtl ? 0 : totalCols - 1;
    RenderTableCol* colGroup = table()->colElement(rightmostColumn);
    if (colGroup) {
        const BorderValue& gb = colGroup->style()->borderRight();
        if (gb.style() == BHIDDEN)
            return -1;
        if (gb.style() > BHIDDEN && gb.width > borderWidth)
            borderWidth = gb.width;
    }

    bool allHidden = true;
    for (int r = 0; r < m_gridRows; r++) {
        const CellStruct& current = cellAt(r, rightmostColumn);
        if (!current.cell)
            continue;
        // FIXME: Don't repeat for the same cell
        const BorderValue& cb = current.cell->style()->borderRight();
        const BorderValue& rb = current.cell->parent()->style()->borderRight();
        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
            continue;
        else
            allHidden = false;
        if (cb.style() > BHIDDEN && cb.width > borderWidth)
            borderWidth = cb.width;
        if (rb.style() > BHIDDEN && rb.width > borderWidth)
            borderWidth = rb.width;
    }
    if (allHidden)
        return -1;

    return (borderWidth + 1) / 2;
}

void RenderTableSection::recalcOuterBorder()
{
    bool rtl = table()->style()->direction() == RTL;
    m_outerBorderTop = calcOuterBorderTop();
    m_outerBorderBottom = calcOuterBorderBottom();
    m_outerBorderLeft = calcOuterBorderLeft(rtl);
    m_outerBorderRight = calcOuterBorderRight(rtl);
}


void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
{
    // put this back in when all layout tests can handle it
    // ASSERT(!needsLayout());
    // avoid crashing on bugs that cause us to paint with dirty layout
    if (needsLayout())
        return;
    
    unsigned totalRows = m_gridRows;
    unsigned totalCols = table()->columns().size();

    if (!totalRows || !totalCols)
        return;

    tx += m_x;
    ty += m_y;

    // Check which rows and cols are visible and only paint these.
    // FIXME: Could use a binary search here.
    PaintPhase paintPhase = paintInfo.phase;
    int x = paintInfo.rect.x();
    int y = paintInfo.rect.y();
    int w = paintInfo.rect.width();
    int h = paintInfo.rect.height();

    int os = 2 * maximalOutlineSize(paintPhase);
    unsigned startrow = 0;
    unsigned endrow = totalRows;
    
    // If some cell overflows, just paint all of them.
    if (!m_hasOverflowingCell) {
        for (; startrow < totalRows; startrow++) {
            if (ty + m_rowPos[startrow + 1] >= y - os)
                break;
        }
        if (startrow == totalRows && ty + m_rowPos[totalRows] + table()->outerBorderBottom() >= y - os)
            startrow--;

        for (; endrow > 0; endrow--) {
            if (ty + m_rowPos[endrow - 1] <= y + h + os)
                break;
        }
        if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os)
            endrow++;
    }

    unsigned startcol = 0;
    unsigned endcol = totalCols;
    // FIXME: Implement RTL.
    if (!m_hasOverflowingCell && style()->direction() == LTR) {
        for (; startcol < totalCols; startcol++) {
            if (tx + table()->columnPositions()[startcol + 1] >= x - os)
                break;
        }
        if (startcol == totalCols && tx + table()->columnPositions()[totalCols] + table()->outerBorderRight() >= x - os)
            startcol--;

        for (; endcol > 0; endcol--) {
            if (tx + table()->columnPositions()[endcol - 1] <= x + w + os)
                break;
        }
        if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os)
            endcol++;
    }

    if (startcol < endcol) {
        // draw the cells
        for (unsigned r = startrow; r < endrow; r++) {
            unsigned c = startcol;
            // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
            while (c && cellAt(r, c).inColSpan)
                c--;
            for (; c < endcol; c++) {
                CellStruct current = cellAt(r, c);
                RenderTableCell* cell = current.cell;
                    
                // Cells must always paint in the order in which they appear taking into account
                // their upper left originating row/column.  For cells with rowspans, avoid repainting
                // if we've already seen the cell.
                if (!cell || (r > startrow && (cellAt(r - 1, c).cell == cell)))
                    continue;

                RenderTableRow* row = static_cast<RenderTableRow*>(cell->parent());

                if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
                    // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
                    // the column group, column, row group, row, and then the cell.
                    RenderObject* col = table()->colElement(c);
                    RenderObject* colGroup = 0;
                    if (col && col->parent()->style()->display() == TABLE_COLUMN_GROUP)
                        colGroup = col->parent();

                    // Column groups and columns first.
                    // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
                    // the stack, since we have already opened a transparency layer (potentially) for the table row group.
                    // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
                    // cell.
                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, colGroup);
                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, col);

                    // Paint the row group next.
                    cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);

                    // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
                    // painting the row background for the cell.
                    if (!row->hasLayer())
                        cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
                }

                if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
                    cell->paint(paintInfo, tx, ty);
            }
        }
    }
}

void RenderTableSection::imageChanged(CachedImage* image)
{
    if (!image || !image->canRender() || !parent())
        return;
    
    // FIXME: Examine cells and repaint only the rect the image paints in.
    repaint();
}

void RenderTableSection::recalcCells()
{
    m_cCol = 0;
    m_cRow = -1;
    clearGrid();
    m_gridRows = 0;

    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
        if (row->isTableRow()) {
            m_cRow++;
            m_cCol = 0;
            if (!ensureRows(m_cRow + 1))
                break;
            m_grid[m_cRow].rowRenderer = row;

            for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
                if (cell->isTableCell())
                    addCell(static_cast<RenderTableCell*>(cell), row);
            }
        }
    }
    m_needsCellRecalc = false;
    setNeedsLayout(true);
}

void RenderTableSection::clearGrid()
{
    int rows = m_gridRows;
    while (rows--)
        delete m_grid[rows].row;
}

int RenderTableSection::numColumns() const
{
    int result = 0;
    
    for (int r = 0; r < m_gridRows; ++r) {
        for (int c = result; c < table()->numEffCols(); ++c) {
            const CellStruct& cell = cellAt(r, c);
            if (cell.cell || cell.inColSpan)
                result = c;
        }
    }
    
    return result + 1;
}

void RenderTableSection::appendColumn(int pos)
{
    for (int row = 0; row < m_gridRows; ++row) {
        m_grid[row].row->resize(pos + 1);
        CellStruct& c = cellAt(row, pos);
        c.cell = 0;
        c.inColSpan = false;
    }
}

void RenderTableSection::splitColumn(int pos, int newSize)
{
    if (m_cCol > pos)
        m_cCol++;
    for (int row = 0; row < m_gridRows; ++row) {
        m_grid[row].row->resize(newSize);
        Row& r = *m_grid[row].row;
        memmove(r.data() + pos + 1, r.data() + pos, (newSize - 1 - pos) * sizeof(CellStruct));
        r[pos + 1].cell = 0;
        r[pos + 1].inColSpan = r[pos].inColSpan || r[pos].cell;
    }
}

RenderObject* RenderTableSection::removeChildNode(RenderObject* child, bool fullRemove)
{
    setNeedsCellRecalc();
    return RenderContainer::removeChildNode(child, fullRemove);
}

// Hit Testing
bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
{
    // Table sections cannot ever be hit tested.  Effectively they do not exist.
    // Just forward to our children always.
    tx += m_x;
    ty += m_y;

    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        // FIXME: We have to skip over inline flows, since they can show up inside table rows
        // at the moment (a demoted inline <form> for example). If we ever implement a
        // table-specific hit-test method (which we should do for performance reasons anyway),
        // then we can remove this check.
        if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
            updateHitTestResult(result, IntPoint(x - tx, y - ty));
            return true;
        }
    }
    
    return false;
}

#ifndef NDEBUG
void RenderTableSection::dump(TextStream* stream, DeprecatedString ind) const
{
    *stream << endl << ind << "grid=(" << m_gridRows << "," << table()->numEffCols() << ")" << endl << ind;
    for (int r = 0; r < m_gridRows; r++) {
        for (int c = 0; c < table()->numEffCols(); c++) {
            if (cellAt(r, c).cell && !cellAt(r, c).inColSpan)
                *stream << "(" << cellAt(r, c).cell->row() << "," << cellAt(r, c).cell->col() << ","
                        << cellAt(r, c).cell->rowSpan() << "," << cellAt(r, c).cell->colSpan() << ") ";
            else
                *stream << cellAt(r, c).cell << "null cell ";
        }
        *stream << endl << ind;
    }
    RenderContainer::dump(stream,ind);
}
#endif

} // namespace WebCore
