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
19 #include "mshtml_private.h"
24 IHTMLSelectElement IHTMLSelectElement_iface
;
26 nsIDOMHTMLSelectElement
*nsselect
;
29 static inline HTMLSelectElement
*impl_from_IHTMLSelectElement(IHTMLSelectElement
*iface
)
31 return CONTAINING_RECORD(iface
, HTMLSelectElement
, IHTMLSelectElement_iface
);
34 static HRESULT
htmlselect_item(HTMLSelectElement
*This
, int i
, IDispatch
**ret
)
36 nsIDOMHTMLOptionsCollection
*nscol
;
41 nsres
= nsIDOMHTMLSelectElement_GetOptions(This
->nsselect
, &nscol
);
42 if(NS_FAILED(nsres
)) {
43 ERR("GetOptions failed: %08x\n", nsres
);
47 nsres
= nsIDOMHTMLOptionsCollection_Item(nscol
, i
, &nsnode
);
48 nsIDOMHTMLOptionsCollection_Release(nscol
);
49 if(NS_FAILED(nsres
)) {
50 ERR("Item failed: %08x\n", nsres
);
57 hres
= get_node(This
->element
.node
.doc
, nsnode
, TRUE
, &node
);
58 nsIDOMNode_Release(nsnode
);
62 *ret
= (IDispatch
*)&node
->IHTMLDOMNode_iface
;
69 static HRESULT WINAPI
HTMLSelectElement_QueryInterface(IHTMLSelectElement
*iface
,
70 REFIID riid
, void **ppv
)
72 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
74 return IHTMLDOMNode_QueryInterface(&This
->element
.node
.IHTMLDOMNode_iface
, riid
, ppv
);
77 static ULONG WINAPI
HTMLSelectElement_AddRef(IHTMLSelectElement
*iface
)
79 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
81 return IHTMLDOMNode_AddRef(&This
->element
.node
.IHTMLDOMNode_iface
);
84 static ULONG WINAPI
HTMLSelectElement_Release(IHTMLSelectElement
*iface
)
86 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
88 return IHTMLDOMNode_Release(&This
->element
.node
.IHTMLDOMNode_iface
);
91 static HRESULT WINAPI
HTMLSelectElement_GetTypeInfoCount(IHTMLSelectElement
*iface
, UINT
*pctinfo
)
93 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
95 return IDispatchEx_GetTypeInfoCount(&This
->element
.node
.dispex
.IDispatchEx_iface
, pctinfo
);
98 static HRESULT WINAPI
HTMLSelectElement_GetTypeInfo(IHTMLSelectElement
*iface
, UINT iTInfo
,
99 LCID lcid
, ITypeInfo
**ppTInfo
)
101 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
103 return IDispatchEx_GetTypeInfo(&This
->element
.node
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
,
107 static HRESULT WINAPI
HTMLSelectElement_GetIDsOfNames(IHTMLSelectElement
*iface
, REFIID riid
,
108 LPOLESTR
*rgszNames
, UINT cNames
,
109 LCID lcid
, DISPID
*rgDispId
)
111 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
113 return IDispatchEx_GetIDsOfNames(&This
->element
.node
.dispex
.IDispatchEx_iface
, riid
, rgszNames
,
114 cNames
, lcid
, rgDispId
);
117 static HRESULT WINAPI
HTMLSelectElement_Invoke(IHTMLSelectElement
*iface
, DISPID dispIdMember
,
118 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
119 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
121 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
123 return IDispatchEx_Invoke(&This
->element
.node
.dispex
.IDispatchEx_iface
, dispIdMember
, riid
,
124 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
127 static HRESULT WINAPI
HTMLSelectElement_put_size(IHTMLSelectElement
*iface
, LONG v
)
129 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
130 FIXME("(%p)->(%d)\n", This
, v
);
134 static HRESULT WINAPI
HTMLSelectElement_get_size(IHTMLSelectElement
*iface
, LONG
*p
)
136 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
137 FIXME("(%p)->(%p)\n", This
, p
);
141 static HRESULT WINAPI
HTMLSelectElement_put_multiple(IHTMLSelectElement
*iface
, VARIANT_BOOL v
)
143 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
146 TRACE("(%p)->(%x)\n", This
, v
);
148 nsres
= nsIDOMHTMLSelectElement_SetMultiple(This
->nsselect
, !!v
);
149 assert(nsres
== NS_OK
);
153 static HRESULT WINAPI
HTMLSelectElement_get_multiple(IHTMLSelectElement
*iface
, VARIANT_BOOL
*p
)
155 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
159 TRACE("(%p)->(%p)\n", This
, p
);
161 nsres
= nsIDOMHTMLSelectElement_GetMultiple(This
->nsselect
, &val
);
162 assert(nsres
== NS_OK
);
164 *p
= val
? VARIANT_TRUE
: VARIANT_FALSE
;
168 static HRESULT WINAPI
HTMLSelectElement_put_name(IHTMLSelectElement
*iface
, BSTR v
)
170 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
171 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
175 static HRESULT WINAPI
HTMLSelectElement_get_name(IHTMLSelectElement
*iface
, BSTR
*p
)
177 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
179 const PRUnichar
*name
= NULL
;
182 TRACE("(%p)->(%p)\n", This
, p
);
184 nsAString_Init(&name_str
, NULL
);
186 nsres
= nsIDOMHTMLSelectElement_GetName(This
->nsselect
, &name_str
);
187 if(NS_SUCCEEDED(nsres
)) {
188 static const WCHAR wszGarbage
[] = {'g','a','r','b','a','g','e',0};
190 nsAString_GetData(&name_str
, &name
);
193 * Native never returns empty string here. If an element has no name,
194 * name of previous element or ramdom data is returned.
196 *p
= SysAllocString(*name
? name
: wszGarbage
);
198 ERR("GetName failed: %08x\n", nsres
);
201 nsAString_Finish(&name_str
);
203 TRACE("name=%s\n", debugstr_w(*p
));
207 static HRESULT WINAPI
HTMLSelectElement_get_options(IHTMLSelectElement
*iface
, IDispatch
**p
)
209 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
211 TRACE("(%p)->(%p)\n", This
, p
);
213 *p
= (IDispatch
*)&This
->IHTMLSelectElement_iface
;
214 IDispatch_AddRef(*p
);
218 static HRESULT WINAPI
HTMLSelectElement_put_onchange(IHTMLSelectElement
*iface
, VARIANT v
)
220 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
222 TRACE("(%p)->()\n", This
);
224 return set_node_event(&This
->element
.node
, EVENTID_CHANGE
, &v
);
227 static HRESULT WINAPI
HTMLSelectElement_get_onchange(IHTMLSelectElement
*iface
, VARIANT
*p
)
229 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
230 FIXME("(%p)->(%p)\n", This
, p
);
234 static HRESULT WINAPI
HTMLSelectElement_put_selectedIndex(IHTMLSelectElement
*iface
, LONG v
)
236 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
239 TRACE("(%p)->(%d)\n", This
, v
);
241 nsres
= nsIDOMHTMLSelectElement_SetSelectedIndex(This
->nsselect
, v
);
243 ERR("SetSelectedIndex failed: %08x\n", nsres
);
248 static HRESULT WINAPI
HTMLSelectElement_get_selectedIndex(IHTMLSelectElement
*iface
, LONG
*p
)
250 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
253 TRACE("(%p)->(%p)\n", This
, p
);
255 nsres
= nsIDOMHTMLSelectElement_GetSelectedIndex(This
->nsselect
, p
);
256 if(NS_FAILED(nsres
)) {
257 ERR("GetSelectedIndex failed: %08x\n", nsres
);
264 static HRESULT WINAPI
HTMLSelectElement_get_type(IHTMLSelectElement
*iface
, BSTR
*p
)
266 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
270 TRACE("(%p)->(%p)\n", This
, p
);
272 nsAString_Init(&type_str
, NULL
);
273 nsres
= nsIDOMHTMLSelectElement_GetType(This
->nsselect
, &type_str
);
274 return return_nsstr(nsres
, &type_str
, p
);
277 static HRESULT WINAPI
HTMLSelectElement_put_value(IHTMLSelectElement
*iface
, BSTR v
)
279 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
283 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
285 nsAString_InitDepend(&value_str
, v
);
286 nsres
= nsIDOMHTMLSelectElement_SetValue(This
->nsselect
, &value_str
);
287 nsAString_Finish(&value_str
);
289 ERR("SetValue failed: %08x\n", nsres
);
294 static HRESULT WINAPI
HTMLSelectElement_get_value(IHTMLSelectElement
*iface
, BSTR
*p
)
296 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
300 TRACE("(%p)->(%p)\n", This
, p
);
302 nsAString_Init(&value_str
, NULL
);
303 nsres
= nsIDOMHTMLSelectElement_GetValue(This
->nsselect
, &value_str
);
304 return return_nsstr(nsres
, &value_str
, p
);
307 static HRESULT WINAPI
HTMLSelectElement_put_disabled(IHTMLSelectElement
*iface
, VARIANT_BOOL v
)
309 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
312 TRACE("(%p)->(%x)\n", This
, v
);
314 nsres
= nsIDOMHTMLSelectElement_SetDisabled(This
->nsselect
, v
!= VARIANT_FALSE
);
315 if(NS_FAILED(nsres
)) {
316 ERR("SetDisabled failed: %08x\n", nsres
);
323 static HRESULT WINAPI
HTMLSelectElement_get_disabled(IHTMLSelectElement
*iface
, VARIANT_BOOL
*p
)
325 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
326 cpp_bool disabled
= FALSE
;
329 TRACE("(%p)->(%p)\n", This
, p
);
331 nsres
= nsIDOMHTMLSelectElement_GetDisabled(This
->nsselect
, &disabled
);
332 if(NS_FAILED(nsres
)) {
333 ERR("GetDisabled failed: %08x\n", nsres
);
337 *p
= disabled
? VARIANT_TRUE
: VARIANT_FALSE
;
341 static HRESULT WINAPI
HTMLSelectElement_get_form(IHTMLSelectElement
*iface
, IHTMLFormElement
**p
)
343 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
344 FIXME("(%p)->(%p)\n", This
, p
);
348 static HRESULT WINAPI
HTMLSelectElement_add(IHTMLSelectElement
*iface
, IHTMLElement
*element
,
351 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
352 nsIWritableVariant
*nsvariant
;
353 HTMLElement
*element_obj
;
356 TRACE("(%p)->(%p %s)\n", This
, element
, debugstr_variant(&before
));
358 element_obj
= unsafe_impl_from_IHTMLElement(element
);
360 FIXME("External IHTMLElement implementation?\n");
364 nsvariant
= create_nsvariant();
368 switch(V_VT(&before
)) {
370 nsres
= nsIWritableVariant_SetAsEmpty(nsvariant
);
373 nsres
= nsIWritableVariant_SetAsInt16(nsvariant
, V_I2(&before
));
376 FIXME("unhandled before %s\n", debugstr_variant(&before
));
377 nsIWritableVariant_Release(nsvariant
);
381 if(NS_SUCCEEDED(nsres
))
382 nsres
= nsIDOMHTMLSelectElement_Add(This
->nsselect
, element_obj
->nselem
, (nsIVariant
*)nsvariant
);
383 nsIWritableVariant_Release(nsvariant
);
384 if(NS_FAILED(nsres
)) {
385 ERR("Add failed: %08x\n", nsres
);
392 static HRESULT WINAPI
HTMLSelectElement_remove(IHTMLSelectElement
*iface
, LONG index
)
394 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
396 TRACE("(%p)->(%d)\n", This
, index
);
397 nsres
= nsIDOMHTMLSelectElement_select_Remove(This
->nsselect
, index
);
398 if(NS_FAILED(nsres
)) {
399 ERR("Remove failed: %08x\n", nsres
);
405 static HRESULT WINAPI
HTMLSelectElement_put_length(IHTMLSelectElement
*iface
, LONG v
)
407 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
410 TRACE("(%p)->(%d)\n", This
, v
);
412 nsres
= nsIDOMHTMLSelectElement_SetLength(This
->nsselect
, v
);
414 ERR("SetLength failed: %08x\n", nsres
);
419 static HRESULT WINAPI
HTMLSelectElement_get_length(IHTMLSelectElement
*iface
, LONG
*p
)
421 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
425 TRACE("(%p)->(%p)\n", This
, p
);
427 nsres
= nsIDOMHTMLSelectElement_GetLength(This
->nsselect
, &length
);
429 ERR("GetLength failed: %08x\n", nsres
);
433 TRACE("ret %d\n", *p
);
437 static HRESULT WINAPI
HTMLSelectElement_get__newEnum(IHTMLSelectElement
*iface
, IUnknown
**p
)
439 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
440 FIXME("(%p)->(%p)\n", This
, p
);
444 static HRESULT WINAPI
HTMLSelectElement_item(IHTMLSelectElement
*iface
, VARIANT name
,
445 VARIANT index
, IDispatch
**pdisp
)
447 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
449 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&name
), debugstr_variant(&index
), pdisp
);
455 if(V_VT(&name
) == VT_I4
) {
458 return htmlselect_item(This
, V_I4(&name
), pdisp
);
461 FIXME("Unsupported args\n");
465 static HRESULT WINAPI
HTMLSelectElement_tags(IHTMLSelectElement
*iface
, VARIANT tagName
,
468 HTMLSelectElement
*This
= impl_from_IHTMLSelectElement(iface
);
469 FIXME("(%p)->(v %p)\n", This
, pdisp
);
473 static const IHTMLSelectElementVtbl HTMLSelectElementVtbl
= {
474 HTMLSelectElement_QueryInterface
,
475 HTMLSelectElement_AddRef
,
476 HTMLSelectElement_Release
,
477 HTMLSelectElement_GetTypeInfoCount
,
478 HTMLSelectElement_GetTypeInfo
,
479 HTMLSelectElement_GetIDsOfNames
,
480 HTMLSelectElement_Invoke
,
481 HTMLSelectElement_put_size
,
482 HTMLSelectElement_get_size
,
483 HTMLSelectElement_put_multiple
,
484 HTMLSelectElement_get_multiple
,
485 HTMLSelectElement_put_name
,
486 HTMLSelectElement_get_name
,
487 HTMLSelectElement_get_options
,
488 HTMLSelectElement_put_onchange
,
489 HTMLSelectElement_get_onchange
,
490 HTMLSelectElement_put_selectedIndex
,
491 HTMLSelectElement_get_selectedIndex
,
492 HTMLSelectElement_get_type
,
493 HTMLSelectElement_put_value
,
494 HTMLSelectElement_get_value
,
495 HTMLSelectElement_put_disabled
,
496 HTMLSelectElement_get_disabled
,
497 HTMLSelectElement_get_form
,
498 HTMLSelectElement_add
,
499 HTMLSelectElement_remove
,
500 HTMLSelectElement_put_length
,
501 HTMLSelectElement_get_length
,
502 HTMLSelectElement_get__newEnum
,
503 HTMLSelectElement_item
,
504 HTMLSelectElement_tags
507 static inline HTMLSelectElement
*impl_from_HTMLDOMNode(HTMLDOMNode
*iface
)
509 return CONTAINING_RECORD(iface
, HTMLSelectElement
, element
.node
);
512 static HRESULT
HTMLSelectElement_QI(HTMLDOMNode
*iface
, REFIID riid
, void **ppv
)
514 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
518 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
519 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
520 *ppv
= &This
->IHTMLSelectElement_iface
;
521 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
522 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
523 *ppv
= &This
->IHTMLSelectElement_iface
;
524 }else if(IsEqualGUID(&IID_IHTMLSelectElement
, riid
)) {
525 TRACE("(%p)->(IID_IHTMLSelectElement %p)\n", This
, ppv
);
526 *ppv
= &This
->IHTMLSelectElement_iface
;
530 IUnknown_AddRef((IUnknown
*)*ppv
);
534 return HTMLElement_QI(&This
->element
.node
, riid
, ppv
);
537 static HRESULT
HTMLSelectElementImpl_put_disabled(HTMLDOMNode
*iface
, VARIANT_BOOL v
)
539 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
540 return IHTMLSelectElement_put_disabled(&This
->IHTMLSelectElement_iface
, v
);
543 static HRESULT
HTMLSelectElementImpl_get_disabled(HTMLDOMNode
*iface
, VARIANT_BOOL
*p
)
545 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
546 return IHTMLSelectElement_get_disabled(&This
->IHTMLSelectElement_iface
, p
);
549 #define DISPID_OPTIONCOL_0 MSHTML_DISPID_CUSTOM_MIN
551 static HRESULT
HTMLSelectElement_get_dispid(HTMLDOMNode
*iface
, BSTR name
, DWORD flags
, DISPID
*dispid
)
556 for(ptr
= name
; *ptr
&& isdigitW(*ptr
); ptr
++) {
557 idx
= idx
*10 + (*ptr
-'0');
558 if(idx
> MSHTML_CUSTOM_DISPID_CNT
) {
559 WARN("too big idx\n");
560 return DISP_E_UNKNOWNNAME
;
564 return DISP_E_UNKNOWNNAME
;
566 *dispid
= DISPID_OPTIONCOL_0
+ idx
;
570 static HRESULT
HTMLSelectElement_invoke(HTMLDOMNode
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
571 VARIANT
*res
, EXCEPINFO
*ei
, IServiceProvider
*caller
)
573 HTMLSelectElement
*This
= impl_from_HTMLDOMNode(iface
);
575 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
, caller
);
578 case DISPATCH_PROPERTYGET
: {
582 hres
= htmlselect_item(This
, id
-DISPID_OPTIONCOL_0
, &ret
);
587 V_VT(res
) = VT_DISPATCH
;
588 V_DISPATCH(res
) = ret
;
596 FIXME("unimplemented flags %x\n", flags
);
603 static const NodeImplVtbl HTMLSelectElementImplVtbl
= {
604 HTMLSelectElement_QI
,
605 HTMLElement_destructor
,
608 HTMLElement_handle_event
,
609 HTMLElement_get_attr_col
,
612 HTMLSelectElementImpl_put_disabled
,
613 HTMLSelectElementImpl_get_disabled
,
616 HTMLSelectElement_get_dispid
,
617 HTMLSelectElement_invoke
620 static const tid_t HTMLSelectElement_tids
[] = {
622 IHTMLSelectElement_tid
,
626 static dispex_static_data_t HTMLSelectElement_dispex
= {
628 DispHTMLSelectElement_tid
,
630 HTMLSelectElement_tids
633 HRESULT
HTMLSelectElement_Create(HTMLDocumentNode
*doc
, nsIDOMHTMLElement
*nselem
, HTMLElement
**elem
)
635 HTMLSelectElement
*ret
;
638 ret
= heap_alloc_zero(sizeof(HTMLSelectElement
));
640 return E_OUTOFMEMORY
;
642 ret
->IHTMLSelectElement_iface
.lpVtbl
= &HTMLSelectElementVtbl
;
643 ret
->element
.node
.vtbl
= &HTMLSelectElementImplVtbl
;
645 HTMLElement_Init(&ret
->element
, doc
, nselem
, &HTMLSelectElement_dispex
);
647 nsres
= nsIDOMHTMLElement_QueryInterface(nselem
, &IID_nsIDOMHTMLSelectElement
,
648 (void**)&ret
->nsselect
);
650 /* Share nsselect reference with nsnode */
651 assert(nsres
== NS_OK
&& (nsIDOMNode
*)ret
->nsselect
== ret
->element
.node
.nsnode
);
652 nsIDOMNode_Release(ret
->element
.node
.nsnode
);
654 *elem
= &ret
->element
;