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 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;
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
00112
00113
00114
00115
00116 if (isReadOnly()) {
00117 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00118 return;
00119 }
00120
00121
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
00136 setValue(v, exceptioncode);
00137 }
00138
00139 NodeImpl *AttrImpl::cloneNode ( bool )
00140 {
00141 return new AttrImpl(0, docPtr(), new AttributeImpl(m_attribute->id(), m_attribute->val()));
00142 }
00143
00144
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
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
00226 AttributeImpl* old = attributes(false)->getAttributeItem(id);
00227
00228
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
00266 clone->m_prefix = m_prefix;
00267 if ( clone->m_prefix )
00268 clone->m_prefix->ref();
00269
00270
00271 if(namedAttrMap)
00272 *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
00273
00274
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
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
00378 attach();
00379
00380 setChanged( false );
00381 setHasChangedChild( false );
00382 newStyle->deref();
00383 return;
00384 }
00385 if( m_render && newStyle ) {
00386
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
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
00414 bool ElementImpl::childAllowed( NodeImpl *newChild )
00415 {
00416 if (!childTypeAllowed(newChild->nodeType()))
00417 return false;
00418
00419
00420
00421
00422
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 * )
00455 {
00456 if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
00457 return;
00458
00459
00460
00461 }
00462
00463 void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl * )
00464 {
00465 if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
00466 return;
00467
00468
00469
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 , _tagName,
00493 false , 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
00513 DOMStringImpl* localName = _qualifiedName->copy();
00514 localName->ref();
00515 localName->remove(0,colonpos+1);
00516 m_id = doc->document()->tagId(_namespaceURI, localName, false , 0);
00517 localName->deref();
00518 m_prefix = _qualifiedName->copy();
00519 m_prefix->ref();
00520 m_prefix->truncate(colonpos);
00521 }
00522 else {
00523
00524 m_id = doc->document()->tagId(_namespaceURI, _qualifiedName, false , 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
00543 clone->m_prefix = m_prefix;
00544 if ( clone->m_prefix )
00545 clone->m_prefix->ref();
00546
00547
00548 if(namedAttrMap)
00549 *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
00550
00551
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
00595 if (isReadOnly()) {
00596 exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
00597 return 0;
00598 }
00599
00600
00601 if (arg->getDocument() != m_element->getDocument()) {
00602 exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
00603 return 0;
00604 }
00605
00606
00607 if (!arg->isAttributeNode()) {
00608 exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
00609 return 0;
00610 }
00611 AttrImpl *attr = static_cast<AttrImpl*>(arg);
00612
00613
00614
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;
00623
00624
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
00637
00638 Node NamedAttrMapImpl::removeNamedItem ( NodeImpl::Id id, int &exceptioncode )
00639 {
00640
00641
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
00709
00710 m_element = 0;
00711 clearAttributes();
00712 }
00713
00714 NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other)
00715 {
00716
00717 if (!m_element) return *this;
00718
00719 clearAttributes();
00720 m_len = other.m_len;
00721 m_attrs = new AttributeImpl* [m_len];
00722
00723
00724
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
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
00750
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
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
00791
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