mshtml: Added new get_handler_vector helper for creating handle_vector_t.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-02-13 21:11:15 +01:00 committed by Alexandre Julliard
parent 72ee409e7f
commit db67232ce2
1 changed files with 39 additions and 49 deletions

View File

@ -911,6 +911,27 @@ static inline event_target_t *get_event_target_data(EventTarget *event_target, B
return event_target->ptr = heap_alloc_zero(sizeof(event_target_t)); return event_target->ptr = heap_alloc_zero(sizeof(event_target_t));
} }
static handler_vector_t *get_handler_vector(EventTarget *event_target, eventid_t eid, BOOL alloc)
{
event_target_t *data;
data = get_event_target_data(event_target, alloc);
if(!data)
return NULL;
if(alloc && !data->event_table[eid]) {
data->event_table[eid] = heap_alloc_zero(sizeof(*data->event_table[eid]));
if(data->event_table[eid]) {
const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->bind_event)
vtbl->bind_event(&event_target->dispex, eid);
else
FIXME("Unsupported event binding on target %p\n", event_target);
}
}
return data->event_table[eid];
}
static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv) static HRESULT call_disp_func(IDispatch *disp, DISPPARAMS *dp, VARIANT *retv)
{ {
IDispatchEx *dispex; IDispatchEx *dispex;
@ -1315,15 +1336,6 @@ HRESULT call_fire_event(HTMLDOMNode *node, eventid_t eid)
return S_OK; return S_OK;
} }
static BOOL alloc_handler_vector(event_target_t *event_target, eventid_t eid)
{
if(event_target->event_table[eid])
return TRUE;
event_target->event_table[eid] = heap_alloc_zero(sizeof(*event_target->event_table[eid]));
return event_target->event_table[eid] != NULL;
}
HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, eventid_t eid) HRESULT ensure_doc_nsevent_handler(HTMLDocumentNode *doc, eventid_t eid)
{ {
nsIDOMNode *nsnode = NULL; nsIDOMNode *nsnode = NULL;
@ -1378,16 +1390,6 @@ void detach_events(HTMLDocumentNode *doc)
release_nsevents(doc); release_nsevents(doc);
} }
/* Caller should ensure that it's called only once for given event in the target. */
static void bind_event(EventTarget *event_target, eventid_t eid)
{
const dispex_static_data_vtbl_t *vtbl = dispex_get_vtbl(&event_target->dispex);
if(vtbl->bind_event)
vtbl->bind_event(&event_target->dispex, eid);
else
FIXME("Unsupported event binding on target %p\n", event_target);
}
static void remove_event_handler(EventTarget *event_target, eventid_t eid) static void remove_event_handler(EventTarget *event_target, eventid_t eid)
{ {
event_target_t *data; event_target_t *data;
@ -1407,7 +1409,7 @@ static void remove_event_handler(EventTarget *event_target, eventid_t eid)
static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp) static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid, IDispatch *disp)
{ {
event_target_t *data; handler_vector_t *handler_vector;
if(event_info[eid].flags & EVENT_FIXME) if(event_info[eid].flags & EVENT_FIXME)
FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name)); FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
@ -1416,20 +1418,14 @@ static HRESULT set_event_handler_disp(EventTarget *event_target, eventid_t eid,
if(!disp) if(!disp)
return S_OK; return S_OK;
data = get_event_target_data(event_target, TRUE); handler_vector = get_handler_vector(event_target, eid, TRUE);
if(!data) if(!handler_vector)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if(!data->event_table[eid]) { if(handler_vector->handler_prop)
if(!alloc_handler_vector(data, eid)) IDispatch_Release(handler_vector->handler_prop);
return E_OUTOFMEMORY;
bind_event(event_target, eid); handler_vector->handler_prop = disp;
}else if(data->event_table[eid]->handler_prop) {
IDispatch_Release(data->event_table[eid]->handler_prop);
}
data->event_table[eid]->handler_prop = disp;
IDispatch_AddRef(disp); IDispatch_AddRef(disp);
return S_OK; return S_OK;
} }
@ -1503,7 +1499,7 @@ HRESULT get_event_handler(EventTarget *event_target, eventid_t eid, VARIANT *var
HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res) HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARIANT_BOOL *res)
{ {
event_target_t *data; handler_vector_t *handler_vector;
eventid_t eid; eventid_t eid;
DWORD i = 0; DWORD i = 0;
@ -1517,31 +1513,25 @@ HRESULT attach_event(EventTarget *event_target, BSTR name, IDispatch *disp, VARI
if(event_info[eid].flags & EVENT_FIXME) if(event_info[eid].flags & EVENT_FIXME)
FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name)); FIXME("unimplemented event %s\n", debugstr_w(event_info[eid].name));
data = get_event_target_data(event_target, TRUE); handler_vector = get_handler_vector(event_target, eid, TRUE);
if(!data) if(!handler_vector)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if(data->event_table[eid]) { while(i < handler_vector->handler_cnt && handler_vector->handlers[i])
while(i < data->event_table[eid]->handler_cnt && data->event_table[eid]->handlers[i]) i++;
i++; if(i == handler_vector->handler_cnt) {
}else if(alloc_handler_vector(data, eid)) {
bind_event(event_target, eid);
}else {
return E_OUTOFMEMORY;
}
if(i == data->event_table[eid]->handler_cnt) {
if(i) if(i)
data->event_table[eid]->handlers = heap_realloc_zero(data->event_table[eid]->handlers, handler_vector->handlers = heap_realloc_zero(handler_vector->handlers,
(i + 1) * sizeof(*data->event_table[eid]->handlers)); (i + 1) * sizeof(*handler_vector->handlers));
else else
data->event_table[eid]->handlers = heap_alloc_zero(sizeof(*data->event_table[eid]->handlers)); handler_vector->handlers = heap_alloc_zero(sizeof(*handler_vector->handlers));
if(!data->event_table[eid]->handlers) if(!handler_vector->handlers)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
data->event_table[eid]->handler_cnt++; handler_vector->handler_cnt++;
} }
IDispatch_AddRef(disp); IDispatch_AddRef(disp);
data->event_table[eid]->handlers[i] = disp; handler_vector->handlers[i] = disp;
*res = VARIANT_TRUE; *res = VARIANT_TRUE;
return S_OK; return S_OK;