mshtml: Fix WARN typo.
[wine] / dlls / mshtml / htmlanchor.c
1 /*
2  * Copyright 2007 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdarg.h>
20 #include <stdio.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28
29 #include "mshtml_private.h"
30 #include "htmlevent.h"
31
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35
36 typedef struct {
37     HTMLElement element;
38
39     IHTMLAnchorElement IHTMLAnchorElement_iface;
40
41     nsIDOMHTMLAnchorElement *nsanchor;
42 } HTMLAnchorElement;
43
44 static HRESULT navigate_anchor(HTMLAnchorElement *This)
45 {
46     nsAString href_str, target_str;
47     nsresult nsres;
48     HRESULT hres = E_FAIL;
49
50     static const WCHAR _selfW[] = {'_','s','e','l','f',0};
51
52     nsAString_Init(&target_str, NULL);
53     nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str);
54     if(NS_SUCCEEDED(nsres)) {
55         const PRUnichar *target;
56
57         nsAString_GetData(&target_str, &target);
58         if(*target && strcmpiW(target, _selfW)) {
59             FIXME("Navigating to target %s is not implemented\n", debugstr_w(target));
60             nsAString_Finish(&target_str);
61             return S_OK;
62         }
63     }
64     nsAString_Finish(&target_str);
65
66     nsAString_Init(&href_str, NULL);
67     nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str);
68     if(NS_SUCCEEDED(nsres)) {
69         const PRUnichar *href;
70
71         nsAString_GetData(&href_str, &href);
72         if(*href) {
73             HTMLWindow *window = This->element.node.doc->basedoc.window;
74             hres = navigate_url(window, href, window->url);
75         }else {
76             TRACE("empty href\n");
77             hres = S_OK;
78         }
79     }
80     nsAString_Finish(&href_str);
81     return hres;
82 }
83
84 static inline HTMLAnchorElement *impl_from_IHTMLAnchorElement(IHTMLAnchorElement *iface)
85 {
86     return CONTAINING_RECORD(iface, HTMLAnchorElement, IHTMLAnchorElement_iface);
87 }
88
89 static HRESULT WINAPI HTMLAnchorElement_QueryInterface(IHTMLAnchorElement *iface,
90         REFIID riid, void **ppv)
91 {
92     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
93
94     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
95 }
96
97 static ULONG WINAPI HTMLAnchorElement_AddRef(IHTMLAnchorElement *iface)
98 {
99     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
100
101     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
102 }
103
104 static ULONG WINAPI HTMLAnchorElement_Release(IHTMLAnchorElement *iface)
105 {
106     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
107
108     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
109 }
110
111 static HRESULT WINAPI HTMLAnchorElement_GetTypeInfoCount(IHTMLAnchorElement *iface, UINT *pctinfo)
112 {
113     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
114     return IDispatchEx_GetTypeInfoCount(&This->element.node.dispex.IDispatchEx_iface, pctinfo);
115 }
116
117 static HRESULT WINAPI HTMLAnchorElement_GetTypeInfo(IHTMLAnchorElement *iface, UINT iTInfo,
118                                               LCID lcid, ITypeInfo **ppTInfo)
119 {
120     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
121     return IDispatchEx_GetTypeInfo(&This->element.node.dispex.IDispatchEx_iface, iTInfo, lcid,
122             ppTInfo);
123 }
124
125 static HRESULT WINAPI HTMLAnchorElement_GetIDsOfNames(IHTMLAnchorElement *iface, REFIID riid,
126                                                 LPOLESTR *rgszNames, UINT cNames,
127                                                 LCID lcid, DISPID *rgDispId)
128 {
129     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
130     return IDispatchEx_GetIDsOfNames(&This->element.node.dispex.IDispatchEx_iface, riid, rgszNames,
131             cNames, lcid, rgDispId);
132 }
133
134 static HRESULT WINAPI HTMLAnchorElement_Invoke(IHTMLAnchorElement *iface, DISPID dispIdMember,
135                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
136                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
137 {
138     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
139     return IDispatchEx_Invoke(&This->element.node.dispex.IDispatchEx_iface, dispIdMember, riid,
140             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
141 }
142
143 static HRESULT WINAPI HTMLAnchorElement_put_href(IHTMLAnchorElement *iface, BSTR v)
144 {
145     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
146     nsAString nsstr;
147     nsresult nsres;
148
149     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
150
151     nsAString_InitDepend(&nsstr, v);
152     nsres = nsIDOMHTMLAnchorElement_SetHref(This->nsanchor, &nsstr);
153     nsAString_Finish(&nsstr);
154     if(NS_FAILED(nsres))
155         return E_FAIL;
156
157     return S_OK;
158 }
159
160 static HRESULT WINAPI HTMLAnchorElement_get_href(IHTMLAnchorElement *iface, BSTR *p)
161 {
162     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
163     nsAString href_str;
164     nsresult nsres;
165     HRESULT hres;
166
167     TRACE("(%p)->(%p)\n", This, p);
168
169     nsAString_Init(&href_str, NULL);
170     nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str);
171     if(NS_SUCCEEDED(nsres)) {
172         const PRUnichar *href;
173
174         nsAString_GetData(&href_str, &href);
175         hres = nsuri_to_url(href, TRUE, p);
176     }else {
177         ERR("GetHref failed: %08x\n", nsres);
178         hres = E_FAIL;
179     }
180
181     nsAString_Finish(&href_str);
182     return hres;
183 }
184
185 static HRESULT WINAPI HTMLAnchorElement_put_target(IHTMLAnchorElement *iface, BSTR v)
186 {
187     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
188     nsAString nsstr;
189     nsresult nsres;
190
191     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
192
193     nsAString_InitDepend(&nsstr, v);
194     nsres = nsIDOMHTMLAnchorElement_SetTarget(This->nsanchor, &nsstr);
195     nsAString_Finish(&nsstr);
196     if(NS_FAILED(nsres))
197         return E_FAIL;
198
199     return S_OK;
200 }
201
202 static HRESULT WINAPI HTMLAnchorElement_get_target(IHTMLAnchorElement *iface, BSTR *p)
203 {
204     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
205     nsAString target_str;
206     nsresult nsres;
207
208     TRACE("(%p)->(%p)\n", This, p);
209
210     nsAString_Init(&target_str, NULL);
211     nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str);
212
213     return return_nsstr(nsres, &target_str, p);
214 }
215
216 static HRESULT WINAPI HTMLAnchorElement_put_rel(IHTMLAnchorElement *iface, BSTR v)
217 {
218     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
219     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI HTMLAnchorElement_get_rel(IHTMLAnchorElement *iface, BSTR *p)
224 {
225     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
226     FIXME("(%p)->(%p)\n", This, p);
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI HTMLAnchorElement_put_rev(IHTMLAnchorElement *iface, BSTR v)
231 {
232     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
233     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI HTMLAnchorElement_get_rev(IHTMLAnchorElement *iface, BSTR *p)
238 {
239     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
240     FIXME("(%p)->(%p)\n", This, p);
241     return E_NOTIMPL;
242 }
243
244 static HRESULT WINAPI HTMLAnchorElement_put_urn(IHTMLAnchorElement *iface, BSTR v)
245 {
246     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
247     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI HTMLAnchorElement_get_urn(IHTMLAnchorElement *iface, BSTR *p)
252 {
253     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
254     FIXME("(%p)->(%p)\n", This, p);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI HTMLAnchorElement_put_Methods(IHTMLAnchorElement *iface, BSTR v)
259 {
260     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
261     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI HTMLAnchorElement_get_Methods(IHTMLAnchorElement *iface, BSTR *p)
266 {
267     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
268     FIXME("(%p)->(%p)\n", This, p);
269     return E_NOTIMPL;
270 }
271
272 static HRESULT WINAPI HTMLAnchorElement_put_name(IHTMLAnchorElement *iface, BSTR v)
273 {
274     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
275     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
276     return E_NOTIMPL;
277 }
278
279 static HRESULT WINAPI HTMLAnchorElement_get_name(IHTMLAnchorElement *iface, BSTR *p)
280 {
281     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
282     FIXME("(%p)->(%p)\n", This, p);
283     return E_NOTIMPL;
284 }
285
286 static HRESULT WINAPI HTMLAnchorElement_put_host(IHTMLAnchorElement *iface, BSTR v)
287 {
288     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
289     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
290     return E_NOTIMPL;
291 }
292
293 static HRESULT WINAPI HTMLAnchorElement_get_host(IHTMLAnchorElement *iface, BSTR *p)
294 {
295     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
296     FIXME("(%p)->(%p)\n", This, p);
297     return E_NOTIMPL;
298 }
299
300 static HRESULT WINAPI HTMLAnchorElement_put_hostname(IHTMLAnchorElement *iface, BSTR v)
301 {
302     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
303     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI HTMLAnchorElement_get_hostname(IHTMLAnchorElement *iface, BSTR *p)
308 {
309     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
310     FIXME("(%p)->(%p)\n", This, p);
311     return E_NOTIMPL;
312 }
313
314 static HRESULT WINAPI HTMLAnchorElement_put_pathname(IHTMLAnchorElement *iface, BSTR v)
315 {
316     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
317     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
318     return E_NOTIMPL;
319 }
320
321 static HRESULT WINAPI HTMLAnchorElement_get_pathname(IHTMLAnchorElement *iface, BSTR *p)
322 {
323     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
324     FIXME("(%p)->(%p)\n", This, p);
325     return E_NOTIMPL;
326 }
327
328 static HRESULT WINAPI HTMLAnchorElement_put_port(IHTMLAnchorElement *iface, BSTR v)
329 {
330     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
331     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
332     return E_NOTIMPL;
333 }
334
335 static HRESULT WINAPI HTMLAnchorElement_get_port(IHTMLAnchorElement *iface, BSTR *p)
336 {
337     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
338     FIXME("(%p)->(%p)\n", This, p);
339     return E_NOTIMPL;
340 }
341
342 static HRESULT WINAPI HTMLAnchorElement_put_protocol(IHTMLAnchorElement *iface, BSTR v)
343 {
344     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
345     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
346     return E_NOTIMPL;
347 }
348
349 static HRESULT WINAPI HTMLAnchorElement_get_protocol(IHTMLAnchorElement *iface, BSTR *p)
350 {
351     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
352     FIXME("(%p)->(%p)\n", This, p);
353     return E_NOTIMPL;
354 }
355
356 static HRESULT WINAPI HTMLAnchorElement_put_search(IHTMLAnchorElement *iface, BSTR v)
357 {
358     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
359     FIXME("(%p)->(%p)\n", This, debugstr_w(v));
360     return E_NOTIMPL;
361 }
362
363 static HRESULT WINAPI HTMLAnchorElement_get_search(IHTMLAnchorElement *iface, BSTR *p)
364 {
365     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
366     FIXME("(%p)->(%p)\n", This, p);
367     return E_NOTIMPL;
368 }
369
370 static HRESULT WINAPI HTMLAnchorElement_put_hash(IHTMLAnchorElement *iface, BSTR v)
371 {
372     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
373     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
374     return E_NOTIMPL;
375 }
376
377 static HRESULT WINAPI HTMLAnchorElement_get_hash(IHTMLAnchorElement *iface, BSTR *p)
378 {
379     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
380     FIXME("(%p)->(%p)\n", This, p);
381     return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI HTMLAnchorElement_put_onblur(IHTMLAnchorElement *iface, VARIANT v)
385 {
386     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
387
388     TRACE("(%p)->()\n", This);
389
390     return IHTMLElement2_put_onblur(&This->element.IHTMLElement2_iface, v);
391 }
392
393 static HRESULT WINAPI HTMLAnchorElement_get_onblur(IHTMLAnchorElement *iface, VARIANT *p)
394 {
395     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
396
397     TRACE("(%p)->(%p)\n", This, p);
398
399     return IHTMLElement2_get_onblur(&This->element.IHTMLElement2_iface, p);
400 }
401
402 static HRESULT WINAPI HTMLAnchorElement_put_onfocus(IHTMLAnchorElement *iface, VARIANT v)
403 {
404     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
405
406     TRACE("(%p)->()\n", This);
407
408     return IHTMLElement2_put_onfocus(&This->element.IHTMLElement2_iface, v);
409 }
410
411 static HRESULT WINAPI HTMLAnchorElement_get_onfocus(IHTMLAnchorElement *iface, VARIANT *p)
412 {
413     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
414
415     TRACE("(%p)->(%p)\n", This, p);
416
417     return IHTMLElement2_get_onfocus(&This->element.IHTMLElement2_iface, p);
418 }
419
420 static HRESULT WINAPI HTMLAnchorElement_put_accessKey(IHTMLAnchorElement *iface, BSTR v)
421 {
422     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
423
424     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
425
426     return IHTMLElement2_put_accessKey(&This->element.IHTMLElement2_iface, v);
427 }
428
429 static HRESULT WINAPI HTMLAnchorElement_get_accessKey(IHTMLAnchorElement *iface, BSTR *p)
430 {
431     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
432
433     TRACE("(%p)->(%p)\n", This, p);
434
435     return IHTMLElement2_get_accessKey(&This->element.IHTMLElement2_iface, p);
436 }
437
438 static HRESULT WINAPI HTMLAnchorElement_get_protocolLong(IHTMLAnchorElement *iface, BSTR *p)
439 {
440     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
441     FIXME("(%p)->(%p)\n", This, p);
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI HTMLAnchorElement_get_mimeType(IHTMLAnchorElement *iface, BSTR *p)
446 {
447     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
448     FIXME("(%p)->(%p)\n", This, p);
449     return E_NOTIMPL;
450 }
451
452 static HRESULT WINAPI HTMLAnchorElement_get_nameProp(IHTMLAnchorElement *iface, BSTR *p)
453 {
454     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
455     FIXME("(%p)->(%p)\n", This, p);
456     return E_NOTIMPL;
457 }
458
459 static HRESULT WINAPI HTMLAnchorElement_put_tabIndex(IHTMLAnchorElement *iface, short v)
460 {
461     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
462
463     TRACE("(%p)->()\n", This);
464
465     return IHTMLElement2_put_tabIndex(&This->element.IHTMLElement2_iface, v);
466 }
467
468 static HRESULT WINAPI HTMLAnchorElement_get_tabIndex(IHTMLAnchorElement *iface, short *p)
469 {
470     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
471
472     TRACE("(%p)->(%p)\n", This, p);
473
474     return IHTMLElement2_get_tabIndex(&This->element.IHTMLElement2_iface, p);
475 }
476
477 static HRESULT WINAPI HTMLAnchorElement_focus(IHTMLAnchorElement *iface)
478 {
479     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
480
481     TRACE("(%p)\n", This);
482
483     return IHTMLElement2_focus(&This->element.IHTMLElement2_iface);
484 }
485
486 static HRESULT WINAPI HTMLAnchorElement_blur(IHTMLAnchorElement *iface)
487 {
488     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
489
490     TRACE("(%p)\n", This);
491
492     return IHTMLElement2_blur(&This->element.IHTMLElement2_iface);
493 }
494
495 static const IHTMLAnchorElementVtbl HTMLAnchorElementVtbl = {
496     HTMLAnchorElement_QueryInterface,
497     HTMLAnchorElement_AddRef,
498     HTMLAnchorElement_Release,
499     HTMLAnchorElement_GetTypeInfoCount,
500     HTMLAnchorElement_GetTypeInfo,
501     HTMLAnchorElement_GetIDsOfNames,
502     HTMLAnchorElement_Invoke,
503     HTMLAnchorElement_put_href,
504     HTMLAnchorElement_get_href,
505     HTMLAnchorElement_put_target,
506     HTMLAnchorElement_get_target,
507     HTMLAnchorElement_put_rel,
508     HTMLAnchorElement_get_rel,
509     HTMLAnchorElement_put_rev,
510     HTMLAnchorElement_get_rev,
511     HTMLAnchorElement_put_urn,
512     HTMLAnchorElement_get_urn,
513     HTMLAnchorElement_put_Methods,
514     HTMLAnchorElement_get_Methods,
515     HTMLAnchorElement_put_name,
516     HTMLAnchorElement_get_name,
517     HTMLAnchorElement_put_host,
518     HTMLAnchorElement_get_host,
519     HTMLAnchorElement_put_hostname,
520     HTMLAnchorElement_get_hostname,
521     HTMLAnchorElement_put_pathname,
522     HTMLAnchorElement_get_pathname,
523     HTMLAnchorElement_put_port,
524     HTMLAnchorElement_get_port,
525     HTMLAnchorElement_put_protocol,
526     HTMLAnchorElement_get_protocol,
527     HTMLAnchorElement_put_search,
528     HTMLAnchorElement_get_search,
529     HTMLAnchorElement_put_hash,
530     HTMLAnchorElement_get_hash,
531     HTMLAnchorElement_put_onblur,
532     HTMLAnchorElement_get_onblur,
533     HTMLAnchorElement_put_onfocus,
534     HTMLAnchorElement_get_onfocus,
535     HTMLAnchorElement_put_accessKey,
536     HTMLAnchorElement_get_accessKey,
537     HTMLAnchorElement_get_protocolLong,
538     HTMLAnchorElement_get_mimeType,
539     HTMLAnchorElement_get_nameProp,
540     HTMLAnchorElement_put_tabIndex,
541     HTMLAnchorElement_get_tabIndex,
542     HTMLAnchorElement_focus,
543     HTMLAnchorElement_blur
544 };
545
546 static inline HTMLAnchorElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
547 {
548     return CONTAINING_RECORD(iface, HTMLAnchorElement, element.node);
549 }
550
551 static HRESULT HTMLAnchorElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
552 {
553     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
554
555     *ppv = NULL;
556
557     if(IsEqualGUID(&IID_IUnknown, riid)) {
558         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
559         *ppv = &This->IHTMLAnchorElement_iface;
560     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
561         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
562         *ppv = &This->IHTMLAnchorElement_iface;
563     }else if(IsEqualGUID(&IID_IHTMLAnchorElement, riid)) {
564         TRACE("(%p)->(IID_IHTMLAnchorElement %p)\n", This, ppv);
565         *ppv = &This->IHTMLAnchorElement_iface;
566     }
567
568     if(*ppv) {
569         IUnknown_AddRef((IUnknown*)*ppv);
570         return S_OK;
571     }
572
573     return HTMLElement_QI(&This->element.node, riid, ppv);
574 }
575
576 static void HTMLAnchorElement_destructor(HTMLDOMNode *iface)
577 {
578     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
579
580     if(This->nsanchor)
581         nsIDOMHTMLAnchorElement_Release(This->nsanchor);
582
583     HTMLElement_destructor(&This->element.node);
584 }
585
586 static HRESULT HTMLAnchorElement_handle_event(HTMLDOMNode *iface, eventid_t eid, BOOL *prevent_default)
587 {
588     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
589
590     if(eid == EVENTID_CLICK) {
591         TRACE("CLICK\n");
592         *prevent_default = TRUE;
593         return navigate_anchor(This);
594     }
595
596     return S_OK;
597 }
598
599 static const NodeImplVtbl HTMLAnchorElementImplVtbl = {
600     HTMLAnchorElement_QI,
601     HTMLAnchorElement_destructor,
602     HTMLElement_clone,
603     HTMLElement_get_attr_col,
604     NULL,
605     NULL,
606     HTMLAnchorElement_handle_event
607 };
608
609 static const tid_t HTMLAnchorElement_iface_tids[] = {
610     IHTMLAnchorElement_tid,
611     HTMLELEMENT_TIDS,
612     IHTMLTextContainer_tid,
613     IHTMLUniqueName_tid,
614     0
615 };
616
617 static dispex_static_data_t HTMLAnchorElement_dispex = {
618     NULL,
619     DispHTMLAnchorElement_tid,
620     NULL,
621     HTMLAnchorElement_iface_tids
622 };
623
624 HRESULT HTMLAnchorElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
625 {
626     HTMLAnchorElement *ret;
627     nsresult nsres;
628
629     ret = heap_alloc_zero(sizeof(HTMLAnchorElement));
630     if(!ret)
631         return E_OUTOFMEMORY;
632
633     ret->IHTMLAnchorElement_iface.lpVtbl = &HTMLAnchorElementVtbl;
634     ret->element.node.vtbl = &HTMLAnchorElementImplVtbl;
635
636     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLAnchorElement, (void**)&ret->nsanchor);
637     if(NS_FAILED(nsres)) {
638         ERR("Could not get nsIDOMHTMLAnchorElement iface: %08x\n", nsres);
639         heap_free(ret);
640         return E_FAIL;
641     }
642
643     HTMLElement_Init(&ret->element, doc, nselem, &HTMLAnchorElement_dispex);
644
645     *elem = &ret->element;
646     return S_OK;
647 }