2 * Copyright 2006 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
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
38 IHTMLSelectElement IHTMLSelectElement_iface
;
40 nsIDOMHTMLSelectElement
*nsselect
;
43 static inline HTMLSelectElement
*impl_from_IHTMLSelectElement(IHTMLSelectElement
*iface
)
45 return CONTAINING_RECORD(iface
, HTMLSelectElement
, IHTMLSelectElement_iface
);
48 static HRESULT
htmlselect_item(HTMLSelectElement
*This
, int i
, IDispatch
**ret
)
50 nsIDOMHTMLOptionsCollection
*nscol
;
55 nsres
= nsIDOMHTMLSelectElement_GetOptions(This
->nsselect
, &nscol
);
56 if(NS_FAILED(nsres
)) {
57 ERR("GetOptions failed: %08x\n", nsres
);
61 nsres
= nsIDOMHTMLOptionsCollection_Item(nscol
, i
, &nsnode
);
62 nsIDOMHTMLOptionsCollection_Release(nscol
);
63 if(NS_FAILED(nsres
)) {
64 ERR("Item failed: %08x\n", nsres
);
71 hres
= get_node(This
->element
.node
.doc
, nsnode
, TRUE
, &node
);
72 nsIDOMNode_Release(nsnode
);
76 IHTMLDOMNode_AddRef(&node
->IHTMLDOMNode_iface
);
77 *ret
= (IDispatch
*)&node
->IHTMLDOMNode_iface
;
84 static HRESULT WINAPI
HTMLSelectElement_QueryInterface(IHTMLSelectElement
*iface
,
85 REFIID riid
, void **ppv
)
87 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
89 return IHTMLDOMNode_QueryInterface(&This
->element
.node
.IHTMLDOMNode_iface
, riid
, ppv
);
92 static ULONG WINAPI
HTMLSelectElement_AddRef(IHTMLSelectElement
*iface
)
94 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
96 return IHTMLDOMNode_AddRef(&This
->element
.node
.IHTMLDOMNode_iface
);
99 static ULONG WINAPI
HTMLSelectElement_Release(IHTMLSelectElement
*iface
)
101 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
103 return IHTMLDOMNode_Release(&This
->element
.node
.IHTMLDOMNode_iface
);
106 static HRESULT WINAPI
HTMLSelectElement_GetTypeInfoCount(IHTMLSelectElement
*iface
, UINT
*pctinfo
)
108 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
110 return IDispatchEx_GetTypeInfoCount(&This
->element
.node
.dispex
.IDispatchEx_iface
, pctinfo
);
113 static HRESULT WINAPI
HTMLSelectElement_GetTypeInfo(IHTMLSelectElement
*iface
, UINT iTInfo
,
114 LCID lcid
, ITypeInfo
**ppTInfo
)
116 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
118 return IDispatchEx_GetTypeInfo(&This
->element
.node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
,
122 static HRESULT WINAPI
HTMLSelectElement_GetIDsOfNames(IHTMLSelectElement
*iface
, REFIID riid
,
123 LPOLESTR
*rgszNames
, UINT cNames
,
124 LCID lcid
, DISPID
*rgDispId
)
126 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
128 return IDispatchEx_GetIDsOfNames(&This
->element
.node
.dispex
.IDispatchEx_iface
, riid
, rgszNames
,
129 cNames
, lcid
, rgDispId
);
132 static HRESULT WINAPI
HTMLSelectElement_Invoke(IHTMLSelectElement
*iface
, DISPID dispIdMember
,
133 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
134 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
136 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
138 return IDispatchEx_Invoke(&This
->element
.node
.dispex
.IDispatchEx_iface
, dispIdMember
, riid
,
139 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
142 static HRESULT WINAPI
HTMLSelectElement_put_size(IHTMLSelectElement
*iface
, LONG v
)
144 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
145 FIXME("(%p)->(%d)\n", This
, v
);
149 static HRESULT WINAPI
HTMLSelectElement_get_size(IHTMLSelectElement
*iface
, LONG
*p
)
151 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
152 FIXME("(%p)->(%p)\n", This
, p
);
156 static HRESULT WINAPI
HTMLSelectElement_put_multiple(IHTMLSelectElement
*iface
, VARIANT_BOOL v
)
158 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
159 FIXME("(%p)->(%x)\n", This
, v
);
163 static HRESULT WINAPI
HTMLSelectElement_get_multiple(IHTMLSelectElement
*iface
, VARIANT_BOOL
*p
)
165 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
166 FIXME("(%p)->(%p)\n", This
, p
);
170 static HRESULT WINAPI
HTMLSelectElement_put_name(IHTMLSelectElement
*iface
, BSTR v
)
172 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
173 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
177 static HRESULT WINAPI
HTMLSelectElement_get_name(IHTMLSelectElement
*iface
, BSTR
*p
)
179 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
181 const PRUnichar
*name
= NULL
;
184 TRACE("(%p)->(%p)\n", This
, p
);
186 nsAString_Init(&name_str
, NULL
);
188 nsres
= nsIDOMHTMLSelectElement_GetName(This
->nsselect
, &name_str
);
189 if(NS_SUCCEEDED(nsres
)) {
190 static const WCHAR wszGarbage
[] = {'g','a','r','b','a','g','e',0};
192 nsAString_GetData(&name_str
, &name
);
195 * Native never returns empty string here. If an element has no name,
196 * name of previous element or ramdom data is returned.
198 *p
= SysAllocString(*name
? name
: wszGarbage
);
200 ERR("GetName failed: %08x\n", nsres
);
203 nsAString_Finish(&name_str
);
205 TRACE("name=%s\n", debugstr_w(*p
));
209 static HRESULT WINAPI
HTMLSelectElement_get_options(IHTMLSelectElement
*iface
, IDispatch
**p
)
211 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
213 TRACE("(%p)->(%p)\n", This
, p
);
215 *p
= (IDispatch
*)&This
->IHTMLSelectElement_iface
;
216 IDispatch_AddRef(*p
);
220 static HRESULT WINAPI
HTMLSelectElement_put_onchange(IHTMLSelectElement
*iface
, VARIANT v
)
222 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
224 TRACE("(%p)->()\n", This
);
226 return set_node_event(&This
->element
.node
, EVENTID_CHANGE
, &v
);
229 static HRESULT WINAPI
HTMLSelectElement_get_onchange(IHTMLSelectElement
*iface
, VARIANT
*p
)
231 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
232 FIXME("(%p)->(%p)\n", This
, p
);
236 static HRESULT WINAPI
HTMLSelectElement_put_selectedIndex(IHTMLSelectElement
*iface
, LONG v
)
238 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
241 TRACE("(%p)->(%d)\n", This
, v
);
243 nsres
= nsIDOMHTMLSelectElement_SetSelectedIndex(This
->nsselect
, v
);
245 ERR("SetSelectedIndex failed: %08x\n", nsres
);
250 static HRESULT WINAPI
HTMLSelectElement_get_selectedIndex(IHTMLSelectElement
*iface
, LONG
*p
)
252 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
256 TRACE("(%p)->(%p)\n", This
, p
);
258 nsres
= nsIDOMHTMLSelectElement_GetSelectedIndex(This
->nsselect
, &idx
);
260 ERR("GetSelectedIndex failed: %08x\n", nsres
);
266 static HRESULT WINAPI
HTMLSelectElement_get_type(IHTMLSelectElement
*iface
, BSTR
*p
)
268 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
269 const PRUnichar
*type
;
274 TRACE("(%p)->(%p)\n", This
, p
);
276 nsAString_Init(&type_str
, NULL
);
277 nsres
= nsIDOMHTMLSelectElement_GetType(This
->nsselect
, &type_str
);
278 if(NS_SUCCEEDED(nsres
)) {
279 nsAString_GetData(&type_str
, &type
);
280 *p
= *type
? SysAllocString(type
) : NULL
;
282 ERR("GetType failed: %08x\n", nsres
);
286 nsAString_Finish(&type_str
);
291 static HRESULT WINAPI
HTMLSelectElement_put_value(IHTMLSelectElement
*iface
, BSTR v
)
293 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
297 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
299 nsAString_InitDepend(&value_str
, v
);
300 nsres
= nsIDOMHTMLSelectElement_SetValue(This
->nsselect
, &value_str
);
301 nsAString_Finish(&value_str
);
303 ERR("SetValue failed: %08x\n", nsres
);
308 static HRESULT WINAPI
HTMLSelectElement_get_value(IHTMLSelectElement
*iface
, BSTR
*p
)
310 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
312 const PRUnichar
*value
= NULL
;
315 TRACE("(%p)->(%p)\n", This
, p
);
317 nsAString_Init(&value_str
, NULL
);
319 nsres
= nsIDOMHTMLSelectElement_GetValue(This
->nsselect
, &value_str
);
320 if(NS_SUCCEEDED(nsres
)) {
321 nsAString_GetData(&value_str
, &value
);
322 *p
= *value
? SysAllocString(value
) : NULL
;
324 ERR("GetValue failed: %08x\n", nsres
);
327 nsAString_Finish(&value_str
);
329 TRACE("value=%s\n", debugstr_w(*p
));
333 static HRESULT WINAPI
HTMLSelectElement_put_disabled(IHTMLSelectElement
*iface
, VARIANT_BOOL v
)
335 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
338 TRACE("(%p)->(%x)\n", This
, v
);
340 nsres
= nsIDOMHTMLSelectElement_SetDisabled(This
->nsselect
, v
!= VARIANT_FALSE
);
341 if(NS_FAILED(nsres
)) {
342 ERR("SetDisabled failed: %08x\n", nsres
);
349 static HRESULT WINAPI
HTMLSelectElement_get_disabled(IHTMLSelectElement
*iface
, VARIANT_BOOL
*p
)
351 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
352 PRBool disabled
= FALSE
;
355 TRACE("(%p)->(%p)\n", This
, p
);
357 nsres
= nsIDOMHTMLSelectElement_GetDisabled(This
->nsselect
, &disabled
);
358 if(NS_FAILED(nsres
)) {
359 ERR("GetDisabled failed: %08x\n", nsres
);
363 *p
= disabled
? VARIANT_TRUE
: VARIANT_FALSE
;
367 static HRESULT WINAPI
HTMLSelectElement_get_form(IHTMLSelectElement
*iface
, IHTMLFormElement
**p
)
369 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
370 FIXME("(%p)->(%p)\n", This
, p
);
374 static HRESULT WINAPI
HTMLSelectElement_add(IHTMLSelectElement
*iface
, IHTMLElement
*element
,
377 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
378 IHTMLDOMNode
*node
, *tmp
;
381 FIXME("(%p)->(%p %s): semi-stub\n", This
, element
, debugstr_variant(&before
));
383 if(V_VT(&before
) != VT_EMPTY
) {
384 FIXME("unhandled before %s\n", debugstr_variant(&before
));
388 hres
= IHTMLElement_QueryInterface(element
, &IID_IHTMLDOMNode
, (void**)&node
);
392 hres
= IHTMLDOMNode_appendChild(&This
->element
.node
.IHTMLDOMNode_iface
, node
, &tmp
);
393 IHTMLDOMNode_Release(node
);
394 if(SUCCEEDED(hres
) && tmp
)
395 IHTMLDOMNode_Release(tmp
);
400 static HRESULT WINAPI
HTMLSelectElement_remove(IHTMLSelectElement
*iface
, LONG index
)
402 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
403 FIXME("(%p)->(%d)\n", This
, index
);
407 static HRESULT WINAPI
HTMLSelectElement_put_length(IHTMLSelectElement
*iface
, LONG v
)
409 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
412 TRACE("(%p)->(%d)\n", This
, v
);
414 nsres
= nsIDOMHTMLSelectElement_SetLength(This
->nsselect
, v
);
416 ERR("SetLength failed: %08x\n", nsres
);
421 static HRESULT WINAPI
HTMLSelectElement_get_length(IHTMLSelectElement
*iface
, LONG
*p
)
423 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
427 TRACE("(%p)->(%p)\n", This
, p
);
429 nsres
= nsIDOMHTMLSelectElement_GetLength(This
->nsselect
, &length
);
431 ERR("GetLength failed: %08x\n", nsres
);
435 TRACE("ret %d\n", *p
);
439 static HRESULT WINAPI
HTMLSelectElement_get__newEnum(IHTMLSelectElement
*iface
, IUnknown
**p
)
441 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
442 FIXME("(%p)->(%p)\n", This
, p
);
446 static HRESULT WINAPI
HTMLSelectElement_item(IHTMLSelectElement
*iface
, VARIANT name
,
447 VARIANT index
, IDispatch
**pdisp
)
449 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
451 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&name
), debugstr_variant(&index
), pdisp
);
457 if(V_VT(&name
) == VT_I4
) {
460 return htmlselect_item(This
, V_I4(&name
), pdisp
);
463 FIXME("Unsupported args\n");
467 static HRESULT WINAPI
HTMLSelectElement_tags(IHTMLSelectElement
*iface
, VARIANT tagName
,
470 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
471 FIXME("(%p)->(v %p)\n", This
, pdisp
);
475 static const IHTMLSelectElementVtbl HTMLSelectElementVtbl
= {
476 HTMLSelectElement_QueryInterface
,
477 HTMLSelectElement_AddRef
,
478 HTMLSelectElement_Release
,
479 HTMLSelectElement_GetTypeInfoCount
,
480 HTMLSelectElement_GetTypeInfo
,
481 HTMLSelectElement_GetIDsOfNames
,
482 HTMLSelectElement_Invoke
,
483 HTMLSelectElement_put_size
,
484 HTMLSelectElement_get_size
,
485 HTMLSelectElement_put_multiple
,
486 HTMLSelectElement_get_multiple
,
487 HTMLSelectElement_put_name
,
488 HTMLSelectElement_get_name
,
489 HTMLSelectElement_get_options
,
490 HTMLSelectElement_put_onchange
,
491 HTMLSelectElement_get_onchange
,
492 HTMLSelectElement_put_selectedIndex
,
493 HTMLSelectElement_get_selectedIndex
,
494 HTMLSelectElement_get_type
,
495 HTMLSelectElement_put_value
,
496 HTMLSelectElement_get_value
,
497 HTMLSelectElement_put_disabled
,
498 HTMLSelectElement_get_disabled
,
499 HTMLSelectElement_get_form
,
500 HTMLSelectElement_add
,
501 HTMLSelectElement_remove
,
502 HTMLSelectElement_put_length
,
503 HTMLSelectElement_get_length
,
504 HTMLSelectElement_get__newEnum
,
505 HTMLSelectElement_item
,
506 HTMLSelectElement_tags
509 static inline HTMLSelectElement
*impl_from_HTMLDOMNode(HTMLDOMNode
*iface
)
511 return CONTAINING_RECORD(iface
, HTMLSelectElement
, element
.node
);
514 static HRESULT
HTMLSelectElement_QI(HTMLDOMNode
*iface
, REFIID riid
, void **ppv
)
516 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
520 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
521 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
522 *ppv
= &This
->IHTMLSelectElement_iface
;
523 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
524 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
525 *ppv
= &This
->IHTMLSelectElement_iface
;
526 }else if(IsEqualGUID(&IID_IHTMLSelectElement
, riid
)) {
527 TRACE("(%p)->(IID_IHTMLSelectElement %p)\n", This
, ppv
);
528 *ppv
= &This
->IHTMLSelectElement_iface
;
532 IUnknown_AddRef((IUnknown
*)*ppv
);
536 return HTMLElement_QI(&This
->element
.node
, riid
, ppv
);
539 static void HTMLSelectElement_destructor(HTMLDOMNode
*iface
)
541 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
543 nsIDOMHTMLSelectElement_Release(This
->nsselect
);
545 HTMLElement_destructor(&This
->element
.node
);
548 static HRESULT
HTMLSelectElementImpl_put_disabled(HTMLDOMNode
*iface
, VARIANT_BOOL v
)
550 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
551 return IHTMLSelectElement_put_disabled(&This
->IHTMLSelectElement_iface
, v
);
554 static HRESULT
HTMLSelectElementImpl_get_disabled(HTMLDOMNode
*iface
, VARIANT_BOOL
*p
)
556 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
557 return IHTMLSelectElement_get_disabled(&This
->IHTMLSelectElement_iface
, p
);
560 #define DISPID_OPTIONCOL_0 MSHTML_DISPID_CUSTOM_MIN
562 static HRESULT
HTMLSelectElement_get_dispid(HTMLDOMNode
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
567 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++) {
568 idx
= idx
*10 + (*ptr
-'0');
569 if(idx
> MSHTML_CUSTOM_DISPID_CNT
) {
570 WARN("too big idx\n");
571 return DISP_E_UNKNOWNNAME
;
575 return DISP_E_UNKNOWNNAME
;
577 *dispid
= DISPID_OPTIONCOL_0
+ idx
;
581 static HRESULT
HTMLSelectElement_invoke(HTMLDOMNode
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
582 VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
584 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
586 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
, caller
);
589 case DISPATCH_PROPERTYGET
: {
593 hres
= htmlselect_item(This
, id
-DISPID_OPTIONCOL_0
, &ret
);
598 V_VT(res
) = VT_DISPATCH
;
599 V_DISPATCH(res
) = ret
;
607 FIXME("unimplemented flags %x\n", flags
);
614 static const NodeImplVtbl HTMLSelectElementImplVtbl
= {
615 HTMLSelectElement_QI
,
616 HTMLSelectElement_destructor
,
620 HTMLSelectElementImpl_put_disabled
,
621 HTMLSelectElementImpl_get_disabled
,
624 HTMLSelectElement_get_dispid
,
625 HTMLSelectElement_invoke
628 static const tid_t HTMLSelectElement_tids
[] = {
630 IHTMLSelectElement_tid
,
634 static dispex_static_data_t HTMLSelectElement_dispex
= {
636 DispHTMLSelectElement_tid
,
638 HTMLSelectElement_tids
641 HRESULT
HTMLSelectElement_Create(HTMLDocumentNode
*doc
, nsIDOMHTMLElement
*nselem
, HTMLElement
**elem
)
643 HTMLSelectElement
*ret
;
646 ret
= heap_alloc_zero(sizeof(HTMLSelectElement
));
648 return E_OUTOFMEMORY
;
650 ret
->IHTMLSelectElement_iface
.lpVtbl
= &HTMLSelectElementVtbl
;
651 ret
->element
.node
.vtbl
= &HTMLSelectElementImplVtbl
;
653 nsres
= nsIDOMHTMLElement_QueryInterface(nselem
, &IID_nsIDOMHTMLSelectElement
,
654 (void**)&ret
->nsselect
);
655 if(NS_FAILED(nsres
)) {
656 ERR("Could not get nsIDOMHTMLSelectElement interfce: %08x\n", nsres
);
661 HTMLElement_Init(&ret
->element
, doc
, nselem
, &HTMLSelectElement_dispex
);
663 *elem
= &ret
->element
;