mshtml: Add separate task list for tasks dispatching events.
[wine.git] / dlls / mshtml / htmlattr.c
blobb7e40a23d553ffc4e62c2212fd9fadbdf0a7f27b
1 /*
2 * Copyright 2011 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
29 #include "mshtml_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface)
37 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute_iface);
40 static HRESULT WINAPI HTMLDOMAttribute_QueryInterface(IHTMLDOMAttribute *iface,
41 REFIID riid, void **ppv)
43 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
45 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
47 if(IsEqualGUID(&IID_IUnknown, riid)) {
48 *ppv = &This->IHTMLDOMAttribute_iface;
49 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute, riid)) {
50 *ppv = &This->IHTMLDOMAttribute_iface;
51 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute2, riid)) {
52 *ppv = &This->IHTMLDOMAttribute2_iface;
53 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
54 return *ppv ? S_OK : E_NOINTERFACE;
55 }else {
56 WARN("%s not supported\n", debugstr_mshtml_guid(riid));
57 *ppv = NULL;
58 return E_NOINTERFACE;
61 IUnknown_AddRef((IUnknown*)*ppv);
62 return S_OK;
65 static ULONG WINAPI HTMLDOMAttribute_AddRef(IHTMLDOMAttribute *iface)
67 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
68 LONG ref = InterlockedIncrement(&This->ref);
70 TRACE("(%p) ref=%ld\n", This, ref);
72 return ref;
75 static ULONG WINAPI HTMLDOMAttribute_Release(IHTMLDOMAttribute *iface)
77 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
78 LONG ref = InterlockedDecrement(&This->ref);
80 TRACE("(%p) ref=%ld\n", This, ref);
82 if(!ref) {
83 assert(!This->elem);
84 release_dispex(&This->dispex);
85 VariantClear(&This->value);
86 free(This->name);
87 free(This);
90 return ref;
93 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfoCount(IHTMLDOMAttribute *iface, UINT *pctinfo)
95 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
96 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
99 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfo(IHTMLDOMAttribute *iface, UINT iTInfo,
100 LCID lcid, ITypeInfo **ppTInfo)
102 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
103 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
106 static HRESULT WINAPI HTMLDOMAttribute_GetIDsOfNames(IHTMLDOMAttribute *iface, REFIID riid,
107 LPOLESTR *rgszNames, UINT cNames,
108 LCID lcid, DISPID *rgDispId)
110 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
111 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
112 lcid, rgDispId);
115 static HRESULT WINAPI HTMLDOMAttribute_Invoke(IHTMLDOMAttribute *iface, DISPID dispIdMember,
116 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
117 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
119 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
120 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
121 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
124 static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BSTR *p)
126 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
128 TRACE("(%p)->(%p)\n", This, p);
130 if(!This->elem) {
131 if(!This->name) {
132 FIXME("No name available\n");
133 return E_FAIL;
136 *p = SysAllocString(This->name);
137 return *p ? S_OK : E_OUTOFMEMORY;
140 return IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, p);
143 static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, VARIANT v)
145 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
146 DISPID dispidNamed = DISPID_PROPERTYPUT;
147 DISPPARAMS dp = {&v, &dispidNamed, 1, 1};
148 EXCEPINFO ei;
149 VARIANT ret;
151 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
153 if(!This->elem)
154 return VariantCopy(&This->value, &v);
156 memset(&ei, 0, sizeof(ei));
158 return IDispatchEx_InvokeEx(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
159 DISPATCH_PROPERTYPUT, &dp, &ret, &ei, NULL);
162 static HRESULT WINAPI HTMLDOMAttribute_get_nodeValue(IHTMLDOMAttribute *iface, VARIANT *p)
164 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
166 TRACE("(%p)->(%p)\n", This, p);
168 if(!This->elem)
169 return VariantCopy(p, &This->value);
171 return get_elem_attr_value_by_dispid(This->elem, This->dispid, p);
174 static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, VARIANT_BOOL *p)
176 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
177 nsIDOMAttr *nsattr;
178 nsAString nsname;
179 BSTR name;
180 nsresult nsres;
181 HRESULT hres;
183 TRACE("(%p)->(%p)\n", This, p);
185 if(!This->elem || !This->elem->dom_element) {
186 FIXME("NULL This->elem\n");
187 return E_UNEXPECTED;
190 if(get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN) {
191 *p = VARIANT_TRUE;
192 return S_OK;
195 hres = IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, &name);
196 if(FAILED(hres))
197 return hres;
199 /* FIXME: This is not exactly right, we have some attributes that don't map directly to Gecko attributes. */
200 nsAString_InitDepend(&nsname, name);
201 nsres = nsIDOMElement_GetAttributeNode(This->elem->dom_element, &nsname, &nsattr);
202 nsAString_Finish(&nsname);
203 SysFreeString(name);
204 if(NS_FAILED(nsres))
205 return E_FAIL;
207 /* If the Gecko attribute node can be found, we know that the attribute is specified.
208 There is no point in calling GetSpecified */
209 if(nsattr) {
210 nsIDOMAttr_Release(nsattr);
211 *p = VARIANT_TRUE;
212 }else {
213 *p = VARIANT_FALSE;
215 return S_OK;
218 static const IHTMLDOMAttributeVtbl HTMLDOMAttributeVtbl = {
219 HTMLDOMAttribute_QueryInterface,
220 HTMLDOMAttribute_AddRef,
221 HTMLDOMAttribute_Release,
222 HTMLDOMAttribute_GetTypeInfoCount,
223 HTMLDOMAttribute_GetTypeInfo,
224 HTMLDOMAttribute_GetIDsOfNames,
225 HTMLDOMAttribute_Invoke,
226 HTMLDOMAttribute_get_nodeName,
227 HTMLDOMAttribute_put_nodeValue,
228 HTMLDOMAttribute_get_nodeValue,
229 HTMLDOMAttribute_get_specified
232 static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute2(IHTMLDOMAttribute2 *iface)
234 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute2_iface);
237 static HRESULT WINAPI HTMLDOMAttribute2_QueryInterface(IHTMLDOMAttribute2 *iface, REFIID riid, void **ppv)
239 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
240 return IHTMLDOMAttribute_QueryInterface(&This->IHTMLDOMAttribute_iface, riid, ppv);
243 static ULONG WINAPI HTMLDOMAttribute2_AddRef(IHTMLDOMAttribute2 *iface)
245 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
246 return IHTMLDOMAttribute_AddRef(&This->IHTMLDOMAttribute_iface);
249 static ULONG WINAPI HTMLDOMAttribute2_Release(IHTMLDOMAttribute2 *iface)
251 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
252 return IHTMLDOMAttribute_Release(&This->IHTMLDOMAttribute_iface);
255 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfoCount(IHTMLDOMAttribute2 *iface, UINT *pctinfo)
257 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
258 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
261 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfo(IHTMLDOMAttribute2 *iface, UINT iTInfo,
262 LCID lcid, ITypeInfo **ppTInfo)
264 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
265 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
268 static HRESULT WINAPI HTMLDOMAttribute2_GetIDsOfNames(IHTMLDOMAttribute2 *iface, REFIID riid,
269 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
271 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
272 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
273 lcid, rgDispId);
276 static HRESULT WINAPI HTMLDOMAttribute2_Invoke(IHTMLDOMAttribute2 *iface, DISPID dispIdMember,
277 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
278 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
280 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
281 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
282 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
285 static HRESULT WINAPI HTMLDOMAttribute2_get_name(IHTMLDOMAttribute2 *iface, BSTR *p)
287 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
289 TRACE("(%p)->(%p)\n", This, p);
291 return IHTMLDOMAttribute_get_nodeName(&This->IHTMLDOMAttribute_iface, p);
294 static HRESULT WINAPI HTMLDOMAttribute2_put_value(IHTMLDOMAttribute2 *iface, BSTR v)
296 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
297 VARIANT var;
299 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
301 V_VT(&var) = VT_BSTR;
302 V_BSTR(&var) = v;
303 return IHTMLDOMAttribute_put_nodeValue(&This->IHTMLDOMAttribute_iface, var);
306 static HRESULT WINAPI HTMLDOMAttribute2_get_value(IHTMLDOMAttribute2 *iface, BSTR *p)
308 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
309 VARIANT val;
310 HRESULT hres;
312 TRACE("(%p)->(%p)\n", This, p);
314 V_VT(&val) = VT_EMPTY;
315 if(This->elem)
316 hres = get_elem_attr_value_by_dispid(This->elem, This->dispid, &val);
317 else
318 hres = VariantCopy(&val, &This->value);
319 if(SUCCEEDED(hres))
320 hres = attr_value_to_string(&val);
321 if(FAILED(hres))
322 return hres;
324 assert(V_VT(&val) == VT_BSTR);
325 *p = V_BSTR(&val);
326 if(!*p && !(*p = SysAllocStringLen(NULL, 0)))
327 return E_OUTOFMEMORY;
328 return S_OK;
331 static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *p)
333 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
335 TRACE("(%p)->(%p)\n", This, p);
337 *p = variant_bool(This->elem && get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN);
338 return S_OK;
341 static HRESULT WINAPI HTMLDOMAttribute2_get_nodeType(IHTMLDOMAttribute2 *iface, LONG *p)
343 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
344 FIXME("(%p)->(%p)\n", This, p);
345 return E_NOTIMPL;
348 static HRESULT WINAPI HTMLDOMAttribute2_get_parentNode(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
350 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
352 TRACE("(%p)->(%p)\n", This, p);
354 *p = NULL;
355 return S_OK;
358 static HRESULT WINAPI HTMLDOMAttribute2_get_childNodes(IHTMLDOMAttribute2 *iface, IDispatch **p)
360 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
361 FIXME("(%p)->(%p)\n", This, p);
362 return E_NOTIMPL;
365 static HRESULT WINAPI HTMLDOMAttribute2_get_firstChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
367 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
368 FIXME("(%p)->(%p)\n", This, p);
369 return E_NOTIMPL;
372 static HRESULT WINAPI HTMLDOMAttribute2_get_lastChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
374 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
375 FIXME("(%p)->(%p)\n", This, p);
376 return E_NOTIMPL;
379 static HRESULT WINAPI HTMLDOMAttribute2_get_previousSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
381 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
382 FIXME("(%p)->(%p)\n", This, p);
383 return E_NOTIMPL;
386 static HRESULT WINAPI HTMLDOMAttribute2_get_nextSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
388 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
389 FIXME("(%p)->(%p)\n", This, p);
390 return E_NOTIMPL;
393 static HRESULT WINAPI HTMLDOMAttribute2_get_attributes(IHTMLDOMAttribute2 *iface, IDispatch **p)
395 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
396 FIXME("(%p)->(%p)\n", This, p);
397 return E_NOTIMPL;
400 static HRESULT WINAPI HTMLDOMAttribute2_get_ownerDocument(IHTMLDOMAttribute2 *iface, IDispatch **p)
402 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
403 FIXME("(%p)->(%p)\n", This, p);
404 return E_NOTIMPL;
407 static HRESULT WINAPI HTMLDOMAttribute2_insertBefore(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
408 VARIANT refChild, IHTMLDOMNode **node)
410 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
411 FIXME("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
412 return E_NOTIMPL;
415 static HRESULT WINAPI HTMLDOMAttribute2_replaceChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
416 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
418 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
419 FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
420 return E_NOTIMPL;
423 static HRESULT WINAPI HTMLDOMAttribute2_removeChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *oldChild,
424 IHTMLDOMNode **node)
426 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
427 FIXME("(%p)->(%p %p)\n", This, oldChild, node);
428 return E_NOTIMPL;
431 static HRESULT WINAPI HTMLDOMAttribute2_appendChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
432 IHTMLDOMNode **node)
434 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
435 FIXME("(%p)->(%p %p)\n", This, newChild, node);
436 return E_NOTIMPL;
439 static HRESULT WINAPI HTMLDOMAttribute2_hasChildNodes(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *fChildren)
441 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
442 FIXME("(%p)->(%p)\n", This, fChildren);
443 return E_NOTIMPL;
446 static HRESULT WINAPI HTMLDOMAttribute2_cloneNode(IHTMLDOMAttribute2 *iface, VARIANT_BOOL fDeep,
447 IHTMLDOMAttribute **clonedNode)
449 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
450 FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode);
451 return E_NOTIMPL;
454 static const IHTMLDOMAttribute2Vtbl HTMLDOMAttribute2Vtbl = {
455 HTMLDOMAttribute2_QueryInterface,
456 HTMLDOMAttribute2_AddRef,
457 HTMLDOMAttribute2_Release,
458 HTMLDOMAttribute2_GetTypeInfoCount,
459 HTMLDOMAttribute2_GetTypeInfo,
460 HTMLDOMAttribute2_GetIDsOfNames,
461 HTMLDOMAttribute2_Invoke,
462 HTMLDOMAttribute2_get_name,
463 HTMLDOMAttribute2_put_value,
464 HTMLDOMAttribute2_get_value,
465 HTMLDOMAttribute2_get_expando,
466 HTMLDOMAttribute2_get_nodeType,
467 HTMLDOMAttribute2_get_parentNode,
468 HTMLDOMAttribute2_get_childNodes,
469 HTMLDOMAttribute2_get_firstChild,
470 HTMLDOMAttribute2_get_lastChild,
471 HTMLDOMAttribute2_get_previousSibling,
472 HTMLDOMAttribute2_get_nextSibling,
473 HTMLDOMAttribute2_get_attributes,
474 HTMLDOMAttribute2_get_ownerDocument,
475 HTMLDOMAttribute2_insertBefore,
476 HTMLDOMAttribute2_replaceChild,
477 HTMLDOMAttribute2_removeChild,
478 HTMLDOMAttribute2_appendChild,
479 HTMLDOMAttribute2_hasChildNodes,
480 HTMLDOMAttribute2_cloneNode
483 static const tid_t HTMLDOMAttribute_iface_tids[] = {
484 IHTMLDOMAttribute_tid,
485 IHTMLDOMAttribute2_tid,
488 static dispex_static_data_t HTMLDOMAttribute_dispex = {
489 L"Attr",
490 NULL,
491 DispHTMLDOMAttribute_tid,
492 HTMLDOMAttribute_iface_tids
495 HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface)
497 return iface->lpVtbl == &HTMLDOMAttributeVtbl ? impl_from_IHTMLDOMAttribute(iface) : NULL;
500 HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, compat_mode_t compat_mode, HTMLDOMAttribute **attr)
502 HTMLAttributeCollection *col;
503 HTMLDOMAttribute *ret;
504 HRESULT hres;
506 ret = calloc(1, sizeof(*ret));
507 if(!ret)
508 return E_OUTOFMEMORY;
510 ret->IHTMLDOMAttribute_iface.lpVtbl = &HTMLDOMAttributeVtbl;
511 ret->IHTMLDOMAttribute2_iface.lpVtbl = &HTMLDOMAttribute2Vtbl;
512 ret->ref = 1;
513 ret->dispid = dispid;
514 ret->elem = elem;
516 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLDOMAttribute_iface,
517 &HTMLDOMAttribute_dispex, compat_mode);
519 /* For attributes attached to an element, (elem,dispid) pair should be valid used for its operation. */
520 if(elem) {
521 hres = HTMLElement_get_attr_col(&elem->node, &col);
522 if(FAILED(hres)) {
523 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface);
524 return hres;
526 IHTMLAttributeCollection_Release(&col->IHTMLAttributeCollection_iface);
528 list_add_tail(&elem->attrs->attrs, &ret->entry);
531 /* For detached attributes we may still do most operations if we have its name available. */
532 if(name) {
533 ret->name = wcsdup(name);
534 if(!ret->name) {
535 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface);
536 return E_OUTOFMEMORY;
540 *attr = ret;
541 return S_OK;