mshtml: Moved nsIDOMEventListener implementations to HTMLDocumentNode.
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c
index c1eca66..a5422f2 100644
--- a/dlls/mshtml/htmldoc.c
+++ b/dlls/mshtml/htmldoc.c
@@ -1763,6 +1763,8 @@
 {
     HTMLDocumentNode *This = HTMLDOCNODE_NODE_THIS(iface);
 
+    if(This->nsevent_listener)
+        release_nsevents(This);
     if(This->secmgr)
         IInternetSecurityManager_Release(This->secmgr);
 
@@ -1819,11 +1821,12 @@
     HTMLDocumentNode_SecMgr_Init(doc);
     doc->ref = 1;
 
+    doc->basedoc.window = window;
+
     nsIDOMHTMLDocument_AddRef(nsdoc);
     doc->nsdoc = nsdoc;
     init_mutation(doc);
-
-    doc->basedoc.window = window;
+    init_nsevents(doc);
 
     list_init(&doc->bindings);
     list_init(&doc->selection_list);
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index eb4b34f..e3a12b2 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -365,11 +365,6 @@
     DWORD update;
 };
 
-typedef struct {
-    const nsIDOMEventListenerVtbl      *lpDOMEventListenerVtbl;
-    NSContainer *This;
-} nsEventListener;
-
 struct NSContainer {
     const nsIWebBrowserChromeVtbl       *lpWebBrowserChromeVtbl;
     const nsIContextMenuListenerVtbl    *lpContextMenuListenerVtbl;
@@ -380,12 +375,6 @@
     const nsIWeakReferenceVtbl          *lpWeakReferenceVtbl;
     const nsISupportsWeakReferenceVtbl  *lpSupportsWeakReferenceVtbl;
 
-    nsEventListener blur_listener;
-    nsEventListener focus_listener;
-    nsEventListener keypress_listener;
-    nsEventListener load_listener;
-    nsEventListener htmlevent_listener;
-
     nsIWebBrowser *webbrowser;
     nsIWebNavigation *navigation;
     nsIBaseWindow *window;
@@ -479,6 +468,8 @@
     struct _mutation_queue_t *next;
 } mutation_queue_t;
 
+typedef struct nsDocumentEventListener nsDocumentEventListener;
+
 struct HTMLDocumentNode {
     HTMLDOMNode node;
     HTMLDocument basedoc;
@@ -495,6 +486,7 @@
     BOOL content_ready;
 
     IInternetSecurityManager *secmgr;
+    nsDocumentEventListener *nsevent_listener;
 
     mutation_queue_t *mutation_queue;
     mutation_queue_t *mutation_queue_tail;
@@ -656,10 +648,12 @@
 nsICommandParams *create_nscommand_params(void);
 HRESULT nsnode_to_nsstring(nsIDOMNode*,nsAString*);
 void get_editor_controller(NSContainer*);
-void init_nsevents(NSContainer*);
-void add_nsevent_listener(HTMLWindow*,LPCWSTR);
 nsresult get_nsinterface(nsISupports*,REFIID,void**);
 
+void init_nsevents(HTMLDocumentNode*);
+void release_nsevents(HTMLDocumentNode*);
+void add_nsevent_listener(HTMLWindow*,LPCWSTR);
+
 void set_window_bscallback(HTMLWindow*,nsChannelBSC*);
 void set_current_mon(HTMLWindow*,IMoniker*);
 HRESULT start_binding(HTMLWindow*,HTMLDocumentNode*,BSCallback*,IBindCtx*);
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index d5fea3a..3a1644c 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -955,10 +955,6 @@
 
             if(This->window)
                 update_window_doc(This->window);
-
-            /* events are reset when a new document URI is loaded, so re-initialise them here */
-            if(This->window && This->window->doc_obj->basedoc.window == This->window)
-                init_nsevents(This->window->doc_obj->nscontainer);
         }
 
         This->bsc.readed += This->nsstream->buf_size;
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index f6efd26..6207c13 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -1697,8 +1697,6 @@
     if(NS_FAILED(nsres))
         ERR("SetParentURIContentListener failed: %08x\n", nsres);
 
-    init_nsevents(ret);
-
     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIScrollable, (void**)&scrollable);
     if(NS_SUCCEEDED(nsres)) {
         nsres = nsIScrollable_SetDefaultScrollbarPreferences(scrollable,
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c
index e2758ce..3aef738 100644
--- a/dlls/mshtml/nsevents.c
+++ b/dlls/mshtml/nsevents.c
@@ -35,6 +35,35 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
 
+typedef struct {
+    const nsIDOMEventListenerVtbl      *lpDOMEventListenerVtbl;
+    nsDocumentEventListener *This;
+} nsEventListener;
+
+struct nsDocumentEventListener {
+    nsEventListener blur_listener;
+    nsEventListener focus_listener;
+    nsEventListener keypress_listener;
+    nsEventListener load_listener;
+    nsEventListener htmlevent_listener;
+
+    LONG ref;
+
+    HTMLDocumentNode *doc;
+};
+
+static LONG release_listener(nsDocumentEventListener *This)
+{
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    if(!ref)
+        heap_free(This);
+
+    return ref;
+}
+
 #define NSEVENTLIST_THIS(iface) DEFINE_THIS(nsEventListener, DOMEventListener, iface)
 
 static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface,
@@ -63,37 +92,44 @@
 
 static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
-    return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
+    nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This;
+    LONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) ref=%d\n", This, ref);
+
+    return ref;
 }
 
 static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
-    return nsIWebBrowserChrome_Release(NSWBCHROME(This));
+    nsDocumentEventListener *This = NSEVENTLIST_THIS(iface)->This;
+
+    return release_listener(This);
 }
 
-static BOOL is_doc_child_focus(NSContainer *This)
+static BOOL is_doc_child_focus(HTMLDocumentObj *doc)
 {
     HWND hwnd;
 
-    if(!This->doc)
-        return FALSE;
-
-    for(hwnd = GetFocus(); hwnd && hwnd != This->doc->basedoc.doc_obj->hwnd; hwnd = GetParent(hwnd));
+    for(hwnd = GetFocus(); hwnd && hwnd != doc->hwnd; hwnd = GetParent(hwnd));
 
     return hwnd != NULL;
 }
 
 static nsresult NSAPI handle_blur(nsIDOMEventListener *iface, nsIDOMEvent *event)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc;
+    HTMLDocumentObj *doc_obj;
 
-    TRACE("(%p)\n", This);
+    TRACE("(%p)\n", doc);
 
-    if(!This->reset_focus && This->doc && This->doc->basedoc.doc_obj->focus && !is_doc_child_focus(This)) {
-        This->doc->basedoc.doc_obj->focus = FALSE;
-        notif_focus(This->doc);
+    if(!doc)
+        return NS_ERROR_FAILURE;
+    doc_obj = doc->basedoc.doc_obj;
+
+    if(!doc_obj->nscontainer->reset_focus && doc_obj->focus && !is_doc_child_focus(doc_obj)) {
+        doc_obj->focus = FALSE;
+        notif_focus(doc_obj);
     }
 
     return NS_OK;
@@ -101,13 +137,18 @@
 
 static nsresult NSAPI handle_focus(nsIDOMEventListener *iface, nsIDOMEvent *event)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc;
+    HTMLDocumentObj *doc_obj;
 
-    TRACE("(%p)\n", This);
+    TRACE("(%p)\n", doc);
 
-    if(!This->reset_focus && This->doc && !This->doc->focus) {
-        This->doc->focus = TRUE;
-        notif_focus(This->doc);
+    if(!doc)
+        return NS_ERROR_FAILURE;
+    doc_obj = doc->basedoc.doc_obj;
+
+    if(!doc_obj->nscontainer->reset_focus && !doc_obj->focus) {
+        doc_obj->focus = TRUE;
+        notif_focus(doc_obj);
     }
 
     return NS_OK;
@@ -116,45 +157,52 @@
 static nsresult NSAPI handle_keypress(nsIDOMEventListener *iface,
         nsIDOMEvent *event)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc;
+    HTMLDocumentObj *doc_obj;
 
-    TRACE("(%p)->(%p)\n", This, event);
+    if(!doc)
+        return NS_ERROR_FAILURE;
+    doc_obj = doc->basedoc.doc_obj;
 
-    update_doc(&This->doc->basedoc, UPDATE_UI);
-    if(This->doc->usermode == EDITMODE)
-        handle_edit_event(&This->doc->basedoc, event);
+    TRACE("(%p)->(%p)\n", doc, event);
+
+    update_doc(&doc_obj->basedoc, UPDATE_UI);
+    if(doc_obj->usermode == EDITMODE)
+        handle_edit_event(&doc_obj->basedoc, event);
 
     return NS_OK;
 }
 
 static nsresult NSAPI handle_load(nsIDOMEventListener *iface, nsIDOMEvent *event)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc;
+    HTMLDocumentObj *doc_obj;
     nsIDOMHTMLElement *nsbody = NULL;
 
-    TRACE("(%p)\n", This);
+    TRACE("(%p)\n", doc);
 
-    if(!This->doc)
-        return NS_OK;
+    if(!doc)
+        return NS_ERROR_FAILURE;
+    doc_obj = doc->basedoc.doc_obj;
 
-    connect_scripts(This->doc->basedoc.window);
+    connect_scripts(doc->basedoc.window);
 
-    if(This->editor_controller) {
-        nsIController_Release(This->editor_controller);
-        This->editor_controller = NULL;
+    if(doc_obj->nscontainer->editor_controller) {
+        nsIController_Release(doc_obj->nscontainer->editor_controller);
+        doc_obj->nscontainer->editor_controller = NULL;
     }
 
-    if(This->doc->usermode == EDITMODE)
-        handle_edit_load(&This->doc->basedoc);
+    if(doc_obj->usermode == EDITMODE)
+        handle_edit_load(&doc_obj->basedoc);
 
-    if(!This->doc->basedoc.doc_node->nsdoc) {
+    if(!doc->nsdoc) {
         ERR("NULL nsdoc\n");
         return NS_ERROR_FAILURE;
     }
 
-    nsIDOMHTMLDocument_GetBody(This->doc->basedoc.doc_node->nsdoc, &nsbody);
+    nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody);
     if(nsbody) {
-        fire_event(This->doc->basedoc.doc_node, EVENTID_LOAD, (nsIDOMNode*)nsbody, event);
+        fire_event(doc, EVENTID_LOAD, (nsIDOMNode*)nsbody, event);
         nsIDOMHTMLElement_Release(nsbody);
     }
 
@@ -163,7 +211,7 @@
 
 static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event)
 {
-    NSContainer *This = NSEVENTLIST_THIS(iface)->This;
+    HTMLDocumentNode *doc = NSEVENTLIST_THIS(iface)->This->doc;
     const PRUnichar *type;
     nsIDOMEventTarget *event_target;
     nsIDOMNode *nsnode;
@@ -190,7 +238,7 @@
         return NS_OK;
     }
 
-    fire_event(This->doc->basedoc.doc_node, eid, nsnode, event);
+    fire_event(doc, eid, nsnode, event);
 
     nsIDOMNode_Release(nsnode);
 
@@ -227,11 +275,11 @@
 
 }
 
-static void init_listener(nsEventListener *This, NSContainer *container,
+static void init_listener(nsEventListener *This, nsDocumentEventListener *listener,
         const nsIDOMEventListenerVtbl *vtbl)
 {
     This->lpDOMEventListenerVtbl = vtbl;
-    This->This = container;
+    This->This = listener;
 }
 
 void add_nsevent_listener(HTMLWindow *window, LPCWSTR type)
@@ -245,13 +293,22 @@
         return;
     }
 
-    init_event(target, type, NSEVENTLIST(&window->doc_obj->nscontainer->htmlevent_listener), TRUE);
+    init_event(target, type, NSEVENTLIST(&window->doc->nsevent_listener->htmlevent_listener), TRUE);
     nsIDOMEventTarget_Release(target);
 }
 
-void init_nsevents(NSContainer *This)
+void release_nsevents(HTMLDocumentNode *doc)
 {
-    nsIDOMWindow *dom_window;
+    if(doc->nsevent_listener) {
+        doc->nsevent_listener->doc = NULL;
+        release_listener(doc->nsevent_listener);
+        doc->nsevent_listener = NULL;
+    }
+}
+
+void init_nsevents(HTMLDocumentNode *doc)
+{
+    nsDocumentEventListener *listener;
     nsIDOMEventTarget *target;
     nsresult nsres;
 
@@ -260,29 +317,31 @@
     static const PRUnichar wsz_keypress[]  = {'k','e','y','p','r','e','s','s',0};
     static const PRUnichar wsz_load[]      = {'l','o','a','d',0};
 
-    init_listener(&This->blur_listener,        This, &blur_vtbl);
-    init_listener(&This->focus_listener,       This, &focus_vtbl);
-    init_listener(&This->keypress_listener,    This, &keypress_vtbl);
-    init_listener(&This->load_listener,        This, &load_vtbl);
-    init_listener(&This->htmlevent_listener,   This, &htmlevent_vtbl);
-
-    nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window);
-    if(NS_FAILED(nsres)) {
-        ERR("GetContentDOMWindow failed: %08x\n", nsres);
+    listener = heap_alloc(sizeof(nsDocumentEventListener));
+    if(!listener)
         return;
-    }
 
-    nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target);
-    nsIDOMWindow_Release(dom_window);
+    listener->ref = 1;
+    listener->doc = doc;
+
+    init_listener(&listener->blur_listener,        listener, &blur_vtbl);
+    init_listener(&listener->focus_listener,       listener, &focus_vtbl);
+    init_listener(&listener->keypress_listener,    listener, &keypress_vtbl);
+    init_listener(&listener->load_listener,        listener, &load_vtbl);
+    init_listener(&listener->htmlevent_listener,   listener, &htmlevent_vtbl);
+
+    doc->nsevent_listener = listener;
+
+    nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target);
     if(NS_FAILED(nsres)) {
         ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
         return;
     }
 
-    init_event(target, wsz_blur,       NSEVENTLIST(&This->blur_listener),        TRUE);
-    init_event(target, wsz_focus,      NSEVENTLIST(&This->focus_listener),       TRUE);
-    init_event(target, wsz_keypress,   NSEVENTLIST(&This->keypress_listener),    FALSE);
-    init_event(target, wsz_load,       NSEVENTLIST(&This->load_listener),        TRUE);
+    init_event(target, wsz_blur,       NSEVENTLIST(&listener->blur_listener),        TRUE);
+    init_event(target, wsz_focus,      NSEVENTLIST(&listener->focus_listener),       TRUE);
+    init_event(target, wsz_keypress,   NSEVENTLIST(&listener->keypress_listener),    FALSE);
+    init_event(target, wsz_load,       NSEVENTLIST(&listener->load_listener),        TRUE);
 
     nsIDOMEventTarget_Release(target);
 }