wined3d: alphaop fixes for color keying.
[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     nsIDOMElementCSSInlineStyle *nselemstyle;
247     nsIDOMCSSStyleDeclaration *nsstyle;
248     nsresult nsres;
249
250     TRACE("(%p)->(%p)\n", This, p);
251
252     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMElementCSSInlineStyle,
253                                              (void**)&nselemstyle);
254     if(NS_FAILED(nsres)) {
255         ERR("Coud not get nsIDOMCSSStyleDeclaration interface: %08x\n", nsres);
256         return E_FAIL;
257     }
258
259     nsres = nsIDOMElementCSSInlineStyle_GetStyle(nselemstyle, &nsstyle);
260     nsIDOMElementCSSInlineStyle_Release(nselemstyle);
261     if(NS_FAILED(nsres)) {
262         ERR("GetStyle failed: %08x\n", nsres);
263         return E_FAIL;
264     }
265
266     /* FIXME: Store style instead of creating a new instance in each call */
267     *p = HTMLStyle_Create(nsstyle);
268
269     nsIDOMCSSStyleDeclaration_Release(nsstyle);
270     return S_OK;
271 }
272
273 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
274 {
275     HTMLElement *This = HTMLELEM_THIS(iface);
276     FIXME("(%p)->()\n", This);
277     return E_NOTIMPL;
278 }
279
280 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
281 {
282     HTMLElement *This = HTMLELEM_THIS(iface);
283     FIXME("(%p)->(%p)\n", This, p);
284     return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
288 {
289     HTMLElement *This = HTMLELEM_THIS(iface);
290     FIXME("(%p)->()\n", This);
291     return E_NOTIMPL;
292 }
293
294 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
295 {
296     HTMLElement *This = HTMLELEM_THIS(iface);
297     FIXME("(%p)->(%p)\n", This, p);
298     return E_NOTIMPL;
299 }
300
301 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
302 {
303     HTMLElement *This = HTMLELEM_THIS(iface);
304     FIXME("(%p)->()\n", This);
305     return E_NOTIMPL;
306 }
307
308 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
309 {
310     HTMLElement *This = HTMLELEM_THIS(iface);
311     FIXME("(%p)->(%p)\n", This, p);
312     return E_NOTIMPL;
313 }
314
315 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
316 {
317     HTMLElement *This = HTMLELEM_THIS(iface);
318     FIXME("(%p)->()\n", This);
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
323 {
324     HTMLElement *This = HTMLELEM_THIS(iface);
325     FIXME("(%p)->(%p)\n", This, p);
326     return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
330 {
331     HTMLElement *This = HTMLELEM_THIS(iface);
332     FIXME("(%p)->()\n", This);
333     return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
337 {
338     HTMLElement *This = HTMLELEM_THIS(iface);
339     FIXME("(%p)->(%p)\n", This, p);
340     return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
344 {
345     HTMLElement *This = HTMLELEM_THIS(iface);
346     FIXME("(%p)->()\n", This);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
351 {
352     HTMLElement *This = HTMLELEM_THIS(iface);
353     FIXME("(%p)->(%p)\n", This, p);
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
358 {
359     HTMLElement *This = HTMLELEM_THIS(iface);
360     FIXME("(%p)->()\n", This);
361     return E_NOTIMPL;
362 }
363
364 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
365 {
366     HTMLElement *This = HTMLELEM_THIS(iface);
367     FIXME("(%p)->(%p)\n", This, p);
368     return E_NOTIMPL;
369 }
370
371 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
372 {
373     HTMLElement *This = HTMLELEM_THIS(iface);
374     FIXME("(%p)->()\n", This);
375     return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
379 {
380     HTMLElement *This = HTMLELEM_THIS(iface);
381     FIXME("(%p)->(%p)\n", This, p);
382     return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
386 {
387     HTMLElement *This = HTMLELEM_THIS(iface);
388     FIXME("(%p)->()\n", This);
389     return E_NOTIMPL;
390 }
391
392 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
393 {
394     HTMLElement *This = HTMLELEM_THIS(iface);
395     FIXME("(%p)->(%p)\n", This, p);
396     return E_NOTIMPL;
397 }
398
399 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
400 {
401     HTMLElement *This = HTMLELEM_THIS(iface);
402     FIXME("(%p)->()\n", This);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
407 {
408     HTMLElement *This = HTMLELEM_THIS(iface);
409     FIXME("(%p)->(%p)\n", This, p);
410     return E_NOTIMPL;
411 }
412
413 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
414 {
415     HTMLElement *This = HTMLELEM_THIS(iface);
416     FIXME("(%p)->()\n", This);
417     return E_NOTIMPL;
418 }
419
420 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
421 {
422     HTMLElement *This = HTMLELEM_THIS(iface);
423     FIXME("(%p)->(%p)\n", This, p);
424     return E_NOTIMPL;
425 }
426
427 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
428 {
429     HTMLElement *This = HTMLELEM_THIS(iface);
430     FIXME("(%p)->(%p)\n", This, p);
431     return E_NOTIMPL;
432 }
433
434 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
435 {
436     HTMLElement *This = HTMLELEM_THIS(iface);
437     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
438     return E_NOTIMPL;
439 }
440
441 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
442 {
443     HTMLElement *This = HTMLELEM_THIS(iface);
444     FIXME("(%p)->(%p)\n", This, p);
445     return E_NOTIMPL;
446 }
447
448 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
449 {
450     HTMLElement *This = HTMLELEM_THIS(iface);
451     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
452     return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
456 {
457     HTMLElement *This = HTMLELEM_THIS(iface);
458     FIXME("(%p)->(%p)\n", This, p);
459     return E_NOTIMPL;
460 }
461
462 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
463 {
464     HTMLElement *This = HTMLELEM_THIS(iface);
465     FIXME("(%p)->()\n", This);
466     return E_NOTIMPL;
467 }
468
469 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
470 {
471     HTMLElement *This = HTMLELEM_THIS(iface);
472     FIXME("(%p)->(%p)\n", This, p);
473     return E_NOTIMPL;
474 }
475
476 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
477 {
478     HTMLElement *This = HTMLELEM_THIS(iface);
479     FIXME("(%p)->()\n", This);
480     return E_NOTIMPL;
481 }
482
483 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
484                                            VARIANT_BOOL *pfResult)
485 {
486     HTMLElement *This = HTMLELEM_THIS(iface);
487     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, long *p)
492 {
493     HTMLElement *This = HTMLELEM_THIS(iface);
494     FIXME("(%p)->(%p)\n", This, p);
495     return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
499 {
500     HTMLElement *This = HTMLELEM_THIS(iface);
501     FIXME("(%p)->(%p)\n", This, p);
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
506 {
507     HTMLElement *This = HTMLELEM_THIS(iface);
508     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
509     return E_NOTIMPL;
510 }
511
512 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
513 {
514     HTMLElement *This = HTMLELEM_THIS(iface);
515     FIXME("(%p)->(%p)\n", This, p);
516     return E_NOTIMPL;
517 }
518
519 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, long *p)
520 {
521     HTMLElement *This = HTMLELEM_THIS(iface);
522     FIXME("(%p)->(%p)\n", This, p);
523     return E_NOTIMPL;
524 }
525
526 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, long *p)
527 {
528     HTMLElement *This = HTMLELEM_THIS(iface);
529     FIXME("(%p)->(%p)\n", This, p);
530     return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, long *p)
534 {
535     HTMLElement *This = HTMLELEM_THIS(iface);
536     FIXME("(%p)->(%p)\n", This, p);
537     return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, long *p)
541 {
542     HTMLElement *This = HTMLELEM_THIS(iface);
543     FIXME("(%p)->(%p)\n", This, p);
544     return E_NOTIMPL;
545 }
546
547 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
548 {
549     HTMLElement *This = HTMLELEM_THIS(iface);
550     FIXME("(%p)->(%p)\n", This, p);
551     return E_NOTIMPL;
552 }
553
554 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
555 {
556     HTMLElement *This = HTMLELEM_THIS(iface);
557     nsIDOMNSHTMLElement *nselem;
558     nsAString html_str;
559     nsresult nsres;
560
561     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
562
563     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
564     if(NS_FAILED(nsres)) {
565         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
566         return E_FAIL;
567     }
568
569     nsAString_Init(&html_str, v);
570     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
571     nsAString_Finish(&html_str);
572
573     if(NS_FAILED(nsres)) {
574         FIXME("SetInnerHtml failed %08x\n", nsres);
575         return E_FAIL;
576     }
577
578     return S_OK;
579 }
580
581 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
582 {
583     HTMLElement *This = HTMLELEM_THIS(iface);
584     FIXME("(%p)->(%p)\n", This, p);
585     return E_NOTIMPL;
586 }
587
588 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
589 {
590     HTMLElement *This = HTMLELEM_THIS(iface);
591     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
592     return E_NOTIMPL;
593 }
594
595 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
596 {
597     HTMLElement *This = HTMLELEM_THIS(iface);
598     FIXME("(%p)->(%p)\n", This, p);
599     return E_NOTIMPL;
600 }
601
602 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
603 {
604     HTMLElement *This = HTMLELEM_THIS(iface);
605     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
606     return E_NOTIMPL;
607 }
608
609 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
610 {
611     HTMLElement *This = HTMLELEM_THIS(iface);
612     FIXME("(%p)->(%p)\n", This, p);
613     return E_NOTIMPL;
614 }
615
616 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
617 {
618     HTMLElement *This = HTMLELEM_THIS(iface);
619     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
620     return E_NOTIMPL;
621 }
622
623 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
624 {
625     HTMLElement *This = HTMLELEM_THIS(iface);
626     FIXME("(%p)->(%p)\n", This, p);
627     return E_NOTIMPL;
628 }
629
630 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
631                                                      BSTR html)
632 {
633     HTMLElement *This = HTMLELEM_THIS(iface);
634     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
635     return E_NOTIMPL;
636 }
637
638 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
639                                                      BSTR text)
640 {
641     HTMLElement *This = HTMLELEM_THIS(iface);
642     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
643     return E_NOTIMPL;
644 }
645
646 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
647 {
648     HTMLElement *This = HTMLELEM_THIS(iface);
649     FIXME("(%p)->(%p)\n", This, p);
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
654 {
655     HTMLElement *This = HTMLELEM_THIS(iface);
656     FIXME("(%p)->(%p)\n", This, p);
657     return E_NOTIMPL;
658 }
659
660 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
661 {
662     HTMLElement *This = HTMLELEM_THIS(iface);
663     FIXME("(%p)\n", This);
664     return E_NOTIMPL;
665 }
666
667 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
668                                               IHTMLFiltersCollection **p)
669 {
670     HTMLElement *This = HTMLELEM_THIS(iface);
671     FIXME("(%p)->(%p)\n", This, p);
672     return E_NOTIMPL;
673 }
674
675 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
676 {
677     HTMLElement *This = HTMLELEM_THIS(iface);
678     FIXME("(%p)->()\n", This);
679     return E_NOTIMPL;
680 }
681
682 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
683 {
684     HTMLElement *This = HTMLELEM_THIS(iface);
685     FIXME("(%p)->(%p)\n", This, p);
686     return E_NOTIMPL;
687 }
688
689 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
690 {
691     HTMLElement *This = HTMLELEM_THIS(iface);
692     FIXME("(%p)->(%p)\n", This, String);
693     return E_NOTIMPL;
694 }
695
696 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
697 {
698     HTMLElement *This = HTMLELEM_THIS(iface);
699     FIXME("(%p)->()\n", This);
700     return E_NOTIMPL;
701 }
702
703 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
704 {
705     HTMLElement *This = HTMLELEM_THIS(iface);
706     FIXME("(%p)->(%p)\n", This, p);
707     return E_NOTIMPL;
708 }
709
710 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
711 {
712     HTMLElement *This = HTMLELEM_THIS(iface);
713     FIXME("(%p)->()\n", This);
714     return E_NOTIMPL;
715 }
716
717 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
718 {
719     HTMLElement *This = HTMLELEM_THIS(iface);
720     FIXME("(%p)->(%p)\n", This, p);
721     return E_NOTIMPL;
722 }
723
724 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
725 {
726     HTMLElement *This = HTMLELEM_THIS(iface);
727     FIXME("(%p)->()\n", This);
728     return E_NOTIMPL;
729 }
730
731 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
732 {
733     HTMLElement *This = HTMLELEM_THIS(iface);
734     FIXME("(%p)->(%p)\n", This, p);
735     return E_NOTIMPL;
736 }
737
738 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
739 {
740     HTMLElement *This = HTMLELEM_THIS(iface);
741     FIXME("(%p)->()\n", This);
742     return E_NOTIMPL;
743 }
744
745 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
746 {
747     HTMLElement *This = HTMLELEM_THIS(iface);
748     FIXME("(%p)->(%p)\n", This, p);
749     return E_NOTIMPL;
750 }
751
752 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
753 {
754     HTMLElement *This = HTMLELEM_THIS(iface);
755     FIXME("(%p)->()\n", This);
756     return E_NOTIMPL;
757 }
758
759 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
760 {
761     HTMLElement *This = HTMLELEM_THIS(iface);
762     FIXME("(%p)->(%p)\n", This, p);
763     return E_NOTIMPL;
764 }
765
766 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
767 {
768     HTMLElement *This = HTMLELEM_THIS(iface);
769     FIXME("(%p)->()\n", This);
770     return E_NOTIMPL;
771 }
772
773 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
774 {
775     HTMLElement *This = HTMLELEM_THIS(iface);
776     FIXME("(%p)->(%p)\n", This, p);
777     return E_NOTIMPL;
778 }
779
780 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
781 {
782     HTMLElement *This = HTMLELEM_THIS(iface);
783     FIXME("(%p)->()\n", This);
784     return E_NOTIMPL;
785 }
786
787 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
788 {
789     HTMLElement *This = HTMLELEM_THIS(iface);
790     FIXME("(%p)->(%p)\n", This, p);
791     return E_NOTIMPL;
792 }
793
794 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
795 {
796     HTMLElement *This = HTMLELEM_THIS(iface);
797     FIXME("(%p)->()\n", This);
798     return E_NOTIMPL;
799 }
800
801 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
802 {
803     HTMLElement *This = HTMLELEM_THIS(iface);
804     FIXME("(%p)->(%p)\n", This, p);
805     return E_NOTIMPL;
806 }
807
808 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
809 {
810     HTMLElement *This = HTMLELEM_THIS(iface);
811     FIXME("(%p)->()\n", This);
812     return E_NOTIMPL;
813 }
814
815 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
816 {
817     HTMLElement *This = HTMLELEM_THIS(iface);
818     FIXME("(%p)->(%p)\n", This, p);
819     return E_NOTIMPL;
820 }
821
822 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
823 {
824     HTMLElement *This = HTMLELEM_THIS(iface);
825     FIXME("(%p)->(%p)\n", This, p);
826     return E_NOTIMPL;
827 }
828
829 static void create_all_list(HTMLDocument *doc, HTMLElement *elem, elem_vector *buf)
830 {
831     nsIDOMNodeList *nsnode_list;
832     nsIDOMNode *iter;
833     PRUint32 list_len = 0, i;
834     HTMLDOMNode *node;
835     nsresult nsres;
836
837     nsres = nsIDOMNode_GetChildNodes(elem->node->nsnode, &nsnode_list);
838     if(NS_FAILED(nsres)) {
839         ERR("GetChildNodes failed: %08x\n", nsres);
840         return;
841     }
842
843     nsIDOMNodeList_GetLength(nsnode_list, &list_len);
844     if(!list_len)
845         return;
846
847     for(i=0; i<list_len; i++) {
848         nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
849         if(NS_FAILED(nsres)) {
850             ERR("Item failed: %08x\n", nsres);
851             continue;
852         }
853
854         node = get_node(doc, iter);
855         if(node->node_type != NT_HTMLELEM)
856             continue;
857
858         elem_vector_add(buf, (HTMLElement*)node->impl.elem);
859         create_all_list(doc, (HTMLElement*)node->impl.elem, buf);
860     }
861 }
862
863 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
864 {
865     HTMLElement *This = HTMLELEM_THIS(iface);
866     elem_vector buf = {NULL, 0, 8};
867
868     TRACE("(%p)->(%p)\n", This, p);
869
870     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement**));
871
872     create_all_list(This->node->doc, This, &buf);
873
874     if(!buf.len) {
875         mshtml_free(buf.buf);
876         buf.buf = NULL;
877     }else if(buf.size > buf.len) {
878         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement**));
879     }
880
881     return HTMLElementCollection_Create((IUnknown*)HTMLELEM(This), buf.buf, buf.len, p);
882 }
883
884 static void HTMLElement_destructor(IUnknown *iface)
885 {
886     HTMLElement *This = HTMLELEM_THIS(iface);
887
888     if(This->destructor)
889         This->destructor(This->impl);
890
891     if(This->nselem)
892         nsIDOMHTMLElement_Release(This->nselem);
893
894     mshtml_free(This);
895 }
896
897 #undef HTMLELEM_THIS
898
899 static const IHTMLElementVtbl HTMLElementVtbl = {
900     HTMLElement_QueryInterface,
901     HTMLElement_AddRef,
902     HTMLElement_Release,
903     HTMLElement_GetTypeInfoCount,
904     HTMLElement_GetTypeInfo,
905     HTMLElement_GetIDsOfNames,
906     HTMLElement_Invoke,
907     HTMLElement_setAttribute,
908     HTMLElement_getAttribute,
909     HTMLElement_removeAttribute,
910     HTMLElement_put_className,
911     HTMLElement_get_className,
912     HTMLElement_put_id,
913     HTMLElement_get_id,
914     HTMLElement_get_tagName,
915     HTMLElement_get_parentElement,
916     HTMLElement_get_style,
917     HTMLElement_put_onhelp,
918     HTMLElement_get_onhelp,
919     HTMLElement_put_onclick,
920     HTMLElement_get_onclick,
921     HTMLElement_put_ondblclick,
922     HTMLElement_get_ondblclick,
923     HTMLElement_put_onkeydown,
924     HTMLElement_get_onkeydown,
925     HTMLElement_put_onkeyup,
926     HTMLElement_get_onkeyup,
927     HTMLElement_put_onkeypress,
928     HTMLElement_get_onkeypress,
929     HTMLElement_put_onmouseout,
930     HTMLElement_get_onmouseout,
931     HTMLElement_put_onmouseover,
932     HTMLElement_get_onmouseover,
933     HTMLElement_put_onmousemove,
934     HTMLElement_get_onmousemove,
935     HTMLElement_put_onmousedown,
936     HTMLElement_get_onmousedown,
937     HTMLElement_put_onmouseup,
938     HTMLElement_get_onmouseup,
939     HTMLElement_get_document,
940     HTMLElement_put_title,
941     HTMLElement_get_title,
942     HTMLElement_put_language,
943     HTMLElement_get_language,
944     HTMLElement_put_onselectstart,
945     HTMLElement_get_onselectstart,
946     HTMLElement_scrollIntoView,
947     HTMLElement_contains,
948     HTMLElement_get_sourceIndex,
949     HTMLElement_get_recordNumber,
950     HTMLElement_put_lang,
951     HTMLElement_get_lang,
952     HTMLElement_get_offsetLeft,
953     HTMLElement_get_offsetTop,
954     HTMLElement_get_offsetWidth,
955     HTMLElement_get_offsetHeight,
956     HTMLElement_get_offsetParent,
957     HTMLElement_put_innerHTML,
958     HTMLElement_get_innerHTML,
959     HTMLElement_put_innerText,
960     HTMLElement_get_innerText,
961     HTMLElement_put_outerHTML,
962     HTMLElement_get_outerHTML,
963     HTMLElement_put_outerText,
964     HTMLElement_get_outerText,
965     HTMLElement_insertAdjacentHTML,
966     HTMLElement_insertAdjacentText,
967     HTMLElement_get_parentTextEdit,
968     HTMLElement_get_isTextEdit,
969     HTMLElement_click,
970     HTMLElement_get_filters,
971     HTMLElement_put_ondragstart,
972     HTMLElement_get_ondragstart,
973     HTMLElement_toString,
974     HTMLElement_put_onbeforeupdate,
975     HTMLElement_get_onbeforeupdate,
976     HTMLElement_put_onafterupdate,
977     HTMLElement_get_onafterupdate,
978     HTMLElement_put_onerrorupdate,
979     HTMLElement_get_onerrorupdate,
980     HTMLElement_put_onrowexit,
981     HTMLElement_get_onrowexit,
982     HTMLElement_put_onrowenter,
983     HTMLElement_get_onrowenter,
984     HTMLElement_put_ondatasetchanged,
985     HTMLElement_get_ondatasetchanged,
986     HTMLElement_put_ondataavailable,
987     HTMLElement_get_ondataavailable,
988     HTMLElement_put_ondatasetcomplete,
989     HTMLElement_get_ondatasetcomplete,
990     HTMLElement_put_onfilterchange,
991     HTMLElement_get_onfilterchange,
992     HTMLElement_get_children,
993     HTMLElement_get_all
994 };
995
996 HRESULT HTMLElement_QI(HTMLElement *This, REFIID riid, void **ppv)
997 {
998     *ppv =  NULL;
999
1000     if(IsEqualGUID(&IID_IUnknown, riid)) {
1001         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1002         *ppv = HTMLELEM(This);
1003     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1004         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1005         *ppv = HTMLELEM(This);
1006     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1007         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1008         *ppv = HTMLELEM(This);
1009     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1010         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1011         *ppv = HTMLELEM2(This);
1012     }
1013
1014     if(*ppv) {
1015         IHTMLElement_AddRef(HTMLELEM(This));
1016         return S_OK;
1017     }
1018
1019     return HTMLDOMNode_QI(This->node, riid, ppv);
1020 }
1021
1022 void HTMLElement_Create(HTMLDOMNode *node)
1023 {
1024     HTMLElement *ret;
1025     nsAString class_name_str;
1026     const PRUnichar *class_name;
1027     nsresult nsres;
1028
1029     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
1030     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
1031     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
1032     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
1033
1034     ret = mshtml_alloc(sizeof(HTMLElement));
1035     ret->lpHTMLElementVtbl = &HTMLElementVtbl;
1036     ret->node = node;
1037     ret->impl = NULL;
1038     ret->destructor = NULL;
1039
1040     node->node_type = NT_HTMLELEM;
1041     node->impl.elem = HTMLELEM(ret);
1042     node->destructor = HTMLElement_destructor;
1043
1044     HTMLElement2_Init(ret);
1045
1046     nsres = nsIDOMNode_QueryInterface(node->nsnode, &IID_nsIDOMHTMLElement, (void**)&ret->nselem);
1047     if(NS_FAILED(nsres))
1048         return;
1049
1050     nsAString_Init(&class_name_str, NULL);
1051     nsIDOMHTMLElement_GetTagName(ret->nselem, &class_name_str);
1052
1053     nsAString_GetData(&class_name_str, &class_name, NULL);
1054
1055     if(!strcmpW(class_name, wszBODY))
1056         HTMLBodyElement_Create(ret);
1057     else if(!strcmpW(class_name, wszINPUT))
1058         HTMLInputElement_Create(ret);
1059     else if(!strcmpW(class_name, wszSELECT))
1060         HTMLSelectElement_Create(ret);
1061     else if(!strcmpW(class_name, wszTEXTAREA))
1062         HTMLTextAreaElement_Create(ret);
1063
1064     nsAString_Finish(&class_name_str);
1065 }
1066
1067 typedef struct {
1068     const IHTMLElementCollectionVtbl *lpHTMLElementCollectionVtbl;
1069
1070     IUnknown *ref_unk;
1071     HTMLElement **elems;
1072     DWORD len;
1073
1074     LONG ref;
1075 } HTMLElementCollection;
1076
1077 #define HTMLELEMCOL(x)  ((IHTMLElementCollection*) &(x)->lpHTMLElementCollectionVtbl)
1078
1079 #define ELEMCOL_THIS(iface) DEFINE_THIS(HTMLElementCollection, HTMLElementCollection, iface)
1080
1081 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
1082                                                            REFIID riid, void **ppv)
1083 {
1084     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1085
1086     *ppv = NULL;
1087
1088     if(IsEqualGUID(&IID_IUnknown, riid)) {
1089         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1090         *ppv = HTMLELEMCOL(This);
1091     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1092         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1093         *ppv = HTMLELEMCOL(This);
1094     }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
1095         TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
1096         *ppv = HTMLELEMCOL(This);
1097     }
1098
1099     if(*ppv) {
1100         IHTMLElementCollection_AddRef(HTMLELEMCOL(This));
1101         return S_OK;
1102     }
1103
1104     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1105     return E_NOINTERFACE;
1106 }
1107
1108 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
1109 {
1110     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1111     LONG ref = InterlockedIncrement(&This->ref);
1112
1113     TRACE("(%p) ref=%d\n", This, ref);
1114
1115     return ref;
1116 }
1117
1118 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
1119 {
1120     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1121     LONG ref = InterlockedDecrement(&This->ref);
1122
1123     TRACE("(%p) ref=%d\n", This, ref);
1124
1125     if(!ref) {
1126         IUnknown_Release(This->ref_unk);
1127         mshtml_free(This->elems);
1128         mshtml_free(This);
1129     }
1130
1131     return ref;
1132 }
1133
1134 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
1135                                                              UINT *pctinfo)
1136 {
1137     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1138     FIXME("(%p)->(%p)\n", This, pctinfo);
1139     return E_NOTIMPL;
1140 }
1141
1142 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
1143         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1144 {
1145     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1146     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1147     return E_NOTIMPL;
1148 }
1149
1150 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
1151         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1152 {
1153     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1154     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1155                                         lcid, rgDispId);
1156     return E_NOTIMPL;
1157 }
1158
1159 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
1160         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1161         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1162 {
1163     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1164     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1165             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1166     return E_NOTIMPL;
1167 }
1168
1169 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
1170                                                      BSTR *String)
1171 {
1172     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1173     FIXME("(%p)->(%p)\n", This, String);
1174     return E_NOTIMPL;
1175 }
1176
1177 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
1178                                                        long v)
1179 {
1180     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1181     FIXME("(%p)->(%ld)\n", This, v);
1182     return E_NOTIMPL;
1183 }
1184
1185 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
1186                                                        long *p)
1187 {
1188     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1189
1190     TRACE("(%p)->(%p)\n", This, p);
1191
1192     *p = This->len;
1193     return S_OK;
1194 }
1195
1196 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
1197                                                          IUnknown **p)
1198 {
1199     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1200     FIXME("(%p)->(%p)\n", This, p);
1201     return E_NOTIMPL;
1202 }
1203
1204 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
1205         VARIANT name, VARIANT index, IDispatch **pdisp)
1206 {
1207     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1208
1209     TRACE("(%p)->(v(%d) v(%d) %p)\n", This, V_VT(&name), V_VT(&index), pdisp);
1210
1211     if(V_VT(&name) == VT_I4) {
1212         TRACE("name is VT_I4: %d\n", V_I4(&name));
1213         if(V_I4(&name) < 0 || V_I4(&name) >= This->len) {
1214             ERR("Invalid name! name=%d\n", V_I4(&name));
1215             return E_INVALIDARG;
1216         }
1217
1218         *pdisp = (IDispatch*)This->elems[V_I4(&name)];
1219         IDispatch_AddRef(*pdisp);
1220         TRACE("Returning pdisp=%p\n", pdisp);
1221         return S_OK;
1222     }
1223
1224     if(V_VT(&name) == VT_BSTR) {
1225         DWORD i;
1226         nsAString tag_str;
1227         const PRUnichar *tag;
1228         elem_vector buf = {NULL, 0, 8};
1229
1230         TRACE("name is VT_BSTR: %s\n", debugstr_w(V_BSTR(&name)));
1231
1232         nsAString_Init(&tag_str, NULL);
1233         buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1234
1235         for(i=0; i<This->len; i++) {
1236             if(!This->elems[i]->nselem) continue;
1237
1238             nsIDOMHTMLElement_GetId(This->elems[i]->nselem, &tag_str);
1239             nsAString_GetData(&tag_str, &tag, NULL);
1240
1241             if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1242                                 V_BSTR(&name), -1) == CSTR_EQUAL) {
1243                 TRACE("Found name. elem=%d\n", i);
1244                 if (V_VT(&index) == VT_I4)
1245                     if (buf.len == V_I4(&index)) {
1246                         nsAString_Finish(&tag_str);
1247                         mshtml_free(buf.buf);
1248                         buf.buf = NULL;
1249                         *pdisp = (IDispatch*)This->elems[i];
1250                         TRACE("Returning element %d pdisp=%p\n", i, pdisp);
1251                         IDispatch_AddRef(*pdisp);
1252                         return S_OK;
1253                     }
1254                 elem_vector_add(&buf, This->elems[i]);
1255             }
1256         }
1257         nsAString_Finish(&tag_str);
1258         if (V_VT(&index) == VT_I4) {
1259             mshtml_free(buf.buf);
1260             buf.buf = NULL;
1261             ERR("Invalid index. index=%d >= buf.len=%d\n",V_I4(&index), buf.len);
1262             return E_INVALIDARG;
1263         }
1264         if(!buf.len) {
1265             mshtml_free(buf.buf);
1266             buf.buf = NULL;
1267         } else if(buf.size > buf.len) {
1268             buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1269         }
1270         TRACE("Returning %d element(s).\n", buf.len);
1271         return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1272     }
1273
1274     FIXME("unsupported arguments\n");
1275     return E_INVALIDARG;
1276 }
1277
1278 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
1279                                                  VARIANT tagName, IDispatch **pdisp)
1280 {
1281     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1282     DWORD i;
1283     nsAString tag_str;
1284     const PRUnichar *tag;
1285     elem_vector buf = {NULL, 0, 8};
1286
1287     if(V_VT(&tagName) != VT_BSTR) {
1288         WARN("Invalid arg\n");
1289         return DISP_E_MEMBERNOTFOUND;
1290     }
1291
1292     TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
1293
1294     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1295
1296     nsAString_Init(&tag_str, NULL);
1297
1298     for(i=0; i<This->len; i++) {
1299         if(!This->elems[i]->nselem)
1300             continue;
1301
1302         nsIDOMElement_GetTagName(This->elems[i]->nselem, &tag_str);
1303         nsAString_GetData(&tag_str, &tag, NULL);
1304
1305         if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1306                           V_BSTR(&tagName), -1) == CSTR_EQUAL)
1307             elem_vector_add(&buf, This->elems[i]);
1308     }
1309
1310     nsAString_Finish(&tag_str);
1311
1312     TRACE("fount %d tags\n", buf.len);
1313
1314     if(!buf.len) {
1315         mshtml_free(buf.buf);
1316         buf.buf = NULL;
1317     }else if(buf.size > buf.len) {
1318         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1319     }
1320
1321     return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1322 }
1323
1324 #undef ELEMCOL_THIS
1325
1326 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
1327     HTMLElementCollection_QueryInterface,
1328     HTMLElementCollection_AddRef,
1329     HTMLElementCollection_Release,
1330     HTMLElementCollection_GetTypeInfoCount,
1331     HTMLElementCollection_GetTypeInfo,
1332     HTMLElementCollection_GetIDsOfNames,
1333     HTMLElementCollection_Invoke,
1334     HTMLElementCollection_toString,
1335     HTMLElementCollection_put_length,
1336     HTMLElementCollection_get_length,
1337     HTMLElementCollection_get__newEnum,
1338     HTMLElementCollection_item,
1339     HTMLElementCollection_tags
1340 };
1341
1342 static HRESULT HTMLElementCollection_Create(IUnknown *ref_unk, HTMLElement **elems, DWORD len,
1343                                             IDispatch **p)
1344 {
1345     HTMLElementCollection *ret = mshtml_alloc(sizeof(HTMLElementCollection));
1346
1347     ret->lpHTMLElementCollectionVtbl = &HTMLElementCollectionVtbl;
1348     ret->ref = 1;
1349     ret->elems = elems;
1350     ret->len = len;
1351
1352     IUnknown_AddRef(ref_unk);
1353     ret->ref_unk = ref_unk;
1354
1355     TRACE("ret=%p len=%d\n", ret, len);
1356
1357     *p = (IDispatch*)ret;
1358     return S_OK;
1359 }