mshtml: Added IHTMLAnchorElement::get_hostname 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         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     nsAString hostname_str;
378     nsresult nsres;
379
380     TRACE("(%p)->(%p)\n", This, p);
381
382     nsAString_Init(&hostname_str, NULL);
383     nsres = nsIDOMHTMLAnchorElement_GetHostname(This->nsanchor, &hostname_str);
384     return return_nsstr(nsres, &hostname_str, p);
385 }
386
387 static HRESULT WINAPI HTMLAnchorElement_put_pathname(IHTMLAnchorElement *iface, BSTR v)
388 {
389     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
390     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
391     return E_NOTIMPL;
392 }
393
394 static HRESULT WINAPI HTMLAnchorElement_get_pathname(IHTMLAnchorElement *iface, BSTR *p)
395 {
396     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
397     FIXME("(%p)->(%p)\n", This, p);
398     return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI HTMLAnchorElement_put_port(IHTMLAnchorElement *iface, BSTR v)
402 {
403     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
404     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
405     return E_NOTIMPL;
406 }
407
408 static HRESULT WINAPI HTMLAnchorElement_get_port(IHTMLAnchorElement *iface, BSTR *p)
409 {
410     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
411     FIXME("(%p)->(%p)\n", This, p);
412     return E_NOTIMPL;
413 }
414
415 static HRESULT WINAPI HTMLAnchorElement_put_protocol(IHTMLAnchorElement *iface, BSTR v)
416 {
417     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
418     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
419     return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI HTMLAnchorElement_get_protocol(IHTMLAnchorElement *iface, BSTR *p)
423 {
424     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
425     FIXME("(%p)->(%p)\n", This, p);
426     return E_NOTIMPL;
427 }
428
429 static HRESULT WINAPI HTMLAnchorElement_put_search(IHTMLAnchorElement *iface, BSTR v)
430 {
431     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
432     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
433     return E_NOTIMPL;
434 }
435
436 static HRESULT WINAPI HTMLAnchorElement_get_search(IHTMLAnchorElement *iface, BSTR *p)
437 {
438     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
439     FIXME("(%p)->(%p)\n", This, p);
440     return E_NOTIMPL;
441 }
442
443 static HRESULT WINAPI HTMLAnchorElement_put_hash(IHTMLAnchorElement *iface, BSTR v)
444 {
445     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
446     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
447     return E_NOTIMPL;
448 }
449
450 static HRESULT WINAPI HTMLAnchorElement_get_hash(IHTMLAnchorElement *iface, BSTR *p)
451 {
452     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
453     FIXME("(%p)->(%p)\n", This, p);
454     return E_NOTIMPL;
455 }
456
457 static HRESULT WINAPI HTMLAnchorElement_put_onblur(IHTMLAnchorElement *iface, VARIANT v)
458 {
459     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
460
461     TRACE("(%p)->()\n", This);
462
463     return IHTMLElement2_put_onblur(&This->element.IHTMLElement2_iface, v);
464 }
465
466 static HRESULT WINAPI HTMLAnchorElement_get_onblur(IHTMLAnchorElement *iface, VARIANT *p)
467 {
468     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
469
470     TRACE("(%p)->(%p)\n", This, p);
471
472     return IHTMLElement2_get_onblur(&This->element.IHTMLElement2_iface, p);
473 }
474
475 static HRESULT WINAPI HTMLAnchorElement_put_onfocus(IHTMLAnchorElement *iface, VARIANT v)
476 {
477     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
478
479     TRACE("(%p)->()\n", This);
480
481     return IHTMLElement2_put_onfocus(&This->element.IHTMLElement2_iface, v);
482 }
483
484 static HRESULT WINAPI HTMLAnchorElement_get_onfocus(IHTMLAnchorElement *iface, VARIANT *p)
485 {
486     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
487
488     TRACE("(%p)->(%p)\n", This, p);
489
490     return IHTMLElement2_get_onfocus(&This->element.IHTMLElement2_iface, p);
491 }
492
493 static HRESULT WINAPI HTMLAnchorElement_put_accessKey(IHTMLAnchorElement *iface, BSTR v)
494 {
495     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
496
497     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
498
499     return IHTMLElement2_put_accessKey(&This->element.IHTMLElement2_iface, v);
500 }
501
502 static HRESULT WINAPI HTMLAnchorElement_get_accessKey(IHTMLAnchorElement *iface, BSTR *p)
503 {
504     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
505
506     TRACE("(%p)->(%p)\n", This, p);
507
508     return IHTMLElement2_get_accessKey(&This->element.IHTMLElement2_iface, p);
509 }
510
511 static HRESULT WINAPI HTMLAnchorElement_get_protocolLong(IHTMLAnchorElement *iface, BSTR *p)
512 {
513     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
514     FIXME("(%p)->(%p)\n", This, p);
515     return E_NOTIMPL;
516 }
517
518 static HRESULT WINAPI HTMLAnchorElement_get_mimeType(IHTMLAnchorElement *iface, BSTR *p)
519 {
520     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
521     FIXME("(%p)->(%p)\n", This, p);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI HTMLAnchorElement_get_nameProp(IHTMLAnchorElement *iface, BSTR *p)
526 {
527     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
528     FIXME("(%p)->(%p)\n", This, p);
529     return E_NOTIMPL;
530 }
531
532 static HRESULT WINAPI HTMLAnchorElement_put_tabIndex(IHTMLAnchorElement *iface, short v)
533 {
534     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
535
536     TRACE("(%p)->()\n", This);
537
538     return IHTMLElement2_put_tabIndex(&This->element.IHTMLElement2_iface, v);
539 }
540
541 static HRESULT WINAPI HTMLAnchorElement_get_tabIndex(IHTMLAnchorElement *iface, short *p)
542 {
543     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
544
545     TRACE("(%p)->(%p)\n", This, p);
546
547     return IHTMLElement2_get_tabIndex(&This->element.IHTMLElement2_iface, p);
548 }
549
550 static HRESULT WINAPI HTMLAnchorElement_focus(IHTMLAnchorElement *iface)
551 {
552     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
553
554     TRACE("(%p)\n", This);
555
556     return IHTMLElement2_focus(&This->element.IHTMLElement2_iface);
557 }
558
559 static HRESULT WINAPI HTMLAnchorElement_blur(IHTMLAnchorElement *iface)
560 {
561     HTMLAnchorElement *This = impl_from_IHTMLAnchorElement(iface);
562
563     TRACE("(%p)\n", This);
564
565     return IHTMLElement2_blur(&This->element.IHTMLElement2_iface);
566 }
567
568 static const IHTMLAnchorElementVtbl HTMLAnchorElementVtbl = {
569     HTMLAnchorElement_QueryInterface,
570     HTMLAnchorElement_AddRef,
571     HTMLAnchorElement_Release,
572     HTMLAnchorElement_GetTypeInfoCount,
573     HTMLAnchorElement_GetTypeInfo,
574     HTMLAnchorElement_GetIDsOfNames,
575     HTMLAnchorElement_Invoke,
576     HTMLAnchorElement_put_href,
577     HTMLAnchorElement_get_href,
578     HTMLAnchorElement_put_target,
579     HTMLAnchorElement_get_target,
580     HTMLAnchorElement_put_rel,
581     HTMLAnchorElement_get_rel,
582     HTMLAnchorElement_put_rev,
583     HTMLAnchorElement_get_rev,
584     HTMLAnchorElement_put_urn,
585     HTMLAnchorElement_get_urn,
586     HTMLAnchorElement_put_Methods,
587     HTMLAnchorElement_get_Methods,
588     HTMLAnchorElement_put_name,
589     HTMLAnchorElement_get_name,
590     HTMLAnchorElement_put_host,
591     HTMLAnchorElement_get_host,
592     HTMLAnchorElement_put_hostname,
593     HTMLAnchorElement_get_hostname,
594     HTMLAnchorElement_put_pathname,
595     HTMLAnchorElement_get_pathname,
596     HTMLAnchorElement_put_port,
597     HTMLAnchorElement_get_port,
598     HTMLAnchorElement_put_protocol,
599     HTMLAnchorElement_get_protocol,
600     HTMLAnchorElement_put_search,
601     HTMLAnchorElement_get_search,
602     HTMLAnchorElement_put_hash,
603     HTMLAnchorElement_get_hash,
604     HTMLAnchorElement_put_onblur,
605     HTMLAnchorElement_get_onblur,
606     HTMLAnchorElement_put_onfocus,
607     HTMLAnchorElement_get_onfocus,
608     HTMLAnchorElement_put_accessKey,
609     HTMLAnchorElement_get_accessKey,
610     HTMLAnchorElement_get_protocolLong,
611     HTMLAnchorElement_get_mimeType,
612     HTMLAnchorElement_get_nameProp,
613     HTMLAnchorElement_put_tabIndex,
614     HTMLAnchorElement_get_tabIndex,
615     HTMLAnchorElement_focus,
616     HTMLAnchorElement_blur
617 };
618
619 static inline HTMLAnchorElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
620 {
621     return CONTAINING_RECORD(iface, HTMLAnchorElement, element.node);
622 }
623
624 static HRESULT HTMLAnchorElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
625 {
626     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
627
628     *ppv = NULL;
629
630     if(IsEqualGUID(&IID_IUnknown, riid)) {
631         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
632         *ppv = &This->IHTMLAnchorElement_iface;
633     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
634         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
635         *ppv = &This->IHTMLAnchorElement_iface;
636     }else if(IsEqualGUID(&IID_IHTMLAnchorElement, riid)) {
637         TRACE("(%p)->(IID_IHTMLAnchorElement %p)\n", This, ppv);
638         *ppv = &This->IHTMLAnchorElement_iface;
639     }
640
641     if(*ppv) {
642         IUnknown_AddRef((IUnknown*)*ppv);
643         return S_OK;
644     }
645
646     return HTMLElement_QI(&This->element.node, riid, ppv);
647 }
648
649 static HRESULT HTMLAnchorElement_handle_event(HTMLDOMNode *iface, eventid_t eid, nsIDOMEvent *event, BOOL *prevent_default)
650 {
651     HTMLAnchorElement *This = impl_from_HTMLDOMNode(iface);
652
653     if(eid == EVENTID_CLICK) {
654         nsIDOMMouseEvent *mouse_event;
655         UINT16 button;
656         nsresult nsres;
657
658         TRACE("CLICK\n");
659
660         nsres = nsIDOMEvent_QueryInterface(event, &IID_nsIDOMMouseEvent, (void**)&mouse_event);
661         assert(nsres == NS_OK);
662
663         nsres = nsIDOMMouseEvent_GetButton(mouse_event, &button);
664         assert(nsres == NS_OK);
665
666         nsIDOMMouseEvent_Release(mouse_event);
667
668         switch(button) {
669         case 0:
670             *prevent_default = TRUE;
671             return navigate_anchor(This);
672         case 1:
673             *prevent_default = TRUE;
674             return navigate_anchor_window(This, NULL);
675         default:
676             *prevent_default = FALSE;
677             return S_OK;
678         }
679     }
680
681     return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default);
682 }
683
684 static const NodeImplVtbl HTMLAnchorElementImplVtbl = {
685     HTMLAnchorElement_QI,
686     HTMLElement_destructor,
687     HTMLElement_clone,
688     HTMLAnchorElement_handle_event,
689     HTMLElement_get_attr_col
690 };
691
692 static const tid_t HTMLAnchorElement_iface_tids[] = {
693     IHTMLAnchorElement_tid,
694     HTMLELEMENT_TIDS,
695     IHTMLUniqueName_tid,
696     0
697 };
698
699 static dispex_static_data_t HTMLAnchorElement_dispex = {
700     NULL,
701     DispHTMLAnchorElement_tid,
702     NULL,
703     HTMLAnchorElement_iface_tids
704 };
705
706 HRESULT HTMLAnchorElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
707 {
708     HTMLAnchorElement *ret;
709     nsresult nsres;
710
711     ret = heap_alloc_zero(sizeof(HTMLAnchorElement));
712     if(!ret)
713         return E_OUTOFMEMORY;
714
715     ret->IHTMLAnchorElement_iface.lpVtbl = &HTMLAnchorElementVtbl;
716     ret->element.node.vtbl = &HTMLAnchorElementImplVtbl;
717
718     HTMLElement_Init(&ret->element, doc, nselem, &HTMLAnchorElement_dispex);
719
720     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLAnchorElement, (void**)&ret->nsanchor);
721
722     /* Shere the reference with nsnode */
723     assert(nsres == NS_OK && (nsIDOMNode*)ret->nsanchor == ret->element.node.nsnode);
724     nsIDOMNode_Release(ret->element.node.nsnode);
725
726     *elem = &ret->element;
727     return S_OK;
728 }