File indexing completed on 2024-04-28 15:24:50
0001 /* 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 0005 * (C) 1999 Antti Koivisto (koivisto@kde.org) 0006 * (C) 2001 Peter Kelly (pmk@post.com) 0007 * (C) 2001 Dirk Mueller (mueller@kde.org) 0008 * (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Library General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2 of the License, or (at your option) any later version. 0014 * 0015 * This library is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 * Library General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Library General Public License 0021 * along with this library; see the file COPYING.LIB. If not, write to 0022 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0023 * Boston, MA 02110-1301, USA. 0024 * 0025 */ 0026 #ifndef _DOM_ELEMENTImpl_h_ 0027 #define _DOM_ELEMENTImpl_h_ 0028 0029 #include "dom_nodeimpl.h" 0030 #include "dom/dom_exception.h" 0031 #include "dom/dom_element.h" 0032 #include "xml/dom_stringimpl.h" 0033 #include "misc/shared.h" 0034 #include "wtf/Vector.h" 0035 #include "xml/ClassNames.h" 0036 0037 // WebCore SVG 0038 #include "dom/QualifiedName.h" 0039 // End WebCore SVG 0040 0041 namespace khtml 0042 { 0043 class CSSStyleSelector; 0044 } 0045 0046 namespace DOM 0047 { 0048 0049 class ElementImpl; 0050 class DocumentImpl; 0051 class NamedAttrMapImpl; 0052 class ElementRareDataImpl; 0053 class CSSInlineStyleDeclarationImpl; 0054 0055 // Attr can have Text and EntityReference children 0056 // therefore it has to be a fullblown Node. The plan 0057 // is to dynamically allocate a textchild and store the 0058 // resulting nodevalue in the AttributeImpl upon 0059 // destruction. however, this is not yet implemented. 0060 class AttrImpl : public NodeBaseImpl 0061 { 0062 friend class ElementImpl; 0063 friend class NamedAttrMapImpl; 0064 0065 public: 0066 AttrImpl(ElementImpl *element, DocumentImpl *docPtr, NamespaceName namespaceName, LocalName localName, PrefixName prefix, DOMStringImpl *value); 0067 ~AttrImpl(); 0068 0069 private: 0070 AttrImpl(const AttrImpl &other); 0071 AttrImpl &operator = (const AttrImpl &other); 0072 void createTextChild(); 0073 public: 0074 0075 // DOM methods & attributes for Attr 0076 bool specified() const 0077 { 0078 return true; /* we don't yet support default attributes*/ 0079 } 0080 ElementImpl *ownerElement() const 0081 { 0082 return m_element; 0083 } 0084 void setOwnerElement(ElementImpl *impl) 0085 { 0086 m_element = impl; 0087 } 0088 DOMString name() const; 0089 0090 //DOMString value() const; 0091 void setValue(const DOMString &v, int &exceptioncode); 0092 0093 // DOM methods overridden from parent classes 0094 DOMString nodeName() const override; 0095 unsigned short nodeType() const override; 0096 DOMString prefix() const override; 0097 void setPrefix(const DOMString &refix, int &exceptioncode) override; 0098 DOMString namespaceURI() const override; 0099 DOMString localName() const override; 0100 0101 inline const PrefixName &prefixName() const 0102 { 0103 return m_prefix; 0104 } 0105 0106 DOMString nodeValue() const override; 0107 void setNodeValue(const DOMString &, int &exceptioncode) override; 0108 WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override; 0109 0110 // Other methods (not part of DOM) 0111 bool isAttributeNode() const override 0112 { 0113 return true; 0114 } 0115 bool childAllowed(NodeImpl *newChild) override; 0116 bool childTypeAllowed(unsigned short type) override; 0117 NodeImpl::Id id() const override 0118 { 0119 return makeId(m_namespace.id(), m_localName.id()); 0120 } 0121 void childrenChanged() override; 0122 0123 // non-virtual id, for faster attribute look-ups 0124 inline NodeImpl::Id fastId() const 0125 { 0126 return makeId(m_namespace.id(), m_localName.id()); 0127 } 0128 0129 // This is used for when the value is normalized on setting by 0130 // parseAttribute; it silently updates it w/o issuing any events, etc. 0131 // Doesn't work for ATTR_ID! 0132 void rewriteValue(const DOMString &newValue); 0133 0134 DOMString toString() const override; 0135 0136 void setElement(ElementImpl *element); 0137 DOMStringImpl *val() const 0138 { 0139 return m_value; 0140 } 0141 0142 protected: 0143 ElementImpl *m_element; 0144 LocalName m_localName; 0145 NamespaceName m_namespace; 0146 PrefixName m_prefix; 0147 DOMStringImpl *m_value; 0148 }; 0149 0150 // Mini version of AttrImpl internal to NamedAttrMapImpl. 0151 // Stores either the id (LocalName and NamespaceName) and value of an attribute 0152 // (in the case of m_localName.id() != 0), or a pointer to an AttrImpl (if m_localName.id() == 0) 0153 // The latter case only happens when the Attr node is requested by some DOM 0154 // code or is an XML attribute. 0155 // In most cases the id and value is all we need to store, which is more 0156 // memory efficient. 0157 // FIXME: update comment - no longer create mini version for only html attributes 0158 struct AttributeImpl { 0159 inline NodeImpl::Id id() const 0160 { 0161 return m_localName.id() ? makeId(m_namespace.id(), m_localName.id()) : m_data.attr->fastId(); 0162 } 0163 DOMStringImpl *val() const 0164 { 0165 if (m_localName.id()) { 0166 return m_data.value; 0167 } else { 0168 return m_data.attr->val(); 0169 } 0170 } 0171 DOMString value() const 0172 { 0173 return val(); 0174 } 0175 AttrImpl *attr() const 0176 { 0177 return m_localName.id() ? nullptr : m_data.attr; 0178 } 0179 DOMString namespaceURI() const 0180 { 0181 return m_localName.id() ? m_namespace.toString() : m_data.attr->namespaceURI(); 0182 } 0183 DOMString prefix() const 0184 { 0185 return m_localName.id() ? m_prefix.toString() : m_data.attr->prefix(); 0186 } 0187 DOMString localName() const 0188 { 0189 return m_localName.id() ? m_localName.toString() : m_data.attr->localName(); 0190 } 0191 const PrefixName &prefixName() const 0192 { 0193 return m_localName.id() ? m_prefix : m_data.attr->prefixName(); 0194 } 0195 0196 // for WebCore api compat 0197 QualifiedName name() const 0198 { 0199 return m_localName.id() ? QualifiedName(m_prefix, m_localName, m_namespace) : QualifiedName(id(), PrefixName::fromString(prefix())); 0200 } 0201 0202 void setValue(DOMStringImpl *value, ElementImpl *element); 0203 AttrImpl *createAttr(ElementImpl *element, DocumentImpl *docPtr); 0204 void free(); 0205 0206 // See the description for AttrImpl. 0207 void rewriteValue(const DOMString &newValue); 0208 0209 LocalName m_localName; 0210 NamespaceName m_namespace; 0211 PrefixName m_prefix; 0212 union { 0213 DOMStringImpl *value; 0214 AttrImpl *attr; 0215 } m_data; 0216 }; 0217 0218 struct CombinedStyleDecl { 0219 DOM::CSSInlineStyleDeclarationImpl *inlineDecls; 0220 DOM::CSSStyleDeclarationImpl *nonCSSDecls; 0221 }; 0222 0223 class ElementImpl : public NodeBaseImpl 0224 { 0225 friend class DocumentImpl; 0226 friend class NamedAttrMapImpl; 0227 friend class AttrImpl; 0228 friend class NodeImpl; 0229 friend class khtml::CSSStyleSelector; 0230 public: 0231 ElementImpl(DocumentImpl *doc); 0232 ~ElementImpl(); 0233 0234 // stuff for WebCore DOM & SVG api compatibility 0235 bool hasTagName(const QualifiedName &name) const override 0236 { 0237 return qualifiedName() == name;/*should be matches here*/ 0238 } 0239 QualifiedName qualifiedName() const 0240 { 0241 return QualifiedName(id(), m_prefix); 0242 } 0243 CSSInlineStyleDeclarationImpl *style() 0244 { 0245 return getInlineStyleDecls(); 0246 } 0247 void setAttribute(const QualifiedName &name, const DOMString &value) 0248 { 0249 setAttribute(name.id(), value); /* is it enough for SVG or should the full setAttribute() be called? */ 0250 } 0251 bool hasAttribute(const QualifiedName &name) const 0252 { 0253 return hasAttribute(name.tagName()); 0254 } 0255 DOMString getAttribute(const QualifiedName &name) const 0256 { 0257 int ec; 0258 return const_cast<ElementImpl *>(this)->getAttributeNS(name.namespaceURI(), name.localName(), ec); 0259 } 0260 DOMString getAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptionCode) const 0261 { 0262 return const_cast<ElementImpl *>(this)->getAttributeNS(namespaceURI, localName, exceptionCode); 0263 } 0264 // FIXME: get rid of const_cast hacks (the const qualifiers of getAttribute should be reviewed 0265 // as for external API it should look like const,hower we can replace AttributeImpl (small version) 0266 // with normal AttrImpl (NodeImpl) 0267 // END OF FIXME 0268 // enf of WC api compatibility stuff 0269 0270 //Higher-level DOM stuff 0271 bool hasAttributes() const override; 0272 bool hasAttribute(const DOMString &name) const; 0273 bool hasAttributeNS(const DOMString &namespaceURI, const DOMString &localName) const; 0274 DOMString getAttribute(const DOMString &name); 0275 void setAttribute(const DOMString &name, const DOMString &value, int &exceptioncode); 0276 void removeAttribute(const DOMString &name, int &exceptioncode); 0277 void removeAttribute(NodeImpl::Id id, int &exceptioncode); 0278 AttrImpl *getAttributeNode(const DOMString &name); 0279 Attr setAttributeNode(AttrImpl *newAttr, int &exceptioncode); 0280 Attr removeAttributeNode(AttrImpl *oldAttr, int &exceptioncode); 0281 0282 DOMString getAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode); 0283 void removeAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode); 0284 AttrImpl *getAttributeNodeNS(const DOMString &namespaceURI, const DOMString &localName, int &exceptioncode); 0285 Attr setAttributeNodeNS(AttrImpl *newAttr, int &exceptioncode); 0286 0287 // At this level per WAI-ARIA 0288 void blur(); 0289 void focus(); 0290 0291 //Lower-level implementation primitives 0292 inline DOMString getAttribute(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const 0293 { 0294 return DOMString(getAttributeImpl(id, prefix, nsAware)); 0295 } 0296 inline DOMStringImpl *getAttributeImpl(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const; 0297 void setAttribute(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, const DOMString &value, int &exceptioncode); 0298 void setAttributeNS(const DOMString &namespaceURI, const DOMString &localName, const DOMString &value, int &exceptioncode); 0299 0300 inline DOMStringImpl *getAttributeImplById(NodeImpl::Id id) const; 0301 0302 // WebCore API 0303 DOMString getIDAttribute() const 0304 { 0305 return getAttribute(ATTR_ID); 0306 } 0307 // End 0308 0309 bool hasAttribute(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const 0310 { 0311 return getAttributeImpl(id, prefix, nsAware) != nullptr; 0312 } 0313 DOMString prefix() const override 0314 { 0315 return m_prefix.toString(); 0316 } 0317 void setPrefix(const DOMString &_prefix, int &exceptioncode) override; 0318 DOMString namespaceURI() const override; 0319 inline const PrefixName &prefixName() const 0320 { 0321 return m_prefix; 0322 } 0323 0324 short tabIndex() const override; 0325 void setTabIndex(short _tabIndex); 0326 void setNoTabIndex(); 0327 bool hasTabIndex() const; 0328 0329 // DOM methods overridden from parent classes 0330 virtual DOMString tagName() const; 0331 DOMString localName() const override; 0332 0333 // Internal version of tagName for elements that doesn't 0334 // do case normalization 0335 DOMString nonCaseFoldedTagName() const; 0336 0337 unsigned short nodeType() const override; 0338 WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override; 0339 DOMString nodeName() const override; 0340 NodeImpl::Id id() const override = 0; 0341 bool isElementNode() const override 0342 { 0343 return true; 0344 } 0345 void insertedIntoDocument() override; 0346 void removedFromDocument() override; 0347 0348 // ElementTraversal API 0349 ElementImpl *firstElementChild() const; 0350 ElementImpl *lastElementChild() const; 0351 ElementImpl *previousElementSibling() const; 0352 ElementImpl *nextElementSibling() const; 0353 unsigned childElementCount() const; 0354 0355 // convenience methods which ignore exceptions 0356 void setAttribute(NodeImpl::Id id, const DOMString &value); 0357 void setBooleanAttribute(NodeImpl::Id id, bool b); 0358 0359 NamedAttrMapImpl *attributes(bool readonly = false) const 0360 { 0361 if (m_needsStyleAttributeUpdate) { 0362 synchronizeStyleAttribute(); 0363 } 0364 if (!readonly && !namedAttrMap) { 0365 createAttributeMap(); 0366 } 0367 return namedAttrMap; 0368 } 0369 0370 //This is always called, whenever an attribute changed 0371 virtual void parseAttribute(AttributeImpl *) {} 0372 void parseNullAttribute(NodeImpl::Id id, PrefixName prefix) 0373 { 0374 AttributeImpl aimpl; 0375 aimpl.m_localName = LocalName::fromId(localNamePart(id)); 0376 aimpl.m_namespace = NamespaceName::fromId(namespacePart(id)); 0377 aimpl.m_prefix = prefix; 0378 aimpl.m_data.value = nullptr; 0379 parseAttribute(&aimpl); 0380 } 0381 0382 void parseAttribute(AttrImpl *fullAttr) 0383 { 0384 AttributeImpl aimpl; 0385 aimpl.m_localName = emptyLocalName; 0386 aimpl.m_data.attr = fullAttr; 0387 parseAttribute(&aimpl); 0388 } 0389 0390 inline const ClassNames &classNames() const; 0391 0392 // not part of the DOM 0393 void setAttributeMap(NamedAttrMapImpl *list); 0394 0395 // State of the element. 0396 QString state() override 0397 { 0398 return QString(); 0399 } 0400 0401 virtual void copyNonAttributeProperties(const ElementImpl * /*source*/) {} 0402 0403 void attach() override; 0404 void close() override; 0405 void detach() override; 0406 void structureChanged() override; 0407 void backwardsStructureChanged() override; 0408 virtual void attributeChanged(NodeImpl::Id attrId); 0409 // for WebCore API compatibility 0410 virtual void attributeChanged(AttributeImpl *attribute, bool /*preserveDecls*/) 0411 { 0412 attributeChanged(attribute->id()); 0413 } 0414 0415 void defaultEventHandler(EventImpl *evt) override; 0416 0417 khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent) override; 0418 khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *) override; 0419 void recalcStyle(StyleChange = NoChange) override; 0420 khtml::RenderStyle *computedStyle() override; 0421 0422 virtual void mouseEventHandler(MouseEvent * /*ev*/, bool /*inside*/) {} 0423 0424 bool childAllowed(NodeImpl *newChild) override; 0425 bool childTypeAllowed(unsigned short type) override; 0426 DOM::CSSInlineStyleDeclarationImpl *inlineStyleDecls() const 0427 { 0428 return m_hasCombinedStyle ? m_style.combinedDecls->inlineDecls : m_style.inlineDecls; 0429 } 0430 DOM::CSSStyleDeclarationImpl *nonCSSStyleDecls() const 0431 { 0432 return m_hasCombinedStyle ? m_style.combinedDecls->nonCSSDecls : nullptr; 0433 } 0434 DOM::CSSInlineStyleDeclarationImpl *getInlineStyleDecls(); 0435 0436 void dispatchAttrRemovalEvent(NodeImpl::Id id, DOMStringImpl *value); 0437 void dispatchAttrAdditionEvent(NodeImpl::Id id, DOMStringImpl *value); 0438 0439 DOMString toString() const override; 0440 DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const override; 0441 0442 bool isFocusableImpl(FocusType ft) const override; 0443 bool isContentEditable() const override; 0444 void setContentEditable(bool enabled); 0445 0446 void scrollIntoView(bool alignToTop); 0447 0448 /** Returns the opening tag and properties. 0449 * Examples: '<b', '<img alt="hello" src="image.png" 0450 * 0451 * For security reasons, passwords are stripped out of all src= and 0452 * href= tags if expandurls is turned on. 0453 * 0454 * @param expandurls If this is set then in the above example, it would give 0455 * src="http://website.com/image.png". Note that the password 0456 * is stripped out of the url. 0457 * 0458 * DOM::RangeImpl uses this which is why it is public. 0459 */ 0460 DOMString openTagStartToString(bool expandurls = false) const; 0461 0462 void updateId(DOMStringImpl *oldId, DOMStringImpl *newId); 0463 //Called when mapping from id to this node in document should be removed 0464 virtual void removeId(const DOMString &id); 0465 //Called when mapping from id to this node in document should be added 0466 virtual void addId(const DOMString &id); 0467 0468 // Synchronize style attribute after it was changed via CSSOM 0469 void synchronizeStyleAttribute() const; 0470 0471 protected: 0472 void createAttributeMap() const; 0473 void createInlineDecl(); // for inline styles 0474 void createNonCSSDecl(); // for presentational styles 0475 void finishCloneNode(ElementImpl *clone, bool deep); 0476 0477 private: 0478 // There is some information such as computed style for display:none 0479 // elements that is needed only for a few elements. We store it 0480 // in one of these. 0481 ElementRareDataImpl *rareData(); 0482 const ElementRareDataImpl *rareData() const; 0483 ElementRareDataImpl *createRareData(); 0484 0485 protected: // member variables 0486 mutable NamedAttrMapImpl *namedAttrMap; 0487 0488 union { 0489 DOM::CSSInlineStyleDeclarationImpl *inlineDecls; 0490 CombinedStyleDecl *combinedDecls; 0491 } m_style; 0492 PrefixName m_prefix; 0493 }; 0494 0495 class XMLElementImpl : public ElementImpl 0496 { 0497 0498 public: 0499 XMLElementImpl(DocumentImpl *doc, NamespaceName namespacename, LocalName localName, PrefixName prefix); 0500 ~XMLElementImpl(); 0501 0502 void parseAttribute(AttributeImpl *attr) override; 0503 0504 WTF::PassRefPtr<NodeImpl> cloneNode(bool deep) override; 0505 0506 // Other methods (not part of DOM) 0507 bool isXMLElementNode() const override 0508 { 0509 return true; 0510 } 0511 Id id() const override 0512 { 0513 return makeId(m_namespace.id(), m_localName.id()); 0514 } 0515 0516 protected: 0517 LocalName m_localName; 0518 NamespaceName m_namespace; 0519 }; 0520 0521 // the map of attributes of an element 0522 class NamedAttrMapImpl : public NamedNodeMapImpl 0523 { 0524 friend class ElementImpl; 0525 public: 0526 NamedAttrMapImpl(ElementImpl *element); 0527 virtual ~NamedAttrMapImpl(); 0528 0529 // DOM methods & attributes for NamedNodeMap 0530 NodeImpl *getNamedItem(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) override; 0531 Node removeNamedItem(NodeImpl::Id id, const PrefixName &prefix, bool nsAware, int &exceptioncode) override; 0532 Node setNamedItem(NodeImpl *arg, const PrefixName &prefix, bool nsAware, int &exceptioncode) override; 0533 0534 // for WebCore api compat 0535 virtual NodeImpl *getNamedItem(const QualifiedName &name) 0536 { 0537 return getNamedItem(name.id(), name.prefixId(), true); 0538 } 0539 0540 NodeImpl *item(unsigned index) override; 0541 unsigned length() const override 0542 { 0543 return m_attrs.size(); 0544 } 0545 0546 // Other methods (not part of DOM) 0547 bool isReadOnly() override 0548 { 0549 return false; 0550 } 0551 bool htmlCompat() override 0552 { 0553 return m_element ? m_element->m_htmlCompat : false; 0554 } 0555 0556 AttributeImpl &attributeAt(unsigned index) 0557 { 0558 return m_attrs[index]; 0559 } 0560 const AttributeImpl &attributeAt(unsigned index) const 0561 { 0562 return m_attrs[index]; 0563 } 0564 AttrImpl *attrAt(unsigned index) const 0565 { 0566 return m_attrs[index].attr(); 0567 } 0568 // ### replace idAt and getValueAt with attrAt 0569 NodeImpl::Id idAt(unsigned index) const; 0570 DOMStringImpl *valueAt(unsigned index) const; 0571 DOMStringImpl *getValue(NodeImpl::Id id, const PrefixName &prefix = emptyPrefixName, bool nsAware = false) const; 0572 void setValue(NodeImpl::Id id, DOMStringImpl *value, const PrefixName &prefix = emptyPrefixName, bool nsAware = false); 0573 Attr removeAttr(AttrImpl *attr); 0574 void copyAttributes(NamedAttrMapImpl *other); 0575 void setElement(ElementImpl *element); 0576 void detachFromElement(); 0577 0578 int find(NodeImpl::Id id, const PrefixName &prefix, bool nsAware) const; 0579 inline DOMStringImpl *fastFind(NodeImpl::Id id) const; 0580 0581 inline void clearClass() 0582 { 0583 m_classNames.clear(); 0584 } 0585 void setClass(const DOMString &string); 0586 inline const ClassNames &classNames() const 0587 { 0588 return m_classNames; 0589 } 0590 0591 // Rewrites value if attribute already exists or adds a new attribute otherwise 0592 // @important: any changes won't be propagated to parent Element 0593 void setValueWithoutElementUpdate(NodeImpl::Id id, DOMStringImpl *value); 0594 0595 protected: 0596 ElementImpl *m_element; 0597 WTF::Vector<AttributeImpl> m_attrs; 0598 ClassNames m_classNames; 0599 }; 0600 0601 // ------------ inline DOM helper functions --------------- 0602 0603 inline bool checkQualifiedName(const DOMString &qualifiedName, const DOMString &namespaceURI, int *colonPos, 0604 bool nameCanBeNull, bool nameCanBeEmpty, int *pExceptioncode) 0605 { 0606 0607 // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied 0608 if (!nameCanBeNull && qualifiedName.isNull()) { 0609 if (pExceptioncode) { 0610 *pExceptioncode = DOMException::NAMESPACE_ERR; 0611 } 0612 return false; 0613 } 0614 0615 // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character. 0616 if (!qualifiedName.isNull() && !Element::khtmlValidQualifiedName(qualifiedName) 0617 && (!qualifiedName.isEmpty() || !nameCanBeEmpty)) { 0618 if (pExceptioncode) { 0619 *pExceptioncode = DOMException::INVALID_CHARACTER_ERR; 0620 } 0621 return false; 0622 } 0623 0624 // NAMESPACE_ERR: 0625 // - Raised if the qualifiedName is malformed, 0626 // - if the qualifiedName has a prefix and the namespaceURI is null, or 0627 // - if the qualifiedName is null and the namespaceURI is different from null 0628 // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different 0629 // from "http://www.w3.org/XML/1998/namespace" [Namespaces]. 0630 int colonpos = -1; 0631 uint i; 0632 DOMStringImpl *qname = qualifiedName.implementation(); 0633 for (i = 0; i < (qname ? qname->l : 0); i++) { 0634 if ((*qname)[i] == QLatin1Char(':')) { 0635 colonpos = i; 0636 break; 0637 } 0638 } 0639 0640 bool hasXMLPrefix = colonpos == 3 && (*qname)[0] == QLatin1Char('x') && 0641 (*qname)[1] == QLatin1Char('m') && (*qname)[2] == QLatin1Char('l'); 0642 bool hasXMLNSPrefix = colonpos == 5 && (*qname)[0] == QLatin1Char('x') && 0643 (*qname)[1] == QLatin1Char('m') && (*qname)[2] == QLatin1Char('l') && 0644 (*qname)[3] == QLatin1Char('n') && (*qname)[4] == QLatin1Char('s'); 0645 0646 if ((!qualifiedName.isNull() && Element::khtmlMalformedQualifiedName(qualifiedName)) || 0647 (colonpos >= 0 && namespaceURI.isNull()) || 0648 colonpos == 0 || // prefix has to consist of at least a letter 0649 (qualifiedName.isNull() && !namespaceURI.isNull()) || 0650 (hasXMLPrefix && namespaceURI != XML_NAMESPACE) || 0651 (hasXMLNSPrefix && namespaceURI != XMLNS_NAMESPACE) || 0652 (namespaceURI == XMLNS_NAMESPACE && !hasXMLNSPrefix && qualifiedName != "xmlns")) { 0653 if (pExceptioncode) { 0654 *pExceptioncode = DOMException::NAMESPACE_ERR; 0655 } 0656 return false; 0657 } 0658 if (colonPos) { 0659 *colonPos = colonpos; 0660 } 0661 return true; 0662 } 0663 0664 inline void splitPrefixLocalName(DOMStringImpl *qualifiedName, DOMString &prefix, DOMString &localName, int colonPos = -2) 0665 { 0666 if (colonPos == -2) 0667 for (uint i = 0; i < qualifiedName->l; ++i) 0668 if (qualifiedName->s[i] == QLatin1Char(':')) { 0669 colonPos = i; 0670 break; 0671 } 0672 if (colonPos >= 0) { 0673 prefix = qualifiedName->copy(); 0674 localName = prefix.split(colonPos + 1); 0675 prefix.implementation()->truncate(colonPos); 0676 } else { 0677 localName = qualifiedName; 0678 } 0679 } 0680 0681 inline void splitPrefixLocalName(const DOMString &qualifiedName, PrefixName &prefix, LocalName &localName, bool htmlCompat = false, int colonPos = -2) 0682 { 0683 DOMString localname, prefixname; 0684 splitPrefixLocalName(qualifiedName.implementation(), prefixname, localname, colonPos); 0685 if (htmlCompat) { 0686 prefix = PrefixName::fromString(prefixname, khtml::IDS_NormalizeLower); 0687 localName = LocalName::fromString(localname, khtml::IDS_NormalizeLower); 0688 } else { 0689 prefix = PrefixName::fromString(prefixname); 0690 localName = LocalName::fromString(localname); 0691 } 0692 } 0693 0694 // methods that could be very hot and therefore need to be inlined 0695 inline DOMStringImpl *ElementImpl::getAttributeImpl(NodeImpl::Id id, const PrefixName &prefix, bool nsAware) const 0696 { 0697 if (m_needsStyleAttributeUpdate && (id == ATTR_STYLE)) { 0698 synchronizeStyleAttribute(); 0699 } 0700 return namedAttrMap ? namedAttrMap->getValue(id, prefix, nsAware) : nullptr; 0701 } 0702 0703 inline const ClassNames &ElementImpl::classNames() const 0704 { 0705 // hasClass() should be called on element first as in CSSStyleSelector::checkSimpleSelector 0706 return namedAttrMap->classNames(); 0707 } 0708 0709 inline DOMStringImpl *ElementImpl::getAttributeImplById(NodeImpl::Id id) const 0710 { 0711 return namedAttrMap ? namedAttrMap->fastFind(id) : nullptr; 0712 } 0713 0714 inline DOMStringImpl *NamedAttrMapImpl::fastFind(NodeImpl::Id id) const 0715 { 0716 unsigned mask = anyQName; 0717 if (namespacePart(id) == anyNamespace) { 0718 mask = anyLocalName; 0719 id = localNamePart(id); 0720 } 0721 unsigned len = m_attrs.size(); 0722 for (unsigned i = 0; i < len; ++i) 0723 if (id == (m_attrs[i].id() & mask)) { 0724 return m_attrs[i].val(); 0725 } 0726 return nullptr; 0727 } 0728 0729 } //namespace 0730 0731 #endif