[MSHTML]
[reactos.git] / reactos / dll / win32 / mshtml / htmlnode.c
1 /*
2 * Copyright 2006 Jacek Caban for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "mshtml_private.h"
20
21 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
22 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
23
24 typedef struct {
25 DispatchEx dispex;
26 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
27
28 LONG ref;
29
30 /* FIXME: implement weak reference */
31 HTMLDocumentNode *doc;
32
33 nsIDOMNodeList *nslist;
34 } HTMLDOMChildrenCollection;
35
36 typedef struct {
37 IEnumVARIANT IEnumVARIANT_iface;
38
39 LONG ref;
40
41 ULONG iter;
42 HTMLDOMChildrenCollection *col;
43 } HTMLDOMChildrenCollectionEnum;
44
45 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
46 {
47 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
48 }
49
50 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
51 {
52 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
53
54 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
55
56 if(IsEqualGUID(riid, &IID_IUnknown)) {
57 *ppv = &This->IEnumVARIANT_iface;
58 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
59 *ppv = &This->IEnumVARIANT_iface;
60 }else {
61 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
62 *ppv = NULL;
63 return E_NOINTERFACE;
64 }
65
66 IUnknown_AddRef((IUnknown*)*ppv);
67 return S_OK;
68 }
69
70 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
71 {
72 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
73 LONG ref = InterlockedIncrement(&This->ref);
74
75 TRACE("(%p) ref=%d\n", This, ref);
76
77 return ref;
78 }
79
80 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
81 {
82 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
83 LONG ref = InterlockedDecrement(&This->ref);
84
85 TRACE("(%p) ref=%d\n", This, ref);
86
87 if(!ref) {
88 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
89 heap_free(This);
90 }
91
92 return ref;
93 }
94
95 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
96 {
97 ULONG len;
98 nsresult nsres;
99
100 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
101 assert(nsres == NS_OK);
102 return len;
103 }
104
105 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
106 {
107 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
108 ULONG fetched = 0, len;
109 nsIDOMNode *nsnode;
110 HTMLDOMNode *node;
111 nsresult nsres;
112 HRESULT hres;
113
114 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
115
116 len = get_enum_len(This);
117
118 while(This->iter+fetched < len && fetched < celt) {
119 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
120 assert(nsres == NS_OK);
121
122 hres = get_node(This->col->doc, nsnode, TRUE, &node);
123 nsIDOMNode_Release(nsnode);
124 if(FAILED(hres)) {
125 ERR("get_node failed: %08x\n", hres);
126 break;
127 }
128
129 V_VT(rgVar+fetched) = VT_DISPATCH;
130 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
131 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
132 fetched++;
133 }
134
135 This->iter += fetched;
136 if(pCeltFetched)
137 *pCeltFetched = fetched;
138 return fetched == celt ? S_OK : S_FALSE;
139 }
140
141 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
142 {
143 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
144 ULONG len;
145
146 TRACE("(%p)->(%d)\n", This, celt);
147
148 len = get_enum_len(This);
149 if(This->iter + celt > len) {
150 This->iter = len;
151 return S_FALSE;
152 }
153
154 This->iter += celt;
155 return S_OK;
156 }
157
158 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
159 {
160 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
161
162 TRACE("(%p)->()\n", This);
163
164 This->iter = 0;
165 return S_OK;
166 }
167
168 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
169 {
170 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
171 FIXME("(%p)->(%p)\n", This, ppEnum);
172 return E_NOTIMPL;
173 }
174
175 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
176 HTMLDOMChildrenCollectionEnum_QueryInterface,
177 HTMLDOMChildrenCollectionEnum_AddRef,
178 HTMLDOMChildrenCollectionEnum_Release,
179 HTMLDOMChildrenCollectionEnum_Next,
180 HTMLDOMChildrenCollectionEnum_Skip,
181 HTMLDOMChildrenCollectionEnum_Reset,
182 HTMLDOMChildrenCollectionEnum_Clone
183 };
184
185 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
186 {
187 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
188 }
189
190 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
191 {
192 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
193
194 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
195
196 if(IsEqualGUID(&IID_IUnknown, riid)) {
197 *ppv = &This->IHTMLDOMChildrenCollection_iface;
198 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
199 *ppv = &This->IHTMLDOMChildrenCollection_iface;
200 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
201 return *ppv ? S_OK : E_NOINTERFACE;
202 }else {
203 *ppv = NULL;
204 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
205 return E_NOINTERFACE;
206 }
207
208 IUnknown_AddRef((IUnknown*)*ppv);
209 return S_OK;
210 }
211
212 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
213 {
214 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
215 LONG ref = InterlockedIncrement(&This->ref);
216
217 TRACE("(%p) ref=%d\n", This, ref);
218
219 return ref;
220 }
221
222 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
223 {
224 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
225 LONG ref = InterlockedDecrement(&This->ref);
226
227 TRACE("(%p) ref=%d\n", This, ref);
228
229 if(!ref) {
230 htmldoc_release(&This->doc->basedoc);
231 nsIDOMNodeList_Release(This->nslist);
232 heap_free(This);
233 }
234
235 return ref;
236 }
237
238 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
239 {
240 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
241 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
242 }
243
244 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
245 LCID lcid, ITypeInfo **ppTInfo)
246 {
247 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
248 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
249 }
250
251 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
252 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
253 {
254 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
255 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
256 lcid, rgDispId);
257 }
258
259 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
260 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
261 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
262 {
263 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
264 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
265 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
266 }
267
268 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
269 {
270 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
271 UINT32 length=0;
272
273 TRACE("(%p)->(%p)\n", This, p);
274
275 nsIDOMNodeList_GetLength(This->nslist, &length);
276 *p = length;
277 return S_OK;
278 }
279
280 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
281 {
282 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
283 HTMLDOMChildrenCollectionEnum *ret;
284
285 TRACE("(%p)->(%p)\n", This, p);
286
287 ret = heap_alloc(sizeof(*ret));
288 if(!ret)
289 return E_OUTOFMEMORY;
290
291 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
292 ret->ref = 1;
293 ret->iter = 0;
294
295 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
296 ret->col = This;
297
298 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
299 return S_OK;
300 }
301
302 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
303 {
304 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
305 nsIDOMNode *nsnode = NULL;
306 HTMLDOMNode *node;
307 UINT32 length=0;
308 nsresult nsres;
309 HRESULT hres;
310
311 TRACE("(%p)->(%d %p)\n", This, index, ppItem);
312
313 if (ppItem)
314 *ppItem = NULL;
315 else
316 return E_POINTER;
317
318 nsIDOMNodeList_GetLength(This->nslist, &length);
319 if(index < 0 || index >= length)
320 return E_INVALIDARG;
321
322 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
323 if(NS_FAILED(nsres) || !nsnode) {
324 ERR("Item failed: %08x\n", nsres);
325 return E_FAIL;
326 }
327
328 hres = get_node(This->doc, nsnode, TRUE, &node);
329 if(FAILED(hres))
330 return hres;
331
332 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
333 return S_OK;
334 }
335
336 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
337 HTMLDOMChildrenCollection_QueryInterface,
338 HTMLDOMChildrenCollection_AddRef,
339 HTMLDOMChildrenCollection_Release,
340 HTMLDOMChildrenCollection_GetTypeInfoCount,
341 HTMLDOMChildrenCollection_GetTypeInfo,
342 HTMLDOMChildrenCollection_GetIDsOfNames,
343 HTMLDOMChildrenCollection_Invoke,
344 HTMLDOMChildrenCollection_get_length,
345 HTMLDOMChildrenCollection_get__newEnum,
346 HTMLDOMChildrenCollection_item
347 };
348
349 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
350 {
351 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
352 }
353
354 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
355
356 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
357 {
358 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
359 WCHAR *ptr;
360 DWORD idx=0;
361 UINT32 len = 0;
362
363 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
364 idx = idx*10 + (*ptr-'0');
365 if(*ptr)
366 return DISP_E_UNKNOWNNAME;
367
368 nsIDOMNodeList_GetLength(This->nslist, &len);
369 if(idx >= len)
370 return DISP_E_UNKNOWNNAME;
371
372 *dispid = DISPID_CHILDCOL_0 + idx;
373 TRACE("ret %x\n", *dispid);
374 return S_OK;
375 }
376
377 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
378 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
379 {
380 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
381
382 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
383
384 switch(flags) {
385 case DISPATCH_PROPERTYGET: {
386 IDispatch *disp = NULL;
387 HRESULT hres;
388
389 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
390 id - DISPID_CHILDCOL_0, &disp);
391 if(FAILED(hres))
392 return hres;
393
394 V_VT(res) = VT_DISPATCH;
395 V_DISPATCH(res) = disp;
396 break;
397 }
398
399 default:
400 FIXME("unimplemented flags %x\n", flags);
401 return E_NOTIMPL;
402 }
403
404 return S_OK;
405 }
406
407 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
408 NULL,
409 HTMLDOMChildrenCollection_get_dispid,
410 HTMLDOMChildrenCollection_invoke,
411 NULL
412 };
413
414 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
415 IHTMLDOMChildrenCollection_tid,
416 0
417 };
418
419 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
420 &HTMLDOMChildrenCollection_dispex_vtbl,
421 DispDOMChildrenCollection_tid,
422 NULL,
423 HTMLDOMChildrenCollection_iface_tids
424 };
425
426 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocumentNode *doc, nsIDOMNodeList *nslist)
427 {
428 HTMLDOMChildrenCollection *ret;
429
430 ret = heap_alloc_zero(sizeof(*ret));
431 if(!ret)
432 return NULL;
433
434 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
435 ret->ref = 1;
436
437 nsIDOMNodeList_AddRef(nslist);
438 ret->nslist = nslist;
439
440 htmldoc_addref(&doc->basedoc);
441 ret->doc = doc;
442
443 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface,
444 &HTMLDOMChildrenCollection_dispex);
445
446 return &ret->IHTMLDOMChildrenCollection_iface;
447 }
448
449 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
450 {
451 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
452 }
453
454 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
455 REFIID riid, void **ppv)
456 {
457 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
458
459 return This->vtbl->qi(This, riid, ppv);
460 }
461
462 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
463 {
464 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
465 LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
466
467 TRACE("(%p) ref=%d\n", This, ref);
468
469 return ref;
470 }
471
472 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
473 {
474 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
475 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
476
477 TRACE("(%p) ref=%d\n", This, ref);
478
479 if(!ref) {
480 if(This->vtbl->unlink)
481 This->vtbl->unlink(This);
482 This->vtbl->destructor(This);
483 release_dispex(&This->dispex);
484 heap_free(This);
485 }
486
487 return ref;
488 }
489
490 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
491 {
492 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
493 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
494 }
495
496 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
497 LCID lcid, ITypeInfo **ppTInfo)
498 {
499 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
500 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
501 }
502
503 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
504 LPOLESTR *rgszNames, UINT cNames,
505 LCID lcid, DISPID *rgDispId)
506 {
507 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
508 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
509 lcid, rgDispId);
510 }
511
512 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
513 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
514 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
515 {
516 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
517 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
518 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
519 }
520
521 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
522 {
523 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
524 UINT16 type = -1;
525
526 TRACE("(%p)->(%p)\n", This, p);
527
528 nsIDOMNode_GetNodeType(This->nsnode, &type);
529
530 switch(type) {
531 case ELEMENT_NODE:
532 *p = 1;
533 break;
534 case TEXT_NODE:
535 *p = 3;
536 break;
537 case COMMENT_NODE:
538 case DOCUMENT_TYPE_NODE:
539 *p = 8;
540 break;
541 case DOCUMENT_NODE:
542 *p = 9;
543 break;
544 case DOCUMENT_FRAGMENT_NODE:
545 *p = 11;
546 break;
547 default:
548 /*
549 * FIXME:
550 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
551 * It needs more tests.
552 */
553 FIXME("type %u\n", type);
554 *p = 0;
555 }
556
557 return S_OK;
558 }
559
560 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
561 {
562 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
563 HTMLDOMNode *node;
564 nsIDOMNode *nsnode;
565 nsresult nsres;
566 HRESULT hres;
567
568 TRACE("(%p)->(%p)\n", This, p);
569
570 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
571 if(NS_FAILED(nsres)) {
572 ERR("GetParentNode failed: %08x\n", nsres);
573 return E_FAIL;
574 }
575
576 if(!nsnode) {
577 *p = NULL;
578 return S_OK;
579 }
580
581 hres = get_node(This->doc, nsnode, TRUE, &node);
582 nsIDOMNode_Release(nsnode);
583 if(FAILED(hres))
584 return hres;
585
586 *p = &node->IHTMLDOMNode_iface;
587 return S_OK;
588 }
589
590 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
591 {
592 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
593 cpp_bool has_child = FALSE;
594 nsresult nsres;
595
596 TRACE("(%p)->(%p)\n", This, fChildren);
597
598 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
599 if(NS_FAILED(nsres))
600 ERR("HasChildNodes failed: %08x\n", nsres);
601
602 *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE;
603 return S_OK;
604 }
605
606 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
607 {
608 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
609 nsIDOMNodeList *nslist;
610 nsresult nsres;
611
612 TRACE("(%p)->(%p)\n", This, p);
613
614 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
615 if(NS_FAILED(nsres)) {
616 ERR("GetChildNodes failed: %08x\n", nsres);
617 return E_FAIL;
618 }
619
620 *p = (IDispatch*)create_child_collection(This->doc, nslist);
621 nsIDOMNodeList_Release(nslist);
622
623 return *p ? S_OK : E_OUTOFMEMORY;
624 }
625
626 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
627 {
628 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
629 HTMLAttributeCollection *col;
630 HRESULT hres;
631
632 TRACE("(%p)->(%p)\n", This, p);
633
634 if(This->vtbl->get_attr_col) {
635 hres = This->vtbl->get_attr_col(This, &col);
636 if(FAILED(hres))
637 return hres;
638
639 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
640 return S_OK;
641 }
642
643 *p = NULL;
644 return S_OK;
645 }
646
647 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
648 VARIANT refChild, IHTMLDOMNode **node)
649 {
650 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
651 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
652 nsIDOMNode *nsnode;
653 nsresult nsres;
654 HRESULT hres = S_OK;
655
656 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
657
658 new_child = get_node_obj(newChild);
659 if(!new_child) {
660 ERR("invalid newChild\n");
661 return E_INVALIDARG;
662 }
663
664 switch(V_VT(&refChild)) {
665 case VT_NULL:
666 break;
667 case VT_DISPATCH: {
668 IHTMLDOMNode *ref_iface;
669
670 if(!V_DISPATCH(&refChild))
671 break;
672
673 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
674 if(FAILED(hres))
675 break;
676
677 ref_node = get_node_obj(ref_iface);
678 IHTMLDOMNode_Release(ref_iface);
679 if(!ref_node) {
680 ERR("unvalid node\n");
681 hres = E_FAIL;
682 break;
683 }
684 break;
685 }
686 default:
687 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
688 hres = E_NOTIMPL;
689 }
690
691 if(SUCCEEDED(hres)) {
692 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
693 if(NS_FAILED(nsres)) {
694 ERR("InsertBefore failed: %08x\n", nsres);
695 hres = E_FAIL;
696 }
697 }
698 node_release(new_child);
699 if(ref_node)
700 node_release(ref_node);
701 if(FAILED(hres))
702 return hres;
703
704 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
705 nsIDOMNode_Release(nsnode);
706 if(FAILED(hres))
707 return hres;
708
709 *node = &node_obj->IHTMLDOMNode_iface;
710 return S_OK;
711 }
712
713 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
714 IHTMLDOMNode **node)
715 {
716 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
717 HTMLDOMNode *node_obj;
718 nsIDOMNode *nsnode;
719 nsresult nsres;
720 HRESULT hres;
721
722 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
723
724 node_obj = get_node_obj(oldChild);
725 if(!node_obj)
726 return E_FAIL;
727
728 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
729 node_release(node_obj);
730 if(NS_FAILED(nsres)) {
731 ERR("RemoveChild failed: %08x\n", nsres);
732 return E_FAIL;
733 }
734
735 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
736 nsIDOMNode_Release(nsnode);
737 if(FAILED(hres))
738 return hres;
739
740 /* FIXME: Make sure that node != newChild */
741 *node = &node_obj->IHTMLDOMNode_iface;
742 return S_OK;
743 }
744
745 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
746 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
747 {
748 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
749 HTMLDOMNode *node_new, *node_old, *ret_node;
750 nsIDOMNode *nsnode;
751 nsresult nsres;
752 HRESULT hres;
753
754 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
755
756 node_new = get_node_obj(newChild);
757 if(!node_new)
758 return E_FAIL;
759
760 node_old = get_node_obj(oldChild);
761 if(!node_old) {
762 node_release(node_new);
763 return E_FAIL;
764 }
765
766 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
767 node_release(node_new);
768 node_release(node_old);
769 if(NS_FAILED(nsres))
770 return E_FAIL;
771
772 hres = get_node(This->doc, nsnode, TRUE, &ret_node);
773 nsIDOMNode_Release(nsnode);
774 if(FAILED(hres))
775 return hres;
776
777 *node = &ret_node->IHTMLDOMNode_iface;
778 return S_OK;
779 }
780
781 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
782 IHTMLDOMNode **clonedNode)
783 {
784 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
785 HTMLDOMNode *new_node;
786 nsIDOMNode *nsnode;
787 nsresult nsres;
788 HRESULT hres;
789
790 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
791
792 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
793 if(NS_FAILED(nsres) || !nsnode) {
794 ERR("CloneNode failed: %08x\n", nsres);
795 return E_FAIL;
796 }
797
798 hres = This->vtbl->clone(This, nsnode, &new_node);
799 if(FAILED(hres))
800 return hres;
801
802 *clonedNode = &new_node->IHTMLDOMNode_iface;
803 return S_OK;
804 }
805
806 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
807 IHTMLDOMNode **removed)
808 {
809 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
810 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
811 return E_NOTIMPL;
812 }
813
814 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
815 IHTMLDOMNode **swappedNode)
816 {
817 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
818 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
819 return E_NOTIMPL;
820 }
821
822 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
823 IHTMLDOMNode **replaced)
824 {
825 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
826 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
827 return E_NOTIMPL;
828 }
829
830 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
831 IHTMLDOMNode **node)
832 {
833 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
834 HTMLDOMNode *node_obj;
835 nsIDOMNode *nsnode;
836 nsresult nsres;
837 HRESULT hres;
838
839 TRACE("(%p)->(%p %p)\n", This, newChild, node);
840
841 node_obj = get_node_obj(newChild);
842 if(!node_obj)
843 return E_FAIL;
844
845 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
846 node_release(node_obj);
847 if(NS_FAILED(nsres)) {
848 ERR("AppendChild failed: %08x\n", nsres);
849 return E_FAIL;
850 }
851
852 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
853 nsIDOMNode_Release(nsnode);
854 if(FAILED(hres))
855 return hres;
856
857 /* FIXME: Make sure that node != newChild */
858 *node = &node_obj->IHTMLDOMNode_iface;
859 return S_OK;
860 }
861
862 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
863 {
864 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
865 nsAString name;
866 nsresult nsres;
867
868 TRACE("(%p)->(%p)\n", This, p);
869
870 nsAString_Init(&name, NULL);
871 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
872 return return_nsstr(nsres, &name, p);
873 }
874
875 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
876 {
877 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
878
879 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
880
881 switch(V_VT(&v)) {
882 case VT_BSTR: {
883 nsAString val_str;
884
885 nsAString_InitDepend(&val_str, V_BSTR(&v));
886 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
887 nsAString_Finish(&val_str);
888
889 return S_OK;
890 }
891
892 default:
893 FIXME("unsupported value %s\n", debugstr_variant(&v));
894 }
895
896 return E_NOTIMPL;
897 }
898
899 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
900 {
901 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
902 const PRUnichar *val;
903 nsAString val_str;
904
905 TRACE("(%p)->(%p)\n", This, p);
906
907 nsAString_Init(&val_str, NULL);
908 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
909 nsAString_GetData(&val_str, &val);
910
911 if(*val) {
912 V_VT(p) = VT_BSTR;
913 V_BSTR(p) = SysAllocString(val);
914 }else {
915 V_VT(p) = VT_NULL;
916 }
917
918 nsAString_Finish(&val_str);
919
920 return S_OK;
921 }
922
923 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
924 {
925 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
926 nsIDOMNode *nschild = NULL;
927 HTMLDOMNode *node;
928 HRESULT hres;
929
930 TRACE("(%p)->(%p)\n", This, p);
931
932 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
933 if(!nschild) {
934 *p = NULL;
935 return S_OK;
936 }
937
938 hres = get_node(This->doc, nschild, TRUE, &node);
939 nsIDOMNode_Release(nschild);
940 if(FAILED(hres))
941 return hres;
942
943 *p = &node->IHTMLDOMNode_iface;
944 return S_OK;
945 }
946
947 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
948 {
949 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
950 nsIDOMNode *nschild = NULL;
951 HTMLDOMNode *node;
952 HRESULT hres;
953
954 TRACE("(%p)->(%p)\n", This, p);
955
956 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
957 if(!nschild) {
958 *p = NULL;
959 return S_OK;
960 }
961
962 hres = get_node(This->doc, nschild, TRUE, &node);
963 nsIDOMNode_Release(nschild);
964 if(FAILED(hres))
965 return hres;
966
967 *p = &node->IHTMLDOMNode_iface;
968 return S_OK;
969 }
970
971 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
972 {
973 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
974 nsIDOMNode *nschild = NULL;
975 HTMLDOMNode *node;
976 HRESULT hres;
977
978 TRACE("(%p)->(%p)\n", This, p);
979
980 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
981 if(!nschild) {
982 *p = NULL;
983 return S_OK;
984 }
985
986 hres = get_node(This->doc, nschild, TRUE, &node);
987 nsIDOMNode_Release(nschild);
988 if(FAILED(hres))
989 return hres;
990
991 *p = &node->IHTMLDOMNode_iface;
992 return S_OK;
993 }
994
995 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
996 {
997 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
998 nsIDOMNode *nssibling = NULL;
999 HTMLDOMNode *node;
1000 HRESULT hres;
1001
1002 TRACE("(%p)->(%p)\n", This, p);
1003
1004 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1005 if(!nssibling) {
1006 *p = NULL;
1007 return S_OK;
1008 }
1009
1010 hres = get_node(This->doc, nssibling, TRUE, &node);
1011 nsIDOMNode_Release(nssibling);
1012 if(FAILED(hres))
1013 return hres;
1014
1015 *p = &node->IHTMLDOMNode_iface;
1016 return S_OK;
1017 }
1018
1019 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1020 HTMLDOMNode_QueryInterface,
1021 HTMLDOMNode_AddRef,
1022 HTMLDOMNode_Release,
1023 HTMLDOMNode_GetTypeInfoCount,
1024 HTMLDOMNode_GetTypeInfo,
1025 HTMLDOMNode_GetIDsOfNames,
1026 HTMLDOMNode_Invoke,
1027 HTMLDOMNode_get_nodeType,
1028 HTMLDOMNode_get_parentNode,
1029 HTMLDOMNode_hasChildNodes,
1030 HTMLDOMNode_get_childNodes,
1031 HTMLDOMNode_get_attributes,
1032 HTMLDOMNode_insertBefore,
1033 HTMLDOMNode_removeChild,
1034 HTMLDOMNode_replaceChild,
1035 HTMLDOMNode_cloneNode,
1036 HTMLDOMNode_removeNode,
1037 HTMLDOMNode_swapNode,
1038 HTMLDOMNode_replaceNode,
1039 HTMLDOMNode_appendChild,
1040 HTMLDOMNode_get_nodeName,
1041 HTMLDOMNode_put_nodeValue,
1042 HTMLDOMNode_get_nodeValue,
1043 HTMLDOMNode_get_firstChild,
1044 HTMLDOMNode_get_lastChild,
1045 HTMLDOMNode_get_previousSibling,
1046 HTMLDOMNode_get_nextSibling
1047 };
1048
1049 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1050 {
1051 HTMLDOMNode *ret;
1052
1053 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1054 return NULL;
1055
1056 ret = impl_from_IHTMLDOMNode(iface);
1057 node_addref(ret);
1058 return ret;
1059 }
1060
1061 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1062 {
1063 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1064 }
1065
1066 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1067 REFIID riid, void **ppv)
1068 {
1069 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1070
1071 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1072 }
1073
1074 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1075 {
1076 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1077
1078 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1079 }
1080
1081 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1082 {
1083 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1084
1085 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1086 }
1087
1088 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1089 {
1090 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1091 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1092 }
1093
1094 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1095 LCID lcid, ITypeInfo **ppTInfo)
1096 {
1097 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1098 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1099 }
1100
1101 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1102 LPOLESTR *rgszNames, UINT cNames,
1103 LCID lcid, DISPID *rgDispId)
1104 {
1105 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1106 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1107 lcid, rgDispId);
1108 }
1109
1110 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1111 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1112 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1113 {
1114 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1115 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1116 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1117 }
1118
1119 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1120 {
1121 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1122
1123 TRACE("(%p)->(%p)\n", This, p);
1124
1125 /* FIXME: Better check for document node */
1126 if(This == &This->doc->node) {
1127 *p = NULL;
1128 }else {
1129 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
1130 IDispatch_AddRef(*p);
1131 }
1132 return S_OK;
1133 }
1134
1135 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1136 HTMLDOMNode2_QueryInterface,
1137 HTMLDOMNode2_AddRef,
1138 HTMLDOMNode2_Release,
1139 HTMLDOMNode2_GetTypeInfoCount,
1140 HTMLDOMNode2_GetTypeInfo,
1141 HTMLDOMNode2_GetIDsOfNames,
1142 HTMLDOMNode2_Invoke,
1143 HTMLDOMNode2_get_ownerDocument
1144 };
1145
1146 static nsXPCOMCycleCollectionParticipant node_ccp;
1147
1148 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1149 {
1150 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1151
1152 if(IsEqualGUID(&IID_IUnknown, riid)) {
1153 *ppv = &This->IHTMLDOMNode_iface;
1154 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1155 *ppv = &This->IHTMLDOMNode_iface;
1156 }else if(IsEqualGUID(&IID_IDispatchEx, riid) && This->dispex.data) {
1157 *ppv = &This->dispex.IDispatchEx_iface;
1158 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1159 *ppv = &This->IHTMLDOMNode_iface;
1160 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1161 *ppv = &This->IHTMLDOMNode2_iface;
1162 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1163 *ppv = &node_ccp;
1164 return NS_OK;
1165 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1166 *ppv = &This->IHTMLDOMNode_iface;
1167 return NS_OK;
1168 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1169 return *ppv ? S_OK : E_NOINTERFACE;
1170 }else {
1171 *ppv = NULL;
1172 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1173 return E_NOINTERFACE;
1174 }
1175
1176 IUnknown_AddRef((IUnknown*)*ppv);
1177 return S_OK;
1178 }
1179
1180 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1181 {
1182 if(This->nsnode)
1183 nsIDOMNode_Release(This->nsnode);
1184 if(This->doc && &This->doc->node != This)
1185 htmldoc_release(&This->doc->basedoc);
1186 if(This->event_target)
1187 release_event_target(This->event_target);
1188 }
1189
1190 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1191 {
1192 return create_node(This->doc, nsnode, ret);
1193 }
1194
1195 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1196
1197 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1198 HTMLDOMNode_QI,
1199 HTMLDOMNode_destructor,
1200 HTMLDOMNode_cpc,
1201 HTMLDOMNode_clone
1202 };
1203
1204 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode)
1205 {
1206 nsresult nsres;
1207
1208 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1209 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1210
1211 ccref_init(&node->ccref, 1);
1212
1213 if(&doc->node != node)
1214 htmldoc_addref(&doc->basedoc);
1215 node->doc = doc;
1216
1217 nsIDOMNode_AddRef(nsnode);
1218 node->nsnode = nsnode;
1219
1220 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1221 assert(nsres == NS_OK);
1222 }
1223
1224 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1225 {
1226 UINT16 node_type;
1227 HRESULT hres;
1228
1229 nsIDOMNode_GetNodeType(nsnode, &node_type);
1230
1231 switch(node_type) {
1232 case ELEMENT_NODE: {
1233 HTMLElement *elem;
1234 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1235 if(FAILED(hres))
1236 return hres;
1237 *ret = &elem->node;
1238 break;
1239 }
1240 case TEXT_NODE:
1241 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1242 if(FAILED(hres))
1243 return hres;
1244 break;
1245 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1246 case DOCUMENT_TYPE_NODE:
1247 case COMMENT_NODE: {
1248 HTMLElement *comment;
1249 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1250 if(FAILED(hres))
1251 return hres;
1252 *ret = &comment->node;
1253 break;
1254 }
1255 case ATTRIBUTE_NODE:
1256 ERR("Called on attribute node\n");
1257 return E_UNEXPECTED;
1258 default: {
1259 HTMLDOMNode *node;
1260
1261 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1262 if(!node)
1263 return E_OUTOFMEMORY;
1264
1265 node->vtbl = &HTMLDOMNodeImplVtbl;
1266 HTMLDOMNode_Init(doc, node, nsnode);
1267 *ret = node;
1268 }
1269 }
1270
1271 TRACE("type %d ret %p\n", node_type, *ret);
1272 return S_OK;
1273 }
1274
1275 static void NSAPI HTMLDOMNode_unmark_if_purple(void *p)
1276 {
1277 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1278 ccref_unmark_if_purple(&This->ccref);
1279 }
1280
1281 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1282 {
1283 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1284
1285 TRACE("%p\n", This);
1286
1287 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1288
1289 if(This->nsnode)
1290 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1291 if(This->doc && &This->doc->node != This)
1292 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1293 dispex_traverse(&This->dispex, cb);
1294
1295 if(This->vtbl->traverse)
1296 This->vtbl->traverse(This, cb);
1297
1298 return NS_OK;
1299 }
1300
1301 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1302 {
1303 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1304
1305 TRACE("%p\n", This);
1306
1307 if(This->vtbl->unlink)
1308 This->vtbl->unlink(This);
1309
1310 dispex_unlink(&This->dispex);
1311
1312 if(This->nsnode) {
1313 nsIDOMNode *nsnode = This->nsnode;
1314 This->nsnode = NULL;
1315 nsIDOMNode_Release(nsnode);
1316 }
1317
1318 if(This->doc && &This->doc->node != This) {
1319 HTMLDocument *doc = &This->doc->basedoc;
1320 This->doc = NULL;
1321 htmldoc_release(doc);
1322 }else {
1323 This->doc = NULL;
1324 }
1325
1326 return NS_OK;
1327 }
1328
1329 void init_node_cc(void)
1330 {
1331 static const CCObjCallback node_ccp_callback = {
1332 HTMLDOMNode_unmark_if_purple,
1333 HTMLDOMNode_traverse,
1334 HTMLDOMNode_unlink
1335 };
1336
1337 ccp_init(&node_ccp, &node_ccp_callback);
1338 }
1339
1340 HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1341 {
1342 nsISupports *unk = NULL;
1343 nsresult nsres;
1344
1345 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1346 assert(nsres == NS_OK);
1347
1348 if(unk) {
1349 *ret = get_node_obj((IHTMLDOMNode*)unk);
1350 nsISupports_Release(unk);
1351 return NS_OK;
1352 }
1353
1354 if(!create) {
1355 *ret = NULL;
1356 return S_OK;
1357 }
1358
1359 return create_node(This, nsnode, ret);
1360 }