WebCore:
[WebKit-https.git] / WebCore / rendering / RenderTable.cpp
1 /**
2  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3  *           (C) 1997 Torben Weis (weis@kde.org)
4  *           (C) 1998 Waldo Bastian (bastian@kde.org)
5  *           (C) 1999 Lars Knoll (knoll@kde.org)
6  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
8  * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "RenderTable.h"
28
29 #include "AutoTableLayout.h"
30 #include "DeleteButtonController.h"
31 #include "Document.h"
32 #include "FixedTableLayout.h"
33 #include "FrameView.h"
34 #include "HTMLNames.h"
35 #include "RenderLayer.h"
36 #include "RenderTableCell.h"
37 #include "RenderTableCol.h"
38 #include "RenderTableSection.h"
39 #include "RenderView.h"
40 #include "TextStream.h"
41
42 using namespace std;
43
44 namespace WebCore {
45
46 using namespace HTMLNames;
47
48 RenderTable::RenderTable(Node* node)
49     : RenderBlock(node)
50     , m_caption(0)
51     , m_head(0)
52     , m_foot(0)
53     , m_firstBody(0)
54     , m_tableLayout(0)
55     , m_currentBorder(0)
56     , m_frame(Void)
57     , m_rules(None)
58     , m_hasColElements(false)
59     , m_padding(0)
60     , m_needsSectionRecalc(0)
61     , m_hSpacing(0)
62     , m_vSpacing(0)
63     , m_borderLeft(0)
64     , m_borderRight(0)
65 {
66     m_columnPos.fill(0, 2);
67     m_columns.fill(ColumnStruct(), 1);
68 }
69
70 RenderTable::~RenderTable()
71 {
72     delete m_tableLayout;
73 }
74
75 void RenderTable::setStyle(RenderStyle* newStyle)
76 {
77     ETableLayout oldTableLayout = style() ? style()->tableLayout() : TAUTO;
78     RenderBlock::setStyle(newStyle);
79
80     // In the collapsed border model, there is no cell spacing.
81     m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
82     m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
83     m_columnPos[0] = m_hSpacing;
84
85     if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
86         delete m_tableLayout;
87
88         // According to the CSS2 spec, you only use fixed table layout if an
89         // explicit width is specified on the table.  Auto width implies auto table layout.
90         if (style()->tableLayout() == TFIXED && !style()->width().isAuto())
91             m_tableLayout = new FixedTableLayout(this);
92         else
93             m_tableLayout = new AutoTableLayout(this);
94     }
95 }
96
97 static inline void resetSectionPointerIfNotBefore(RenderTableSection*& ptr, RenderObject* before)
98 {
99     if (!before || !ptr)
100         return;
101     RenderObject* o = before->previousSibling();
102     while (o && o != ptr)
103         o = o->previousSibling();
104     if (!o)
105         ptr = 0;
106 }
107
108 void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
109 {
110     // Make sure we don't append things after :after-generated content if we have it.
111     if (!beforeChild && isAfterContent(lastChild()))
112         beforeChild = lastChild();
113
114     bool wrapInAnonymousSection = true;
115     bool isTableElement = element() && element()->hasTagName(tableTag);
116
117     if (child->isRenderBlock() && child->style()->display() == TABLE_CAPTION) {
118         // First caption wins.
119         if (beforeChild && m_caption) {
120             RenderObject* o = beforeChild->previousSibling();
121             while (o && o != m_caption)
122                 o = o->previousSibling();
123             if (!o)
124                 m_caption = 0;
125         }
126         if (!m_caption)
127             m_caption = static_cast<RenderBlock*>(child);
128         wrapInAnonymousSection = false;
129     } else if (child->isTableCol()) {
130         m_hasColElements = true;
131         wrapInAnonymousSection = false;
132     } else if (child->isTableSection()) {
133         switch (child->style()->display()) {
134             case TABLE_HEADER_GROUP:
135                 if (child->isTableSection()) {
136                     resetSectionPointerIfNotBefore(m_head, beforeChild);
137                     if (!m_head) {
138                         m_head = static_cast<RenderTableSection*>(child);
139                     } else {
140                         resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
141                         if (!m_firstBody) 
142                             m_firstBody = static_cast<RenderTableSection*>(child);
143                     }
144                 }
145                 wrapInAnonymousSection = false;
146                 break;
147             case TABLE_FOOTER_GROUP:
148                 if (child->isTableSection()) {
149                     resetSectionPointerIfNotBefore(m_foot, beforeChild);
150                     if (!m_foot) {
151                         m_foot = static_cast<RenderTableSection*>(child);
152                         wrapInAnonymousSection = false;
153                         break;
154                     }
155                 }
156                 // Fall through.
157             case TABLE_ROW_GROUP:
158                 if (child->isTableSection()) {
159                     resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
160                     if (!m_firstBody)
161                         m_firstBody = static_cast<RenderTableSection*>(child);
162                 }
163                 wrapInAnonymousSection = false;
164                 break;
165             default:
166                 ASSERT_NOT_REACHED();
167         }
168     } else if (child->isTableCell() || child->isTableRow()) {
169         wrapInAnonymousSection = true;
170     } else {
171         // Allow a form to just sit at the top level.
172         wrapInAnonymousSection = !isTableElement || !child->element() || !(child->element()->hasTagName(formTag) && document()->isHTMLDocument());
173
174         // FIXME: Allow the delete button container element to sit at the top level. This is needed until http://bugs.webkit.org/show_bug.cgi?id=11363 is fixed.
175         if (wrapInAnonymousSection && child->element() && child->element()->isHTMLElement() && static_cast<HTMLElement*>(child->element())->id() == DeleteButtonController::containerElementIdentifier)
176             wrapInAnonymousSection = false;
177     }
178
179     if (!wrapInAnonymousSection) {
180         // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
181         while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION)
182             beforeChild = beforeChild->parent();
183
184         RenderContainer::addChild(child, beforeChild);
185         return;
186     }
187
188     if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
189         lastChild()->addChild(child);
190         return;
191     }
192
193     RenderObject* lastBox = beforeChild;
194     while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION)
195         lastBox = lastBox->parent();
196     if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
197         lastBox->addChild(child, beforeChild);
198         return;
199     }
200
201     if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION)
202         beforeChild = 0;
203     RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
204     RenderStyle* newStyle = new (renderArena()) RenderStyle();
205     newStyle->inheritFrom(style());
206     newStyle->setDisplay(TABLE_ROW_GROUP);
207     section->setStyle(newStyle);
208     addChild(section, beforeChild);
209     section->addChild(child);
210 }
211
212 void RenderTable::calcWidth()
213 {
214     if (isPositioned())
215         calcAbsoluteHorizontal();
216
217     RenderBlock* cb = containingBlock();
218     int availableWidth = cb->availableWidth();
219
220     LengthType widthType = style()->width().type();
221     if (widthType > Relative && style()->width().isPositive()) {
222         // Percent or fixed table
223         m_width = style()->width().calcMinValue(availableWidth);
224         m_width = max(minPrefWidth(), m_width);
225     } else {
226         // An auto width table should shrink to fit within the line width if necessary in order to 
227         // avoid overlapping floats.
228         availableWidth = cb->lineWidth(m_y);
229         
230         // Subtract out any fixed margins from our available width for auto width tables.
231         int marginTotal = 0;
232         if (!style()->marginLeft().isAuto())
233             marginTotal += style()->marginLeft().calcValue(availableWidth);
234         if (!style()->marginRight().isAuto())
235             marginTotal += style()->marginRight().calcValue(availableWidth);
236             
237         // Subtract out our margins to get the available content width.
238         int availContentWidth = max(0, availableWidth - marginTotal);
239         
240         // Ensure we aren't bigger than our max width or smaller than our min width.
241         m_width = min(availContentWidth, maxPrefWidth());
242     }
243     
244     m_width = max(m_width, minPrefWidth());
245
246     // Finally, with our true width determined, compute our margins for real.
247     m_marginRight = 0;
248     m_marginLeft = 0;
249     calcHorizontalMargins(style()->marginLeft(), style()->marginRight(), availableWidth);
250 }
251
252 void RenderTable::layout()
253 {
254     ASSERT(needsLayout());
255
256     if (layoutOnlyPositionedObjects())
257         return;
258
259     recalcSectionsIfNeeded();
260         
261     IntRect oldBounds;
262     IntRect oldOutlineBox;
263     bool checkForRepaint = checkForRepaintDuringLayout();
264     if (checkForRepaint) {
265         oldBounds = absoluteClippedOverflowRect();
266         oldOutlineBox = absoluteOutlineBox();
267     }
268     
269     view()->pushLayoutState(this, IntSize(m_x, m_y));
270
271     m_height = 0;
272     m_overflowHeight = 0;
273     m_overflowTop = 0;
274     initMaxMarginValues();
275     
276     int oldWidth = m_width;
277     calcWidth();
278
279     if (m_caption && m_width != oldWidth)
280         m_caption->setNeedsLayout(true, false);
281
282     // FIXME: The optimisation below doesn't work since the internal table
283     // layout could have changed.  we need to add a flag to the table
284     // layout that tells us if something has changed in the min max
285     // calculations to do it correctly.
286 //     if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )
287     m_tableLayout->layout();
288
289     setCellWidths();
290
291     // layout child objects
292     int calculatedHeight = 0;
293     int oldTableTop = m_caption ? m_caption->height() + m_caption->marginTop() + m_caption->marginBottom() : 0;
294
295     RenderObject* child = firstChild();
296     while (child) {
297         // FIXME: What about a form that has a display value that makes it a table section?
298         if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag)))
299             child->layout();
300         if (child->isTableSection()) {
301             static_cast<RenderTableSection*>(child)->calcRowHeight();
302             calculatedHeight += static_cast<RenderTableSection*>(child)->layoutRows(0);
303         }
304         child = child->nextSibling();
305     }
306
307     m_overflowWidth = m_width + (collapseBorders() ? outerBorderRight() - borderRight() : 0);
308     m_overflowLeft = collapseBorders() ? borderLeft() - outerBorderLeft() : 0;
309
310     // If any table section moved vertically, we will just repaint everything from that
311     // section down (it is quite unlikely that any of the following sections
312     // did not shift).
313     bool sectionMoved = false;
314     int movedSectionTop = 0;
315
316     // FIXME: Collapse caption margin.
317     if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
318         IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
319
320         m_caption->setPos(m_caption->marginLeft(), m_height);
321         if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
322             m_caption->repaintDuringLayoutIfMoved(captionRect);
323
324         m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
325         m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
326         m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
327         m_overflowTop = min(m_overflowTop, m_caption->yPos() + m_caption->overflowTop(false));
328         m_overflowHeight = max(m_overflowHeight, m_caption->yPos() + m_caption->overflowHeight(false));
329
330         if (m_height != oldTableTop) {
331             sectionMoved = true;
332             movedSectionTop = min(m_height, oldTableTop);
333         }
334     }
335
336     int bpTop = borderTop() + (collapseBorders() ? 0 : paddingTop());
337     int bpBottom = borderBottom() + (collapseBorders() ? 0 : paddingBottom());
338     
339     m_height += bpTop;
340
341     int oldHeight = m_height;
342     if (!isPositioned())
343         calcHeight();
344     m_height = oldHeight;
345
346     Length h = style()->height();
347     int th = 0;
348     if (h.isFixed())
349         // Tables size as though CSS height includes border/padding.
350         th = h.value() - (bpTop + bpBottom);
351     else if (h.isPercent())
352         th = calcPercentageHeight(h);
353     th = max(0, th);
354
355     // layout rows
356     if (th > calculatedHeight) {
357         // we have to redistribute that height to get the constraint correctly
358         // just force the first body to the height needed
359         // FIXME: This should take height constraints on all table sections into account and distribute
360         // accordingly. For now this should be good enough.
361         if (m_firstBody) {
362             m_firstBody->calcRowHeight();
363             m_firstBody->layoutRows(th - calculatedHeight);
364         } else if (!style()->htmlHacks())
365             // Completely empty tables (with no sections or anything) should at least honor specified height
366             // in strict mode.
367             m_height += th;
368     }
369     
370     int bl = borderLeft();
371     if (!collapseBorders())
372         bl += paddingLeft();
373
374     // position the table sections
375     RenderTableSection* section = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
376     while (section) {
377         if (!sectionMoved && section->yPos() != m_height) {
378             sectionMoved = true;
379             movedSectionTop = min(m_height, section->yPos()) + section->overflowTop(false);
380         }
381         section->setPos(bl, m_height);
382
383         m_height += section->height();
384         m_overflowLeft = min(m_overflowLeft, section->xPos() + section->overflowLeft(false));
385         m_overflowWidth = max(m_overflowWidth, section->xPos() + section->overflowWidth(false));
386         m_overflowTop = min(m_overflowTop, section->yPos() + section->overflowTop(false));
387         m_overflowHeight = max(m_overflowHeight, section->yPos() + section->overflowHeight(false));
388         section = sectionBelow(section);
389     }
390
391     m_height += bpBottom;
392
393     if (m_caption && m_caption->style()->captionSide() == CAPBOTTOM) {
394         IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
395
396         m_caption->setPos(m_caption->marginLeft(), m_height);
397         if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
398             m_caption->repaintDuringLayoutIfMoved(captionRect);
399
400         m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
401         m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
402         m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
403     }
404
405     if (isPositioned())
406         calcHeight();
407
408     m_overflowHeight = max(m_overflowHeight, m_height);
409
410     // table can be containing block of positioned elements.
411     // FIXME: Only pass true if width or height changed.
412     layoutPositionedObjects(true);
413
414     if (!hasOverflowClip()) {
415         if (ShadowData* boxShadow = style()->boxShadow()) {
416             m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
417             m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
418             m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
419             m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
420         }
421     }
422
423     view()->popLayoutState();
424
425     bool didFullRepaint = true;
426     // Repaint with our new bounds if they are different from our old bounds.
427     if (checkForRepaint)
428         didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
429     if (!didFullRepaint && sectionMoved) {
430         IntRect repaintRect(m_overflowLeft, movedSectionTop, m_overflowWidth - m_overflowLeft, m_overflowHeight - movedSectionTop);
431         if (FrameView* frameView = view()->frameView())
432             frameView->addRepaintInfo(this, repaintRect);
433     }
434     
435     setNeedsLayout(false);
436 }
437
438 void RenderTable::setCellWidths()
439 {
440     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
441         if (child->isTableSection())
442             static_cast<RenderTableSection*>(child)->setCellWidths();
443     }
444 }
445
446 void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
447 {
448     tx += xPos();
449     ty += yPos();
450
451     PaintPhase paintPhase = paintInfo.phase;
452
453     int os = 2 * maximalOutlineSize(paintPhase);
454     if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + overflowHeight(false) <= paintInfo.rect.y() - os)
455         return;
456     if (tx + overflowLeft(false) >= paintInfo.rect.right() + os || tx + overflowWidth(false) <= paintInfo.rect.x() - os)
457         return;
458
459     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
460         paintBoxDecorations(paintInfo, tx, ty);
461
462     // We're done.  We don't bother painting any children.
463     if (paintPhase == PaintPhaseBlockBackground)
464         return;
465
466     // We don't paint our own background, but we do let the kids paint their backgrounds.
467     if (paintPhase == PaintPhaseChildBlockBackgrounds)
468         paintPhase = PaintPhaseChildBlockBackground;
469     PaintInfo info(paintInfo);
470     info.phase = paintPhase;
471     info.paintingRoot = paintingRootForChildren(paintInfo);
472
473     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
474         if (!child->hasLayer() && (child->isTableSection() || child == m_caption))
475             child->paint(info, tx, ty);
476     }
477
478     if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
479         // Collect all the unique border styles that we want to paint in a sorted list.  Once we
480         // have all the styles sorted, we then do individual passes, painting each style of border
481         // from lowest precedence to highest precedence.
482         info.phase = PaintPhaseCollapsedTableBorders;
483         RenderTableCell::CollapsedBorderStyles borderStyles;
484         RenderObject* stop = nextInPreOrderAfterChildren();
485         for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder())
486             if (o->isTableCell())
487                 static_cast<RenderTableCell*>(o)->collectBorderStyles(borderStyles);
488         RenderTableCell::sortBorderStyles(borderStyles);
489         size_t count = borderStyles.size();
490         for (size_t i = 0; i < count; ++i) {
491             m_currentBorder = &borderStyles[i];
492             for (RenderObject* child = firstChild(); child; child = child->nextSibling())
493                 if (child->isTableSection())
494                     child->paint(info, tx, ty);
495         }
496         m_currentBorder = 0;
497     }
498 }
499
500 void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
501 {
502     int w = width();
503     int h = height();
504
505     // Account for the caption.
506     if (m_caption) {
507         int captionHeight = (m_caption->height() + m_caption->marginBottom() +  m_caption->marginTop());
508         h -= captionHeight;
509         if (m_caption->style()->captionSide() != CAPBOTTOM)
510             ty += captionHeight;
511     }
512
513     int my = max(ty, paintInfo.rect.y());
514     int mh;
515     if (ty < paintInfo.rect.y())
516         mh = max(0, h - (paintInfo.rect.y() - ty));
517     else
518         mh = min(paintInfo.rect.height(), h);
519
520     paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
521     
522     paintBackground(paintInfo.context, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
523
524     if (style()->hasBorder() && !collapseBorders())
525         paintBorder(paintInfo.context, tx, ty, w, h, style());
526 }
527
528 void RenderTable::calcPrefWidths()
529 {
530     ASSERT(prefWidthsDirty());
531
532     recalcSectionsIfNeeded();
533     recalcHorizontalBorders();
534
535     m_tableLayout->calcPrefWidths(m_minPrefWidth, m_maxPrefWidth);
536
537     if (m_caption)
538         m_minPrefWidth = max(m_minPrefWidth, m_caption->minPrefWidth());
539
540     setPrefWidthsDirty(false);
541 }
542
543 void RenderTable::splitColumn(int pos, int firstSpan)
544 {
545     // we need to add a new columnStruct
546     int oldSize = m_columns.size();
547     m_columns.resize(oldSize + 1);
548     int oldSpan = m_columns[pos].span;
549     ASSERT(oldSpan > firstSpan);
550     m_columns[pos].span = firstSpan;
551     memmove(m_columns.data() + pos + 1, m_columns.data() + pos, (oldSize - pos) * sizeof(ColumnStruct));
552     m_columns[pos + 1].span = oldSpan - firstSpan;
553
554     // change width of all rows.
555     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
556         if (child->isTableSection())
557             static_cast<RenderTableSection*>(child)->splitColumn(pos, oldSize + 1);
558     }
559
560     m_columnPos.resize(numEffCols() + 1);
561     setNeedsLayoutAndPrefWidthsRecalc();
562 }
563
564 void RenderTable::appendColumn(int span)
565 {
566     // easy case.
567     int pos = m_columns.size();
568     int newSize = pos + 1;
569     m_columns.resize(newSize);
570     m_columns[pos].span = span;
571
572     // change width of all rows.
573     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
574         if (child->isTableSection())
575             static_cast<RenderTableSection*>(child)->appendColumn(pos);
576     }
577
578     m_columnPos.resize(numEffCols() + 1);
579     setNeedsLayoutAndPrefWidthsRecalc();
580 }
581
582 RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge) const
583 {
584     if (!m_hasColElements)
585         return 0;
586     RenderObject* child = firstChild();
587     int cCol = 0;
588
589     while (child) {
590         if (child->isTableCol()) {
591             RenderTableCol* colElem = static_cast<RenderTableCol*>(child);
592             int span = colElem->span();
593             if (!colElem->firstChild()) {
594                 int startCol = cCol;
595                 int endCol = cCol + span - 1;
596                 cCol += span;
597                 if (cCol > col) {
598                     if (startEdge)
599                         *startEdge = startCol == col;
600                     if (endEdge)
601                         *endEdge = endCol == col;
602                     return colElem;
603                 }
604             }
605
606             RenderObject* next = child->firstChild();
607             if (!next)
608                 next = child->nextSibling();
609             if (!next && child->parent()->isTableCol())
610                 next = child->parent()->nextSibling();
611             child = next;
612         } else if (child == m_caption)
613             child = child->nextSibling();
614         else
615             break;
616     }
617
618     return 0;
619 }
620
621 void RenderTable::recalcSections() const
622 {
623     m_caption = 0;
624     m_head = 0;
625     m_foot = 0;
626     m_firstBody = 0;
627     m_hasColElements = false;
628
629     // We need to get valid pointers to caption, head, foot and first body again
630     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
631         switch (child->style()->display()) {
632             case TABLE_CAPTION:
633                 if (!m_caption && child->isRenderBlock()) {
634                     m_caption = static_cast<RenderBlock*>(child);
635                     m_caption->setNeedsLayout(true);
636                 }
637                 break;
638             case TABLE_COLUMN:
639             case TABLE_COLUMN_GROUP:
640                 m_hasColElements = true;
641                 break;
642             case TABLE_HEADER_GROUP:
643                 if (child->isTableSection()) {
644                     RenderTableSection* section = static_cast<RenderTableSection*>(child);
645                     if (!m_head)
646                         m_head = section;
647                     else if (!m_firstBody)
648                         m_firstBody = section;
649                     section->recalcCellsIfNeeded();
650                 }
651                 break;
652             case TABLE_FOOTER_GROUP:
653                 if (child->isTableSection()) {
654                     RenderTableSection* section = static_cast<RenderTableSection*>(child);
655                     if (!m_foot)
656                         m_foot = section;
657                     else if (!m_firstBody)
658                         m_firstBody = section;
659                     section->recalcCellsIfNeeded();
660                 }
661                 break;
662             case TABLE_ROW_GROUP:
663                 if (child->isTableSection()) {
664                     RenderTableSection* section = static_cast<RenderTableSection*>(child);
665                     if (!m_firstBody)
666                         m_firstBody = section;
667                     section->recalcCellsIfNeeded();
668                 }
669                 break;
670             default:
671                 break;
672         }
673     }
674
675     // repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
676     int maxCols = 0;
677     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
678         if (child->isTableSection()) {
679             RenderTableSection* section = static_cast<RenderTableSection*>(child);
680             int sectionCols = section->numColumns();
681             if (sectionCols > maxCols)
682                 maxCols = sectionCols;
683         }
684     }
685     
686     m_columns.resize(maxCols);
687     m_columnPos.resize(maxCols + 1);
688
689     ASSERT(selfNeedsLayout());
690
691     m_needsSectionRecalc = false;
692 }
693
694 RenderObject* RenderTable::removeChildNode(RenderObject* child, bool fullRemove)
695 {
696     setNeedsSectionRecalc();
697     return RenderContainer::removeChildNode(child, fullRemove);
698 }
699
700 int RenderTable::calcBorderLeft() const
701 {
702     if (collapseBorders()) {
703         // Determined by the first cell of the first row. See the CSS 2.1 spec, section 17.6.2.
704         if (!numEffCols())
705             return 0;
706
707         unsigned borderWidth = 0;
708
709         const BorderValue& tb = style()->borderLeft();
710         if (tb.style() == BHIDDEN)
711             return 0;
712         if (tb.style() > BHIDDEN)
713             borderWidth = tb.width;
714
715         int leftmostColumn = style()->direction() == RTL ? numEffCols() - 1 : 0;
716         RenderTableCol* colGroup = colElement(leftmostColumn);
717         if (colGroup) {
718             const BorderValue& gb = style()->borderLeft();
719             if (gb.style() == BHIDDEN)
720                 return 0;
721             if (gb.style() > BHIDDEN)
722                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width));
723         }
724         
725         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
726         if (firstNonEmptySection && !firstNonEmptySection->numRows())
727             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
728         
729         if (firstNonEmptySection) {
730             const BorderValue& sb = firstNonEmptySection->style()->borderLeft();
731             if (sb.style() == BHIDDEN)
732                 return 0;
733
734             if (sb.style() > BHIDDEN)
735                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width));
736
737             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, leftmostColumn);
738             
739             if (cs.cell) {
740                 const BorderValue& cb = cs.cell->style()->borderLeft();
741                 if (cb.style() == BHIDDEN)
742                     return 0;
743
744                 const BorderValue& rb = cs.cell->parent()->style()->borderLeft();
745                 if (rb.style() == BHIDDEN)
746                     return 0;
747
748                 if (cb.style() > BHIDDEN)
749                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width));
750                 if (rb.style() > BHIDDEN)
751                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width));
752             }
753         }
754         return borderWidth / 2;
755     }
756     return RenderBlock::borderLeft();
757 }
758     
759 int RenderTable::calcBorderRight() const
760 {
761     if (collapseBorders()) {
762         // Determined by the last cell of the first row. See the CSS 2.1 spec, section 17.6.2.
763         if (!numEffCols())
764             return 0;
765
766         unsigned borderWidth = 0;
767
768         const BorderValue& tb = style()->borderRight();
769         if (tb.style() == BHIDDEN)
770             return 0;
771         if (tb.style() > BHIDDEN)
772             borderWidth = tb.width;
773
774         int rightmostColumn = style()->direction() == RTL ? 0 : numEffCols() - 1;
775         RenderTableCol* colGroup = colElement(rightmostColumn);
776         if (colGroup) {
777             const BorderValue& gb = style()->borderRight();
778             if (gb.style() == BHIDDEN)
779                 return 0;
780             if (gb.style() > BHIDDEN)
781                 borderWidth = max(borderWidth, static_cast<unsigned>(gb.width));
782         }
783         
784         RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
785         if (firstNonEmptySection && !firstNonEmptySection->numRows())
786             firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
787         
788         if (firstNonEmptySection) {
789             const BorderValue& sb = firstNonEmptySection->style()->borderRight();
790             if (sb.style() == BHIDDEN)
791                 return 0;
792
793             if (sb.style() > BHIDDEN)
794                 borderWidth = max(borderWidth, static_cast<unsigned>(sb.width));
795
796             const RenderTableSection::CellStruct& cs = firstNonEmptySection->cellAt(0, rightmostColumn);
797             
798             if (cs.cell) {
799                 const BorderValue& cb = cs.cell->style()->borderRight();
800                 if (cb.style() == BHIDDEN)
801                     return 0;
802
803                 const BorderValue& rb = cs.cell->parent()->style()->borderRight();
804                 if (rb.style() == BHIDDEN)
805                     return 0;
806
807                 if (cb.style() > BHIDDEN)
808                     borderWidth = max(borderWidth, static_cast<unsigned>(cb.width));
809                 if (rb.style() > BHIDDEN)
810                     borderWidth = max(borderWidth, static_cast<unsigned>(rb.width));
811             }
812         }
813         return (borderWidth + 1) / 2;
814     }
815     return RenderBlock::borderRight();
816 }
817
818 void RenderTable::recalcHorizontalBorders()
819 {
820     m_borderLeft = calcBorderLeft();
821     m_borderRight = calcBorderRight();
822 }
823
824 int RenderTable::borderTop() const
825 {
826     if (collapseBorders())
827         return outerBorderTop();
828     return RenderBlock::borderTop();
829 }
830
831 int RenderTable::borderBottom() const
832 {
833     if (collapseBorders())
834         return outerBorderBottom();
835     return RenderBlock::borderBottom();
836 }
837
838 int RenderTable::outerBorderTop() const
839 {
840     if (!collapseBorders())
841         return 0;
842     int borderWidth = 0;
843     RenderTableSection* topSection;
844     if (m_head)
845         topSection = m_head;
846     else if (m_firstBody)
847         topSection = m_firstBody;
848     else if (m_foot)
849         topSection = m_foot;
850     else
851         topSection = 0;
852     if (topSection) {
853         borderWidth = topSection->outerBorderTop();
854         if (borderWidth == -1)
855             return 0;   // Overridden by hidden
856     }
857     const BorderValue& tb = style()->borderTop();
858     if (tb.style() == BHIDDEN)
859         return 0;
860     if (tb.style() > BHIDDEN)
861         borderWidth = max(borderWidth, static_cast<int>(tb.width / 2));
862     return borderWidth;
863 }
864
865 int RenderTable::outerBorderBottom() const
866 {
867     if (!collapseBorders())
868         return 0;
869     int borderWidth = 0;
870     RenderTableSection* bottomSection;
871     if (m_foot)
872         bottomSection = m_foot;
873     else {
874         RenderObject* child;
875         for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling())
876             ;
877         bottomSection = child ? static_cast<RenderTableSection*>(child) : 0;
878     }
879     if (bottomSection) {
880         borderWidth = bottomSection->outerBorderBottom();
881         if (borderWidth == -1)
882             return 0;   // Overridden by hidden
883     }
884     const BorderValue& tb = style()->borderBottom();
885     if (tb.style() == BHIDDEN)
886         return 0;
887     if (tb.style() > BHIDDEN)
888         borderWidth = max(borderWidth, static_cast<int>((tb.width + 1) / 2));
889     return borderWidth;
890 }
891
892 int RenderTable::outerBorderLeft() const
893 {
894     if (!collapseBorders())
895         return 0;
896
897     int borderWidth = 0;
898
899     const BorderValue& tb = style()->borderLeft();
900     if (tb.style() == BHIDDEN)
901         return 0;
902     if (tb.style() > BHIDDEN)
903         borderWidth = tb.width / 2;
904
905     bool allHidden = true;
906     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
907         if (!child->isTableSection())
908             continue;
909         int sw = static_cast<RenderTableSection*>(child)->outerBorderLeft();
910         if (sw == -1)
911             continue;
912         else
913             allHidden = false;
914         borderWidth = max(borderWidth, sw);
915     }
916     if (allHidden)
917         return 0;
918
919     return borderWidth;
920 }
921
922 int RenderTable::outerBorderRight() const
923 {
924     if (!collapseBorders())
925         return 0;
926
927     int borderWidth = 0;
928
929     const BorderValue& tb = style()->borderRight();
930     if (tb.style() == BHIDDEN)
931         return 0;
932     if (tb.style() > BHIDDEN)
933         borderWidth = (tb.width + 1) / 2;
934
935     bool allHidden = true;
936     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
937         if (!child->isTableSection())
938             continue;
939         int sw = static_cast<RenderTableSection*>(child)->outerBorderRight();
940         if (sw == -1)
941             continue;
942         else
943             allHidden = false;
944         borderWidth = max(borderWidth, sw);
945     }
946     if (allHidden)
947         return 0;
948
949     return borderWidth;
950 }
951
952 RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
953 {
954     recalcSectionsIfNeeded();
955
956     if (section == m_head)
957         return 0;
958
959     RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
960     while (prevSection) {
961         if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(prevSection)->numRows()))
962             break;
963         prevSection = prevSection->previousSibling();
964     }
965     if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
966         prevSection = m_head;
967     return static_cast<RenderTableSection*>(prevSection);
968 }
969
970 RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
971 {
972     recalcSectionsIfNeeded();
973
974     if (section == m_foot)
975         return 0;
976
977     RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
978     while (nextSection) {
979         if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(nextSection)->numRows()))
980             break;
981         nextSection = nextSection->nextSibling();
982     }
983     if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
984         nextSection = m_foot;
985     return static_cast<RenderTableSection*>(nextSection);
986 }
987
988 RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
989 {
990     recalcSectionsIfNeeded();
991
992     // Find the section and row to look in
993     int r = cell->row();
994     RenderTableSection* section = 0;
995     int rAbove = 0;
996     if (r > 0) {
997         // cell is not in the first row, so use the above row in its own section
998         section = cell->section();
999         rAbove = r - 1;
1000     } else {
1001         section = sectionAbove(cell->section(), true);
1002         if (section)
1003             rAbove = section->numRows() - 1;
1004     }
1005
1006     // Look up the cell in the section's grid, which requires effective col index
1007     if (section) {
1008         int effCol = colToEffCol(cell->col());
1009         RenderTableSection::CellStruct aboveCell;
1010         // If we hit a span back up to a real cell.
1011         do {
1012             aboveCell = section->cellAt(rAbove, effCol);
1013             effCol--;
1014         } while (!aboveCell.cell && aboveCell.inColSpan && effCol >= 0);
1015         return aboveCell.cell;
1016     } else
1017         return 0;
1018 }
1019
1020 RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
1021 {
1022     recalcSectionsIfNeeded();
1023
1024     // Find the section and row to look in
1025     int r = cell->row() + cell->rowSpan() - 1;
1026     RenderTableSection* section = 0;
1027     int rBelow = 0;
1028     if (r < cell->section()->numRows() - 1) {
1029         // The cell is not in the last row, so use the next row in the section.
1030         section = cell->section();
1031         rBelow = r + 1;
1032     } else {
1033         section = sectionBelow(cell->section(), true);
1034         if (section)
1035             rBelow = 0;
1036     }
1037
1038     // Look up the cell in the section's grid, which requires effective col index
1039     if (section) {
1040         int effCol = colToEffCol(cell->col());
1041         RenderTableSection::CellStruct belowCell;
1042         // If we hit a colspan back up to a real cell.
1043         do {
1044             belowCell = section->cellAt(rBelow, effCol);
1045             effCol--;
1046         } while (!belowCell.cell && belowCell.inColSpan && effCol >= 0);
1047         return belowCell.cell;
1048     } else
1049         return 0;
1050 }
1051
1052 RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
1053 {
1054     recalcSectionsIfNeeded();
1055
1056     RenderTableSection* section = cell->section();
1057     int effCol = colToEffCol(cell->col());
1058     if (!effCol)
1059         return 0;
1060     
1061     // If we hit a colspan back up to a real cell.
1062     RenderTableSection::CellStruct prevCell;
1063     do {
1064         prevCell = section->cellAt(cell->row(), effCol - 1);
1065         effCol--;
1066     } while (!prevCell.cell && prevCell.inColSpan && effCol >= 0);
1067     return prevCell.cell;
1068 }
1069
1070 RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
1071 {
1072     recalcSectionsIfNeeded();
1073
1074     int effCol = colToEffCol(cell->col() + cell->colSpan());
1075     if (effCol >= numEffCols())
1076         return 0;
1077     return cell->section()->cellAt(cell->row(), effCol).cell;
1078 }
1079
1080 RenderBlock* RenderTable::firstLineBlock() const
1081 {
1082     return 0;
1083 }
1084
1085 void RenderTable::updateFirstLetter()
1086 {
1087 }
1088
1089 IntRect RenderTable::getOverflowClipRect(int tx, int ty)
1090 {
1091     IntRect rect = RenderBlock::getOverflowClipRect(tx, ty);
1092     
1093     // If we have a caption, expand the clip to include the caption.
1094     // FIXME: Technically this is wrong, but it's virtually impossible to fix this
1095     // for real until captions have been re-written.
1096     // FIXME: This code assumes (like all our other caption code) that only top/bottom are
1097     // supported.  When we actually support left/right and stop mapping them to top/bottom,
1098     // we might have to hack this code first (depending on what order we do these bug fixes in).
1099     if (m_caption) {
1100         rect.setHeight(height());
1101         rect.setY(ty);
1102     }
1103
1104     return rect;
1105 }
1106
1107 #ifndef NDEBUG
1108 void RenderTable::dump(TextStream* stream, DeprecatedString ind) const
1109 {
1110     if (m_caption)
1111         *stream << " tCaption";
1112     if (m_head)
1113         *stream << " head";
1114     if (m_foot)
1115         *stream << " foot";
1116
1117     *stream << endl << ind << "cspans:";
1118     for (unsigned i = 0; i < m_columns.size(); i++)
1119         *stream << " " << m_columns[i].span;
1120     *stream << endl << ind;
1121
1122     RenderBlock::dump(stream, ind);
1123 }
1124 #endif
1125
1126 }