| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# html_miscimpl.cpp

    00001
    00024 // -------------------------------------------------------------------------
    00025 #include "html/html_miscimpl.h"
    00026 #include "html/html_formimpl.h"
    00027
    00028 #include "misc/htmlhashes.h"
    00029 #include "dom/dom_node.h"
    00030
    00031 using namespace DOM;
    00032
    00033 #include <kdebug.h>
    00034
    00035 HTMLBaseFontElementImpl::HTMLBaseFontElementImpl(DocumentPtr *doc)
    00036     : HTMLElementImpl(doc)
    00037 {
    00038 }
    00039
    00040 HTMLBaseFontElementImpl::~HTMLBaseFontElementImpl()
    00041 {
    00042 }
    00043
    00044 NodeImpl::Id HTMLBaseFontElementImpl::id() const
    00045 {
    00046     return ID_BASEFONT;
    00047 }
    00048
    00049 // -------------------------------------------------------------------------
    00050
    00051 HTMLCollectionImpl::HTMLCollectionImpl(NodeImpl *_base, int _type)
    00052 {
    00053     base = _base;
    00054     base->ref();
    00055     type = _type;
    00056     currentItem = 0L;
    00057     idsDone = false;
    00058 }
    00059
    00060 HTMLCollectionImpl::~HTMLCollectionImpl()
    00061 {
    00062     base->deref();
    00063 }
    00064
    00065 unsigned long HTMLCollectionImpl::calcLength(NodeImpl *current) const
    00066 {
    00067     unsigned long len = 0;
    00068     while(current)
    00069     {
    00070         if(current->nodeType() == Node::ELEMENT_NODE)
    00071         {
    00072             bool deep = true;
    00073             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
    00074             switch(type)
    00075             {
    00076             case DOC_IMAGES:
    00077                 if(e->id() == ID_IMG)
    00078                     len++;
    00079                 break;
    00080             case DOC_FORMS:
    00081                 if(e->id() == ID_FORM)
    00082                     len++;
    00083                 break;
    00084             case TABLE_TBODIES:
    00085                 if(e->id() == ID_TBODY)
    00086                     len++;
    00087                 else if(e->id() == ID_TABLE)
    00088                     deep = false;
    00089                 break;
    00090             case TR_CELLS:
    00091                 if(e->id() == ID_TD || e->id() == ID_TH)
    00092                     len++;
    00093                 else if(e->id() == ID_TABLE)
    00094                     deep = false;
    00095                 break;
    00096             case TABLE_ROWS:
    00097             case TSECTION_ROWS:
    00098                 if(e->id() == ID_TR)
    00099                     len++;
    00100                 else if(e->id() == ID_TABLE)
    00101                     deep = false;
    00102                 break;
    00103             case SELECT_OPTIONS:
    00104                 if(e->id() == ID_OPTION)
    00105                     len++;
    00106                 break;
    00107             case MAP_AREAS:
    00108                 if(e->id() == ID_AREA)
    00109                     len++;
    00110                 break;
    00111             case DOC_APPLETS:   // all OBJECT and APPLET elements
    00112                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
    00113                     len++;
    00114                 break;
    00115             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
    00116                 if(e->id() == ID_A || e->id() == ID_AREA)
    00117                     if(!e->getAttribute(ATTR_HREF).isNull())
    00118                         len++;
    00119                 break;
    00120             case DOC_ANCHORS:      // all A elements with a value for name and/or id
    00121                 if(e->id() == ID_A) {
    00122                     if(e->hasID() || !e->getAttribute(ATTR_NAME).isNull())
    00123                         len++;
    00124                 }
    00125                 break;
    00126             case DOC_ALL:      // "all" elements
    00127                 len++;
    00128                 break;
    00129             case NODE_CHILDREN: // first-level children
    00130                 len++;
    00131                 deep = false;
    00132                 break;
    00133             default:
    00134                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
    00135             }
    00136             if(deep && current->firstChild())
    00137                 len += calcLength(current->firstChild());
    00138         }
    00139         current = current->nextSibling();
    00140     }
    00141     return len;
    00142 }
    00143
    00144 // since the collections are to be "live", we have to do the
    00145 // calculation every time...
    00146 unsigned long HTMLCollectionImpl::length() const
    00147 {
    00148     return calcLength(base->firstChild());
    00149 }
    00150
    00151 NodeImpl *HTMLCollectionImpl::getItem(NodeImpl *current, int index, int &len) const
    00152 {
    00153     while(current)
    00154     {
    00155         if(current->nodeType() == Node::ELEMENT_NODE)
    00156         {
    00157             bool deep = true;
    00158             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
    00159             switch(type)
    00160             {
    00161             case DOC_IMAGES:
    00162                 if(e->id() == ID_IMG)
    00163                     len++;
    00164                 break;
    00165             case DOC_FORMS:
    00166                 if(e->id() == ID_FORM)
    00167                     len++;
    00168                 break;
    00169             case TABLE_TBODIES:
    00170                 if(e->id() == ID_TBODY)
    00171                     len++;
    00172                 else if(e->id() == ID_TABLE)
    00173                     deep = false;
    00174                 break;
    00175             case TR_CELLS:
    00176                 if(e->id() == ID_TD || e->id() == ID_TH)
    00177                     len++;
    00178                 else if(e->id() == ID_TABLE)
    00179                     deep = false;
    00180                 break;
    00181             case TABLE_ROWS:
    00182             case TSECTION_ROWS:
    00183                 if(e->id() == ID_TR)
    00184                     len++;
    00185                 else if(e->id() == ID_TABLE)
    00186                     deep = false;
    00187                 break;
    00188             case SELECT_OPTIONS:
    00189                 if(e->id() == ID_OPTION)
    00190                     len++;
    00191                 break;
    00192             case MAP_AREAS:
    00193                 if(e->id() == ID_AREA)
    00194                     len++;
    00195                 break;
    00196             case DOC_APPLETS:   // all OBJECT and APPLET elements
    00197                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
    00198                     len++;
    00199                 break;
    00200             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
    00201                 if(e->id() == ID_A || e->id() == ID_AREA)
    00202                     if(!e->getAttribute(ATTR_HREF).isNull())
    00203                         len++;
    00204                 break;
    00205             case DOC_ANCHORS:      // all A elements with a value for name or an id attribute
    00206                 if(e->id() == ID_A) {
    00207                     if(e->hasID() || !e->getAttribute(ATTR_NAME).isNull())
    00208                         len++;
    00209                 }
    00210                 break;
    00211             case DOC_ALL:
    00212                 len++;
    00213                 break;
    00214             case NODE_CHILDREN:
    00215                 len++;
    00216                 deep = false;
    00217                 break;
    00218             default:
    00219                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
    00220             }
    00221             if(len == (index + 1)) return current;
    00222             NodeImpl *retval=0;
    00223             if(deep && current->firstChild())
    00224                 retval = getItem(current->firstChild(), index, len);
    00225             if(retval) return retval;
    00226         }
    00227         current = current->nextSibling();
    00228     }
    00229     return 0;
    00230 }
    00231
    00232 NodeImpl *HTMLCollectionImpl::item( unsigned long index ) const
    00233 {
    00234     int pos = 0;
    00235     return getItem(base->firstChild(), index, pos);
    00236 }
    00237
    00238 NodeImpl *HTMLCollectionImpl::firstItem() const
    00239 {
    00240     int pos = 0;
    00241     currentItem = getItem(base->firstChild(), 0, pos);
    00242     return currentItem;
    00243 }
    00244
    00245 NodeImpl *HTMLCollectionImpl::nextItem() const
    00246 {
    00247     int pos = 0;
    00248     // Look for the 'second' item. The first one is currentItem, already given back.
    00249     NodeImpl *retval = getItem(currentItem, 1, pos);
    00250     if (retval)
    00251     {
    00252         currentItem = retval;
    00253         return retval;
    00254     }
    00255     // retval was 0, means we have to go up
    00256     while( !retval && currentItem->parentNode()
    00257            && currentItem->parentNode() != base )
    00258     {
    00259         currentItem = currentItem->parentNode();
    00260         if (currentItem->nextSibling())
    00261         {
    00262             // ... and to take the first one from there
    00263             pos = 0;
    00264             retval = getItem(currentItem->nextSibling(), 0, pos);
    00265         }
    00266     }
    00267     currentItem = retval;
    00268     return currentItem;
    00269 }
    00270
    00271 NodeImpl *HTMLCollectionImpl::getNamedItem( NodeImpl *current, int attr_id,
    00272                                             const DOMString &name ) const
    00273 {
    00274     if(name.isEmpty())
    00275         return 0;
    00276
    00277     while(current)
    00278     {
    00279         if(current->nodeType() == Node::ELEMENT_NODE)
    00280         {
    00281             bool deep = true;
    00282             bool check = false;
    00283             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
    00284             switch(type)
    00285             {
    00286             case DOC_IMAGES:
    00287                 if(e->id() == ID_IMG)
    00288                     check = true;
    00289                 break;
    00290             case DOC_FORMS:
    00291                 if(e->id() == ID_FORM)
    00292                     check = true;
    00293                 break;
    00294             case TABLE_TBODIES:
    00295                 if(e->id() == ID_TBODY)
    00296                     check = true;
    00297                 else if(e->id() == ID_TABLE)
    00298                     deep = false;
    00299                 break;
    00300             case TR_CELLS:
    00301                 if(e->id() == ID_TD || e->id() == ID_TH)
    00302                     check = true;
    00303                 else if(e->id() == ID_TABLE)
    00304                     deep = false;
    00305                 break;
    00306             case TABLE_ROWS:
    00307             case TSECTION_ROWS:
    00308                 if(e->id() == ID_TR)
    00309                     check = true;
    00310                 else if(e->id() == ID_TABLE)
    00311                     deep = false;
    00312                 break;
    00313             case SELECT_OPTIONS:
    00314                 if(e->id() == ID_OPTION)
    00315                     check = true;
    00316                 break;
    00317             case MAP_AREAS:
    00318                 if(e->id() == ID_AREA)
    00319                     check = true;
    00320                 break;
    00321             case DOC_APPLETS:   // all OBJECT and APPLET elements
    00322                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
    00323                     check = true;
    00324                 break;
    00325             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
    00326                 if(e->id() == ID_A || e->id() == ID_AREA)
    00327                     if(!e->getAttribute(ATTR_HREF).isNull())
    00328                         check = true;
    00329                 break;
    00330             case DOC_ANCHORS:      // all A elements with a value for name
    00331                 if(e->id() == ID_A) {
    00332                     if(e->hasID() || !e->getAttribute(ATTR_NAME).isNull())
    00333                         check = true;
    00334                 }
    00335                 break;
    00336             case DOC_ALL:
    00337                 check = true;
    00338                 break;
    00339             case NODE_CHILDREN:
    00340                 check = true;
    00341                 deep = false;
    00342                 break;
    00343             default:
    00344                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
    00345                 break;
    00346             }
    00347             if(check && e->getAttribute(attr_id) == name)
    00348             {
    00349                 //kdDebug( 6030 ) << "found node: " << e << " " << current << " " << e->id() << " " << e->tagName().string() << endl;
    00350                 return current;
    00351             }
    00352             NodeImpl *retval = 0;
    00353             if(deep && current->firstChild())
    00354                 retval = getNamedItem(current->firstChild(), attr_id, name);
    00355             if(retval)
    00356             {
    00357                 //kdDebug( 6030 ) << "got a return value " << retval << endl;
    00358                 return retval;
    00359             }
    00360         }
    00361         current = current->nextSibling();
    00362     }
    00363     return 0;
    00364 }
    00365
    00366 NodeImpl *HTMLCollectionImpl::namedItem( const DOMString &name ) const
    00367 {
    00368     // http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/nameditem.asp
    00369     // This method first searches for an object with a matching id
    00370     // attribute. If a match is not found, the method then searches for an
    00371     // object with a matching name attribute, but only on those elements
    00372     // that are allowed a name attribute.
    00373     idsDone = false;
    00374     currentItem = getNamedItem(base->firstChild(), ATTR_ID, name);
    00375     if(currentItem)
    00376         return currentItem;
    00377     idsDone = true;
    00378     currentItem = getNamedItem(base->firstChild(), ATTR_NAME, name);
    00379     return currentItem;
    00380 }
    00381
    00382 NodeImpl *HTMLCollectionImpl::nextNamedItem( const DOMString &name ) const
    00383 {
    00384     // nextNamedItemInternal can return an item that has both id=<name> and name=<name>
    00385     // Here, we have to filter out such cases.
    00386     NodeImpl *impl = nextNamedItemInternal( name );
    00387     if (!idsDone) // looking for id=<name> -> no filtering
    00388         return impl;
    00389     // looking for name=<name> -> filter out if id=<name>
    00390     bool ok = false;
    00391     while (impl && !ok)
    00392     {
    00393         if(impl->nodeType() == Node::ELEMENT_NODE)
    00394         {
    00395             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(impl);
    00396             ok = (e->getAttribute(ATTR_ID) != name);
    00397             if (!ok)
    00398                 impl = nextNamedItemInternal( name );
    00399         } else // can't happen
    00400             ok = true;
    00401     }
    00402     return impl;
    00403 }
    00404
    00405 NodeImpl *HTMLCollectionImpl::nextNamedItemInternal( const DOMString &name ) const
    00406 {
    00407     //kdDebug() << "\nHTMLCollectionImpl::nextNamedItem starting at " << currentItem << endl;
    00408     // Go to next item first (to avoid returning the same)
    00409     currentItem = nextItem();
    00410     //kdDebug() << "*HTMLCollectionImpl::nextNamedItem next item is " << currentItem << endl;
    00411
    00412     if ( currentItem )
    00413     {
    00414         // Then look for next matching named item
    00415         NodeImpl *retval = getNamedItem(currentItem, idsDone ? ATTR_NAME : ATTR_ID, name);
    00416         if ( retval )
    00417         {
    00418             //kdDebug() << "*HTMLCollectionImpl::nextNamedItem found " << retval << endl;
    00419             currentItem = retval;
    00420             return retval;
    00421         }
    00422
    00423         // retval was 0, means we have to go up
    00424         while( !retval && currentItem->parentNode()
    00425                && currentItem->parentNode() != base )
    00426         {
    00427             currentItem = currentItem->parentNode();
    00428             if (currentItem->nextSibling())
    00429             {
    00430                 // ... and to take the first one from there
    00431                 retval = getNamedItem(currentItem->nextSibling(), idsDone ? ATTR_NAME : ATTR_ID, name);
    00432             }
    00433         }
    00434         if ( retval )
    00435         {
    00436             //kdDebug() << "*HTMLCollectionImpl::nextNamedItem found after going up " << retval << endl;
    00437             currentItem = retval;
    00438             return currentItem;
    00439         }
    00440     }
    00441
    00442     if ( idsDone )
    00443         return 0;
    00444     // After doing all ATTR_ID, do ATTR_NAME
    00445     //kdDebug() << "*HTMLCollectionImpl::nextNamedItem going to ATTR_NAME now" << endl;
    00446     idsDone = true;
    00447     currentItem = getNamedItem(base->firstChild(), ATTR_NAME, name);
    00448     return currentItem;
    00449
    00450 }
    00451
    00452 // -----------------------------------------------------------------------------
    00453
    00454 unsigned long HTMLFormCollectionImpl::calcLength(NodeImpl*) const
    00455 {
    00456     QPtrList<HTMLGenericFormElementImpl> l = static_cast<HTMLFormElementImpl*>( base )->formElements;
    00457
    00458     int len = 0;
    00459     for ( unsigned i = 0; i < l.count(); i++ )
    00460         if ( l.at( i )->isEnumeratable() )
    00461             ++len;
    00462
    00463     return len;
    00464 }
    00465
    00466 NodeImpl* HTMLFormCollectionImpl::getItem(NodeImpl *, int index, int&) const
    00467 {
    00468     QPtrList<HTMLGenericFormElementImpl> l = static_cast<HTMLFormElementImpl*>( base )->formElements;
    00469
    00470     for ( unsigned i = 0; i < l.count(); i++ ) {
    00471
    00472         if( l.at( i )->isEnumeratable() ) {
    00473             if ( !index )
    00474                 return l.at( i );
    00475
    00476             --index;
    00477         }
    00478     }
    00479
    00480     return 0;
    00481 }
    00482
    00483 NodeImpl* HTMLFormCollectionImpl::getNamedItem(NodeImpl*, int attr_id, const DOMString& name) const
    00484 {
    00485     currentPos = 0;
    00486     return getNamedFormItem( attr_id, name, 0 );
    00487 }
    00488
    00489 NodeImpl* HTMLFormCollectionImpl::getNamedFormItem(int attr_id, const DOMString& name, int duplicateNumber) const
    00490 {
    00491     if(base->nodeType() == Node::ELEMENT_NODE)
    00492     {
    00493         HTMLElementImpl* e = static_cast<HTMLElementImpl*>(base);
    00494         bool foundInputElements = false;
    00495         if(e->id() == ID_FORM)
    00496         {
    00497             HTMLGenericFormElementImpl* element;
    00498             HTMLFormElementImpl* f = static_cast<HTMLFormElementImpl*>(e);
    00499
    00500             for(element = f->formElements.first(); element; element = f->formElements.next())
    00501                 if(element->isEnumeratable() && element->getAttribute(attr_id) == name)
    00502                 {
    00503                     if (!duplicateNumber)
    00504                         return element;
    00505                     --duplicateNumber;
    00506                     foundInputElements = true;
    00507                 }
    00508         }
    00509         // IE looks at <img> only if no <input> has the same name
    00510         if ( !foundInputElements )
    00511         {
    00512             HTMLImageElementImpl* element;
    00513             HTMLFormElementImpl* f = static_cast<HTMLFormElementImpl*>(e);
    00514
    00515             for(element = f->imgElements.first(); element; element = f->imgElements.next())
    00516                 if(element->getAttribute(attr_id) == name)
    00517                 {
    00518                     if (!duplicateNumber)
    00519                         return element;
    00520                     --duplicateNumber;
    00521                     foundInputElements = true;
    00522                 }
    00523         }
    00524     }
    00525     return 0;
    00526 }
    00527
    00528 NodeImpl * HTMLFormCollectionImpl::firstItem() const
    00529 {
    00530     currentPos = 0;
    00531     int dummy = 0;
    00532     return getItem(0 /*base->firstChild() unused*/, currentPos, dummy);
    00533 }
    00534
    00535 NodeImpl * HTMLFormCollectionImpl::nextItem() const
    00536 {
    00537     // This implementation loses the whole benefit of firstItem/nextItem :(
    00538     int dummy = 0;
    00539     return getItem(0 /*base->firstChild() unused*/, ++currentPos, dummy);
    00540 }
    00541
    00542 NodeImpl * HTMLFormCollectionImpl::nextNamedItemInternal( const DOMString &name ) const
    00543 {
    00544     NodeImpl *retval = getNamedFormItem( idsDone ? ATTR_NAME : ATTR_ID, name, ++currentPos );
    00545     if ( retval )
    00546         return retval;
    00547     if ( idsDone ) // we're done
    00548         return 0;
    00549     // After doing all ATTR_ID, do ATTR_NAME
    00550     idsDone = true;
    00551     return getNamedItem(base->firstChild(), ATTR_NAME, name);
    00552 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:33:56 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001