LayoutTests:
[WebKit-https.git] / WebCore / dom / Document.cpp
index 5c7f89e..ae3ff06 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
  *
  * This library is free software; you can redistribute it and/or
 #include "DocumentLoader.h"
 #include "DocumentType.h"
 #include "EditingText.h"
+#include "Editor.h"
+#include "EditorClient.h"
 #include "EntityReference.h"
 #include "Event.h"
+#include "EventHandler.h"
 #include "EventListener.h"
 #include "EventNames.h"
 #include "ExceptionCode.h"
+#include "FocusController.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameTree.h"
 #include "FrameView.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
 #include "HTMLBodyElement.h"
 #include "HTMLDocument.h"
 #include "HTMLElementFactory.h"
+#include "HTMLFrameOwnerElement.h"
+#include "HTMLHeadElement.h"
 #include "HTMLImageLoader.h"
 #include "HTMLInputElement.h"
 #include "HTMLLinkElement.h"
@@ -55,8 +64,8 @@
 #include "HTMLNameCollection.h"
 #include "HTMLNames.h"
 #include "HTMLStyleElement.h"
-#include "HitTestRequest.h"
-#include "HitTestResult.h"
+#include "HTMLTitleElement.h"
+#include "HTTPParsers.h"
 #include "JSEditor.h"
 #include "KeyboardEvent.h"
 #include "Logging.h"
@@ -78,6 +87,7 @@
 #include "StringHash.h"
 #include "StyleSheetList.h"
 #include "SystemTime.h"
+#include "TextEvent.h"
 #include "TextIterator.h"
 #include "TextResourceDecoder.h"
 #include "TreeWalker.h"
 #include "kjs_proxy.h"
 #include "xmlhttprequest.h"
 
-#ifdef XPATH_SUPPORT
+#if ENABLE(XPATH)
 #include "XPathEvaluator.h"
 #include "XPathExpression.h"
 #include "XPathNSResolver.h"
 #include "XPathResult.h"
 #endif
 
-#ifdef XSLT_SUPPORT
+#if ENABLE(XSLT)
 #include "XSLTProcessor.h"
 #endif
 
-#ifdef XBL_SUPPORT
+#if ENABLE(XBL)
 #include "XBLBindingManager.h"
 #endif
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
 #include "SVGDocumentExtensions.h"
 #include "SVGElementFactory.h"
 #include "SVGZoomEvent.h"
 #include "SVGStyleElement.h"
-#include "KSVGTimeScheduler.h"
+#include "TimeScheduler.h"
 #endif
 
 using namespace std;
+using namespace WTF;
+using namespace Unicode;
 
 namespace WebCore {
 
@@ -124,10 +136,10 @@ using namespace HTMLNames;
 // This amount of time must have elapsed before we will even consider scheduling a layout without a delay.
 // FIXME: For faster machines this value can really be lowered to 200.  250 is adequate, but a little high
 // for dual G5s. :)
-const int cLayoutScheduleThreshold = 250;
+static const int cLayoutScheduleThreshold = 250;
 
 // Use 1 to represent the document's default form.
-HTMLFormElement* const defaultForm = (HTMLFormElement*) 1;
+static HTMLFormElement* const defaultForm = reinterpret_cast<HTMLFormElement*>(1);
 
 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
 static const unsigned PHI = 0x9e3779b9U;
@@ -158,8 +170,8 @@ static inline bool isValidNameStart(UChar32 c)
         return true;
 
     // rules (a) and (f) above
-    const uint32_t nameStartMask = U_GC_LL_MASK | U_GC_LU_MASK | U_GC_LO_MASK | U_GC_LT_MASK | U_GC_NL_MASK;
-    if (!(U_GET_GC_MASK(c) & nameStartMask))
+    const uint32_t nameStartMask = Letter_Lowercase | Letter_Uppercase | Letter_Other | Letter_Titlecase | Number_Letter;
+    if (!(Unicode::category(c) & nameStartMask))
         return false;
 
     // rule (c) above
@@ -167,8 +179,8 @@ static inline bool isValidNameStart(UChar32 c)
         return false;
 
     // rule (d) above
-    UDecompositionType decompType = static_cast<UDecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-    if (decompType == U_DT_FONT || decompType == U_DT_COMPAT)
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
         return false;
 
     return true;
@@ -189,8 +201,8 @@ static inline bool isValidNamePart(UChar32 c)
         return true;
 
     // rules (b) and (f) above
-    const uint32_t otherNamePartMask = U_GC_MC_MASK | U_GC_ME_MASK | U_GC_MN_MASK | U_GC_LM_MASK | U_GC_ND_MASK;
-    if (!(U_GET_GC_MASK(c) & otherNamePartMask))
+    const uint32_t otherNamePartMask = Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining | Letter_Modifier | Number_DecimalDigit;
+    if (!(Unicode::category(c) & otherNamePartMask))
         return false;
 
     // rule (c) above
@@ -198,14 +210,62 @@ static inline bool isValidNamePart(UChar32 c)
         return false;
 
     // rule (d) above
-    UDecompositionType decompType = static_cast<UDecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-    if (decompType == U_DT_FONT || decompType == U_DT_COMPAT)
+    DecompositionType decompType = decompositionType(c);
+    if (decompType == DecompositionFont || decompType == DecompositionCompat)
         return false;
 
     return true;
 }
 
-DeprecatedPtrList<Document> * Document::changedDocuments = 0;
+static Widget* widgetForNode(Node* focusedNode)
+  {
+    if (!focusedNode)
+        return 0;
+    RenderObject* renderer = focusedNode->renderer();
+    if (!renderer || !renderer->isWidget())
+        return 0;
+    return static_cast<RenderWidget*>(renderer)->widget();
+}
+
+static bool relinquishesEditingFocus(Node *node)
+{
+    assert(node);
+    assert(node->isContentEditable());
+
+    Node *root = node->rootEditableElement();
+    Frame* frame = node->document()->frame();
+    if (!frame || !root)
+        return false;
+
+    return frame->editor()->shouldEndEditing(rangeOfContents(root).get());
+}
+
+static bool acceptsEditingFocus(Node *node)
+{
+    assert(node);
+    assert(node->isContentEditable());
+
+    Node *root = node->rootEditableElement();
+    Frame* frame = node->document()->frame();
+    if (!frame || !root)
+        return false;
+
+    return frame->editor()->shouldBeginEditing(rangeOfContents(root).get());
+}
+
+static void clearSelectionIfNeeded(Frame* frame, Node* newFocusedNode)
+{
+    if (!frame)
+        return;
+
+    // Clear the selection when changing the focus node to null or to a node that is not 
+    // contained by the current selection.
+    Node* startContainer = frame->selectionController()->start().node();
+    if (!newFocusedNode || (startContainer && startContainer != newFocusedNode && !(startContainer->isDescendantOf(newFocusedNode)) && startContainer->shadowAncestorNode() != newFocusedNode))
+        frame->selectionController()->clear();
+}
+
+DeprecatedPtrList<Document>*  Document::changedDocuments = 0;
 
 // FrameView might be 0
 Document::Document(DOMImplementation* impl, FrameView *v)
@@ -216,18 +276,20 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     , m_title("")
     , m_titleSetExplicitly(false)
     , m_imageLoadEventTimer(this, &Document::imageLoadEventTimerFired)
-#ifdef XBL_SUPPORT
-    , m_bindingManager(new XBLBindingManager(this))
-#endif
-#ifdef XSLT_SUPPORT
+#if ENABLE(XSLT)
     , m_transformSource(0)
 #endif
+    , m_xmlVersion("1.0")
+    , m_xmlStandalone(false)
+#if ENABLE(XBL)
+    , m_bindingManager(new XBLBindingManager(this))
+#endif
     , m_savedRenderer(0)
     , m_passwordFields(0)
     , m_secureForms(0)
     , m_designMode(inherit)
     , m_selfOnlyRefCount(0)
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
     , m_svgExtensions(0)
 #endif
 #if PLATFORM(MAC)
@@ -237,6 +299,7 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     , m_accessKeyMapValid(false)
     , m_createRenderers(true)
     , m_inPageCache(false)
+    , m_isAllowedToLoadLocalResources(false)
 {
     m_document.resetSkippingRef(this);
 
@@ -250,17 +313,16 @@ Document::Document(DOMImplementation* impl, FrameView *v)
     m_docLoader = new DocLoader(v ? v->frame() : 0, this);
 
     visuallyOrdered = false;
-    m_loadingSheet = false;
     m_bParsing = false;
     m_docChanged = false;
     m_tokenizer = 0;
+    m_wellFormed = false;
 
     pMode = Strict;
     hMode = XHtml;
     m_textColor = Color::black;
     m_listenerTypes = 0;
     m_inDocument = true;
-    m_styleSelectorDirty = false;
     m_inStyleRecalc = false;
     m_closeAfterStyleRecalc = false;
     m_usesDescendantRules = false;
@@ -300,7 +362,7 @@ void Document::removedLastRef()
         // we must make sure not to be retaining any of our children through
         // these extra pointers or we will create a reference cycle
         m_docType = 0;
-        m_focusNode = 0;
+        m_focusedNode = 0;
         m_hoverNode = 0;
         m_activeNode = 0;
         m_titleElement = 0;
@@ -319,16 +381,21 @@ void Document::removedLastRef()
 
 Document::~Document()
 {
-    assert(!renderer());
-    assert(!m_inPageCache);
-    assert(m_savedRenderer == 0);
+    ASSERT(!renderer());
+    ASSERT(!m_inPageCache);
+    ASSERT(!m_savedRenderer);
+
+    removeAllEventListeners();
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
     delete m_svgExtensions;
 #endif
 
     XMLHttpRequest::detachRequests(this);
-    KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this);
+    {
+        KJS::JSLock lock;
+        KJS::ScriptInterpreter::forgetAllDOMNodesForDocument(this);
+    }
 
     if (m_docChanged && changedDocuments)
         changedDocuments->remove(this);
@@ -342,11 +409,11 @@ Document::~Document()
         m_renderArena = 0;
     }
 
-#ifdef XSLT_SUPPORT
+#if ENABLE(XSLT)
     xmlFreeDoc((xmlDocPtr)m_transformSource);
 #endif
 
-#ifdef XBL_SUPPORT
+#if ENABLE(XBL)
     delete m_bindingManager;
 #endif
 
@@ -574,17 +641,39 @@ PassRefPtr<Node> Document::adoptNode(PassRefPtr<Node> source, ExceptionCode& ec)
                 source->parentNode()->removeChild(source.get(), ec);
     }
                 
-    for (Node* node = source.get(); node; node = node->traverseNextNode(source.get())) {
-        KJS::ScriptInterpreter::updateDOMNodeDocument(node, node->document(), this);
+    for (Node* node = source.get(); node; node = node->traverseNextNode(source.get()))
         node->setDocument(this);
-    }
 
     return source;
 }
 
+// FIXME: This should really be in a possible ElementFactory class
+PassRefPtr<Element> Document::createElement(const QualifiedName& qName, bool createdByParser, ExceptionCode& ec)
+{
+    RefPtr<Element> e;
+
+    // FIXME: Use registered namespaces and look up in a hash to find the right factory.
+    if (qName.namespaceURI() == xhtmlNamespaceURI)
+        e = HTMLElementFactory::createHTMLElement(qName.localName(), this, 0, createdByParser);
+#if ENABLE(SVG)
+    else if (qName.namespaceURI() == SVGNames::svgNamespaceURI)
+        e = SVGElementFactory::createSVGElement(qName, this, createdByParser);
+#endif
+    
+    if (!e)
+        e = new Element(qName, document());
+    
+    if (e && !qName.prefix().isNull()) {
+        e->setPrefix(qName.prefix(), ec);
+        if (ec)
+            return 0;
+    }    
+    
+    return e.release();
+}
+
 PassRefPtr<Element> Document::createElementNS(const String &_namespaceURI, const String &qualifiedName, ExceptionCode& ec)
 {
-    // FIXME: We'd like a faster code path that skips this check for calls from inside the engine where the name is known to be valid.
     String prefix, localName;
     if (!parseQualifiedName(qualifiedName, prefix, localName)) {
         ec = INVALID_CHARACTER_ERR;
@@ -594,24 +683,7 @@ PassRefPtr<Element> Document::createElementNS(const String &_namespaceURI, const
     RefPtr<Element> e;
     QualifiedName qName = QualifiedName(AtomicString(prefix), AtomicString(localName), AtomicString(_namespaceURI));
     
-    // FIXME: Use registered namespaces and look up in a hash to find the right factory.
-    if (_namespaceURI == xhtmlNamespaceURI) {
-        e = HTMLElementFactory::createHTMLElement(qName.localName(), this, 0, false);
-        if (e && !prefix.isNull()) {
-            e->setPrefix(qName.prefix(), ec);
-            if (ec)
-                return 0;
-        }
-    }
-#ifdef SVG_SUPPORT
-    else if (_namespaceURI == SVGNames::svgNamespaceURI)
-        e = SVGElementFactory::createSVGElement(qName, this, false);
-#endif
-    
-    if (!e)
-        e = new Element(qName, document());
-    
-    return e.release();
+    return createElement(qName, false, ec);
 }
 
 Element *Document::getElementById(const AtomicString& elementId) const
@@ -662,7 +734,7 @@ String Document::inputEncoding() const
 String Document::defaultCharset() const
 {
     if (Frame* f = frame())
-        return f->settings()->encoding();
+        return f->settings()->defaultTextEncodingName();
     return String();
 }
 
@@ -673,6 +745,42 @@ void Document::setCharset(const String& charset)
     decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);
 }
 
+void Document::setXMLVersion(const String& version, ExceptionCode& ec)
+{
+    // FIXME: also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document.
+    if (!implementation()->hasFeature("XML", String())) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+   
+    m_xmlVersion = version;
+}
+
+void Document::setXMLStandalone(bool standalone, ExceptionCode& ec)
+{
+    if (!implementation()->hasFeature("XML", String())) {
+        ec = NOT_SUPPORTED_ERR;
+        return;
+    }
+
+    m_xmlStandalone = standalone;
+}
+
+String Document::documentURI() const
+{
+    return m_baseURL;
+}
+
+void Document::setDocumentURI(const String &uri)
+{
+    m_baseURL = uri.deprecatedString();
+}
+
+String Document::baseURI() const
+{
+    return documentURI();
+}
+
 Element* Document::elementFromPoint(int x, int y) const
 {
     if (!renderer())
@@ -730,14 +838,24 @@ void Document::updateTitle()
         f->loader()->setTitle(m_title);
 }
 
-void Document::setTitle(const String& title, Node* titleElement)
+void Document::setTitle(const String& title, Element* titleElement)
 {
     if (!titleElement) {
         // Title set by JavaScript -- overrides any title elements.
         m_titleSetExplicitly = true;
-        m_titleElement = 0;
+        if (!isHTMLDocument())
+            m_titleElement = 0;
+        else if (!m_titleElement) {
+            if (HTMLElement* headElement = head()) {
+                ExceptionCode ec = 0;
+                m_titleElement = createElement("title", ec);
+                ASSERT(!ec);
+                headElement->appendChild(m_titleElement, ec);
+                ASSERT(!ec);
+            }
+        }
     } else if (titleElement != m_titleElement) {
-        if (m_titleElement)
+        if (m_titleElement || m_titleSetExplicitly)
             // Only allow the first title element to change the title -- others have no effect.
             return;
         m_titleElement = titleElement;
@@ -748,17 +866,30 @@ void Document::setTitle(const String& title, Node* titleElement)
 
     m_title = title;
     updateTitle();
+
+    if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag))
+        static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);
 }
 
-void Document::removeTitle(Node* titleElement)
+void Document::removeTitle(Element* titleElement)
 {
     if (m_titleElement != titleElement)
         return;
 
-    // FIXME: Ideally we might want this to search for the first remaining title element, and use it.
     m_titleElement = 0;
+    m_titleSetExplicitly = false;
+
+    // Update title based on first title element in the head, if one exists.
+    if (HTMLElement* headElement = head()) {
+        for (Node* e = headElement->firstChild(); e; e = e->nextSibling())
+            if (e->hasTagName(titleTag)) {
+                HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);
+                setTitle(titleElement->text(), titleElement);
+                break;
+            }
+    }
 
-    if (!m_title.isEmpty()) {
+    if (!m_titleElement && !m_title.isEmpty()) {
         m_title = "";
         updateTitle();
     }
@@ -774,11 +905,22 @@ Node::NodeType Document::nodeType() const
     return DOCUMENT_NODE;
 }
 
+FrameView* Document::view() const
+{
+    return m_view;
+}
+
 Frame* Document::frame() const 
 {
     return m_view ? m_view->frame() : 0; 
 }
 
+Page* Document::page() const
+{
+    Frame* frame = this->frame();
+    return frame ? frame->page() : 0;    
+}
+
 PassRefPtr<Range> Document::createRange()
 {
     return new Range(this);
@@ -851,7 +993,7 @@ void Document::recalcStyle(StyleChange change)
             const Settings *settings = m_view->frame()->settings();
             if (printing() && !settings->shouldPrintBackgrounds())
                 _style->setForceBackgroundsToWhite(true);
-            const AtomicString& stdfont = settings->stdFontName();
+            const AtomicString& stdfont = settings->standardFontFamily();
             if (!stdfont.isEmpty()) {
                 fontDescription.firstFamily().setFamily(stdfont);
                 fontDescription.firstFamily().appendFamily(0);
@@ -993,7 +1135,7 @@ void Document::detach()
     m_imageLoadEventDispatchingList.clear();
     
     m_hoverNode = 0;
-    m_focusNode = 0;
+    m_focusedNode = 0;
     m_activeNode = 0;
 
     ContainerNode::detach();
@@ -1090,10 +1232,10 @@ void Document::updateSelection()
         // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
         // and will fill the gap before 'bar'.
         Position startPos = selection.visibleStart().deepEquivalent();
-        if (startPos.downstream().inRenderedContent())
+        if (startPos.downstream().isCandidate())
             startPos = startPos.downstream();
         Position endPos = selection.visibleEnd().deepEquivalent();
-        if (endPos.upstream().inRenderedContent())
+        if (endPos.upstream().isCandidate())
             endPos = endPos.upstream();
         
         // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
@@ -1115,9 +1257,9 @@ void Document::updateSelection()
 #endif
 }
 
-Tokenizer *Document::createTokenizer()
+TokenizerDocument::createTokenizer()
 {
-    return newXMLTokenizer(this, m_view);
+    return new XMLTokenizer(this, m_view);
 }
 
 void Document::open()
@@ -1128,9 +1270,6 @@ void Document::open()
         setURL(parent->baseURL());
         setBaseURL(parent->baseURL());
     }
-    else
-        setURL(DeprecatedString());
-        
 
     if ((frame() && frame()->loader()->isLoadingMainResource()) || (tokenizer() && tokenizer()->executingScript()))
         return;
@@ -1165,7 +1304,7 @@ void Document::implicitOpen()
 
 HTMLElement* Document::body()
 {
-    Node *de = documentElement();
+    Nodede = documentElement();
     if (!de)
         return 0;
     
@@ -1178,7 +1317,20 @@ HTMLElement* Document::body()
         if (i->hasTagName(bodyTag))
             body = i;
     }
-    return static_cast<HTMLElement *>(body);
+    return static_cast<HTMLElement*>(body);
+}
+
+HTMLHeadElement* Document::head()
+{
+    Node* de = documentElement();
+    if (!de)
+        return 0;
+
+    for (Node* e = de->firstChild(); e; e = e->nextSibling())
+        if (e->hasTagName(headTag))
+            return static_cast<HTMLHeadElement*>(e);
+
+    return 0;
 }
 
 void Document::close()
@@ -1204,6 +1356,8 @@ void Document::implicitClose()
 
     m_processingLoadEvent = true;
 
+    m_wellFormed = m_tokenizer && m_tokenizer->wellFormed();
+
     // We have to clear the tokenizer, in case someone document.write()s from the
     // onLoad event handler, as in Radar 3206524.
     delete m_tokenizer;
@@ -1235,19 +1389,22 @@ void Document::implicitClose()
 
     m_processingLoadEvent = false;
 
+    // An event handler may have removed the frame
+    if (!frame())
+        return;
+
     // Make sure both the initial layout and reflow happen after the onload
     // fires. This will improve onload scores, and other browsers do it.
     // If they wanna cheat, we can too. -dwh
 
-    if (frame() && frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
+    if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
         // Just bail out. Before or during the onload we were shifted to another page.
         // The old i-Bench suite does this. When this happens don't bother painting or laying out.        
         view()->unscheduleRelayout();
         return;
     }
 
-    if (frame())
-        frame()->loader()->checkEmitLoadEvent();
+    frame()->loader()->checkEmitLoadEvent();
 
     // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
     // that has been sized already.  Otherwise, our view size would be incorrect, so doing any 
@@ -1265,7 +1422,7 @@ void Document::implicitClose()
         axObjectCache()->postNotificationToElement(renderer(), "AXLoadComplete");
 #endif
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
     // FIXME: Officially, time 0 is when the outermost <svg> receives its
     // SVGLoad event, but we don't implement those yet.  This is close enough
     // for now.  In some cases we should have fired earlier.
@@ -1375,16 +1532,43 @@ void Document::clear()
 
 void Document::setURL(const DeprecatedString& url)
 {
+    if (url == m_url)
+        return;
+
     m_url = url;
     if (m_styleSelector)
         m_styleSelector->setEncodedURL(m_url);
+
+    m_isAllowedToLoadLocalResources = shouldBeAllowedToLoadLocalResources();
+ }
+bool Document::shouldBeAllowedToLoadLocalResources() const
+{
+    if (FrameLoader::shouldTreatURLAsLocal(m_url))
+        return true;
+
+    Frame* frame = this->frame();
+    if (!frame)
+        return false;
+    
+    DocumentLoader* documentLoader = frame->loader()->documentLoader();
+    if (!documentLoader)
+        return false;
+    
+    return documentLoader->substituteData().isValid();
+}
+
+void Document::setBaseURL(const DeprecatedString& baseURL) 
+{ 
+    m_baseURL = baseURL; 
+    if (m_elemSheet)
+        m_elemSheet->setHref(m_baseURL);
 }
 
 void Document::setCSSStyleSheet(const String &url, const String& charset, const String &sheet)
 {
     m_sheet = new CSSStyleSheet(this, url, charset);
     m_sheet->parseString(sheet);
-    m_loadingSheet = false;
 
     updateStyleSelector();
 }
@@ -1412,178 +1596,103 @@ void Document::determineParseMode(const String&)
     hMode = XHtml;
 }
 
-Node* Document::nextFocusNode(Node* fromNode)
+static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
 {
-    unsigned short fromTabIndex;
-
-    if (!fromNode) {
-        // No starting node supplied; begin with the top of the document
-
-        int lowestTabIndex = 65535;
-        for (Node* n = this; n; n = n->traverseNextNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() > 0 && n->tabIndex() < lowestTabIndex)
-                    lowestTabIndex = n->tabIndex();
-
-        if (lowestTabIndex == 65535)
-            lowestTabIndex = 0;
-
-        // Go to the first node in the document that has the desired tab index
-        for (Node* n = this; n; n = n->traverseNextNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == lowestTabIndex)
-                return n;
-
-        return 0;
-    }
-
-    fromTabIndex = fromNode->tabIndex();
-
-    if (fromTabIndex == 0) {
-        // Just need to find the next selectable node after fromNode (in document order) that has a tab index of 0
-        Node* n;
-        for (n = fromNode->traverseNextNode(); n; n = n->traverseNextNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == 0)
-                break;
-        
-        return n;
-    }
-    
-    // Find the lowest tab index out of all the nodes except fromNode, that is greater than or equal to fromNode's
-    // tab index. For nodes with the same tab index as fromNode, we are only interested in those that come after
-    // fromNode in document order.
-    // If we don't find a suitable tab index, the next focus node will be one with a tab index of 0.
-    unsigned short lowestSuitableTabIndex = 65535;
-
-    bool reachedFromNode = false;
-    for (Node* n = this; n; n = n->traverseNextNode()) {
-        if (n == fromNode)
-            reachedFromNode = true;
-        else if (n->isKeyboardFocusable()
-                 && ((reachedFromNode && n->tabIndex() >= fromTabIndex)
-                     || (!reachedFromNode && n->tabIndex() > fromTabIndex)))
-            // We found a selectable node with a tab index at least as high as fromNode's. Keep searching though,
-            // as there may be another node which has a lower tab index but is still suitable for use.
-            lowestSuitableTabIndex = min(lowestSuitableTabIndex, n->tabIndex());
-    }
-
-    if (lowestSuitableTabIndex == 65535) {
-        // No next node with a tab index -> just take first node with tab index of 0
-        Node* n;
-        for (n = this; n; n = n->traverseNextNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == 0)
-                break;
-        
-        return n;
-    }
-
-    // Search forwards from fromNode
-    for (Node* n = fromNode->traverseNextNode(); n; n = n->traverseNextNode())
-        if (n->isKeyboardFocusable() && n->tabIndex() == lowestSuitableTabIndex)
+    // Search is inclusive of start
+    for (Node* n = start; n; n = n->traverseNextNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
             return n;
+    
+    return 0;
+}
 
-    // The next node isn't after fromNode, start from the beginning of the document
-    for (Node* n = this; n != fromNode; n = n->traverseNextNode())
-        if (n->isKeyboardFocusable() && n->tabIndex() == lowestSuitableTabIndex)
+static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+    // Search is inclusive of start
+    for (Node* n = start; n; n = n->traversePreviousNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
             return n;
-
-    ASSERT_NOT_REACHED();
+    
     return 0;
 }
 
-Node* Document::previousFocusNode(Node* fromNode)
+static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
 {
-    Node* lastNode;
-    for (lastNode = this; lastNode->lastChild(); lastNode = lastNode->lastChild());
+    // Search is inclusive of start
+    int winningTabIndex = SHRT_MAX + 1;
+    Node* winner = 0;
+    for (Node* n = start; n; n = n->traverseNextNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
+            winner = n;
+            winningTabIndex = n->tabIndex();
+        }
     
-    if (!fromNode) {
-        // No starting node supplied; begin with the very last node in the document
+    return winner;
+}
 
-        int highestTabIndex = 0;
-        for (Node* n = lastNode; n; n = n->traversePreviousNode()) {
-            if (n->isKeyboardFocusable()) {
-                if (n->tabIndex() == 0)
-                    return n;
-                else if (n->tabIndex() > highestTabIndex)
-                    highestTabIndex = n->tabIndex();
-            }
+static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+    // Search is inclusive of start
+    int winningTabIndex = 0;
+    Node* winner = 0;
+    for (Node* n = start; n; n = n->traversePreviousNode())
+        if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) {
+            winner = n;
+            winningTabIndex = n->tabIndex();
         }
-
-        // No node with a tab index of 0; just go to the last node with the highest tab index
-        for (Node* n = lastNode; n; n = n->traversePreviousNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == highestTabIndex)
-                return n;
-
-        return 0;
-    }
     
-    unsigned short fromTabIndex = fromNode->tabIndex();
-
-    if (fromTabIndex == 0) {
-        // Find the previous selectable node before fromNode (in document order) that has a tab index of 0
-        Node* n;
-        for (n = fromNode->traversePreviousNode(); n; n = n->traversePreviousNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == 0)
-                break;
-        
-        if (n)
-            return n;
+    return winner;
+}
 
-        // No previous nodes with a 0 tab index, go to the last node in the document that has the highest tab index
-        int highestTabIndex = 0;
-        for (n = this; n; n = n->traverseNextNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() > highestTabIndex)
-                highestTabIndex = n->tabIndex();
+Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event)
+{
+    if (start) {
+        // First try to find a node with the same tabindex as start that comes after start in the document.
+        if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
+            return winner;
 
-        if (!highestTabIndex)
+        if (start->tabIndex() == 0)
+            // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
             return 0;
-
-        for (n = lastNode; n; n = n->traversePreviousNode())
-            if (n->isKeyboardFocusable() && n->tabIndex() == highestTabIndex)
-                return n;
-
-        ASSERT_NOT_REACHED();
-        return 0;
     }
-    
-    // Find the lowest tab index out of all the nodes except fromNode, that is less than or equal to fromNode's
-    // tab index. For nodes with the same tab index as fromNode, we are only interested in those before
-    // fromNode.
-    // If we don't find a suitable tab index, then there will be no previous focus node.
-    unsigned short highestSuitableTabIndex = 0;
 
-    bool reachedFromNode = false;
-    for (Node* n = this; n; n = n->traverseNextNode()) {
-        if (n->isKeyboardFocusable() &&
-            ((!reachedFromNode && (n->tabIndex() <= fromTabIndex)) ||
-             (reachedFromNode && (n->tabIndex() < fromTabIndex)))  &&
-            (n->tabIndex() > highestSuitableTabIndex) &&
-            (n != fromNode)) {
+    // Look for the first node in the document that:
+    // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
+    // 2) comes first in the document, if there's a tie.
+    if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event))
+        return winner;
 
-            // We found a selectable node with a tab index no higher than fromNode's. Keep searching though, as
-            // there may be another node which has a higher tab index but is still suitable for use.
-            highestSuitableTabIndex = n->tabIndex();
-        }
+    // There are no nodes with a tabindex greater than start's tabindex,
+    // so find the first node with a tabindex of 0.
+    return nextNodeWithExactTabIndex(this, 0, event);
+}
 
-        if (n == fromNode)
-            reachedFromNode = true;
-    }
+Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event)
+{
+    Node* last;
+    for (last = this; last->lastChild(); last = last->lastChild())
+        ; // Empty loop.
 
-    if (highestSuitableTabIndex == 0)
-        // No previous node with a tab index. Since the order specified by HTML is nodes with tab index > 0
-        // first, this means that there is no previous node.
-        return 0;
+    // First try to find the last node in the document that comes before start and has the same tabindex as start.
+    // If start is null, find the last node in the document with a tabindex of 0.
+    Node* startingNode;
+    int startingTabIndex;
+    if (start) {
+        startingNode = start->traversePreviousNode();
+        startingTabIndex = start->tabIndex();
+    } else {
+        startingNode = last;
+        startingTabIndex = 0;
+    }
 
-    // Search backwards from fromNode
-    for (Node* n = fromNode->traversePreviousNode(); n; n = n->traversePreviousNode())
-        if (n->isKeyboardFocusable() && (n->tabIndex() == highestSuitableTabIndex))
-            return n;
-    
-    // The previous node isn't before fromNode, start from the end of the document
-    for (Node* n = lastNode; n != fromNode; n = n->traversePreviousNode())
-        if (n->isKeyboardFocusable() && (n->tabIndex() == highestSuitableTabIndex))
-            return n;
+    if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event))
+        return winner;
 
-    ASSERT_NOT_REACHED();
-    return 0;
+    // There are no nodes before start with the same tabindex as start, so look for a node that:
+    // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
+    // 2) comes last in the document, if there's a tie.
+    startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX;
+    return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
 }
 
 int Document::nodeAbsIndex(Node *node)
@@ -1622,37 +1731,14 @@ void Document::processHttpEquiv(const String &equiv, const String &content)
         m_preferredStylesheetSet = content;
         updateStyleSelector();
     } else if (equalIgnoringCase(equiv, "refresh")) {
-        // get delay and url
-        DeprecatedString str = content.stripWhiteSpace().deprecatedString();
-        int pos = str.find(RegularExpression("[;,]"));
-        if (pos == -1)
-            pos = str.find(RegularExpression("[ \t]"));
-
-        if (pos == -1) // There can be no url (David)
-        {
-            bool ok = false;
-            int delay = 0;
-            delay = str.toInt(&ok);
-            // We want a new history item if the refresh timeout > 1 second
-            if (ok && frame)
+        double delay;
+        String url;
+        if (frame && parseHTTPRefresh(content, true, delay, url)) {
+            if (url.isEmpty())
                 frame->loader()->scheduleRedirection(delay, frame->loader()->url().url(), delay <= 1);
-        } else {
-            double delay = 0;
-            bool ok = false;
-            delay = str.left(pos).stripWhiteSpace().toDouble(&ok);
-
-            pos++;
-            while(pos < (int)str.length() && str[pos].isSpace()) pos++;
-            str = str.mid(pos);
-            if (str.find("url", 0,  false) == 0)
-                str = str.mid(3);
-            str = str.stripWhiteSpace();
-            if (str.length() && str[0] == '=')
-                str = str.mid(1).stripWhiteSpace();
-            str = parseURL(String(str)).deprecatedString();
-            if (ok && frame)
+            else
                 // We want a new history item if the refresh timeout > 1 second
-                frame->loader()->scheduleRedirection(delay, completeURL(str), delay <= 1);
+                frame->loader()->scheduleRedirection(delay, completeURL(url), delay <= 1);
         }
     } else if (equalIgnoringCase(equiv, "expires")) {
         String str = content.stripWhiteSpace();
@@ -1665,22 +1751,21 @@ void Document::processHttpEquiv(const String &equiv, const String &content)
     }
 }
 
-MouseEventWithHitTestResults Document::prepareMouseEvent(bool readonly, bool active, bool mouseMove,
-                                                         const IntPoint& point, const PlatformMouseEvent& event)
+MouseEventWithHitTestResults Document::prepareMouseEvent(const HitTestRequest& request, const IntPoint& documentPoint, const PlatformMouseEvent& event)
 {
+    ASSERT(!renderer() || renderer()->isRenderView());
+
     if (!renderer())
-        return MouseEventWithHitTestResults(event, 0, 0, false);
+        return MouseEventWithHitTestResults(event, 0, IntPoint(), 0, false);
 
-    assert(renderer()->isRenderView());
-    HitTestRequest request(readonly, active, mouseMove);
-    HitTestResult result(point);
+    HitTestResult result(documentPoint);
     renderer()->layer()->hitTest(request, result);
 
-    if (!readonly)
+    if (!request.readonly)
         updateRendering();
 
-    bool isOverLink = result.URLElement() && !result.URLElement()->getAttribute(hrefAttr).isNull();
-    return MouseEventWithHitTestResults(event, result.innerNode(), result.scrollbar(), isOverLink);
+    bool isOverLink = result.URLElement() && result.URLElement()->isLink();
+    return MouseEventWithHitTestResults(event, result.innerNode(), result.localPoint(), result.scrollbar(), isOverLink);
 }
 
 // DOM Section 1.1.1
@@ -1712,6 +1797,87 @@ bool Document::childTypeAllowed(NodeType type)
     return false;
 }
 
+bool Document::canReplaceChild(Node* newChild, Node* oldChild)
+{
+    if (oldChild->nodeType() == newChild->nodeType())
+        return true;
+
+    int numDoctypes = 0;
+    int numElements = 0;
+
+    // First, check how many doctypes and elements we have, not counting
+    // the child we're about to remove.
+    for (Node* c = firstChild(); c; c = c->nextSibling()) {
+        if (c == oldChild)
+            continue;
+        
+        switch (c->nodeType()) {
+            case DOCUMENT_TYPE_NODE:
+                numDoctypes++;
+                break;
+            case ELEMENT_NODE:
+                numElements++;
+                break;
+            default:
+                break;
+        }
+    }
+    
+    // Then, see how many doctypes and elements might be added by the new child.
+    if (newChild->nodeType() == DOCUMENT_FRAGMENT_NODE) {
+        for (Node* c = firstChild(); c; c = c->nextSibling()) {
+            switch (c->nodeType()) {
+                case ATTRIBUTE_NODE:
+                case CDATA_SECTION_NODE:
+                case DOCUMENT_FRAGMENT_NODE:
+                case DOCUMENT_NODE:
+                case ENTITY_NODE:
+                case ENTITY_REFERENCE_NODE:
+                case NOTATION_NODE:
+                case TEXT_NODE:
+                case XPATH_NAMESPACE_NODE:
+                    return false;
+                case COMMENT_NODE:
+                case PROCESSING_INSTRUCTION_NODE:
+                    break;
+                case DOCUMENT_TYPE_NODE:
+                    numDoctypes++;
+                    break;
+                case ELEMENT_NODE:
+                    numElements++;
+                    break;
+            }
+        }
+    } else {
+        switch (newChild->nodeType()) {
+            case ATTRIBUTE_NODE:
+            case CDATA_SECTION_NODE:
+            case DOCUMENT_FRAGMENT_NODE:
+            case DOCUMENT_NODE:
+            case ENTITY_NODE:
+            case ENTITY_REFERENCE_NODE:
+            case NOTATION_NODE:
+            case TEXT_NODE:
+            case XPATH_NAMESPACE_NODE:
+                return false;
+            case COMMENT_NODE:
+            case PROCESSING_INSTRUCTION_NODE:
+                return true;
+            case DOCUMENT_TYPE_NODE:
+                numDoctypes++;
+                break;
+            case ELEMENT_NODE:
+                numElements++;
+                break;
+        }                
+    }
+        
+    if (numElements > 1 || numDoctypes > 1)
+        return false;
+    
+    return true;
+}
+
 PassRefPtr<Node> Document::cloneNode(bool /*deep*/)
 {
     // Spec says cloning Document nodes is "implementation dependent"
@@ -1755,7 +1921,7 @@ void Document::stylesheetLoaded()
         printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
 #endif
 
-    updateStyleSelector();    
+    updateStyleSelector();
 }
 
 void Document::updateStyleSelector()
@@ -1806,7 +1972,7 @@ void Document::recalcStyleSelector()
             // Processing instruction (XML documents only)
             ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
             sheet = pi->sheet();
-#ifdef XSLT_SUPPORT
+#if ENABLE(XSLT)
             // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
             if (pi->isXSL() && !transformSourceDocument()) {
                 // Don't apply XSL transforms until loading is finished.
@@ -1837,9 +2003,12 @@ void Document::recalcStyleSelector()
                 }
             }
 
-        }
-        else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))) {
-            HTMLElement *e = static_cast<HTMLElement *>(n);
+        } else if (n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag))
+#if ENABLE(SVG)
+            ||  (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
+#endif
+        ) {
+            Element* e = static_cast<Element*>(n);
             DeprecatedString title = e->getAttribute(titleAttr).deprecatedString();
             bool enabledViaScript = false;
             if (e->hasLocalName(linkTag)) {
@@ -1854,6 +2023,11 @@ void Document::recalcStyleSelector()
 
             // Get the current preferred styleset.  This is the
             // set of sheets that will be enabled.
+#if ENABLE(SVG)
+            if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
+                sheet = static_cast<SVGStyleElement*>(n)->sheet();
+            else
+#endif
             if (e->hasLocalName(linkTag))
                 sheet = static_cast<HTMLLinkElement*>(n)->sheet();
             else
@@ -1877,30 +2051,13 @@ void Document::recalcStyleSelector()
                 
                 if (title != m_preferredStylesheetSet)
                     sheet = 0;
-            }
-        }
-#ifdef SVG_SUPPORT
-        else if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag)) {
-            DeprecatedString title;
-            // <STYLE> element
-            SVGStyleElement *s = static_cast<SVGStyleElement*>(n);
-            if (!s->isLoading()) {
-                sheet = s->sheet();
-                if(sheet)
-                    title = s->getAttribute(SVGNames::titleAttr).deprecatedString();
-            }
-
-            if (!title.isEmpty() && m_preferredStylesheetSet.isEmpty())
-                m_preferredStylesheetSet = m_selectedStylesheetSet = title;
 
-            if (!title.isEmpty()) {
-                if (title != m_preferredStylesheetSet)
-                    sheet = 0; // don't use it
-
-                title = title.replace('&', "&&");
-            }
-       }
+#if ENABLE(SVG)
+                if (!n->isHTMLElement())
+                    title = title.replace('&', "&&");
 #endif
+            }
+        }
 
         if (sheet) {
             sheet->ref();
@@ -1925,7 +2082,6 @@ void Document::recalcStyleSelector()
         usersheet += m_printSheet;
     m_styleSelector = new CSSStyleSelector(this, usersheet, m_styleSheets.get(), !inCompatMode());
     m_styleSelector->setEncodedURL(m_url);
-    m_styleSelectorDirty = false;
 }
 
 void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
@@ -1938,6 +2094,11 @@ void Document::setActiveNode(PassRefPtr<Node> newActiveNode)
     m_activeNode = newActiveNode;
 }
 
+void Document::focusedNodeRemoved(Node* node)
+{
+    setFocusedNode(0);
+}
+
 void Document::hoveredNodeDetached(Node* node)
 {
     if (!m_hoverNode || (node != m_hoverNode && (!m_hoverNode->isTextNode() || node != m_hoverNode->parent())))
@@ -1946,8 +2107,8 @@ void Document::hoveredNodeDetached(Node* node)
     m_hoverNode = node->parent();
     while (m_hoverNode && !m_hoverNode->renderer())
         m_hoverNode = m_hoverNode->parent();
-    if (view())
-        view()->scheduleHoverStateUpdate();
+    if (frame())
+        frame()->eventHandler()->scheduleHoverStateUpdate();
 }
 
 void Document::activeChainNodeDetached(Node* node)
@@ -1960,47 +2121,8 @@ void Document::activeChainNodeDetached(Node* node)
         m_activeNode = m_activeNode->parent();
 }
 
-bool Document::relinquishesEditingFocus(Node *node)
-{
-    assert(node);
-    assert(node->isContentEditable());
-
-    Node *root = node->rootEditableElement();
-    if (!frame() || !root)
-        return false;
-
-    return frame()->shouldEndEditing(rangeOfContents(root).get());
-}
-
-bool Document::acceptsEditingFocus(Node *node)
-{
-    assert(node);
-    assert(node->isContentEditable());
-
-    Node *root = node->rootEditableElement();
-    if (!frame() || !root)
-        return false;
-
-    return frame()->shouldBeginEditing(rangeOfContents(root).get());
-}
-
-void Document::didBeginEditing()
-{
-    if (!frame())
-        return;
-    
-    frame()->didBeginEditing();
-}
-
-void Document::didEndEditing()
-{
-    if (!frame())
-        return;
-    
-    frame()->didEndEditing();
-}
-
 #if PLATFORM(MAC)
+
 const Vector<DashboardRegionValue>& Document::dashboardRegions() const
 {
     return m_dashboardRegions;
@@ -2011,112 +2133,100 @@ void Document::setDashboardRegions(const Vector<DashboardRegionValue>& regions)
     m_dashboardRegions = regions;
     setDashboardRegionsDirty(false);
 }
-#endif
 
-static Widget *widgetForNode(Node *focusNode)
-{
-    if (!focusNode)
-        return 0;
-    RenderObject *renderer = focusNode->renderer();
-    if (!renderer || !renderer->isWidget())
-        return 0;
-    return static_cast<RenderWidget*>(renderer)->widget();
-}
+#endif
 
-bool Document::setFocusNode(PassRefPtr<Node> newFocusNode)
+bool Document::setFocusedNode(PassRefPtr<Node> newFocusedNode)
 {    
-    // Make sure newFocusNode is actually in this document
-    if (newFocusNode && (newFocusNode->document() != this))
+    // Make sure newFocusedNode is actually in this document
+    if (newFocusedNode && (newFocusedNode->document() != this))
         return true;
 
-    if (m_focusNode == newFocusNode)
+    if (m_focusedNode == newFocusedNode)
         return true;
 
-    if (m_focusNode && m_focusNode.get() == m_focusNode->rootEditableElement() && !relinquishesEditingFocus(m_focusNode.get()))
-        return false;
+    if (m_focusedNode && m_focusedNode.get() == m_focusedNode->rootEditableElement() && !relinquishesEditingFocus(m_focusedNode.get()))
+          return false;
         
     bool focusChangeBlocked = false;
-    RefPtr<Node> oldFocusNode = m_focusNode;
-    m_focusNode = 0;
-    clearSelectionIfNeeded(newFocusNode.get());
+    RefPtr<Node> oldFocusedNode = m_focusedNode;
+    m_focusedNode = 0;
+    clearSelectionIfNeeded(frame(), newFocusedNode.get());
 
     // Remove focus from the existing focus node (if any)
-    if (oldFocusNode && !oldFocusNode->m_inDetach) { 
-        if (oldFocusNode->active())
-            oldFocusNode->setActive(false);
+    if (oldFocusedNode && !oldFocusedNode->m_inDetach) { 
+        if (oldFocusedNode->active())
+            oldFocusedNode->setActive(false);
 
-        oldFocusNode->setFocus(false);
+        oldFocusedNode->setFocus(false);
                 
         // Dispatch a change event for text fields or textareas that have been edited
-        RenderObject *r = static_cast<RenderObject*>(oldFocusNode.get()->renderer());
+        RenderObject *r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer());
         if (r && (r->isTextArea() || r->isTextField()) && r->isEdited()) {
-            EventTargetNodeCast(oldFocusNode.get())->dispatchHTMLEvent(changeEvent, true, false);
-            if ((r = static_cast<RenderObject*>(oldFocusNode.get()->renderer())))
+            EventTargetNodeCast(oldFocusedNode.get())->dispatchHTMLEvent(changeEvent, true, false);
+            if ((r = static_cast<RenderObject*>(oldFocusedNode.get()->renderer())))
                 r->setEdited(false);
         }
 
         // Dispatch the blur event and let the node do any other blur related activities (important for text fields)
-        EventTargetNodeCast(oldFocusNode.get())->dispatchBlurEvent();
+        EventTargetNodeCast(oldFocusedNode.get())->dispatchBlurEvent();
 
-        if (m_focusNode) {
+        if (m_focusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            newFocusNode = 0;
+            newFocusedNode = 0;
         }
-        clearSelectionIfNeeded(newFocusNode.get());
-        EventTargetNodeCast(oldFocusNode.get())->dispatchUIEvent(DOMFocusOutEvent);
-        if (m_focusNode) {
+        clearSelectionIfNeeded(frame(), newFocusedNode.get());
+        EventTargetNodeCast(oldFocusedNode.get())->dispatchUIEvent(DOMFocusOutEvent);
+        if (m_focusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            newFocusNode = 0;
+            newFocusedNode = 0;
         }
-        clearSelectionIfNeeded(newFocusNode.get());
-        if ((oldFocusNode.get() == this) && oldFocusNode->hasOneRef())
+        clearSelectionIfNeeded(frame(), newFocusedNode.get());
+        if ((oldFocusedNode.get() == this) && oldFocusedNode->hasOneRef())
             return true;
             
-        if (oldFocusNode.get() == oldFocusNode->rootEditableElement())
-            didEndEditing();
+        if (oldFocusedNode.get() == oldFocusedNode->rootEditableElement())
+            frame()->editor()->didEndEditing();
     }
 
-    if (newFocusNode) {
-        if (newFocusNode == newFocusNode->rootEditableElement() && !acceptsEditingFocus(newFocusNode.get())) {
+    if (newFocusedNode) {
+        if (newFocusedNode == newFocusedNode->rootEditableElement() && !acceptsEditingFocus(newFocusedNode.get())) {
             // delegate blocks focus change
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
         // Set focus on the new node
-        m_focusNode = newFocusNode.get();
+        m_focusedNode = newFocusedNode.get();
 
         // Dispatch the focus event and let the node do any other focus related activities (important for text fields)
-        EventTargetNodeCast(m_focusNode.get())->dispatchFocusEvent();
+        EventTargetNodeCast(m_focusedNode.get())->dispatchFocusEvent();
 
-        if (m_focusNode != newFocusNode) {
+        if (m_focusedNode != newFocusedNode) {
             // handler shifted focus
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
-        EventTargetNodeCast(m_focusNode.get())->dispatchUIEvent(DOMFocusInEvent);
-        if (m_focusNode != newFocusNode) { 
+        EventTargetNodeCast(m_focusedNode.get())->dispatchUIEvent(DOMFocusInEvent);
+        if (m_focusedNode != newFocusedNode) { 
             // handler shifted focus
             focusChangeBlocked = true;
-            goto SetFocusNodeDone;
+            goto SetFocusedNodeDone;
         }
-        m_focusNode->setFocus();
-        
-        if (m_focusNode.get() == m_focusNode->rootEditableElement())
-            didBeginEditing();
-        
+        m_focusedNode->setFocus();
+
         // eww, I suck. set the qt focus correctly
         // ### find a better place in the code for this
         if (view()) {
-            Widget *focusWidget = widgetForNode(m_focusNode.get());
+            Widget *focusWidget = widgetForNode(m_focusedNode.get());
             if (focusWidget) {
                 // Make sure a widget has the right size before giving it focus.
                 // Otherwise, we are testing edge cases of the Widget code.
                 // Specifically, in WebCore this does not work well for text fields.
                 updateLayout();
                 // Re-get the widget in case updating the layout changed things.
-                focusWidget = widgetForNode(m_focusNode.get());
+                focusWidget = widgetForNode(m_focusedNode.get());
             }
             if (focusWidget)
                 focusWidget->setFocus();
@@ -2126,27 +2236,15 @@ bool Document::setFocusNode(PassRefPtr<Node> newFocusNode)
    }
 
 #if PLATFORM(MAC)
-    if (!focusChangeBlocked && m_focusNode && AXObjectCache::accessibilityEnabled())
+    if (!focusChangeBlocked && m_focusedNode && AXObjectCache::accessibilityEnabled())
         axObjectCache()->handleFocusedUIElementChanged();
 #endif
 
-SetFocusNodeDone:
+SetFocusedNodeDone:
     updateRendering();
     return !focusChangeBlocked;
-}
-
-void Document::clearSelectionIfNeeded(Node *newFocusNode)
-{
-    if (!frame())
-        return;
-
-    // Clear the selection when changing the focus node to null or to a node that is not 
-    // contained by the current selection.
-    Node *startContainer = frame()->selectionController()->start().node();
-    if (!newFocusNode || (startContainer && startContainer != newFocusNode && !(startContainer->isDescendantOf(newFocusNode)) && startContainer->shadowAncestorNode() != newFocusNode))
-        frame()->selectionController()->clear();
-}
-
+  }
+  
 void Document::setCSSTarget(Node* n)
 {
     if (m_cssTarget)
@@ -2163,7 +2261,7 @@ Node* Document::getCSSTarget() const
 
 void Document::attachNodeIterator(NodeIterator *ni)
 {
-    m_nodeIterators.append(ni);
+    m_nodeIterators.add(ni);
 }
 
 void Document::detachNodeIterator(NodeIterator *ni)
@@ -2177,9 +2275,10 @@ void Document::notifyBeforeNodeRemoval(Node *n)
         f->selectionController()->nodeWillBeRemoved(n);
         f->dragCaretController()->nodeWillBeRemoved(n);
     }
-    DeprecatedPtrListIterator<NodeIterator> it(m_nodeIterators);
-    for (; it.current(); ++it)
-        it.current()->notifyBeforeNodeRemoval(n);
+
+    HashSet<NodeIterator*>::const_iterator end = m_nodeIterators.end();
+    for (HashSet<NodeIterator*>::const_iterator it = m_nodeIterators.begin(); it != end; ++it)
+        (*it)->notifyBeforeNodeRemoval(n);
 }
 
 DOMWindow* Document::defaultView() const
@@ -2193,20 +2292,22 @@ DOMWindow* Document::defaultView() const
 PassRefPtr<Event> Document::createEvent(const String &eventType, ExceptionCode& ec)
 {
     if (eventType == "UIEvents" || eventType == "UIEvent")
-        return new UIEvent();
+        return new UIEvent;
     if (eventType == "MouseEvents" || eventType == "MouseEvent")
-        return new MouseEvent();
+        return new MouseEvent;
     if (eventType == "MutationEvents" || eventType == "MutationEvent")
-        return new MutationEvent();
+        return new MutationEvent;
     if (eventType == "KeyboardEvents" || eventType == "KeyboardEvent")
-        return new KeyboardEvent();
+        return new KeyboardEvent;
     if (eventType == "HTMLEvents" || eventType == "Event" || eventType == "Events")
-        return new Event();
-#ifdef SVG_SUPPORT
+        return new Event;
+    if (eventType == "TextEvent")
+        return new TextEvent;
+#if ENABLE(SVG)
     if (eventType == "SVGEvents")
-        return new Event();
+        return new Event;
     if (eventType == "SVGZoomEvents")
-        return new SVGZoomEvent();
+        return new SVGZoomEvent;
 #endif
     ec = NOT_SUPPORTED_ERR;
     return 0;
@@ -2244,9 +2345,12 @@ void Document::defaultEventHandler(Event *evt)
             if (elem) {
                 elem->accessKeyAction(false);
                 evt->setDefaultHandled();
+                return;
             }
         }
     }
+
+    ContainerNode::defaultEventHandler(evt);
 }
 
 void Document::setHTMLWindowEventListener(const AtomicString &eventType, PassRefPtr<EventListener> listener)
@@ -2366,7 +2470,7 @@ void Document::imageLoadEventTimerFired(Timer<Document>*)
     dispatchImageLoadEventsNow();
 }
 
-Element *Document::ownerElement() const
+ElementDocument::ownerElement() const
 {
     if (!frame())
         return 0;
@@ -2502,8 +2606,9 @@ HTMLMapElement *Document::getImageMap(const String& URL) const
     if (URL.isNull())
         return 0;
     int hashPos = URL.find('#');
-    AtomicString name = (hashPos < 0 ? URL : URL.substring(hashPos + 1)).impl();
-    return m_imageMapsByName.get(name.impl());
+    String name = (hashPos < 0 ? URL : URL.substring(hashPos + 1)).impl();
+    AtomicString mapName = hMode == XHtml ? name : name.lower();
+    return m_imageMapsByName.get(mapName.impl());
 }
 
 void Document::setDecoder(TextResourceDecoder *decoder)
@@ -2704,17 +2809,17 @@ void Document::addMarker(Node *node, DocumentMarker newMarker)
         Vector<DocumentMarker>& markers = vectorPair->first;
         Vector<IntRect>& rects = vectorPair->second;
         ASSERT(markers.size() == rects.size());
-        Vector<DocumentMarker>::iterator it;
-        for (it = markers.begin(); it != markers.end();) {
-            DocumentMarker marker = *it;
+        size_t i;
+        for (i = 0; i != markers.size();) {
+            DocumentMarker marker = markers[i];
             
             if (newMarker.endOffset < marker.startOffset+1) {
                 // This is the first marker that is completely after newMarker, and disjoint from it.
-                // We found our insertion point.\10
+                // We found our insertion point.
                 break;
             } else if (newMarker.startOffset > marker.endOffset) {
                 // maker is before newMarker, and disjoint from it.  Keep scanning.
-                it++;
+                i++;
             } else if (newMarker == marker) {
                 // already have this one, NOP
                 return;
@@ -2723,16 +2828,14 @@ void Document::addMarker(Node *node, DocumentMarker newMarker)
                 newMarker.startOffset = min(newMarker.startOffset, marker.startOffset);
                 newMarker.endOffset = max(newMarker.endOffset, marker.endOffset);
                 // remove old one, we'll add newMarker later
-                unsigned removalIndex = it - markers.begin();
-                markers.remove(removalIndex);
-                rects.remove(removalIndex);
+                markers.remove(i);
+                rects.remove(i);
                 // it points to the next marker to consider
             }
         }
-        // at this point it points to the node before which we want to insert
-        unsigned insertionIndex = it - markers.begin();
-        markers.insert(insertionIndex, newMarker);
-        rects.insert(insertionIndex, placeholderRectForMarker());
+        // at this point i points to the node before which we want to insert
+        markers.insert(i, newMarker);
+        rects.insert(i, placeholderRectForMarker());
     }
     
     // repaint the affected node
@@ -2755,10 +2858,9 @@ void Document::copyMarkers(Node *srcNode, unsigned startOffset, int length, Node
 
     bool docDirty = false;
     unsigned endOffset = startOffset + length - 1;
-    Vector<DocumentMarker>::iterator it;
     Vector<DocumentMarker>& markers = vectorPair->first;
-    for (it = markers.begin(); it != markers.end(); ++it) {
-        DocumentMarker marker = *it;
+    for (size_t i = 0; i != markers.size(); ++i) {
+        DocumentMarker marker = markers[i];
 
         // stop if we are now past the specified range
         if (marker.startOffset > endOffset)
@@ -2799,9 +2901,8 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
     ASSERT(markers.size() == rects.size());
     bool docDirty = false;
     unsigned endOffset = startOffset + length - 1;
-    Vector<DocumentMarker>::iterator it;
-    for (it = markers.begin(); it < markers.end();) {
-        DocumentMarker marker = *it;
+    for (size_t i = 0; i < markers.size();) {
+        DocumentMarker marker = markers[i];
 
         // markers are returned in order, so stop if we are now past the specified range
         if (marker.startOffset > endOffset)
@@ -2809,7 +2910,7 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
         
         // skip marker that is wrong type or before target
         if (marker.endOffset < startOffset || (marker.type != markerType && markerType != DocumentMarker::AllMarkers)) {
-            it++;
+            i++;
             continue;
         }
 
@@ -2817,29 +2918,25 @@ void Document::removeMarkers(Node *node, unsigned startOffset, int length, Docum
         docDirty = true;
 
         // pitch the old marker and any associated rect
-        unsigned removalIndex = it - markers.begin();
-        markers.remove(removalIndex);
-        rects.remove(removalIndex);
-        // it now points to the next node
+        markers.remove(i);
+        rects.remove(i);
         
         // add either of the resulting slices that are left after removing target
         if (startOffset > marker.startOffset) {
             DocumentMarker newLeft = marker;
             newLeft.endOffset = startOffset;
-            unsigned insertionIndex = it - markers.begin();
-            markers.insert(insertionIndex, newLeft);
-            rects.insert(insertionIndex, placeholderRectForMarker());
-            // it now points to the newly-inserted node, but we want to skip that one
-            it++;
+            markers.insert(i, newLeft);
+            rects.insert(i, placeholderRectForMarker());
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
         }
         if (marker.endOffset > endOffset) {
             DocumentMarker newRight = marker;
             newRight.startOffset = endOffset;
-            unsigned insertionIndex = it - markers.begin();
-            markers.insert(insertionIndex, newRight);
-            rects.insert(insertionIndex, placeholderRectForMarker());
-            // it now points to the newly-inserted node, but we want to skip that one
-            it++;
+            markers.insert(i, newRight);
+            rects.insert(i, placeholderRectForMarker());
+            // i now points to the newly-inserted node, but we want to skip that one
+            i++;
         }
     }
 
@@ -2952,19 +3049,18 @@ void Document::removeMarkers(DocumentMarker::MarkerType markerType)
         Vector<DocumentMarker>& markers = vectorPair->first;
         Vector<IntRect>& rects = vectorPair->second;
         ASSERT(markers.size() == rects.size());
-        Vector<DocumentMarker>::iterator markerIterator;
-        for (markerIterator = markers.begin(); markerIterator != markers.end();) {
-            DocumentMarker marker = *markerIterator;
+        for (size_t i = 0; i != markers.size();) {
+            DocumentMarker marker = markers[i];
 
             // skip nodes that are not of the specified type
             if (marker.type != markerType && markerType != DocumentMarker::AllMarkers) {
-                ++markerIterator;
+                ++i;
                 continue;
             }
 
             // pitch the old marker
-            markers.remove(markerIterator - markers.begin());
-            rects.remove(markerIterator - markers.begin());
+            markers.remove(i);
+            rects.remove(i);
             nodeNeedsRepaint = true;
             // markerIterator now points to the next node
         }
@@ -2996,10 +3092,9 @@ void Document::repaintMarkers(DocumentMarker::MarkerType markerType)
         // inner loop: process each marker in the current node
         MarkerMapVectorPair* vectorPair = i->second;
         Vector<DocumentMarker>& markers = vectorPair->first;
-        Vector<DocumentMarker>::iterator markerIterator;
         bool nodeNeedsRepaint = false;
-        for (markerIterator = markers.begin(); markerIterator != markers.end(); ++markerIterator) {
-            DocumentMarker marker = *markerIterator;
+        for (size_t i = 0; i != markers.size(); ++i) {
+            DocumentMarker marker = markers[i];
             
             // skip nodes that are not of the specified type
             if (marker.type == markerType || markerType == DocumentMarker::AllMarkers) {
@@ -3067,9 +3162,8 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
     ASSERT(markers.size() == rects.size());
     
     bool docDirty = false;
-    Vector<DocumentMarker>::iterator it;
-    for (it = markers.begin(); it != markers.end(); ++it) {
-        DocumentMarker &marker = *it;
+    for (size_t i = 0; i != markers.size(); ++i) {
+        DocumentMarker &marker = markers[i];
         if (marker.startOffset >= startOffset && (markerType == DocumentMarker::AllMarkers || marker.type == markerType)) {
             assert((int)marker.startOffset + delta >= 0);
             marker.startOffset += delta;
@@ -3077,7 +3171,7 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
             docDirty = true;
             
             // Marker moved, so previously-computed rendered rectangle is now invalid
-            rects[it - markers.begin()] = placeholderRectForMarker();
+            rects[i] = placeholderRectForMarker();
         }
     }
     
@@ -3086,7 +3180,7 @@ void Document::shiftMarkers(Node *node, unsigned startOffset, int delta, Documen
         node->renderer()->repaint();
 }
 
-#ifdef XSLT_SUPPORT
+#if ENABLE(XSLT)
 
 void Document::applyXSLTransform(ProcessingInstruction* pi)
 {
@@ -3138,7 +3232,7 @@ Document *Document::topDocument() const
 {
     Document *doc = const_cast<Document *>(this);
     Element *element;
-    while ((element = doc->ownerElement()) != 0)
+    while ((element = doc->ownerElement()))
         doc = element->document();
     
     return doc;
@@ -3168,12 +3262,10 @@ PassRefPtr<Attr> Document::createAttributeNS(const String &namespaceURI, const S
     
     // FIXME: Assume this is a mapped attribute, since createAttribute isn't namespace-aware.  There's no harm to XML
     // documents if we're wrong.
-    return new Attr(0, this, new MappedAttribute(QualifiedName(prefix.impl(), 
-                                                                       localName.impl(),
-                                                                       namespaceURI.impl()), String("").impl()));
+    return new Attr(0, this, new MappedAttribute(QualifiedName(prefix, localName, namespaceURI), StringImpl::empty()));
 }
 
-#ifdef SVG_SUPPORT
+#if ENABLE(SVG)
 const SVGDocumentExtensions* Document::svgExtensions()
 {
     return m_svgExtensions;
@@ -3317,7 +3409,7 @@ Vector<String> Document::formElementsState() const
 {
     Vector<String> stateVector;
     stateVector.reserveCapacity(m_formElementsWithState.size() * 3);
-    typedef HashSet<HTMLGenericFormElement*>::const_iterator Iterator;
+    typedef ListHashSet<HTMLGenericFormElement*>::const_iterator Iterator;
     Iterator end = m_formElementsWithState.end();
     for (Iterator it = m_formElementsWithState.begin(); it != end; ++it) {
         HTMLGenericFormElement* e = *it;
@@ -3328,7 +3420,7 @@ Vector<String> Document::formElementsState() const
     return stateVector;
 }
 
-#ifdef XPATH_SUPPORT
+#if ENABLE(XPATH)
 
 PassRefPtr<XPathExpression> Document::createExpression(const String& expression,
                                                        XPathNSResolver* resolver,
@@ -3358,7 +3450,7 @@ PassRefPtr<XPathResult> Document::evaluate(const String& expression,
     return m_xpathEvaluator->evaluate(expression, contextNode, resolver, type, result, ec);
 }
 
-#endif // XPATH_SUPPORT
+#endif // ENABLE(XPATH)
 
 void Document::setStateForNewFormElements(const Vector<String>& stateVector)
 {