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