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