WebCore:
[WebKit-https.git] / WebCore / dom / Element.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Peter Kelly (pmk@post.com)
5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
6  *           (C) 2007 David Smith (catfish.man@gmail.com)
7  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
8  *           (C) 2007 Eric Seidel (eric@webkit.org)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "Element.h"
28
29 #include "CSSStyleSelector.h"
30 #include "ClassNames.h"
31 #include "ClassNodeList.h"
32 #include "Document.h"
33 #include "Editor.h"
34 #include "ExceptionCode.h"
35 #include "FocusController.h"
36 #include "Frame.h"
37 #include "FrameView.h"
38 #include "HTMLElement.h"
39 #include "HTMLNames.h"
40 #include "KURL.h"
41 #include "NamedAttrMap.h"
42 #include "NodeList.h"
43 #include "Page.h"
44 #include "RenderBlock.h"
45 #include "SelectionController.h"
46 #include "TextIterator.h"
47 #include "TextStream.h"
48 #include "XMLNames.h"
49
50 namespace WebCore {
51
52 using namespace HTMLNames;
53 using namespace XMLNames;
54
55 class ElementRareData {
56 public:
57     ElementRareData(Element*);
58     void resetComputedStyle(Element*);
59
60     IntSize m_minimumSizeForResizing;
61     RenderStyle* m_computedStyle;
62     bool m_needsFocusAppearanceUpdateSoonAfterAttach;
63 };
64
65 typedef HashMap<const Element*, ElementRareData*> ElementRareDataMap;
66
67 static ElementRareDataMap& rareDataMap()
68 {
69     static ElementRareDataMap* dataMap = new ElementRareDataMap;
70     return *dataMap;
71 }
72
73 static ElementRareData* rareDataFromMap(const Element* element)
74 {
75     return rareDataMap().get(element);
76 }
77
78 static inline IntSize defaultMinimumSizeForResizing()
79 {
80     return IntSize(INT_MAX, INT_MAX);
81 }
82
83 inline ElementRareData::ElementRareData(Element* element)
84     : m_minimumSizeForResizing(defaultMinimumSizeForResizing())
85     , m_computedStyle(0)
86     , m_needsFocusAppearanceUpdateSoonAfterAttach(false)
87 {
88 }
89
90 void ElementRareData::resetComputedStyle(Element* element)
91 {
92     if (!m_computedStyle)
93         return;
94     m_computedStyle->deref(element->document()->renderArena());
95     m_computedStyle = 0;
96 }
97
98 Element::Element(const QualifiedName& qName, Document *doc)
99     : ContainerNode(doc)
100     , m_tagName(qName)
101 {
102 }
103
104 Element::~Element()
105 {
106     if (namedAttrMap)
107         namedAttrMap->detachFromElement();
108
109     if (!m_attrWasSpecifiedOrElementHasRareData)
110         ASSERT(!rareDataMap().contains(this));
111     else {
112         ElementRareDataMap& dataMap = rareDataMap();
113         ElementRareDataMap::iterator it = dataMap.find(this);
114         ASSERT(it != dataMap.end());
115         delete it->second;
116         dataMap.remove(it);
117     }
118 }
119
120 inline ElementRareData* Element::rareData()
121 {
122     return m_attrWasSpecifiedOrElementHasRareData ? rareDataFromMap(this) : 0;
123 }
124
125 inline const ElementRareData* Element::rareData() const
126 {
127     return m_attrWasSpecifiedOrElementHasRareData ? rareDataFromMap(this) : 0;
128 }
129
130 ElementRareData* Element::createRareData()
131 {
132     if (m_attrWasSpecifiedOrElementHasRareData)
133         return rareDataMap().get(this);
134     ASSERT(!rareDataMap().contains(this));
135     ElementRareData* data = new ElementRareData(this);
136     rareDataMap().set(this, data);
137     m_attrWasSpecifiedOrElementHasRareData = true;
138     return data;
139 }
140
141 PassRefPtr<Node> Element::cloneNode(bool deep)
142 {
143     ExceptionCode ec = 0;
144     RefPtr<Element> clone = document()->createElementNS(namespaceURI(), nodeName(), ec);
145     ASSERT(!ec);
146     
147     // clone attributes
148     if (namedAttrMap)
149         *clone->attributes() = *namedAttrMap;
150
151     clone->copyNonAttributeProperties(this);
152     
153     if (deep)
154         cloneChildNodes(clone.get());
155
156     return clone.release();
157 }
158
159 void Element::removeAttribute(const QualifiedName& name, ExceptionCode& ec)
160 {
161     if (namedAttrMap) {
162         namedAttrMap->removeNamedItem(name, ec);
163         if (ec == NOT_FOUND_ERR)
164             ec = 0;
165     }
166 }
167
168 void Element::setAttribute(const QualifiedName& name, const String &value)
169 {
170     ExceptionCode ec = 0;
171     setAttribute(name, value.impl(), ec);
172 }
173
174 void Element::setBooleanAttribute(const QualifiedName& name, bool b)
175 {
176     if (b)
177         setAttribute(name, name.localName());
178     else {
179         ExceptionCode ex;
180         removeAttribute(name, ex);
181     }
182 }
183
184 // Virtual function, defined in base class.
185 NamedAttrMap *Element::attributes() const
186 {
187     return attributes(false);
188 }
189
190 NamedAttrMap* Element::attributes(bool readonly) const
191 {
192     updateStyleAttributeIfNeeded();
193     if (!readonly && !namedAttrMap)
194         createAttributeMap();
195     return namedAttrMap.get();
196 }
197
198 Node::NodeType Element::nodeType() const
199 {
200     return ELEMENT_NODE;
201 }
202
203 const ClassNames* Element::getClassNames() const
204 {
205     return 0;
206 }
207
208 const AtomicString& Element::getIDAttribute() const
209 {
210     return namedAttrMap ? namedAttrMap->id() : nullAtom;
211 }
212
213 bool Element::hasAttribute(const QualifiedName& name) const
214 {
215     return hasAttributeNS(name.namespaceURI(), name.localName());
216 }
217
218 const AtomicString& Element::getAttribute(const QualifiedName& name) const
219 {
220     if (name == styleAttr)
221         updateStyleAttributeIfNeeded();
222
223     if (namedAttrMap)
224         if (Attribute* a = namedAttrMap->getAttributeItem(name))
225             return a->value();
226
227     return nullAtom;
228 }
229
230 void Element::scrollIntoView(bool alignToTop) 
231 {
232     document()->updateLayoutIgnorePendingStylesheets();
233     IntRect bounds = getRect();    
234     if (renderer()) {
235         // Align to the top / bottom and to the closest edge.
236         if (alignToTop)
237             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignTopAlways);
238         else
239             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignBottomAlways);
240     }
241 }
242
243 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
244 {
245     document()->updateLayoutIgnorePendingStylesheets();
246     IntRect bounds = getRect();    
247     if (renderer()) {
248         if (centerIfNeeded)
249             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignCenterIfNeeded, RenderLayer::gAlignCenterIfNeeded);
250         else
251             renderer()->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
252     }
253 }
254
255 void Element::scrollByUnits(int units, ScrollGranularity granularity)
256 {
257     document()->updateLayoutIgnorePendingStylesheets();
258     if (RenderObject *rend = renderer()) {
259         if (rend->hasOverflowClip()) {
260             ScrollDirection direction = ScrollDown;
261             if (units < 0) {
262                 direction = ScrollUp;
263                 units = -units;
264             }
265             rend->layer()->scroll(direction, granularity, units);
266         }
267     }
268 }
269
270 void Element::scrollByLines(int lines)
271 {
272     scrollByUnits(lines, ScrollByLine);
273 }
274
275 void Element::scrollByPages(int pages)
276 {
277     scrollByUnits(pages, ScrollByPage);
278 }
279
280 int Element::offsetLeft()
281 {
282     document()->updateLayoutIgnorePendingStylesheets();
283     if (RenderObject* rend = renderer())
284         return rend->offsetLeft();
285     return 0;
286 }
287
288 int Element::offsetTop()
289 {
290     document()->updateLayoutIgnorePendingStylesheets();
291     if (RenderObject* rend = renderer())
292         return rend->offsetTop();
293     return 0;
294 }
295
296 int Element::offsetWidth()
297 {
298     document()->updateLayoutIgnorePendingStylesheets();
299     if (RenderObject* rend = renderer())
300         return rend->offsetWidth();
301     return 0;
302 }
303
304 int Element::offsetHeight()
305 {
306     document()->updateLayoutIgnorePendingStylesheets();
307     if (RenderObject* rend = renderer())
308         return rend->offsetHeight();
309     return 0;
310 }
311
312 Element* Element::offsetParent()
313 {
314     document()->updateLayoutIgnorePendingStylesheets();
315     if (RenderObject* rend = renderer())
316         if (RenderObject* offsetParent = rend->offsetParent())
317             return static_cast<Element*>(offsetParent->element());
318     return 0;
319 }
320
321 int Element::clientLeft()
322 {
323     document()->updateLayoutIgnorePendingStylesheets();
324
325     if (RenderObject* rend = renderer())
326         return rend->clientLeft();
327     return 0;
328 }
329
330 int Element::clientTop()
331 {
332     document()->updateLayoutIgnorePendingStylesheets();
333
334     if (RenderObject* rend = renderer())
335         return rend->clientTop();
336     return 0;
337 }
338
339 int Element::clientWidth()
340 {
341     document()->updateLayoutIgnorePendingStylesheets();
342
343     // When in strict mode, clientWidth for the document element should return the width of the containing frame.
344     // When in quirks mode, clientWidth for the body element should return the width of the containing frame.
345     bool inCompatMode = document()->inCompatMode();
346     if ((!inCompatMode && document()->documentElement() == this) ||
347         (inCompatMode && isHTMLElement() && document()->body() == this)) {
348         if (FrameView* view = document()->view())
349             return view->visibleWidth();
350     }
351     
352
353     if (RenderObject* rend = renderer())
354         return rend->clientWidth();
355     return 0;
356 }
357
358 int Element::clientHeight()
359 {
360     document()->updateLayoutIgnorePendingStylesheets();
361
362     // When in strict mode, clientHeight for the document element should return the height of the containing frame.
363     // When in quirks mode, clientHeight for the body element should return the height of the containing frame.
364     bool inCompatMode = document()->inCompatMode();     
365
366     if ((!inCompatMode && document()->documentElement() == this) ||
367         (inCompatMode && isHTMLElement() && document()->body() == this)) {
368         if (FrameView* view = document()->view())
369             return view->visibleHeight();
370     }
371     
372     if (RenderObject* rend = renderer())
373         return rend->clientHeight();
374     return 0;
375 }
376
377 int Element::scrollLeft()
378 {
379     document()->updateLayoutIgnorePendingStylesheets();
380     if (RenderObject* rend = renderer())
381         return rend->scrollLeft();
382     return 0;
383 }
384
385 int Element::scrollTop()
386 {
387     document()->updateLayoutIgnorePendingStylesheets();
388     if (RenderObject* rend = renderer())
389         return rend->scrollTop();
390     return 0;
391 }
392
393 void Element::setScrollLeft(int newLeft)
394 {
395     document()->updateLayoutIgnorePendingStylesheets();
396     if (RenderObject *rend = renderer())
397         rend->setScrollLeft(newLeft);
398 }
399
400 void Element::setScrollTop(int newTop)
401 {
402     document()->updateLayoutIgnorePendingStylesheets();
403     if (RenderObject *rend = renderer())
404         rend->setScrollTop(newTop);
405 }
406
407 int Element::scrollWidth()
408 {
409     document()->updateLayoutIgnorePendingStylesheets();
410     if (RenderObject* rend = renderer())
411         return rend->scrollWidth();
412     return 0;
413 }
414
415 int Element::scrollHeight()
416 {
417     document()->updateLayoutIgnorePendingStylesheets();
418     if (RenderObject* rend = renderer())
419         return rend->scrollHeight();
420     return 0;
421 }
422
423 static inline bool shouldIgnoreAttributeCase(const Element* e)
424 {
425     return e && e->document()->isHTMLDocument() && e->isHTMLElement();
426 }
427
428 const AtomicString& Element::getAttribute(const String& name) const
429 {
430     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
431     if (localName == styleAttr.localName())
432         updateStyleAttributeIfNeeded();
433     
434     if (namedAttrMap)
435         if (Attribute* a = namedAttrMap->getAttributeItem(localName))
436             return a->value();
437     
438     return nullAtom;
439 }
440
441 const AtomicString& Element::getAttributeNS(const String& namespaceURI, const String& localName) const
442 {
443     return getAttribute(QualifiedName(nullAtom, localName, namespaceURI));
444 }
445
446 void Element::setAttribute(const String& name, const String& value, ExceptionCode& ec)
447 {
448     if (!Document::isValidName(name)) {
449         ec = INVALID_CHARACTER_ERR;
450         return;
451     }
452
453     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
454
455     // allocate attributemap if necessary
456     Attribute* old = attributes(false)->getAttributeItem(localName);
457
458     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
459     if (namedAttrMap->isReadOnlyNode()) {
460         ec = NO_MODIFICATION_ALLOWED_ERR;
461         return;
462     }
463     
464     document()->incDOMTreeVersion();
465
466     if (localName == idAttr.localName())
467         updateId(old ? old->value() : nullAtom, value);
468     
469     if (old && value.isNull())
470         namedAttrMap->removeAttribute(old->name());
471     else if (!old && !value.isNull())
472         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value.impl()));
473     else if (old && !value.isNull()) {
474         old->setValue(value);
475         attributeChanged(old);
476     }
477 }
478
479 void Element::setAttribute(const QualifiedName& name, StringImpl* value, ExceptionCode& ec)
480 {
481     document()->incDOMTreeVersion();
482
483     // allocate attributemap if necessary
484     Attribute* old = attributes(false)->getAttributeItem(name);
485
486     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
487     if (namedAttrMap->isReadOnlyNode()) {
488         ec = NO_MODIFICATION_ALLOWED_ERR;
489         return;
490     }
491
492     if (name == idAttr)
493         updateId(old ? old->value() : nullAtom, value);
494     
495     if (old && !value)
496         namedAttrMap->removeAttribute(name);
497     else if (!old && value)
498         namedAttrMap->addAttribute(createAttribute(name, value));
499     else if (old && value) {
500         old->setValue(value);
501         attributeChanged(old);
502     }
503 }
504
505 Attribute* Element::createAttribute(const QualifiedName& name, StringImpl* value)
506 {
507     return new Attribute(name, value);
508 }
509
510 void Element::setAttributeMap(NamedAttrMap* list)
511 {
512     document()->incDOMTreeVersion();
513
514     // If setting the whole map changes the id attribute, we need to call updateId.
515
516     Attribute *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0;
517     Attribute *newId = list ? list->getAttributeItem(idAttr) : 0;
518
519     if (oldId || newId)
520         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
521
522     if (namedAttrMap)
523         namedAttrMap->element = 0;
524
525     namedAttrMap = list;
526
527     if (namedAttrMap) {
528         namedAttrMap->element = this;
529         unsigned len = namedAttrMap->length();
530         for (unsigned i = 0; i < len; i++)
531             attributeChanged(namedAttrMap->attrs[i]);
532         // FIXME: What about attributes that were in the old map that are not in the new map?
533     }
534 }
535
536 bool Element::hasAttributes() const
537 {
538     updateStyleAttributeIfNeeded();
539     return namedAttrMap && namedAttrMap->length() > 0;
540 }
541
542 String Element::nodeName() const
543 {
544     return m_tagName.toString();
545 }
546
547 String Element::nodeNamePreservingCase() const
548 {
549     return m_tagName.toString();
550 }
551
552 void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec)
553 {
554     ec = 0;
555     checkSetPrefix(_prefix, ec);
556     if (ec)
557         return;
558
559     m_tagName.setPrefix(_prefix);
560 }
561
562 String Element::baseURI() const
563 {
564     KURL xmlbase(getAttribute(baseAttr).deprecatedString());
565
566     if (!xmlbase.protocol().isEmpty())
567         return xmlbase.string();
568
569     Node* parent = parentNode();
570     if (parent)
571         return KURL(parent->baseURI().deprecatedString(), xmlbase.deprecatedString()).string();
572
573     return xmlbase.string();
574 }
575
576 Node* Element::insertAdjacentElement(const String& where, Node* newChild, int& exception)
577 {
578     if (!newChild) {
579         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
580         exception = TYPE_MISMATCH_ERR;
581         return 0;
582     }
583     
584     // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
585     // a document fragment is created and the elements appended in the correct order. This document
586     // fragment isn't returned anywhere.
587     //
588     // This is impossible for us to implement as the DOM tree does not allow for such structures,
589     // Opera also appears to disallow such usage.
590     
591     if (equalIgnoringCase(where, "beforeBegin")) {
592         if (Node* p = parent())
593             return p->insertBefore(newChild, this, exception) ? newChild : 0;
594     } else if (equalIgnoringCase(where, "afterBegin")) {
595         return insertBefore(newChild, firstChild(), exception) ? newChild : 0;
596     } else if (equalIgnoringCase(where, "beforeEnd")) {
597         return appendChild(newChild, exception) ? newChild : 0;
598     } else if (equalIgnoringCase(where, "afterEnd")) {
599         if (Node* p = parent())
600             return p->insertBefore(newChild, nextSibling(), exception) ? newChild : 0;
601     } else {
602         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
603         exception = NOT_SUPPORTED_ERR;
604     }
605     return 0;
606 }
607
608 bool Element::contains(const Node* node) const
609 {
610     if (!node)
611         return false;
612     return this == node || node->isDescendantOf(this);
613 }
614
615 void Element::createAttributeMap() const
616 {
617     namedAttrMap = new NamedAttrMap(const_cast<Element*>(this));
618 }
619
620 bool Element::isURLAttribute(Attribute *attr) const
621 {
622     return false;
623 }
624
625 const QualifiedName& Element::imageSourceAttributeName() const
626 {
627     return srcAttr;
628 }
629
630 RenderStyle* Element::styleForRenderer(RenderObject* parentRenderer)
631 {
632     return document()->styleSelector()->styleForElement(this);
633 }
634
635 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
636 {
637     if (document()->documentElement() == this && style->display() == NONE) {
638         // Ignore display: none on root elements.  Force a display of block in that case.
639         RenderBlock* result = new (arena) RenderBlock(this);
640         if (result)
641             result->setAnimatableStyle(style);
642         return result;
643     }
644     return RenderObject::createObject(this, style);
645 }
646
647
648 void Element::insertedIntoDocument()
649 {
650     // need to do superclass processing first so inDocument() is true
651     // by the time we reach updateId
652     ContainerNode::insertedIntoDocument();
653
654     if (hasID()) {
655         NamedAttrMap* attrs = attributes(true);
656         if (attrs) {
657             Attribute* idItem = attrs->getAttributeItem(idAttr);
658             if (idItem && !idItem->isNull())
659                 updateId(nullAtom, idItem->value());
660         }
661     }
662 }
663
664 void Element::removedFromDocument()
665 {
666     if (hasID()) {
667         NamedAttrMap* attrs = attributes(true);
668         if (attrs) {
669             Attribute* idItem = attrs->getAttributeItem(idAttr);
670             if (idItem && !idItem->isNull())
671                 updateId(idItem->value(), nullAtom);
672         }
673     }
674
675     ContainerNode::removedFromDocument();
676 }
677
678 void Element::attach()
679 {
680     createRendererIfNeeded();
681     ContainerNode::attach();
682     if (ElementRareData* rd = rareData()) {
683         if (rd->m_needsFocusAppearanceUpdateSoonAfterAttach) {
684             if (isFocusable() && document()->focusedNode() == this)
685                 document()->updateFocusAppearanceSoon();
686             rd->m_needsFocusAppearanceUpdateSoonAfterAttach = false;
687         }
688     }
689 }
690
691 void Element::detach()
692 {
693     cancelFocusAppearanceUpdate();
694     if (ElementRareData* rd = rareData())
695         rd->resetComputedStyle(this);
696     ContainerNode::detach();
697 }
698
699 void Element::recalcStyle(StyleChange change)
700 {
701     // ### should go away and be done in renderobject
702     RenderStyle* currentStyle = renderStyle();
703     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
704
705 #if ENABLE(SVG)
706     if (!hasParentStyle && isShadowNode() && isSVGElement())
707         hasParentStyle = true;
708 #endif
709
710     if ((change > NoChange || changed())) {
711         if (ElementRareData* rd = rareData())
712             rd->resetComputedStyle(this);
713     }
714     if (hasParentStyle && (change >= Inherit || changed())) {
715         RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
716         StyleChange ch = diff(currentStyle, newStyle);
717         if (ch == Detach) {
718             if (attached())
719                 detach();
720             // ### Suboptimal. Style gets calculated again.
721             attach();
722             // attach recalulates the style for all children. No need to do it twice.
723             setChanged(NoStyleChange);
724             setHasChangedChild(false);
725             newStyle->deref(document()->renderArena());
726             return;
727         }
728
729         if (currentStyle && newStyle) {
730             // Preserve "affected by" bits that were propagated to us from descendants
731             if (currentStyle->affectedByHoverRules())
732                 newStyle->setAffectedByHoverRules(true);
733             if (currentStyle->affectedByActiveRules())
734                 newStyle->setAffectedByActiveRules(true);
735             if (currentStyle->affectedByDragRules())
736                 newStyle->setAffectedByDragRules(true);
737         }
738
739         if (ch != NoChange) {
740             if (newStyle)
741                 setRenderStyle(newStyle);
742         } else if (changed() && newStyle && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
743             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
744             // fooled into believing this style is the same.  This is only necessary if the document actually uses
745             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
746             // descendants.
747             if (renderer())
748                 renderer()->setStyleInternal(newStyle);
749             else
750                 setRenderStyle(newStyle);
751         }
752
753         newStyle->deref(document()->renderArena());
754
755         if (change != Force) {
756             if (document()->usesDescendantRules() && styleChangeType() == FullStyleChange)
757                 change = Force;
758             else
759                 change = ch;
760         }
761     }
762
763     for (Node *n = firstChild(); n; n = n->nextSibling()) {
764         if (change >= Inherit || n->isTextNode() || n->hasChangedChild() || n->changed())
765             n->recalcStyle(change);
766     }
767
768     setChanged(NoStyleChange);
769     setHasChangedChild(false);
770 }
771
772 bool Element::childTypeAllowed(NodeType type)
773 {
774     switch (type) {
775         case ELEMENT_NODE:
776         case TEXT_NODE:
777         case COMMENT_NODE:
778         case PROCESSING_INSTRUCTION_NODE:
779         case CDATA_SECTION_NODE:
780         case ENTITY_REFERENCE_NODE:
781             return true;
782             break;
783         default:
784             return false;
785     }
786 }
787
788 void Element::dispatchAttrRemovalEvent(Attribute*)
789 {
790     ASSERT(!eventDispatchForbidden());
791 #if 0
792     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
793         return;
794     ExceptionCode ec = 0;
795     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
796         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
797 #endif
798 }
799
800 void Element::dispatchAttrAdditionEvent(Attribute *attr)
801 {
802     ASSERT(!eventDispatchForbidden());
803 #if 0
804     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
805         return;
806     ExceptionCode ec = 0;
807     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
808         attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
809 #endif
810 }
811
812 String Element::openTagStartToString() const
813 {
814     String result = "<" + nodeName();
815
816     NamedAttrMap *attrMap = attributes(true);
817
818     if (attrMap) {
819         unsigned numAttrs = attrMap->length();
820         for (unsigned i = 0; i < numAttrs; i++) {
821             result += " ";
822
823             Attribute *attribute = attrMap->attributeItem(i);
824             result += attribute->name().toString();
825             if (!attribute->value().isNull()) {
826                 result += "=\"";
827                 // FIXME: substitute entities for any instances of " or '
828                 result += attribute->value();
829                 result += "\"";
830             }
831         }
832     }
833
834     return result;
835 }
836
837 String Element::toString() const
838 {
839     String result = openTagStartToString();
840
841     if (hasChildNodes()) {
842         result += ">";
843
844         for (Node *child = firstChild(); child != NULL; child = child->nextSibling()) {
845             result += child->toString();
846         }
847
848         result += "</";
849         result += nodeName();
850         result += ">";
851     } else {
852         result += " />";
853     }
854
855     return result;
856 }
857
858 void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
859 {
860     if (!inDocument())
861         return;
862
863     if (oldId == newId)
864         return;
865
866     Document* doc = document();
867     if (!oldId.isEmpty())
868         doc->removeElementById(oldId, this);
869     if (!newId.isEmpty())
870         doc->addElementById(newId, this);
871 }
872
873 #ifndef NDEBUG
874 void Element::dump(TextStream *stream, DeprecatedString ind) const
875 {
876     updateStyleAttributeIfNeeded();
877     if (namedAttrMap) {
878         for (unsigned i = 0; i < namedAttrMap->length(); i++) {
879             Attribute *attr = namedAttrMap->attributeItem(i);
880             *stream << " " << attr->name().localName().deprecatedString().ascii()
881                     << "=\"" << attr->value().deprecatedString().ascii() << "\"";
882         }
883     }
884
885     ContainerNode::dump(stream,ind);
886 }
887 #endif
888
889 #ifndef NDEBUG
890 void Element::formatForDebugger(char *buffer, unsigned length) const
891 {
892     String result;
893     String s;
894     
895     s = nodeName();
896     if (s.length() > 0) {
897         result += s;
898     }
899           
900     s = getAttribute(idAttr);
901     if (s.length() > 0) {
902         if (result.length() > 0)
903             result += "; ";
904         result += "id=";
905         result += s;
906     }
907           
908     s = getAttribute(classAttr);
909     if (s.length() > 0) {
910         if (result.length() > 0)
911             result += "; ";
912         result += "class=";
913         result += s;
914     }
915           
916     strncpy(buffer, result.deprecatedString().latin1(), length - 1);
917 }
918 #endif
919
920 PassRefPtr<Attr> Element::setAttributeNode(Attr *attr, ExceptionCode& ec)
921 {
922     ASSERT(attr);
923     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
924 }
925
926 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
927 {
928     ASSERT(attr);
929     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
930 }
931
932 PassRefPtr<Attr> Element::removeAttributeNode(Attr *attr, ExceptionCode& ec)
933 {
934     if (!attr || attr->ownerElement() != this) {
935         ec = NOT_FOUND_ERR;
936         return 0;
937     }
938     if (document() != attr->document()) {
939         ec = WRONG_DOCUMENT_ERR;
940         return 0;
941     }
942
943     NamedAttrMap *attrs = attributes(true);
944     if (!attrs)
945         return 0;
946
947     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
948 }
949
950 void Element::setAttributeNS(const String& namespaceURI, const String& qualifiedName, const String& value, ExceptionCode& ec)
951 {
952     String prefix, localName;
953     if (!Document::parseQualifiedName(qualifiedName, prefix, localName)) {
954         ec = INVALID_CHARACTER_ERR;
955         return;
956     }
957     setAttribute(QualifiedName(prefix, localName, namespaceURI), value.impl(), ec);
958 }
959
960 void Element::removeAttribute(const String& name, ExceptionCode& ec)
961 {
962     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
963
964     if (namedAttrMap) {
965         namedAttrMap->removeNamedItem(localName, ec);
966         if (ec == NOT_FOUND_ERR)
967             ec = 0;
968     }
969 }
970
971 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
972 {
973     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
974 }
975
976 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
977 {
978     NamedAttrMap* attrs = attributes(true);
979     if (!attrs)
980         return 0;
981     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
982     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
983 }
984
985 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
986 {
987     NamedAttrMap* attrs = attributes(true);
988     if (!attrs)
989         return 0;
990     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
991 }
992
993 bool Element::hasAttribute(const String& name) const
994 {
995     NamedAttrMap* attrs = attributes(true);
996     if (!attrs)
997         return false;
998     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
999     return attrs->getAttributeItem(localName);
1000 }
1001
1002 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1003 {
1004     NamedAttrMap* attrs = attributes(true);
1005     if (!attrs)
1006         return false;
1007     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1008 }
1009
1010 CSSStyleDeclaration *Element::style()
1011 {
1012     return 0;
1013 }
1014
1015 void Element::focus(bool restorePreviousSelection)
1016 {
1017     Document* doc = document();
1018     if (doc->focusedNode() == this)
1019         return;
1020
1021     doc->updateLayoutIgnorePendingStylesheets();
1022     
1023     if (!supportsFocus())
1024         return;
1025     
1026     if (Page* page = doc->page())
1027         page->focusController()->setFocusedNode(this, doc->frame());
1028
1029     if (!isFocusable()) {
1030         createRareData()->m_needsFocusAppearanceUpdateSoonAfterAttach = true;
1031         return;
1032     }
1033         
1034     cancelFocusAppearanceUpdate();
1035     updateFocusAppearance(restorePreviousSelection);
1036 }
1037
1038 void Element::updateFocusAppearance(bool restorePreviousSelection)
1039 {
1040     if (this == rootEditableElement()) { 
1041         Frame* frame = document()->frame();
1042         if (!frame)
1043             return;
1044
1045         // FIXME: We should restore the previous selection if there is one.
1046         Selection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? Selection(Position(this, 0), DOWNSTREAM) : Selection::selectionFromContentsOfNode(this);
1047         
1048         if (frame->shouldChangeSelection(newSelection)) {
1049             frame->selectionController()->setSelection(newSelection);
1050             frame->revealSelection();
1051         }
1052     } else if (renderer() && !renderer()->isWidget())
1053         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1054 }
1055
1056 void Element::blur()
1057 {
1058     cancelFocusAppearanceUpdate();
1059     Document* doc = document();
1060     if (doc->focusedNode() == this) {
1061         if (doc->frame())
1062             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1063         else
1064             doc->setFocusedNode(0);
1065     }
1066 }
1067
1068 String Element::innerText() const
1069 {
1070     // We need to update layout, since plainText uses line boxes in the render tree.
1071     document()->updateLayoutIgnorePendingStylesheets();
1072
1073     if (!renderer())
1074         return textContent(true);
1075
1076     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1077 }
1078
1079 String Element::outerText() const
1080 {
1081     // Getting outerText is the same as getting innerText, only
1082     // setting is different. You would think this should get the plain
1083     // text for the outer range, but this is wrong, <br> for instance
1084     // would return different values for inner and outer text by such
1085     // a rule, but it doesn't in WinIE, and we want to match that.
1086     return innerText();
1087 }
1088
1089 String Element::title() const
1090 {
1091     return String();
1092 }
1093
1094 IntSize Element::minimumSizeForResizing() const
1095 {
1096     const ElementRareData* rd = rareData();
1097     return rd ? rd->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1098 }
1099
1100 void Element::setMinimumSizeForResizing(const IntSize& size)
1101 {
1102     if (size == defaultMinimumSizeForResizing() && !rareData())
1103         return;
1104     createRareData()->m_minimumSizeForResizing = size;
1105 }
1106
1107 RenderStyle* Element::computedStyle()
1108 {
1109     if (RenderStyle* usedStyle = renderStyle())
1110         return usedStyle;
1111
1112     if (!attached())
1113         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1114         // document tree and figure out when to destroy the computed style for such elements.
1115         return 0;
1116
1117     ElementRareData* rd = createRareData();
1118     if (!rd->m_computedStyle)
1119         rd->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
1120     return rd->m_computedStyle;
1121 }
1122
1123 void Element::cancelFocusAppearanceUpdate()
1124 {
1125     if (ElementRareData* rd = rareData())
1126         rd->m_needsFocusAppearanceUpdateSoonAfterAttach = false;
1127     if (document()->focusedNode() == this)
1128         document()->cancelFocusAppearanceUpdate();
1129 }
1130
1131 }