92ade9007ecd7b0e15592acd2fa17e5350180d0e
[WebKit-https.git] / WebCore / dom / Node.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Trolltech ASA
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25 #include "Node.h"
26
27 #include "CString.h"
28 #include "ChildNodeList.h"
29 #include "DOMImplementation.h"
30 #include "Document.h"
31 #include "Element.h"
32 #include "ExceptionCode.h"
33 #include "Frame.h"
34 #include "HTMLNames.h"
35 #include "KURL.h"
36 #include "Logging.h"
37 #include "NamedAttrMap.h"
38 #include "RenderObject.h"
39 #include "Text.h"
40 #include "TextStream.h"
41 #include "XMLNames.h"
42 #include "htmlediting.h"
43 #include "kjs_binding.h"
44
45 namespace WebCore {
46
47 using namespace HTMLNames;
48
49 typedef HashSet<NodeList*> NodeListSet;
50 struct NodeListsNodeData {
51     NodeListSet m_registeredLists;
52     NodeList::Caches m_childNodeListCaches;
53 };
54
55 // NodeList that limits to a particular tag.
56 class TagNodeList : public NodeList {
57 public:
58     TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
59
60     virtual unsigned length() const;
61     virtual Node* item(unsigned index) const;
62
63 private:
64     virtual bool nodeMatches(Node*) const;
65
66     AtomicString m_namespaceURI;
67     AtomicString m_localName;
68 };
69
70 inline TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
71     : NodeList(rootNode), m_namespaceURI(namespaceURI), m_localName(localName)
72 {
73     ASSERT(m_namespaceURI.isNull() || !m_namespaceURI.isEmpty());
74 }
75
76 unsigned TagNodeList::length() const
77 {
78     return recursiveLength();
79 }
80
81 Node* TagNodeList::item(unsigned index) const
82 {
83     return recursiveItem(index);
84 }
85
86 bool TagNodeList::nodeMatches(Node* testNode) const
87 {
88     if (!testNode->isElementNode())
89         return false;
90
91     if (m_namespaceURI != starAtom && m_namespaceURI != testNode->namespaceURI())
92         return false;
93
94     return m_localName == starAtom || m_localName == testNode->localName();
95 }
96
97
98 bool Node::isSupported(const String& feature, const String& version)
99 {
100     return DOMImplementation::instance()->hasFeature(feature, version);
101 }
102
103 #ifndef NDEBUG
104 WTFLogChannel LogWebCoreNodeLeaks =  { 0x00000000, "", WTFLogChannelOn };
105
106 struct NodeCounter {
107     static unsigned count; 
108
109     ~NodeCounter() 
110     { 
111         if (count) 
112             LOG(WebCoreNodeLeaks, "LEAK: %u Node\n", count); 
113     }
114 };
115 unsigned NodeCounter::count = 0;
116 static NodeCounter nodeCounter;
117
118 static bool shouldIgnoreLeaks = false;
119 static HashSet<Node*> ignoreSet;
120 #endif
121
122 void Node::startIgnoringLeaks()
123 {
124 #ifndef NDEBUG
125     shouldIgnoreLeaks = true;
126 #endif
127 }
128
129 void Node::stopIgnoringLeaks()
130 {
131 #ifndef NDEBUG
132     shouldIgnoreLeaks = false;
133 #endif
134 }
135
136 Node::Node(Document *doc)
137     : m_document(doc),
138       m_previous(0),
139       m_next(0),
140       m_renderer(0),
141       m_nodeLists(0),
142       m_tabIndex(0),
143       m_hasId(false),
144       m_hasClass(false),
145       m_attached(false),
146       m_styleChange(NoStyleChange),
147       m_hasChangedChild(false),
148       m_inDocument(false),
149       m_isLink(false),
150       m_attrWasSpecifiedOrElementHasRareData(false),
151       m_focused(false),
152       m_active(false),
153       m_hovered(false),
154       m_inActiveChain(false),
155       m_inDetach(false),
156       m_inSubtreeMark(false)
157 {
158 #ifndef NDEBUG
159     if (shouldIgnoreLeaks)
160         ignoreSet.add(this);
161     else
162         ++NodeCounter::count;
163 #endif
164 }
165
166 void Node::setDocument(Document* doc)
167 {
168     if (inDocument() || m_document == doc)
169         return;
170
171     willMoveToNewOwnerDocument();
172
173     {
174         KJS::JSLock lock;
175         KJS::ScriptInterpreter::updateDOMNodeDocument(this, m_document.get(), doc);
176     }    
177     m_document = doc;
178
179     didMoveToNewOwnerDocument();
180 }
181
182 Node::~Node()
183 {
184 #ifndef NDEBUG
185     HashSet<Node*>::iterator it = ignoreSet.find(this);
186     if (it != ignoreSet.end())
187         ignoreSet.remove(it);
188     else
189         --NodeCounter::count;
190 #endif
191     if (renderer())
192         detach();
193     delete m_nodeLists;
194     if (m_previous)
195         m_previous->setNextSibling(0);
196     if (m_next)
197         m_next->setPreviousSibling(0);
198 }
199
200 String Node::nodeValue() const
201 {
202   return String();
203 }
204
205 void Node::setNodeValue(const String& /*nodeValue*/, ExceptionCode& ec)
206 {
207     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
208     if (isReadOnlyNode()) {
209         ec = NO_MODIFICATION_ALLOWED_ERR;
210         return;
211     }
212
213     // by default nodeValue is null, so setting it has no effect
214 }
215
216 PassRefPtr<NodeList> Node::childNodes()
217 {
218     if (!m_nodeLists)
219         m_nodeLists = new NodeListsNodeData;
220
221     return new ChildNodeList(this, &m_nodeLists->m_childNodeListCaches);
222 }
223
224 Node* Node::virtualFirstChild() const
225 {
226     return 0;
227 }
228
229 Node* Node::virtualLastChild() const
230 {
231     return 0;
232 }
233
234 Node *Node::lastDescendant() const
235 {
236     Node *n = const_cast<Node *>(this);
237     while (n && n->lastChild())
238         n = n->lastChild();
239     return n;
240 }
241
242 Node* Node::firstDescendant() const
243 {
244     Node *n = const_cast<Node *>(this);
245     while (n && n->firstChild())
246         n = n->firstChild();
247     return n;
248 }
249
250 bool Node::insertBefore(PassRefPtr<Node>, Node*, ExceptionCode& ec)
251 {
252     ec = HIERARCHY_REQUEST_ERR;
253     return false;
254 }
255
256 bool Node::replaceChild(PassRefPtr<Node>, Node*, ExceptionCode& ec)
257 {
258     ec = HIERARCHY_REQUEST_ERR;
259     return false;
260 }
261
262 bool Node::removeChild(Node*, ExceptionCode& ec)
263 {
264     ec = NOT_FOUND_ERR;
265     return false;
266 }
267
268 bool Node::appendChild(PassRefPtr<Node>, ExceptionCode& ec)
269 {
270     ec = HIERARCHY_REQUEST_ERR;
271     return false;
272 }
273
274 void Node::remove(ExceptionCode& ec)
275 {
276     ref();
277     if (Node *p = parentNode())
278         p->removeChild(this, ec);
279     else
280         ec = HIERARCHY_REQUEST_ERR;
281     deref();
282 }
283
284 bool Node::hasChildNodes(  ) const
285 {
286   return false;
287 }
288
289 void Node::normalize ()
290 {
291     ExceptionCode ec = 0;
292     Node *child = firstChild();
293
294     if (isElementNode()) {
295         // Normalize any attribute children we might have 
296         Element *element = static_cast<Element *>(this);
297         NamedAttrMap *attrMap = element->attributes();
298         
299         if (attrMap) {
300             unsigned numAttrs = attrMap->length();
301             
302             for (unsigned i = 0; i < numAttrs; i++) {
303                 Attribute *attribute = attrMap->attributeItem(i);
304                 Attr *attr = attribute->attr();
305                 
306                 if (attr)
307                     attr->normalize();
308             }
309         }
310     }
311     
312     // Recursively go through the subtree beneath us, normalizing all nodes. In the case
313     // where there are two adjacent text nodes, they are merged together
314     while (child) {
315         Node *nextChild = child->nextSibling();
316
317         if (nextChild && child->nodeType() == TEXT_NODE && nextChild->nodeType() == TEXT_NODE) {
318             // Current child and the next one are both text nodes... merge them
319             Text *currentText = static_cast<Text*>(child);
320             Text *nextText = static_cast<Text*>(nextChild);
321
322             currentText->appendData(nextText->data(),ec);
323             if (ec)
324                 return;
325
326             nextChild->remove(ec);
327             if (ec)
328                 return;
329         }
330         else {
331             child->normalize();
332             child = nextChild;
333         }
334     }
335     
336     // Check if we have a single empty text node left and remove it if so
337     child = firstChild();
338     if (child && !child->nextSibling() && child->isTextNode()) {
339         Text *text = static_cast<Text*>(child);
340         if (text->data().isEmpty())
341             child->remove(ec);
342     }
343 }
344
345 const AtomicString& Node::prefix() const
346 {
347     // For nodes other than elements and attributes, the prefix is always null
348     return nullAtom;
349 }
350
351 void Node::setPrefix(const AtomicString& /*prefix*/, ExceptionCode& ec)
352 {
353     // The spec says that for nodes other than elements and attributes, prefix is always null.
354     // It does not say what to do when the user tries to set the prefix on another type of
355     // node, however Mozilla throws a NAMESPACE_ERR exception.
356     ec = NAMESPACE_ERR;
357 }
358
359 const AtomicString& Node::localName() const
360 {
361     return emptyAtom;
362 }
363
364 const AtomicString& Node::namespaceURI() const
365 {
366     return nullAtom;
367 }
368
369 ContainerNode* Node::addChild(PassRefPtr<Node>)
370 {
371     return 0;
372 }
373
374 bool Node::isContentEditable() const
375 {
376     return parent() && parent()->isContentEditable();
377 }
378
379 bool Node::isContentRichlyEditable() const
380 {
381     return parent() && parent()->isContentRichlyEditable();
382 }
383
384 IntRect Node::getRect() const
385 {
386     int _x, _y;
387     if (renderer() && renderer()->absolutePosition(_x, _y))
388         return IntRect( _x, _y, renderer()->width(), renderer()->height() + renderer()->borderTopExtra() + renderer()->borderBottomExtra());
389
390     return IntRect();
391 }
392
393 void Node::setChanged(StyleChangeType changeType)
394 {
395     if ((changeType != NoStyleChange) && !attached()) // changed compared to what?
396         return;
397
398     if (!(changeType == InlineStyleChange && m_styleChange == FullStyleChange))
399         m_styleChange = changeType;
400
401     if (m_styleChange != NoStyleChange) {
402         for (Node* p = parentNode(); p; p = p->parentNode())
403             p->setHasChangedChild(true);
404         document()->setDocumentChanged(true);
405     }
406 }
407
408 bool Node::isFocusable() const
409 {
410     return false;
411 }
412
413 bool Node::isKeyboardFocusable(KeyboardEvent*) const
414 {
415     return isFocusable();
416 }
417
418 bool Node::isMouseFocusable() const
419 {
420     return isFocusable();
421 }
422
423 unsigned Node::nodeIndex() const
424 {
425     Node *_tempNode = previousSibling();
426     unsigned count=0;
427     for( count=0; _tempNode; count++ )
428         _tempNode = _tempNode->previousSibling();
429     return count;
430 }
431
432 void Node::registerNodeList(NodeList* list)
433 {
434     if (!m_nodeLists)
435         m_nodeLists = new NodeListsNodeData;
436     m_nodeLists->m_registeredLists.add(list);
437 }
438
439 void Node::unregisterNodeList(NodeList* list)
440 {
441     if (!m_nodeLists)
442         return;
443     m_nodeLists->m_registeredLists.remove(list);
444 }
445
446 void Node::notifyLocalNodeListsAttributeChanged()
447 {
448     if (!m_nodeLists)
449         return;
450
451     NodeListSet::iterator end = m_nodeLists->m_registeredLists.end();
452     for (NodeListSet::iterator i = m_nodeLists->m_registeredLists.begin(); i != end; ++i)
453         (*i)->rootNodeAttributeChanged();
454 }
455
456 void Node::notifyNodeListsAttributeChanged()
457 {
458     for (Node *n = this; n; n = n->parentNode())
459         n->notifyLocalNodeListsAttributeChanged();
460 }
461
462 void Node::notifyLocalNodeListsChildrenChanged()
463 {
464     if (!m_nodeLists)
465         return;
466
467     m_nodeLists->m_childNodeListCaches.reset();
468
469     NodeListSet::iterator end = m_nodeLists->m_registeredLists.end();
470     for (NodeListSet::iterator i = m_nodeLists->m_registeredLists.begin(); i != end; ++i)
471         (*i)->rootNodeChildrenChanged();
472 }
473
474 void Node::notifyNodeListsChildrenChanged()
475 {
476     for (Node *n = this; n; n = n->parentNode())
477         n->notifyLocalNodeListsChildrenChanged();
478 }
479
480 unsigned Node::childNodeCount() const
481 {
482     return 0;
483 }
484
485 Node *Node::childNode(unsigned /*index*/) const
486 {
487     return 0;
488 }
489
490 Node *Node::traverseNextNode(const Node *stayWithin) const
491 {
492     if (firstChild()) {
493         ASSERT(!stayWithin || firstChild()->isDescendantOf(stayWithin));
494         return firstChild();
495     }
496     if (this == stayWithin)
497         return 0;
498     if (nextSibling()) {
499         ASSERT(!stayWithin || nextSibling()->isDescendantOf(stayWithin));
500         return nextSibling();
501     }
502     const Node *n = this;
503     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
504         n = n->parentNode();
505     if (n) {
506         ASSERT(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
507         return n->nextSibling();
508     }
509     return 0;
510 }
511
512 Node *Node::traverseNextSibling(const Node *stayWithin) const
513 {
514     if (this == stayWithin)
515         return 0;
516     if (nextSibling()) {
517         ASSERT(!stayWithin || nextSibling()->isDescendantOf(stayWithin));
518         return nextSibling();
519     }
520     const Node *n = this;
521     while (n && !n->nextSibling() && (!stayWithin || n->parentNode() != stayWithin))
522         n = n->parentNode();
523     if (n) {
524         ASSERT(!stayWithin || !n->nextSibling() || n->nextSibling()->isDescendantOf(stayWithin));
525         return n->nextSibling();
526     }
527     return 0;
528 }
529
530 Node *Node::traversePreviousNode(const Node *stayWithin) const
531 {
532     if (this == stayWithin)
533         return 0;
534     if (previousSibling()) {
535         Node *n = previousSibling();
536         while (n->lastChild())
537             n = n->lastChild();
538         return n;
539     }
540     return parentNode();
541 }
542
543 Node *Node::traversePreviousNodePostOrder(const Node *stayWithin) const
544 {
545     if (lastChild()) {
546         ASSERT(!stayWithin || lastChild()->isDescendantOf(stayWithin));
547         return lastChild();
548     }
549     if (this == stayWithin)
550         return 0;
551     if (previousSibling()) {
552         ASSERT(!stayWithin || previousSibling()->isDescendantOf(stayWithin));
553         return previousSibling();
554     }
555     const Node *n = this;
556     while (n && !n->previousSibling() && (!stayWithin || n->parentNode() != stayWithin))
557         n = n->parentNode();
558     if (n) {
559         ASSERT(!stayWithin || !n->previousSibling() || n->previousSibling()->isDescendantOf(stayWithin));
560         return n->previousSibling();
561     }
562     return 0;
563 }
564
565 void Node::checkSetPrefix(const AtomicString &_prefix, ExceptionCode& ec)
566 {
567     // Perform error checking as required by spec for setting Node.prefix. Used by
568     // Element::setPrefix() and Attr::setPrefix()
569
570     // FIXME: Implement support for INVALID_CHARACTER_ERR: Raised if the specified prefix contains an illegal character.
571     
572     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
573     if (isReadOnlyNode()) {
574         ec = NO_MODIFICATION_ALLOWED_ERR;
575         return;
576     }
577
578     // FIXME: Implement NAMESPACE_ERR: - Raised if the specified prefix is malformed
579     // We have to comment this out, since it's used for attributes and tag names, and we've only
580     // switched one over.
581     /*
582     // - if the namespaceURI of this node is null,
583     // - if the specified prefix is "xml" and the namespaceURI of this node is different from
584     //   "http://www.w3.org/XML/1998/namespace",
585     // - if this node is an attribute and the specified prefix is "xmlns" and
586     //   the namespaceURI of this node is different from "http://www.w3.org/2000/xmlns/",
587     // - or if this node is an attribute and the qualifiedName of this node is "xmlns" [Namespaces].
588     if ((namespacePart(id()) == noNamespace && id() > ID_LAST_TAG) ||
589         (_prefix == "xml" && String(document()->namespaceURI(id())) != "http://www.w3.org/XML/1998/namespace")) {
590         ec = NAMESPACE_ERR;
591         return;
592     }*/
593 }
594
595 bool Node::canReplaceChild(Node* newChild, Node* oldChild)
596 {
597     if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) {
598         if (!childTypeAllowed(newChild->nodeType()))
599             return false;
600     }
601     else {
602         for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) {
603             if (!childTypeAllowed(n->nodeType())) 
604                 return false;
605         }
606     }
607     
608     return true;
609 }
610
611 void Node::checkReplaceChild(Node* newChild, Node* oldChild, ExceptionCode& ec)
612 {
613     // Perform error checking as required by spec for adding a new child. Used by
614     // appendChild(), replaceChild() and insertBefore()
615     
616     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
617     if (!newChild) {
618         ec = NOT_FOUND_ERR;
619         return;
620     }
621     
622     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
623     if (isReadOnlyNode()) {
624         ec = NO_MODIFICATION_ALLOWED_ERR;
625         return;
626     }
627     
628     bool shouldAdoptChild = false;
629     
630     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
631     // created this node.
632     // We assume that if newChild is a DocumentFragment, all children are created from the same document
633     // as the fragment itself (otherwise they could not have been added as children)
634     if (newChild->document() != document()) {
635         // but if the child is not in a document yet then loosen the
636         // restriction, so that e.g. creating an element with the Option()
637         // constructor and then adding it to a different document works,
638         // as it does in Mozilla and Mac IE.
639         if (!newChild->inDocument()) {
640             shouldAdoptChild = true;
641         } else {
642             ec = WRONG_DOCUMENT_ERR;
643             return;
644         }
645     }
646     
647     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
648     // newChild node, or if the node to append is one of this node's ancestors.
649     
650     // check for ancestor/same node
651     if (newChild == this || isDescendantOf(newChild)) {
652         ec = HIERARCHY_REQUEST_ERR;
653         return;
654     }
655     
656     if (!canReplaceChild(newChild, oldChild)) {
657         ec = HIERARCHY_REQUEST_ERR;
658         return;
659     }
660        
661     // change the document pointer of newChild and all of its children to be the new document
662     if (shouldAdoptChild)
663         for (Node* node = newChild; node; node = node->traverseNextNode(newChild))
664             node->setDocument(document());
665 }
666
667 void Node::checkAddChild(Node *newChild, ExceptionCode& ec)
668 {
669     // Perform error checking as required by spec for adding a new child. Used by
670     // appendChild(), replaceChild() and insertBefore()
671
672     // Not mentioned in spec: throw NOT_FOUND_ERR if newChild is null
673     if (!newChild) {
674         ec = NOT_FOUND_ERR;
675         return;
676     }
677
678     // NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly
679     if (isReadOnlyNode()) {
680         ec = NO_MODIFICATION_ALLOWED_ERR;
681         return;
682     }
683
684     bool shouldAdoptChild = false;
685
686     // WRONG_DOCUMENT_ERR: Raised if newChild was created from a different document than the one that
687     // created this node.
688     // We assume that if newChild is a DocumentFragment, all children are created from the same document
689     // as the fragment itself (otherwise they could not have been added as children)
690     if (newChild->document() != document()) {
691         // but if the child is not in a document yet then loosen the
692         // restriction, so that e.g. creating an element with the Option()
693         // constructor and then adding it to a different document works,
694         // as it does in Mozilla and Mac IE.
695         if (!newChild->inDocument()) {
696             shouldAdoptChild = true;
697         } else {
698             ec = WRONG_DOCUMENT_ERR;
699             return;
700         }
701     }
702
703     // HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not allow children of the type of the
704     // newChild node, or if the node to append is one of this node's ancestors.
705
706     // check for ancestor/same node
707     if (newChild == this || isDescendantOf(newChild)) {
708         ec = HIERARCHY_REQUEST_ERR;
709         return;
710     }
711     
712     if (newChild->nodeType() != DOCUMENT_FRAGMENT_NODE) {
713         if (!childTypeAllowed(newChild->nodeType())) {
714             ec = HIERARCHY_REQUEST_ERR;
715             return;
716         }
717     }
718     else {
719         for (Node *n = newChild->firstChild(); n; n = n->nextSibling()) {
720             if (!childTypeAllowed(n->nodeType())) {
721                 ec = HIERARCHY_REQUEST_ERR;
722                 return;
723             }
724         }
725     }
726     
727     // change the document pointer of newChild and all of its children to be the new document
728     if (shouldAdoptChild)
729         for (Node* node = newChild; node; node = node->traverseNextNode(newChild))
730             node->setDocument(document());
731 }
732
733 bool Node::isDescendantOf(const Node *other) const
734 {
735     // Return true if other is an ancestor of this, otherwise false
736     if (!other)
737         return false;
738     for (const Node *n = parentNode(); n; n = n->parentNode()) {
739         if (n == other)
740             return true;
741     }
742     return false;
743 }
744
745 bool Node::childAllowed( Node *newChild )
746 {
747     return childTypeAllowed(newChild->nodeType());
748 }
749
750 Node::StyleChange Node::diff( RenderStyle *s1, RenderStyle *s2 ) const
751 {
752     // FIXME: The behavior of this function is just totally wrong.  It doesn't handle
753     // explicit inheritance of non-inherited properties and so you end up not re-resolving
754     // style in cases where you need to.
755     StyleChange ch = NoInherit;
756     EDisplay display1 = s1 ? s1->display() : NONE;
757     bool fl1 = s1 && s1->hasPseudoStyle(RenderStyle::FIRST_LETTER);
758     EDisplay display2 = s2 ? s2->display() : NONE;
759     bool fl2 = s2 && s2->hasPseudoStyle(RenderStyle::FIRST_LETTER);
760         
761     if (display1 != display2 || fl1 != fl2 || (s1 && s2 && !s1->contentDataEquivalent(s2)))
762         ch = Detach;
763     else if (!s1 || !s2)
764         ch = Inherit;
765     else if (*s1 == *s2)
766         ch = NoChange;
767     else if (s1->inheritedNotEqual(s2))
768         ch = Inherit;
769     
770     // If the pseudoStyles have changed, we want any StyleChange that is not NoChange
771     // because setStyle will do the right thing with anything else.
772     if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::BEFORE)) {
773         RenderStyle* ps2 = s2->getPseudoStyle(RenderStyle::BEFORE);
774         if (!ps2)
775             ch = NoInherit;
776         else {
777             RenderStyle* ps1 = s1->getPseudoStyle(RenderStyle::BEFORE);
778             ch = ps1 && *ps1 == *ps2 ? NoChange : NoInherit;
779         }
780     }
781     if (ch == NoChange && s1->hasPseudoStyle(RenderStyle::AFTER)) {
782         RenderStyle* ps2 = s2->getPseudoStyle(RenderStyle::AFTER);
783         if (!ps2)
784             ch = NoInherit;
785         else {
786             RenderStyle* ps1 = s1->getPseudoStyle(RenderStyle::AFTER);
787             ch = ps2 && *ps1 == *ps2 ? NoChange : NoInherit;
788         }
789     }
790     
791     return ch;
792 }
793
794 #ifndef NDEBUG
795 void Node::dump(TextStream* stream, DeprecatedString ind) const
796 {
797     if (m_hasId) { *stream << " hasId"; }
798     if (m_hasClass) { *stream << " hasClass"; }
799     if (m_focused) { *stream << " focused"; }
800     if (m_active) { *stream << " active"; }
801
802     *stream << " tabIndex=" << m_tabIndex;
803     *stream << endl;
804
805     for (Node* child = firstChild(); child; child = child->nextSibling()) {
806         *stream << ind << child->nodeName() << ": ";
807         child->dump(stream, ind + "  ");
808     }
809 }
810 #endif
811
812 void Node::attach()
813 {
814     ASSERT(!attached());
815     ASSERT(!renderer() || (renderer()->style() && renderer()->parent()));
816     document()->incDOMTreeVersion();
817     m_attached = true;
818 }
819
820 void Node::willRemove()
821 {
822     // If the document is in the page cache, then we don't need to clear out the focused node.
823     if (!document()->inPageCache() && m_focused)
824         document()->focusedNodeRemoved(this);
825 }
826
827 void Node::detach()
828 {
829     m_inDetach = true;
830
831     if (renderer())
832         renderer()->destroy();
833     setRenderer(0);
834
835     Document* doc = document();
836     if (m_hovered)
837         doc->hoveredNodeDetached(this);
838     if (m_inActiveChain)
839         doc->activeChainNodeDetached(this);
840     doc->incDOMTreeVersion();
841
842     m_active = false;
843     m_hovered = false;
844     m_inActiveChain = false;
845     m_attached = false;
846     m_inDetach = false;
847 }
848
849 void Node::insertedIntoDocument()
850 {
851     setInDocument(true);
852     insertedIntoTree(false);
853 }
854
855 void Node::removedFromDocument()
856 {
857     setInDocument(false);
858     removedFromTree(false);
859 }
860
861 void Node::childrenChanged()
862 {
863 }
864
865 bool Node::isReadOnlyNode()
866 {
867     // Entity & Entity Reference nodes and their descendants are read-only
868     Node *n = this;
869     while (n) {
870         if (n->nodeType() == ENTITY_NODE || n->nodeType() == ENTITY_REFERENCE_NODE)
871             return true;
872         n = n->parentNode();
873     }
874     return false;
875 }
876
877 Node *Node::previousEditable() const
878 {
879     Node *node = previousLeafNode();
880     while (node) {
881         if (node->isContentEditable())
882             return node;
883         node = node->previousLeafNode();
884     }
885     return 0;
886 }
887
888 // Offset specifies the child node to start at.  If it is past
889 // the last child, it specifies to start at next sibling.
890 Node *Node::nextEditable(int offset) const
891 {
892     ASSERT(offset>=0);
893     Node *node;
894     if (hasChildNodes())
895         node = (offset >= (int)childNodeCount()) ? nextSibling() : childNode(offset)->nextLeafNode();
896     else
897         node = nextLeafNode();
898     while (node) {
899         if (node->isContentEditable())
900             return node;
901         node = node->nextLeafNode();
902     }
903     return 0;
904 }
905
906 Node *Node::nextEditable() const
907 {
908     Node *node = nextLeafNode();
909     while (node) {
910         if (node->isContentEditable())
911             return node;
912         node = node->nextLeafNode();
913     }
914     return 0;
915 }
916
917 RenderObject * Node::previousRenderer()
918 {
919     for (Node *n = previousSibling(); n; n = n->previousSibling()) {
920         if (n->renderer())
921             return n->renderer();
922     }
923     return 0;
924 }
925
926 RenderObject * Node::nextRenderer()
927 {
928     // Avoid an O(n^2) problem with this function by not checking for nextRenderer() when the parent element hasn't even 
929     // been attached yet.
930     if (parent() && !parent()->attached())
931         return 0;
932
933     for (Node *n = nextSibling(); n; n = n->nextSibling()) {
934         if (n->renderer())
935             return n->renderer();
936     }
937     return 0;
938 }
939
940 // FIXME: This code is used by editing.  Seems like it could move over there and not pollute Node.
941 Node *Node::previousNodeConsideringAtomicNodes() const
942 {
943     if (previousSibling()) {
944         Node *n = previousSibling();
945         while (!isAtomicNode(n) && n->lastChild())
946             n = n->lastChild();
947         return n;
948     }
949     else if (parentNode()) {
950         return parentNode();
951     }
952     else {
953         return 0;
954     }
955 }
956
957 Node *Node::nextNodeConsideringAtomicNodes() const
958 {
959     if (!isAtomicNode(this) && firstChild())
960         return firstChild();
961     if (nextSibling())
962         return nextSibling();
963     const Node *n = this;
964     while (n && !n->nextSibling())
965         n = n->parentNode();
966     if (n)
967         return n->nextSibling();
968     return 0;
969 }
970
971 Node *Node::previousLeafNode() const
972 {
973     Node *node = previousNodeConsideringAtomicNodes();
974     while (node) {
975         if (isAtomicNode(node))
976             return node;
977         node = node->previousNodeConsideringAtomicNodes();
978     }
979     return 0;
980 }
981
982 Node *Node::nextLeafNode() const
983 {
984     Node *node = nextNodeConsideringAtomicNodes();
985     while (node) {
986         if (isAtomicNode(node))
987             return node;
988         node = node->nextNodeConsideringAtomicNodes();
989     }
990     return 0;
991 }
992
993 void Node::createRendererIfNeeded()
994 {
995     if (!document()->shouldCreateRenderers())
996         return;
997     
998     ASSERT(!attached());
999     ASSERT(!renderer());
1000     
1001     Node *parent = parentNode();    
1002     ASSERT(parent);
1003     
1004     RenderObject *parentRenderer = parent->renderer();
1005     if (parentRenderer && parentRenderer->canHaveChildren()
1006 #if ENABLE(SVG)
1007         && parent->childShouldCreateRenderer(this)
1008 #endif
1009         ) {
1010         RenderStyle* style = styleForRenderer(parentRenderer);
1011         if (rendererIsNeeded(style)) {
1012             if (RenderObject* r = createRenderer(document()->renderArena(), style)) {
1013                 if (!parentRenderer->isChildAllowed(r, style))
1014                     r->destroy();
1015                 else {
1016                     setRenderer(r);
1017                     renderer()->setStyle(style);
1018                     parentRenderer->addChild(renderer(), nextRenderer());
1019                 }
1020             }
1021         }
1022         style->deref(document()->renderArena());
1023     }
1024 }
1025
1026 RenderStyle *Node::styleForRenderer(RenderObject *parent)
1027 {
1028     RenderStyle *style = parent->style();
1029     style->ref();
1030     return style;
1031 }
1032
1033 bool Node::rendererIsNeeded(RenderStyle *style)
1034 {
1035     return (document()->documentElement() == this) || (style->display() != NONE);
1036 }
1037
1038 RenderObject *Node::createRenderer(RenderArena *arena, RenderStyle *style)
1039 {
1040     ASSERT(false);
1041     return 0;
1042 }
1043
1044 RenderStyle* Node::renderStyle() const
1045
1046     return m_renderer ? m_renderer->style() : 0; 
1047 }
1048
1049 void Node::setRenderStyle(RenderStyle* s)
1050 {
1051     if (m_renderer)
1052         m_renderer->setStyle(s); 
1053 }
1054
1055 RenderStyle* Node::computedStyle()
1056 {
1057     return parent() ? parent()->computedStyle() : 0;
1058 }
1059
1060 int Node::maxOffset() const
1061 {
1062     return 1;
1063 }
1064
1065 // FIXME: Shouldn't these functions be in the editing code?  Code that asks questions about HTML in the core DOM class
1066 // is obviously misplaced.
1067 int Node::caretMinOffset() const
1068 {
1069     return renderer() ? renderer()->caretMinOffset() : 0;
1070 }
1071
1072 int Node::caretMaxOffset() const
1073 {
1074     return renderer() ? renderer()->caretMaxOffset() : 1;
1075 }
1076
1077 unsigned Node::caretMaxRenderedOffset() const
1078 {
1079     return renderer() ? renderer()->caretMaxRenderedOffset() : 1;
1080 }
1081
1082 int Node::previousOffset (int current) const
1083 {
1084     return renderer() ? renderer()->previousOffset(current) : current - 1;
1085 }
1086
1087 int Node::nextOffset (int current) const
1088 {
1089     return renderer() ? renderer()->nextOffset(current) : current + 1;
1090 }
1091
1092 Node* Node::shadowAncestorNode()
1093 {
1094 #if ENABLE(SVG)
1095     // SVG elements living in a shadow tree only occour when <use> created them.
1096     // For these cases we do NOT want to return the shadowParentNode() here
1097     // but the actual shadow tree element - as main difference to the HTML forms
1098     // shadow tree concept. (This function _could_ be made virtual - opinions?)
1099     if (isSVGElement())
1100         return this;
1101 #endif
1102
1103     Node *n = this;    
1104     while (n) {
1105         if (n->isShadowNode())
1106             return n->shadowParentNode();
1107         n = n->parentNode();
1108     } 
1109     return this;
1110 }
1111
1112 bool Node::isBlockFlow() const
1113 {
1114     return renderer() && renderer()->isBlockFlow();
1115 }
1116
1117 bool Node::isBlockFlowOrBlockTable() const
1118 {
1119     return renderer() && (renderer()->isBlockFlow() || renderer()->isTable() && !renderer()->isInline());
1120 }
1121
1122 bool Node::isEditableBlock() const
1123 {
1124     return isContentEditable() && isBlockFlow();
1125 }
1126
1127 Element *Node::enclosingBlockFlowOrTableElement() const
1128 {
1129     Node *n = const_cast<Node *>(this);
1130     if (isBlockFlowOrBlockTable())
1131         return static_cast<Element *>(n);
1132
1133     while (1) {
1134         n = n->parentNode();
1135         if (!n)
1136             break;
1137         if (n->isBlockFlowOrBlockTable() || n->hasTagName(bodyTag))
1138             return static_cast<Element *>(n);
1139     }
1140     return 0;
1141 }
1142
1143 Element *Node::enclosingBlockFlowElement() const
1144 {
1145     Node *n = const_cast<Node *>(this);
1146     if (isBlockFlow())
1147         return static_cast<Element *>(n);
1148
1149     while (1) {
1150         n = n->parentNode();
1151         if (!n)
1152             break;
1153         if (n->isBlockFlow() || n->hasTagName(bodyTag))
1154             return static_cast<Element *>(n);
1155     }
1156     return 0;
1157 }
1158
1159 Element *Node::enclosingInlineElement() const
1160 {
1161     Node *n = const_cast<Node *>(this);
1162     Node *p;
1163
1164     while (1) {
1165         p = n->parentNode();
1166         if (!p || p->isBlockFlow() || p->hasTagName(bodyTag))
1167             return static_cast<Element *>(n);
1168         // Also stop if any previous sibling is a block
1169         for (Node *sibling = n->previousSibling(); sibling; sibling = sibling->previousSibling()) {
1170             if (sibling->isBlockFlow())
1171                 return static_cast<Element *>(n);
1172         }
1173         n = p;
1174     }
1175     ASSERT_NOT_REACHED();
1176     return 0;
1177 }
1178
1179 Element* Node::rootEditableElement() const
1180 {
1181     Element* result = 0;
1182     for (Node* n = const_cast<Node*>(this); n && n->isContentEditable(); n = n->parentNode()) {
1183         if (n->isElementNode())
1184             result = static_cast<Element*>(n);
1185         if (n->hasTagName(bodyTag))
1186             break;
1187     }
1188     return result;
1189 }
1190
1191 bool Node::inSameContainingBlockFlowElement(Node *n)
1192 {
1193     return n ? enclosingBlockFlowElement() == n->enclosingBlockFlowElement() : false;
1194 }
1195
1196 // FIXME: End of obviously misplaced HTML editing functions.  Try to move these out of Node.
1197
1198 PassRefPtr<NodeList> Node::getElementsByTagName(const String& name)
1199 {
1200     return getElementsByTagNameNS("*", name);
1201 }
1202  
1203 PassRefPtr<NodeList> Node::getElementsByTagNameNS(const String& namespaceURI, const String& localName)
1204 {
1205     if (localName.isNull())
1206         return 0;
1207
1208     String name = localName;
1209     if (document()->isHTMLDocument())
1210         name = localName.lower();
1211     return new TagNodeList(this, namespaceURI.isEmpty() ? nullAtom : AtomicString(namespaceURI), name);
1212 }
1213
1214 Document *Node::ownerDocument() const
1215 {
1216     Document *doc = document();
1217     return doc == this ? 0 : doc;
1218 }
1219
1220 bool Node::hasAttributes() const
1221 {
1222     return false;
1223 }
1224
1225 NamedAttrMap *Node::attributes() const
1226 {
1227     return 0;
1228 }
1229
1230 String Node::baseURI() const
1231 {
1232     Node* parent = parentNode();
1233     if (parent)
1234         return parent->baseURI();
1235
1236     return String();
1237 }
1238
1239 bool Node::isEqualNode(Node *other) const
1240 {
1241     if (!other)
1242         return false;
1243     
1244     if (nodeType() != other->nodeType())
1245         return false;
1246     
1247     if (nodeName() != other->nodeName())
1248         return false;
1249     
1250     if (localName() != other->localName())
1251         return false;
1252     
1253     if (namespaceURI() != other->namespaceURI())
1254         return false;
1255     
1256     if (prefix() != other->prefix())
1257         return false;
1258     
1259     if (nodeValue() != other->nodeValue())
1260         return false;
1261     
1262     NamedAttrMap *attrs = attributes();
1263     NamedAttrMap *otherAttrs = other->attributes();
1264     
1265     if (!attrs && otherAttrs)
1266         return false;
1267     
1268     if (attrs && !attrs->mapsEquivalent(otherAttrs))
1269         return false;
1270     
1271     Node *child = firstChild();
1272     Node *otherChild = other->firstChild();
1273     
1274     while (child) {
1275         if (!child->isEqualNode(otherChild))
1276             return false;
1277         
1278         child = child->nextSibling();
1279         otherChild = otherChild->nextSibling();
1280     }
1281     
1282     if (otherChild)
1283         return false;
1284     
1285     // FIXME: For DocumentType nodes we should check equality on
1286     // the entities and notations NamedNodeMaps as well.
1287     
1288     return true;
1289 }
1290
1291 bool Node::isDefaultNamespace(const String &namespaceURI) const
1292 {
1293     // Implemented according to
1294     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#isDefaultNamespaceAlgo
1295     
1296     switch (nodeType()) {
1297         case ELEMENT_NODE: {
1298             const Element *elem = static_cast<const Element *>(this);
1299             
1300             if (elem->prefix().isNull())
1301                 return elem->namespaceURI() == namespaceURI;
1302
1303             if (elem->hasAttributes()) {
1304                 NamedAttrMap *attrs = elem->attributes();
1305                 
1306                 for (unsigned i = 0; i < attrs->length(); i++) {
1307                     Attribute *attr = attrs->attributeItem(i);
1308                     
1309                     if (attr->localName() == "xmlns")
1310                         return attr->value() == namespaceURI;
1311                 }
1312             }
1313
1314             if (Element* ancestor = ancestorElement())
1315                 return ancestor->isDefaultNamespace(namespaceURI);
1316
1317             return false;
1318         }
1319         case DOCUMENT_NODE:
1320             return static_cast <const Document *>(this)->documentElement()->isDefaultNamespace(namespaceURI);
1321         case ENTITY_NODE:
1322         case NOTATION_NODE:
1323         case DOCUMENT_TYPE_NODE:
1324         case DOCUMENT_FRAGMENT_NODE:
1325             return false;
1326         case ATTRIBUTE_NODE: {
1327             const Attr *attr = static_cast<const Attr *>(this);
1328             if (attr->ownerElement())
1329                 return attr->ownerElement()->isDefaultNamespace(namespaceURI);
1330             return false;
1331         }
1332         default:
1333             if (Element* ancestor = ancestorElement())
1334                 return ancestor->isDefaultNamespace(namespaceURI);
1335             return false;
1336     }
1337 }
1338
1339 String Node::lookupPrefix(const String &namespaceURI) const
1340 {
1341     // Implemented according to
1342     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespacePrefixAlgo
1343     
1344     if (namespaceURI.isEmpty())
1345         return String();
1346     
1347     switch (nodeType()) {
1348         case ELEMENT_NODE:
1349             return lookupNamespacePrefix(namespaceURI, static_cast<const Element *>(this));
1350         case DOCUMENT_NODE:
1351             return static_cast<const Document *>(this)->documentElement()->lookupPrefix(namespaceURI);
1352         case ENTITY_NODE:
1353         case NOTATION_NODE:
1354         case DOCUMENT_FRAGMENT_NODE:
1355         case DOCUMENT_TYPE_NODE:
1356             return String();
1357         case ATTRIBUTE_NODE: {
1358             const Attr *attr = static_cast<const Attr *>(this);
1359             if (attr->ownerElement())
1360                 return attr->ownerElement()->lookupPrefix(namespaceURI);
1361             return String();
1362         }
1363         default:
1364             if (Element* ancestor = ancestorElement())
1365                 return ancestor->lookupPrefix(namespaceURI);
1366             return String();
1367     }
1368 }
1369
1370 String Node::lookupNamespaceURI(const String &prefix) const
1371 {
1372     // Implemented according to
1373     // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algorithms.html#lookupNamespaceURIAlgo
1374     
1375     if (!prefix.isNull() && prefix.isEmpty())
1376         return String();
1377     
1378     switch (nodeType()) {
1379         case ELEMENT_NODE: {
1380             const Element *elem = static_cast<const Element *>(this);
1381             
1382             if (!elem->namespaceURI().isNull() && elem->prefix() == prefix)
1383                 return elem->namespaceURI();
1384             
1385             if (elem->hasAttributes()) {
1386                 NamedAttrMap *attrs = elem->attributes();
1387                 
1388                 for (unsigned i = 0; i < attrs->length(); i++) {
1389                     Attribute *attr = attrs->attributeItem(i);
1390                     
1391                     if (attr->prefix() == "xmlns" && attr->localName() == prefix) {
1392                         if (!attr->value().isEmpty())
1393                             return attr->value();
1394                         
1395                         return String();
1396                     } else if (attr->localName() == "xmlns" && prefix.isNull()) {
1397                         if (!attr->value().isEmpty())
1398                             return attr->value();
1399                         
1400                         return String();
1401                     }
1402                 }
1403             }
1404             if (Element* ancestor = ancestorElement())
1405                 return ancestor->lookupNamespaceURI(prefix);
1406             return String();
1407         }
1408         case DOCUMENT_NODE:
1409             return static_cast<const Document *>(this)->documentElement()->lookupNamespaceURI(prefix);
1410         case ENTITY_NODE:
1411         case NOTATION_NODE:
1412         case DOCUMENT_TYPE_NODE:
1413         case DOCUMENT_FRAGMENT_NODE:
1414             return String();
1415         case ATTRIBUTE_NODE: {
1416             const Attr *attr = static_cast<const Attr *>(this);
1417             
1418             if (attr->ownerElement())
1419                 return attr->ownerElement()->lookupNamespaceURI(prefix);
1420             else
1421                 return String();
1422         }
1423         default:
1424             if (Element* ancestor = ancestorElement())
1425                 return ancestor->lookupNamespaceURI(prefix);
1426             return String();
1427     }
1428 }
1429
1430 String Node::lookupNamespacePrefix(const String &_namespaceURI, const Element *originalElement) const
1431 {
1432     if (_namespaceURI.isNull())
1433         return String();
1434             
1435     if (originalElement->lookupNamespaceURI(prefix()) == _namespaceURI)
1436         return prefix();
1437     
1438     if (hasAttributes()) {
1439         NamedAttrMap *attrs = attributes();
1440         
1441         for (unsigned i = 0; i < attrs->length(); i++) {
1442             Attribute *attr = attrs->attributeItem(i);
1443             
1444             if (attr->prefix() == "xmlns" &&
1445                 attr->value() == _namespaceURI &&
1446                 originalElement->lookupNamespaceURI(attr->localName()) == _namespaceURI)
1447                 return attr->localName();
1448         }
1449     }
1450     
1451     if (Element* ancestor = ancestorElement())
1452         return ancestor->lookupNamespacePrefix(_namespaceURI, originalElement);
1453     return String();
1454 }
1455
1456 String Node::textContent(bool convertBRsToNewlines) const
1457 {
1458     switch (nodeType()) {
1459         case TEXT_NODE:
1460         case CDATA_SECTION_NODE:
1461         case COMMENT_NODE:
1462         case PROCESSING_INSTRUCTION_NODE:
1463             return nodeValue();
1464         
1465         case ELEMENT_NODE:
1466             if (hasTagName(brTag) && 
1467                 convertBRsToNewlines)
1468                 return "\n";
1469         case ATTRIBUTE_NODE:
1470         case ENTITY_NODE:
1471         case ENTITY_REFERENCE_NODE:
1472         case DOCUMENT_FRAGMENT_NODE: {
1473             String s = "";
1474         
1475             for (Node *child = firstChild(); child; child = child->nextSibling()) {
1476                 if (child->nodeType() == COMMENT_NODE || child->nodeType() == PROCESSING_INSTRUCTION_NODE)
1477                     continue;
1478             
1479                 s += child->textContent(convertBRsToNewlines);
1480             }
1481         
1482             return s;
1483         }
1484         
1485         case DOCUMENT_NODE:
1486         case DOCUMENT_TYPE_NODE:
1487         case NOTATION_NODE:
1488         default:
1489             return String();            
1490     }
1491 }
1492
1493 void Node::setTextContent(const String &text, ExceptionCode& ec)
1494 {           
1495     switch (nodeType()) {
1496         case TEXT_NODE:
1497         case CDATA_SECTION_NODE:
1498         case COMMENT_NODE:
1499         case PROCESSING_INSTRUCTION_NODE:
1500             setNodeValue(text, ec);
1501             break;
1502         case ELEMENT_NODE:
1503         case ATTRIBUTE_NODE:
1504         case ENTITY_NODE:
1505         case ENTITY_REFERENCE_NODE:
1506         case DOCUMENT_FRAGMENT_NODE: {
1507             ContainerNode *container = static_cast<ContainerNode *>(this);
1508             
1509             container->removeChildren();
1510             
1511             if (!text.isEmpty())
1512                 appendChild(document()->createTextNode(text), ec);
1513             break;
1514         }
1515         case DOCUMENT_NODE:
1516         case DOCUMENT_TYPE_NODE:
1517         case NOTATION_NODE:
1518         default:
1519             // Do nothing
1520             break;
1521     }
1522 }
1523
1524 Element* Node::ancestorElement() const
1525 {
1526     // In theory, there can be EntityReference nodes between elements, but this is currently not supported.
1527     for (Node* n = parentNode(); n; n = n->parentNode()) {
1528         if (n->isElementNode())
1529             return static_cast<Element*>(n);
1530     }
1531     return 0;
1532 }
1533
1534 bool Node::offsetInCharacters() const
1535 {
1536     return false;
1537 }
1538
1539 #ifndef NDEBUG
1540
1541 static void appendAttributeDesc(const Node* node, String& string, const QualifiedName& name, const char* attrDesc)
1542 {
1543     if (node->isElementNode()) {
1544         String attr = static_cast<const Element*>(node)->getAttribute(name);
1545         if (!attr.isEmpty()) {
1546             string += attrDesc;
1547             string += attr;
1548         }
1549     }
1550 }
1551
1552 void Node::showNode(const char* prefix) const
1553 {
1554     if (!prefix)
1555         prefix = "";
1556     if (isTextNode()) {
1557         String value = nodeValue();
1558         value.replace('\\', "\\\\");
1559         value.replace('\n', "\\n");
1560         fprintf(stderr, "%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this, value.utf8().data());
1561     } else {
1562         String attrs = "";
1563         appendAttributeDesc(this, attrs, classAttr, " CLASS=");
1564         appendAttributeDesc(this, attrs, styleAttr, " STYLE=");
1565         fprintf(stderr, "%s%s\t%p%s\n", prefix, nodeName().utf8().data(), this, attrs.utf8().data());
1566     }
1567 }
1568
1569 void Node::showTreeForThis() const
1570 {
1571     showTreeAndMark(this, "*");
1572 }
1573
1574 void Node::showTreeAndMark(const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, const char * markedLabel2) const
1575 {
1576     const Node* rootNode;
1577     const Node* node = this;
1578     while (node->parentNode() && !node->hasTagName(bodyTag))
1579         node = node->parentNode();
1580     rootNode = node;
1581         
1582     for (node = rootNode; node; node = node->traverseNextNode()) {
1583         if (node == markedNode1)
1584             fprintf(stderr, "%s", markedLabel1);
1585         if (node == markedNode2)
1586             fprintf(stderr, "%s", markedLabel2);
1587                         
1588         for (const Node* tmpNode = node; tmpNode && tmpNode != rootNode; tmpNode = tmpNode->parentNode())
1589             fprintf(stderr, "\t");
1590         node->showNode();
1591     }
1592 }
1593
1594 void Node::formatForDebugger(char* buffer, unsigned length) const
1595 {
1596     String result;
1597     String s;
1598     
1599     s = nodeName();
1600     if (s.length() == 0)
1601         result += "<none>";
1602     else
1603         result += s;
1604           
1605     strncpy(buffer, result.utf8().data(), length - 1);
1606 }
1607
1608 #endif
1609
1610 }
1611
1612 #ifndef NDEBUG
1613
1614 void showTree(const WebCore::Node* node)
1615 {
1616     if (node)
1617         node->showTreeForThis();
1618 }
1619
1620 #endif