00001
00025
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
00104
00105
00106
00107
00108 if (isReadOnly()) {
00109 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00110 return;
00111 }
00112
00113
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
00128 setValue(v, exceptioncode);
00129 }
00130
00131 NodeImpl *AttrImpl::cloneNode ( bool )
00132 {
00133 return new AttrImpl(0, docPtr(), new AttributeImpl(m_attribute->id(), m_attribute->val()));
00134 }
00135
00136
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
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
00218 AttributeImpl* old = attributes(false)->getAttributeItem(id);
00219
00220
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
00255 ElementImpl *clone = getDocument()->createElement(tagName());
00256 if (!clone) return 0;
00257
00258
00259 if(namedAttrMap)
00260 *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
00261
00262
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
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
00366 attach();
00367
00368 setChanged( false );
00369 setHasChangedChild( false );
00370 newStyle->deref();
00371 return;
00372 }
00373 if( m_render && newStyle ) {
00374
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
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
00402 bool ElementImpl::childAllowed( NodeImpl *newChild )
00403 {
00404 if (!childTypeAllowed(newChild->nodeType()))
00405 return false;
00406
00407
00408
00409
00410
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 * )
00443 {
00444 if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
00445 return;
00446
00447
00448
00449 }
00450
00451 void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl * )
00452 {
00453 if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
00454 return;
00455
00456
00457
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 , _tagName, false );
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
00495 DOMStringImpl* localName = _qualifiedName->copy();
00496 localName->ref();
00497 localName->remove(0,colonpos+1);
00498 m_id = doc->document()->tagId(_namespaceURI, localName, false );
00499 localName->deref();
00500 m_prefix = _qualifiedName->copy();
00501 m_prefix->ref();
00502 m_prefix->truncate(colonpos);
00503 }
00504 else {
00505
00506 m_id = doc->document()->tagId(_namespaceURI, _qualifiedName, false );
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
00524
00525 XMLElementImpl *clone = new XMLElementImpl(docPtr(), getDocument()->tagName(m_id).implementation());
00526 clone->m_id = m_id;
00527
00528
00529 if(namedAttrMap)
00530 *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
00531
00532
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
00576 if (isReadOnly()) {
00577 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00578 return 0;
00579 }
00580
00581
00582 if (arg->getDocument() != element->getDocument()) {
00583 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00584 return 0;
00585 }
00586
00587
00588 if (!arg->isAttributeNode()) {
00589 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00590 return 0;
00591 }
00592 AttrImpl *attr = static_cast<AttrImpl*>(arg);
00593
00594
00595
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;
00604
00605
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
00618
00619 Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, int &exceptioncode )
00620 {
00621
00622
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
00689
00690 element = 0;
00691 clearAttributes();
00692 }
00693
00694 NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other)
00695 {
00696
00697 if (!element) return *this;
00698
00699 clearAttributes();
00700 len = other.len;
00701 attrs = new AttributeImpl* [len];
00702
00703
00704
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
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
00730
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
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
00771
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