khtml Library API Documentation

html_tableimpl.cpp

00001 
00026 #include "html/html_documentimpl.h"
00027 #include "html/html_tableimpl.h"
00028 
00029 #include "dom/dom_exception.h"
00030 #include "dom/dom_node.h"
00031 
00032 #include "misc/htmlhashes.h"
00033 #include "khtmlview.h"
00034 #include "khtml_part.h"
00035 
00036 #include "css/cssstyleselector.h"
00037 #include "css/cssproperties.h"
00038 #include "css/cssvalues.h"
00039 #include "css/csshelper.h"
00040 
00041 #include "rendering/render_table.h"
00042 
00043 #include <kdebug.h>
00044 #include <kglobal.h>
00045 
00046 using namespace khtml;
00047 using namespace DOM;
00048 
00049 HTMLTableElementImpl::HTMLTableElementImpl(DocumentPtr *doc)
00050   : HTMLElementImpl(doc)
00051 {
00052     tCaption = 0;
00053     head = 0;
00054     foot = 0;
00055     firstBody = 0;
00056 
00057 #if 0
00058     rules = None;
00059     frame = Void;
00060 #endif
00061     padding = 1;
00062 
00063     m_noBorder = true;
00064     m_solid = false;
00065 
00066     // reset font color and sizes here, if we don't have strict parse mode.
00067     // this is 90% compatible to ie and mozilla, and the by way easiest solution...
00068     // only difference to 100% correct is that in strict mode <font> elements are propagated into tables.
00069     if ( getDocument()->parseMode() != DocumentImpl::Strict ) {
00070         addCSSProperty( CSS_PROP_FONT_SIZE, CSS_VAL_MEDIUM );
00071         addCSSProperty( CSS_PROP_COLOR, "-konq-text" );
00072         addCSSProperty( CSS_PROP_FONT_FAMILY, "konq_default" );
00073     }
00074 }
00075 
00076 HTMLTableElementImpl::~HTMLTableElementImpl()
00077 {
00078 }
00079 
00080 NodeImpl::Id HTMLTableElementImpl::id() const
00081 {
00082     return ID_TABLE;
00083 }
00084 
00085 NodeImpl* HTMLTableElementImpl::setCaption( HTMLTableCaptionElementImpl *c )
00086 {
00087     int exceptioncode = 0;
00088     NodeImpl* r;
00089     if(tCaption) {
00090         replaceChild ( c, tCaption, exceptioncode );
00091         r = c;
00092     }
00093     else
00094         r = insertBefore( c, firstChild(), exceptioncode );
00095     tCaption = c;
00096     return r;
00097 }
00098 
00099 NodeImpl* HTMLTableElementImpl::setTHead( HTMLTableSectionElementImpl *s )
00100 {
00101     int exceptioncode = 0;
00102     NodeImpl* r;
00103     if(head) {
00104         replaceChild( s, head, exceptioncode );
00105         r = s;
00106     }
00107     else if( foot )
00108         r = insertBefore( s, foot, exceptioncode );
00109     else if( firstBody )
00110         r = insertBefore( s, firstBody, exceptioncode );
00111     else
00112         r = appendChild( s, exceptioncode );
00113 
00114     head = s;
00115     return r;
00116 }
00117 
00118 NodeImpl* HTMLTableElementImpl::setTFoot( HTMLTableSectionElementImpl *s )
00119 {
00120     int exceptioncode = 0;
00121     NodeImpl* r;
00122     if(foot) {
00123         replaceChild ( s, foot, exceptioncode );
00124         r = s;
00125     }
00126     else if( firstBody )
00127         r = insertBefore( s, firstBody, exceptioncode );
00128     else
00129         r = appendChild( s, exceptioncode );
00130     foot = s;
00131     return r;
00132 }
00133 
00134 NodeImpl* HTMLTableElementImpl::setTBody( HTMLTableSectionElementImpl *s )
00135 {
00136     int exceptioncode = 0;
00137     NodeImpl* r;
00138 
00139     if(!firstBody)
00140         firstBody = s;
00141 
00142     if( foot )
00143         r = insertBefore( s, foot, exceptioncode );
00144     else
00145         r = appendChild( s, exceptioncode );
00146 
00147     return r;
00148 }
00149 
00150 HTMLElementImpl *HTMLTableElementImpl::createTHead(  )
00151 {
00152     if(!head)
00153     {
00154         int exceptioncode = 0;
00155         head = new HTMLTableSectionElementImpl(docPtr(), ID_THEAD, true /* implicit */);
00156         if(foot)
00157             insertBefore( head, foot, exceptioncode );
00158         if(firstBody)
00159             insertBefore( head, firstBody, exceptioncode);
00160         else
00161             appendChild(head, exceptioncode);
00162     }
00163     return head;
00164 }
00165 
00166 void HTMLTableElementImpl::deleteTHead(  )
00167 {
00168     if(head) {
00169         int exceptioncode = 0;
00170         HTMLElementImpl::removeChild(head, exceptioncode);
00171     }
00172     head = 0;
00173 }
00174 
00175 HTMLElementImpl *HTMLTableElementImpl::createTFoot(  )
00176 {
00177     if(!foot)
00178     {
00179         int exceptioncode = 0;
00180         foot = new HTMLTableSectionElementImpl(docPtr(), ID_TFOOT, true /*implicit */);
00181         if(firstBody)
00182             insertBefore( foot, firstBody, exceptioncode );
00183         else
00184             appendChild(foot, exceptioncode);
00185     }
00186     return foot;
00187 }
00188 
00189 void HTMLTableElementImpl::deleteTFoot(  )
00190 {
00191     if(foot) {
00192         int exceptioncode = 0;
00193         HTMLElementImpl::removeChild(foot, exceptioncode);
00194     }
00195     foot = 0;
00196 }
00197 
00198 HTMLElementImpl *HTMLTableElementImpl::createCaption(  )
00199 {
00200     if(!tCaption)
00201     {
00202         int exceptioncode = 0;
00203         tCaption = new HTMLTableCaptionElementImpl(docPtr());
00204         insertBefore( tCaption, firstChild(), exceptioncode );
00205     }
00206     return tCaption;
00207 }
00208 
00209 void HTMLTableElementImpl::deleteCaption(  )
00210 {
00211     if(tCaption) {
00212         int exceptioncode = 0;
00213         HTMLElementImpl::removeChild(tCaption, exceptioncode);
00214     }
00215     tCaption = 0;
00216 }
00217 
00218 HTMLElementImpl *HTMLTableElementImpl::insertRow( long index, int &exceptioncode )
00219 {
00220     // The DOM requires that we create a tbody if the table is empty
00221     // (cf DOM2TS HTMLTableElement31 test)
00222     // (note: this is different from "if the table has no sections", since we can have
00223     // <TABLE><TR>)
00224     if(!firstBody && !head && !foot && !hasChildNodes())
00225         setTBody( new HTMLTableSectionElementImpl(docPtr(), ID_TBODY, true /* implicit */) );
00226 
00227     //kdDebug(6030) << k_funcinfo << index << endl;
00228     // IE treats index=-1 as default value meaning 'append after last'
00229     // This isn't in the DOM. So, not implemented yet.
00230     HTMLTableSectionElementImpl* section = 0L;
00231     HTMLTableSectionElementImpl* lastSection = 0L;
00232     NodeImpl *node = firstChild();
00233     bool append = index == -1;
00234     for ( ; node && (index>=0 || append) ; node = node->nextSibling() )
00235     {
00236         if ( node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY )
00237         {
00238             section = static_cast<HTMLTableSectionElementImpl *>(node);
00239             lastSection = section;
00240             //kdDebug(6030) << k_funcinfo << "section id=" << node->id() << " rows:" << section->numRows() << endl;
00241             if ( !append )
00242             {
00243                 int rows = section->numRows();
00244                 if ( rows > index )
00245                     break;
00246                 else
00247                     index -= rows;
00248                 //kdDebug(6030) << "       index is now " << index << endl;
00249             }
00250         }
00251         // Note: we now can have both TR and sections (THEAD/TBODY/TFOOT) as children of a TABLE
00252         else if ( node->id() == ID_TR )
00253         {
00254             section = 0L;
00255             //kdDebug(6030) << k_funcinfo << "row" << endl;
00256             if (!append && !index)
00257             {
00258                 // Insert row right here, before "node"
00259                 HTMLTableRowElementImpl* row = new HTMLTableRowElementImpl(docPtr());
00260                 insertBefore(row, node, exceptioncode );
00261                 return row;
00262             }
00263             if ( !append )
00264                 index--;
00265             //kdDebug(6030) << "       index is now " << index << endl;
00266         }
00267         section = 0L;
00268     }
00269     // Index == 0 means "insert before first row in current section"
00270     // or "append after last row" (if there's no current section anymore)
00271     if ( !section && ( index == 0 || append ) )
00272     {
00273         section = lastSection;
00274         index = section ? section->numRows() : 0;
00275     }
00276     if ( section && ( index >= 0 || append ) ) {
00277         //kdDebug(6030) << "Inserting row into section " << section << " at index " << index << endl;
00278         return section->insertRow( index, exceptioncode );
00279     } else {
00280         // No more sections => index is too big
00281         exceptioncode = DOMException::INDEX_SIZE_ERR;
00282         return 0L;
00283     }
00284 }
00285 
00286 void HTMLTableElementImpl::deleteRow( long index, int &exceptioncode )
00287 {
00288     HTMLTableSectionElementImpl* section = 0L;
00289     NodeImpl *node = firstChild();
00290     bool lastRow = index == -1;
00291     HTMLTableSectionElementImpl* lastSection = 0L;
00292     for ( ; node ; node = node->nextSibling() )
00293     {
00294         if ( node->id() == ID_THEAD || node->id() == ID_TFOOT || node->id() == ID_TBODY )
00295         {
00296             section = static_cast<HTMLTableSectionElementImpl *>(node);
00297             lastSection = section;
00298             int rows = section->numRows();
00299             if ( !lastRow )
00300             {
00301                 if ( rows > index )
00302                     break;
00303                 else
00304                     index -= rows;
00305             }
00306         }
00307         section = 0L;
00308     }
00309     if ( lastRow )
00310         lastSection->deleteRow( -1, exceptioncode );
00311     else if ( section && index >= 0 && index < section->numRows() )
00312         section->deleteRow( index, exceptioncode );
00313     else
00314         exceptioncode = DOMException::INDEX_SIZE_ERR;
00315 }
00316 
00317 NodeImpl *HTMLTableElementImpl::addChild(NodeImpl *child)
00318 {
00319 #ifdef DEBUG_LAYOUT
00320     kdDebug( 6030 ) << nodeName().string() << "(Table)::addChild( " << child->nodeName().string() << " )" << endl;
00321 #endif
00322 
00323     switch(child->id())
00324     {
00325     case ID_CAPTION:
00326         return setCaption(static_cast<HTMLTableCaptionElementImpl *>(child));
00327         break;
00328     case ID_COL:
00329     case ID_COLGROUP:
00330         if(head || foot || firstBody)
00331             return 0;
00332     {
00333         int exceptioncode = 0;
00334         return appendChild(child, exceptioncode);
00335     }
00336     case ID_THEAD:
00337         return setTHead(static_cast<HTMLTableSectionElementImpl *>(child));
00338         break;
00339     case ID_TFOOT:
00340         return setTFoot(static_cast<HTMLTableSectionElementImpl *>(child));
00341         break;
00342     case ID_TBODY:
00343         return setTBody(static_cast<HTMLTableSectionElementImpl *>(child));
00344         break;
00345     }
00346     return 0;
00347 }
00348 
00349 void HTMLTableElementImpl::parseAttribute(AttributeImpl *attr)
00350 {
00351     // ### to CSS!!
00352     switch(attr->id())
00353     {
00354     case ATTR_WIDTH:
00355         if (!attr->value().isEmpty())
00356             addCSSLength( CSS_PROP_WIDTH, attr->value() );
00357         else
00358             removeCSSProperty(CSS_PROP_WIDTH);
00359         break;
00360     case ATTR_HEIGHT:
00361         if (!attr->value().isEmpty())
00362             addCSSLength(CSS_PROP_HEIGHT, attr->value());
00363         else
00364             removeCSSProperty(CSS_PROP_HEIGHT);
00365         break;
00366     case ATTR_BORDER:
00367     {
00368         int border;
00369         // ### this needs more work, as the border value is not only
00370         //     the border of the box, but also between the cells
00371         if(!attr->val())
00372             border = 0;
00373         else if(attr->val()->l == 0)
00374             border = 1;
00375         else
00376             border = attr->val()->toInt();
00377 #ifdef DEBUG_DRAW_BORDER
00378         border=1;
00379 #endif
00380         m_noBorder = !border;
00381         DOMString v = QString::number( border );
00382         addCSSLength(CSS_PROP_BORDER_WIDTH, v );
00383 #if 0
00384         // wanted by HTML4 specs
00385         if(!border)
00386             frame = Void, rules = None;
00387         else
00388             frame = Box, rules = All;
00389 #endif
00390         break;
00391     }
00392     case ATTR_BGCOLOR:
00393         if (!attr->value().isEmpty())
00394             addCSSProperty(CSS_PROP_BACKGROUND_COLOR, attr->value());
00395         else
00396             removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
00397         break;
00398     case ATTR_BORDERCOLOR:
00399         if(!attr->value().isEmpty()) {
00400             addCSSProperty(CSS_PROP_BORDER_COLOR, attr->value());
00401             addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
00402             addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
00403             addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
00404             addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
00405             m_solid = true;
00406         }
00407         break;
00408     case ATTR_BACKGROUND:
00409     {
00410         if (!attr->value().isEmpty()) {
00411             QString url = khtml::parseURL( attr->value() ).string();
00412             url = getDocument()->completeURL( url );
00413             addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" );
00414         }
00415         else
00416             removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE);
00417         break;
00418     }
00419     case ATTR_FRAME:
00420 #if 0
00421         if ( strcasecmp( attr->value(), "void" ) == 0 )
00422             frame = Void;
00423         else if ( strcasecmp( attr->value(), "border" ) == 0 )
00424             frame = Box;
00425         else if ( strcasecmp( attr->value(), "box" ) == 0 )
00426             frame = Box;
00427         else if ( strcasecmp( attr->value(), "hsides" ) == 0 )
00428             frame = Hsides;
00429         else if ( strcasecmp( attr->value(), "vsides" ) == 0 )
00430             frame = Vsides;
00431         else if ( strcasecmp( attr->value(), "above" ) == 0 )
00432             frame = Above;
00433         else if ( strcasecmp( attr->value(), "below" ) == 0 )
00434             frame = Below;
00435         else if ( strcasecmp( attr->value(), "lhs" ) == 0 )
00436             frame = Lhs;
00437         else if ( strcasecmp( attr->value(), "rhs" ) == 0 )
00438             frame = Rhs;
00439 #endif
00440         break;
00441     case ATTR_RULES:
00442 #if 0
00443         if ( strcasecmp( attr->value(), "none" ) == 0 )
00444             rules = None;
00445         else if ( strcasecmp( attr->value(), "groups" ) == 0 )
00446             rules = Groups;
00447         else if ( strcasecmp( attr->value(), "rows" ) == 0 )
00448             rules = Rows;
00449         else if ( strcasecmp( attr->value(), "cols" ) == 0 )
00450             rules = Cols;
00451         else if ( strcasecmp( attr->value(), "all" ) == 0 )
00452             rules = All;
00453 #endif
00454         break;
00455    case ATTR_CELLSPACING:
00456         if (!attr->value().isEmpty())
00457             addCSSLength(CSS_PROP_BORDER_SPACING, attr->value(), true);
00458         else
00459             removeCSSProperty(CSS_PROP_BORDER_SPACING);
00460         break;
00461     case ATTR_CELLPADDING:
00462         if (!attr->value().isEmpty()) {
00463             addCSSLength(CSS_PROP_PADDING_TOP, attr->value(), true);
00464             addCSSLength(CSS_PROP_PADDING_LEFT, attr->value(), true);
00465             addCSSLength(CSS_PROP_PADDING_BOTTOM, attr->value(), true);
00466             addCSSLength(CSS_PROP_PADDING_RIGHT, attr->value(), true);
00467         padding = kMax( 0, attr->value().toInt() );
00468         }
00469         else {
00470             removeCSSProperty(CSS_PROP_PADDING_TOP);
00471             removeCSSProperty(CSS_PROP_PADDING_LEFT);
00472             removeCSSProperty(CSS_PROP_PADDING_BOTTOM);
00473             removeCSSProperty(CSS_PROP_PADDING_RIGHT);
00474         padding = 1;
00475         }
00476         break;
00477     case ATTR_COLS:
00478     {
00479         // ###
00480 #if 0
00481         int c;
00482         c = attr->val()->toInt();
00483         addColumns(c-totalCols);
00484         break;
00485 #endif
00486     }
00487     case ATTR_ALIGN:
00488         if (!attr->value().isEmpty())
00489             addCSSProperty(CSS_PROP_FLOAT, attr->value());
00490         else
00491             removeCSSProperty(CSS_PROP_FLOAT);
00492         break;
00493     case ATTR_VALIGN:
00494         if (!attr->value().isEmpty())
00495             addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value());
00496         else
00497             removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
00498         break;
00499     case ATTR_NOSAVE:
00500     break;
00501     default:
00502         HTMLElementImpl::parseAttribute(attr);
00503     }
00504 }
00505 
00506 void HTMLTableElementImpl::attach()
00507 {
00508     if (!m_noBorder) {
00509         int v = m_solid ? CSS_VAL_SOLID : CSS_VAL_OUTSET;
00510         addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, v);
00511         addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v);
00512         addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, v);
00513         addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, v);
00514     }
00515 
00516     HTMLElementImpl::attach();
00517     if ( m_render && m_render->isTable() )
00518     static_cast<RenderTable *>(m_render)->setCellPadding( padding );
00519 }
00520 
00521 // --------------------------------------------------------------------------
00522 
00523 void HTMLTablePartElementImpl::parseAttribute(AttributeImpl *attr)
00524 {
00525     switch(attr->id())
00526     {
00527     case ATTR_BGCOLOR:
00528         if (attr->val())
00529             addCSSProperty(CSS_PROP_BACKGROUND_COLOR, attr->value() );
00530         else
00531             removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
00532         break;
00533     case ATTR_BACKGROUND:
00534     {
00535         if (attr->val()) {
00536             QString url = khtml::parseURL( attr->value() ).string();
00537             url = getDocument()->completeURL( url );
00538             addCSSProperty(CSS_PROP_BACKGROUND_IMAGE,  "url('"+url+"')" );
00539         }
00540         else
00541             removeCSSProperty(CSS_PROP_BACKGROUND_IMAGE);
00542         break;
00543     }
00544     case ATTR_BORDERCOLOR:
00545     {
00546         if(!attr->value().isEmpty()) {
00547             addCSSProperty(CSS_PROP_BORDER_COLOR, attr->value());
00548             addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
00549             addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
00550             addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
00551             addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
00552             m_solid = true;
00553         }
00554         break;
00555     }
00556     case ATTR_VALIGN:
00557     {
00558         if (!attr->value().isEmpty())
00559             addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value());
00560         else
00561             removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
00562         break;
00563     }
00564     case ATTR_HEIGHT:
00565         if (!attr->value().isEmpty())
00566             addCSSLength(CSS_PROP_HEIGHT, attr->value());
00567         else
00568             removeCSSProperty(CSS_PROP_HEIGHT);
00569         break;
00570     case ATTR_NOSAVE:
00571     break;
00572     default:
00573         HTMLElementImpl::parseAttribute(attr);
00574     }
00575 }
00576 
00577 // -------------------------------------------------------------------------
00578 
00579 HTMLTableSectionElementImpl::HTMLTableSectionElementImpl(DocumentPtr *doc,
00580                                                          ushort tagid, bool implicit)
00581     : HTMLTablePartElementImpl(doc)
00582 {
00583     _id = tagid;
00584     m_implicit = implicit;
00585 }
00586 
00587 HTMLTableSectionElementImpl::~HTMLTableSectionElementImpl()
00588 {
00589 }
00590 
00591 NodeImpl::Id HTMLTableSectionElementImpl::id() const
00592 {
00593     return _id;
00594 }
00595 
00596 
00597 // these functions are rather slow, since we need to get the row at
00598 // the index... but they aren't used during usual HTML parsing anyway
00599 HTMLElementImpl *HTMLTableSectionElementImpl::insertRow( long index, int& exceptioncode )
00600 {
00601     HTMLTableRowElementImpl *r = 0L;
00602     NodeListImpl *children = childNodes();
00603     int numRows = children ? (int)children->length() : 0;
00604     //kdDebug(6030) << k_funcinfo << "index=" << index << " numRows=" << numRows << endl;
00605     if ( index < -1 || index > numRows ) {
00606         exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
00607     }
00608     else
00609     {
00610         r = new HTMLTableRowElementImpl(docPtr());
00611         if ( numRows == index || index == -1 )
00612             appendChild(r, exceptioncode);
00613         else {
00614             NodeImpl *n;
00615             if(index < 1)
00616                 n = firstChild();
00617             else
00618                 n = children->item(index);
00619             insertBefore(r, n, exceptioncode );
00620         }
00621     }
00622     delete children;
00623     return r;
00624 }
00625 
00626 void HTMLTableSectionElementImpl::deleteRow( long index, int &exceptioncode )
00627 {
00628     NodeListImpl *children = childNodes();
00629     int numRows = children ? (int)children->length() : 0;
00630     if ( index == -1 ) index = numRows - 1;
00631     if( index >= 0 && index < numRows )
00632         HTMLElementImpl::removeChild(children->item(index), exceptioncode);
00633     else
00634         exceptioncode = DOMException::INDEX_SIZE_ERR;
00635     delete children;
00636 }
00637 
00638 
00639 int HTMLTableSectionElementImpl::numRows() const
00640 {
00641     int rows = 0;
00642     const NodeImpl *n = firstChild();
00643     while (n) {
00644         if (n->id() == ID_TR)
00645             rows++;
00646         n = n->nextSibling();
00647     }
00648 
00649     return rows;
00650 }
00651 
00652 // -------------------------------------------------------------------------
00653 
00654 HTMLTableRowElementImpl::HTMLTableRowElementImpl(DocumentPtr *doc)
00655   : HTMLTablePartElementImpl(doc)
00656 {
00657 }
00658 
00659 HTMLTableRowElementImpl::~HTMLTableRowElementImpl()
00660 {
00661 }
00662 
00663 NodeImpl::Id HTMLTableRowElementImpl::id() const
00664 {
00665     return ID_TR;
00666 }
00667 
00668 long HTMLTableRowElementImpl::rowIndex() const
00669 {
00670     // some complex traversal stuff here to take into account that some rows may be in different sections
00671     int rIndex = 0;
00672     const NodeImpl *n = this;
00673     do {
00674         while (!n->previousSibling() && !(n->isElementNode() && n->id() == ID_TABLE))
00675             n = n->parentNode();
00676         if (n->isElementNode() && n->id() == ID_TABLE)
00677             n = 0;
00678         if (n) {
00679             n = n->previousSibling();
00680             while (!(n->isElementNode() && n->id() == ID_TR) && n->lastChild())
00681                 n = n->lastChild();
00682         }
00683 
00684         if (n && n->isElementNode() && n->id() == ID_TR)
00685             rIndex++;
00686     }
00687     while (n && n->isElementNode() && n->id() == ID_TR);
00688 
00689     return rIndex;
00690 }
00691 
00692 long HTMLTableRowElementImpl::sectionRowIndex() const
00693 {
00694     int rIndex = 0;
00695     const NodeImpl *n = this;
00696     do {
00697         n = n->previousSibling();
00698         if (n && n->isElementNode() && n->id() == ID_TR)
00699             rIndex++;
00700     }
00701     while (n);
00702 
00703     return rIndex;
00704 }
00705 
00706 HTMLElementImpl *HTMLTableRowElementImpl::insertCell( long index, int &exceptioncode )
00707 {
00708     HTMLTableCellElementImpl *c = 0L;
00709     NodeListImpl *children = childNodes();
00710     int numCells = children ? children->length() : 0;
00711     if ( index < -1 || index > numCells )
00712         exceptioncode = DOMException::INDEX_SIZE_ERR; // per the DOM
00713     else
00714     {
00715         c = new HTMLTableCellElementImpl(docPtr(), ID_TD);
00716         if(numCells == index || index == -1)
00717             appendChild(c, exceptioncode);
00718         else {
00719             NodeImpl *n;
00720             if(index < 1)
00721                 n = firstChild();
00722             else
00723                 n = children->item(index);
00724             insertBefore(c, n, exceptioncode);
00725         }
00726     }
00727     delete children;
00728     return c;
00729 }
00730 
00731 void HTMLTableRowElementImpl::deleteCell( long index, int &exceptioncode )
00732 {
00733     NodeListImpl *children = childNodes();
00734     int numCells = children ? children->length() : 0;
00735     if ( index == -1 ) index = numCells-1;
00736     if( index >= 0 && index < numCells )
00737         HTMLElementImpl::removeChild(children->item(index), exceptioncode);
00738     else
00739         exceptioncode = DOMException::INDEX_SIZE_ERR;
00740     delete children;
00741 }
00742 
00743 // -------------------------------------------------------------------------
00744 
00745 HTMLTableCellElementImpl::HTMLTableCellElementImpl(DocumentPtr *doc, int tag)
00746   : HTMLTablePartElementImpl(doc)
00747 {
00748   _col = -1;
00749   _row = -1;
00750   cSpan = rSpan = 1;
00751   m_nowrap = false;
00752   _id = tag;
00753   rowHeight = 0;
00754 }
00755 
00756 HTMLTableCellElementImpl::~HTMLTableCellElementImpl()
00757 {
00758 }
00759 
00760 void HTMLTableCellElementImpl::parseAttribute(AttributeImpl *attr)
00761 {
00762     switch(attr->id())
00763     {
00764     case ATTR_BORDER:
00765         // euhm? not supported by other browsers as far as I can see (Dirk)
00766         //addCSSLength(CSS_PROP_BORDER_WIDTH, attr->value());
00767         break;
00768     case ATTR_ROWSPAN:
00769         // ###
00770         rSpan = attr->val() ? attr->val()->toInt() : 1;
00771         // limit this to something not causing an overflow with short int
00772         if(rSpan < 1 || rSpan > 1024) rSpan = 1;
00773         break;
00774     case ATTR_COLSPAN:
00775         // ###
00776         cSpan = attr->val() ? attr->val()->toInt() : 1;
00777         // limit this to something not causing an overflow with short int
00778         if(cSpan < 1 || cSpan > 1024) cSpan = 1;
00779         break;
00780     case ATTR_NOWRAP:
00781         m_nowrap = (attr->val() != 0);
00782         break;
00783     case ATTR_WIDTH:
00784         if (!attr->value().isEmpty())
00785             addCSSLength( CSS_PROP_WIDTH, attr->value() );
00786         else
00787             removeCSSProperty(CSS_PROP_WIDTH);
00788         break;
00789     case ATTR_NOSAVE:
00790     break;
00791     default:
00792         HTMLTablePartElementImpl::parseAttribute(attr);
00793     }
00794 }
00795 
00796 void HTMLTableCellElementImpl::attach()
00797 {
00798     HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parentNode());
00799     while(p && p->id() != ID_TABLE)
00800         p = static_cast<HTMLElementImpl*>(p->parentNode());
00801 
00802     if(p) {
00803         HTMLTableElementImpl* table = static_cast<HTMLTableElementImpl*>(p);
00804         if (table->m_noBorder) {
00805             addCSSProperty(CSS_PROP_BORDER_WIDTH, "0");
00806         }
00807         else {
00808             addCSSProperty(CSS_PROP_BORDER_WIDTH, "1px");
00809             int v = (table->m_solid || m_solid) ? CSS_VAL_SOLID : CSS_VAL_INSET;
00810             addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, v);
00811             addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v);
00812             addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, v);
00813             addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, v);
00814 
00815             if (!m_solid)
00816                 addCSSProperty(CSS_PROP_BORDER_COLOR, "inherit");
00817         }
00818     }
00819 
00820     HTMLTablePartElementImpl::attach();
00821 }
00822 
00823 // -------------------------------------------------------------------------
00824 
00825 HTMLTableColElementImpl::HTMLTableColElementImpl(DocumentPtr *doc, ushort i)
00826     : HTMLTablePartElementImpl(doc)
00827 {
00828     _id = i;
00829     _span = (_id == ID_COLGROUP ? 0 : 1);
00830 }
00831 
00832 HTMLTableColElementImpl::~HTMLTableColElementImpl()
00833 {
00834 }
00835 
00836 NodeImpl::Id HTMLTableColElementImpl::id() const
00837 {
00838     return _id;
00839 }
00840 
00841 
00842 void HTMLTableColElementImpl::parseAttribute(AttributeImpl *attr)
00843 {
00844     switch(attr->id())
00845     {
00846     case ATTR_SPAN:
00847         _span = attr->val() ? attr->val()->toInt() : 1;
00848         break;
00849     case ATTR_WIDTH:
00850         if (!attr->value().isEmpty())
00851             addCSSLength(CSS_PROP_WIDTH, attr->value(), false, true );
00852         else
00853             removeCSSProperty(CSS_PROP_WIDTH);
00854         break;
00855     case ATTR_VALIGN:
00856         if (!attr->value().isEmpty())
00857             addCSSProperty(CSS_PROP_VERTICAL_ALIGN, attr->value());
00858         else
00859             removeCSSProperty(CSS_PROP_VERTICAL_ALIGN);
00860         break;
00861     default:
00862         HTMLTablePartElementImpl::parseAttribute(attr);
00863     }
00864 
00865 }
00866 
00867 // -------------------------------------------------------------------------
00868 
00869 HTMLTableCaptionElementImpl::HTMLTableCaptionElementImpl(DocumentPtr *doc)
00870   : HTMLTablePartElementImpl(doc)
00871 {
00872 }
00873 
00874 HTMLTableCaptionElementImpl::~HTMLTableCaptionElementImpl()
00875 {
00876 }
00877 
00878 NodeImpl::Id HTMLTableCaptionElementImpl::id() const
00879 {
00880     return ID_CAPTION;
00881 }
00882 
00883 
00884 void HTMLTableCaptionElementImpl::parseAttribute(AttributeImpl *attr)
00885 {
00886     switch(attr->id())
00887     {
00888     case ATTR_ALIGN:
00889         if (!attr->value().isEmpty())
00890             addCSSProperty(CSS_PROP_CAPTION_SIDE, attr->value());
00891         else
00892             removeCSSProperty(CSS_PROP_CAPTION_SIDE);
00893         break;
00894     default:
00895         HTMLElementImpl::parseAttribute(attr);
00896     }
00897 
00898 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:22:38 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001