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