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