00001
00026
00027
00028
00029
00030 #include "rendering/render_table.h"
00031 #include "rendering/table_layout.h"
00032 #include "html/html_tableimpl.h"
00033 #include "misc/htmltags.h"
00034
00035 #include <kglobal.h>
00036
00037 #include <qapplication.h>
00038 #include <qstyle.h>
00039
00040 #include <kdebug.h>
00041 #include <assert.h>
00042
00043 using namespace khtml;
00044
00045 RenderTable::RenderTable(DOM::NodeImpl* node)
00046 : RenderFlow(node)
00047 {
00048
00049 tCaption = 0;
00050 head = 0;
00051 foot = 0;
00052 firstBody = 0;
00053
00054 m_maxWidth = 0;
00055
00056 tableLayout = 0;
00057
00058 rules = None;
00059 frame = Void;
00060 has_col_elems = false;
00061 needSectionRecalc = false;
00062 padding = 0;
00063
00064 columnPos.resize( 2 );
00065 columnPos.fill( 0 );
00066 columns.resize( 1 );
00067 columns.fill( ColumnStruct() );
00068
00069 columnPos[0] = 0;
00070 }
00071
00072 RenderTable::~RenderTable()
00073 {
00074 delete tableLayout;
00075 }
00076
00077 void RenderTable::setStyle(RenderStyle *_style)
00078 {
00079 ETableLayout oldTableLayout = style() ? style()->tableLayout() : TAUTO;
00080 if ( _style->display() != INLINE_TABLE ) _style->setDisplay(TABLE);
00081 RenderFlow::setStyle(_style);
00082
00083
00084 setInline(style()->display()==INLINE_TABLE && !isPositioned());
00085 setReplaced(style()->display()==INLINE_TABLE);
00086
00087 spacing = style()->borderSpacing();
00088 columnPos[0] = spacing;
00089
00090 if ( !tableLayout || style()->tableLayout() != oldTableLayout ) {
00091 delete tableLayout;
00092
00093 if (style()->tableLayout() == TFIXED ) {
00094 tableLayout = new FixedTableLayout(this);
00095 #ifdef DEBUG_LAYOUT
00096 kdDebug( 6040 ) << "using fixed table layout" << endl;
00097 #endif
00098 } else
00099 tableLayout = new AutoTableLayout(this);
00100 }
00101 }
00102
00103 void RenderTable::position(int x, int y, int, int, int, bool, bool, int)
00104 {
00105
00106 m_x = x + marginLeft();
00107 m_y = y + marginTop();
00108 }
00109
00110 void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild)
00111 {
00112 #ifdef DEBUG_LAYOUT
00113 kdDebug( 6040 ) << renderName() << "(Table)::addChild( " << child->renderName() << ", " <<
00114 (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
00115 #endif
00116 RenderObject *o = child;
00117
00118 switch(child->style()->display())
00119 {
00120 case TABLE_CAPTION:
00121 tCaption = static_cast<RenderFlow *>(child);
00122 break;
00123 case TABLE_COLUMN:
00124 case TABLE_COLUMN_GROUP:
00125 RenderContainer::addChild(child,beforeChild);
00126 has_col_elems = true;
00127 return;
00128 case TABLE_HEADER_GROUP:
00129 if ( !head )
00130 head = static_cast<RenderTableSection *>(child);
00131 break;
00132 case TABLE_FOOTER_GROUP:
00133 if ( !foot )
00134 foot = static_cast<RenderTableSection *>(child);
00135 break;
00136 case TABLE_ROW_GROUP:
00137 if(!firstBody)
00138 firstBody = static_cast<RenderTableSection *>(child);
00139 break;
00140 default:
00141 if ( !beforeChild && lastChild() &&
00142 lastChild()->isTableSection() && lastChild()->isAnonymousBox() ) {
00143 o = lastChild();
00144 } else {
00145 RenderObject *lastBox = beforeChild;
00146 while ( lastBox && lastBox->parent()->isAnonymousBox() &&
00147 !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION )
00148 lastBox = lastBox->parent();
00149 if ( lastBox && lastBox->isAnonymousBox() ) {
00150 lastBox->addChild( child, beforeChild );
00151 return;
00152 } else {
00153 if ( beforeChild && !beforeChild->isTableSection() )
00154 beforeChild = 0;
00155
00156 o = new RenderTableSection(0 );
00157 RenderStyle *newStyle = new RenderStyle();
00158 newStyle->inheritFrom(style());
00159 newStyle->setDisplay(TABLE_ROW_GROUP);
00160 o->setStyle(newStyle);
00161 o->setIsAnonymousBox(true);
00162 addChild(o, beforeChild);
00163 }
00164 }
00165 o->addChild(child);
00166 child->setLayouted( false );
00167 child->setMinMaxKnown( false );
00168 return;
00169 }
00170 RenderContainer::addChild(child,beforeChild);
00171 }
00172
00173
00174
00175 void RenderTable::calcWidth()
00176 {
00177 if ( isPositioned() ) {
00178 calcAbsoluteHorizontal();
00179 }
00180
00181 RenderObject *cb = containingBlock();
00182 int availableWidth = cb->contentWidth();
00183
00184 LengthType widthType = style()->width().type();
00185 if(widthType > Relative && style()->width().value() > 0) {
00186
00187 m_width = style()->width().minWidth( availableWidth );
00188 if(m_minWidth > m_width) m_width = m_minWidth;
00189
00190 } else {
00191 m_width = KMIN(short( availableWidth ),m_maxWidth);
00192 }
00193
00194
00195 if ( style()->flowAroundFloats() && cb->isFlow() ) {
00196 availableWidth = static_cast<RenderFlow *>(cb)->lineWidth( m_y );
00197 m_width = KMIN( short( availableWidth ), m_width );
00198 }
00199
00200 m_width = KMAX (m_width, m_minWidth);
00201
00202 m_marginRight=0;
00203 m_marginLeft=0;
00204
00205 calcHorizontalMargins(style()->marginLeft(),style()->marginRight(),availableWidth);
00206 }
00207
00208 void RenderTable::layout()
00209 {
00210 KHTMLAssert( !layouted() );
00211 KHTMLAssert( minMaxKnown() );
00212 KHTMLAssert( !needSectionRecalc );
00213
00214
00215
00216 m_height = 0;
00217
00218
00219 calcWidth();
00220
00221
00222
00223
00224
00225
00226 tableLayout->layout();
00227
00228 #ifdef DEBUG_LAYOUT
00229 kdDebug( 6040 ) << renderName() << "(Table)::layout1() width=" << width() << ", marginLeft=" << marginLeft() << " marginRight=" << marginRight() << endl;
00230 #endif
00231
00232 setCellWidths();
00233
00234
00235 int calculatedHeight = 0;
00236
00237 RenderObject *child = firstChild();
00238 while( child ) {
00239 if ( !child->layouted() )
00240 child->layout();
00241 if ( child->isTableSection() ) {
00242 static_cast<RenderTableSection *>(child)->calcRowHeight();
00243 calculatedHeight += static_cast<RenderTableSection *>(child)->layoutRows( 0 );
00244 }
00245 child = child->nextSibling();
00246 }
00247
00248
00249 if(tCaption && tCaption->style()->captionSide() != CAPBOTTOM) {
00250 tCaption->setPos(tCaption->marginLeft(), m_height);
00251 m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
00252 }
00253
00254 m_height += borderTop();
00255
00256
00257 Length h = style()->height();
00258 int th=0;
00259 if (h.isFixed())
00260 th = h.value();
00261 else if (h.isPercent()) {
00262 Length ch = containingBlock()->style()->height();
00263 if (ch.isFixed())
00264 th = h.width(ch.value());
00265 else {
00266
00267 RenderObject* ro = parent();
00268 for (; ro && !ro->isTableCell(); ro=ro->parent());
00269 if (!ro)
00270 {
00271
00272
00273 th = h.width(viewRect().height() - 20 );
00274
00275
00276 setOverhangingContents();
00277 }
00278 }
00279 }
00280
00281
00282 if ( th > calculatedHeight ) {
00283
00284
00285
00286
00287 if (firstBody) {
00288 firstBody->calcRowHeight();
00289 firstBody->layoutRows( th - calculatedHeight );
00290 }
00291 }
00292 int bl = borderLeft();
00293
00294
00295 if ( head ) {
00296 head->setPos(bl, m_height);
00297 m_height += head->height();
00298 }
00299 RenderTableSection *body = firstBody;
00300 while ( body ) {
00301 body->setPos(bl, m_height);
00302 m_height += body->height();
00303 RenderObject *next = body->nextSibling();
00304 if ( next && next->isTableSection() && next != foot )
00305 body = static_cast<RenderTableSection *>(next);
00306 else
00307 body = 0;
00308 }
00309 if ( foot ) {
00310 foot->setPos(bl, m_height);
00311 m_height += foot->height();
00312 }
00313
00314
00315 m_height += borderBottom();
00316
00317 if(tCaption && tCaption->style()->captionSide()==CAPBOTTOM) {
00318 tCaption->setPos(tCaption->marginLeft(), m_height);
00319 m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
00320 }
00321
00322
00323
00324 calcHeight();
00325
00326
00327
00328
00329
00330 layoutSpecialObjects( true );
00331
00332 setLayouted();
00333
00334 }
00335
00336 void RenderTable::setCellWidths()
00337 {
00338 #ifdef DEBUG_LAYOUT
00339 kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
00340 #endif
00341
00342 RenderObject *child = firstChild();
00343 while( child ) {
00344 if ( child->isTableSection() )
00345 static_cast<RenderTableSection *>(child)->setCellWidths();
00346 child = child->nextSibling();
00347 }
00348 }
00349
00350 void RenderTable::paint( QPainter *p, int _x, int _y,
00351 int _w, int _h, int _tx, int _ty)
00352 {
00353
00354 if(!layouted()) return;
00355
00356 _tx += xPos();
00357 _ty += yPos();
00358
00359
00360 if(isRelPositioned())
00361 relativePositionOffset(_tx, _ty);
00362
00363
00364 #ifdef TABLE_PRINT
00365 kdDebug( 6040 ) << "RenderTable::paint() w/h = (" << width() << "/" << height() << ")" << endl;
00366 #endif
00367 if (!overhangingContents() && !isRelPositioned() && !isPositioned())
00368 {
00369 if((_ty > _y + _h) || (_ty + height() < _y)) return;
00370 if((_tx > _x + _w) || (_tx + width() < _x)) return;
00371 }
00372
00373 bool clipped = false;
00374
00375 if (style()->overflow()==OHIDDEN || (style()->position() == ABSOLUTE && style()->clipSpecified()) ) {
00376 calcClip(p, _tx, _ty);
00377 clipped = true;
00378 }
00379
00380 #ifdef TABLE_PRINT
00381 kdDebug( 6040 ) << "RenderTable::paint(2) " << _tx << "/" << _ty << " (" << _y << "/" << _h << ")" << endl;
00382 #endif
00383
00384 if(style()->visibility() == VISIBLE)
00385 paintBoxDecorations(p, _x, _y, _w, _h, _tx, _ty);
00386
00387 RenderObject *child = firstChild();
00388 while( child ) {
00389 if ( child->isTableSection() || child == tCaption )
00390 child->paint( p, _x, _y, _w, _h, _tx, _ty );
00391 child = child->nextSibling();
00392 }
00393
00394 if ( specialObjects )
00395 paintSpecialObjects( p, _x, _y, _w, _h, _tx, _ty);
00396
00397
00398
00399
00400 if ( clipped )
00401 p->restore();
00402
00403 #ifdef BOX_DEBUG
00404 outlineBox(p, _tx, _ty, "blue");
00405 #endif
00406 }
00407
00408 void RenderTable::calcMinMaxWidth()
00409 {
00410 KHTMLAssert( !minMaxKnown() );
00411
00412 if ( needSectionRecalc )
00413 recalcSections();
00414
00415 #ifdef DEBUG_LAYOUT
00416 kdDebug( 6040 ) << renderName() << "(Table " << this << ")::calcMinMaxWidth()" << endl;
00417 #endif
00418
00419 tableLayout->calcMinMaxWidth();
00420
00421 if (tCaption && tCaption->minWidth() > m_minWidth)
00422 m_minWidth = tCaption->minWidth();
00423
00424 setMinMaxKnown();
00425 #ifdef DEBUG_LAYOUT
00426 kdDebug( 6040 ) << renderName() << " END: (Table " << this << ")::calcMinMaxWidth() min = " << m_minWidth << " max = " << m_maxWidth << endl;
00427 #endif
00428 }
00429
00430 void RenderTable::close()
00431 {
00432
00433 setLayouted(false);
00434 setMinMaxKnown(false);
00435 }
00436
00437 int RenderTable::borderTopExtra()
00438 {
00439 if (tCaption && tCaption->style()->captionSide()!=CAPBOTTOM)
00440 return -(tCaption->height() + tCaption->marginBottom() + tCaption->marginTop());
00441 else
00442 return 0;
00443
00444 }
00445
00446 int RenderTable::borderBottomExtra()
00447 {
00448 if (tCaption && tCaption->style()->captionSide()==CAPBOTTOM)
00449 return -(tCaption->height() + tCaption->marginBottom() + tCaption->marginTop());
00450 else
00451 return 0;
00452 }
00453
00454
00455 void RenderTable::splitColumn( int pos, int firstSpan )
00456 {
00457
00458 int oldSize = columns.size();
00459 columns.resize( oldSize + 1 );
00460 int oldSpan = columns[pos].span;
00461
00462 KHTMLAssert( oldSpan > firstSpan );
00463 columns[pos].span = firstSpan;
00464 memmove( columns.data()+pos+1, columns.data()+pos, (oldSize-pos)*sizeof(ColumnStruct) );
00465 columns[pos+1].span = oldSpan - firstSpan;
00466
00467
00468 RenderObject *child = firstChild();
00469 while ( child ) {
00470 if ( child->isTableSection() ) {
00471 RenderTableSection *section = static_cast<RenderTableSection *>(child);
00472 int size = section->grid.size();
00473 int row = 0;
00474 if ( section->cCol > pos )
00475 section->cCol++;
00476 while ( row < size ) {
00477 section->grid[row].row->resize( oldSize+1 );
00478 RenderTableSection::Row &r = *section->grid[row].row;
00479 memmove( r.data()+pos+1, r.data()+pos, (oldSize-pos)*sizeof( RenderTableCell * ) );
00480
00481 r[pos+1] = r[pos] ? (RenderTableCell *)-1 : 0;
00482 row++;
00483 }
00484 }
00485 child = child->nextSibling();
00486 }
00487 columnPos.resize( numEffCols()+1 );
00488 setMinMaxKnown( false );
00489 setLayouted( false );
00490 }
00491
00492 void RenderTable::appendColumn( int span )
00493 {
00494
00495 int pos = columns.size();
00496
00497 int newSize = pos + 1;
00498 columns.resize( newSize );
00499 columns[pos].span = span;
00500
00501
00502
00503 RenderObject *child = firstChild();
00504 while ( child ) {
00505 if ( child->isTableSection() ) {
00506 RenderTableSection *section = static_cast<RenderTableSection *>(child);
00507 int size = section->grid.size();
00508 int row = 0;
00509 while ( row < size ) {
00510 section->grid[row].row->resize( newSize );
00511 section->cellAt( row, pos ) = 0;
00512 row++;
00513 }
00514
00515 }
00516 child = child->nextSibling();
00517 }
00518 columnPos.resize( numEffCols()+1 );
00519 setMinMaxKnown( false );
00520 setLayouted( false );
00521 }
00522
00523 RenderTableCol *RenderTable::colElement( int col ) {
00524 if ( !has_col_elems )
00525 return 0;
00526 RenderObject *child = firstChild();
00527 int cCol = 0;
00528 while ( child ) {
00529 if ( child->isTableCol() ) {
00530 RenderTableCol *colElem = static_cast<RenderTableCol *>(child);
00531 int span = colElem->span();
00532 if ( !colElem->firstChild() ) {
00533 cCol += span;
00534 if ( cCol > col )
00535 return colElem;
00536 }
00537
00538 RenderObject *next = child->firstChild();
00539 if ( !next )
00540 next = child->nextSibling();
00541 if ( !next && child->parent()->isTableCol() )
00542 next = child->parent()->nextSibling();
00543 child = next;
00544 } else
00545 break;
00546 }
00547 return 0;
00548 }
00549
00550 void RenderTable::recalcSections()
00551 {
00552 tCaption = 0;
00553 head = foot = firstBody = 0;
00554 has_col_elems = false;
00555
00556 RenderObject *child = firstChild();
00557
00558 while ( child ) {
00559 switch(child->style()->display()) {
00560 case TABLE_CAPTION:
00561 if ( !tCaption) {
00562 tCaption = static_cast<RenderFlow*>(child);
00563 tCaption->setLayouted(false);
00564 }
00565 break;
00566 case TABLE_COLUMN:
00567 case TABLE_COLUMN_GROUP:
00568 has_col_elems = true;
00569 break;
00570 case TABLE_HEADER_GROUP: {
00571 RenderTableSection *section = static_cast<RenderTableSection *>(child);
00572 if ( !head )
00573 head = section;
00574 if ( section->needCellRecalc )
00575 section->recalcCells();
00576 break;
00577 }
00578 case TABLE_FOOTER_GROUP: {
00579 RenderTableSection *section = static_cast<RenderTableSection *>(child);
00580 if ( !foot )
00581 foot = section;
00582 if ( section->needCellRecalc )
00583 section->recalcCells();
00584 break;
00585 }
00586 case TABLE_ROW_GROUP: {
00587 RenderTableSection *section = static_cast<RenderTableSection *>(child);
00588 if ( !firstBody )
00589 firstBody = section;
00590 if ( section->needCellRecalc )
00591 section->recalcCells();
00592 }
00593 default:
00594 break;
00595 }
00596 child = child->nextSibling();
00597 }
00598 needSectionRecalc = false;
00599 setLayouted( false );
00600 }
00601
00602 RenderObject* RenderTable::removeChildNode(RenderObject* child)
00603 {
00604 setNeedSectionRecalc();
00605 return RenderContainer::removeChildNode( child );
00606 }
00607
00608
00609 #ifndef NDEBUG
00610 void RenderTable::dump(QTextStream *stream, QString ind) const
00611 {
00612 if (tCaption)
00613 *stream << " tCaption";
00614 if (head)
00615 *stream << " head";
00616 if (foot)
00617 *stream << " foot";
00618
00619 *stream << endl << ind << "cspans:";
00620 for ( unsigned int i = 0; i < columns.size(); i++ )
00621 *stream << " " << columns[i].span;
00622 *stream << endl << ind;
00623
00624 RenderFlow::dump(stream,ind);
00625 }
00626 #endif
00627
00628
00629
00630 RenderTableSection::RenderTableSection(DOM::NodeImpl* node)
00631 : RenderBox(node)
00632 {
00633
00634 setInline(false);
00635 cCol = 0;
00636 cRow = -1;
00637 needCellRecalc = false;
00638 }
00639
00640 RenderTableSection::~RenderTableSection()
00641 {
00642 clearGrid();
00643 }
00644
00645 void RenderTableSection::detach()
00646 {
00647
00648
00649 if (table())
00650 table()->setNeedSectionRecalc();
00651
00652 RenderBox::detach();
00653 }
00654
00655 void RenderTableSection::setStyle(RenderStyle* _style)
00656 {
00657
00658 if (style())
00659 _style->setDisplay(style()->display());
00660 else if (_style->display() != TABLE_FOOTER_GROUP && _style->display() != TABLE_HEADER_GROUP)
00661 _style->setDisplay(TABLE_ROW_GROUP);
00662
00663 RenderBox::setStyle(_style);
00664 }
00665
00666 void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild)
00667 {
00668 #ifdef DEBUG_LAYOUT
00669 kdDebug( 6040 ) << renderName() << "(TableSection)::addChild( " << child->renderName() << ", beforeChild=" <<
00670 (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
00671 #endif
00672 RenderObject *row = child;
00673
00674 if ( !child->isTableRow() ) {
00675
00676 if( !beforeChild )
00677 beforeChild = lastChild();
00678
00679 if( beforeChild && beforeChild->isAnonymousBox() )
00680 row = beforeChild;
00681 else {
00682 RenderObject *lastBox = beforeChild;
00683 while ( lastBox && lastBox->parent()->isAnonymousBox() && !lastBox->isTableRow() )
00684 lastBox = lastBox->parent();
00685 if ( lastBox && lastBox->isAnonymousBox() ) {
00686 lastBox->addChild( child, beforeChild );
00687 return;
00688 } else {
00689
00690 row = new RenderTableRow(0 );
00691 RenderStyle *newStyle = new RenderStyle();
00692 newStyle->inheritFrom(style());
00693 newStyle->setDisplay( TABLE_ROW );
00694 row->setStyle(newStyle);
00695 row->setIsAnonymousBox(true);
00696 addChild(row, beforeChild);
00697 }
00698 }
00699 row->addChild(child);
00700 child->setLayouted( false );
00701 child->setMinMaxKnown( false );
00702 return;
00703 }
00704
00705 if (beforeChild)
00706 setNeedCellRecalc();
00707
00708 cRow++;
00709 cCol = 0;
00710
00711 ensureRows( cRow+1 );
00712
00713 if (!beforeChild) {
00714 grid[cRow].height = child->style()->height();
00715 if ( grid[cRow].height.isRelative() )
00716 grid[cRow].height = Length();
00717 }
00718
00719
00720 RenderContainer::addChild(child,beforeChild);
00721 }
00722
00723 void RenderTableSection::ensureRows( int numRows )
00724 {
00725 int nRows = grid.size();
00726 int nCols = table()->numEffCols();
00727 if ( numRows > nRows ) {
00728 grid.resize( numRows );
00729 for ( int r = nRows; r < numRows; r++ ) {
00730 grid[r].row = new Row( nCols );
00731 grid[r].row->fill( 0 );
00732 grid[r].baseLine = 0;
00733 grid[r].height = Length();
00734 }
00735 }
00736
00737 }
00738
00739 void RenderTableSection::addCell( RenderTableCell *cell )
00740 {
00741 int rSpan = cell->rowSpan();
00742 int cSpan = cell->colSpan();
00743 QMemArray<RenderTable::ColumnStruct> &columns = table()->columns;
00744 int nCols = columns.size();
00745
00746
00747
00748
00749
00750
00751
00752 #if 0
00753
00754 bool found = false;
00755 while ( !found ) {
00756 found = true;
00757 while ( cCol < nCols && cellAt( cRow, cCol ) )
00758 cCol++;
00759 int pos = cCol;
00760 int span = 0;
00761 while ( pos < nCols && span < cSpan ) {
00762 if ( cellAt( cRow, pos ) ) {
00763 found = false;
00764 cCol = pos;
00765 break;
00766 }
00767 span += columns[pos].span;
00768 pos++;
00769 }
00770 }
00771 #else
00772 while ( cCol < nCols && cellAt( cRow, cCol ) )
00773 cCol++;
00774 #endif
00775
00776
00777
00778 if ( rSpan == 1 ) {
00779
00780 Length height = cell->style()->height();
00781 if ( height.value() > 0 || (height.isRelative() && height.value() >= 0) ) {
00782 Length cRowHeight = grid[cRow].height;
00783 switch( height.type() ) {
00784 case Percent:
00785 if ( !cRowHeight.isPercent() ||
00786 (cRowHeight.isPercent() && cRowHeight.value() < height.value() ) )
00787 grid[cRow].height = height;
00788 break;
00789 case Fixed:
00790 if ( cRowHeight.type() < Percent ||
00791 ( cRowHeight.isFixed() && cRowHeight.value() < height.value() ) )
00792 grid[cRow].height = height;
00793 break;
00794 case Relative:
00795 #if 0
00796
00797 if ( cRowHeight.type == Variable ||
00798 ( cRowHeight.type == Relative && cRowHeight.value < height.value ) )
00799 grid[cRow].height = height;
00800 break;
00801 #endif
00802 default:
00803 break;
00804 }
00805 }
00806 }
00807
00808
00809 ensureRows( cRow + rSpan );
00810
00811 int col = cCol;
00812
00813 RenderTableCell *set = cell;
00814 while ( cSpan ) {
00815 int currentSpan;
00816 if ( cCol >= nCols ) {
00817 table()->appendColumn( cSpan );
00818 currentSpan = cSpan;
00819 } else {
00820 if ( cSpan < columns[cCol].span )
00821 table()->splitColumn( cCol, cSpan );
00822 currentSpan = columns[cCol].span;
00823 }
00824 int r = 0;
00825 while ( r < rSpan ) {
00826 if ( !cellAt( cRow + r, cCol ) ) {
00827
00828 cellAt( cRow + r, cCol ) = set;
00829 }
00830 r++;
00831 }
00832 cCol++;
00833 cSpan -= currentSpan;
00834 set = (RenderTableCell *)-1;
00835 }
00836 if ( cell ) {
00837 cell->setRow( cRow );
00838 cell->setCol( table()->effColToCol( col ) );
00839 }
00840 }
00841
00842
00843
00844 void RenderTableSection::setCellWidths()
00845 {
00846 #ifdef DEBUG_LAYOUT
00847 kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
00848 #endif
00849 QMemArray<int> &columnPos = table()->columnPos;
00850
00851 int rows = grid.size();
00852 for ( int i = 0; i < rows; i++ ) {
00853 Row &row = *grid[i].row;
00854 int cols = row.size();
00855 for ( int j = 0; j < cols; j++ ) {
00856 RenderTableCell *cell = row[j];
00857
00858 if ( !cell || cell == (RenderTableCell *)-1 )
00859 continue;
00860 int endCol = j;
00861 int cspan = cell->colSpan();
00862 while ( cspan && endCol < cols ) {
00863 cspan -= table()->columns[endCol].span;
00864 endCol++;
00865 }
00866 int w = columnPos[endCol] - columnPos[j] - table()->cellSpacing();
00867 #ifdef DEBUG_LAYOUT
00868 kdDebug( 6040 ) << "setting width of cell " << cell << " " << cell->row() << "/" << cell->col() << " to " << w << " colspan=" << cell->colSpan() << " start=" << j << " end=" << endCol << endl;
00869 #endif
00870 int oldWidth = cell->width();
00871 if ( w != oldWidth ) {
00872 cell->setLayouted(false);
00873 cell->setWidth( w );
00874 }
00875 }
00876 }
00877 }
00878
00879
00880 void RenderTableSection::calcRowHeight()
00881 {
00882 int indx;
00883 RenderTableCell *cell;
00884
00885 int totalRows = grid.size();
00886 int spacing = table()->cellSpacing();
00887
00888 rowPos.resize( totalRows + 1 );
00889 rowPos[0] = spacing + borderTop();
00890
00891 for ( int r = 0; r < totalRows; r++ ) {
00892 rowPos[r+1] = 0;
00893
00894 int baseline=0;
00895 int bdesc = 0;
00896
00897 int ch = grid[r].height.minWidth( 0 );
00898 int pos = rowPos[ r+1 ] + ch + table()->cellSpacing();
00899
00900 if ( pos > rowPos[r+1] )
00901 rowPos[r+1] = pos;
00902
00903 Row *row = grid[r].row;
00904 int totalCols = row->size();
00905 int totalRows = grid.size();
00906
00907 for ( int c = 0; c < totalCols; c++ ) {
00908 cell = cellAt(r, c);
00909 if ( !cell || cell == (RenderTableCell *)-1 )
00910 continue;
00911 if ( r < totalRows - 1 && cellAt(r+1, c) == cell )
00912 continue;
00913
00914 if ( ( indx = r - cell->rowSpan() + 1 ) < 0 )
00915 indx = 0;
00916
00917 ch = cell->style()->height().width(0);
00918 if ( cell->height() > ch)
00919 ch = cell->height();
00920
00921 pos = rowPos[ indx ] + ch + table()->cellSpacing();
00922
00923 if ( pos > rowPos[r+1] )
00924 rowPos[r+1] = pos;
00925
00926
00927 EVerticalAlign va = cell->style()->verticalAlign();
00928 if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP
00929 || va == SUPER || va == SUB)
00930 {
00931 int b=cell->baselinePosition();
00932
00933 if (b>baseline)
00934 baseline=b;
00935
00936 int td = rowPos[ indx ] + ch - b;
00937 if (td>bdesc)
00938 bdesc = td;
00939 }
00940 }
00941
00942
00943 if (baseline) {
00944
00945 int bRowPos = baseline + bdesc + table()->cellSpacing() ;
00946 if (rowPos[r+1]<bRowPos)
00947 rowPos[r+1]=bRowPos;
00948
00949 grid[r].baseLine = baseline;
00950 }
00951
00952 if ( rowPos[r+1] < rowPos[r] )
00953 rowPos[r+1] = rowPos[r];
00954
00955 }
00956 }
00957
00958 int RenderTableSection::layoutRows( int toAdd )
00959 {
00960 int rHeight;
00961 int rindx;
00962 int totalRows = grid.size();
00963 int spacing = table()->cellSpacing();
00964
00965 if (toAdd && totalRows && rowPos[totalRows]) {
00966
00967 int totalHeight = rowPos[totalRows] + toAdd;
00968
00969
00970 int dh = totalHeight-rowPos[totalRows];
00971 int totalPercent = 0;
00972 int numVariable = 0;
00973 for ( int r = 0; r < totalRows; r++ ) {
00974 if ( grid[r].height.isVariable() )
00975 numVariable++;
00976 else if ( grid[r].height.isPercent() )
00977 totalPercent += grid[r].height.value();
00978 }
00979 if ( totalPercent ) {
00980
00981
00982 int add = 0;
00983 if ( totalPercent > 100 )
00984 totalPercent = 100;
00985 int rh = rowPos[1]-rowPos[0];
00986 for ( int r = 0; r < totalRows; r++ ) {
00987 if ( totalPercent > 0 && grid[r].height.isPercent() ) {
00988 int toAdd = QMIN( dh, (totalHeight * grid[r].height.value() / 100)-rh );
00989
00990
00991 toAdd = QMAX(0, toAdd);
00992 add += toAdd;
00993 dh -= toAdd;
00994 totalPercent -= grid[r].height.value();
00995
00996 }
00997 if ( r < totalRows-1 )
00998 rh = rowPos[r+2] - rowPos[r+1];
00999 rowPos[r+1] += add;
01000 }
01001 }
01002 if ( numVariable ) {
01003
01004
01005 int add = 0;
01006 for ( int r = 0; r < totalRows; r++ ) {
01007 if ( numVariable > 0 && grid[r].height.isVariable() ) {
01008 int toAdd = dh/numVariable;
01009 add += toAdd;
01010 dh -= toAdd;
01011 }
01012 rowPos[r+1] += add;
01013 }
01014 }
01015 if (dh>0) {
01016
01017 int tot=rowPos[totalRows];
01018 int add=0;
01019 int prev=rowPos[0];
01020 for ( int r = 0; r < totalRows; r++ ) {
01021
01022 add+=dh*(rowPos[r+1]-prev)/tot;
01023 prev=rowPos[r+1];
01024 rowPos[r+1]+=add;
01025 }
01026 }
01027 }
01028
01029 int leftOffset = borderLeft() + spacing;
01030
01031 int nEffCols = table()->numEffCols();
01032 for ( int r = 0; r < totalRows; r++ )
01033 {
01034 Row *row = grid[r].row;
01035 int totalCols = row->size();
01036 for ( int c = 0; c < nEffCols; c++ )
01037 {
01038 RenderTableCell *cell = cellAt(r, c);
01039 if (!cell || cell == (RenderTableCell *)-1 )
01040 continue;
01041 if ( r < totalRows - 1 && cell == cellAt(r+1, c) )
01042 continue;
01043
01044 if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
01045 rindx = 0;
01046
01047 rHeight = rowPos[r+1] - rowPos[rindx] - spacing;
01048 #ifdef DEBUG_LAYOUT
01049 kdDebug( 6040 ) << "setting position " << r << "/" << c << ": "
01050 << table()->columnPos[c] << "/" << rowPos[rindx] << " height=" << rHeight<< endl;
01051 #endif
01052
01053 EVerticalAlign va = cell->style()->verticalAlign();
01054 int te=0;
01055 switch (va)
01056 {
01057 case SUB:
01058 case SUPER:
01059 case TEXT_TOP:
01060 case TEXT_BOTTOM:
01061 case BASELINE:
01062 te = getBaseline(r) - cell->baselinePosition() ;
01063 break;
01064 case TOP:
01065 te = 0;
01066 break;
01067 case MIDDLE:
01068 te = (rHeight - cell->height())/2;
01069 break;
01070 case BOTTOM:
01071 te = rHeight - cell->height();
01072 break;
01073 default:
01074 break;
01075 }
01076 #ifdef DEBUG_LAYOUT
01077
01078 #endif
01079 cell->setCellTopExtra( te );
01080 cell->setCellBottomExtra( rHeight - cell->height() - te);
01081
01082 if (style()->direction()==RTL) {
01083 cell->setPos(
01084 table()->columnPos[(int)totalCols] -
01085 table()->columnPos[table()->colToEffCol(cell->col()+cell->colSpan())] +
01086 leftOffset,
01087 rowPos[rindx] );
01088 } else {
01089 cell->setPos( table()->columnPos[c] + leftOffset, rowPos[rindx] );
01090 }
01091 }
01092 }
01093
01094 m_height = rowPos[totalRows];
01095 return m_height;
01096 }
01097
01098
01099 void RenderTableSection::paint( QPainter *p, int x, int y, int w, int h,
01100 int tx, int ty)
01101 {
01102 unsigned int totalRows = grid.size();
01103 unsigned int totalCols = table()->columns.size();
01104
01105 tx += m_x;
01106 ty += m_y;
01107
01108
01109
01110 unsigned int startrow = 0;
01111 unsigned int endrow = totalRows;
01112 for ( ; startrow < totalRows; startrow++ ) {
01113 if ( ty + rowPos[startrow+1] > y )
01114 break;
01115 }
01116 for ( ; endrow > 0; endrow-- ) {
01117 if ( ty + rowPos[endrow-1] < y + h )
01118 break;
01119 }
01120 unsigned int startcol = 0;
01121 unsigned int endcol = totalCols;
01122 if ( style()->direction() == LTR ) {
01123 for ( ; startcol < totalCols; startcol++ ) {
01124 if ( tx + table()->columnPos[startcol+1] > x )
01125 break;
01126 }
01127 for ( ; endcol > 0; endcol-- ) {
01128 if ( tx + table()->columnPos[endcol-1] < x + w )
01129 break;
01130 }
01131 }
01132 if ( startcol < endcol ) {
01133
01134 for ( unsigned int r = startrow; r < endrow; r++ ) {
01135 unsigned int c = startcol;
01136
01137 while ( c && cellAt( r, c ) == (RenderTableCell *)-1 )
01138 c--;
01139 for ( ; c < endcol; c++ ) {
01140 RenderTableCell *cell = cellAt(r, c);
01141 if (!cell || cell == (RenderTableCell *)-1 )
01142 continue;
01143 if ( (r < endrow - 1) && (cellAt(r+1, c) == cell) )
01144 continue;
01145
01146 #ifdef TABLE_PRINT
01147 kdDebug( 6040 ) << "painting cell " << r << "/" << c << endl;
01148 #endif
01149 cell->paint( p, x, y, w, h, tx, ty);
01150 }
01151 }
01152 }
01153 }
01154
01155 void RenderTableSection::recalcCells()
01156 {
01157 cCol = 0;
01158 cRow = -1;
01159 clearGrid();
01160 grid.resize( 0 );
01161
01162 RenderObject *row = firstChild();
01163 while ( row ) {
01164 cRow++;
01165 cCol = 0;
01166 ensureRows( cRow+1 );
01167 RenderObject *cell = row->firstChild();
01168 while ( cell ) {
01169 if ( cell->isTableCell() )
01170 addCell( static_cast<RenderTableCell *>(cell) );
01171 cell = cell->nextSibling();
01172 }
01173 row = row->nextSibling();
01174 }
01175 needCellRecalc = false;
01176 setLayouted( false );
01177 }
01178
01179 void RenderTableSection::clearGrid()
01180 {
01181 int rows = grid.size();
01182 while ( rows-- ) {
01183 delete grid[rows].row;
01184 }
01185 }
01186
01187 RenderObject* RenderTableSection::removeChildNode(RenderObject* child)
01188 {
01189 setNeedCellRecalc();
01190 return RenderContainer::removeChildNode( child );
01191 }
01192
01193 #ifndef NDEBUG
01194 void RenderTableSection::dump(QTextStream *stream, QString ind) const
01195 {
01196 *stream << endl << ind << "grid=(" << grid.size() << "," << table()->numEffCols() << ")" << endl << ind;
01197 for ( unsigned int r = 0; r < grid.size(); r++ ) {
01198 for ( int c = 0; c < table()->numEffCols(); c++ ) {
01199 if ( cellAt( r, c ) && cellAt( r, c ) != (RenderTableCell *)-1 )
01200 *stream << "(" << cellAt( r, c )->row() << "," << cellAt( r, c )->col() << ","
01201 << cellAt(r, c)->rowSpan() << "," << cellAt(r, c)->colSpan() << ") ";
01202 else
01203 *stream << cellAt( r, c ) << "null cell ";
01204 }
01205 *stream << endl << ind;
01206 }
01207 RenderContainer::dump(stream,ind);
01208 }
01209 #endif
01210
01211
01212
01213 RenderTableRow::RenderTableRow(DOM::NodeImpl* node)
01214 : RenderContainer(node)
01215 {
01216
01217 setInline(false);
01218 }
01219
01220 void RenderTableRow::detach()
01221 {
01222 section()->setNeedCellRecalc();
01223
01224 RenderContainer::detach();
01225 }
01226
01227 void RenderTableRow::setStyle(RenderStyle* style)
01228 {
01229 style->setDisplay(TABLE_ROW);
01230 RenderContainer::setStyle(style);
01231 }
01232
01233 void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
01234 {
01235 #ifdef DEBUG_LAYOUT
01236 kdDebug( 6040 ) << renderName() << "(TableRow)::addChild( " << child->renderName() << " )" << ", " <<
01237 (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
01238 #endif
01239 RenderTableCell *cell;
01240
01241 if ( !child->isTableCell() ) {
01242 RenderObject *last = beforeChild;
01243 if ( !last )
01244 last = lastChild();
01245 RenderTableCell *cell = 0;
01246 if( last && last->isAnonymousBox() && last->isTableCell() )
01247 cell = static_cast<RenderTableCell *>(last);
01248 else {
01249 kdDebug( 6040 ) << "creating anonymous table cell" << endl;
01250 cell = new RenderTableCell(0 );
01251 RenderStyle *newStyle = new RenderStyle();
01252 newStyle->inheritFrom(style());
01253 newStyle->setDisplay( TABLE_CELL );
01254 cell->setStyle(newStyle);
01255 cell->setIsAnonymousBox(true);
01256 addChild(cell, beforeChild);
01257 }
01258 cell->addChild(child);
01259 child->setLayouted( false );
01260 child->setMinMaxKnown( false );
01261 return;
01262 } else
01263 cell = static_cast<RenderTableCell *>(child);
01264
01265 static_cast<RenderTableSection *>(parent())->addCell( cell );
01266
01267 RenderContainer::addChild(cell,beforeChild);
01268
01269 if ( ( beforeChild || nextSibling()) && section() )
01270 section()->setNeedCellRecalc();
01271 }
01272
01273 RenderObject* RenderTableRow::removeChildNode(RenderObject* child)
01274 {
01275
01276
01277
01278 return RenderContainer::removeChildNode( child );
01279 }
01280
01281 #ifndef NDEBUG
01282 void RenderTableRow::dump(QTextStream *stream, QString ind) const
01283 {
01284 RenderContainer::dump(stream,ind);
01285 }
01286 #endif
01287
01288 void RenderTableRow::layout()
01289 {
01290 KHTMLAssert( !layouted() );
01291 KHTMLAssert( minMaxKnown() );
01292
01293 RenderObject *child = firstChild();
01294 while( child ) {
01295 if ( child->isTableCell() && !child->layouted() ) {
01296 RenderTableCell *cell = static_cast<RenderTableCell *>(child);
01297 cell->calcVerticalMargins();
01298 cell->layout();
01299 cell->setCellTopExtra(0);
01300 cell->setCellBottomExtra(0);
01301 }
01302 child = child->nextSibling();
01303 }
01304 setLayouted();
01305 }
01306
01307
01308
01309 RenderTableCell::RenderTableCell(DOM::NodeImpl* _node)
01310 : RenderFlow(_node)
01311 {
01312 _col = -1;
01313 _row = -1;
01314 updateFromElement();
01315 setSpecialObjects(true);
01316 _topExtra = 0;
01317 _bottomExtra = 0;
01318 }
01319
01320 void RenderTableCell::detach()
01321 {
01322 if (parent() && section())
01323 section()->setNeedCellRecalc();
01324
01325 RenderFlow::detach();
01326 }
01327
01328 void RenderTableCell::updateFromElement()
01329 {
01330 DOM::NodeImpl *node = element();
01331 if ( node && (node->id() == ID_TD || node->id() == ID_TH) ) {
01332 DOM::HTMLTableCellElementImpl *tc = static_cast<DOM::HTMLTableCellElementImpl *>(node);
01333 cSpan = tc->colSpan();
01334 rSpan = tc->rowSpan();
01335 nWrap = tc->noWrap();
01336 } else {
01337 cSpan = rSpan = 1;
01338 nWrap = false;
01339 }
01340 }
01341
01342 void RenderTableCell::calcMinMaxWidth()
01343 {
01344 KHTMLAssert( !minMaxKnown() );
01345 #ifdef DEBUG_LAYOUT
01346 kdDebug( 6040 ) << renderName() << "(TableCell)::calcMinMaxWidth() known=" << minMaxKnown() << endl;
01347 #endif
01348
01349 RenderFlow::calcMinMaxWidth();
01350
01351 setMinMaxKnown();
01352 }
01353
01354 void RenderTableCell::calcWidth()
01355 {
01356 }
01357
01358 void RenderTableCell::setWidth( int width )
01359 {
01360 if ( width != m_width ) {
01361 m_width = width;
01362 m_widthChanged = true;
01363 }
01364 }
01365
01366 void RenderTableCell::close()
01367 {
01368 RenderFlow::close();
01369
01370 #ifdef DEBUG_LAYOUT
01371 kdDebug( 6040 ) << renderName() << "(RenderTableCell)::close() total height =" << m_height << endl;
01372 #endif
01373 }
01374
01375
01376 void RenderTableCell::repaintRectangle(int x, int y, int w, int h, bool f)
01377 {
01378 y += _topExtra;
01379 RenderFlow::repaintRectangle(x, y, w, h, f);
01380 }
01381
01382 bool RenderTableCell::absolutePosition(int &xPos, int &yPos, bool f)
01383 {
01384 bool ret = RenderFlow::absolutePosition(xPos, yPos, f);
01385 if (ret)
01386 yPos += _topExtra;
01387 return ret;
01388 }
01389
01390 short RenderTableCell::baselinePosition( bool ) const
01391 {
01392 RenderObject *o = firstChild();
01393 int offset = paddingTop() + borderTop();
01394 if ( !o ) return offset;
01395 while ( o->firstChild() ) {
01396 if ( !o->isInline() )
01397 offset += o->paddingTop() + o->borderTop();
01398 o = o->firstChild();
01399 }
01400 offset += o->baselinePosition( true );
01401 return offset;
01402 }
01403
01404
01405 void RenderTableCell::setStyle( RenderStyle *style )
01406 {
01407 style->setDisplay(TABLE_CELL);
01408 RenderFlow::setStyle( style );
01409 setSpecialObjects(true);
01410 }
01411
01412 #ifdef BOX_DEBUG
01413 #include <qpainter.h>
01414
01415 static void outlineBox(QPainter *p, int _tx, int _ty, int w, int h)
01416 {
01417 p->setPen(QPen(QColor("yellow"), 3, Qt::DotLine));
01418 p->setBrush( Qt::NoBrush );
01419 p->drawRect(_tx, _ty, w, h );
01420 }
01421 #endif
01422
01423 void RenderTableCell::paint(QPainter *p, int _x, int _y,
01424 int _w, int _h, int _tx, int _ty)
01425 {
01426
01427 #ifdef TABLE_PRINT
01428 kdDebug( 6040 ) << renderName() << "(RenderTableCell)::paint() w/h = (" << width() << "/" << height() << ")" << " _y/_h=" << _y << "/" << _h << endl;
01429 #endif
01430
01431 if (!layouted()) return;
01432
01433 _tx += m_x;
01434 _ty += m_y + _topExtra;
01435
01436
01437 if(!overhangingContents() && ((_ty-_topExtra > _y + _h)
01438 || (_ty + m_height+_topExtra+_bottomExtra < _y))) return;
01439
01440 paintObject(p, _x, _y, _w, _h, _tx, _ty);
01441
01442 #ifdef BOX_DEBUG
01443 ::outlineBox( p, _tx, _ty - _topExtra, width(), height() + borderTopExtra() + borderBottomExtra());
01444 #endif
01445 }
01446
01447
01448 void RenderTableCell::paintBoxDecorations(QPainter *p,int, int _y,
01449 int, int _h, int _tx, int _ty)
01450 {
01451 int w = width();
01452 int h = height() + borderTopExtra() + borderBottomExtra();
01453 _ty -= borderTopExtra();
01454
01455 QColor c = style()->backgroundColor();
01456 if ( !c.isValid() && parent() )
01457 c = parent()->style()->backgroundColor();
01458 if ( !c.isValid() && parent() && parent()->parent() )
01459 c = parent()->parent()->style()->backgroundColor();
01460 if ( !c.isValid() ) {
01461
01462 RenderTableCol *col = table()->colElement( _col );
01463 if ( col ) {
01464 c = col->style()->backgroundColor();
01465 if ( !c.isValid() ) {
01466
01467 RenderStyle *style = col->parent()->style();
01468 if ( style->display() == TABLE_COLUMN_GROUP )
01469 c = style->backgroundColor();
01470 }
01471 }
01472 }
01473
01474
01475 CachedImage *bg = style()->backgroundImage();
01476 if ( !bg && parent() )
01477 bg = parent()->style()->backgroundImage();
01478 if ( !bg && parent() && parent()->parent() )
01479 bg = parent()->parent()->style()->backgroundImage();
01480 if ( !bg ) {
01481
01482 RenderTableCol *col = table()->colElement( _col );
01483 if ( col ) {
01484 bg = col->style()->backgroundImage();
01485 if ( !bg ) {
01486
01487 RenderStyle *style = col->parent()->style();
01488 if ( style->display() == TABLE_COLUMN_GROUP )
01489 bg = style->backgroundImage();
01490 }
01491 }
01492 }
01493
01494 int my = QMAX(_ty,_y);
01495 int end = QMIN( _y + _h, _ty + h );
01496 int mh = end - my;
01497
01498 if ( bg || c.isValid() )
01499 paintBackground(p, c, bg, my, mh, _tx, _ty, w, h);
01500
01501 if(style()->hasBorder())
01502 paintBorder(p, _tx, _ty, w, h, style());
01503 }
01504
01505
01506 #ifndef NDEBUG
01507 void RenderTableCell::dump(QTextStream *stream, QString ind) const
01508 {
01509 *stream << " row=" << _row;
01510 *stream << " col=" << _col;
01511 *stream << " rSpan=" << rSpan;
01512 *stream << " cSpan=" << cSpan;
01513
01514
01515 RenderFlow::dump(stream,ind);
01516 }
01517 #endif
01518
01519
01520
01521 RenderTableCol::RenderTableCol(DOM::NodeImpl* node)
01522 : RenderContainer(node)
01523 {
01524
01525 setInline(true);
01526
01527 _span = 1;
01528 updateFromElement();
01529 }
01530
01531 void RenderTableCol::updateFromElement()
01532 {
01533 DOM::NodeImpl *node = element();
01534 if ( node && (node->id() == ID_COL || node->id() == ID_COLGROUP) ) {
01535 DOM::HTMLTableColElementImpl *tc = static_cast<DOM::HTMLTableColElementImpl *>(node);
01536 _span = tc->span();
01537 } else
01538 _span = ! ( style() && style()->display() == TABLE_COLUMN_GROUP );
01539 }
01540
01541 void RenderTableCol::addChild(RenderObject *child, RenderObject *beforeChild)
01542 {
01543 #ifdef DEBUG_LAYOUT
01544
01545
01546 #endif
01547
01548 if (child->style()->display() == TABLE_COLUMN)
01549
01550 RenderContainer::addChild(child,beforeChild);
01551 }
01552
01553 #ifndef NDEBUG
01554 void RenderTableCol::dump(QTextStream *stream, QString ind) const
01555 {
01556 *stream << " _span=" << _span;
01557 RenderContainer::dump(stream,ind);
01558 }
01559 #endif
01560
01561 #undef TABLE_DEBUG
01562 #undef DEBUG_LAYOUT
01563 #undef BOX_DEBUG