mshtml: Added IHTMLElement4::setAttributeNode implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
423b7ba1d1
commit
17fcc112ad
|
@ -491,6 +491,11 @@ static dispex_static_data_t HTMLDOMAttribute_dispex = {
|
||||||
HTMLDOMAttribute_iface_tids
|
HTMLDOMAttribute_iface_tids
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface)
|
||||||
|
{
|
||||||
|
return iface->lpVtbl == &HTMLDOMAttributeVtbl ? impl_from_IHTMLDOMAttribute(iface) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDOMAttribute **attr)
|
HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDOMAttribute **attr)
|
||||||
{
|
{
|
||||||
HTMLAttributeCollection *col;
|
HTMLAttributeCollection *col;
|
||||||
|
|
|
@ -612,14 +612,27 @@ static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMembe
|
||||||
wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT set_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *v)
|
||||||
|
{
|
||||||
|
DISPID propput_dispid = DISPID_PROPERTYPUT;
|
||||||
|
DISPPARAMS dp = {v, &propput_dispid, 1, 1};
|
||||||
|
EXCEPINFO ei;
|
||||||
|
|
||||||
|
if(dispid == DISPID_IHTMLELEMENT_STYLE) {
|
||||||
|
TRACE("Ignoring call on style attribute\n");
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IDispatchEx_InvokeEx(&elem->node.event_target.dispex.IDispatchEx_iface, dispid,
|
||||||
|
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
|
static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
|
||||||
VARIANT AttributeValue, LONG lFlags)
|
VARIANT AttributeValue, LONG lFlags)
|
||||||
{
|
{
|
||||||
HTMLElement *This = impl_from_IHTMLElement(iface);
|
HTMLElement *This = impl_from_IHTMLElement(iface);
|
||||||
|
DISPID dispid;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
|
|
||||||
DISPPARAMS dispParams;
|
|
||||||
EXCEPINFO excep;
|
|
||||||
|
|
||||||
TRACE("(%p)->(%s %s %08x)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
|
TRACE("(%p)->(%s %s %08x)\n", This, debugstr_w(strAttributeName), debugstr_variant(&AttributeValue), lFlags);
|
||||||
|
|
||||||
|
@ -628,18 +641,7 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
if(dispid == DISPID_IHTMLELEMENT_STYLE) {
|
return set_elem_attr_value_by_dispid(This, dispid, &AttributeValue);
|
||||||
TRACE("Ignoring call on style attribute\n");
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispParams.cArgs = 1;
|
|
||||||
dispParams.cNamedArgs = 1;
|
|
||||||
dispParams.rgdispidNamedArgs = &dispidNamed;
|
|
||||||
dispParams.rgvarg = &AttributeValue;
|
|
||||||
|
|
||||||
return IDispatchEx_InvokeEx(&This->node.event_target.dispex.IDispatchEx_iface, dispid,
|
|
||||||
LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams, NULL, &excep, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *ret)
|
HRESULT get_elem_attr_value_by_dispid(HTMLElement *elem, DISPID dispid, VARIANT *ret)
|
||||||
|
@ -3718,8 +3720,68 @@ static HRESULT WINAPI HTMLElement4_setAttributeNode(IHTMLElement4 *iface, IHTMLD
|
||||||
IHTMLDOMAttribute **ppretAttribute)
|
IHTMLDOMAttribute **ppretAttribute)
|
||||||
{
|
{
|
||||||
HTMLElement *This = impl_from_IHTMLElement4(iface);
|
HTMLElement *This = impl_from_IHTMLElement4(iface);
|
||||||
FIXME("(%p)->(%p %p)\n", This, pattr, ppretAttribute);
|
HTMLDOMAttribute *attr, *iter, *replace = NULL;
|
||||||
return E_NOTIMPL;
|
HTMLAttributeCollection *attrs;
|
||||||
|
DISPID dispid;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%p %p)\n", This, pattr, ppretAttribute);
|
||||||
|
|
||||||
|
attr = unsafe_impl_from_IHTMLDOMAttribute(pattr);
|
||||||
|
if(!attr)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
if(attr->elem) {
|
||||||
|
WARN("Tried to set already attached attribute.\n");
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
hres = IDispatchEx_GetDispID(&This->node.event_target.dispex.IDispatchEx_iface,
|
||||||
|
attr->name, fdexNameCaseInsensitive|fdexNameEnsure, &dispid);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
|
||||||
|
hres = HTMLElement_get_attr_col(&This->node, &attrs);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(iter, &attrs->attrs, HTMLDOMAttribute, entry) {
|
||||||
|
if(iter->dispid == dispid) {
|
||||||
|
replace = iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(replace) {
|
||||||
|
hres = get_elem_attr_value_by_dispid(This, dispid, &replace->value);
|
||||||
|
if(FAILED(hres)) {
|
||||||
|
WARN("could not get attr value: %08x\n", hres);
|
||||||
|
V_VT(&replace->value) = VT_EMPTY;
|
||||||
|
}
|
||||||
|
if(!replace->name) {
|
||||||
|
replace->name = attr->name;
|
||||||
|
attr->name = NULL;
|
||||||
|
}
|
||||||
|
list_add_head(&replace->entry, &attr->entry);
|
||||||
|
list_remove(&replace->entry);
|
||||||
|
replace->elem = NULL;
|
||||||
|
}else {
|
||||||
|
list_add_tail(&attrs->attrs, &attr->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
IHTMLDOMAttribute_AddRef(&attr->IHTMLDOMAttribute_iface);
|
||||||
|
attr->elem = This;
|
||||||
|
attr->dispid = dispid;
|
||||||
|
|
||||||
|
IHTMLAttributeCollection_Release(&attrs->IHTMLAttributeCollection_iface);
|
||||||
|
|
||||||
|
hres = set_elem_attr_value_by_dispid(This, dispid, &attr->value);
|
||||||
|
if(FAILED(hres))
|
||||||
|
WARN("Could not set attribute value: %08x\n", hres);
|
||||||
|
VariantClear(&attr->value);
|
||||||
|
|
||||||
|
*ppretAttribute = replace ? &replace->IHTMLDOMAttribute_iface : NULL;
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI HTMLElement4_removeAttributeNode(IHTMLElement4 *iface, IHTMLDOMAttribute *pattr,
|
static HRESULT WINAPI HTMLElement4_removeAttributeNode(IHTMLElement4 *iface, IHTMLDOMAttribute *pattr,
|
||||||
|
|
|
@ -943,15 +943,18 @@ typedef struct {
|
||||||
|
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
/* name and value are valid only for detached attributes (when elem == NULL). */
|
/* value is valid only for detached attributes (when elem == NULL). */
|
||||||
WCHAR *name;
|
|
||||||
VARIANT value;
|
VARIANT value;
|
||||||
|
/* name must be valid for detached attributes */
|
||||||
|
WCHAR *name;
|
||||||
|
|
||||||
HTMLElement *elem;
|
HTMLElement *elem;
|
||||||
DISPID dispid;
|
DISPID dispid;
|
||||||
struct list entry;
|
struct list entry;
|
||||||
} HTMLDOMAttribute;
|
} HTMLDOMAttribute;
|
||||||
|
|
||||||
|
HTMLDOMAttribute *unsafe_impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
HRESULT HTMLDOMAttribute_Create(const WCHAR*,HTMLElement*,DISPID,HTMLDOMAttribute**) DECLSPEC_HIDDEN;
|
HRESULT HTMLDOMAttribute_Create(const WCHAR*,HTMLElement*,DISPID,HTMLDOMAttribute**) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
HRESULT HTMLElement_Create(HTMLDocumentNode*,nsIDOMNode*,BOOL,HTMLElement**) DECLSPEC_HIDDEN;
|
HRESULT HTMLElement_Create(HTMLDocumentNode*,nsIDOMNode*,BOOL,HTMLElement**) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -8524,8 +8524,10 @@ static void test_elems(IHTMLDocument2 *doc)
|
||||||
|
|
||||||
static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem)
|
static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem)
|
||||||
{
|
{
|
||||||
IHTMLDOMAttribute *attr, *attr2;
|
IHTMLDOMAttribute *attr, *attr2, *attr3;
|
||||||
|
IHTMLElement4 *elem4;
|
||||||
VARIANT v;
|
VARIANT v;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
get_elem_attr_node((IUnknown*)elem, "noattr", FALSE);
|
get_elem_attr_node((IUnknown*)elem, "noattr", FALSE);
|
||||||
|
|
||||||
|
@ -8636,6 +8638,57 @@ static void test_attr(IHTMLDocument2 *doc, IHTMLElement *elem)
|
||||||
SysFreeString(V_BSTR(&v));
|
SysFreeString(V_BSTR(&v));
|
||||||
test_attr_value(attr, "testing");
|
test_attr_value(attr, "testing");
|
||||||
|
|
||||||
|
elem4 = get_elem4_iface((IUnknown*)elem);
|
||||||
|
|
||||||
|
hres = IHTMLElement4_setAttributeNode(elem4, attr, &attr2);
|
||||||
|
ok(hres == S_OK, "setAttributeNode failed: %08x\n", hres);
|
||||||
|
ok(!attr2, "attr2 != NULL\n");
|
||||||
|
|
||||||
|
test_elem_attr(elem, "Test", "testing");
|
||||||
|
put_attr_value(attr, "new value");
|
||||||
|
test_elem_attr(elem, "Test", "new value");
|
||||||
|
|
||||||
|
attr2 = get_elem_attr_node((IUnknown*)elem, "Test", TRUE);
|
||||||
|
ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr), "attr2 != attr\n");
|
||||||
|
IHTMLDOMAttribute_Release(attr2);
|
||||||
|
|
||||||
|
attr3 = create_attr((IUnknown*)doc, "Test");
|
||||||
|
put_attr_value(attr3, "replace test");
|
||||||
|
|
||||||
|
hres = IHTMLElement4_setAttributeNode(elem4, attr3, &attr2);
|
||||||
|
ok(hres == S_OK, "setAttributeNode failed: %08x\n", hres);
|
||||||
|
ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr), "attr2 != attr\n");
|
||||||
|
IHTMLDOMAttribute_Release(attr2);
|
||||||
|
|
||||||
|
test_elem_attr(elem, "Test", "replace test");
|
||||||
|
test_attr_value(attr, "new value");
|
||||||
|
test_attr_value(attr3, "replace test");
|
||||||
|
|
||||||
|
attr2 = get_elem_attr_node((IUnknown*)elem, "Test", TRUE);
|
||||||
|
ok(iface_cmp((IUnknown*)attr2, (IUnknown*)attr3), "attr2 != attr3\n");
|
||||||
|
IHTMLDOMAttribute_Release(attr2);
|
||||||
|
|
||||||
|
put_attr_value(attr, "new value2");
|
||||||
|
test_elem_attr(elem, "Test", "replace test");
|
||||||
|
test_attr_value(attr, "new value2");
|
||||||
|
test_attr_value(attr3, "replace test");
|
||||||
|
|
||||||
|
put_attr_value(attr3, "new replace value");
|
||||||
|
test_elem_attr(elem, "Test", "new replace value");
|
||||||
|
test_attr_value(attr, "new value2");
|
||||||
|
test_attr_value(attr3, "new replace value");
|
||||||
|
|
||||||
|
/* Attached attributes cause errors. */
|
||||||
|
hres = IHTMLElement4_setAttributeNode(elem4, attr3, &attr2);
|
||||||
|
ok(hres == E_INVALIDARG, "setAttributeNode failed: %08x, expected E_INVALIDARG\n", hres);
|
||||||
|
IHTMLDOMAttribute_Release(attr3);
|
||||||
|
|
||||||
|
attr2 = get_elem_attr_node((IUnknown*)elem, "id", TRUE);
|
||||||
|
hres = IHTMLElement4_setAttributeNode(elem4, attr2, &attr3);
|
||||||
|
ok(hres == E_INVALIDARG, "setAttributeNode failed: %08x, expected E_INVALIDARG\n", hres);
|
||||||
|
IHTMLDOMAttribute_Release(attr2);
|
||||||
|
|
||||||
|
IHTMLElement4_Release(elem4);
|
||||||
IHTMLDOMAttribute_Release(attr);
|
IHTMLDOMAttribute_Release(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue