dom_elementimpl.cpp Source File (khtml Library)

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

# dom_elementimpl.cpp

    00001
    00025 //#define EVENT_DEBUG
    00026 #include "dom/dom_exception.h"
    00027 #include "dom/dom_node.h"
    00028 #include "xml/dom_textimpl.h"
    00029 #include "xml/dom_docimpl.h"
    00030 #include "xml/dom2_eventsimpl.h"
    00031 #include "xml/dom_elementimpl.h"
    00032
    00033 #include "html/dtd.h"
    00034 #include "html/htmlparser.h"
    00035
    00036 #include "rendering/render_root.h"
    00037 #include "misc/htmlhashes.h"
    00038 #include "css/css_valueimpl.h"
    00039 #include "css/css_stylesheetimpl.h"
    00040 #include "css/cssstyleselector.h"
    00041 #include "xml/dom_xmlimpl.h"
    00042
    00043 #include <qtextstream.h>
    00044 #include <kdebug.h>
    00045
    00046 using namespace DOM;
    00047 using namespace khtml;
    00048
    00049 void AttributeImpl::allocateImpl(ElementImpl* e) {
    00050     _impl = new AttrImpl(e, e->docPtr(), this);
    00051     _impl->ref();
    00052 }
    00053
    00054 void AttributeImpl::detachImpl()
    00055 {
    00056     if (_impl) {
    00057         _impl->deref();
    00058         _impl = 0;
    00059     }
    00060 }
    00061
    00062 AttrImpl::AttrImpl(ElementImpl* element, DocumentPtr* docPtr, AttributeImpl* a)
    00063     : NodeBaseImpl(docPtr),
    00064       m_element(element),
    00065       m_attribute(a)
    00066 {
    00067     assert(!m_attribute->_impl);
    00068     m_attribute->_impl = this;
    00069     m_attribute->ref();
    00070     m_specified = true; // we don't yet support default attributes
    00071 }
    00072
    00073 AttrImpl::~AttrImpl()
    00074 {
    00075     m_attribute->_impl = 0;
    00076     m_attribute->deref();
    00077 }
    00078
    00079 DOMString AttrImpl::nodeName() const
    00080 {
    00081     return getDocument()->attrName(m_attribute->id());
    00082 }
    00083
    00084 unsigned short AttrImpl::nodeType() const
    00085 {
    00086     return Node::ATTRIBUTE_NODE;
    00087 }
    00088
    00089 DOMString AttrImpl::prefix() const
    00090 {
    00091     return m_attribute->prefix();
    00092 }
    00093
    00094 void AttrImpl::setPrefix(const DOMString &_prefix, int &exceptioncode )
    00095 {
    00096     checkSetPrefix(_prefix, exceptioncode);
    00097     if (exceptioncode)
    00098         return;
    00099
    00100     m_attribute->setPrefix(_prefix.implementation());
    00101 }
    00102
    00103 DOMString AttrImpl::nodeValue() const {
    00104     return m_attribute->val();
    00105 }
    00106
    00107 void AttrImpl::setValue( const DOMString &v, int &exceptioncode )
    00108 {
    00109     exceptioncode = 0;
    00110
    00111     // ### according to the DOM docs, we should create an unparsed Text child
    00112     // node here
    00113     // do not interprete entities in the string, its literal!
    00114
    00115     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    00116     if (isReadOnly()) {
    00117         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00118         return;
    00119     }
    00120
    00121     // ### what to do on 0 ?
    00122     if (v.isNull()) {
    00123         exceptioncode = DOMException::DOMSTRING_SIZE_ERR;
    00124         return;
    00125     }
    00126
    00127     m_attribute->setValue(v.implementation());
    00128     if (m_element)
    00129         m_element->parseAttribute(m_attribute);
    00130 }
    00131
    00132 void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode )
    00133 {
    00134     exceptioncode = 0;
    00135     // NO_MODIFICATION_ALLOWED_ERR: taken care of by setValue()
    00136     setValue(v, exceptioncode);
    00137 }
    00138
    00139 NodeImpl *AttrImpl::cloneNode ( bool /*deep*/)
    00140 {
    00141         return new AttrImpl(0, docPtr(), new AttributeImpl(m_attribute->id(), m_attribute->val()));
    00142 }
    00143
    00144 // DOM Section 1.1.1
    00145 bool AttrImpl::childAllowed( NodeImpl *newChild )
    00146 {
    00147     if(!newChild)
    00148         return false;
    00149
    00150     return childTypeAllowed(newChild->nodeType());
    00151 }
    00152
    00153 bool AttrImpl::childTypeAllowed( unsigned short type )
    00154 {
    00155     switch (type) {
    00156         case Node::TEXT_NODE:
    00157         case Node::ENTITY_REFERENCE_NODE:
    00158             return true;
    00159             break;
    00160         default:
    00161             return false;
    00162     }
    00163 }
    00164
    00165 // -------------------------------------------------------------------------
    00166
    00167 ElementImpl::ElementImpl(DocumentPtr *doc)
    00168     : NodeBaseImpl(doc)
    00169 {
    00170     namedAttrMap = 0;
    00171     m_styleDecls = 0;
    00172     m_prefix = 0;
    00173 }
    00174
    00175 ElementImpl::~ElementImpl()
    00176 {
    00177     if(namedAttrMap) {
    00178         namedAttrMap->detachFromElement();
    00179         namedAttrMap->deref();
    00180     }
    00181
    00182     if (m_styleDecls) {
    00183         m_styleDecls->setNode(0);
    00184         m_styleDecls->setParent(0);
    00185         m_styleDecls->deref();
    00186     }
    00187
    00188     if (m_prefix)
    00189         m_prefix->deref();
    00190 }
    00191
    00192 void ElementImpl::removeAttribute( NodeImpl::Id id, int &exceptioncode )
    00193 {
    00194     if (namedAttrMap)
    00195         namedAttrMap->removeNamedItem(id, exceptioncode);
    00196 }
    00197
    00198 void ElementImpl::setAttribute(NodeImpl::Id id, const DOMString &value)
    00199 {
    00200     int exceptioncode = 0;
    00201     setAttribute(id,value.implementation(),exceptioncode);
    00202 }
    00203
    00204 unsigned short ElementImpl::nodeType() const
    00205 {
    00206     return Node::ELEMENT_NODE;
    00207 }
    00208
    00209 DOMString ElementImpl::getAttribute(NodeImpl::Id id) const
    00210 {
    00211     if (!namedAttrMap) return DOMString();
    00212     AttributeImpl* a = namedAttrMap->getAttributeItem(id);
    00213     if (a) return a->val();
    00214
    00215     // then search in default attr in case it is not yet set
    00216     NamedAttrMapImpl* dm = defaultMap();
    00217     if(!dm) return DOMString();
    00218     AttributeImpl* defattr = dm->getAttributeItem(id);
    00219     if (!defattr) return DOMString();
    00220     return defattr->val();
    00221 }
    00222
    00223 void ElementImpl::setAttribute(NodeImpl::Id id, DOMStringImpl* value, int &exceptioncode )
    00224 {
    00225     // allocate attributemap if necessary
    00226     AttributeImpl* old = attributes(false)->getAttributeItem(id);
    00227
    00228     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    00229     if (namedAttrMap->isReadOnly()) {
    00230         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00231         return;
    00232     }
    00233
    00234     if (old && !value)
    00235         namedAttrMap->removeAttribute(id);
    00236     else if (!old && value)
    00237         namedAttrMap->addAttribute(new AttributeImpl(id, value));
    00238     else if (old && value) {
    00239         old->setValue(value);
    00240         parseAttribute(old);
    00241     }
    00242 }
    00243
    00244 void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
    00245 {
    00246     if(namedAttrMap)
    00247         namedAttrMap->deref();
    00248
    00249     namedAttrMap = list;
    00250
    00251     if(namedAttrMap) {
    00252         namedAttrMap->ref();
    00253         namedAttrMap->m_element = this;
    00254         unsigned int len = namedAttrMap->length();
    00255         for(unsigned int i = 0; i < len; i++)
    00256             parseAttribute(namedAttrMap->m_attrs[i]);
    00257     }
    00258 }
    00259
    00260 NodeImpl *ElementImpl::cloneNode(bool deep)
    00261 {
    00262     ElementImpl *clone = getDocument()->createElement(tagName(), 0);
    00263     if (!clone) return 0;
    00264
    00265     // clone prefix (namespace)
    00266     clone->m_prefix = m_prefix;
    00267     if ( clone->m_prefix )
    00268         clone->m_prefix->ref();
    00269
    00270     // clone attributes
    00271     if(namedAttrMap)
    00272         *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
    00273
    00274     // clone individual style rules
    00275     if (m_styleDecls)
    00276         *(clone->styleRules()) = *m_styleDecls;
    00277
    00278     if (deep)
    00279         cloneChildNodes(clone);
    00280     return clone;
    00281 }
    00282
    00283 DOMString ElementImpl::nodeName() const
    00284 {
    00285     return tagName();
    00286 }
    00287
    00288 DOMString ElementImpl::tagName() const
    00289 {
    00290     DOMString tn = getDocument()->tagName(id());
    00291
    00292     if (m_prefix)
    00293         return DOMString(m_prefix) + ":" + tn;
    00294
    00295     return tn;
    00296 }
    00297
    00298 void ElementImpl::setPrefix( const DOMString &_prefix, int &exceptioncode )
    00299 {
    00300     checkSetPrefix(_prefix, exceptioncode);
    00301     if (exceptioncode)
    00302         return;
    00303
    00304     if (m_prefix)
    00305         m_prefix->deref();
    00306     m_prefix = _prefix.implementation();
    00307     if (m_prefix)
    00308         m_prefix->ref();
    00309 }
    00310
    00311 void ElementImpl::createAttributeMap() const
    00312 {
    00313     namedAttrMap = new NamedAttrMapImpl(const_cast<ElementImpl*>(this));
    00314     namedAttrMap->ref();
    00315 }
    00316
    00317 NamedAttrMapImpl* ElementImpl::defaultMap() const
    00318 {
    00319     return 0;
    00320 }
    00321
    00322 void ElementImpl::attach()
    00323 {
    00324     assert(!attached());
    00325     assert(!m_render);
    00326     assert(parentNode());
    00327
    00328 #if SPEED_DEBUG < 1
    00329     if (parentNode()->renderer()) {
    00330         RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
    00331         _style->ref();
    00332         m_render = RenderObject::createObject(this, _style);
    00333         if(m_render)
    00334             parentNode()->renderer()->addChild(m_render, nextRenderer());
    00335         _style->deref();
    00336     }
    00337 #endif
    00338
    00339     NodeBaseImpl::attach();
    00340 }
    00341
    00342 void ElementImpl::recalcStyle( StyleChange change )
    00343 {
    00344     // ### should go away and be done in renderobject
    00345     RenderStyle* _style = m_render ? m_render->style() : 0;
    00346 #if 0
    00347     const char* debug;
    00348     switch(change) {
    00349     case NoChange: debug = "NoChange";
    00350         break;
    00351     case NoInherit: debug= "NoInherit";
    00352         break;
    00353     case Inherit: debug = "Inherit";
    00354         break;
    00355     case Force: debug = "Force";
    00356         break;
    00357     }
    00358     qDebug("recalcStyle(%d: %s)[%p: %s]", change, debug, this, tagName().string().latin1());
    00359 #endif
    00360     if ( change >= Inherit || changed() ) {
    00361         EDisplay oldDisplay = _style ? _style->display() : NONE;
    00362
    00363         int dynamicState = StyleSelector::None;
    00364         if ( m_render && m_render->mouseInside() )
    00365             dynamicState |= StyleSelector::Hover;
    00366         if ( m_focused )
    00367             dynamicState |= StyleSelector::Focus;
    00368         if ( m_active )
    00369             dynamicState |= StyleSelector::Active;
    00370
    00371         RenderStyle *newStyle = getDocument()->styleSelector()->styleForElement(this, dynamicState);
    00372         newStyle->ref();
    00373         StyleChange ch = diff( _style, newStyle );
    00374         if ( ch != NoChange ) {
    00375             if (oldDisplay != newStyle->display()) {
    00376                 if (attached()) detach();
    00377                 // ### uuhm, suboptimal. style gets calculated again
    00378                 attach();
    00379                 // attach recalulates the style for all children. No need to do it twice.
    00380                 setChanged( false );
    00381                 setHasChangedChild( false );
    00382                 newStyle->deref();
    00383                 return;
    00384             }
    00385             if( m_render && newStyle ) {
    00386                 //qDebug("--> setting style on render element bgcolor=%s", newStyle->backgroundColor().name().latin1());
    00387                 m_render->setStyle(newStyle);
    00388             }
    00389         }
    00390         newStyle->deref();
    00391
    00392         if ( change != Force )
    00393             change = ch;
    00394     }
    00395
    00396     NodeImpl *n;
    00397     for (n = _first; n; n = n->nextSibling()) {
    00398         //qDebug("    (%p) calling recalcStyle on child %s/%p, change=%d", this, n, n->isElementNode() ? ((ElementImpl *)n)->tagName().string().latin1() : n->isTextNode() ? "text" : "unknown", change );
    00399         if ( change >= Inherit || n->isTextNode() ||
    00400              n->hasChangedChild() || n->changed() )
    00401             n->recalcStyle( change );
    00402     }
    00403
    00404     setChanged( false );
    00405     setHasChangedChild( false );
    00406 }
    00407
    00408 bool ElementImpl::isSelectable() const
    00409 {
    00410     return false;
    00411 }
    00412
    00413 // DOM Section 1.1.1
    00414 bool ElementImpl::childAllowed( NodeImpl *newChild )
    00415 {
    00416     if (!childTypeAllowed(newChild->nodeType()))
    00417         return false;
    00418
    00419     // ### check xml element allowedness according to DTD
    00420
    00421     // If either this node or the other node is an XML element node, allow regardless (we don't do DTD checks for XML
    00422     // yet)
    00423     if (isXMLElementNode() || newChild->isXMLElementNode())
    00424         return true;
    00425     else
    00426         return checkChild(id(), newChild->id());
    00427 }
    00428
    00429 bool ElementImpl::childTypeAllowed( unsigned short type )
    00430 {
    00431     switch (type) {
    00432         case Node::ELEMENT_NODE:
    00433         case Node::TEXT_NODE:
    00434         case Node::COMMENT_NODE:
    00435         case Node::PROCESSING_INSTRUCTION_NODE:
    00436         case Node::CDATA_SECTION_NODE:
    00437         case Node::ENTITY_REFERENCE_NODE:
    00438             return true;
    00439             break;
    00440         default:
    00441             return false;
    00442     }
    00443 }
    00444
    00445 void ElementImpl::createDecl( )
    00446 {
    00447     m_styleDecls = new CSSStyleDeclarationImpl(0);
    00448     m_styleDecls->ref();
    00449     m_styleDecls->setParent(getDocument()->elementSheet());
    00450     m_styleDecls->setNode(this);
    00451     m_styleDecls->setStrictParsing( getDocument()->parseMode() == DocumentImpl::Strict );
    00452 }
    00453
    00454 void ElementImpl::dispatchAttrRemovalEvent(AttributeImpl * /*attr*/)
    00455 {
    00456     if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
    00457         return;
    00458     //int exceptioncode = 0;
    00459     //dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
    00460     //attr->value(), getDocument()->attrName(attr->id()),MutationEvent::REMOVAL),exceptioncode);
    00461 }
    00462
    00463 void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl * /*attr*/)
    00464 {
    00465     if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
    00466         return;
    00467    //int exceptioncode = 0;
    00468    //dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
    00469    //attr->value(),getDocument()->attrName(attr->id()),MutationEvent::ADDITION),exceptioncode);
    00470 }
    00471
    00472 #ifndef NDEBUG
    00473 void ElementImpl::dump(QTextStream *stream, QString ind) const
    00474 {
    00475     if (namedAttrMap) {
    00476         for (uint i = 0; i < namedAttrMap->length(); i++) {
    00477             AttributeImpl *attr = namedAttrMap->attributeItem(i);
    00478             *stream << " " << DOMString(getDocument()->attrName(attr->id())).string().ascii()
    00479                     << "=\"" << DOMString(attr->value()).string().ascii() << "\"";
    00480         }
    00481     }
    00482
    00483     NodeBaseImpl::dump(stream,ind);
    00484 }
    00485 #endif
    00486
    00487 // -------------------------------------------------------------------------
    00488
    00489 XMLElementImpl::XMLElementImpl(DocumentPtr *doc, DOMStringImpl *_tagName)
    00490     : ElementImpl(doc)
    00491 {
    00492     m_id = doc->document()->tagId(0 /* no namespace */, _tagName,
    00493                                   false /* allocate */, 0);
    00494 }
    00495
    00496 XMLElementImpl::XMLElementImpl(DocumentPtr *doc, Id id)
    00497     : ElementImpl(doc), m_id(id)
    00498 {
    00499 }
    00500
    00501 XMLElementImpl::XMLElementImpl(DocumentPtr *doc, DOMStringImpl *_qualifiedName, DOMStringImpl *_namespaceURI)
    00502     : ElementImpl(doc)
    00503 {
    00504     int colonpos = -1;
    00505     for (uint i = 0; i < _qualifiedName->l; ++i)
    00506         if (_qualifiedName->s[i] == ':') {
    00507             colonpos = i;
    00508             break;
    00509         }
    00510
    00511     if (colonpos >= 0) {
    00512         // we have a prefix
    00513         DOMStringImpl* localName = _qualifiedName->copy();
    00514         localName->ref();
    00515         localName->remove(0,colonpos+1);
    00516         m_id = doc->document()->tagId(_namespaceURI, localName, false /* allocate */, 0);
    00517         localName->deref();
    00518         m_prefix = _qualifiedName->copy();
    00519         m_prefix->ref();
    00520         m_prefix->truncate(colonpos);
    00521     }
    00522     else {
    00523         // no prefix
    00524         m_id = doc->document()->tagId(_namespaceURI, _qualifiedName, false /* allocate */, 0);
    00525         m_prefix = 0;
    00526     }
    00527 }
    00528
    00529 XMLElementImpl::~XMLElementImpl()
    00530 {
    00531 }
    00532
    00533 DOMString XMLElementImpl::localName() const
    00534 {
    00535     return getDocument()->tagName(m_id);
    00536 }
    00537
    00538
    00539 NodeImpl *XMLElementImpl::cloneNode ( bool deep )
    00540 {
    00541     XMLElementImpl *clone = new XMLElementImpl(docPtr(), m_id);
    00542     // clone prefix (namespace)
    00543     clone->m_prefix = m_prefix;
    00544     if ( clone->m_prefix )
    00545         clone->m_prefix->ref();
    00546
    00547     // clone attributes
    00548     if(namedAttrMap)
    00549         *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
    00550
    00551     // clone individual style rules
    00552     if (m_styleDecls)
    00553         *(clone->styleRules()) = *m_styleDecls;
    00554
    00555     if (deep)
    00556         cloneChildNodes(clone);
    00557
    00558     return clone;
    00559 }
    00560
    00561 // -------------------------------------------------------------------------
    00562
    00563 NamedAttrMapImpl::NamedAttrMapImpl(ElementImpl *e)
    00564     : m_element(e)
    00565 {
    00566     m_attrs = 0;
    00567     m_len = 0;
    00568 }
    00569
    00570 NamedAttrMapImpl::~NamedAttrMapImpl()
    00571 {
    00572     clearAttributes();
    00573 }
    00574
    00575
    00576 AttrImpl *NamedAttrMapImpl::getNamedItem ( NodeImpl::Id id ) const
    00577 {
    00578     AttributeImpl* a = getAttributeItem(id);
    00579     if (!a) return 0;
    00580
    00581     if (!a->attrImpl())
    00582         a->allocateImpl(m_element);
    00583
    00584     return a->attrImpl();
    00585 }
    00586
    00587 Node NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, int &exceptioncode )
    00588 {
    00589     if (!m_element) {
    00590         exceptioncode = DOMException::NOT_FOUND_ERR;
    00591         return 0;
    00592     }
    00593
    00594     // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
    00595     if (isReadOnly()) {
    00596         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00597         return 0;
    00598     }
    00599
    00600     // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
    00601     if (arg->getDocument() != m_element->getDocument()) {
    00602         exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
    00603         return 0;
    00604     }
    00605
    00606     // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
    00607     if (!arg->isAttributeNode()) {
    00608         exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
    00609         return 0;
    00610     }
    00611     AttrImpl *attr = static_cast<AttrImpl*>(arg);
    00612
    00613     // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
    00614     // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    00615     if (attr->ownerElement() && attr->ownerElement() != m_element) {
    00616         exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
    00617         return 0;
    00618     }
    00619
    00620     AttributeImpl* a = attr->attrImpl();
    00621     AttributeImpl* old = getAttributeItem(a->id());
    00622     if (old == a) return arg; // we know about it already
    00623
    00624     // ### slightly inefficient - resizes attribute array twice.
    00625     Node r;
    00626     if (old) {
    00627         if (!old->attrImpl())
    00628             old->allocateImpl(m_element);
    00629         r = old->_impl;
    00630         removeAttribute(a->id());
    00631     }
    00632     addAttribute(a);
    00633     return r;
    00634 }
    00635
    00636 // The DOM2 spec doesn't say that removeAttribute[NS] throws NOT_FOUND_ERR
    00637 // if the attribute is not found - David
    00638 Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, int &exceptioncode )
    00639 {
    00640     // ### should this really be raised when the attribute to remove isn't there at all?
    00641     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    00642     if (isReadOnly()) {
    00643         exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
    00644         return Node();
    00645     }
    00646
    00647     AttributeImpl* a = getAttributeItem(id);
    00648     if (!a) return Node();
    00649
    00650     if (!a->attrImpl())  a->allocateImpl(m_element);
    00651     Node r(a->attrImpl());
    00652     removeAttribute(id);
    00653     return r;
    00654 }
    00655
    00656 AttrImpl *NamedAttrMapImpl::item ( unsigned long index ) const
    00657 {
    00658     if (index >= m_len)
    00659         return 0;
    00660
    00661     if (!m_attrs[index]->attrImpl())
    00662         m_attrs[index]->allocateImpl(m_element);
    00663
    00664     return m_attrs[index]->attrImpl();
    00665 }
    00666
    00667 unsigned long NamedAttrMapImpl::length(  ) const
    00668 {
    00669     return m_len;
    00670 }
    00671
    00672 AttributeImpl* NamedAttrMapImpl::getAttributeItem(NodeImpl::Id id) const
    00673 {
    00674     for (unsigned long i = 0; i < m_len; ++i)
    00675         if (m_attrs[i]->id() == id)
    00676             return m_attrs[i];
    00677
    00678     return 0;
    00679 }
    00680
    00681 NodeImpl::Id NamedAttrMapImpl::mapId(const DOMString& namespaceURI,
    00682                                      const DOMString& localName, bool readonly)
    00683 {
    00684     assert(m_element);
    00685     if (!m_element) return 0;
    00686     return m_element->getDocument()->attrId(namespaceURI.implementation(),
    00687                                             localName.implementation(), readonly, 0);
    00688 }
    00689
    00690 void NamedAttrMapImpl::clearAttributes()
    00691 {
    00692     if (m_attrs) {
    00693         uint i;
    00694         for (i = 0; i < m_len; i++) {
    00695             if (m_attrs[i]->_impl)
    00696                 m_attrs[i]->_impl->m_element = 0;
    00697             m_attrs[i]->detachImpl();
    00698             m_attrs[i]->deref();
    00699         }
    00700         delete [] m_attrs;
    00701         m_attrs = 0;
    00702     }
    00703     m_len = 0;
    00704 }
    00705
    00706 void NamedAttrMapImpl::detachFromElement()
    00707 {
    00708     // we allow a NamedAttrMapImpl w/o an element in case someone still has a reference
    00709     // to if after the element gets deleted - but the map is now invalid
    00710     m_element = 0;
    00711     clearAttributes();
    00712 }
    00713
    00714 NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other)
    00715 {
    00716     // clone all attributes in the other map, but attach to our element
    00717     if (!m_element) return *this;
    00718
    00719     clearAttributes();
    00720     m_len = other.m_len;
    00721     m_attrs = new AttributeImpl* [m_len];
    00722
    00723     // first initialize m_attrs vector, then call parseAttribute on it
    00724     // this allows parseAttribute to use getAttribute
    00725     for (uint i = 0; i < m_len; i++) {
    00726         m_attrs[i] = new AttributeImpl(other.m_attrs[i]->id(), other.m_attrs[i]->val());
    00727         m_attrs[i]->ref();
    00728     }
    00729
    00730     for(uint i = 0; i < m_len; i++)
    00731         m_element->parseAttribute(m_attrs[i]);
    00732
    00733     return *this;
    00734 }
    00735
    00736 void NamedAttrMapImpl::addAttribute(AttributeImpl *attr)
    00737 {
    00738     // Add the attribute tot he list
    00739     AttributeImpl **newAttrs = new AttributeImpl* [m_len+1];
    00740     if (m_attrs) {
    00741       for (uint i = 0; i < m_len; i++)
    00742         newAttrs[i] = m_attrs[i];
    00743       delete [] m_attrs;
    00744     }
    00745     m_attrs = newAttrs;
    00746     m_attrs[m_len++] = attr;
    00747     attr->ref();
    00748
    00749     // Notify the element that the attribute has been added, and dispatch appropriate mutation events
    00750     // Note that element may be null here if we are called from insertAttr() during parsing
    00751     if (m_element) {
    00752         m_element->parseAttribute(attr);
    00753         m_element->dispatchAttrAdditionEvent(attr);
    00754         m_element->dispatchSubtreeModifiedEvent();
    00755     }
    00756 }
    00757
    00758 void NamedAttrMapImpl::removeAttribute(NodeImpl::Id id)
    00759 {
    00760     unsigned long index = m_len+1;
    00761     for (unsigned long i = 0; i < m_len; ++i)
    00762         if (m_attrs[i]->id() == id) {
    00763             index = i;
    00764             break;
    00765         }
    00766
    00767     if (index >= m_len) return;
    00768
    00769     // Remove the attribute from the list
    00770     AttributeImpl* attr = m_attrs[index];
    00771     if (m_attrs[index]->_impl)
    00772         m_attrs[index]->_impl->m_element = 0;
    00773     if (m_len == 1) {
    00774         delete [] m_attrs;
    00775         m_attrs = 0;
    00776         m_len = 0;
    00777     }
    00778     else {
    00779         AttributeImpl **newAttrs = new AttributeImpl* [m_len-1];
    00780         uint i;
    00781         for (i = 0; i < uint(index); i++)
    00782             newAttrs[i] = m_attrs[i];
    00783         m_len--;
    00784         for (; i < m_len; i++)
    00785             newAttrs[i] = m_attrs[i+1];
    00786         delete [] m_attrs;
    00787         m_attrs = newAttrs;
    00788     }
    00789
    00790     // Notify the element that the attribute has been removed
    00791     // dispatch appropriate mutation events
    00792     if (m_element && attr->_value) {
    00793         DOMStringImpl* value = attr->_value;
    00794         attr->_value = 0;
    00795         m_element->parseAttribute(attr);
    00796         attr->_value = value;
    00797     }
    00798     if (m_element) {
    00799         m_element->dispatchAttrRemovalEvent(attr);
    00800         m_element->dispatchSubtreeModifiedEvent();
    00801     }
    00802     attr->detachImpl();
    00803     attr->deref();
    00804 }
    00805

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:43 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001