From 73d4d172d5685c6694fa88d512f51eee6061217c Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 29 Apr 2010 18:29:23 +0200 Subject: [PATCH] mshtml: Added support for accessing select options by index. --- dlls/mshtml/htmlselect.c | 80 ++++++++++++++++++++++++++++++++++- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/nsiface.idl | 15 ++++++- dlls/mshtml/tests/jstest.html | 16 +++++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 20f11ee3611..ee5d214bd1e 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -504,6 +504,80 @@ static HRESULT HTMLSelectElementImpl_get_disabled(HTMLDOMNode *iface, VARIANT_BO return IHTMLSelectElement_get_disabled(HTMLSELECT(This), p); } +#define DISPID_OPTIONCOL_0 MSHTML_DISPID_CUSTOM_MIN + +static HRESULT HTMLSelectElement_get_dispid(HTMLDOMNode *iface, BSTR name, DWORD flags, DISPID *dispid) +{ + const WCHAR *ptr; + DWORD idx = 0; + + for(ptr = name; *ptr && isdigitW(*ptr); ptr++) { + idx = idx*10 + (*ptr-'0'); + if(idx > MSHTML_CUSTOM_DISPID_CNT) { + WARN("too big idx\n"); + return DISP_E_UNKNOWNNAME; + } + } + if(*ptr) + return DISP_E_UNKNOWNNAME; + + *dispid = DISPID_OPTIONCOL_0 + idx; + return S_OK; +} + +static HRESULT HTMLSelectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLSelectElement *This = HTMLSELECT_NODE_THIS(iface); + + TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case DISPATCH_PROPERTYGET: { + nsIDOMHTMLOptionsCollection *nscol; + nsIDOMNode *nsnode; + nsresult nsres; + + nsres = nsIDOMHTMLSelectElement_GetOptions(This->nsselect, &nscol); + if(NS_FAILED(nsres)) { + ERR("GetOptions failed: %08x\n", nsres); + return E_FAIL; + } + + nsres = nsIDOMHTMLOptionsCollection_Item(nscol, id-DISPID_OPTIONCOL_0, &nsnode); + nsIDOMHTMLOptionsCollection_Release(nscol); + if(NS_FAILED(nsres)) { + ERR("Item failed: %08x\n", nsres); + return E_FAIL; + } + + if(nsnode) { + HTMLDOMNode *node; + + node = get_node(This->element.node.doc, nsnode, TRUE); + nsIDOMNode_Release(nsnode); + if(!node) { + ERR("Could not find node\n"); + return E_FAIL; + } + + IHTMLDOMNode_AddRef(HTMLDOMNODE(node)); + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)HTMLDOMNODE(node); + }else { + V_VT(res) = VT_NULL; + } + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + #undef HTMLSELECT_NODE_THIS static const NodeImplVtbl HTMLSelectElementImplVtbl = { @@ -512,7 +586,11 @@ static const NodeImplVtbl HTMLSelectElementImplVtbl = { NULL, NULL, HTMLSelectElementImpl_put_disabled, - HTMLSelectElementImpl_get_disabled + HTMLSelectElementImpl_get_disabled, + NULL, + NULL, + HTMLSelectElement_get_dispid, + HTMLSelectElement_invoke }; static const tid_t HTMLSelectElement_tids[] = { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index c88b3e5fc3a..4deb4d6357d 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -144,6 +144,7 @@ typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; #define MSHTML_DISPID_CUSTOM_MIN 0x60000000 #define MSHTML_DISPID_CUSTOM_MAX 0x6fffffff +#define MSHTML_CUSTOM_DISPID_CNT (MSHTML_DISPID_CUSTOM_MAX-MSHTML_DISPID_CUSTOM_MIN) typedef struct { HRESULT (*value)(IUnknown*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 66ab8e6a49b..4ccc64a7c02 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -119,7 +119,6 @@ typedef nsISupports nsIDOMDOMImplementation; typedef nsISupports nsIDOMCDATASection; typedef nsISupports nsIDOMProcessingInstruction; typedef nsISupports nsIDOMEntityReference; -typedef nsISupports nsIDOMHTMLOptionsCollection; typedef nsISupports nsIWebProgressListener; typedef nsISupports nsIDOMCSSValue; typedef nsISupports nsIPrintSession; @@ -1319,6 +1318,20 @@ interface nsIDOMHTMLOptionElement : nsIDOMHTMLElement nsresult SetValue(const nsAString *aValue); } +[ + object, + uuid(bce0213c-f70f-488f-b93f-688acca55d63), + local + /* FROZEN */ +] +interface nsIDOMHTMLOptionsCollection : nsISupports +{ + nsresult GetLength(PRUint32 *aLength); + nsresult SetLength(PRUint32 aLength); + nsresult Item(PRUint32 index, nsIDOMNode **_retval); + nsresult NamedItem(const nsAString *name, nsIDOMNode **_retval); +} + [ object, uuid(a6cf9090-15b3-11d2-932e-00805f8add32), diff --git a/dlls/mshtml/tests/jstest.html b/dlls/mshtml/tests/jstest.html index 6192f815af3..3363c5ae8ca 100644 --- a/dlls/mshtml/tests/jstest.html +++ b/dlls/mshtml/tests/jstest.html @@ -20,6 +20,17 @@ function test_removeAttribute(e) { } +function test_select_index() { + var s = document.getElementById("sel"); + + ok("0" in s, "'0' is not in s"); + ok(s[0].text === "opt1", "s[0].text = " + s[0].text); + ok("1" in s, "'1 is not in s"); + ok(s[1].text === "opt2", "s[1].text = " + s[1].text); + ok("2" in s, "'2' is in s"); + ok(s[2] === null, "s[2] = " + s[2]); +} + function runTest() { obj = new Object(); ok(obj === window.obj, "obj !== window.obj"); @@ -28,11 +39,16 @@ function runTest() { test_removeAttribute(document.getElementById("divid")); test_removeAttribute(document.body); + test_select_index(); external.reportSuccess(); }
+