dwrite: Implement CreateFontFaceFromHdc().
[wine.git] / dlls / mshtml / htmlnode.c
bloba89b0ca18628c1b0fa7e5b655e58992ce0f8e98d
1 /*
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 <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
37 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
39 typedef struct {
40 DispatchEx dispex;
41 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
43 LONG ref;
45 /* FIXME: implement weak reference */
46 HTMLDocumentNode *doc;
48 nsIDOMNodeList *nslist;
49 } HTMLDOMChildrenCollection;
51 typedef struct {
52 IEnumVARIANT IEnumVARIANT_iface;
54 LONG ref;
56 ULONG iter;
57 HTMLDOMChildrenCollection *col;
58 } HTMLDOMChildrenCollectionEnum;
60 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
62 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
65 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
67 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
69 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
71 if(IsEqualGUID(riid, &IID_IUnknown)) {
72 *ppv = &This->IEnumVARIANT_iface;
73 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
74 *ppv = &This->IEnumVARIANT_iface;
75 }else {
76 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
77 *ppv = NULL;
78 return E_NOINTERFACE;
81 IUnknown_AddRef((IUnknown*)*ppv);
82 return S_OK;
85 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
87 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
88 LONG ref = InterlockedIncrement(&This->ref);
90 TRACE("(%p) ref=%d\n", This, ref);
92 return ref;
95 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
97 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
98 LONG ref = InterlockedDecrement(&This->ref);
100 TRACE("(%p) ref=%d\n", This, ref);
102 if(!ref) {
103 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
104 heap_free(This);
107 return ref;
110 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
112 ULONG len;
113 nsresult nsres;
115 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
116 assert(nsres == NS_OK);
117 return len;
120 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
122 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
123 ULONG fetched = 0, len;
124 nsIDOMNode *nsnode;
125 HTMLDOMNode *node;
126 nsresult nsres;
127 HRESULT hres;
129 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
131 len = get_enum_len(This);
133 while(This->iter+fetched < len && fetched < celt) {
134 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
135 assert(nsres == NS_OK);
137 hres = get_node(This->col->doc, nsnode, TRUE, &node);
138 nsIDOMNode_Release(nsnode);
139 if(FAILED(hres)) {
140 ERR("get_node failed: %08x\n", hres);
141 break;
144 V_VT(rgVar+fetched) = VT_DISPATCH;
145 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
146 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
147 fetched++;
150 This->iter += fetched;
151 if(pCeltFetched)
152 *pCeltFetched = fetched;
153 return fetched == celt ? S_OK : S_FALSE;
156 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
158 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
159 ULONG len;
161 TRACE("(%p)->(%d)\n", This, celt);
163 len = get_enum_len(This);
164 if(This->iter + celt > len) {
165 This->iter = len;
166 return S_FALSE;
169 This->iter += celt;
170 return S_OK;
173 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
175 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
177 TRACE("(%p)->()\n", This);
179 This->iter = 0;
180 return S_OK;
183 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
185 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
186 FIXME("(%p)->(%p)\n", This, ppEnum);
187 return E_NOTIMPL;
190 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
191 HTMLDOMChildrenCollectionEnum_QueryInterface,
192 HTMLDOMChildrenCollectionEnum_AddRef,
193 HTMLDOMChildrenCollectionEnum_Release,
194 HTMLDOMChildrenCollectionEnum_Next,
195 HTMLDOMChildrenCollectionEnum_Skip,
196 HTMLDOMChildrenCollectionEnum_Reset,
197 HTMLDOMChildrenCollectionEnum_Clone
200 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
202 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
205 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
207 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
209 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
211 if(IsEqualGUID(&IID_IUnknown, riid)) {
212 *ppv = &This->IHTMLDOMChildrenCollection_iface;
213 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
214 *ppv = &This->IHTMLDOMChildrenCollection_iface;
215 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
216 return *ppv ? S_OK : E_NOINTERFACE;
217 }else {
218 *ppv = NULL;
219 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
220 return E_NOINTERFACE;
223 IUnknown_AddRef((IUnknown*)*ppv);
224 return S_OK;
227 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
229 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
230 LONG ref = InterlockedIncrement(&This->ref);
232 TRACE("(%p) ref=%d\n", This, ref);
234 return ref;
237 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
239 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
240 LONG ref = InterlockedDecrement(&This->ref);
242 TRACE("(%p) ref=%d\n", This, ref);
244 if(!ref) {
245 htmldoc_release(&This->doc->basedoc);
246 nsIDOMNodeList_Release(This->nslist);
247 heap_free(This);
250 return ref;
253 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
255 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
256 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
259 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
260 LCID lcid, ITypeInfo **ppTInfo)
262 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
263 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
266 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
267 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
269 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
270 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
271 lcid, rgDispId);
274 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
275 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
276 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
278 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
279 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
280 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
283 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
285 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
286 UINT32 length=0;
288 TRACE("(%p)->(%p)\n", This, p);
290 nsIDOMNodeList_GetLength(This->nslist, &length);
291 *p = length;
292 return S_OK;
295 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
297 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
298 HTMLDOMChildrenCollectionEnum *ret;
300 TRACE("(%p)->(%p)\n", This, p);
302 ret = heap_alloc(sizeof(*ret));
303 if(!ret)
304 return E_OUTOFMEMORY;
306 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
307 ret->ref = 1;
308 ret->iter = 0;
310 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
311 ret->col = This;
313 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
314 return S_OK;
317 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
319 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
320 nsIDOMNode *nsnode = NULL;
321 HTMLDOMNode *node;
322 UINT32 length=0;
323 nsresult nsres;
324 HRESULT hres;
326 TRACE("(%p)->(%d %p)\n", This, index, ppItem);
328 if (ppItem)
329 *ppItem = NULL;
330 else
331 return E_POINTER;
333 nsIDOMNodeList_GetLength(This->nslist, &length);
334 if(index < 0 || index >= length)
335 return E_INVALIDARG;
337 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
338 if(NS_FAILED(nsres) || !nsnode) {
339 ERR("Item failed: %08x\n", nsres);
340 return E_FAIL;
343 hres = get_node(This->doc, nsnode, TRUE, &node);
344 if(FAILED(hres))
345 return hres;
347 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
348 return S_OK;
351 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
352 HTMLDOMChildrenCollection_QueryInterface,
353 HTMLDOMChildrenCollection_AddRef,
354 HTMLDOMChildrenCollection_Release,
355 HTMLDOMChildrenCollection_GetTypeInfoCount,
356 HTMLDOMChildrenCollection_GetTypeInfo,
357 HTMLDOMChildrenCollection_GetIDsOfNames,
358 HTMLDOMChildrenCollection_Invoke,
359 HTMLDOMChildrenCollection_get_length,
360 HTMLDOMChildrenCollection_get__newEnum,
361 HTMLDOMChildrenCollection_item
364 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
366 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
369 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
371 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
373 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
374 WCHAR *ptr;
375 DWORD idx=0;
376 UINT32 len = 0;
378 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
379 idx = idx*10 + (*ptr-'0');
380 if(*ptr)
381 return DISP_E_UNKNOWNNAME;
383 nsIDOMNodeList_GetLength(This->nslist, &len);
384 if(idx >= len)
385 return DISP_E_UNKNOWNNAME;
387 *dispid = DISPID_CHILDCOL_0 + idx;
388 TRACE("ret %x\n", *dispid);
389 return S_OK;
392 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
393 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
395 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
397 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
399 switch(flags) {
400 case DISPATCH_PROPERTYGET: {
401 IDispatch *disp = NULL;
402 HRESULT hres;
404 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
405 id - DISPID_CHILDCOL_0, &disp);
406 if(FAILED(hres))
407 return hres;
409 V_VT(res) = VT_DISPATCH;
410 V_DISPATCH(res) = disp;
411 break;
414 default:
415 FIXME("unimplemented flags %x\n", flags);
416 return E_NOTIMPL;
419 return S_OK;
422 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
423 NULL,
424 HTMLDOMChildrenCollection_get_dispid,
425 HTMLDOMChildrenCollection_invoke,
426 NULL
429 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
430 IHTMLDOMChildrenCollection_tid,
434 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
435 &HTMLDOMChildrenCollection_dispex_vtbl,
436 DispDOMChildrenCollection_tid,
437 NULL,
438 HTMLDOMChildrenCollection_iface_tids
441 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocumentNode *doc, nsIDOMNodeList *nslist)
443 HTMLDOMChildrenCollection *ret;
445 ret = heap_alloc_zero(sizeof(*ret));
446 if(!ret)
447 return NULL;
449 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
450 ret->ref = 1;
452 nsIDOMNodeList_AddRef(nslist);
453 ret->nslist = nslist;
455 htmldoc_addref(&doc->basedoc);
456 ret->doc = doc;
458 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface,
459 &HTMLDOMChildrenCollection_dispex);
461 return &ret->IHTMLDOMChildrenCollection_iface;
464 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
466 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
469 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
470 REFIID riid, void **ppv)
472 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
474 return This->vtbl->qi(This, riid, ppv);
477 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
479 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
480 LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
482 TRACE("(%p) ref=%d\n", This, ref);
484 return ref;
487 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
489 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
490 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
492 TRACE("(%p) ref=%d\n", This, ref);
494 if(!ref) {
495 if(This->vtbl->unlink)
496 This->vtbl->unlink(This);
497 This->vtbl->destructor(This);
498 release_dispex(&This->dispex);
499 heap_free(This);
502 return ref;
505 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
507 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
508 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
511 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
512 LCID lcid, ITypeInfo **ppTInfo)
514 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
515 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
518 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
519 LPOLESTR *rgszNames, UINT cNames,
520 LCID lcid, DISPID *rgDispId)
522 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
523 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
524 lcid, rgDispId);
527 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
528 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
529 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
531 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
532 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
533 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
536 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
538 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
539 UINT16 type = -1;
541 TRACE("(%p)->(%p)\n", This, p);
543 nsIDOMNode_GetNodeType(This->nsnode, &type);
545 switch(type) {
546 case ELEMENT_NODE:
547 *p = 1;
548 break;
549 case TEXT_NODE:
550 *p = 3;
551 break;
552 case COMMENT_NODE:
553 case DOCUMENT_TYPE_NODE:
554 *p = 8;
555 break;
556 case DOCUMENT_NODE:
557 *p = 9;
558 break;
559 case DOCUMENT_FRAGMENT_NODE:
560 *p = 11;
561 break;
562 default:
564 * FIXME:
565 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
566 * It needs more tests.
568 FIXME("type %u\n", type);
569 *p = 0;
572 return S_OK;
575 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
577 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
578 HTMLDOMNode *node;
579 nsIDOMNode *nsnode;
580 nsresult nsres;
581 HRESULT hres;
583 TRACE("(%p)->(%p)\n", This, p);
585 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
586 if(NS_FAILED(nsres)) {
587 ERR("GetParentNode failed: %08x\n", nsres);
588 return E_FAIL;
591 if(!nsnode) {
592 *p = NULL;
593 return S_OK;
596 hres = get_node(This->doc, nsnode, TRUE, &node);
597 nsIDOMNode_Release(nsnode);
598 if(FAILED(hres))
599 return hres;
601 *p = &node->IHTMLDOMNode_iface;
602 return S_OK;
605 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
607 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
608 cpp_bool has_child = FALSE;
609 nsresult nsres;
611 TRACE("(%p)->(%p)\n", This, fChildren);
613 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
614 if(NS_FAILED(nsres))
615 ERR("HasChildNodes failed: %08x\n", nsres);
617 *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE;
618 return S_OK;
621 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
623 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
624 nsIDOMNodeList *nslist;
625 nsresult nsres;
627 TRACE("(%p)->(%p)\n", This, p);
629 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
630 if(NS_FAILED(nsres)) {
631 ERR("GetChildNodes failed: %08x\n", nsres);
632 return E_FAIL;
635 *p = (IDispatch*)create_child_collection(This->doc, nslist);
636 nsIDOMNodeList_Release(nslist);
638 return *p ? S_OK : E_OUTOFMEMORY;
641 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
643 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
644 HTMLAttributeCollection *col;
645 HRESULT hres;
647 TRACE("(%p)->(%p)\n", This, p);
649 if(This->vtbl->get_attr_col) {
650 hres = This->vtbl->get_attr_col(This, &col);
651 if(FAILED(hres))
652 return hres;
654 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
655 return S_OK;
658 *p = NULL;
659 return S_OK;
662 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
663 VARIANT refChild, IHTMLDOMNode **node)
665 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
666 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
667 nsIDOMNode *nsnode;
668 nsresult nsres;
669 HRESULT hres = S_OK;
671 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
673 new_child = get_node_obj(newChild);
674 if(!new_child) {
675 ERR("invalid newChild\n");
676 return E_INVALIDARG;
679 switch(V_VT(&refChild)) {
680 case VT_NULL:
681 break;
682 case VT_DISPATCH: {
683 IHTMLDOMNode *ref_iface;
685 if(!V_DISPATCH(&refChild))
686 break;
688 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
689 if(FAILED(hres))
690 break;
692 ref_node = get_node_obj(ref_iface);
693 IHTMLDOMNode_Release(ref_iface);
694 if(!ref_node) {
695 ERR("unvalid node\n");
696 hres = E_FAIL;
697 break;
699 break;
701 default:
702 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
703 hres = E_NOTIMPL;
706 if(SUCCEEDED(hres)) {
707 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
708 if(NS_FAILED(nsres)) {
709 ERR("InsertBefore failed: %08x\n", nsres);
710 hres = E_FAIL;
713 node_release(new_child);
714 if(ref_node)
715 node_release(ref_node);
716 if(FAILED(hres))
717 return hres;
719 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
720 nsIDOMNode_Release(nsnode);
721 if(FAILED(hres))
722 return hres;
724 *node = &node_obj->IHTMLDOMNode_iface;
725 return S_OK;
728 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
729 IHTMLDOMNode **node)
731 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
732 HTMLDOMNode *node_obj;
733 nsIDOMNode *nsnode;
734 nsresult nsres;
735 HRESULT hres;
737 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
739 node_obj = get_node_obj(oldChild);
740 if(!node_obj)
741 return E_FAIL;
743 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
744 node_release(node_obj);
745 if(NS_FAILED(nsres)) {
746 ERR("RemoveChild failed: %08x\n", nsres);
747 return E_FAIL;
750 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
751 nsIDOMNode_Release(nsnode);
752 if(FAILED(hres))
753 return hres;
755 /* FIXME: Make sure that node != newChild */
756 *node = &node_obj->IHTMLDOMNode_iface;
757 return S_OK;
760 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
761 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
763 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
764 HTMLDOMNode *node_new, *node_old, *ret_node;
765 nsIDOMNode *nsnode;
766 nsresult nsres;
767 HRESULT hres;
769 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
771 node_new = get_node_obj(newChild);
772 if(!node_new)
773 return E_FAIL;
775 node_old = get_node_obj(oldChild);
776 if(!node_old) {
777 node_release(node_new);
778 return E_FAIL;
781 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
782 node_release(node_new);
783 node_release(node_old);
784 if(NS_FAILED(nsres))
785 return E_FAIL;
787 hres = get_node(This->doc, nsnode, TRUE, &ret_node);
788 nsIDOMNode_Release(nsnode);
789 if(FAILED(hres))
790 return hres;
792 *node = &ret_node->IHTMLDOMNode_iface;
793 return S_OK;
796 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
797 IHTMLDOMNode **clonedNode)
799 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
800 HTMLDOMNode *new_node;
801 nsIDOMNode *nsnode;
802 nsresult nsres;
803 HRESULT hres;
805 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
807 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
808 if(NS_FAILED(nsres) || !nsnode) {
809 ERR("CloneNode failed: %08x\n", nsres);
810 return E_FAIL;
813 hres = This->vtbl->clone(This, nsnode, &new_node);
814 if(FAILED(hres))
815 return hres;
817 *clonedNode = &new_node->IHTMLDOMNode_iface;
818 return S_OK;
821 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
822 IHTMLDOMNode **removed)
824 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
825 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
826 return E_NOTIMPL;
829 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
830 IHTMLDOMNode **swappedNode)
832 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
833 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
834 return E_NOTIMPL;
837 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
838 IHTMLDOMNode **replaced)
840 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
841 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
842 return E_NOTIMPL;
845 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
846 IHTMLDOMNode **node)
848 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
849 HTMLDOMNode *node_obj;
850 nsIDOMNode *nsnode;
851 nsresult nsres;
852 HRESULT hres;
854 TRACE("(%p)->(%p %p)\n", This, newChild, node);
856 node_obj = get_node_obj(newChild);
857 if(!node_obj)
858 return E_FAIL;
860 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
861 node_release(node_obj);
862 if(NS_FAILED(nsres)) {
863 ERR("AppendChild failed: %08x\n", nsres);
864 return E_FAIL;
867 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
868 nsIDOMNode_Release(nsnode);
869 if(FAILED(hres))
870 return hres;
872 /* FIXME: Make sure that node != newChild */
873 *node = &node_obj->IHTMLDOMNode_iface;
874 return S_OK;
877 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
879 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
880 nsAString name;
881 nsresult nsres;
883 TRACE("(%p)->(%p)\n", This, p);
885 nsAString_Init(&name, NULL);
886 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
887 return return_nsstr(nsres, &name, p);
890 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
892 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
894 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
896 switch(V_VT(&v)) {
897 case VT_BSTR: {
898 nsAString val_str;
900 nsAString_InitDepend(&val_str, V_BSTR(&v));
901 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
902 nsAString_Finish(&val_str);
904 return S_OK;
907 default:
908 FIXME("unsupported value %s\n", debugstr_variant(&v));
911 return E_NOTIMPL;
914 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
916 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
917 const PRUnichar *val;
918 nsAString val_str;
920 TRACE("(%p)->(%p)\n", This, p);
922 nsAString_Init(&val_str, NULL);
923 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
924 nsAString_GetData(&val_str, &val);
926 if(*val) {
927 V_VT(p) = VT_BSTR;
928 V_BSTR(p) = SysAllocString(val);
929 }else {
930 V_VT(p) = VT_NULL;
933 nsAString_Finish(&val_str);
935 return S_OK;
938 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
940 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
941 nsIDOMNode *nschild = NULL;
942 HTMLDOMNode *node;
943 HRESULT hres;
945 TRACE("(%p)->(%p)\n", This, p);
947 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
948 if(!nschild) {
949 *p = NULL;
950 return S_OK;
953 hres = get_node(This->doc, nschild, TRUE, &node);
954 nsIDOMNode_Release(nschild);
955 if(FAILED(hres))
956 return hres;
958 *p = &node->IHTMLDOMNode_iface;
959 return S_OK;
962 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
964 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
965 nsIDOMNode *nschild = NULL;
966 HTMLDOMNode *node;
967 HRESULT hres;
969 TRACE("(%p)->(%p)\n", This, p);
971 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
972 if(!nschild) {
973 *p = NULL;
974 return S_OK;
977 hres = get_node(This->doc, nschild, TRUE, &node);
978 nsIDOMNode_Release(nschild);
979 if(FAILED(hres))
980 return hres;
982 *p = &node->IHTMLDOMNode_iface;
983 return S_OK;
986 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
988 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
989 nsIDOMNode *nschild = NULL;
990 HTMLDOMNode *node;
991 HRESULT hres;
993 TRACE("(%p)->(%p)\n", This, p);
995 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
996 if(!nschild) {
997 *p = NULL;
998 return S_OK;
1001 hres = get_node(This->doc, nschild, TRUE, &node);
1002 nsIDOMNode_Release(nschild);
1003 if(FAILED(hres))
1004 return hres;
1006 *p = &node->IHTMLDOMNode_iface;
1007 return S_OK;
1010 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1012 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1013 nsIDOMNode *nssibling = NULL;
1014 HTMLDOMNode *node;
1015 HRESULT hres;
1017 TRACE("(%p)->(%p)\n", This, p);
1019 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1020 if(!nssibling) {
1021 *p = NULL;
1022 return S_OK;
1025 hres = get_node(This->doc, nssibling, TRUE, &node);
1026 nsIDOMNode_Release(nssibling);
1027 if(FAILED(hres))
1028 return hres;
1030 *p = &node->IHTMLDOMNode_iface;
1031 return S_OK;
1034 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1035 HTMLDOMNode_QueryInterface,
1036 HTMLDOMNode_AddRef,
1037 HTMLDOMNode_Release,
1038 HTMLDOMNode_GetTypeInfoCount,
1039 HTMLDOMNode_GetTypeInfo,
1040 HTMLDOMNode_GetIDsOfNames,
1041 HTMLDOMNode_Invoke,
1042 HTMLDOMNode_get_nodeType,
1043 HTMLDOMNode_get_parentNode,
1044 HTMLDOMNode_hasChildNodes,
1045 HTMLDOMNode_get_childNodes,
1046 HTMLDOMNode_get_attributes,
1047 HTMLDOMNode_insertBefore,
1048 HTMLDOMNode_removeChild,
1049 HTMLDOMNode_replaceChild,
1050 HTMLDOMNode_cloneNode,
1051 HTMLDOMNode_removeNode,
1052 HTMLDOMNode_swapNode,
1053 HTMLDOMNode_replaceNode,
1054 HTMLDOMNode_appendChild,
1055 HTMLDOMNode_get_nodeName,
1056 HTMLDOMNode_put_nodeValue,
1057 HTMLDOMNode_get_nodeValue,
1058 HTMLDOMNode_get_firstChild,
1059 HTMLDOMNode_get_lastChild,
1060 HTMLDOMNode_get_previousSibling,
1061 HTMLDOMNode_get_nextSibling
1064 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1066 HTMLDOMNode *ret;
1068 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1069 return NULL;
1071 ret = impl_from_IHTMLDOMNode(iface);
1072 node_addref(ret);
1073 return ret;
1076 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1078 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1081 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1082 REFIID riid, void **ppv)
1084 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1086 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1089 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1091 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1093 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1096 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1098 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1100 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1103 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1105 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1106 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1109 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1110 LCID lcid, ITypeInfo **ppTInfo)
1112 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1113 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1116 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1117 LPOLESTR *rgszNames, UINT cNames,
1118 LCID lcid, DISPID *rgDispId)
1120 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1121 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1122 lcid, rgDispId);
1125 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1126 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1127 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1129 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1130 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1131 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1134 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1136 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1138 TRACE("(%p)->(%p)\n", This, p);
1140 /* FIXME: Better check for document node */
1141 if(This == &This->doc->node) {
1142 *p = NULL;
1143 }else {
1144 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
1145 IDispatch_AddRef(*p);
1147 return S_OK;
1150 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1151 HTMLDOMNode2_QueryInterface,
1152 HTMLDOMNode2_AddRef,
1153 HTMLDOMNode2_Release,
1154 HTMLDOMNode2_GetTypeInfoCount,
1155 HTMLDOMNode2_GetTypeInfo,
1156 HTMLDOMNode2_GetIDsOfNames,
1157 HTMLDOMNode2_Invoke,
1158 HTMLDOMNode2_get_ownerDocument
1161 static nsXPCOMCycleCollectionParticipant node_ccp;
1163 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1165 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1167 if(IsEqualGUID(&IID_IUnknown, riid)) {
1168 *ppv = &This->IHTMLDOMNode_iface;
1169 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1170 *ppv = &This->IHTMLDOMNode_iface;
1171 }else if(IsEqualGUID(&IID_IDispatchEx, riid) && This->dispex.data) {
1172 *ppv = &This->dispex.IDispatchEx_iface;
1173 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1174 *ppv = &This->IHTMLDOMNode_iface;
1175 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1176 *ppv = &This->IHTMLDOMNode2_iface;
1177 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1178 *ppv = &node_ccp;
1179 return NS_OK;
1180 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1181 *ppv = &This->IHTMLDOMNode_iface;
1182 return NS_OK;
1183 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1184 return *ppv ? S_OK : E_NOINTERFACE;
1185 }else {
1186 *ppv = NULL;
1187 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1188 return E_NOINTERFACE;
1191 IUnknown_AddRef((IUnknown*)*ppv);
1192 return S_OK;
1195 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1197 if(This->nsnode)
1198 nsIDOMNode_Release(This->nsnode);
1199 if(This->doc && &This->doc->node != This)
1200 htmldoc_release(&This->doc->basedoc);
1201 if(This->event_target)
1202 release_event_target(This->event_target);
1205 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1207 return create_node(This->doc, nsnode, ret);
1210 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1212 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1213 HTMLDOMNode_QI,
1214 HTMLDOMNode_destructor,
1215 HTMLDOMNode_cpc,
1216 HTMLDOMNode_clone
1219 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode)
1221 nsresult nsres;
1223 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1224 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1226 ccref_init(&node->ccref, 1);
1228 if(&doc->node != node)
1229 htmldoc_addref(&doc->basedoc);
1230 node->doc = doc;
1232 nsIDOMNode_AddRef(nsnode);
1233 node->nsnode = nsnode;
1235 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1236 assert(nsres == NS_OK);
1239 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1241 UINT16 node_type;
1242 HRESULT hres;
1244 nsIDOMNode_GetNodeType(nsnode, &node_type);
1246 switch(node_type) {
1247 case ELEMENT_NODE: {
1248 HTMLElement *elem;
1249 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1250 if(FAILED(hres))
1251 return hres;
1252 *ret = &elem->node;
1253 break;
1255 case TEXT_NODE:
1256 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1257 if(FAILED(hres))
1258 return hres;
1259 break;
1260 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1261 case DOCUMENT_TYPE_NODE:
1262 case COMMENT_NODE: {
1263 HTMLElement *comment;
1264 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1265 if(FAILED(hres))
1266 return hres;
1267 *ret = &comment->node;
1268 break;
1270 case ATTRIBUTE_NODE:
1271 ERR("Called on attribute node\n");
1272 return E_UNEXPECTED;
1273 default: {
1274 HTMLDOMNode *node;
1276 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1277 if(!node)
1278 return E_OUTOFMEMORY;
1280 node->vtbl = &HTMLDOMNodeImplVtbl;
1281 HTMLDOMNode_Init(doc, node, nsnode);
1282 *ret = node;
1286 TRACE("type %d ret %p\n", node_type, *ret);
1287 return S_OK;
1290 static void NSAPI HTMLDOMNode_unmark_if_purple(void *p)
1292 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1293 ccref_unmark_if_purple(&This->ccref);
1296 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1298 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1300 TRACE("%p\n", This);
1302 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1304 if(This->nsnode)
1305 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1306 if(This->doc && &This->doc->node != This)
1307 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1308 dispex_traverse(&This->dispex, cb);
1310 if(This->vtbl->traverse)
1311 This->vtbl->traverse(This, cb);
1313 return NS_OK;
1316 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1318 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1320 TRACE("%p\n", This);
1322 if(This->vtbl->unlink)
1323 This->vtbl->unlink(This);
1325 dispex_unlink(&This->dispex);
1327 if(This->nsnode) {
1328 nsIDOMNode *nsnode = This->nsnode;
1329 This->nsnode = NULL;
1330 nsIDOMNode_Release(nsnode);
1333 if(This->doc && &This->doc->node != This) {
1334 HTMLDocument *doc = &This->doc->basedoc;
1335 This->doc = NULL;
1336 htmldoc_release(doc);
1337 }else {
1338 This->doc = NULL;
1341 return NS_OK;
1344 void init_node_cc(void)
1346 static const CCObjCallback node_ccp_callback = {
1347 HTMLDOMNode_unmark_if_purple,
1348 HTMLDOMNode_traverse,
1349 HTMLDOMNode_unlink
1352 ccp_init(&node_ccp, &node_ccp_callback);
1355 HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1357 nsISupports *unk = NULL;
1358 nsresult nsres;
1360 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1361 assert(nsres == NS_OK);
1363 if(unk) {
1364 *ret = get_node_obj((IHTMLDOMNode*)unk);
1365 nsISupports_Release(unk);
1366 return NS_OK;
1369 if(!create) {
1370 *ret = NULL;
1371 return S_OK;
1374 return create_node(This, nsnode, ret);