HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode) { HTMLDOMNode *iter = This->nodes, *ret; PRUint16 node_type; while(iter) { if(iter->nsnode == nsnode) break; iter = iter->next; } if(iter) return iter; ret = mshtml_alloc(sizeof(HTMLDOMNode)); ret->lpHTMLDOMNodeVtbl = &HTMLDOMNodeVtbl; ret->node_type = NT_UNKNOWN; ret->impl.unk = NULL; ret->destructor = NULL; ret->doc = This; nsIDOMNode_AddRef(nsnode); ret->nsnode = nsnode; ret->next = This->nodes; This->nodes = ret; nsIDOMNode_GetNodeType(nsnode, &node_type); if(node_type == NS_ELEMENT_NODE || node_type == NS_DOCUMENT_NODE) HTMLElement_Create(ret); return ret; }
void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode) { node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl; node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl; node->ref = 1; node->doc = doc; if(nsnode) nsIDOMNode_AddRef(nsnode); node->nsnode = nsnode; node->next = doc->nodes; doc->nodes = node; }
void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode) { nsresult nsres; node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl; node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl; ccref_init(&node->ccref, 1); if(&doc->node != node) htmldoc_addref(&doc->basedoc); node->doc = doc; nsIDOMNode_AddRef(nsnode); node->nsnode = nsnode; nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface); assert(nsres == NS_OK); }
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, eventid_t eid) { nsIDOMNode *nsnode = NULL; TRACE("%s\n", debugstr_w(event_info[eid].name)); if(!doc->nsdoc || doc->event_vector[eid] || !(event_info[eid].flags & (EVENT_DEFAULTLISTENER|EVENT_BIND_TO_BODY))) return S_OK; if(event_info[eid].flags & EVENT_BIND_TO_BODY) { nsnode = doc->node.nsnode; nsIDOMNode_AddRef(nsnode); } doc->event_vector[eid] = TRUE; add_nsevent_listener(doc, nsnode, event_info[eid].name); if(nsnode) nsIDOMNode_Release(nsnode); return S_OK; }
static void fire_event_obj(HTMLDocumentNode *doc, eventid_t eid, HTMLEventObj *event_obj, nsIDOMNode *target, IDispatch *script_this) { IHTMLEventObj *prev_event; nsIDOMNode *parent, *nsnode; BOOL prevent_default = FALSE; HTMLInnerWindow *window; HTMLDOMNode *node; UINT16 node_type; nsresult nsres; HRESULT hres; TRACE("(%p) %s\n", doc, debugstr_w(event_info[eid].name)); window = doc->window; if(!window) { WARN("NULL window\n"); return; } htmldoc_addref(&doc->basedoc); prev_event = window->event; window->event = event_obj ? &event_obj->IHTMLEventObj_iface : NULL; nsIDOMNode_GetNodeType(target, &node_type); nsnode = target; nsIDOMNode_AddRef(nsnode); switch(node_type) { case ELEMENT_NODE: do { hres = get_node(doc, nsnode, FALSE, &node); if(SUCCEEDED(hres) && node) { call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, script_this ? script_this : (IDispatch*)&node->IHTMLDOMNode_iface); node_release(node); } if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble)) break; nsIDOMNode_GetParentNode(nsnode, &parent); nsIDOMNode_Release(nsnode); nsnode = parent; if(!nsnode) break; nsIDOMNode_GetNodeType(nsnode, &node_type); }while(node_type == ELEMENT_NODE); if(!(event_info[eid].flags & EVENT_BUBBLE) || (event_obj && event_obj->cancel_bubble)) break; case DOCUMENT_NODE: if(event_info[eid].flags & EVENT_FORWARDBODY) { nsIDOMHTMLElement *nsbody; nsresult nsres; nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); if(NS_SUCCEEDED(nsres) && nsbody) { hres = get_node(doc, (nsIDOMNode*)nsbody, FALSE, &node); if(SUCCEEDED(hres) && node) { call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, script_this ? script_this : (IDispatch*)&node->IHTMLDOMNode_iface); node_release(node); } nsIDOMHTMLElement_Release(nsbody); }else { ERR("Could not get body: %08x\n", nsres); } } call_event_handlers(doc, event_obj, doc->node.event_target, &doc->basedoc.cp_container, eid, script_this ? script_this : (IDispatch*)&doc->basedoc.IHTMLDocument2_iface); break; default: FIXME("unimplemented node type %d\n", node_type); } if(nsnode) nsIDOMNode_Release(nsnode); if(event_obj && event_obj->prevent_default) prevent_default = TRUE; window->event = prev_event; if(!prevent_default && (event_info[eid].flags & EVENT_HASDEFAULTHANDLERS)) { nsIDOMNode_AddRef(target); nsnode = target; do { hres = get_node(doc, nsnode, TRUE, &node); if(FAILED(hres)) break; if(node) { if(node->vtbl->handle_event) hres = node->vtbl->handle_event(node, eid, event_obj ? event_obj->nsevent : NULL, &prevent_default); node_release(node); if(FAILED(hres) || prevent_default || (event_obj && event_obj->cancel_bubble)) break; } nsres = nsIDOMNode_GetParentNode(nsnode, &parent); if(NS_FAILED(nsres)) break; nsIDOMNode_Release(nsnode); nsnode = parent; } while(nsnode); if(nsnode) nsIDOMNode_Release(nsnode); } if(prevent_default && event_obj && event_obj->nsevent) { TRACE("calling PreventDefault\n"); nsIDOMEvent_PreventDefault(event_obj->nsevent); } htmldoc_release(&doc->basedoc); }
HRESULT get_elem_source_index(HTMLElement *elem, LONG *ret) { elem_vector_t buf = {NULL, 0, 8}; nsIDOMNode *parent_node, *iter; UINT16 parent_type; HTMLDOMNode *node; int i; nsresult nsres; HRESULT hres; iter = elem->node.nsnode; nsIDOMNode_AddRef(iter); /* Find document or document fragment parent. */ while(1) { nsres = nsIDOMNode_GetParentNode(iter, &parent_node); nsIDOMNode_Release(iter); assert(nsres == NS_OK); if(!parent_node) break; nsres = nsIDOMNode_GetNodeType(parent_node, &parent_type); assert(nsres == NS_OK); if(parent_type != ELEMENT_NODE) { if(parent_type != DOCUMENT_NODE && parent_type != DOCUMENT_FRAGMENT_NODE) FIXME("Unexpected parent_type %d\n", parent_type); break; } iter = parent_node; } if(!parent_node) { *ret = -1; return S_OK; } hres = get_node(elem->node.doc, parent_node, TRUE, &node); nsIDOMNode_Release(parent_node); if(FAILED(hres)) return hres; /* Create all children collection and find the element in it. * This could be optimized if we ever find the reason. */ buf.buf = heap_alloc(buf.size*sizeof(*buf.buf)); if(!buf.buf) { IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface); return E_OUTOFMEMORY; } create_all_list(elem->node.doc, node, &buf); for(i=0; i < buf.len; i++) { if(buf.buf[i] == elem) break; } IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface); heap_free(buf.buf); if(i == buf.len) { FIXME("The element is not in parent's child list?\n"); return E_UNEXPECTED; } *ret = i; return S_OK; }
void fire_event(HTMLDocumentNode *doc, eventid_t eid, BOOL set_event, nsIDOMNode *target, nsIDOMEvent *nsevent) { IHTMLEventObj *prev_event, *event_obj = NULL; nsIDOMNode *parent, *nsnode; HTMLDOMNode *node; PRUint16 node_type; HRESULT hres; TRACE("(%p) %s\n", doc, debugstr_w(event_info[eid].name)); prev_event = doc->basedoc.window->event; if(set_event) { hres = get_node(doc, target, TRUE, &node); if(FAILED(hres)) return; event_obj = create_event(node, eid, nsevent); } doc->basedoc.window->event = event_obj; nsIDOMNode_GetNodeType(target, &node_type); nsnode = target; nsIDOMNode_AddRef(nsnode); switch(node_type) { case ELEMENT_NODE: do { hres = get_node(doc, nsnode, FALSE, &node); if(SUCCEEDED(hres) && node) call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, (IDispatch*)&node->IHTMLDOMNode_iface); if(!(event_info[eid].flags & EVENT_BUBBLE)) break; nsIDOMNode_GetParentNode(nsnode, &parent); nsIDOMNode_Release(nsnode); nsnode = parent; if(!nsnode) break; nsIDOMNode_GetNodeType(nsnode, &node_type); }while(node_type == ELEMENT_NODE); if(!(event_info[eid].flags & EVENT_BUBBLE)) break; case DOCUMENT_NODE: if(event_info[eid].flags & EVENT_FORWARDBODY) { nsIDOMHTMLElement *nsbody; nsresult nsres; nsres = nsIDOMHTMLDocument_GetBody(doc->nsdoc, &nsbody); if(NS_SUCCEEDED(nsres) && nsbody) { hres = get_node(doc, (nsIDOMNode*)nsbody, FALSE, &node); if(SUCCEEDED(hres) && node) call_event_handlers(doc, event_obj, *get_node_event_target(node), node->cp_container, eid, (IDispatch*)&node->IHTMLDOMNode_iface); nsIDOMHTMLElement_Release(nsbody); }else { ERR("Could not get body: %08x\n", nsres); } } call_event_handlers(doc, event_obj, doc->node.event_target, &doc->basedoc.cp_container, eid, (IDispatch*)&doc->basedoc.IHTMLDocument2_iface); break; default: FIXME("unimplemented node type %d\n", node_type); } if(nsnode) nsIDOMNode_Release(nsnode); if(event_obj) IHTMLEventObj_Release(event_obj); doc->basedoc.window->event = prev_event; }