cb52e597a6ecd99d87f4bc67d312f6734765b891
[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     if (inDocument())
465         document()->incDOMTreeVersion();
466
467     if (localName == idAttr.localName())
468         updateId(old ? old->value() : nullAtom, value);
469     
470     if (old && value.isNull())
471         namedAttrMap->removeAttribute(old->name());
472     else if (!old && !value.isNull())
473         namedAttrMap->addAttribute(createAttribute(QualifiedName(nullAtom, localName, nullAtom), value.impl()));
474     else if (old && !value.isNull()) {
475         old->setValue(value);
476         attributeChanged(old);
477     }
478 }
479
480 void Element::setAttribute(const QualifiedName& name, StringImpl* value, ExceptionCode& ec)
481 {
482     if (inDocument())
483         document()->incDOMTreeVersion();
484
485     // allocate attributemap if necessary
486     Attribute* old = attributes(false)->getAttributeItem(name);
487
488     // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
489     if (namedAttrMap->isReadOnlyNode()) {
490         ec = NO_MODIFICATION_ALLOWED_ERR;
491         return;
492     }
493
494     if (name == idAttr)
495         updateId(old ? old->value() : nullAtom, value);
496     
497     if (old && !value)
498         namedAttrMap->removeAttribute(name);
499     else if (!old && value)
500         namedAttrMap->addAttribute(createAttribute(name, value));
501     else if (old && value) {
502         old->setValue(value);
503         attributeChanged(old);
504     }
505 }
506
507 Attribute* Element::createAttribute(const QualifiedName& name, StringImpl* value)
508 {
509     return new Attribute(name, value);
510 }
511
512 void Element::setAttributeMap(NamedAttrMap* list)
513 {
514     if (inDocument())
515         document()->incDOMTreeVersion();
516
517     // If setting the whole map changes the id attribute, we need to call updateId.
518
519     Attribute *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(idAttr) : 0;
520     Attribute *newId = list ? list->getAttributeItem(idAttr) : 0;
521
522     if (oldId || newId)
523         updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
524
525     if (namedAttrMap)
526         namedAttrMap->element = 0;
527
528     namedAttrMap = list;
529
530     if (namedAttrMap) {
531         namedAttrMap->element = this;
532         unsigned len = namedAttrMap->length();
533         for (unsigned i = 0; i < len; i++)
534             attributeChanged(namedAttrMap->attrs[i]);
535         // FIXME: What about attributes that were in the old map that are not in the new map?
536     }
537 }
538
539 bool Element::hasAttributes() const
540 {
541     updateStyleAttributeIfNeeded();
542     return namedAttrMap && namedAttrMap->length() > 0;
543 }
544
545 String Element::nodeName() const
546 {
547     return m_tagName.toString();
548 }
549
550 String Element::nodeNamePreservingCase() const
551 {
552     return m_tagName.toString();
553 }
554
555 void Element::setPrefix(const AtomicString &_prefix, ExceptionCode& ec)
556 {
557     ec = 0;
558     checkSetPrefix(_prefix, ec);
559     if (ec)
560         return;
561
562     m_tagName.setPrefix(_prefix);
563 }
564
565 String Element::baseURI() const
566 {
567     KURL xmlbase(getAttribute(baseAttr).deprecatedString());
568
569     if (!xmlbase.protocol().isEmpty())
570         return xmlbase.string();
571
572     Node* parent = parentNode();
573     if (parent)
574         return KURL(parent->baseURI().deprecatedString(), xmlbase.deprecatedString()).string();
575
576     return xmlbase.string();
577 }
578
579 Node* Element::insertAdjacentElement(const String& where, Node* newChild, int& exception)
580 {
581     if (!newChild) {
582         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
583         exception = TYPE_MISMATCH_ERR;
584         return 0;
585     }
586     
587     // In Internet Explorer if the element has no parent and where is "beforeBegin" or "afterEnd",
588     // a document fragment is created and the elements appended in the correct order. This document
589     // fragment isn't returned anywhere.
590     //
591     // This is impossible for us to implement as the DOM tree does not allow for such structures,
592     // Opera also appears to disallow such usage.
593     
594     if (equalIgnoringCase(where, "beforeBegin")) {
595         if (Node* p = parent())
596             return p->insertBefore(newChild, this, exception) ? newChild : 0;
597     } else if (equalIgnoringCase(where, "afterBegin")) {
598         return insertBefore(newChild, firstChild(), exception) ? newChild : 0;
599     } else if (equalIgnoringCase(where, "beforeEnd")) {
600         return appendChild(newChild, exception) ? newChild : 0;
601     } else if (equalIgnoringCase(where, "afterEnd")) {
602         if (Node* p = parent())
603             return p->insertBefore(newChild, nextSibling(), exception) ? newChild : 0;
604     } else {
605         // IE throws COM Exception E_INVALIDARG; this is the best DOM exception alternative
606         exception = NOT_SUPPORTED_ERR;
607     }
608     return 0;
609 }
610
611 bool Element::contains(const Node* node) const
612 {
613     if (!node)
614         return false;
615     return this == node || node->isDescendantOf(this);
616 }
617
618 void Element::createAttributeMap() const
619 {
620     namedAttrMap = new NamedAttrMap(const_cast<Element*>(this));
621 }
622
623 bool Element::isURLAttribute(Attribute *attr) const
624 {
625     return false;
626 }
627
628 const QualifiedName& Element::imageSourceAttributeName() const
629 {
630     return srcAttr;
631 }
632
633 RenderStyle* Element::styleForRenderer(RenderObject* parentRenderer)
634 {
635     return document()->styleSelector()->styleForElement(this);
636 }
637
638 RenderObject* Element::createRenderer(RenderArena* arena, RenderStyle* style)
639 {
640     if (document()->documentElement() == this && style->display() == NONE) {
641         // Ignore display: none on root elements.  Force a display of block in that case.
642         RenderBlock* result = new (arena) RenderBlock(this);
643         if (result)
644             result->setAnimatableStyle(style);
645         return result;
646     }
647     return RenderObject::createObject(this, style);
648 }
649
650
651 void Element::insertedIntoDocument()
652 {
653     // need to do superclass processing first so inDocument() is true
654     // by the time we reach updateId
655     ContainerNode::insertedIntoDocument();
656
657     if (hasID()) {
658         NamedAttrMap* attrs = attributes(true);
659         if (attrs) {
660             Attribute* idItem = attrs->getAttributeItem(idAttr);
661             if (idItem && !idItem->isNull())
662                 updateId(nullAtom, idItem->value());
663         }
664     }
665 }
666
667 void Element::removedFromDocument()
668 {
669     if (hasID()) {
670         NamedAttrMap* attrs = attributes(true);
671         if (attrs) {
672             Attribute* idItem = attrs->getAttributeItem(idAttr);
673             if (idItem && !idItem->isNull())
674                 updateId(idItem->value(), nullAtom);
675         }
676     }
677
678     ContainerNode::removedFromDocument();
679 }
680
681 void Element::attach()
682 {
683     createRendererIfNeeded();
684     ContainerNode::attach();
685     if (ElementRareData* rd = rareData()) {
686         if (rd->m_needsFocusAppearanceUpdateSoonAfterAttach) {
687             if (isFocusable() && document()->focusedNode() == this)
688                 document()->updateFocusAppearanceSoon();
689             rd->m_needsFocusAppearanceUpdateSoonAfterAttach = false;
690         }
691     }
692 }
693
694 void Element::detach()
695 {
696     cancelFocusAppearanceUpdate();
697     if (ElementRareData* rd = rareData())
698         rd->resetComputedStyle(this);
699     ContainerNode::detach();
700 }
701
702 void Element::recalcStyle(StyleChange change)
703 {
704     // ### should go away and be done in renderobject
705     RenderStyle* currentStyle = renderStyle();
706     bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
707
708 #if ENABLE(SVG)
709     if (!hasParentStyle && isShadowNode() && isSVGElement())
710         hasParentStyle = true;
711 #endif
712
713     if ((change > NoChange || changed())) {
714         if (ElementRareData* rd = rareData())
715             rd->resetComputedStyle(this);
716     }
717     if (hasParentStyle && (change >= Inherit || changed())) {
718         RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
719         StyleChange ch = diff(currentStyle, newStyle);
720         if (ch == Detach) {
721             if (attached())
722                 detach();
723             // ### Suboptimal. Style gets calculated again.
724             attach();
725             // attach recalulates the style for all children. No need to do it twice.
726             setChanged(NoStyleChange);
727             setHasChangedChild(false);
728             newStyle->deref(document()->renderArena());
729             return;
730         }
731
732         if (currentStyle && newStyle) {
733             // Preserve "affected by" bits that were propagated to us from descendants
734             if (currentStyle->affectedByHoverRules())
735                 newStyle->setAffectedByHoverRules(true);
736             if (currentStyle->affectedByActiveRules())
737                 newStyle->setAffectedByActiveRules(true);
738             if (currentStyle->affectedByDragRules())
739                 newStyle->setAffectedByDragRules(true);
740         }
741
742         if (ch != NoChange) {
743             if (newStyle)
744                 setRenderStyle(newStyle);
745         } else if (changed() && newStyle && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
746             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
747             // fooled into believing this style is the same.  This is only necessary if the document actually uses
748             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
749             // descendants.
750             if (renderer())
751                 renderer()->setStyleInternal(newStyle);
752             else
753                 setRenderStyle(newStyle);
754         }
755
756         newStyle->deref(document()->renderArena());
757
758         if (change != Force) {
759             if (document()->usesDescendantRules() && styleChangeType() == FullStyleChange)
760                 change = Force;
761             else
762                 change = ch;
763         }
764     }
765
766     for (Node *n = firstChild(); n; n = n->nextSibling()) {
767         if (change >= Inherit || n->isTextNode() || n->hasChangedChild() || n->changed())
768             n->recalcStyle(change);
769     }
770
771     setChanged(NoStyleChange);
772     setHasChangedChild(false);
773 }
774
775 bool Element::childTypeAllowed(NodeType type)
776 {
777     switch (type) {
778         case ELEMENT_NODE:
779         case TEXT_NODE:
780         case COMMENT_NODE:
781         case PROCESSING_INSTRUCTION_NODE:
782         case CDATA_SECTION_NODE:
783         case ENTITY_REFERENCE_NODE:
784             return true;
785             break;
786         default:
787             return false;
788     }
789 }
790
791 void Element::dispatchAttrRemovalEvent(Attribute*)
792 {
793     ASSERT(!eventDispatchForbidden());
794 #if 0
795     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
796         return;
797     ExceptionCode ec = 0;
798     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
799         attr->value(), document()->attrName(attr->id()), MutationEvent::REMOVAL), ec);
800 #endif
801 }
802
803 void Element::dispatchAttrAdditionEvent(Attribute *attr)
804 {
805     ASSERT(!eventDispatchForbidden());
806 #if 0
807     if (!document()->hasListenerType(Document::DOMATTRMODIFIED_LISTENER))
808         return;
809     ExceptionCode ec = 0;
810     dispatchEvent(new MutationEvent(DOMAttrModifiedEvent, true, false, attr, attr->value(),
811         attr->value(),document()->attrName(attr->id()), MutationEvent::ADDITION), ec);
812 #endif
813 }
814
815 String Element::openTagStartToString() const
816 {
817     String result = "<" + nodeName();
818
819     NamedAttrMap *attrMap = attributes(true);
820
821     if (attrMap) {
822         unsigned numAttrs = attrMap->length();
823         for (unsigned i = 0; i < numAttrs; i++) {
824             result += " ";
825
826             Attribute *attribute = attrMap->attributeItem(i);
827             result += attribute->name().toString();
828             if (!attribute->value().isNull()) {
829                 result += "=\"";
830                 // FIXME: substitute entities for any instances of " or '
831                 result += attribute->value();
832                 result += "\"";
833             }
834         }
835     }
836
837     return result;
838 }
839
840 String Element::toString() const
841 {
842     String result = openTagStartToString();
843
844     if (hasChildNodes()) {
845         result += ">";
846
847         for (Node *child = firstChild(); child != NULL; child = child->nextSibling()) {
848             result += child->toString();
849         }
850
851         result += "</";
852         result += nodeName();
853         result += ">";
854     } else {
855         result += " />";
856     }
857
858     return result;
859 }
860
861 void Element::updateId(const AtomicString& oldId, const AtomicString& newId)
862 {
863     if (!inDocument())
864         return;
865
866     if (oldId == newId)
867         return;
868
869     Document* doc = document();
870     if (!oldId.isEmpty())
871         doc->removeElementById(oldId, this);
872     if (!newId.isEmpty())
873         doc->addElementById(newId, this);
874 }
875
876 #ifndef NDEBUG
877 void Element::dump(TextStream *stream, DeprecatedString ind) const
878 {
879     updateStyleAttributeIfNeeded();
880     if (namedAttrMap) {
881         for (unsigned i = 0; i < namedAttrMap->length(); i++) {
882             Attribute *attr = namedAttrMap->attributeItem(i);
883             *stream << " " << attr->name().localName().deprecatedString().ascii()
884                     << "=\"" << attr->value().deprecatedString().ascii() << "\"";
885         }
886     }
887
888     ContainerNode::dump(stream,ind);
889 }
890 #endif
891
892 #ifndef NDEBUG
893 void Element::formatForDebugger(char *buffer, unsigned length) const
894 {
895     String result;
896     String s;
897     
898     s = nodeName();
899     if (s.length() > 0) {
900         result += s;
901     }
902           
903     s = getAttribute(idAttr);
904     if (s.length() > 0) {
905         if (result.length() > 0)
906             result += "; ";
907         result += "id=";
908         result += s;
909     }
910           
911     s = getAttribute(classAttr);
912     if (s.length() > 0) {
913         if (result.length() > 0)
914             result += "; ";
915         result += "class=";
916         result += s;
917     }
918           
919     strncpy(buffer, result.deprecatedString().latin1(), length - 1);
920 }
921 #endif
922
923 PassRefPtr<Attr> Element::setAttributeNode(Attr *attr, ExceptionCode& ec)
924 {
925     ASSERT(attr);
926     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
927 }
928
929 PassRefPtr<Attr> Element::setAttributeNodeNS(Attr* attr, ExceptionCode& ec)
930 {
931     ASSERT(attr);
932     return static_pointer_cast<Attr>(attributes(false)->setNamedItem(attr, ec));
933 }
934
935 PassRefPtr<Attr> Element::removeAttributeNode(Attr *attr, ExceptionCode& ec)
936 {
937     if (!attr || attr->ownerElement() != this) {
938         ec = NOT_FOUND_ERR;
939         return 0;
940     }
941     if (document() != attr->document()) {
942         ec = WRONG_DOCUMENT_ERR;
943         return 0;
944     }
945
946     NamedAttrMap *attrs = attributes(true);
947     if (!attrs)
948         return 0;
949
950     return static_pointer_cast<Attr>(attrs->removeNamedItem(attr->qualifiedName(), ec));
951 }
952
953 void Element::setAttributeNS(const String& namespaceURI, const String& qualifiedName, const String& value, ExceptionCode& ec)
954 {
955     String prefix, localName;
956     if (!Document::parseQualifiedName(qualifiedName, prefix, localName)) {
957         ec = INVALID_CHARACTER_ERR;
958         return;
959     }
960     setAttribute(QualifiedName(prefix, localName, namespaceURI), value.impl(), ec);
961 }
962
963 void Element::removeAttribute(const String& name, ExceptionCode& ec)
964 {
965     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
966
967     if (namedAttrMap) {
968         namedAttrMap->removeNamedItem(localName, ec);
969         if (ec == NOT_FOUND_ERR)
970             ec = 0;
971     }
972 }
973
974 void Element::removeAttributeNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
975 {
976     removeAttribute(QualifiedName(nullAtom, localName, namespaceURI), ec);
977 }
978
979 PassRefPtr<Attr> Element::getAttributeNode(const String& name)
980 {
981     NamedAttrMap* attrs = attributes(true);
982     if (!attrs)
983         return 0;
984     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
985     return static_pointer_cast<Attr>(attrs->getNamedItem(localName));
986 }
987
988 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
989 {
990     NamedAttrMap* attrs = attributes(true);
991     if (!attrs)
992         return 0;
993     return static_pointer_cast<Attr>(attrs->getNamedItem(QualifiedName(nullAtom, localName, namespaceURI)));
994 }
995
996 bool Element::hasAttribute(const String& name) const
997 {
998     NamedAttrMap* attrs = attributes(true);
999     if (!attrs)
1000         return false;
1001     String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
1002     return attrs->getAttributeItem(localName);
1003 }
1004
1005 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
1006 {
1007     NamedAttrMap* attrs = attributes(true);
1008     if (!attrs)
1009         return false;
1010     return attrs->getAttributeItem(QualifiedName(nullAtom, localName, namespaceURI));
1011 }
1012
1013 CSSStyleDeclaration *Element::style()
1014 {
1015     return 0;
1016 }
1017
1018 void Element::focus(bool restorePreviousSelection)
1019 {
1020     Document* doc = document();
1021     if (doc->focusedNode() == this)
1022         return;
1023
1024     doc->updateLayoutIgnorePendingStylesheets();
1025     
1026     if (!supportsFocus())
1027         return;
1028     
1029     if (Page* page = doc->page())
1030         page->focusController()->setFocusedNode(this, doc->frame());
1031
1032     if (!isFocusable()) {
1033         createRareData()->m_needsFocusAppearanceUpdateSoonAfterAttach = true;
1034         return;
1035     }
1036         
1037     cancelFocusAppearanceUpdate();
1038     updateFocusAppearance(restorePreviousSelection);
1039 }
1040
1041 void Element::updateFocusAppearance(bool restorePreviousSelection)
1042 {
1043     if (this == rootEditableElement()) { 
1044         Frame* frame = document()->frame();
1045         if (!frame)
1046             return;
1047
1048         // FIXME: We should restore the previous selection if there is one.
1049         Selection newSelection = hasTagName(htmlTag) || hasTagName(bodyTag) ? Selection(Position(this, 0), DOWNSTREAM) : Selection::selectionFromContentsOfNode(this);
1050         
1051         if (frame->shouldChangeSelection(newSelection)) {
1052             frame->selectionController()->setSelection(newSelection);
1053             frame->revealSelection();
1054         }
1055     } else if (renderer() && !renderer()->isWidget())
1056         renderer()->enclosingLayer()->scrollRectToVisible(getRect());
1057 }
1058
1059 void Element::blur()
1060 {
1061     cancelFocusAppearanceUpdate();
1062     Document* doc = document();
1063     if (doc->focusedNode() == this) {
1064         if (doc->frame())
1065             doc->frame()->page()->focusController()->setFocusedNode(0, doc->frame());
1066         else
1067             doc->setFocusedNode(0);
1068     }
1069 }
1070
1071 String Element::innerText() const
1072 {
1073     // We need to update layout, since plainText uses line boxes in the render tree.
1074     document()->updateLayoutIgnorePendingStylesheets();
1075
1076     if (!renderer())
1077         return textContent(true);
1078
1079     return plainText(rangeOfContents(const_cast<Element*>(this)).get());
1080 }
1081
1082 String Element::outerText() const
1083 {
1084     // Getting outerText is the same as getting innerText, only
1085     // setting is different. You would think this should get the plain
1086     // text for the outer range, but this is wrong, <br> for instance
1087     // would return different values for inner and outer text by such
1088     // a rule, but it doesn't in WinIE, and we want to match that.
1089     return innerText();
1090 }
1091
1092 String Element::title() const
1093 {
1094     return String();
1095 }
1096
1097 IntSize Element::minimumSizeForResizing() const
1098 {
1099     const ElementRareData* rd = rareData();
1100     return rd ? rd->m_minimumSizeForResizing : defaultMinimumSizeForResizing();
1101 }
1102
1103 void Element::setMinimumSizeForResizing(const IntSize& size)
1104 {
1105     if (size == defaultMinimumSizeForResizing() && !rareData())
1106         return;
1107     createRareData()->m_minimumSizeForResizing = size;
1108 }
1109
1110 RenderStyle* Element::computedStyle()
1111 {
1112     if (RenderStyle* usedStyle = renderStyle())
1113         return usedStyle;
1114
1115     if (!attached())
1116         // FIXME: Try to do better than this. Ensure that styleForElement() works for elements that are not in the
1117         // document tree and figure out when to destroy the computed style for such elements.
1118         return 0;
1119
1120     ElementRareData* rd = createRareData();
1121     if (!rd->m_computedStyle)
1122         rd->m_computedStyle = document()->styleSelector()->styleForElement(this, parent() ? parent()->computedStyle() : 0);
1123     return rd->m_computedStyle;
1124 }
1125
1126 void Element::cancelFocusAppearanceUpdate()
1127 {
1128     if (ElementRareData* rd = rareData())
1129         rd->m_needsFocusAppearanceUpdateSoonAfterAttach = false;
1130     if (document()->focusedNode() == this)
1131         document()->cancelFocusAppearanceUpdate();
1132 }
1133
1134 }