LONG ref;
} HTMLElementCollection;
+typedef struct {
+ IEnumVARIANT IEnumVARIANT_iface;
+
+ LONG ref;
+
+ ULONG iter;
+ HTMLElementCollection *col;
+} HTMLElementCollectionEnum;
+
typedef struct {
HTMLElement **buf;
DWORD len;
return type == ELEMENT_NODE || type == COMMENT_NODE;
}
+static inline HTMLElementCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
+{
+ return CONTAINING_RECORD(iface, HTMLElementCollectionEnum, IEnumVARIANT_iface);
+}
+
+static HRESULT WINAPI HTMLElementCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
+
+ if(IsEqualGUID(riid, &IID_IUnknown)) {
+ *ppv = &This->IEnumVARIANT_iface;
+ }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
+ *ppv = &This->IEnumVARIANT_iface;
+ }else {
+ FIXME("Unsupported iface %s\n", debugstr_mshtml_guid(riid));
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI HTMLElementCollectionEnum_AddRef(IEnumVARIANT *iface)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI HTMLElementCollectionEnum_Release(IEnumVARIANT *iface)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref) {
+ IHTMLElementCollection_Release(&This->col->IHTMLElementCollection_iface);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI HTMLElementCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+ ULONG fetched = 0;
+
+ TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
+
+ while(This->iter+fetched < This->col->len && fetched < celt) {
+ V_VT(rgVar+fetched) = VT_DISPATCH;
+ V_DISPATCH(rgVar+fetched) = (IDispatch*)&This->col->elems[This->iter+fetched]->IHTMLElement_iface;
+ IDispatch_AddRef(V_DISPATCH(rgVar+fetched));
+ fetched++;
+ }
+
+ This->iter += fetched;
+ if(pCeltFetched)
+ *pCeltFetched = fetched;
+ return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI HTMLElementCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->(%d)\n", This, celt);
+
+ if(This->iter + celt > This->col->len) {
+ This->iter = This->col->len;
+ return S_FALSE;
+ }
+
+ This->iter += celt;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLElementCollectionEnum_Reset(IEnumVARIANT *iface)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+
+ TRACE("(%p)->()\n", This);
+
+ This->iter = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI HTMLElementCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
+{
+ HTMLElementCollectionEnum *This = impl_from_IEnumVARIANT(iface);
+ FIXME("(%p)->(%p)\n", This, ppEnum);
+ return E_NOTIMPL;
+}
+
+static const IEnumVARIANTVtbl HTMLElementCollectionEnumVtbl = {
+ HTMLElementCollectionEnum_QueryInterface,
+ HTMLElementCollectionEnum_AddRef,
+ HTMLElementCollectionEnum_Release,
+ HTMLElementCollectionEnum_Next,
+ HTMLElementCollectionEnum_Skip,
+ HTMLElementCollectionEnum_Reset,
+ HTMLElementCollectionEnum_Clone
+};
+
static inline HTMLElementCollection *impl_from_IHTMLElementCollection(IHTMLElementCollection *iface)
{
return CONTAINING_RECORD(iface, HTMLElementCollection, IHTMLElementCollection_iface);
{
HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
- *ppv = NULL;
-
if(IsEqualGUID(&IID_IUnknown, riid)) {
- TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = &This->IHTMLElementCollection_iface;
}else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
- TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
*ppv = &This->IHTMLElementCollection_iface;
}else if(dispex_query_interface(&This->dispex, riid, ppv)) {
return *ppv ? S_OK : E_NOINTERFACE;
+ }else {
+ *ppv = NULL;
+ FIXME("Unsupported iface %s\n", debugstr_mshtml_guid(riid));
+ return E_NOINTERFACE;
}
- if(*ppv) {
- IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface);
- return S_OK;
- }
-
- FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
- return E_NOINTERFACE;
+ IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface);
+ return S_OK;
}
static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
IUnknown **p)
{
HTMLElementCollection *This = impl_from_IHTMLElementCollection(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+ HTMLElementCollectionEnum *ret;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ ret = heap_alloc(sizeof(*ret));
+ if(!ret)
+ return E_OUTOFMEMORY;
+
+ ret->IEnumVARIANT_iface.lpVtbl = &HTMLElementCollectionEnumVtbl;
+ ret->ref = 1;
+ ret->iter = 0;
+
+ IHTMLElementCollection_AddRef(&This->IHTMLElementCollection_iface);
+ ret->col = This;
+
+ *p = (IUnknown*)&ret->IEnumVARIANT_iface;
+ return S_OK;
}
static BOOL is_elem_id(HTMLElement *elem, LPCWSTR name)
static BOOL is_elem_name(HTMLElement *elem, LPCWSTR name)
{
const PRUnichar *str;
- nsAString nsstr, nsname;
+ nsAString nsstr;
BOOL ret = FALSE;
nsresult nsres;
return TRUE;
}
- nsAString_InitDepend(&nsname, nameW);
- nsres = nsIDOMHTMLElement_GetAttribute(elem->nselem, &nsname, &nsstr);
- nsAString_Finish(&nsname);
+ nsres = get_elem_attr_value(elem->nselem, nameW, &nsstr, &str);
if(NS_SUCCEEDED(nsres)) {
- nsAString_GetData(&nsstr, &str);
ret = !strcmpiW(str, name);
+ nsAString_Finish(&nsstr);
}
- nsAString_Finish(&nsstr);
return ret;
}
return HTMLElementCollection_Create(buf.buf, buf.len);
}
+HRESULT get_elem_source_index(HTMLElement *elem, LONG *ret)
+{
+ elem_vector_t buf = {NULL, 0, 8};
+ nsIDOMNode *parent_node, *iter;
+ UINT16 parent_type;
+ HTMLDOMNode *node;
+ int i;
+ nsresult nsres;
+ HRESULT hres;
+
+ iter = elem->node.nsnode;
+ nsIDOMNode_AddRef(iter);
+
+ /* Find document or document fragment parent. */
+ while(1) {
+ nsres = nsIDOMNode_GetParentNode(iter, &parent_node);
+ nsIDOMNode_Release(iter);
+ assert(nsres == NS_OK);
+ if(!parent_node)
+ break;
+
+ nsres = nsIDOMNode_GetNodeType(parent_node, &parent_type);
+ assert(nsres == NS_OK);
+
+ if(parent_type != ELEMENT_NODE) {
+ if(parent_type != DOCUMENT_NODE && parent_type != DOCUMENT_FRAGMENT_NODE)
+ FIXME("Unexpected parent_type %d\n", parent_type);
+ break;
+ }
+
+ iter = parent_node;
+ }
+
+ if(!parent_node) {
+ *ret = -1;
+ return S_OK;
+ }
+
+ hres = get_node(elem->node.doc, parent_node, TRUE, &node);
+ nsIDOMNode_Release(parent_node);
+ if(FAILED(hres))
+ return hres;
+
+
+ /* Create all children collection and find the element in it.
+ * This could be optimized if we ever find the reason. */
+ buf.buf = heap_alloc(buf.size*sizeof(*buf.buf));
+ if(!buf.buf) {
+ IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface);
+ return E_OUTOFMEMORY;
+ }
+
+ create_all_list(elem->node.doc, node, &buf);
+
+ for(i=0; i < buf.len; i++) {
+ if(buf.buf[i] == elem)
+ break;
+ }
+ IHTMLDOMNode_Release(&node->IHTMLDOMNode_iface);
+ heap_free(buf.buf);
+ if(i == buf.len) {
+ FIXME("The element is not in parent's child list?\n");
+ return E_UNEXPECTED;
+ }
+
+ *ret = i;
+ return S_OK;
+}
+
static IHTMLElementCollection *HTMLElementCollection_Create(HTMLElement **elems, DWORD len)
{
HTMLElementCollection *ret = heap_alloc_zero(sizeof(HTMLElementCollection));