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 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 
KDE Logo
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