]> git.saurik.com Git - wxWidgets.git/blame - src/msw/webview_ie.cpp
Fix wxKeyEvent::GetKeyCode() descripotion: it doesn't depend on locale.
[wxWidgets.git] / src / msw / webview_ie.cpp
CommitLineData
61b98a2d 1/////////////////////////////////////////////////////////////////////////////
8290e3cd 2// Name: src/msw/webview_ie.cpp
61b98a2d
SL
3// Purpose: wxMSW wxWebViewIE class implementation for web view component
4// Author: Marianne Gagnon
5// Id: $Id$
153530af 6// Copyright: (c) 2010 Marianne Gagnon, 2011 Steven Lamerton
61b98a2d
SL
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
384b8d9f
SL
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
13#if defined(__BORLANDC__)
14 #pragma hdrstop
15#endif
16
8290e3cd 17#include "wx/msw/webview_ie.h"
61b98a2d 18
9d2f31db 19#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
61b98a2d
SL
20
21#include <olectl.h>
22#include <oleidl.h>
23#include <exdispid.h>
24#include <exdisp.h>
25#include <mshtml.h>
cd4e4673 26#include "wx/msw/registry.h"
1d7d04d7 27#include "wx/msw/missing.h"
7d3f6b4d 28#include "wx/filesys.h"
e924e848 29#include "wx/dynlib.h"
f559d1a2
VZ
30#include <initguid.h>
31
32/* These GUID definitions are our own implementation to support interfaces
33 * normally in urlmon.h. See include/wx/msw/webview_ie.h
34 */
35
36namespace {
37
38DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
39DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb);
accc94d5 40DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a);
f559d1a2 41
66ac0400
SL
42enum //Internal find flags
43{
44 wxWEB_VIEW_FIND_ADD_POINTERS = 0x0001,
45 wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT = 0x0002
46};
47
f559d1a2 48}
7d3f6b4d 49
cddf4541
SL
50wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewIE, wxWebView);
51
61b98a2d 52BEGIN_EVENT_TABLE(wxWebViewIE, wxControl)
97ad1425
SL
53 EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent)
54 EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg)
61b98a2d
SL
55END_EVENT_TABLE()
56
57bool wxWebViewIE::Create(wxWindow* parent,
58 wxWindowID id,
59 const wxString& url,
60 const wxPoint& pos,
61 const wxSize& size,
62 long style,
63 const wxString& name)
64{
65 if (!wxControl::Create(parent, id, pos, size, style,
66 wxDefaultValidator, name))
67 {
68 return false;
69 }
70
71 m_webBrowser = NULL;
61b98a2d 72 m_isBusy = false;
74af0b13
SL
73 m_historyLoadingFromList = false;
74 m_historyEnabled = true;
75 m_historyPosition = -1;
c5f417cb 76 m_zoomType = wxWEB_VIEW_ZOOM_TYPE_TEXT;
66ac0400 77 FindClear();
61b98a2d
SL
78
79 if (::CoCreateInstance(CLSID_WebBrowser, NULL,
80 CLSCTX_INPROC_SERVER, // CLSCTX_INPROC,
81 IID_IWebBrowser2 , (void**)&m_webBrowser) != 0)
82 {
83 wxLogError("Failed to initialize IE, CoCreateInstance returned an error");
84 return false;
85 }
86
87 m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself
88
89 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
90 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
61b98a2d 91
accc94d5 92 m_uiHandler = new DocHostUIHandler;
accc94d5
SL
93
94 m_container = new wxIEContainer(this, IID_IWebBrowser2, m_webBrowser, m_uiHandler);
61b98a2d 95
9447a0d6
SL
96 EnableControlFeature(21 /* FEATURE_DISABLE_NAVIGATION_SOUNDS */);
97
4d0dddc7 98 LoadURL(url);
61b98a2d
SL
99 return true;
100}
101
39498710
SL
102wxWebViewIE::~wxWebViewIE()
103{
104 for(unsigned int i = 0; i < m_factories.size(); i++)
105 {
106 m_factories[i]->Release();
107 }
66ac0400 108 FindClear();
39498710 109}
61b98a2d 110
4d0dddc7 111void wxWebViewIE::LoadURL(const wxString& url)
61b98a2d 112{
e8d243a9 113 m_ie.CallMethod("Navigate", wxConvertStringToOle(url));
61b98a2d
SL
114}
115
a977376a 116void wxWebViewIE::DoSetPage(const wxString& html, const wxString& baseUrl)
61b98a2d 117{
7f98bdd6 118 BSTR bstr = SysAllocString(OLESTR(""));
61b98a2d
SL
119 SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
120 if (psaStrings != NULL)
121 {
122 VARIANT *param;
123 HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
124 param->vt = VT_BSTR;
125 param->bstrVal = bstr;
442262d4 126
7f98bdd6 127 hr = SafeArrayUnaccessData(psaStrings);
accc94d5 128
f40f8e17 129 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
130
131 if(!document)
132 return;
133
61b98a2d 134 document->write(psaStrings);
7f98bdd6 135 document->close();
61b98a2d 136
61b98a2d 137 SafeArrayDestroy(psaStrings);
442262d4 138
7f98bdd6
SL
139 bstr = SysAllocString(html.wc_str());
140
141 // Creates a new one-dimensional array
142 psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
143 if (psaStrings != NULL)
144 {
145 hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
146 param->vt = VT_BSTR;
147 param->bstrVal = bstr;
148 hr = SafeArrayUnaccessData(psaStrings);
149
150 document = GetDocument();
e81ef297
SL
151
152 if(!document)
153 return;
154
7f98bdd6 155 document->write(psaStrings);
7f98bdd6
SL
156
157 // SafeArrayDestroy calls SysFreeString for each BSTR
158 SafeArrayDestroy(psaStrings);
159
160 //We send the events when we are done to mimic webkit
161 //Navigated event
162 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
163 GetId(), baseUrl, "");
164 event.SetEventObject(this);
165 HandleWindowEvent(event);
166
167 //Document complete event
168 event.SetEventType(wxEVT_COMMAND_WEB_VIEW_LOADED);
169 event.SetEventObject(this);
170 HandleWindowEvent(event);
171 }
172 else
173 {
174 wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL");
175 }
61b98a2d
SL
176 }
177 else
178 {
7f98bdd6 179 wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL during clear");
61b98a2d 180 }
61b98a2d
SL
181}
182
e669ddde 183wxString wxWebViewIE::GetPageSource() const
61b98a2d 184{
f40f8e17 185 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
186
187 if(document)
7fbc727b 188 {
f40f8e17
SL
189 wxCOMPtr<IHTMLElement> bodyTag;
190 wxCOMPtr<IHTMLElement> htmlTag;
e81ef297
SL
191 wxString source;
192 HRESULT hr = document->get_body(&bodyTag);
7fbc727b
SL
193 if(SUCCEEDED(hr))
194 {
e81ef297
SL
195 hr = bodyTag->get_parentElement(&htmlTag);
196 if(SUCCEEDED(hr))
197 {
198 BSTR bstr;
199 htmlTag->get_outerHTML(&bstr);
200 source = wxString(bstr);
e81ef297 201 }
7fbc727b 202 }
e81ef297
SL
203 return source;
204 }
205 else
206 {
207 return "";
208 }
61b98a2d
SL
209}
210
e669ddde 211wxWebViewZoom wxWebViewIE::GetZoom() const
61b98a2d 212{
8acbf08b
SL
213 switch( m_zoomType )
214 {
215 case wxWEB_VIEW_ZOOM_TYPE_LAYOUT:
216 return GetIEOpticalZoom();
217 case wxWEB_VIEW_ZOOM_TYPE_TEXT:
218 return GetIETextZoom();
219 default:
220 wxFAIL;
221 }
423adfde
SL
222
223 //Dummy return to stop compiler warnings
224 return wxWEB_VIEW_ZOOM_MEDIUM;
1d7d04d7 225
61b98a2d 226}
c5f417cb 227
61b98a2d
SL
228void wxWebViewIE::SetZoom(wxWebViewZoom zoom)
229{
8acbf08b
SL
230 switch( m_zoomType )
231 {
232 case wxWEB_VIEW_ZOOM_TYPE_LAYOUT:
233 SetIEOpticalZoom(zoom);
234 break;
235 case wxWEB_VIEW_ZOOM_TYPE_TEXT:
236 SetIETextZoom(zoom);
237 break;
238 default:
239 wxFAIL;
240 }
61b98a2d
SL
241}
242
c5f417cb 243void wxWebViewIE::SetIETextZoom(wxWebViewZoom level)
61b98a2d 244{
1d7d04d7 245 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb
SL
246 //is 0 to 4 so the check is unnecessary, these match exactly with the
247 //enum values
61b98a2d
SL
248 VARIANT zoomVariant;
249 VariantInit (&zoomVariant);
250 V_VT(&zoomVariant) = VT_I4;
251 V_I4(&zoomVariant) = level;
252
8acbf08b
SL
253#if wxDEBUG_LEVEL
254 HRESULT result =
255#endif
256 m_webBrowser->ExecWB(OLECMDID_ZOOM,
257 OLECMDEXECOPT_DONTPROMPTUSER,
258 &zoomVariant, NULL);
c5f417cb 259 wxASSERT(result == S_OK);
61b98a2d
SL
260}
261
e669ddde 262wxWebViewZoom wxWebViewIE::GetIETextZoom() const
61b98a2d
SL
263{
264 VARIANT zoomVariant;
265 VariantInit (&zoomVariant);
266 V_VT(&zoomVariant) = VT_I4;
61b98a2d 267
8acbf08b
SL
268#if wxDEBUG_LEVEL
269 HRESULT result =
270#endif
271 m_webBrowser->ExecWB(OLECMDID_ZOOM,
272 OLECMDEXECOPT_DONTPROMPTUSER,
273 NULL, &zoomVariant);
c5f417cb 274 wxASSERT(result == S_OK);
61b98a2d 275
c5f417cb
SL
276 //We can safely cast here as we know that the range matches our enum
277 return static_cast<wxWebViewZoom>(V_I4(&zoomVariant));
61b98a2d
SL
278}
279
c5f417cb 280void wxWebViewIE::SetIEOpticalZoom(wxWebViewZoom level)
61b98a2d 281{
1d7d04d7 282 //We do not use OLECMDID_OPTICAL_GETZOOMRANGE as the docs say the range
c5f417cb 283 //is 10 to 1000 so the check is unnecessary
61b98a2d
SL
284 VARIANT zoomVariant;
285 VariantInit (&zoomVariant);
286 V_VT(&zoomVariant) = VT_I4;
c5f417cb
SL
287
288 //We make a somewhat arbitray map here, taken from values used by webkit
289 switch(level)
290 {
291 case wxWEB_VIEW_ZOOM_TINY:
292 V_I4(&zoomVariant) = 60;
293 break;
294 case wxWEB_VIEW_ZOOM_SMALL:
295 V_I4(&zoomVariant) = 80;
296 break;
297 case wxWEB_VIEW_ZOOM_MEDIUM:
298 V_I4(&zoomVariant) = 100;
299 break;
300 case wxWEB_VIEW_ZOOM_LARGE:
301 V_I4(&zoomVariant) = 130;
302 break;
303 case wxWEB_VIEW_ZOOM_LARGEST:
304 V_I4(&zoomVariant) = 160;
305 break;
306 default:
307 wxFAIL;
308 }
61b98a2d 309
8acbf08b
SL
310#if wxDEBUG_LEVEL
311 HRESULT result =
312#endif
313 m_webBrowser->ExecWB((OLECMDID)63 /*OLECMDID_OPTICAL_ZOOM*/,
314 OLECMDEXECOPT_DODEFAULT,
315 &zoomVariant,
316 NULL);
c5f417cb 317 wxASSERT(result == S_OK);
61b98a2d
SL
318}
319
e669ddde 320wxWebViewZoom wxWebViewIE::GetIEOpticalZoom() const
61b98a2d 321{
61b98a2d
SL
322 VARIANT zoomVariant;
323 VariantInit (&zoomVariant);
324 V_VT(&zoomVariant) = VT_I4;
61b98a2d 325
8acbf08b
SL
326#if wxDEBUG_LEVEL
327 HRESULT result =
328#endif
329 m_webBrowser->ExecWB((OLECMDID)63 /*OLECMDID_OPTICAL_ZOOM*/,
330 OLECMDEXECOPT_DODEFAULT, NULL,
331 &zoomVariant);
c5f417cb 332 wxASSERT(result == S_OK);
61b98a2d
SL
333
334 const int zoom = V_I4(&zoomVariant);
61b98a2d 335
c5f417cb
SL
336 //We make a somewhat arbitray map here, taken from values used by webkit
337 if (zoom <= 65)
338 {
339 return wxWEB_VIEW_ZOOM_TINY;
340 }
341 else if (zoom > 65 && zoom <= 90)
342 {
343 return wxWEB_VIEW_ZOOM_SMALL;
344 }
345 else if (zoom > 90 && zoom <= 115)
346 {
347 return wxWEB_VIEW_ZOOM_MEDIUM;
348 }
349 else if (zoom > 115 && zoom <= 145)
350 {
351 return wxWEB_VIEW_ZOOM_LARGE;
352 }
423adfde 353 else /*if (zoom > 145) */ //Using else removes a compiler warning
c5f417cb
SL
354 {
355 return wxWEB_VIEW_ZOOM_LARGEST;
356 }
61b98a2d
SL
357}
358
c5f417cb 359void wxWebViewIE::SetZoomType(wxWebViewZoomType type)
61b98a2d 360{
c5f417cb 361 m_zoomType = type;
61b98a2d
SL
362}
363
364wxWebViewZoomType wxWebViewIE::GetZoomType() const
365{
c5f417cb 366 return m_zoomType;
61b98a2d
SL
367}
368
cd4e4673 369bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType type) const
61b98a2d 370{
cd4e4673
SL
371 //IE 6 and below only support text zoom, so check the registry to see what
372 //version we actually have
373 wxRegKey key(wxRegKey::HKLM, "Software\\Microsoft\\Internet Explorer");
374 wxString value;
375 key.QueryValue("Version", value);
376
377 long version = wxAtoi(value.Left(1));
378 if(version <= 6 && type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT)
379 return false;
380 else
381 return true;
61b98a2d
SL
382}
383
384void wxWebViewIE::Print()
385{
386 m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW,
387 OLECMDEXECOPT_DODEFAULT, NULL, NULL);
388}
389
e669ddde 390bool wxWebViewIE::CanGoBack() const
61b98a2d 391{
74af0b13
SL
392 if(m_historyEnabled)
393 return m_historyPosition > 0;
394 else
395 return false;
396}
61b98a2d 397
e669ddde 398bool wxWebViewIE::CanGoForward() const
74af0b13
SL
399{
400 if(m_historyEnabled)
22ca10fa 401 return m_historyPosition != static_cast<int>(m_historyList.size()) - 1;
74af0b13
SL
402 else
403 return false;
61b98a2d
SL
404}
405
c13d6ac1 406void wxWebViewIE::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
61b98a2d 407{
74af0b13
SL
408 int pos = -1;
409 for(unsigned int i = 0; i < m_historyList.size(); i++)
410 {
3e7968c2
SL
411 //We compare the actual pointers to find the correct item
412 if(m_historyList[i].get() == item.get())
74af0b13
SL
413 pos = i;
414 }
1d7d04d7 415 wxASSERT_MSG(pos != static_cast<int>(m_historyList.size()),
22ca10fa 416 "invalid history item");
74af0b13 417 m_historyLoadingFromList = true;
4d0dddc7 418 LoadURL(item->GetUrl());
74af0b13
SL
419 m_historyPosition = pos;
420}
61b98a2d 421
c13d6ac1 422wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetBackwardHistory()
5cbda74b 423{
c13d6ac1 424 wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
5cbda74b
SL
425 //As we don't have std::copy or an iterator constructor in the wxwidgets
426 //native vector we construct it by hand
427 for(int i = 0; i < m_historyPosition; i++)
428 {
429 backhist.push_back(m_historyList[i]);
430 }
431 return backhist;
432}
433
c13d6ac1 434wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewIE::GetForwardHistory()
5cbda74b 435{
c13d6ac1 436 wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
5cbda74b
SL
437 //As we don't have std::copy or an iterator constructor in the wxwidgets
438 //native vector we construct it by hand
22ca10fa 439 for(int i = m_historyPosition + 1; i < static_cast<int>(m_historyList.size()); i++)
5cbda74b
SL
440 {
441 forwardhist.push_back(m_historyList[i]);
442 }
443 return forwardhist;
444}
445
74af0b13
SL
446void wxWebViewIE::GoBack()
447{
3e7968c2 448 LoadHistoryItem(m_historyList[m_historyPosition - 1]);
74af0b13
SL
449}
450
451void wxWebViewIE::GoForward()
452{
3e7968c2 453 LoadHistoryItem(m_historyList[m_historyPosition + 1]);
61b98a2d
SL
454}
455
456void wxWebViewIE::Stop()
457{
7fbc727b 458 m_ie.CallMethod("Stop");
61b98a2d
SL
459}
460
74af0b13
SL
461void wxWebViewIE::ClearHistory()
462{
463 m_historyList.clear();
464 m_historyPosition = -1;
465}
466
467void wxWebViewIE::EnableHistory(bool enable)
468{
469 m_historyEnabled = enable;
470 m_historyList.clear();
471 m_historyPosition = -1;
472}
61b98a2d
SL
473
474void wxWebViewIE::Reload(wxWebViewReloadFlags flags)
475{
7aa18fc7
SL
476 VARIANTARG level;
477 VariantInit(&level);
478 V_VT(&level) = VT_I2;
61b98a2d 479
7aa18fc7 480 switch(flags)
61b98a2d 481 {
7aa18fc7
SL
482 case wxWEB_VIEW_RELOAD_DEFAULT:
483 V_I2(&level) = REFRESH_NORMAL;
484 break;
485 case wxWEB_VIEW_RELOAD_NO_CACHE:
486 V_I2(&level) = REFRESH_COMPLETELY;
487 break;
488 default:
489 wxFAIL_MSG("Unexpected reload type");
61b98a2d
SL
490 }
491
7aa18fc7 492 m_webBrowser->Refresh2(&level);
61b98a2d
SL
493}
494
495bool wxWebViewIE::IsOfflineMode()
496{
497 wxVariant out = m_ie.GetProperty("Offline");
498
499 wxASSERT(out.GetType() == "bool");
500
501 return out.GetBool();
502}
503
504void wxWebViewIE::SetOfflineMode(bool offline)
505{
506 // FIXME: the wxWidgets docs do not really document what the return
507 // parameter of PutProperty is
8acbf08b
SL
508#if wxDEBUG_LEVEL
509 const bool success =
510#endif
511 m_ie.PutProperty("Offline", (offline ?
512 VARIANT_TRUE :
513 VARIANT_FALSE));
61b98a2d
SL
514 wxASSERT(success);
515}
516
e669ddde 517bool wxWebViewIE::IsBusy() const
60eabdbe 518{
61b98a2d
SL
519 if (m_isBusy) return true;
520
521 wxVariant out = m_ie.GetProperty("Busy");
522
523 wxASSERT(out.GetType() == "bool");
524
525 return out.GetBool();
526}
527
e669ddde 528wxString wxWebViewIE::GetCurrentURL() const
61b98a2d
SL
529{
530 wxVariant out = m_ie.GetProperty("LocationURL");
531
532 wxASSERT(out.GetType() == "string");
533 return out.GetString();
534}
535
e669ddde 536wxString wxWebViewIE::GetCurrentTitle() const
61b98a2d 537{
f40f8e17 538 wxCOMPtr<IHTMLDocument2> document(GetDocument());
7fbc727b 539
e81ef297
SL
540 if(document)
541 {
542 BSTR title;
543 document->get_nameProp(&title);
e81ef297
SL
544 return wxString(title);
545 }
546 else
547 {
548 return "";
549 }
61b98a2d
SL
550}
551
e669ddde 552bool wxWebViewIE::CanCut() const
4681a3ea
SL
553{
554 return CanExecCommand("Cut");
555}
556
e669ddde 557bool wxWebViewIE::CanCopy() const
4681a3ea
SL
558{
559 return CanExecCommand("Copy");
560}
34326da7 561
e669ddde 562bool wxWebViewIE::CanPaste() const
4681a3ea
SL
563{
564 return CanExecCommand("Paste");
565}
566
567void wxWebViewIE::Cut()
568{
569 ExecCommand("Cut");
570}
571
572void wxWebViewIE::Copy()
573{
574 ExecCommand("Copy");
575}
576
577void wxWebViewIE::Paste()
578{
579 ExecCommand("Paste");
580}
581
e669ddde 582bool wxWebViewIE::CanUndo() const
97e49559
SL
583{
584 return CanExecCommand("Undo");
585}
34326da7 586
e669ddde 587bool wxWebViewIE::CanRedo() const
97e49559
SL
588{
589 return CanExecCommand("Redo");
590}
591
592void wxWebViewIE::Undo()
593{
594 ExecCommand("Undo");
595}
596
597void wxWebViewIE::Redo()
598{
599 ExecCommand("Redo");
600}
601
66ac0400
SL
602long wxWebViewIE::Find(const wxString& text, int flags)
603{
58f513e9 604#if !defined(__MINGW32__) && !defined(__VISUALC6__)
66ac0400
SL
605 //If the text is empty then we clear.
606 if(text.IsEmpty())
607 {
608 ClearSelection();
609 if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
610 {
611 FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
612 }
613 FindClear();
614 return wxNOT_FOUND;
615 }
616 //Have we done this search before?
617 if(m_findText == text)
618 {
619 //Just do a highlight?
620 if((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) != (m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT))
621 {
622 m_findFlags = flags;
623 if(!m_findPointers.empty())
624 {
625 FindInternal(m_findText, m_findFlags, ((flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT) == 0 ? wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT : 0));
626 }
627 return m_findPosition;
628 }
629 else if(((m_findFlags & wxWEB_VIEW_FIND_ENTIRE_WORD) == (flags & wxWEB_VIEW_FIND_ENTIRE_WORD)) && ((m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE) == (flags&wxWEB_VIEW_FIND_MATCH_CASE)))
630 {
631 m_findFlags = flags;
632 return FindNext(((flags & wxWEB_VIEW_FIND_BACKWARDS) ? -1 : 1));
633 }
634 }
635 //Remove old highlight if any.
636 if(m_findFlags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
637 {
638 FindInternal(m_findText, (m_findFlags &~ wxWEB_VIEW_FIND_HIGHLIGHT_RESULT), wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT);
639 }
640 //Reset find variables.
641 FindClear();
642 ClearSelection();
643 m_findText = text;
644 m_findFlags = flags;
645 //find the text and return count.
646 FindInternal(text, flags, wxWEB_VIEW_FIND_ADD_POINTERS);
647 return m_findPointers.empty() ? wxNOT_FOUND : m_findPointers.size();
58f513e9
SL
648#else
649 return wxNOT_FOUND;
650#endif
66ac0400
SL
651}
652
c7cbe308
SL
653void wxWebViewIE::SetEditable(bool enable)
654{
f40f8e17 655 wxCOMPtr<IHTMLDocument2> document(GetDocument());
7fbc727b 656
e81ef297
SL
657 if(document)
658 {
659 if( enable )
660 document->put_designMode(SysAllocString(L"On"));
661 else
662 document->put_designMode(SysAllocString(L"Off"));
663
e81ef297 664 }
c7cbe308
SL
665}
666
e669ddde 667bool wxWebViewIE::IsEditable() const
c7cbe308 668{
f40f8e17 669 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
670
671 if(document)
672 {
673 BSTR mode;
674 document->get_designMode(&mode);
e81ef297
SL
675 if(wxString(mode) == "On")
676 return true;
677 else
678 return false;
679 }
c7cbe308 680 else
e81ef297 681 {
c7cbe308 682 return false;
e81ef297 683 }
c7cbe308
SL
684}
685
63a65070
SL
686void wxWebViewIE::SelectAll()
687{
688 ExecCommand("SelectAll");
689}
690
e669ddde 691bool wxWebViewIE::HasSelection() const
63a65070 692{
f40f8e17 693 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
694
695 if(document)
7fbc727b 696 {
f40f8e17 697 wxCOMPtr<IHTMLSelectionObject> selection;
e81ef297
SL
698 wxString sel;
699 HRESULT hr = document->get_selection(&selection);
700 if(SUCCEEDED(hr))
701 {
702 BSTR type;
703 selection->get_type(&type);
704 sel = wxString(type);
e81ef297 705 }
e81ef297
SL
706 return sel != "None";
707 }
708 else
709 {
710 return false;
7fbc727b 711 }
63a65070
SL
712}
713
714void wxWebViewIE::DeleteSelection()
715{
716 ExecCommand("Delete");
717}
718
e669ddde 719wxString wxWebViewIE::GetSelectedText() const
c9355a3d 720{
f40f8e17 721 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
722
723 if(document)
c9355a3d 724 {
f40f8e17 725 wxCOMPtr<IHTMLSelectionObject> selection;
e81ef297
SL
726 wxString selected;
727 HRESULT hr = document->get_selection(&selection);
c9355a3d
SL
728 if(SUCCEEDED(hr))
729 {
f40f8e17 730 wxCOMPtr<IDispatch> disrange;
e81ef297 731 hr = selection->createRange(&disrange);
c9355a3d
SL
732 if(SUCCEEDED(hr))
733 {
f40f8e17 734 wxCOMPtr<IHTMLTxtRange> range;
e81ef297
SL
735 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
736 if(SUCCEEDED(hr))
737 {
738 BSTR text;
739 range->get_text(&text);
740 selected = wxString(text);
e81ef297 741 }
c9355a3d 742 }
c9355a3d 743 }
e81ef297
SL
744 return selected;
745 }
746 else
747 {
748 return "";
c9355a3d 749 }
c9355a3d
SL
750}
751
e669ddde 752wxString wxWebViewIE::GetSelectedSource() const
0fe8a1b6 753{
f40f8e17 754 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
755
756 if(document)
0fe8a1b6 757 {
f40f8e17 758 wxCOMPtr<IHTMLSelectionObject> selection;
e81ef297
SL
759 wxString selected;
760 HRESULT hr = document->get_selection(&selection);
0fe8a1b6
SL
761 if(SUCCEEDED(hr))
762 {
f40f8e17 763 wxCOMPtr<IDispatch> disrange;
e81ef297 764 hr = selection->createRange(&disrange);
0fe8a1b6
SL
765 if(SUCCEEDED(hr))
766 {
f40f8e17 767 wxCOMPtr<IHTMLTxtRange> range;
e81ef297
SL
768 hr = disrange->QueryInterface(IID_IHTMLTxtRange, (void**)&range);
769 if(SUCCEEDED(hr))
770 {
771 BSTR text;
772 range->get_htmlText(&text);
773 selected = wxString(text);
e81ef297 774 }
0fe8a1b6 775 }
0fe8a1b6 776 }
e81ef297
SL
777 return selected;
778 }
779 else
780 {
781 return "";
0fe8a1b6 782 }
0fe8a1b6
SL
783}
784
41933aa5
SL
785void wxWebViewIE::ClearSelection()
786{
f40f8e17 787 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
788
789 if(document)
41933aa5 790 {
f40f8e17 791 wxCOMPtr<IHTMLSelectionObject> selection;
e81ef297
SL
792 wxString selected;
793 HRESULT hr = document->get_selection(&selection);
794 if(SUCCEEDED(hr))
795 {
796 selection->empty();
e81ef297 797 }
41933aa5 798 }
41933aa5
SL
799}
800
e669ddde 801wxString wxWebViewIE::GetPageText() const
241b769f 802{
f40f8e17 803 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
804
805 if(document)
241b769f 806 {
e81ef297 807 wxString text;
f40f8e17 808 wxCOMPtr<IHTMLElement> body;
e81ef297
SL
809 HRESULT hr = document->get_body(&body);
810 if(SUCCEEDED(hr))
811 {
812 BSTR out;
813 body->get_innerText(&out);
814 text = wxString(out);
e81ef297 815 }
e81ef297
SL
816 return text;
817 }
818 else
819 {
820 return "";
241b769f 821 }
241b769f
SL
822}
823
c9ccc09c
SL
824void wxWebViewIE::RunScript(const wxString& javascript)
825{
f40f8e17 826 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
827
828 if(document)
c9ccc09c 829 {
f40f8e17 830 wxCOMPtr<IHTMLWindow2> window;
e81ef297
SL
831 wxString language = "javascript";
832 HRESULT hr = document->get_parentWindow(&window);
833 if(SUCCEEDED(hr))
834 {
835 VARIANT level;
836 VariantInit(&level);
837 V_VT(&level) = VT_EMPTY;
838 window->execScript(SysAllocString(javascript.wc_str()),
839 SysAllocString(language.wc_str()),
840 &level);
841 }
c9ccc09c 842 }
c9ccc09c
SL
843}
844
7d8d6163 845void wxWebViewIE::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
29365629 846{
e924e848
SL
847 wxDynamicLibrary urlMon(wxT("urlmon.dll"));
848 if(urlMon.HasSymbol(wxT("CoInternetGetSession")))
29365629 849 {
f559d1a2 850 typedef HRESULT (WINAPI *CoInternetGetSession_t)(DWORD, wxIInternetSession**, DWORD);
e924e848
SL
851 wxDYNLIB_FUNCTION(CoInternetGetSession_t, CoInternetGetSession, urlMon);
852
853 ClassFactory* cf = new ClassFactory(handler);
f559d1a2 854 wxIInternetSession* session;
e924e848
SL
855 HRESULT res = (*pfnCoInternetGetSession)(0, &session, 0);
856 if(FAILED(res))
857 {
858 wxFAIL_MSG("Could not retrive internet session");
859 }
29365629 860
c9a828e7
VZ
861 HRESULT hr = session->RegisterNameSpace(cf, CLSID_FileProtocol,
862 handler->GetName().wc_str(),
863 0, NULL, 0);
e924e848
SL
864 if(FAILED(hr))
865 {
866 wxFAIL_MSG("Could not register protocol");
867 }
39498710 868 m_factories.push_back(cf);
e924e848
SL
869 }
870 else
29365629 871 {
e924e848 872 wxFAIL_MSG("urlmon does not contain CoInternetGetSession");
29365629
SL
873 }
874}
875
e669ddde 876bool wxWebViewIE::CanExecCommand(wxString command) const
4681a3ea 877{
f40f8e17 878 wxCOMPtr<IHTMLDocument2> document(GetDocument());
7fbc727b 879
e81ef297
SL
880 if(document)
881 {
882 VARIANT_BOOL enabled;
883
884 document->queryCommandEnabled(SysAllocString(command.wc_str()), &enabled);
e81ef297
SL
885
886 return (enabled == VARIANT_TRUE);
887 }
888 else
889 {
890 return false;
891 }
4681a3ea 892
4681a3ea
SL
893}
894
895void wxWebViewIE::ExecCommand(wxString command)
896{
f40f8e17 897 wxCOMPtr<IHTMLDocument2> document(GetDocument());
e81ef297
SL
898
899 if(document)
900 {
901 document->execCommand(SysAllocString(command.wc_str()), VARIANT_FALSE, VARIANT(), NULL);
e81ef297 902 }
617227c3 903}
4681a3ea 904
f40f8e17 905wxCOMPtr<IHTMLDocument2> wxWebViewIE::GetDocument() const
617227c3 906{
f40f8e17
SL
907 wxCOMPtr<IDispatch> dispatch;
908 wxCOMPtr<IHTMLDocument2> document;
e81ef297 909 HRESULT result = m_webBrowser->get_Document(&dispatch);
601d0ba7 910 if(dispatch && SUCCEEDED(result))
e81ef297 911 {
e81ef297 912 //document is set to null automatically if the interface isn't supported
f40f8e17 913 dispatch->QueryInterface(IID_IHTMLDocument2, (void**)&document);
e81ef297 914 }
f40f8e17 915 return document;
4681a3ea
SL
916}
917
66ac0400
SL
918bool wxWebViewIE::IsElementVisible(IHTMLElement* elm)
919{
58f513e9 920#if !defined(__MINGW32__) && !defined(__VISUALC6__)
66ac0400
SL
921 IHTMLCurrentStyle* style;
922 IHTMLElement *elm1 = elm;
923 IHTMLElement2 *elm2;
924 BSTR tmp_bstr;
925 bool is_visible = true;
926 //This method is not perfect but it does discover most of the hidden elements.
927 //so if a better solution is found, then please do improve.
928 while(elm1)
929 {
930 if(SUCCEEDED(elm1->QueryInterface(IID_IHTMLElement2, (void**) &elm2)))
931 {
932 if(SUCCEEDED(elm2->get_currentStyle(&style)))
933 {
934 //Check if the object has the style display:none.
935 if((style->get_display(&tmp_bstr) != S_OK) ||
936 (tmp_bstr != NULL && (_wcsicmp(tmp_bstr, L"none") == 0)))
937 {
938 is_visible = false;
939 }
940 //Check if the object has the style visibility:hidden.
941 if(is_visible && (style->get_visibility(&tmp_bstr) != S_OK) ||
942 (tmp_bstr != NULL && _wcsicmp(tmp_bstr, L"hidden") == 0))
943 {
944 is_visible = false;
945 }
946 style->Release();
947 }
948 elm2->Release();
949 }
950
951 //Lets check the object's parent element.
952 IHTMLElement* parent;
953 if(is_visible && SUCCEEDED(elm1->get_parentElement(&parent)))
954 {
955 elm1->Release();
956 elm1 = parent;
957 }
958 else
959 {
960 elm1->Release();
961 break;
962 }
963 }
964 return is_visible;
58f513e9
SL
965#else
966 return false;
967#endif
66ac0400
SL
968}
969
970void wxWebViewIE::FindInternal(const wxString& text, int flags, int internal_flag)
971{
58f513e9 972#if !defined(__MINGW32__) && !defined(__VISUALC6__)
66ac0400
SL
973 IMarkupServices *pIMS;
974 IMarkupContainer *pIMC;
975 IMarkupPointer *ptrBegin, *ptrEnd;
976 IHTMLElement* elm;
977 long find_flag = 0;
978 IHTMLDocument2 *document = GetDocument();
979 //This function does the acutal work.
980 if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices, (void **)&pIMS)))
981 {
982 if(SUCCEEDED(document->QueryInterface(IID_IMarkupContainer, (void **)&pIMC)))
983 {
984 BSTR attr_bstr = SysAllocString(L"style=\"background-color:#ffff00\"");
985 BSTR text_bstr = SysAllocString(text.wc_str());
986 pIMS->CreateMarkupPointer(&ptrBegin);
987 pIMS->CreateMarkupPointer(&ptrEnd);
988
989 ptrBegin->SetGravity(POINTER_GRAVITY_Right);
990 ptrBegin->MoveToContainer(pIMC, TRUE);
991 //Create the find flag from the wx one.
992 if(flags & wxWEB_VIEW_FIND_ENTIRE_WORD)
993 {
994 find_flag |= FINDTEXT_WHOLEWORD;
995 }
996 if(flags & wxWEB_VIEW_FIND_MATCH_CASE)
997 {
998 find_flag |= FINDTEXT_MATCHCASE;
999 }
1000
1001 //A little speed-up to avoid to re-alloc in the positions vector.
1002 if(text.Len() < 3 && m_findPointers.capacity() < 500)
1003 {
1004 m_findPointers.reserve(text.Len() == 1 ? 1000 : 500);
1005 }
1006
1007 while(ptrBegin->FindText(text_bstr, find_flag, ptrEnd, NULL) == S_OK)
1008 {
1009 if(ptrBegin->CurrentScope(&elm) == S_OK)
1010 {
1011 if(IsElementVisible(elm))
1012 {
1013 //Highlight the word if the flag was set.
1014 if(flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT)
1015 {
1016 IHTMLElement* pFontEl;
1017 pIMS->CreateElement(TAGID_FONT, attr_bstr, &pFontEl);
1018 pIMS->InsertElement(pFontEl, ptrBegin, ptrEnd);
1019 }
1020 if(internal_flag & wxWEB_VIEW_FIND_REMOVE_HIGHLIGHT)
1021 {
1022 IHTMLElement* pFontEl;
1023 ptrBegin->CurrentScope(&pFontEl);
1024 pIMS->RemoveElement(pFontEl);
1025 pFontEl->Release();
1026 }
1027 if(internal_flag & wxWEB_VIEW_FIND_ADD_POINTERS)
1028 {
1029 IMarkupPointer *cptrBegin, *cptrEnd;
1030 pIMS->CreateMarkupPointer(&cptrBegin);
1031 pIMS->CreateMarkupPointer(&cptrEnd);
1032 cptrBegin->MoveToPointer(ptrBegin);
1033 cptrEnd->MoveToPointer(ptrEnd);
1034 m_findPointers.push_back(wxFindPointers(cptrBegin,cptrEnd));
1035 }
1036 }
1037 elm->Release();
1038 }
1039 ptrBegin->MoveToPointer(ptrEnd);
1040 }
1041 //Clean up.
1042 SysFreeString(text_bstr);
1043 SysFreeString(attr_bstr);
1044 pIMC->Release();
1045 ptrBegin->Release();
1046 ptrEnd->Release();
1047 }
1048 pIMS->Release();
1049 }
1050 document->Release();
58f513e9 1051#endif
66ac0400
SL
1052}
1053
1054long wxWebViewIE::FindNext(int direction)
1055{
58f513e9 1056#if !defined(__MINGW32__) && !defined(__VISUALC6__)
66ac0400
SL
1057 //Don't bother if we have no pointers set.
1058 if(m_findPointers.empty())
1059 {
1060 return wxNOT_FOUND;
1061 }
1062 //Manage the find position and do some checks.
1063 if(direction > 0)
1064 {
1065 m_findPosition++;
1066 }
1067 else
1068 {
1069 m_findPosition--;
1070 }
1071
1072 if(m_findPosition >= (signed)m_findPointers.size())
1073 {
1074 if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
1075 {
1076 m_findPosition = 0;
1077 }
1078 else
1079 {
1080 m_findPosition--;
1081 return wxNOT_FOUND;
1082 }
1083 }
1084 else if(m_findPosition < 0)
1085 {
1086 if(m_findFlags & wxWEB_VIEW_FIND_WRAP)
1087 {
1088 m_findPosition = m_findPointers.size()-1;
1089 }
1090 else
1091 {
1092 m_findPosition++;
1093 return wxNOT_FOUND;
1094 }
1095 }
1096 //some variables to use later on.
1097 IHTMLElement *body_element;
1098 IHTMLBodyElement *body;
1099 IHTMLTxtRange *range = NULL;
1100 IMarkupServices *pIMS;
1101 IHTMLDocument2 *document = GetDocument();
1102 long ret = -1;
1103 //Now try to create a range from the body.
1104 if(SUCCEEDED(document->get_body(&body_element)))
1105 {
1106 if(SUCCEEDED(body_element->QueryInterface(IID_IHTMLBodyElement,(void**)&body)))
1107 {
1108 if(SUCCEEDED(body->createTextRange(&range)))
1109 {
1110 //So far so good, now we try to position our find pointers.
1111 if(SUCCEEDED(document->QueryInterface(IID_IMarkupServices,(void **)&pIMS)))
1112 {
1113 IMarkupPointer *begin = m_findPointers[m_findPosition].begin, *end = m_findPointers[m_findPosition].end;
1114 if(pIMS->MoveRangeToPointers(begin,end,range) == S_OK && range->select() == S_OK)
1115 {
1116 ret = m_findPosition;
1117 }
1118 pIMS->Release();
1119 }
1120 range->Release();
1121 }
1122 body->Release();
1123 }
1124 body_element->Release();
1125 }
1126 document->Release();
1127 return ret;
58f513e9
SL
1128#else
1129 return wxNOT_FOUND;
1130#endif
66ac0400
SL
1131}
1132
1133void wxWebViewIE::FindClear()
1134{
58f513e9 1135#if !defined(__MINGW32__) && !defined(__VISUALC6__)
66ac0400
SL
1136 //Reset find variables.
1137 m_findText.Empty();
1138 m_findFlags = wxWEB_VIEW_FIND_DEFAULT;
1139 m_findPosition = -1;
1140
1141 //The m_findPointers contains pointers for the found text.
1142 //Since it uses ref counting we call release on the pointers first
1143 //before we remove them from the vector. In other words do not just
1144 //remove elements from m_findPointers without calling release first
1145 //or you will get a memory leak.
1146 size_t count = m_findPointers.size();
1147 for(size_t i = 0; i < count; i++)
1148 {
1149 m_findPointers[i].begin->Release();
1150 m_findPointers[i].end->Release();
1151 }
1152 m_findPointers.clear();
58f513e9 1153#endif
66ac0400
SL
1154}
1155
9447a0d6
SL
1156bool wxWebViewIE::EnableControlFeature(long flag, bool enable)
1157{
1158#if wxUSE_DYNLIB_CLASS
1159
1160 wxDynamicLibrary urlMon(wxT("urlmon.dll"));
34326da7
SL
1161 if( urlMon.IsLoaded() &&
1162 urlMon.HasSymbol("CoInternetSetFeatureEnabled") &&
9447a0d6
SL
1163 urlMon.HasSymbol("CoInternetIsFeatureEnabled"))
1164 {
1165 typedef HRESULT (WINAPI *CoInternetSetFeatureEnabled_t)(DWORD, DWORD, BOOL);
1166 typedef HRESULT (WINAPI *CoInternetIsFeatureEnabled_t)(DWORD, DWORD);
1167
1168 wxDYNLIB_FUNCTION(CoInternetSetFeatureEnabled_t, CoInternetSetFeatureEnabled, urlMon);
1169 wxDYNLIB_FUNCTION(CoInternetIsFeatureEnabled_t, CoInternetIsFeatureEnabled, urlMon);
1170
1171 HRESULT hr = (*pfnCoInternetIsFeatureEnabled)(flag,
1172 0x2 /* SET_FEATURE_ON_PROCESS */);
1173 if((hr == S_OK && enable) || (hr == S_FALSE && !enable))
1174 return true;
1175
1176 hr = (*pfnCoInternetSetFeatureEnabled)(flag,
1177 0x2/* SET_FEATURE_ON_PROCESS */,
1178 (enable ? TRUE : FALSE));
1179 if ( FAILED(hr) )
1180 {
1181 wxLogApiError(wxT("CoInternetSetFeatureEnabled"), hr);
1182 return false;
1183 }
1184 return true;
1185 }
1186 return false;
1187#else
1188 wxUnusedVar(flag);
1189 wxUnusedVar(enable);
1190 return false;
1191#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
1192}
1193
61b98a2d
SL
1194void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt)
1195{
1196 if (m_webBrowser == NULL) return;
1197
1198 switch (evt.GetDispatchId())
1199 {
1200 case DISPID_BEFORENAVIGATE2:
1201 {
1202 m_isBusy = true;
1203
1204 wxString url = evt[1].GetString();
1205 wxString target = evt[3].GetString();
1206
04fa04d8 1207 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
3225a4b8 1208 GetId(), url, target);
e11b9a6b
SL
1209
1210 //skip empty javascript events.
1211 if(url == "javascript:\"\"" && target.IsEmpty())
1212 {
1213 event.Veto();
1214 }
1215 else
1216 {
1217 event.SetEventObject(this);
1218 HandleWindowEvent(event);
1219 }
61b98a2d 1220
3225a4b8 1221 if (!event.IsAllowed())
61b98a2d
SL
1222 {
1223 wxActiveXEventNativeMSW* nativeParams =
1224 evt.GetNativeParameters();
1225 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE;
1226 }
1227
1228 // at this point, either the navigation event has been cancelled
1229 // and we're not busy, either it was accepted and IWebBrowser2's
1230 // Busy property will be true; so we don't need our override
1231 // flag anymore.
1232 m_isBusy = false;
1233
1234 break;
1235 }
1236
1237 case DISPID_NAVIGATECOMPLETE2:
1238 {
1239 wxString url = evt[1].GetString();
1240 // TODO: set target parameter if possible
1241 wxString target = wxEmptyString;
04fa04d8 1242 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
3225a4b8 1243 GetId(), url, target);
61b98a2d
SL
1244 event.SetEventObject(this);
1245 HandleWindowEvent(event);
1246 break;
1247 }
1248
1249 case DISPID_PROGRESSCHANGE:
1250 {
1251 // download progress
1252 break;
1253 }
1254
1255 case DISPID_DOCUMENTCOMPLETE:
1256 {
3ee442ff
SL
1257 //Only send a complete even if we are actually finished, this brings
1258 //the event in to line with webkit
1259 READYSTATE rs;
1260 m_webBrowser->get_ReadyState( &rs );
1261 if(rs != READYSTATE_COMPLETE)
1262 break;
1263
61b98a2d 1264 wxString url = evt[1].GetString();
113e0a92
SL
1265
1266 //As we are complete we also add to the history list, but not if the
1267 //page is not the main page, ie it is a subframe
60eabdbe 1268 //We also have to check if we are loading a file:// url, if so we
f239a200
SL
1269 //need to change the comparison as ie passes back a different style
1270 //of url
60eabdbe
VZ
1271 if(m_historyEnabled && !m_historyLoadingFromList &&
1272 (url == GetCurrentURL() ||
1273 (GetCurrentURL().substr(0, 4) == "file" &&
f239a200 1274 wxFileSystem::URLToFileName(GetCurrentURL()).GetFullPath() == url)))
74af0b13
SL
1275 {
1276 //If we are not at the end of the list, then erase everything
1277 //between us and the end before adding the new page
22ca10fa 1278 if(m_historyPosition != static_cast<int>(m_historyList.size()) - 1)
74af0b13
SL
1279 {
1280 m_historyList.erase(m_historyList.begin() + m_historyPosition + 1,
1281 m_historyList.end());
1282 }
c13d6ac1 1283 wxSharedPtr<wxWebViewHistoryItem> item(new wxWebViewHistoryItem(url, GetCurrentTitle()));
74af0b13
SL
1284 m_historyList.push_back(item);
1285 m_historyPosition++;
1286 }
1287 //Reset as we are done now
1288 m_historyLoadingFromList = false;
66ac0400
SL
1289 //Reset the find values.
1290 FindClear();
61b98a2d
SL
1291 // TODO: set target parameter if possible
1292 wxString target = wxEmptyString;
04fa04d8 1293 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(),
3225a4b8 1294 url, target);
61b98a2d
SL
1295 event.SetEventObject(this);
1296 HandleWindowEvent(event);
1297 break;
1298 }
1299
1300 case DISPID_STATUSTEXTCHANGE:
1301 {
1302 break;
1303 }
1304
1305 case DISPID_TITLECHANGE:
1306 {
153530af
SL
1307 wxString title = evt[0].GetString();
1308
04fa04d8 1309 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
3225a4b8 1310 GetId(), GetCurrentURL(), "");
153530af
SL
1311 event.SetString(title);
1312 event.SetEventObject(this);
1313 HandleWindowEvent(event);
61b98a2d
SL
1314 break;
1315 }
1316
1317 case DISPID_NAVIGATEERROR:
1318 {
04fa04d8 1319 wxWebViewNavigationError errorType = wxWEB_NAV_ERR_OTHER;
61b98a2d
SL
1320 wxString errorCode = "?";
1321 switch (evt[3].GetLong())
1322 {
1323 case INET_E_INVALID_URL: // (0x800C0002L or -2146697214)
1324 errorCode = "INET_E_INVALID_URL";
1325 errorType = wxWEB_NAV_ERR_REQUEST;
1326 break;
1327 case INET_E_NO_SESSION: // (0x800C0003L or -2146697213)
1328 errorCode = "INET_E_NO_SESSION";
1329 errorType = wxWEB_NAV_ERR_CONNECTION;
1330 break;
1331 case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212)
1332 errorCode = "INET_E_CANNOT_CONNECT";
1333 errorType = wxWEB_NAV_ERR_CONNECTION;
1334 break;
1335 case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211)
1336 errorCode = "INET_E_RESOURCE_NOT_FOUND";
1337 errorType = wxWEB_NAV_ERR_NOT_FOUND;
1338 break;
1339 case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210)
1340 errorCode = "INET_E_OBJECT_NOT_FOUND";
1341 errorType = wxWEB_NAV_ERR_NOT_FOUND;
1342 break;
1343 case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209)
1344 errorCode = "INET_E_DATA_NOT_AVAILABLE";
1345 errorType = wxWEB_NAV_ERR_NOT_FOUND;
1346 break;
1347 case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208)
1348 errorCode = "INET_E_DOWNLOAD_FAILURE";
1349 errorType = wxWEB_NAV_ERR_CONNECTION;
1350 break;
1351 case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207)
1352 errorCode = "INET_E_AUTHENTICATION_REQUIRED";
1353 errorType = wxWEB_NAV_ERR_AUTH;
1354 break;
1355 case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206)
1356 errorCode = "INET_E_NO_VALID_MEDIA";
1357 errorType = wxWEB_NAV_ERR_REQUEST;
1358 break;
1359 case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205)
1360 errorCode = "INET_E_CONNECTION_TIMEOUT";
1361 errorType = wxWEB_NAV_ERR_CONNECTION;
1362 break;
1363 case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204)
1364 errorCode = "INET_E_INVALID_REQUEST";
1365 errorType = wxWEB_NAV_ERR_REQUEST;
1366 break;
1367 case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203)
1368 errorCode = "INET_E_UNKNOWN_PROTOCOL";
1369 errorType = wxWEB_NAV_ERR_REQUEST;
1370 break;
1371 case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202)
1372 errorCode = "INET_E_SECURITY_PROBLEM";
1373 errorType = wxWEB_NAV_ERR_SECURITY;
1374 break;
1375 case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201)
1376 errorCode = "INET_E_CANNOT_LOAD_DATA";
1377 errorType = wxWEB_NAV_ERR_OTHER;
1378 break;
1379 case INET_E_CANNOT_INSTANTIATE_OBJECT:
1380 // CoCreateInstance will return an error code if this happens,
1381 // we'll handle this above.
1382 return;
1383 break;
1384 case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196)
1385 errorCode = "INET_E_REDIRECT_FAILED";
1386 errorType = wxWEB_NAV_ERR_OTHER;
1387 break;
1388 case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195)
1389 errorCode = "INET_E_REDIRECT_TO_DIR";
1390 errorType = wxWEB_NAV_ERR_REQUEST;
1391 break;
1392 case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194)
1393 errorCode = "INET_E_CANNOT_LOCK_REQUEST";
1394 errorType = wxWEB_NAV_ERR_OTHER;
1395 break;
1396 case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193)
1397 errorCode = "INET_E_USE_EXTEND_BINDING";
1398 errorType = wxWEB_NAV_ERR_OTHER;
1399 break;
1400 case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192)
1401 errorCode = "INET_E_TERMINATED_BIND";
1402 errorType = wxWEB_NAV_ERR_OTHER;
1403 break;
1404 case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191)
1405 errorCode = "INET_E_INVALID_CERTIFICATE";
1406 errorType = wxWEB_NAV_ERR_CERTIFICATE;
1407 break;
1408 case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960)
1409 errorCode = "INET_E_CODE_DOWNLOAD_DECLINED";
1410 errorType = wxWEB_NAV_ERR_USER_CANCELLED;
1411 break;
1412 case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704)
1413 // cancel request cancelled...
1414 errorCode = "INET_E_RESULT_DISPATCHED";
1415 errorType = wxWEB_NAV_ERR_OTHER;
1416 break;
1417 case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448)
1418 errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE";
1419 errorType = wxWEB_NAV_ERR_SECURITY;
1420 break;
1421 case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY:
1422 errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY";
1423 errorType = wxWEB_NAV_ERR_SECURITY;
1424 break;
1425 case INET_E_CODE_INSTALL_SUPPRESSED:
1426 errorCode = "INET_E_CODE_INSTALL_SUPPRESSED";
1427 errorType = wxWEB_NAV_ERR_SECURITY;
1428 break;
1429 }
1430
1431 wxString url = evt[1].GetString();
1432 wxString target = evt[2].GetString();
04fa04d8 1433 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(),
3225a4b8 1434 url, target);
61b98a2d
SL
1435 event.SetEventObject(this);
1436 event.SetInt(errorType);
1437 event.SetString(errorCode);
1438 HandleWindowEvent(event);
1439 break;
1440 }
853b6cd0 1441 case DISPID_NEWWINDOW3:
61b98a2d 1442 {
853b6cd0
SL
1443 wxString url = evt[4].GetString();
1444
04fa04d8 1445 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
3225a4b8 1446 GetId(), url, wxEmptyString);
853b6cd0
SL
1447 event.SetEventObject(this);
1448 HandleWindowEvent(event);
1449
d676fb21
SL
1450 //We always cancel this event otherwise an Internet Exporer window
1451 //is opened for the url
1452 wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters();
1453 *V_BOOLREF(&nativeParams->pDispParams->rgvarg[3]) = VARIANT_TRUE;
be19c556
SL
1454 break;
1455 }
61b98a2d
SL
1456 }
1457
1458 evt.Skip();
1459}
1460
7d8d6163 1461VirtualProtocol::VirtualProtocol(wxSharedPtr<wxWebViewHandler> handler)
7d3f6b4d 1462{
7d3f6b4d 1463 m_file = NULL;
29365629 1464 m_handler = handler;
7d3f6b4d
SL
1465}
1466
9f194b9d
SL
1467BEGIN_IID_TABLE(VirtualProtocol)
1468 ADD_IID(Unknown)
1469 ADD_RAW_IID(wxIID_IInternetProtocolRoot)
1470 ADD_RAW_IID(wxIID_IInternetProtocol)
1471END_IID_TABLE;
7d3f6b4d 1472
9f194b9d 1473IMPLEMENT_IUNKNOWN_METHODS(VirtualProtocol)
7d3f6b4d 1474
a9c5eac9 1475HRESULT STDMETHODCALLTYPE VirtualProtocol::Start(LPCWSTR szUrl, wxIInternetProtocolSink *pOIProtSink,
f559d1a2 1476 wxIInternetBindInfo *pOIBindInfo, DWORD grfPI,
0995b9dc 1477 HANDLE_PTR dwReserved)
7d3f6b4d 1478{
0995b9dc
SL
1479 wxUnusedVar(szUrl);
1480 wxUnusedVar(pOIBindInfo);
1481 wxUnusedVar(grfPI);
1482 wxUnusedVar(dwReserved);
7d3f6b4d 1483 m_protocolSink = pOIProtSink;
60eabdbe 1484
29365629
SL
1485 //We get the file itself from the protocol handler
1486 m_file = m_handler->GetFile(szUrl);
1487
7d3f6b4d
SL
1488
1489 if(!m_file)
1490 return INET_E_RESOURCE_NOT_FOUND;
1491
1492 //We return the stream length for current and total size as we can always
1493 //read the whole file from the stream
666f73c4 1494 wxFileOffset length = m_file->GetStream()->GetLength();
f559d1a2
VZ
1495 m_protocolSink->ReportData(wxBSCF_FIRSTDATANOTIFICATION |
1496 wxBSCF_DATAFULLYAVAILABLE |
1497 wxBSCF_LASTDATANOTIFICATION,
666f73c4 1498 length, length);
60eabdbe 1499 return S_OK;
7d3f6b4d
SL
1500}
1501
a9c5eac9 1502HRESULT STDMETHODCALLTYPE VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRead)
7d3f6b4d
SL
1503{
1504 //If the file is null we return false to indicte it is finished
60eabdbe 1505 if(!m_file)
7d3f6b4d
SL
1506 return S_FALSE;
1507
1508 wxStreamError err = m_file->GetStream()->Read(pv, cb).GetLastError();
1509 *pcbRead = m_file->GetStream()->LastRead();
1510
1511 if(err == wxSTREAM_NO_ERROR)
1512 {
1513 if(*pcbRead < cb)
1514 {
1515 wxDELETE(m_file);
1516 m_protocolSink->ReportResult(S_OK, 0, NULL);
1517 }
1518 //As we are not eof there is more data
1519 return S_OK;
1520 }
1521 else if(err == wxSTREAM_EOF)
1522 {
1523 wxDELETE(m_file);
1524 m_protocolSink->ReportResult(S_OK, 0, NULL);
1525 //We are eof and so finished
1526 return S_OK;
1527 }
1528 else if(err == wxSTREAM_READ_ERROR)
1529 {
1530 wxDELETE(m_file);
1531 return INET_E_DOWNLOAD_FAILURE;
1532 }
0995b9dc
SL
1533 else
1534 {
1535 //Dummy return to surpress a compiler warning
1536 wxFAIL;
1537 return INET_E_DOWNLOAD_FAILURE;
1538 }
7d3f6b4d
SL
1539}
1540
9f194b9d
SL
1541BEGIN_IID_TABLE(ClassFactory)
1542 ADD_IID(Unknown)
1543 ADD_IID(ClassFactory)
1544END_IID_TABLE;
1545
1546IMPLEMENT_IUNKNOWN_METHODS(ClassFactory)
1547
a9c5eac9 1548HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid,
7d3f6b4d
SL
1549 void ** ppvObject)
1550{
60eabdbe 1551 if (pUnkOuter)
7d3f6b4d 1552 return CLASS_E_NOAGGREGATION;
29365629 1553 VirtualProtocol* vp = new VirtualProtocol(m_handler);
7d3f6b4d
SL
1554 vp->AddRef();
1555 HRESULT hr = vp->QueryInterface(riid, ppvObject);
1556 vp->Release();
1557 return hr;
1558
60eabdbe 1559}
7d3f6b4d
SL
1560
1561STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
1562{
0995b9dc
SL
1563 wxUnusedVar(fLock);
1564 return S_OK;
7d3f6b4d
SL
1565}
1566
34326da7 1567wxIEContainer::wxIEContainer(wxWindow *parent, REFIID iid, IUnknown *pUnk,
accc94d5
SL
1568 DocHostUIHandler* uiHandler) :
1569 wxActiveXContainer(parent,iid,pUnk)
1570{
1571 m_uiHandler = uiHandler;
1572}
1573
1574wxIEContainer::~wxIEContainer()
1575{
1576}
1577
34326da7 1578bool wxIEContainer::QueryClientSiteInterface(REFIID iid, void **_interface,
accc94d5
SL
1579 const char *&desc)
1580{
1581 if (m_uiHandler && IsEqualIID(iid, wxIID_IDocHostUIHandler))
1582 {
1583 *_interface = (IUnknown *) (wxIDocHostUIHandler *) m_uiHandler;
1584 desc = "IDocHostUIHandler";
1585 return true;
1586 }
1587 return false;
1588}
1589
a9c5eac9 1590HRESULT wxSTDCALL DocHostUIHandler::ShowContextMenu(DWORD dwID, POINT *ppt,
34326da7 1591 IUnknown *pcmdtReserved,
accc94d5
SL
1592 IDispatch *pdispReserved)
1593{
1594 wxUnusedVar(dwID);
1595 wxUnusedVar(ppt);
1596 wxUnusedVar(pcmdtReserved);
1597 wxUnusedVar(pdispReserved);
1598 return E_NOTIMPL;
1599}
1600
a9c5eac9 1601HRESULT wxSTDCALL DocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo)
accc94d5 1602{
34326da7 1603 //don't show 3d border and enable themes.
accc94d5
SL
1604 pInfo->dwFlags = pInfo->dwFlags | DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_THEME;
1605 return S_OK;
1606}
1607
a9c5eac9 1608HRESULT wxSTDCALL DocHostUIHandler::ShowUI(DWORD dwID,
34326da7 1609 IOleInPlaceActiveObject *pActiveObject,
accc94d5
SL
1610 IOleCommandTarget *pCommandTarget,
1611 IOleInPlaceFrame *pFrame,
1612 IOleInPlaceUIWindow *pDoc)
1613{
1614 wxUnusedVar(dwID);
1615 wxUnusedVar(pActiveObject);
1616 wxUnusedVar(pCommandTarget);
1617 wxUnusedVar(pFrame);
1618 wxUnusedVar(pDoc);
1619 return S_FALSE;
1620}
1621
a9c5eac9 1622HRESULT wxSTDCALL DocHostUIHandler::HideUI(void)
accc94d5
SL
1623{
1624 return E_NOTIMPL;
1625}
1626
a9c5eac9 1627HRESULT wxSTDCALL DocHostUIHandler::UpdateUI(void)
accc94d5
SL
1628{
1629 return E_NOTIMPL;
1630}
1631
a9c5eac9 1632HRESULT wxSTDCALL DocHostUIHandler::EnableModeless(BOOL fEnable)
accc94d5
SL
1633{
1634 wxUnusedVar(fEnable);
1635 return E_NOTIMPL;
1636}
1637
a9c5eac9 1638HRESULT wxSTDCALL DocHostUIHandler::OnDocWindowActivate(BOOL fActivate)
accc94d5
SL
1639{
1640 wxUnusedVar(fActivate);
1641 return E_NOTIMPL;
1642}
1643
a9c5eac9 1644HRESULT wxSTDCALL DocHostUIHandler::OnFrameWindowActivate(BOOL fActivate)
accc94d5
SL
1645{
1646 wxUnusedVar(fActivate);
1647 return E_NOTIMPL;
1648}
1649
a9c5eac9 1650HRESULT wxSTDCALL DocHostUIHandler::ResizeBorder(LPCRECT prcBorder,
accc94d5
SL
1651 IOleInPlaceUIWindow *pUIWindow,
1652 BOOL fFrameWindow)
1653{
1654 wxUnusedVar(prcBorder);
1655 wxUnusedVar(pUIWindow);
1656 wxUnusedVar(fFrameWindow);
1657 return E_NOTIMPL;
1658}
1659
a9c5eac9 1660HRESULT wxSTDCALL DocHostUIHandler::TranslateAccelerator(LPMSG lpMsg,
accc94d5
SL
1661 const GUID *pguidCmdGroup,
1662 DWORD nCmdID)
1663{
1664 if(lpMsg && lpMsg->message == WM_KEYDOWN)
1665 {
1666 //control is down?
1667 if((GetKeyState(VK_CONTROL) & 0x8000 ))
1668 {
e5f9b4ae
VZ
1669 //skip the accelerators used by the control
1670 switch(lpMsg->wParam)
accc94d5 1671 {
e5f9b4ae
VZ
1672 case 'F':
1673 case 'L':
1674 case 'N':
1675 case 'O':
1676 case 'P':
1677 return S_OK;
accc94d5
SL
1678 }
1679 }
1680 //skip F5
1681 if(lpMsg->wParam == VK_F5)
1682 {
1683 return S_OK;
1684 }
1685 }
1686
1687 wxUnusedVar(pguidCmdGroup);
1688 wxUnusedVar(nCmdID);
1689 return E_NOTIMPL;
1690}
1691
a9c5eac9 1692HRESULT wxSTDCALL DocHostUIHandler::GetOptionKeyPath(LPOLESTR *pchKey,DWORD dw)
accc94d5
SL
1693{
1694 wxUnusedVar(pchKey);
1695 wxUnusedVar(dw);
1696 return E_NOTIMPL;
1697}
1698
a9c5eac9 1699HRESULT wxSTDCALL DocHostUIHandler::GetDropTarget(IDropTarget *pDropTarget,
accc94d5
SL
1700 IDropTarget **ppDropTarget)
1701{
1702 wxUnusedVar(pDropTarget);
1703 wxUnusedVar(ppDropTarget);
1704 return E_NOTIMPL;
1705}
1706
a9c5eac9 1707HRESULT wxSTDCALL DocHostUIHandler::GetExternal(IDispatch **ppDispatch)
accc94d5
SL
1708{
1709 wxUnusedVar(ppDispatch);
1710 return E_NOTIMPL;
1711}
1712
a9c5eac9 1713HRESULT wxSTDCALL DocHostUIHandler::TranslateUrl(DWORD dwTranslate,
accc94d5
SL
1714 OLECHAR *pchURLIn,
1715 OLECHAR **ppchURLOut)
1716{
1717 wxUnusedVar(dwTranslate);
1718 wxUnusedVar(pchURLIn);
1719 wxUnusedVar(ppchURLOut);
1720 return E_NOTIMPL;
1721}
1722
a9c5eac9 1723HRESULT wxSTDCALL DocHostUIHandler::FilterDataObject(IDataObject *pDO, IDataObject **ppDORet)
accc94d5
SL
1724{
1725 wxUnusedVar(pDO);
1726 wxUnusedVar(ppDORet);
1727 return E_NOTIMPL;
1728}
1729
1730BEGIN_IID_TABLE(DocHostUIHandler)
1731 ADD_IID(Unknown)
1732 ADD_RAW_IID(wxIID_IDocHostUIHandler)
1733END_IID_TABLE;
1734
1735IMPLEMENT_IUNKNOWN_METHODS(DocHostUIHandler)
1736
9d2f31db 1737#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE