khtml Library API Documentation

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