joy.cpl: Remove uneeded FIXME message.
[wine] / dlls / mshtml / htmloption.c
1 /*
2  * Copyright 2007 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <stdarg.h>
20 #include <assert.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28
29 #include "wine/debug.h"
30
31 #include "mshtml_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
34
35 struct HTMLOptionElement {
36     HTMLElement element;
37
38     IHTMLOptionElement IHTMLOptionElement_iface;
39
40     nsIDOMHTMLOptionElement *nsoption;
41 };
42
43 static inline HTMLOptionElement *impl_from_IHTMLOptionElement(IHTMLOptionElement *iface)
44 {
45     return CONTAINING_RECORD(iface, HTMLOptionElement, IHTMLOptionElement_iface);
46 }
47
48 static HRESULT WINAPI HTMLOptionElement_QueryInterface(IHTMLOptionElement *iface,
49         REFIID riid, void **ppv)
50 {
51     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
52
53     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
54 }
55
56 static ULONG WINAPI HTMLOptionElement_AddRef(IHTMLOptionElement *iface)
57 {
58     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
59
60     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
61 }
62
63 static ULONG WINAPI HTMLOptionElement_Release(IHTMLOptionElement *iface)
64 {
65     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
66
67     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
68 }
69
70 static HRESULT WINAPI HTMLOptionElement_GetTypeInfoCount(IHTMLOptionElement *iface, UINT *pctinfo)
71 {
72     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
73     return IDispatchEx_GetTypeInfoCount(&This->element.node.dispex.IDispatchEx_iface, pctinfo);
74 }
75
76 static HRESULT WINAPI HTMLOptionElement_GetTypeInfo(IHTMLOptionElement *iface, UINT iTInfo,
77                                               LCID lcid, ITypeInfo **ppTInfo)
78 {
79     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
80     return IDispatchEx_GetTypeInfo(&This->element.node.dispex.IDispatchEx_iface, iTInfo, lcid,
81             ppTInfo);
82 }
83
84 static HRESULT WINAPI HTMLOptionElement_GetIDsOfNames(IHTMLOptionElement *iface, REFIID riid,
85                                                 LPOLESTR *rgszNames, UINT cNames,
86                                                 LCID lcid, DISPID *rgDispId)
87 {
88     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
89     return IDispatchEx_GetIDsOfNames(&This->element.node.dispex.IDispatchEx_iface, riid, rgszNames,
90             cNames, lcid, rgDispId);
91 }
92
93 static HRESULT WINAPI HTMLOptionElement_Invoke(IHTMLOptionElement *iface, DISPID dispIdMember,
94                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
95                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
96 {
97     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
98     return IDispatchEx_Invoke(&This->element.node.dispex.IDispatchEx_iface, dispIdMember, riid,
99             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
100 }
101
102 static HRESULT WINAPI HTMLOptionElement_put_selected(IHTMLOptionElement *iface, VARIANT_BOOL v)
103 {
104     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
105     nsresult nsres;
106
107     TRACE("(%p)->(%x)\n", This, v);
108
109     nsres = nsIDOMHTMLOptionElement_SetSelected(This->nsoption, v != VARIANT_FALSE);
110     if(NS_FAILED(nsres)) {
111         ERR("SetSelected failed: %08x\n", nsres);
112         return E_FAIL;
113     }
114
115     return S_OK;
116 }
117
118 static HRESULT WINAPI HTMLOptionElement_get_selected(IHTMLOptionElement *iface, VARIANT_BOOL *p)
119 {
120     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
121     cpp_bool selected;
122     nsresult nsres;
123
124     TRACE("(%p)->(%p)\n", This, p);
125
126     nsres = nsIDOMHTMLOptionElement_GetSelected(This->nsoption, &selected);
127     if(NS_FAILED(nsres)) {
128         ERR("GetSelected failed: %08x\n", nsres);
129         return E_FAIL;
130     }
131
132     *p = selected ? VARIANT_TRUE : VARIANT_FALSE;
133     return S_OK;
134 }
135
136 static HRESULT WINAPI HTMLOptionElement_put_value(IHTMLOptionElement *iface, BSTR v)
137 {
138     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
139     nsAString value_str;
140     nsresult nsres;
141
142     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
143
144     nsAString_InitDepend(&value_str, v);
145     nsres = nsIDOMHTMLOptionElement_SetValue(This->nsoption, &value_str);
146     nsAString_Finish(&value_str);
147     if(NS_FAILED(nsres))
148         ERR("SetValue failed: %08x\n", nsres);
149
150     return S_OK;
151 }
152
153 static HRESULT WINAPI HTMLOptionElement_get_value(IHTMLOptionElement *iface, BSTR *p)
154 {
155     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
156     nsAString value_str;
157     nsresult nsres;
158
159     TRACE("(%p)->(%p)\n", This, p);
160
161     nsAString_Init(&value_str, NULL);
162     nsres = nsIDOMHTMLOptionElement_GetValue(This->nsoption, &value_str);
163     return return_nsstr(nsres, &value_str, p);
164 }
165
166 static HRESULT WINAPI HTMLOptionElement_put_defaultSelected(IHTMLOptionElement *iface, VARIANT_BOOL v)
167 {
168     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
169     FIXME("(%p)->(%x)\n", This, v);
170     return E_NOTIMPL;
171 }
172
173 static HRESULT WINAPI HTMLOptionElement_get_defaultSelected(IHTMLOptionElement *iface, VARIANT_BOOL *p)
174 {
175     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
176     FIXME("(%p)->(%p)\n", This, p);
177     return E_NOTIMPL;
178 }
179
180 static HRESULT WINAPI HTMLOptionElement_put_index(IHTMLOptionElement *iface, LONG v)
181 {
182     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
183     FIXME("(%p)->(%d)\n", This, v);
184     return E_NOTIMPL;
185 }
186
187 static HRESULT WINAPI HTMLOptionElement_get_index(IHTMLOptionElement *iface, LONG *p)
188 {
189     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
190     FIXME("(%p)->(%p)\n", This, p);
191     return E_NOTIMPL;
192 }
193
194 static HRESULT WINAPI HTMLOptionElement_put_text(IHTMLOptionElement *iface, BSTR v)
195 {
196     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
197     nsIDOMText *text_node;
198     nsAString text_str;
199     nsIDOMNode *tmp;
200     nsresult nsres;
201
202     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
203
204     if(!This->element.node.doc->nsdoc) {
205         WARN("NULL nsdoc\n");
206         return E_UNEXPECTED;
207     }
208
209     while(1) {
210         nsIDOMNode *child;
211
212         nsres = nsIDOMHTMLOptionElement_GetFirstChild(This->nsoption, &child);
213         if(NS_FAILED(nsres) || !child)
214             break;
215
216         nsres = nsIDOMHTMLOptionElement_RemoveChild(This->nsoption, child, &tmp);
217         nsIDOMNode_Release(child);
218         if(NS_SUCCEEDED(nsres)) {
219             nsIDOMNode_Release(tmp);
220         }else {
221             ERR("RemoveChild failed: %08x\n", nsres);
222             break;
223         }
224     }
225
226     nsAString_InitDepend(&text_str, v);
227     nsres = nsIDOMHTMLDocument_CreateTextNode(This->element.node.doc->nsdoc, &text_str, &text_node);
228     nsAString_Finish(&text_str);
229     if(NS_FAILED(nsres)) {
230         ERR("CreateTextNode failed: %08x\n", nsres);
231         return E_FAIL;
232     }
233
234     nsres = nsIDOMHTMLOptionElement_AppendChild(This->nsoption, (nsIDOMNode*)text_node, &tmp);
235     if(NS_SUCCEEDED(nsres))
236         nsIDOMNode_Release(tmp);
237     else
238         ERR("AppendChild failed: %08x\n", nsres);
239
240     return S_OK;
241 }
242
243 static HRESULT WINAPI HTMLOptionElement_get_text(IHTMLOptionElement *iface, BSTR *p)
244 {
245     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
246     nsAString text_str;
247     nsresult nsres;
248
249     TRACE("(%p)->(%p)\n", This, p);
250
251     nsAString_Init(&text_str, NULL);
252     nsres = nsIDOMHTMLOptionElement_GetText(This->nsoption, &text_str);
253     return return_nsstr(nsres, &text_str, p);
254 }
255
256 static HRESULT WINAPI HTMLOptionElement_get_form(IHTMLOptionElement *iface, IHTMLFormElement **p)
257 {
258     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
259     FIXME("(%p)->(%p)\n", This, p);
260     return E_NOTIMPL;
261 }
262
263 static const IHTMLOptionElementVtbl HTMLOptionElementVtbl = {
264     HTMLOptionElement_QueryInterface,
265     HTMLOptionElement_AddRef,
266     HTMLOptionElement_Release,
267     HTMLOptionElement_GetTypeInfoCount,
268     HTMLOptionElement_GetTypeInfo,
269     HTMLOptionElement_GetIDsOfNames,
270     HTMLOptionElement_Invoke,
271     HTMLOptionElement_put_selected,
272     HTMLOptionElement_get_selected,
273     HTMLOptionElement_put_value,
274     HTMLOptionElement_get_value,
275     HTMLOptionElement_put_defaultSelected,
276     HTMLOptionElement_get_defaultSelected,
277     HTMLOptionElement_put_index,
278     HTMLOptionElement_get_index,
279     HTMLOptionElement_put_text,
280     HTMLOptionElement_get_text,
281     HTMLOptionElement_get_form
282 };
283
284 static inline HTMLOptionElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
285 {
286     return CONTAINING_RECORD(iface, HTMLOptionElement, element.node);
287 }
288
289 static HRESULT HTMLOptionElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
290 {
291     HTMLOptionElement *This = impl_from_HTMLDOMNode(iface);
292
293     *ppv = NULL;
294
295     if(IsEqualGUID(&IID_IUnknown, riid)) {
296         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
297         *ppv = &This->IHTMLOptionElement_iface;
298     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
299         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
300         *ppv = &This->IHTMLOptionElement_iface;
301     }else if(IsEqualGUID(&IID_IHTMLOptionElement, riid)) {
302         TRACE("(%p)->(IID_IHTMLOptionElement %p)\n", This, ppv);
303         *ppv = &This->IHTMLOptionElement_iface;
304     }
305
306     if(*ppv) {
307         IUnknown_AddRef((IUnknown*)*ppv);
308         return S_OK;
309     }
310
311     return HTMLElement_QI(&This->element.node, riid, ppv);
312 }
313
314 static const NodeImplVtbl HTMLOptionElementImplVtbl = {
315     HTMLOptionElement_QI,
316     HTMLElement_destructor,
317     HTMLElement_clone,
318     HTMLElement_get_attr_col
319 };
320
321 static const tid_t HTMLOptionElement_iface_tids[] = {
322     HTMLELEMENT_TIDS,
323     IHTMLOptionElement_tid,
324     0
325 };
326 static dispex_static_data_t HTMLOptionElement_dispex = {
327     NULL,
328     DispHTMLOptionElement_tid,
329     NULL,
330     HTMLOptionElement_iface_tids
331 };
332
333 HRESULT HTMLOptionElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
334 {
335     HTMLOptionElement *ret;
336     nsresult nsres;
337
338     ret = heap_alloc_zero(sizeof(HTMLOptionElement));
339     if(!ret)
340         return E_OUTOFMEMORY;
341
342     ret->IHTMLOptionElement_iface.lpVtbl = &HTMLOptionElementVtbl;
343     ret->element.node.vtbl = &HTMLOptionElementImplVtbl;
344
345     HTMLElement_Init(&ret->element, doc, nselem, &HTMLOptionElement_dispex);
346
347     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLOptionElement, (void**)&ret->nsoption);
348
349     /* Share nsoption reference with nsnode */
350     assert(nsres == NS_OK && (nsIDOMNode*)ret->nsoption == ret->element.node.nsnode);
351     nsIDOMNode_Release(ret->element.node.nsnode);
352
353     *elem = &ret->element;
354     return S_OK;
355 }
356
357 static inline HTMLOptionElementFactory *impl_from_IHTMLOptionElementFactory(IHTMLOptionElementFactory *iface)
358 {
359     return CONTAINING_RECORD(iface, HTMLOptionElementFactory, IHTMLOptionElementFactory_iface);
360 }
361
362 static HRESULT WINAPI HTMLOptionElementFactory_QueryInterface(IHTMLOptionElementFactory *iface,
363                                                               REFIID riid, void **ppv)
364 {
365     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
366
367     *ppv = NULL;
368
369     if(IsEqualGUID(&IID_IUnknown, riid)) {
370         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
371         *ppv = &This->IHTMLOptionElementFactory_iface;
372     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
373         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
374         *ppv = &This->IHTMLOptionElementFactory_iface;
375     }else if(IsEqualGUID(&IID_IHTMLOptionElementFactory, riid)) {
376         TRACE("(%p)->(IID_IHTMLOptionElementFactory %p)\n", This, ppv);
377         *ppv = &This->IHTMLOptionElementFactory_iface;
378     }
379
380     if(*ppv) {
381         IUnknown_AddRef((IUnknown*)*ppv);
382         return S_OK;
383     }
384
385     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
386     return E_NOINTERFACE;
387 }
388
389 static ULONG WINAPI HTMLOptionElementFactory_AddRef(IHTMLOptionElementFactory *iface)
390 {
391     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
392     LONG ref = InterlockedIncrement(&This->ref);
393
394     TRACE("(%p) ref=%d\n", This, ref);
395
396     return ref;
397 }
398
399 static ULONG WINAPI HTMLOptionElementFactory_Release(IHTMLOptionElementFactory *iface)
400 {
401     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
402     LONG ref = InterlockedDecrement(&This->ref);
403
404     TRACE("(%p) ref=%d\n", This, ref);
405
406     if(!ref)
407         heap_free(This);
408
409     return ref;
410 }
411
412 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfoCount(IHTMLOptionElementFactory *iface, UINT *pctinfo)
413 {
414     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
415     FIXME("(%p)->(%p)\n", This, pctinfo);
416     return E_NOTIMPL;
417 }
418
419 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfo(IHTMLOptionElementFactory *iface, UINT iTInfo,
420                                               LCID lcid, ITypeInfo **ppTInfo)
421 {
422     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
423     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
424     return E_NOTIMPL;
425 }
426
427 static HRESULT WINAPI HTMLOptionElementFactory_GetIDsOfNames(IHTMLOptionElementFactory *iface, REFIID riid,
428                                                 LPOLESTR *rgszNames, UINT cNames,
429                                                 LCID lcid, DISPID *rgDispId)
430 {
431     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
432     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
433                                         lcid, rgDispId);
434     return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI HTMLOptionElementFactory_Invoke(IHTMLOptionElementFactory *iface, DISPID dispIdMember,
438                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
439                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
440 {
441     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
442     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
443             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
444     return E_NOTIMPL;
445 }
446
447 static HRESULT WINAPI HTMLOptionElementFactory_create(IHTMLOptionElementFactory *iface,
448         VARIANT text, VARIANT value, VARIANT defaultselected, VARIANT selected,
449         IHTMLOptionElement **optelem)
450 {
451     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
452     nsIDOMHTMLElement *nselem;
453     HTMLDOMNode *node;
454     HRESULT hres;
455
456     static const PRUnichar optionW[] = {'O','P','T','I','O','N',0};
457
458     TRACE("(%p)->(%s %s %s %s %p)\n", This, debugstr_variant(&text), debugstr_variant(&value),
459           debugstr_variant(&defaultselected), debugstr_variant(&selected), optelem);
460
461     if(!This->window || !This->window->doc) {
462         WARN("NULL doc\n");
463         return E_UNEXPECTED;
464     }
465
466     *optelem = NULL;
467
468     hres = create_nselem(This->window->doc, optionW, &nselem);
469     if(FAILED(hres))
470         return hres;
471
472     hres = get_node(This->window->doc, (nsIDOMNode*)nselem, TRUE, &node);
473     nsIDOMHTMLElement_Release(nselem);
474     if(FAILED(hres))
475         return hres;
476
477     hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface,
478             &IID_IHTMLOptionElement, (void**)optelem);
479     node_release(node);
480
481     if(V_VT(&text) == VT_BSTR)
482         IHTMLOptionElement_put_text(*optelem, V_BSTR(&text));
483     else if(V_VT(&text) != VT_EMPTY)
484         FIXME("Unsupported text %s\n", debugstr_variant(&text));
485
486     if(V_VT(&value) == VT_BSTR)
487         IHTMLOptionElement_put_value(*optelem, V_BSTR(&value));
488     else if(V_VT(&value) != VT_EMPTY)
489         FIXME("Unsupported value %s\n", debugstr_variant(&value));
490
491     if(V_VT(&defaultselected) != VT_EMPTY)
492         FIXME("Unsupported defaultselected %s\n", debugstr_variant(&defaultselected));
493     if(V_VT(&selected) != VT_EMPTY)
494         FIXME("Unsupported selected %s\n", debugstr_variant(&selected));
495
496     return S_OK;
497 }
498
499 static const IHTMLOptionElementFactoryVtbl HTMLOptionElementFactoryVtbl = {
500     HTMLOptionElementFactory_QueryInterface,
501     HTMLOptionElementFactory_AddRef,
502     HTMLOptionElementFactory_Release,
503     HTMLOptionElementFactory_GetTypeInfoCount,
504     HTMLOptionElementFactory_GetTypeInfo,
505     HTMLOptionElementFactory_GetIDsOfNames,
506     HTMLOptionElementFactory_Invoke,
507     HTMLOptionElementFactory_create
508 };
509
510 HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr)
511 {
512     HTMLOptionElementFactory *ret;
513
514     ret = heap_alloc(sizeof(*ret));
515     if(!ret)
516         return E_OUTOFMEMORY;
517
518     ret->IHTMLOptionElementFactory_iface.lpVtbl = &HTMLOptionElementFactoryVtbl;
519     ret->ref = 1;
520     ret->window = window;
521
522     *ret_ptr = ret;
523     return S_OK;
524 }