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