mshtml: Print wine_gecko version in load_wine_gecko.
[wine] / dlls / mshtml / htmlelem.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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34
35 #include "mshtml_private.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 static HRESULT HTMLElementCollection_Create(IUnknown*,HTMLElement**,DWORD,IDispatch**);
40
41 typedef struct {
42     HTMLElement **buf;
43     DWORD len;
44     DWORD size;
45 } elem_vector;
46
47 static void elem_vector_add(elem_vector *buf, HTMLElement *elem)
48 {
49     if(buf->len == buf->size) {
50         buf->size <<= 1;
51         buf->buf = mshtml_realloc(buf->buf, buf->size*sizeof(HTMLElement**));
52     }
53
54     buf->buf[buf->len++] = elem;
55 }
56
57 #define HTMLELEM_THIS(iface) DEFINE_THIS(HTMLElement, HTMLElement, iface)
58
59 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
60                                                  REFIID riid, void **ppv)
61 {
62     HTMLElement *This = HTMLELEM_THIS(iface);
63     HRESULT hres;
64
65     if(This->impl)
66         return IUnknown_QueryInterface(This->impl, riid, ppv);
67
68     hres = HTMLElement_QI(This, riid, ppv);
69     if(FAILED(hres))
70         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
71
72     return hres;
73 }
74
75 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
76 {
77     HTMLElement *This = HTMLELEM_THIS(iface);
78
79     if(This->impl)
80         return IUnknown_AddRef(This->impl);
81
82     TRACE("(%p)\n", This);
83     return IHTMLDocument2_AddRef(HTMLDOC(This->node->doc));
84 }
85
86 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
87 {
88     HTMLElement *This = HTMLELEM_THIS(iface);
89
90     if(This->impl)
91         return IUnknown_Release(This->impl);
92
93     TRACE("(%p)\n", This);
94     return IHTMLDocument2_Release(HTMLDOC(This->node->doc));
95 }
96
97 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
98 {
99     HTMLElement *This = HTMLELEM_THIS(iface);
100     FIXME("(%p)->(%p)\n", This, pctinfo);
101     return E_NOTIMPL;
102 }
103
104 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
105                                               LCID lcid, ITypeInfo **ppTInfo)
106 {
107     HTMLElement *This = HTMLELEM_THIS(iface);
108     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
109     return E_NOTIMPL;
110 }
111
112 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
113                                                 LPOLESTR *rgszNames, UINT cNames,
114                                                 LCID lcid, DISPID *rgDispId)
115 {
116     HTMLElement *This = HTMLELEM_THIS(iface);
117     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
118                                         lcid, rgDispId);
119     return E_NOTIMPL;
120 }
121
122 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
123                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
124                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
125 {
126     HTMLElement *This = HTMLELEM_THIS(iface);
127     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
128             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
129     return E_NOTIMPL;
130 }
131
132 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
133                                                VARIANT AttributeValue, LONG lFlags)
134 {
135     HTMLElement *This = HTMLELEM_THIS(iface);
136     FIXME("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
137     return E_NOTIMPL;
138 }
139
140 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
141                                                LONG lFlags, VARIANT *AttributeValue)
142 {
143     HTMLElement *This = HTMLELEM_THIS(iface);
144     nsAString attr_str;
145     nsAString value_str;
146     const PRUnichar *value;
147     nsresult nsres;
148     HRESULT hres = S_OK;
149
150     WARN("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
151
152     nsAString_Init(&attr_str, strAttributeName);
153     nsAString_Init(&value_str, NULL);
154
155     nsres = nsIDOMHTMLElement_GetAttribute(This->nselem, &attr_str, &value_str);
156     nsAString_Finish(&attr_str);
157
158     if(NS_SUCCEEDED(nsres)) {
159         nsAString_GetData(&value_str, &value, NULL);
160         V_VT(AttributeValue) = VT_BSTR;
161         V_BSTR(AttributeValue) = SysAllocString(value);
162         TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
163     }else {
164         ERR("GetAttribute failed: %08x\n", nsres);
165         hres = E_FAIL;
166     }
167
168     nsAString_Finish(&value_str);
169
170     return hres;
171 }
172
173 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
174                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
175 {
176     HTMLElement *This = HTMLELEM_THIS(iface);
177     FIXME("(%p)->()\n", This);
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
182 {
183     HTMLElement *This = HTMLELEM_THIS(iface);
184     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
185     return E_NOTIMPL;
186 }
187
188 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
189 {
190     HTMLElement *This = HTMLELEM_THIS(iface);
191     nsAString class_str;
192     nsresult nsres;
193     HRESULT hres = S_OK;
194
195     TRACE("(%p)->(%p)\n", This, p);
196
197     nsAString_Init(&class_str, NULL);
198     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
199
200     if(NS_SUCCEEDED(nsres)) {
201         const PRUnichar *class;
202         nsAString_GetData(&class_str, &class, NULL);
203         *p = SysAllocString(class);
204     }else {
205         ERR("GetClassName failed: %08x\n", nsres);
206         hres = E_FAIL;
207     }
208
209     nsAString_Finish(&class_str);
210
211     TRACE("className=%s\n", debugstr_w(*p));
212     return hres;
213 }
214
215 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
216 {
217     HTMLElement *This = HTMLELEM_THIS(iface);
218     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
223 {
224     HTMLElement *This = HTMLELEM_THIS(iface);
225     FIXME("(%p)->(%p)\n", This, p);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
230 {
231     HTMLElement *This = HTMLELEM_THIS(iface);
232     FIXME("(%p)->(%p)\n", This, p);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
237 {
238     HTMLElement *This = HTMLELEM_THIS(iface);
239     FIXME("(%p)->(%p)\n", This, p);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
244 {
245     HTMLElement *This = HTMLELEM_THIS(iface);
246     FIXME("(%p)->(%p)\n", This, p);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
251 {
252     HTMLElement *This = HTMLELEM_THIS(iface);
253     FIXME("(%p)->()\n", This);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
258 {
259     HTMLElement *This = HTMLELEM_THIS(iface);
260     FIXME("(%p)->(%p)\n", This, p);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
265 {
266     HTMLElement *This = HTMLELEM_THIS(iface);
267     FIXME("(%p)->()\n", This);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
272 {
273     HTMLElement *This = HTMLELEM_THIS(iface);
274     FIXME("(%p)->(%p)\n", This, p);
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
279 {
280     HTMLElement *This = HTMLELEM_THIS(iface);
281     FIXME("(%p)->()\n", This);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
286 {
287     HTMLElement *This = HTMLELEM_THIS(iface);
288     FIXME("(%p)->(%p)\n", This, p);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
293 {
294     HTMLElement *This = HTMLELEM_THIS(iface);
295     FIXME("(%p)->()\n", This);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
300 {
301     HTMLElement *This = HTMLELEM_THIS(iface);
302     FIXME("(%p)->(%p)\n", This, p);
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
307 {
308     HTMLElement *This = HTMLELEM_THIS(iface);
309     FIXME("(%p)->()\n", This);
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
314 {
315     HTMLElement *This = HTMLELEM_THIS(iface);
316     FIXME("(%p)->(%p)\n", This, p);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
321 {
322     HTMLElement *This = HTMLELEM_THIS(iface);
323     FIXME("(%p)->()\n", This);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
328 {
329     HTMLElement *This = HTMLELEM_THIS(iface);
330     FIXME("(%p)->(%p)\n", This, p);
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
335 {
336     HTMLElement *This = HTMLELEM_THIS(iface);
337     FIXME("(%p)->()\n", This);
338     return E_NOTIMPL;
339 }
340
341 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
342 {
343     HTMLElement *This = HTMLELEM_THIS(iface);
344     FIXME("(%p)->(%p)\n", This, p);
345     return E_NOTIMPL;
346 }
347
348 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
349 {
350     HTMLElement *This = HTMLELEM_THIS(iface);
351     FIXME("(%p)->()\n", This);
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
356 {
357     HTMLElement *This = HTMLELEM_THIS(iface);
358     FIXME("(%p)->(%p)\n", This, p);
359     return E_NOTIMPL;
360 }
361
362 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
363 {
364     HTMLElement *This = HTMLELEM_THIS(iface);
365     FIXME("(%p)->()\n", This);
366     return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
370 {
371     HTMLElement *This = HTMLELEM_THIS(iface);
372     FIXME("(%p)->(%p)\n", This, p);
373     return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
377 {
378     HTMLElement *This = HTMLELEM_THIS(iface);
379     FIXME("(%p)->()\n", This);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
384 {
385     HTMLElement *This = HTMLELEM_THIS(iface);
386     FIXME("(%p)->(%p)\n", This, p);
387     return E_NOTIMPL;
388 }
389
390 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
391 {
392     HTMLElement *This = HTMLELEM_THIS(iface);
393     FIXME("(%p)->()\n", This);
394     return E_NOTIMPL;
395 }
396
397 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
398 {
399     HTMLElement *This = HTMLELEM_THIS(iface);
400     FIXME("(%p)->(%p)\n", This, p);
401     return E_NOTIMPL;
402 }
403
404 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
405 {
406     HTMLElement *This = HTMLELEM_THIS(iface);
407     FIXME("(%p)->(%p)\n", This, p);
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
412 {
413     HTMLElement *This = HTMLELEM_THIS(iface);
414     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
419 {
420     HTMLElement *This = HTMLELEM_THIS(iface);
421     FIXME("(%p)->(%p)\n", This, p);
422     return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
426 {
427     HTMLElement *This = HTMLELEM_THIS(iface);
428     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
429     return E_NOTIMPL;
430 }
431
432 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
433 {
434     HTMLElement *This = HTMLELEM_THIS(iface);
435     FIXME("(%p)->(%p)\n", This, p);
436     return E_NOTIMPL;
437 }
438
439 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
440 {
441     HTMLElement *This = HTMLELEM_THIS(iface);
442     FIXME("(%p)->()\n", This);
443     return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
447 {
448     HTMLElement *This = HTMLELEM_THIS(iface);
449     FIXME("(%p)->(%p)\n", This, p);
450     return E_NOTIMPL;
451 }
452
453 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
454 {
455     HTMLElement *This = HTMLELEM_THIS(iface);
456     FIXME("(%p)->()\n", This);
457     return E_NOTIMPL;
458 }
459
460 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
461                                            VARIANT_BOOL *pfResult)
462 {
463     HTMLElement *This = HTMLELEM_THIS(iface);
464     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
465     return E_NOTIMPL;
466 }
467
468 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, long *p)
469 {
470     HTMLElement *This = HTMLELEM_THIS(iface);
471     FIXME("(%p)->(%p)\n", This, p);
472     return E_NOTIMPL;
473 }
474
475 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
476 {
477     HTMLElement *This = HTMLELEM_THIS(iface);
478     FIXME("(%p)->(%p)\n", This, p);
479     return E_NOTIMPL;
480 }
481
482 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
483 {
484     HTMLElement *This = HTMLELEM_THIS(iface);
485     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
486     return E_NOTIMPL;
487 }
488
489 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
490 {
491     HTMLElement *This = HTMLELEM_THIS(iface);
492     FIXME("(%p)->(%p)\n", This, p);
493     return E_NOTIMPL;
494 }
495
496 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, long *p)
497 {
498     HTMLElement *This = HTMLELEM_THIS(iface);
499     FIXME("(%p)->(%p)\n", This, p);
500     return E_NOTIMPL;
501 }
502
503 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, long *p)
504 {
505     HTMLElement *This = HTMLELEM_THIS(iface);
506     FIXME("(%p)->(%p)\n", This, p);
507     return E_NOTIMPL;
508 }
509
510 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, long *p)
511 {
512     HTMLElement *This = HTMLELEM_THIS(iface);
513     FIXME("(%p)->(%p)\n", This, p);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, long *p)
518 {
519     HTMLElement *This = HTMLELEM_THIS(iface);
520     FIXME("(%p)->(%p)\n", This, p);
521     return E_NOTIMPL;
522 }
523
524 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
525 {
526     HTMLElement *This = HTMLELEM_THIS(iface);
527     FIXME("(%p)->(%p)\n", This, p);
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
532 {
533     HTMLElement *This = HTMLELEM_THIS(iface);
534     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
535     return E_NOTIMPL;
536 }
537
538 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
539 {
540     HTMLElement *This = HTMLELEM_THIS(iface);
541     FIXME("(%p)->(%p)\n", This, p);
542     return E_NOTIMPL;
543 }
544
545 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
546 {
547     HTMLElement *This = HTMLELEM_THIS(iface);
548     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
549     return E_NOTIMPL;
550 }
551
552 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
553 {
554     HTMLElement *This = HTMLELEM_THIS(iface);
555     FIXME("(%p)->(%p)\n", This, p);
556     return E_NOTIMPL;
557 }
558
559 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
560 {
561     HTMLElement *This = HTMLELEM_THIS(iface);
562     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
563     return E_NOTIMPL;
564 }
565
566 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
567 {
568     HTMLElement *This = HTMLELEM_THIS(iface);
569     FIXME("(%p)->(%p)\n", This, p);
570     return E_NOTIMPL;
571 }
572
573 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
574 {
575     HTMLElement *This = HTMLELEM_THIS(iface);
576     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
577     return E_NOTIMPL;
578 }
579
580 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
581 {
582     HTMLElement *This = HTMLELEM_THIS(iface);
583     FIXME("(%p)->(%p)\n", This, p);
584     return E_NOTIMPL;
585 }
586
587 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
588                                                      BSTR html)
589 {
590     HTMLElement *This = HTMLELEM_THIS(iface);
591     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
592     return E_NOTIMPL;
593 }
594
595 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
596                                                      BSTR text)
597 {
598     HTMLElement *This = HTMLELEM_THIS(iface);
599     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
600     return E_NOTIMPL;
601 }
602
603 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
604 {
605     HTMLElement *This = HTMLELEM_THIS(iface);
606     FIXME("(%p)->(%p)\n", This, p);
607     return E_NOTIMPL;
608 }
609
610 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
611 {
612     HTMLElement *This = HTMLELEM_THIS(iface);
613     FIXME("(%p)->(%p)\n", This, p);
614     return E_NOTIMPL;
615 }
616
617 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
618 {
619     HTMLElement *This = HTMLELEM_THIS(iface);
620     FIXME("(%p)\n", This);
621     return E_NOTIMPL;
622 }
623
624 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
625                                               IHTMLFiltersCollection **p)
626 {
627     HTMLElement *This = HTMLELEM_THIS(iface);
628     FIXME("(%p)->(%p)\n", This, p);
629     return E_NOTIMPL;
630 }
631
632 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
633 {
634     HTMLElement *This = HTMLELEM_THIS(iface);
635     FIXME("(%p)->()\n", This);
636     return E_NOTIMPL;
637 }
638
639 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
640 {
641     HTMLElement *This = HTMLELEM_THIS(iface);
642     FIXME("(%p)->(%p)\n", This, p);
643     return E_NOTIMPL;
644 }
645
646 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
647 {
648     HTMLElement *This = HTMLELEM_THIS(iface);
649     FIXME("(%p)->(%p)\n", This, String);
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
654 {
655     HTMLElement *This = HTMLELEM_THIS(iface);
656     FIXME("(%p)->()\n", This);
657     return E_NOTIMPL;
658 }
659
660 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
661 {
662     HTMLElement *This = HTMLELEM_THIS(iface);
663     FIXME("(%p)->(%p)\n", This, p);
664     return E_NOTIMPL;
665 }
666
667 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
668 {
669     HTMLElement *This = HTMLELEM_THIS(iface);
670     FIXME("(%p)->()\n", This);
671     return E_NOTIMPL;
672 }
673
674 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
675 {
676     HTMLElement *This = HTMLELEM_THIS(iface);
677     FIXME("(%p)->(%p)\n", This, p);
678     return E_NOTIMPL;
679 }
680
681 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
682 {
683     HTMLElement *This = HTMLELEM_THIS(iface);
684     FIXME("(%p)->()\n", This);
685     return E_NOTIMPL;
686 }
687
688 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
689 {
690     HTMLElement *This = HTMLELEM_THIS(iface);
691     FIXME("(%p)->(%p)\n", This, p);
692     return E_NOTIMPL;
693 }
694
695 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
696 {
697     HTMLElement *This = HTMLELEM_THIS(iface);
698     FIXME("(%p)->()\n", This);
699     return E_NOTIMPL;
700 }
701
702 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
703 {
704     HTMLElement *This = HTMLELEM_THIS(iface);
705     FIXME("(%p)->(%p)\n", This, p);
706     return E_NOTIMPL;
707 }
708
709 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
710 {
711     HTMLElement *This = HTMLELEM_THIS(iface);
712     FIXME("(%p)->()\n", This);
713     return E_NOTIMPL;
714 }
715
716 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
717 {
718     HTMLElement *This = HTMLELEM_THIS(iface);
719     FIXME("(%p)->(%p)\n", This, p);
720     return E_NOTIMPL;
721 }
722
723 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
724 {
725     HTMLElement *This = HTMLELEM_THIS(iface);
726     FIXME("(%p)->()\n", This);
727     return E_NOTIMPL;
728 }
729
730 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
731 {
732     HTMLElement *This = HTMLELEM_THIS(iface);
733     FIXME("(%p)->(%p)\n", This, p);
734     return E_NOTIMPL;
735 }
736
737 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
738 {
739     HTMLElement *This = HTMLELEM_THIS(iface);
740     FIXME("(%p)->()\n", This);
741     return E_NOTIMPL;
742 }
743
744 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
745 {
746     HTMLElement *This = HTMLELEM_THIS(iface);
747     FIXME("(%p)->(%p)\n", This, p);
748     return E_NOTIMPL;
749 }
750
751 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
752 {
753     HTMLElement *This = HTMLELEM_THIS(iface);
754     FIXME("(%p)->()\n", This);
755     return E_NOTIMPL;
756 }
757
758 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
759 {
760     HTMLElement *This = HTMLELEM_THIS(iface);
761     FIXME("(%p)->(%p)\n", This, p);
762     return E_NOTIMPL;
763 }
764
765 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
766 {
767     HTMLElement *This = HTMLELEM_THIS(iface);
768     FIXME("(%p)->()\n", This);
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
773 {
774     HTMLElement *This = HTMLELEM_THIS(iface);
775     FIXME("(%p)->(%p)\n", This, p);
776     return E_NOTIMPL;
777 }
778
779 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
780 {
781     HTMLElement *This = HTMLELEM_THIS(iface);
782     FIXME("(%p)->(%p)\n", This, p);
783     return E_NOTIMPL;
784 }
785
786 static void create_all_list(HTMLDocument *doc, HTMLElement *elem, elem_vector *buf)
787 {
788     nsIDOMNodeList *nsnode_list;
789     nsIDOMNode *iter;
790     PRUint32 list_len = 0, i;
791     HTMLDOMNode *node;
792     nsresult nsres;
793
794     nsres = nsIDOMNode_GetChildNodes(elem->node->nsnode, &nsnode_list);
795     if(NS_FAILED(nsres)) {
796         ERR("GetChildNodes failed: %08x\n", nsres);
797         return;
798     }
799
800     nsIDOMNodeList_GetLength(nsnode_list, &list_len);
801     if(!list_len)
802         return;
803
804     for(i=0; i<list_len; i++) {
805         nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
806         if(NS_FAILED(nsres)) {
807             ERR("Item failed: %08x\n", nsres);
808             continue;
809         }
810
811         node = get_node(doc, iter);
812         if(node->node_type != NT_HTMLELEM)
813             continue;
814
815         elem_vector_add(buf, (HTMLElement*)node->impl.elem);
816         create_all_list(doc, (HTMLElement*)node->impl.elem, buf);
817     }
818 }
819
820 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
821 {
822     HTMLElement *This = HTMLELEM_THIS(iface);
823     elem_vector buf = {NULL, 0, 8};
824
825     TRACE("(%p)->(%p)\n", This, p);
826
827     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement**));
828
829     create_all_list(This->node->doc, This, &buf);
830
831     if(!buf.len) {
832         mshtml_free(buf.buf);
833         buf.buf = NULL;
834     }else if(buf.size > buf.len) {
835         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement**));
836     }
837
838     return HTMLElementCollection_Create((IUnknown*)HTMLELEM(This), buf.buf, buf.len, p);
839 }
840
841 static void HTMLElement_destructor(IUnknown *iface)
842 {
843     HTMLElement *This = HTMLELEM_THIS(iface);
844
845     if(This->destructor)
846         This->destructor(This->impl);
847
848     if(This->nselem)
849         nsIDOMHTMLElement_Release(This->nselem);
850
851     mshtml_free(This);
852 }
853
854 #undef HTMLELEM_THIS
855
856 static const IHTMLElementVtbl HTMLElementVtbl = {
857     HTMLElement_QueryInterface,
858     HTMLElement_AddRef,
859     HTMLElement_Release,
860     HTMLElement_GetTypeInfoCount,
861     HTMLElement_GetTypeInfo,
862     HTMLElement_GetIDsOfNames,
863     HTMLElement_Invoke,
864     HTMLElement_setAttribute,
865     HTMLElement_getAttribute,
866     HTMLElement_removeAttribute,
867     HTMLElement_put_className,
868     HTMLElement_get_className,
869     HTMLElement_put_id,
870     HTMLElement_get_id,
871     HTMLElement_get_tagName,
872     HTMLElement_get_parentElement,
873     HTMLElement_get_style,
874     HTMLElement_put_onhelp,
875     HTMLElement_get_onhelp,
876     HTMLElement_put_onclick,
877     HTMLElement_get_onclick,
878     HTMLElement_put_ondblclick,
879     HTMLElement_get_ondblclick,
880     HTMLElement_put_onkeydown,
881     HTMLElement_get_onkeydown,
882     HTMLElement_put_onkeyup,
883     HTMLElement_get_onkeyup,
884     HTMLElement_put_onkeypress,
885     HTMLElement_get_onkeypress,
886     HTMLElement_put_onmouseout,
887     HTMLElement_get_onmouseout,
888     HTMLElement_put_onmouseover,
889     HTMLElement_get_onmouseover,
890     HTMLElement_put_onmousemove,
891     HTMLElement_get_onmousemove,
892     HTMLElement_put_onmousedown,
893     HTMLElement_get_onmousedown,
894     HTMLElement_put_onmouseup,
895     HTMLElement_get_onmouseup,
896     HTMLElement_get_document,
897     HTMLElement_put_title,
898     HTMLElement_get_title,
899     HTMLElement_put_language,
900     HTMLElement_get_language,
901     HTMLElement_put_onselectstart,
902     HTMLElement_get_onselectstart,
903     HTMLElement_scrollIntoView,
904     HTMLElement_contains,
905     HTMLElement_get_sourceIndex,
906     HTMLElement_get_recordNumber,
907     HTMLElement_put_lang,
908     HTMLElement_get_lang,
909     HTMLElement_get_offsetLeft,
910     HTMLElement_get_offsetTop,
911     HTMLElement_get_offsetWidth,
912     HTMLElement_get_offsetHeight,
913     HTMLElement_get_offsetParent,
914     HTMLElement_put_innerHTML,
915     HTMLElement_get_innerHTML,
916     HTMLElement_put_innerText,
917     HTMLElement_get_innerText,
918     HTMLElement_put_outerHTML,
919     HTMLElement_get_outerHTML,
920     HTMLElement_put_outerText,
921     HTMLElement_get_outerText,
922     HTMLElement_insertAdjacentHTML,
923     HTMLElement_insertAdjacentText,
924     HTMLElement_get_parentTextEdit,
925     HTMLElement_get_isTextEdit,
926     HTMLElement_click,
927     HTMLElement_get_filters,
928     HTMLElement_put_ondragstart,
929     HTMLElement_get_ondragstart,
930     HTMLElement_toString,
931     HTMLElement_put_onbeforeupdate,
932     HTMLElement_get_onbeforeupdate,
933     HTMLElement_put_onafterupdate,
934     HTMLElement_get_onafterupdate,
935     HTMLElement_put_onerrorupdate,
936     HTMLElement_get_onerrorupdate,
937     HTMLElement_put_onrowexit,
938     HTMLElement_get_onrowexit,
939     HTMLElement_put_onrowenter,
940     HTMLElement_get_onrowenter,
941     HTMLElement_put_ondatasetchanged,
942     HTMLElement_get_ondatasetchanged,
943     HTMLElement_put_ondataavailable,
944     HTMLElement_get_ondataavailable,
945     HTMLElement_put_ondatasetcomplete,
946     HTMLElement_get_ondatasetcomplete,
947     HTMLElement_put_onfilterchange,
948     HTMLElement_get_onfilterchange,
949     HTMLElement_get_children,
950     HTMLElement_get_all
951 };
952
953 HRESULT HTMLElement_QI(HTMLElement *This, REFIID riid, void **ppv)
954 {
955     *ppv =  NULL;
956
957     if(IsEqualGUID(&IID_IUnknown, riid)) {
958         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
959         *ppv = HTMLELEM(This);
960     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
961         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
962         *ppv = HTMLELEM(This);
963     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
964         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
965         *ppv = HTMLELEM(This);
966     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
967         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
968         *ppv = HTMLELEM2(This);
969     }
970
971     if(*ppv) {
972         IHTMLElement_AddRef(HTMLELEM(This));
973         return S_OK;
974     }
975
976     return HTMLDOMNode_QI(This->node, riid, ppv);
977 }
978
979 void HTMLElement_Create(HTMLDOMNode *node)
980 {
981     HTMLElement *ret;
982     nsAString class_name_str;
983     const PRUnichar *class_name;
984     nsresult nsres;
985
986     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
987     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
988     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
989     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
990
991     ret = mshtml_alloc(sizeof(HTMLElement));
992     ret->lpHTMLElementVtbl = &HTMLElementVtbl;
993     ret->node = node;
994     ret->impl = NULL;
995     ret->destructor = NULL;
996
997     node->node_type = NT_HTMLELEM;
998     node->impl.elem = HTMLELEM(ret);
999     node->destructor = HTMLElement_destructor;
1000
1001     HTMLElement2_Init(ret);
1002
1003     nsres = nsIDOMNode_QueryInterface(node->nsnode, &IID_nsIDOMHTMLElement, (void**)&ret->nselem);
1004     if(NS_FAILED(nsres))
1005         return;
1006
1007     nsAString_Init(&class_name_str, NULL);
1008     nsIDOMHTMLElement_GetTagName(ret->nselem, &class_name_str);
1009
1010     nsAString_GetData(&class_name_str, &class_name, NULL);
1011
1012     if(!strcmpW(class_name, wszBODY))
1013         HTMLBodyElement_Create(ret);
1014     else if(!strcmpW(class_name, wszINPUT))
1015         HTMLInputElement_Create(ret);
1016     else if(!strcmpW(class_name, wszSELECT))
1017         HTMLSelectElement_Create(ret);
1018     else if(!strcmpW(class_name, wszTEXTAREA))
1019         HTMLTextAreaElement_Create(ret);
1020
1021     nsAString_Finish(&class_name_str);
1022 }
1023
1024 typedef struct {
1025     const IHTMLElementCollectionVtbl *lpHTMLElementCollectionVtbl;
1026
1027     IUnknown *ref_unk;
1028     HTMLElement **elems;
1029     DWORD len;
1030
1031     LONG ref;
1032 } HTMLElementCollection;
1033
1034 #define HTMLELEMCOL(x)  ((IHTMLElementCollection*) &(x)->lpHTMLElementCollectionVtbl)
1035
1036 #define ELEMCOL_THIS(iface) DEFINE_THIS(HTMLElementCollection, HTMLElementCollection, iface)
1037
1038 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
1039                                                            REFIID riid, void **ppv)
1040 {
1041     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1042
1043     *ppv = NULL;
1044
1045     if(IsEqualGUID(&IID_IUnknown, riid)) {
1046         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1047         *ppv = HTMLELEMCOL(This);
1048     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1049         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1050         *ppv = HTMLELEMCOL(This);
1051     }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
1052         TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
1053         *ppv = HTMLELEMCOL(This);
1054     }
1055
1056     if(*ppv) {
1057         IHTMLElementCollection_AddRef(HTMLELEMCOL(This));
1058         return S_OK;
1059     }
1060
1061     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1062     return E_NOINTERFACE;
1063 }
1064
1065 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
1066 {
1067     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1068     LONG ref = InterlockedIncrement(&This->ref);
1069
1070     TRACE("(%p) ref=%d\n", This, ref);
1071
1072     return ref;
1073 }
1074
1075 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
1076 {
1077     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1078     LONG ref = InterlockedDecrement(&This->ref);
1079
1080     TRACE("(%p) ref=%d\n", This, ref);
1081
1082     if(!ref) {
1083         IUnknown_Release(This->ref_unk);
1084         mshtml_free(This->elems);
1085         mshtml_free(This);
1086     }
1087
1088     return ref;
1089 }
1090
1091 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
1092                                                              UINT *pctinfo)
1093 {
1094     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1095     FIXME("(%p)->(%p)\n", This, pctinfo);
1096     return E_NOTIMPL;
1097 }
1098
1099 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
1100         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1101 {
1102     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1103     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1104     return E_NOTIMPL;
1105 }
1106
1107 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
1108         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1109 {
1110     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1111     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1112                                         lcid, rgDispId);
1113     return E_NOTIMPL;
1114 }
1115
1116 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
1117         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1118         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1119 {
1120     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1121     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1122             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1123     return E_NOTIMPL;
1124 }
1125
1126 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
1127                                                      BSTR *String)
1128 {
1129     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1130     FIXME("(%p)->(%p)\n", This, String);
1131     return E_NOTIMPL;
1132 }
1133
1134 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
1135                                                        long v)
1136 {
1137     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1138     FIXME("(%p)->(%ld)\n", This, v);
1139     return E_NOTIMPL;
1140 }
1141
1142 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
1143                                                        long *p)
1144 {
1145     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1146
1147     TRACE("(%p)->(%p)\n", This, p);
1148
1149     *p = This->len;
1150     return S_OK;
1151 }
1152
1153 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
1154                                                          IUnknown **p)
1155 {
1156     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1157     FIXME("(%p)->(%p)\n", This, p);
1158     return E_NOTIMPL;
1159 }
1160
1161 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
1162         VARIANT name, VARIANT index, IDispatch **pdisp)
1163 {
1164     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1165
1166     if(V_VT(&index) != VT_I4) {
1167         WARN("Invalid index vt=%d\n", V_VT(&index));
1168         return E_INVALIDARG;
1169     }
1170
1171     if(V_VT(&name) != VT_I4 || V_I4(&name) != V_I4(&index))
1172         FIXME("Unsupproted name vt=%d\n", V_VT(&name));
1173
1174     TRACE("(%p)->(%d %d %p)\n", This, V_I4(&name), V_I4(&index), pdisp);
1175
1176     if(V_I4(&index) < 0 || V_I4(&index) >= This->len)
1177         return E_INVALIDARG;
1178
1179     *pdisp = (IDispatch*)This->elems[V_I4(&index)];
1180     IDispatch_AddRef(*pdisp);
1181     return S_OK;
1182 }
1183
1184 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
1185                                                  VARIANT tagName, IDispatch **pdisp)
1186 {
1187     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1188     DWORD i;
1189     nsAString tag_str;
1190     const PRUnichar *tag;
1191     elem_vector buf = {NULL, 0, 8};
1192
1193     if(V_VT(&tagName) != VT_BSTR) {
1194         WARN("Invalid arg\n");
1195         return DISP_E_MEMBERNOTFOUND;
1196     }
1197
1198     TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
1199
1200     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1201
1202     nsAString_Init(&tag_str, NULL);
1203
1204     for(i=0; i<This->len; i++) {
1205         if(!This->elems[i]->nselem)
1206             continue;
1207
1208         nsIDOMElement_GetTagName(This->elems[i]->nselem, &tag_str);
1209         nsAString_GetData(&tag_str, &tag, NULL);
1210
1211         if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1212                           V_BSTR(&tagName), -1) == CSTR_EQUAL)
1213             elem_vector_add(&buf, This->elems[i]);
1214     }
1215
1216     nsAString_Finish(&tag_str);
1217
1218     TRACE("fount %d tags\n", buf.len);
1219
1220     if(!buf.len) {
1221         mshtml_free(buf.buf);
1222         buf.buf = NULL;
1223     }else if(buf.size > buf.len) {
1224         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1225     }
1226
1227     return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1228 }
1229
1230 #undef ELEMCOL_THIS
1231
1232 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
1233     HTMLElementCollection_QueryInterface,
1234     HTMLElementCollection_AddRef,
1235     HTMLElementCollection_Release,
1236     HTMLElementCollection_GetTypeInfoCount,
1237     HTMLElementCollection_GetTypeInfo,
1238     HTMLElementCollection_GetIDsOfNames,
1239     HTMLElementCollection_Invoke,
1240     HTMLElementCollection_toString,
1241     HTMLElementCollection_put_length,
1242     HTMLElementCollection_get_length,
1243     HTMLElementCollection_get__newEnum,
1244     HTMLElementCollection_item,
1245     HTMLElementCollection_tags
1246 };
1247
1248 static HRESULT HTMLElementCollection_Create(IUnknown *ref_unk, HTMLElement **elems, DWORD len,
1249                                             IDispatch **p)
1250 {
1251     HTMLElementCollection *ret = mshtml_alloc(sizeof(HTMLElementCollection));
1252
1253     ret->lpHTMLElementCollectionVtbl = &HTMLElementCollectionVtbl;
1254     ret->ref = 1;
1255     ret->elems = elems;
1256     ret->len = len;
1257
1258     IUnknown_AddRef(ref_unk);
1259     ret->ref_unk = ref_unk;
1260
1261     TRACE("ret=%p len=%d\n", ret, len);
1262
1263     *p = (IDispatch*)ret;
1264     return S_OK;
1265 }