wininet: Rename URLCACHECONTAINER to cache_container.
[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_cpc,
318     HTMLElement_clone,
319     HTMLElement_handle_event,
320     HTMLElement_get_attr_col
321 };
322
323 static const tid_t HTMLOptionElement_iface_tids[] = {
324     HTMLELEMENT_TIDS,
325     IHTMLOptionElement_tid,
326     0
327 };
328 static dispex_static_data_t HTMLOptionElement_dispex = {
329     NULL,
330     DispHTMLOptionElement_tid,
331     NULL,
332     HTMLOptionElement_iface_tids
333 };
334
335 HRESULT HTMLOptionElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
336 {
337     HTMLOptionElement *ret;
338     nsresult nsres;
339
340     ret = heap_alloc_zero(sizeof(HTMLOptionElement));
341     if(!ret)
342         return E_OUTOFMEMORY;
343
344     ret->IHTMLOptionElement_iface.lpVtbl = &HTMLOptionElementVtbl;
345     ret->element.node.vtbl = &HTMLOptionElementImplVtbl;
346
347     HTMLElement_Init(&ret->element, doc, nselem, &HTMLOptionElement_dispex);
348
349     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLOptionElement, (void**)&ret->nsoption);
350
351     /* Share nsoption reference with nsnode */
352     assert(nsres == NS_OK && (nsIDOMNode*)ret->nsoption == ret->element.node.nsnode);
353     nsIDOMNode_Release(ret->element.node.nsnode);
354
355     *elem = &ret->element;
356     return S_OK;
357 }
358
359 static inline HTMLOptionElementFactory *impl_from_IHTMLOptionElementFactory(IHTMLOptionElementFactory *iface)
360 {
361     return CONTAINING_RECORD(iface, HTMLOptionElementFactory, IHTMLOptionElementFactory_iface);
362 }
363
364 static HRESULT WINAPI HTMLOptionElementFactory_QueryInterface(IHTMLOptionElementFactory *iface,
365                                                               REFIID riid, void **ppv)
366 {
367     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
368
369     *ppv = NULL;
370
371     if(IsEqualGUID(&IID_IUnknown, riid)) {
372         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
373         *ppv = &This->IHTMLOptionElementFactory_iface;
374     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
375         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
376         *ppv = &This->IHTMLOptionElementFactory_iface;
377     }else if(IsEqualGUID(&IID_IHTMLOptionElementFactory, riid)) {
378         TRACE("(%p)->(IID_IHTMLOptionElementFactory %p)\n", This, ppv);
379         *ppv = &This->IHTMLOptionElementFactory_iface;
380     }
381
382     if(*ppv) {
383         IUnknown_AddRef((IUnknown*)*ppv);
384         return S_OK;
385     }
386
387     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
388     return E_NOINTERFACE;
389 }
390
391 static ULONG WINAPI HTMLOptionElementFactory_AddRef(IHTMLOptionElementFactory *iface)
392 {
393     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
394     LONG ref = InterlockedIncrement(&This->ref);
395
396     TRACE("(%p) ref=%d\n", This, ref);
397
398     return ref;
399 }
400
401 static ULONG WINAPI HTMLOptionElementFactory_Release(IHTMLOptionElementFactory *iface)
402 {
403     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
404     LONG ref = InterlockedDecrement(&This->ref);
405
406     TRACE("(%p) ref=%d\n", This, ref);
407
408     if(!ref)
409         heap_free(This);
410
411     return ref;
412 }
413
414 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfoCount(IHTMLOptionElementFactory *iface, UINT *pctinfo)
415 {
416     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
417     FIXME("(%p)->(%p)\n", This, pctinfo);
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfo(IHTMLOptionElementFactory *iface, UINT iTInfo,
422                                               LCID lcid, ITypeInfo **ppTInfo)
423 {
424     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
425     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
426     return E_NOTIMPL;
427 }
428
429 static HRESULT WINAPI HTMLOptionElementFactory_GetIDsOfNames(IHTMLOptionElementFactory *iface, REFIID riid,
430                                                 LPOLESTR *rgszNames, UINT cNames,
431                                                 LCID lcid, DISPID *rgDispId)
432 {
433     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
434     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
435                                         lcid, rgDispId);
436     return E_NOTIMPL;
437 }
438
439 static HRESULT WINAPI HTMLOptionElementFactory_Invoke(IHTMLOptionElementFactory *iface, DISPID dispIdMember,
440                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
441                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
442 {
443     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
444     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
445             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
446     return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI HTMLOptionElementFactory_create(IHTMLOptionElementFactory *iface,
450         VARIANT text, VARIANT value, VARIANT defaultselected, VARIANT selected,
451         IHTMLOptionElement **optelem)
452 {
453     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
454     nsIDOMHTMLElement *nselem;
455     HTMLDOMNode *node;
456     HRESULT hres;
457
458     static const PRUnichar optionW[] = {'O','P','T','I','O','N',0};
459
460     TRACE("(%p)->(%s %s %s %s %p)\n", This, debugstr_variant(&text), debugstr_variant(&value),
461           debugstr_variant(&defaultselected), debugstr_variant(&selected), optelem);
462
463     if(!This->window || !This->window->doc) {
464         WARN("NULL doc\n");
465         return E_UNEXPECTED;
466     }
467
468     *optelem = NULL;
469
470     hres = create_nselem(This->window->doc, optionW, &nselem);
471     if(FAILED(hres))
472         return hres;
473
474     hres = get_node(This->window->doc, (nsIDOMNode*)nselem, TRUE, &node);
475     nsIDOMHTMLElement_Release(nselem);
476     if(FAILED(hres))
477         return hres;
478
479     hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface,
480             &IID_IHTMLOptionElement, (void**)optelem);
481     node_release(node);
482
483     if(V_VT(&text) == VT_BSTR)
484         IHTMLOptionElement_put_text(*optelem, V_BSTR(&text));
485     else if(V_VT(&text) != VT_EMPTY)
486         FIXME("Unsupported text %s\n", debugstr_variant(&text));
487
488     if(V_VT(&value) == VT_BSTR)
489         IHTMLOptionElement_put_value(*optelem, V_BSTR(&value));
490     else if(V_VT(&value) != VT_EMPTY)
491         FIXME("Unsupported value %s\n", debugstr_variant(&value));
492
493     if(V_VT(&defaultselected) != VT_EMPTY)
494         FIXME("Unsupported defaultselected %s\n", debugstr_variant(&defaultselected));
495     if(V_VT(&selected) != VT_EMPTY)
496         FIXME("Unsupported selected %s\n", debugstr_variant(&selected));
497
498     return S_OK;
499 }
500
501 static const IHTMLOptionElementFactoryVtbl HTMLOptionElementFactoryVtbl = {
502     HTMLOptionElementFactory_QueryInterface,
503     HTMLOptionElementFactory_AddRef,
504     HTMLOptionElementFactory_Release,
505     HTMLOptionElementFactory_GetTypeInfoCount,
506     HTMLOptionElementFactory_GetTypeInfo,
507     HTMLOptionElementFactory_GetIDsOfNames,
508     HTMLOptionElementFactory_Invoke,
509     HTMLOptionElementFactory_create
510 };
511
512 HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr)
513 {
514     HTMLOptionElementFactory *ret;
515
516     ret = heap_alloc(sizeof(*ret));
517     if(!ret)
518         return E_OUTOFMEMORY;
519
520     ret->IHTMLOptionElementFactory_iface.lpVtbl = &HTMLOptionElementFactoryVtbl;
521     ret->ref = 1;
522     ret->window = window;
523
524     *ret_ptr = ret;
525     return S_OK;
526 }