mshtml: Reimplement IHTMLStyle::get_backgroundPositionY using background-position...
[wine] / dlls / msxml3 / nodelist.c
1 /*
2  *    Node list implementation
3  *
4  * Copyright 2005 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 # include <libxml/xmlerror.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "msxml6.h"
36
37 #include "msxml_private.h"
38
39 #include "wine/debug.h"
40
41 /* This file implements the object returned by childNodes property. Note that this is
42  * not the IXMLDOMNodeList returned by XPath querites - it's implemented in queryresult.c.
43  * They are different because the list returned by childNodes:
44  *  - is "live" - changes to the XML tree are automatically reflected in the list
45  *  - doesn't supports IXMLDOMSelection
46  *  - note that an attribute node have a text child in DOM but not in the XPath data model
47  *    thus the child is inaccessible by an XPath query
48  */
49
50 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
51
52 #ifdef HAVE_LIBXML2
53
54 typedef struct _xmlnodelist
55 {
56     IXMLDOMNodeList IXMLDOMNodeList_iface;
57     LONG ref;
58     xmlNodePtr parent;
59     xmlNodePtr current;
60 } xmlnodelist;
61
62 static inline xmlnodelist *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
63 {
64     return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface);
65 }
66
67 static HRESULT WINAPI xmlnodelist_QueryInterface(
68     IXMLDOMNodeList *iface,
69     REFIID riid,
70     void** ppvObject )
71 {
72     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
73
74     if(!ppvObject)
75         return E_INVALIDARG;
76
77     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
78          IsEqualGUID( riid, &IID_IDispatch ) ||
79          IsEqualGUID( riid, &IID_IXMLDOMNodeList ) )
80     {
81         *ppvObject = iface;
82     }
83     else
84     {
85         FIXME("interface %s not implemented\n", debugstr_guid(riid));
86         *ppvObject = NULL;
87         return E_NOINTERFACE;
88     }
89
90     IXMLDOMNodeList_AddRef( iface );
91
92     return S_OK;
93 }
94
95 static ULONG WINAPI xmlnodelist_AddRef(
96     IXMLDOMNodeList *iface )
97 {
98     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
99     return InterlockedIncrement( &This->ref );
100 }
101
102 static ULONG WINAPI xmlnodelist_Release(
103     IXMLDOMNodeList *iface )
104 {
105     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
106     ULONG ref;
107
108     ref = InterlockedDecrement( &This->ref );
109     if ( ref == 0 )
110     {
111         xmldoc_release( This->parent->doc );
112         heap_free( This );
113     }
114
115     return ref;
116 }
117
118 static HRESULT WINAPI xmlnodelist_GetTypeInfoCount(
119     IXMLDOMNodeList *iface,
120     UINT* pctinfo )
121 {
122     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
123
124     TRACE("(%p)->(%p)\n", This, pctinfo);
125
126     *pctinfo = 1;
127
128     return S_OK;
129 }
130
131 static HRESULT WINAPI xmlnodelist_GetTypeInfo(
132     IXMLDOMNodeList *iface,
133     UINT iTInfo,
134     LCID lcid,
135     ITypeInfo** ppTInfo )
136 {
137     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
138     HRESULT hr;
139
140     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
141
142     hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo);
143
144     return hr;
145 }
146
147 static HRESULT WINAPI xmlnodelist_GetIDsOfNames(
148     IXMLDOMNodeList *iface,
149     REFIID riid,
150     LPOLESTR* rgszNames,
151     UINT cNames,
152     LCID lcid,
153     DISPID* rgDispId )
154 {
155     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
156     ITypeInfo *typeinfo;
157     HRESULT hr;
158
159     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
160           lcid, rgDispId);
161
162     if(!rgszNames || cNames == 0 || !rgDispId)
163         return E_INVALIDARG;
164
165     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
166     if(SUCCEEDED(hr))
167     {
168         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
169         ITypeInfo_Release(typeinfo);
170     }
171
172     return hr;
173 }
174
175 static HRESULT WINAPI xmlnodelist_Invoke(
176     IXMLDOMNodeList *iface,
177     DISPID dispIdMember,
178     REFIID riid,
179     LCID lcid,
180     WORD wFlags,
181     DISPPARAMS* pDispParams,
182     VARIANT* pVarResult,
183     EXCEPINFO* pExcepInfo,
184     UINT* puArgErr )
185 {
186     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
187     ITypeInfo *typeinfo;
188     HRESULT hr;
189
190     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
191           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
192
193     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
194     if(SUCCEEDED(hr))
195     {
196         hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNodeList_iface, dispIdMember, wFlags,
197                 pDispParams, pVarResult, pExcepInfo, puArgErr);
198         ITypeInfo_Release(typeinfo);
199     }
200
201     return hr;
202 }
203
204 static HRESULT WINAPI xmlnodelist_get_item(
205         IXMLDOMNodeList* iface,
206         LONG index,
207         IXMLDOMNode** listItem)
208 {
209     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
210     xmlNodePtr curr;
211     LONG nodeIndex = 0;
212
213     TRACE("(%p)->(%d %p)\n", This, index, listItem);
214
215     if(!listItem)
216         return E_INVALIDARG;
217
218     *listItem = NULL;
219
220     if (index < 0)
221         return S_FALSE;
222
223     curr = This->parent->children;
224     while(curr)
225     {
226         if(nodeIndex++ == index) break;
227         curr = curr->next;
228     }
229     if(!curr) return S_FALSE;
230
231     *listItem = create_node( curr );
232
233     return S_OK;
234 }
235
236 static HRESULT WINAPI xmlnodelist_get_length(
237         IXMLDOMNodeList* iface,
238         LONG* listLength)
239 {
240
241     xmlNodePtr curr;
242     LONG nodeCount = 0;
243
244     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
245
246     TRACE("(%p)->(%p)\n", This, listLength);
247
248     if(!listLength)
249         return E_INVALIDARG;
250
251     curr = This->parent->children;
252     while (curr)
253     {
254         nodeCount++;
255         curr = curr->next;
256     }
257
258     *listLength = nodeCount;
259     return S_OK;
260 }
261
262 static HRESULT WINAPI xmlnodelist_nextNode(
263         IXMLDOMNodeList* iface,
264         IXMLDOMNode** nextItem)
265 {
266     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
267
268     TRACE("(%p)->(%p)\n", This, nextItem );
269
270     if(!nextItem)
271         return E_INVALIDARG;
272
273     *nextItem = NULL;
274
275     if (!This->current)
276         return S_FALSE;
277
278     *nextItem = create_node( This->current );
279     This->current = This->current->next;
280     return S_OK;
281 }
282
283 static HRESULT WINAPI xmlnodelist_reset(
284         IXMLDOMNodeList* iface)
285 {
286     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
287
288     TRACE("%p\n", This);
289     This->current = This->parent->children;
290     return S_OK;
291 }
292
293 static HRESULT WINAPI xmlnodelist__newEnum(
294         IXMLDOMNodeList* iface,
295         IUnknown** ppUnk)
296 {
297     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
298     FIXME("(%p)->(%p)\n", This, ppUnk);
299     return E_NOTIMPL;
300 }
301
302
303 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
304 {
305     xmlnodelist_QueryInterface,
306     xmlnodelist_AddRef,
307     xmlnodelist_Release,
308     xmlnodelist_GetTypeInfoCount,
309     xmlnodelist_GetTypeInfo,
310     xmlnodelist_GetIDsOfNames,
311     xmlnodelist_Invoke,
312     xmlnodelist_get_item,
313     xmlnodelist_get_length,
314     xmlnodelist_nextNode,
315     xmlnodelist_reset,
316     xmlnodelist__newEnum,
317 };
318
319 IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node )
320 {
321     xmlnodelist *nodelist;
322
323     nodelist = heap_alloc( sizeof *nodelist );
324     if ( !nodelist )
325         return NULL;
326
327     nodelist->IXMLDOMNodeList_iface.lpVtbl = &xmlnodelist_vtbl;
328     nodelist->ref = 1;
329     nodelist->parent = node;
330     nodelist->current = node->children;
331
332     xmldoc_add_ref( node->doc );
333
334     return &nodelist->IXMLDOMNodeList_iface;
335 }
336
337 #endif