mshtml: Added HTMLElement::ondataavailable implementation.
[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 #include <assert.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
32 #include "binding.h"
33
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 typedef struct {
39     HTMLElement element;
40
41     IHTMLAnchorElement IHTMLAnchorElement_iface;
42
43     nsIDOMHTMLAnchorElement *nsanchor;
44 } HTMLAnchorElement;
45
46 static HRESULT navigate_anchor_window(HTMLAnchorElement *This, const WCHAR *target)
47 {
48     nsAString href_str;
49     IUri *uri;
50     nsresult nsres;
51     HRESULT hres;
52
53     nsAString_Init(&href_str, NULL);
54     nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str);
55     if(NS_SUCCEEDED(nsres)) {
56         const PRUnichar *href;
57
58         nsAString_GetData(&href_str, &href);
59         hres = create_relative_uri(This->element.node.doc->basedoc.window, href, &uri);
60     }else {
61         ERR("Could not get anchor href: %08x\n", nsres);
62         hres = E_FAIL;
63     }
64     nsAString_Finish(&href_str);
65     if(FAILED(hres))
66         return hres;
67
68     hres = navigate_new_window(This->element.node.doc->basedoc.window, uri, target, NULL);
69     IUri_Release(uri);
70     return hres;
71 }
72
73 static HRESULT navigate_anchor(HTMLAnchorElement *This)
74 {
75     nsAString href_str, target_str;
76     HTMLOuterWindow *window = NULL;
77     nsresult nsres;
78     HRESULT hres = E_FAIL;
79
80     static const WCHAR _parentW[] = {'p','a','r','e','n','t',0};
81     static const WCHAR _selfW[] = {'_','s','e','l','f',0};
82     static const WCHAR _topW[] = {'_','t','o','p',0};
83
84     nsAString_Init(&target_str, NULL);
85     nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str);
86     if(NS_SUCCEEDED(nsres)) {
87         const PRUnichar *target;
88
89         TRACE("target %s\n", debugstr_w(target));
90
91         nsAString_GetData(&target_str, &target);
92         if(*target && strcmpiW(target, _selfW)) {
93             if(!strcmpiW(target, _topW)) {
94                 TRACE("target _top\n");
95                 get_top_window(This->element.node.doc->basedoc.window, &window);
96             }else if(!strcmpiW(target, _parentW)) {
97                 FIXME("Navigating to target _parent is not implemented\n");
98                 nsAString_Finish(&target_str);
99                 return S_OK;
100             }else {
101                 HTMLOuterWindow *top_window;
102
103                 get_top_window(This->element.node.doc->basedoc.window, &top_window);
104
105                 hres = get_frame_by_name(top_window, target, TRUE, &window);
106                 if(FAILED(hres) || !window) {
107                     hres = navigate_anchor_window(This, target);
108                     nsAString_Finish(&target_str);
109                     return hres;
110                 }
111             }
112         }
113     }
114     nsAString_Finish(&target_str);
115
116     nsAString_Init(&href_str, NULL);
117     nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str);
118     if(NS_SUCCEEDED(nsres)) {
119         const PRUnichar *href;
120
121         nsAString_GetData(&href_str, &href);
122         if(*href) {
123             if(!window)
124                 window = This->element.node.doc->basedoc.window;
125             hres = navigate_url(window, href, window->url);
126         }else {
127             TRACE("empty href\n");
128             hres = S_OK;
129         }
130     }
131     nsAString_Finish(&href_str);
132     return hres;
133 }
134
135 static inline HTMLAnchorElement *impl_from_IHTMLAnchorElement(IHTMLAnchorElement *iface)
136 {
137     return CONTAINING_RECORD(iface, HTMLAnchorElement, IHTMLAnchorElement_iface);
138 }
139
140 static HRESULT WINAPI HTMLAnchorElement_QueryInterface(IHTMLAnchorElement *iface,
141         REFIID riid, void **ppv)
142 {
143     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
144
145     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
146 }
147
148 static ULONG WINAPI HTMLAnchorElement_AddRef(IHTMLAnchorElement *iface)
149 {
150     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
151
152     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
153 }
154
155 static ULONG WINAPI HTMLAnchorElement_Release(IHTMLAnchorElement *iface)
156 {
157     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
158
159     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
160 }
161
162 static HRESULT WINAPI HTMLAnchorElement_GetTypeInfoCount(IHTMLAnchorElement *iface, UINT *pctinfo)
163 {
164     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
165     return IDispatchEx_GetTypeInfoCount(&This->element.node.dispex.IDispatchEx_iface, pctinfo);
166 }
167
168 static HRESULT WINAPI HTMLAnchorElement_GetTypeInfo(IHTMLAnchorElement *iface, UINT iTInfo,
169                                               LCID lcid, ITypeInfo **ppTInfo)
170 {
171     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
172     return IDispatchEx_GetTypeInfo(&This->element.node.dispex.IDispatchEx_iface, iTInfo, lcid,
173             ppTInfo);
174 }
175
176 static HRESULT WINAPI HTMLAnchorElement_GetIDsOfNames(IHTMLAnchorElement *iface, REFIID riid,
177                                                 LPOLESTR *rgszNames, UINT cNames,
178                                                 LCID lcid, DISPID *rgDispId)
179 {
180     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
181     return IDispatchEx_GetIDsOfNames(&This->element.node.dispex.IDispatchEx_iface, riid, rgszNames,
182             cNames, lcid, rgDispId);
183 }
184
185 static HRESULT WINAPI HTMLAnchorElement_Invoke(IHTMLAnchorElement *iface, DISPID dispIdMember,
186                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
187                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
188 {
189     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
190     return IDispatchEx_Invoke(&This->element.node.dispex.IDispatchEx_iface, dispIdMember, riid,
191             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
192 }
193
194 static HRESULT WINAPI HTMLAnchorElement_put_href(IHTMLAnchorElement *iface, BSTR v)
195 {
196     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
197     nsAString nsstr;
198     nsresult nsres;
199
200     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
201
202     nsAString_InitDepend(&nsstr, v);
203     nsres = nsIDOMHTMLAnchorElement_SetHref(This->nsanchor, &nsstr);
204     nsAString_Finish(&nsstr);
205     if(NS_FAILED(nsres))
206         return E_FAIL;
207
208     return S_OK;
209 }
210
211 static HRESULT WINAPI HTMLAnchorElement_get_href(IHTMLAnchorElement *iface, BSTR *p)
212 {
213     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
214     nsAString href_str;
215     nsresult nsres;
216     HRESULT hres;
217
218     TRACE("(%p)->(%p)\n", This, p);
219
220     nsAString_Init(&href_str, NULL);
221     nsres = nsIDOMHTMLAnchorElement_GetHref(This->nsanchor, &href_str);
222     if(NS_SUCCEEDED(nsres)) {
223         const PRUnichar *href;
224
225         nsAString_GetData(&href_str, &href);
226         hres = nsuri_to_url(href, TRUE, p);
227     }else {
228         ERR("GetHref failed: %08x\n", nsres);
229         hres = E_FAIL;
230     }
231
232     nsAString_Finish(&href_str);
233     return hres;
234 }
235
236 static HRESULT WINAPI HTMLAnchorElement_put_target(IHTMLAnchorElement *iface, BSTR v)
237 {
238     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
239     nsAString nsstr;
240     nsresult nsres;
241
242     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
243
244     nsAString_InitDepend(&nsstr, v);
245     nsres = nsIDOMHTMLAnchorElement_SetTarget(This->nsanchor, &nsstr);
246     nsAString_Finish(&nsstr);
247     if(NS_FAILED(nsres))
248         return E_FAIL;
249
250     return S_OK;
251 }
252
253 static HRESULT WINAPI HTMLAnchorElement_get_target(IHTMLAnchorElement *iface, BSTR *p)
254 {
255     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
256     nsAString target_str;
257     nsresult nsres;
258
259     TRACE("(%p)->(%p)\n", This, p);
260
261     nsAString_Init(&target_str, NULL);
262     nsres = nsIDOMHTMLAnchorElement_GetTarget(This->nsanchor, &target_str);
263
264     return return_nsstr(nsres, &target_str, p);
265 }
266
267 static HRESULT WINAPI HTMLAnchorElement_put_rel(IHTMLAnchorElement *iface, BSTR v)
268 {
269     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
270     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
271     return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI HTMLAnchorElement_get_rel(IHTMLAnchorElement *iface, BSTR *p)
275 {
276     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
277     FIXME("(%p)->(%p)\n", This, p);
278     return E_NOTIMPL;
279 }
280
281 static HRESULT WINAPI HTMLAnchorElement_put_rev(IHTMLAnchorElement *iface, BSTR v)
282 {
283     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
284     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
285     return E_NOTIMPL;
286 }
287
288 static HRESULT WINAPI HTMLAnchorElement_get_rev(IHTMLAnchorElement *iface, BSTR *p)
289 {
290     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
291     FIXME("(%p)->(%p)\n", This, p);
292     return E_NOTIMPL;
293 }
294
295 static HRESULT WINAPI HTMLAnchorElement_put_urn(IHTMLAnchorElement *iface, BSTR v)
296 {
297     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
298     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
299     return E_NOTIMPL;
300 }
301
302 static HRESULT WINAPI HTMLAnchorElement_get_urn(IHTMLAnchorElement *iface, BSTR *p)
303 {
304     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
305     FIXME("(%p)->(%p)\n", This, p);
306     return E_NOTIMPL;
307 }
308
309 static HRESULT WINAPI HTMLAnchorElement_put_Methods(IHTMLAnchorElement *iface, BSTR v)
310 {
311     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
312     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
313     return E_NOTIMPL;
314 }
315
316 static HRESULT WINAPI HTMLAnchorElement_get_Methods(IHTMLAnchorElement *iface, BSTR *p)
317 {
318     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
319     FIXME("(%p)->(%p)\n", This, p);
320     return E_NOTIMPL;
321 }
322
323 static HRESULT WINAPI HTMLAnchorElement_put_name(IHTMLAnchorElement *iface, BSTR v)
324 {
325     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
326     nsAString nsstr;
327     nsresult nsres;
328
329     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
330
331     nsAString_InitDepend(&nsstr, v);
332     nsres = nsIDOMHTMLAnchorElement_SetName(This->nsanchor, &nsstr);
333     nsAString_Finish(&nsstr);
334     if(NS_FAILED(nsres))
335         return E_FAIL;
336
337     return S_OK;
338 }
339
340 static HRESULT WINAPI HTMLAnchorElement_get_name(IHTMLAnchorElement *iface, BSTR *p)
341 {
342     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
343     nsAString name_str;
344     nsresult nsres;
345
346     TRACE("(%p)->(%p)\n", This, p);
347
348     nsAString_Init(&name_str, NULL);
349     nsres = nsIDOMHTMLAnchorElement_GetName(This->nsanchor, &name_str);
350
351     return return_nsstr(nsres, &name_str, p);
352 }
353
354 static HRESULT WINAPI HTMLAnchorElement_put_host(IHTMLAnchorElement *iface, BSTR v)
355 {
356     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
357     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
358     return E_NOTIMPL;
359 }
360
361 static HRESULT WINAPI HTMLAnchorElement_get_host(IHTMLAnchorElement *iface, BSTR *p)
362 {
363     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
364     FIXME("(%p)->(%p)\n", This, p);
365     return E_NOTIMPL;
366 }
367
368 static HRESULT WINAPI HTMLAnchorElement_put_hostname(IHTMLAnchorElement *iface, BSTR v)
369 {
370     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
371     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
372     return E_NOTIMPL;
373 }
374
375 static HRESULT WINAPI HTMLAnchorElement_get_hostname(IHTMLAnchorElement *iface, BSTR *p)
376 {
377     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
378     FIXME("(%p)->(%p)\n", This, p);
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI HTMLAnchorElement_put_pathname(IHTMLAnchorElement *iface, BSTR v)
383 {
384     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
385     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
386     return E_NOTIMPL;
387 }
388
389 static HRESULT WINAPI HTMLAnchorElement_get_pathname(IHTMLAnchorElement *iface, BSTR *p)
390 {
391     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
392     FIXME("(%p)->(%p)\n", This, p);
393     return E_NOTIMPL;
394 }
395
396 static HRESULT WINAPI HTMLAnchorElement_put_port(IHTMLAnchorElement *iface, BSTR v)
397 {
398     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
399     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
400     return E_NOTIMPL;
401 }
402
403 static HRESULT WINAPI HTMLAnchorElement_get_port(IHTMLAnchorElement *iface, BSTR *p)
404 {
405     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
406     FIXME("(%p)->(%p)\n", This, p);
407     return E_NOTIMPL;
408 }
409
410 static HRESULT WINAPI HTMLAnchorElement_put_protocol(IHTMLAnchorElement *iface, BSTR v)
411 {
412     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
413     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
414     return E_NOTIMPL;
415 }
416
417 static HRESULT WINAPI HTMLAnchorElement_get_protocol(IHTMLAnchorElement *iface, BSTR *p)
418 {
419     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
420     FIXME("(%p)->(%p)\n", This, p);
421     return E_NOTIMPL;
422 }
423
424 static HRESULT WINAPI HTMLAnchorElement_put_search(IHTMLAnchorElement *iface, BSTR v)
425 {
426     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
427     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
428     return E_NOTIMPL;
429 }
430
431 static HRESULT WINAPI HTMLAnchorElement_get_search(IHTMLAnchorElement *iface, BSTR *p)
432 {
433     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
434     FIXME("(%p)->(%p)\n", This, p);
435     return E_NOTIMPL;
436 }
437
438 static HRESULT WINAPI HTMLAnchorElement_put_hash(IHTMLAnchorElement *iface, BSTR v)
439 {
440     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
441     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI HTMLAnchorElement_get_hash(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_put_onblur(IHTMLAnchorElement *iface, VARIANT v)
453 {
454     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
455
456     TRACE("(%p)->()\n", This);
457
458     return IHTMLElement2_put_onblur(&This->element.IHTMLElement2_iface, v);
459 }
460
461 static HRESULT WINAPI HTMLAnchorElement_get_onblur(IHTMLAnchorElement *iface, VARIANT *p)
462 {
463     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
464
465     TRACE("(%p)->(%p)\n", This, p);
466
467     return IHTMLElement2_get_onblur(&This->element.IHTMLElement2_iface, p);
468 }
469
470 static HRESULT WINAPI HTMLAnchorElement_put_onfocus(IHTMLAnchorElement *iface, VARIANT v)
471 {
472     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
473
474     TRACE("(%p)->()\n", This);
475
476     return IHTMLElement2_put_onfocus(&This->element.IHTMLElement2_iface, v);
477 }
478
479 static HRESULT WINAPI HTMLAnchorElement_get_onfocus(IHTMLAnchorElement *iface, VARIANT *p)
480 {
481     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
482
483     TRACE("(%p)->(%p)\n", This, p);
484
485     return IHTMLElement2_get_onfocus(&This->element.IHTMLElement2_iface, p);
486 }
487
488 static HRESULT WINAPI HTMLAnchorElement_put_accessKey(IHTMLAnchorElement *iface, BSTR v)
489 {
490     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
491
492     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
493
494     return IHTMLElement2_put_accessKey(&This->element.IHTMLElement2_iface, v);
495 }
496
497 static HRESULT WINAPI HTMLAnchorElement_get_accessKey(IHTMLAnchorElement *iface, BSTR *p)
498 {
499     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
500
501     TRACE("(%p)->(%p)\n", This, p);
502
503     return IHTMLElement2_get_accessKey(&This->element.IHTMLElement2_iface, p);
504 }
505
506 static HRESULT WINAPI HTMLAnchorElement_get_protocolLong(IHTMLAnchorElement *iface, BSTR *p)
507 {
508     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
509     FIXME("(%p)->(%p)\n", This, p);
510     return E_NOTIMPL;
511 }
512
513 static HRESULT WINAPI HTMLAnchorElement_get_mimeType(IHTMLAnchorElement *iface, BSTR *p)
514 {
515     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
516     FIXME("(%p)->(%p)\n", This, p);
517     return E_NOTIMPL;
518 }
519
520 static HRESULT WINAPI HTMLAnchorElement_get_nameProp(IHTMLAnchorElement *iface, BSTR *p)
521 {
522     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
523     FIXME("(%p)->(%p)\n", This, p);
524     return E_NOTIMPL;
525 }
526
527 static HRESULT WINAPI HTMLAnchorElement_put_tabIndex(IHTMLAnchorElement *iface, short v)
528 {
529     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
530
531     TRACE("(%p)->()\n", This);
532
533     return IHTMLElement2_put_tabIndex(&This->element.IHTMLElement2_iface, v);
534 }
535
536 static HRESULT WINAPI HTMLAnchorElement_get_tabIndex(IHTMLAnchorElement *iface, short *p)
537 {
538     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
539
540     TRACE("(%p)->(%p)\n", This, p);
541
542     return IHTMLElement2_get_tabIndex(&This->element.IHTMLElement2_iface, p);
543 }
544
545 static HRESULT WINAPI HTMLAnchorElement_focus(IHTMLAnchorElement *iface)
546 {
547     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
548
549     TRACE("(%p)\n", This);
550
551     return IHTMLElement2_focus(&This->element.IHTMLElement2_iface);
552 }
553
554 static HRESULT WINAPI HTMLAnchorElement_blur(IHTMLAnchorElement *iface)
555 {
556     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
557
558     TRACE("(%p)\n", This);
559
560     return IHTMLElement2_blur(&This->element.IHTMLElement2_iface);
561 }
562
563 static const IHTMLAnchorElementVtbl HTMLAnchorElementVtbl = {
564     HTMLAnchorElement_QueryInterface,
565     HTMLAnchorElement_AddRef,
566     HTMLAnchorElement_Release,
567     HTMLAnchorElement_GetTypeInfoCount,
568     HTMLAnchorElement_GetTypeInfo,
569     HTMLAnchorElement_GetIDsOfNames,
570     HTMLAnchorElement_Invoke,
571     HTMLAnchorElement_put_href,
572     HTMLAnchorElement_get_href,
573     HTMLAnchorElement_put_target,
574     HTMLAnchorElement_get_target,
575     HTMLAnchorElement_put_rel,
576     HTMLAnchorElement_get_rel,
577     HTMLAnchorElement_put_rev,
578     HTMLAnchorElement_get_rev,
579     HTMLAnchorElement_put_urn,
580     HTMLAnchorElement_get_urn,
581     HTMLAnchorElement_put_Methods,
582     HTMLAnchorElement_get_Methods,
583     HTMLAnchorElement_put_name,
584     HTMLAnchorElement_get_name,
585     HTMLAnchorElement_put_host,
586     HTMLAnchorElement_get_host,
587     HTMLAnchorElement_put_hostname,
588     HTMLAnchorElement_get_hostname,
589     HTMLAnchorElement_put_pathname,
590     HTMLAnchorElement_get_pathname,
591     HTMLAnchorElement_put_port,
592     HTMLAnchorElement_get_port,
593     HTMLAnchorElement_put_protocol,
594     HTMLAnchorElement_get_protocol,
595     HTMLAnchorElement_put_search,
596     HTMLAnchorElement_get_search,
597     HTMLAnchorElement_put_hash,
598     HTMLAnchorElement_get_hash,
599     HTMLAnchorElement_put_onblur,
600     HTMLAnchorElement_get_onblur,
601     HTMLAnchorElement_put_onfocus,
602     HTMLAnchorElement_get_onfocus,
603     HTMLAnchorElement_put_accessKey,
604     HTMLAnchorElement_get_accessKey,
605     HTMLAnchorElement_get_protocolLong,
606     HTMLAnchorElement_get_mimeType,
607     HTMLAnchorElement_get_nameProp,
608     HTMLAnchorElement_put_tabIndex,
609     HTMLAnchorElement_get_tabIndex,
610     HTMLAnchorElement_focus,
611     HTMLAnchorElement_blur
612 };
613
614 static inline HTMLAnchorElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
615 {
616     return CONTAINING_RECORD(iface, HTMLAnchorElement, element.node);
617 }
618
619 static HRESULT HTMLAnchorElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
620 {
621     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
622
623     *ppv = NULL;
624
625     if(IsEqualGUID(&IID_IUnknown, riid)) {
626         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
627         *ppv = &This->IHTMLAnchorElement_iface;
628     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
629         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
630         *ppv = &This->IHTMLAnchorElement_iface;
631     }else if(IsEqualGUID(&IID_IHTMLAnchorElement, riid)) {
632         TRACE("(%p)->(IID_IHTMLAnchorElement %p)\n", This, ppv);
633         *ppv = &This->IHTMLAnchorElement_iface;
634     }
635
636     if(*ppv) {
637         IUnknown_AddRef((IUnknown*)*ppv);
638         return S_OK;
639     }
640
641     return HTMLElement_QI(&This->element.node, riid, ppv);
642 }
643
644 static HRESULT HTMLAnchorElement_handle_event(HTMLDOMNode *iface, eventid_t eid, nsIDOMEvent *event, BOOL *prevent_default)
645 {
646     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
647
648     if(eid == EVENTID_CLICK) {
649         nsIDOMMouseEvent *mouse_event;
650         PRUint16 button;
651         nsresult nsres;
652
653         TRACE("CLICK\n");
654
655         nsres = nsIDOMEvent_QueryInterface(event, &IID_nsIDOMMouseEvent, (void**)&mouse_event);
656         assert(nsres == NS_OK);
657
658         nsres = nsIDOMMouseEvent_GetButton(mouse_event, &button);
659         assert(nsres == NS_OK);
660
661         nsIDOMMouseEvent_Release(mouse_event);
662
663         switch(button) {
664         case 0:
665             *prevent_default = TRUE;
666             return navigate_anchor(This);
667         case 1:
668             *prevent_default = TRUE;
669             return navigate_anchor_window(This, NULL);
670         default:
671             *prevent_default = FALSE;
672             return S_OK;
673         }
674     }
675
676     return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default);
677 }
678
679 static const NodeImplVtbl HTMLAnchorElementImplVtbl = {
680     HTMLAnchorElement_QI,
681     HTMLElement_destructor,
682     HTMLElement_clone,
683     HTMLAnchorElement_handle_event,
684     HTMLElement_get_attr_col
685 };
686
687 static const tid_t HTMLAnchorElement_iface_tids[] = {
688     IHTMLAnchorElement_tid,
689     HTMLELEMENT_TIDS,
690     IHTMLTextContainer_tid,
691     IHTMLUniqueName_tid,
692     0
693 };
694
695 static dispex_static_data_t HTMLAnchorElement_dispex = {
696     NULL,
697     DispHTMLAnchorElement_tid,
698     NULL,
699     HTMLAnchorElement_iface_tids
700 };
701
702 HRESULT HTMLAnchorElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
703 {
704     HTMLAnchorElement *ret;
705     nsresult nsres;
706
707     ret = heap_alloc_zero(sizeof(HTMLAnchorElement));
708     if(!ret)
709         return E_OUTOFMEMORY;
710
711     ret->IHTMLAnchorElement_iface.lpVtbl = &HTMLAnchorElementVtbl;
712     ret->element.node.vtbl = &HTMLAnchorElementImplVtbl;
713
714     HTMLElement_Init(&ret->element, doc, nselem, &HTMLAnchorElement_dispex);
715
716     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLAnchorElement, (void**)&ret->nsanchor);
717
718     /* Shere the reference with nsnode */
719     assert(nsres == NS_OK && (nsIDOMNode*)ret->nsanchor == ret->element.node.nsnode);
720     nsIDOMNode_Release(ret->element.node.nsnode);
721
722     *elem = &ret->element;
723     return S_OK;
724 }