winex11: add owned windows to taskbar if owner is not mapped
[wine] / dlls / 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 <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27
28 #include "wine/debug.h"
29
30 #include "mshtml_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
33
34 #define NSSUPPORTS(x)  ((nsISupports*)  &(x)->lpSupportsVtbl)
35
36 #define HTMLDOMNODE_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode, iface)
37
38 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
39                                                  REFIID riid, void **ppv)
40 {
41     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
42
43     return This->vtbl->qi(This, riid, ppv);
44 }
45
46 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
47 {
48     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
49     LONG ref = InterlockedIncrement(&This->ref);
50
51     TRACE("(%p) ref=%d\n", This, ref);
52
53     return ref;
54 }
55
56 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
57 {
58     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
59     LONG ref = InterlockedDecrement(&This->ref);
60
61     TRACE("(%p) ref=%d\n", This, ref);
62
63     if(!ref) {
64         This->vtbl->destructor(This);
65         heap_free(This);
66     }
67
68     return ref;
69 }
70
71 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
72 {
73     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
74     FIXME("(%p)->(%p)\n", This, pctinfo);
75     return E_NOTIMPL;
76 }
77
78 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
79                                               LCID lcid, ITypeInfo **ppTInfo)
80 {
81     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
82     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
83     return E_NOTIMPL;
84 }
85
86 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
87                                                 LPOLESTR *rgszNames, UINT cNames,
88                                                 LCID lcid, DISPID *rgDispId)
89 {
90     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
91     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
92                                         lcid, rgDispId);
93     return E_NOTIMPL;
94 }
95
96 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
97                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
98                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
99 {
100     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
101     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
102             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
103     return E_NOTIMPL;
104 }
105
106 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, long *p)
107 {
108     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
109     FIXME("(%p)->(%p)\n", This, p);
110     return E_NOTIMPL;
111 }
112
113 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
114 {
115     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
116     FIXME("(%p)->(%p)\n", This, p);
117     return E_NOTIMPL;
118 }
119
120 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
121 {
122     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
123     FIXME("(%p)->(%p)\n", This, fChildren);
124     return E_NOTIMPL;
125 }
126
127 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
128 {
129     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
130     FIXME("(%p)->(%p)\n", This, p);
131     return E_NOTIMPL;
132 }
133
134 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
135 {
136     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
137     FIXME("(%p)->(%p)\n", This, p);
138     return E_NOTIMPL;
139 }
140
141 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
142                                                VARIANT refChild, IHTMLDOMNode **node)
143 {
144     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
145     FIXME("(%p)->(%p v %p)\n", This, newChild, node);
146     return E_NOTIMPL;
147 }
148
149 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
150                                               IHTMLDOMNode **node)
151 {
152     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
153     FIXME("(%p)->(%p %p)\n", This, newChild, node);
154     return E_NOTIMPL;
155 }
156
157 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
158                                                IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
159 {
160     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
161     FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
162     return E_NOTIMPL;
163 }
164
165 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
166                                             IHTMLDOMNode **clonedNode)
167 {
168     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
169     FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode);
170     return E_NOTIMPL;
171 }
172
173 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
174                                              IHTMLDOMNode **removed)
175 {
176     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
177     FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
182                                            IHTMLDOMNode **swappedNode)
183 {
184     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
185     FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
186     return E_NOTIMPL;
187 }
188
189 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
190                                               IHTMLDOMNode **replaced)
191 {
192     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
193     FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
194     return E_NOTIMPL;
195 }
196
197 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
198                                               IHTMLDOMNode **node)
199 {
200     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
201     FIXME("(%p)->(%p %p)\n", This, newChild, node);
202     return E_NOTIMPL;
203 }
204
205 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
206 {
207     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
208
209     TRACE("(%p)->(%p)\n", This, p);
210
211     *p = NULL;
212
213     if(This->nsnode) {
214         nsAString name_str;
215         const PRUnichar *name;
216         nsresult nsres;
217
218         nsAString_Init(&name_str, NULL);
219         nsres = nsIDOMNode_GetNodeName(This->nsnode, &name_str);
220
221         if(NS_SUCCEEDED(nsres)) {
222             nsAString_GetData(&name_str, &name);
223             *p = SysAllocString(name);
224         }else {
225             ERR("GetNodeName failed: %08x\n", nsres);
226         }
227
228         nsAString_Finish(&name_str);
229     }
230
231     return S_OK;
232 }
233
234 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
235 {
236     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
237     FIXME("(%p)->()\n", This);
238     return E_NOTIMPL;
239 }
240
241 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
242 {
243     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
244     FIXME("(%p)->(%p)\n", This, p);
245     return E_NOTIMPL;
246 }
247
248 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
249 {
250     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
251     FIXME("(%p)->(%p)\n", This, p);
252     return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
256 {
257     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
258     FIXME("(%p)->(%p)\n", This, p);
259     return E_NOTIMPL;
260 }
261
262 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
263 {
264     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
265     FIXME("(%p)->(%p)\n", This, p);
266     return E_NOTIMPL;
267 }
268
269 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
270 {
271     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
272     FIXME("(%p)->(%p)\n", This, p);
273     return E_NOTIMPL;
274 }
275
276 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
277     HTMLDOMNode_QueryInterface,
278     HTMLDOMNode_AddRef,
279     HTMLDOMNode_Release,
280     HTMLDOMNode_GetTypeInfoCount,
281     HTMLDOMNode_GetTypeInfo,
282     HTMLDOMNode_GetIDsOfNames,
283     HTMLDOMNode_Invoke,
284     HTMLDOMNode_get_nodeType,
285     HTMLDOMNode_get_parentNode,
286     HTMLDOMNode_hasChildNodes,
287     HTMLDOMNode_get_childNodes,
288     HTMLDOMNode_get_attributes,
289     HTMLDOMNode_insertBefore,
290     HTMLDOMNode_removeChild,
291     HTMLDOMNode_replaceChild,
292     HTMLDOMNode_cloneNode,
293     HTMLDOMNode_removeNode,
294     HTMLDOMNode_swapNode,
295     HTMLDOMNode_replaceNode,
296     HTMLDOMNode_appendChild,
297     HTMLDOMNode_get_nodeName,
298     HTMLDOMNode_put_nodeValue,
299     HTMLDOMNode_get_nodeValue,
300     HTMLDOMNode_get_firstChild,
301     HTMLDOMNode_get_lastChild,
302     HTMLDOMNode_get_previousSibling,
303     HTMLDOMNode_get_nextSibling
304 };
305
306 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
307 {
308     *ppv = NULL;
309
310     if(IsEqualGUID(&IID_IUnknown, riid)) {
311         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
312         *ppv = HTMLDOMNODE(This);
313     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
314         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
315         *ppv = HTMLDOMNODE(This);
316     }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
317         TRACE("(%p)->(IID_IHTMLDOMNode %p)\n", This, ppv);
318         *ppv = HTMLDOMNODE(This);
319     }
320
321     if(*ppv) {
322         IUnknown_AddRef((IUnknown*)*ppv);
323         return S_OK;
324     }
325
326     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
327     return E_NOINTERFACE;
328 }
329
330 void HTMLDOMNode_destructor(HTMLDOMNode *This)
331 {
332     if(This->nsnode)
333         nsIDOMNode_Release(This->nsnode);
334 }
335
336 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
337     HTMLDOMNode_QI,
338     HTMLDOMNode_destructor
339 };
340
341 static HTMLDOMNode *create_node(HTMLDocument *doc, nsIDOMNode *nsnode)
342 {
343     HTMLDOMNode *ret;
344     PRUint16 node_type;
345
346     nsIDOMNode_GetNodeType(nsnode, &node_type);
347
348     switch(node_type) {
349     case ELEMENT_NODE:
350         ret = &HTMLElement_Create(nsnode)->node;
351         break;
352     default:
353         ret = heap_alloc(sizeof(HTMLDOMNode));
354         ret->vtbl = &HTMLDOMNodeImplVtbl;
355     }
356
357     ret->lpHTMLDOMNodeVtbl = &HTMLDOMNodeVtbl;
358     ret->ref = 1;
359     ret->doc = doc;
360
361     nsIDOMNode_AddRef(nsnode);
362     ret->nsnode = nsnode;
363
364     return ret;
365 }
366
367 /*
368  * FIXME
369  * List looks really ugly here. We should use a better data structure or
370  * (better) find a way to store HTMLDOMelement pointer in nsIDOMNode.
371  */
372
373 HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode, BOOL create)
374 {
375     HTMLDOMNode *iter = This->nodes, *ret;
376
377     while(iter) {
378         if(iter->nsnode == nsnode)
379             break;
380         iter = iter->next;
381     }
382
383     if(iter || !create)
384         return iter;
385
386     ret = create_node(This, nsnode);
387
388     ret->next = This->nodes;
389     This->nodes = ret;
390
391     return ret;
392 }
393
394 void release_nodes(HTMLDocument *This)
395 {
396     HTMLDOMNode *iter, *next;
397
398     if(!This->nodes)
399         return;
400
401     for(iter = This->nodes; iter; iter = next) {
402         next = iter->next;
403         iter->doc = NULL;
404         IHTMLDOMNode_Release(HTMLDOMNODE(iter));
405     }
406 }