]> git.saurik.com Git - wxWidgets.git/blame - wxPython/contrib/iewin/IEHtmlWin.cpp
use static_cast<> in event table macros for type safety (patch 843206)
[wxWidgets.git] / wxPython / contrib / iewin / IEHtmlWin.cpp
CommitLineData
c731eb47
RD
1#include "IEHtmlWin.h"
2#include <wx/strconv.h>
d3b55102 3#include <wx/string.h>
c731eb47
RD
4#include <wx/event.h>
5#include <wx/listctrl.h>
d3b55102 6#include <wx/mstream.h>
c731eb47
RD
7#include <oleidl.h>
8#include <winerror.h>
9#include <exdispid.h>
10#include <exdisp.h>
11#include <olectl.h>
12#include <Mshtml.h>
13#include <sstream>
14using namespace std;
15
16DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2);
17DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_NEWWINDOW2);
18DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE);
19DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE);
20DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE);
21DEFINE_EVENT_TYPE(wxEVT_COMMAND_MSHTML_TITLECHANGE);
22
23IMPLEMENT_DYNAMIC_CLASS(wxMSHTMLEvent, wxNotifyEvent);
24
25
26//////////////////////////////////////////////////////////////////////
27BEGIN_EVENT_TABLE(wxIEHtmlWin, wxActiveX)
28END_EVENT_TABLE()
29
30class FS_DWebBrowserEvents2 : public IDispatch
31{
32private:
33 DECLARE_OLE_UNKNOWN(FS_DWebBrowserEvents2);
34
35
36 wxIEHtmlWin *m_iewin;
37
38public:
39 FS_DWebBrowserEvents2(wxIEHtmlWin *iewin) : m_iewin(iewin) {}
1e4a197e 40 virtual ~FS_DWebBrowserEvents2()
c731eb47
RD
41 {
42 }
43
44 //IDispatch
45 STDMETHODIMP GetIDsOfNames(REFIID r, OLECHAR** o, unsigned int i, LCID l, DISPID* d)
1e4a197e 46 {
c731eb47
RD
47 return E_NOTIMPL;
48 };
49
50 STDMETHODIMP GetTypeInfo(unsigned int i, LCID l, ITypeInfo** t)
1e4a197e 51 {
c731eb47
RD
52 return E_NOTIMPL;
53 };
54
55 STDMETHODIMP GetTypeInfoCount(unsigned int* i)
1e4a197e 56 {
c731eb47
RD
57 return E_NOTIMPL;
58 };
59
60 void Post(WXTYPE etype, wxString text, long l1 = 0, long l2 = 0)
61 {
62 if (! m_iewin || ! m_iewin->GetParent())
63 return;
64
65 wxMSHTMLEvent event;
66 event.SetId(m_iewin->GetId());
67 event.SetEventType(etype);
68 event.m_text1 = text;
69 event.m_long1 = l1;
70 event.m_long2 = l2;
71
72 m_iewin->GetParent()->AddPendingEvent(event);
73 };
74
1e4a197e 75 bool Process(WXTYPE etype, wxString text = wxEmptyString, long l1 = 0, long l2 = 0)
c731eb47
RD
76 {
77 if (! m_iewin || ! m_iewin->GetParent())
78 return true;
79
80 wxMSHTMLEvent event;
81 event.SetId(m_iewin->GetId());
82 event.SetEventType(etype);
83 event.m_text1 = text;
84 event.m_long1 = l1;
85 event.m_long2 = l2;
86
87 m_iewin->GetParent()->ProcessEvent(event);
88
89 return event.IsAllowed();
90 };
91
92 wxString GetStrArg(VARIANT& v)
93 {
94 VARTYPE vt = v.vt & ~VT_BYREF;
95
96 if (vt == VT_VARIANT)
97 return GetStrArg(*v.pvarVal);
98 else if (vt == VT_BSTR)
99 {
100 if (v.vt & VT_BYREF)
101 return (v.pbstrVal ? *v.pbstrVal : L"");
102 else
103 return v.bstrVal;
104 }
105 else
1e4a197e 106 return wxEmptyString;
c731eb47
RD
107 };
108
109#define STR_ARG(arg) GetStrArg(pDispParams->rgvarg[arg])
110
111#define LONG_ARG(arg)\
112 (pDispParams->rgvarg[arg].lVal)
113
114
115 STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
116 WORD wFlags, DISPPARAMS * pDispParams,
117 VARIANT * pVarResult, EXCEPINFO * pExcepInfo,
118 unsigned int * puArgErr)
1e4a197e 119 {
c731eb47
RD
120 if (wFlags & DISPATCH_PROPERTYGET)
121 return E_NOTIMPL;
122
123 switch (dispIdMember)
124 {
125 case DISPID_BEFORENAVIGATE2:
126 if (Process(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, STR_ARG(5)))
127 *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
1e4a197e 128 else
c731eb47
RD
129 *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
130 break;
131
132 case DISPID_NEWWINDOW2:
133 if (Process(wxEVT_COMMAND_MSHTML_NEWWINDOW2))
134 *pDispParams->rgvarg->pboolVal = VARIANT_FALSE;
1e4a197e 135 else
c731eb47
RD
136 *pDispParams->rgvarg->pboolVal = VARIANT_TRUE;
137 break;
138
139 case DISPID_PROGRESSCHANGE:
1e4a197e 140 Post(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, wxEmptyString, LONG_ARG(1), LONG_ARG(0));
c731eb47 141 break;
1e4a197e 142
c731eb47
RD
143 case DISPID_DOCUMENTCOMPLETE:
144 Post(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, STR_ARG(0));
145 break;
146
147 case DISPID_STATUSTEXTCHANGE:
148 Post(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, STR_ARG(0));
149 break;
150
151 case DISPID_TITLECHANGE:
152 Post(wxEVT_COMMAND_MSHTML_TITLECHANGE, STR_ARG(0));
153 break;
154 }
155
156 return S_OK;
157 }
158};
159
160#undef STR_ARG
161
162DEFINE_OLE_TABLE(FS_DWebBrowserEvents2)
163 OLE_IINTERFACE(IUnknown)
164 OLE_INTERFACE(DIID_DWebBrowserEvents2, DWebBrowserEvents2)
165END_OLE_TABLE;
166
167
168static const CLSID CLSID_MozillaBrowser =
169{ 0x1339B54C, 0x3453, 0x11D2,
170 { 0x93, 0xB9, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00 } };
172
173
83a73288 174//#define PROGID "Shell.Explorer"
c731eb47 175#define PROGID CLSID_WebBrowser
83a73288 176//#define PROGID CLSID_MozillaBrowser
c731eb47 177//#define PROGID CLSID_HTMLDocument
83a73288
RD
178//#define PROGID "MSCAL.Calendar"
179//#define PROGID "WordPad.Document.1"
180//#define PROGID "SoftwareFX.ChartFX.20"
c731eb47 181
d7abf017 182wxIEHtmlWin::wxIEHtmlWin(wxWindow * parent, wxWindowID id,
83a73288
RD
183 const wxPoint& pos,
184 const wxSize& size,
185 long style,
1e4a197e 186 const wxString& name) :
83a73288 187 wxActiveX(parent, PROGID, id, pos, size, style, name)
c731eb47
RD
188{
189 SetupBrowser();
190}
191
83a73288 192
c731eb47
RD
193wxIEHtmlWin::~wxIEHtmlWin()
194{
195}
196
197void wxIEHtmlWin::SetupBrowser()
198{
199 HRESULT hret;
200
201 // Get IWebBrowser2 Interface
202 hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
203 assert(SUCCEEDED(hret));
204
205 // Web Browser Events
206 FS_DWebBrowserEvents2 *events = new FS_DWebBrowserEvents2(this);
207 hret = ConnectAdvise(DIID_DWebBrowserEvents2, events);
208 if (! SUCCEEDED(hret))
209 delete events;
210
211 // web browser setup
212 m_webBrowser->put_MenuBar(VARIANT_FALSE);
213 m_webBrowser->put_AddressBar(VARIANT_FALSE);
214 m_webBrowser->put_StatusBar(VARIANT_FALSE);
215 m_webBrowser->put_ToolBar(VARIANT_FALSE);
216
217 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
218 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
219
220 m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
221}
222
223
224void wxIEHtmlWin::SetEditMode(bool seton)
225{
226 m_bAmbientUserMode = ! seton;
227 AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
228};
229
230bool wxIEHtmlWin::GetEditMode()
231{
232 return ! m_bAmbientUserMode;
233};
234
235
236void wxIEHtmlWin::SetCharset(wxString charset)
237{
238 // HTML Document ?
239 IDispatch *pDisp = NULL;
240 HRESULT hret = m_webBrowser->get_Document(&pDisp);
241 wxAutoOleInterface<IDispatch> disp(pDisp);
242
243 if (disp.Ok())
244 {
245 wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
246 if (doc.Ok())
d3b55102
RD
247 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
248 //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
c731eb47
RD
249 };
250};
251
252
253class IStreamAdaptorBase : public IStream
254{
255private:
256 DECLARE_OLE_UNKNOWN(IStreamAdaptorBase);
257
258public:
259 IStreamAdaptorBase() {}
260 virtual ~IStreamAdaptorBase() {}
261
262 // ISequentialStream
263 HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) = 0;
264 HRESULT STDMETHODCALLTYPE Write(const void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
265
266 // IStream
267 HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER __RPC_FAR *plibNewPosition) {return E_NOTIMPL;}
268 HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) {return E_NOTIMPL;}
269 HRESULT STDMETHODCALLTYPE CopyTo(IStream __RPC_FAR *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER __RPC_FAR *pcbRead, ULARGE_INTEGER __RPC_FAR *pcbWritten) {return E_NOTIMPL;}
270 HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) {return E_NOTIMPL;}
271 HRESULT STDMETHODCALLTYPE Revert(void) {return E_NOTIMPL;}
272 HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
273 HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {return E_NOTIMPL;}
274 HRESULT STDMETHODCALLTYPE Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) {return E_NOTIMPL;}
275 HRESULT STDMETHODCALLTYPE Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) {return E_NOTIMPL;}
276};
277
278DEFINE_OLE_TABLE(IStreamAdaptorBase)
279 OLE_IINTERFACE(IUnknown)
280 OLE_IINTERFACE(ISequentialStream)
281 OLE_IINTERFACE(IStream)
282END_OLE_TABLE;
283
284class IStreamAdaptor : public IStreamAdaptorBase
285{
286private:
287 istream *m_is;
288
289public:
1e4a197e
RD
290
291 IStreamAdaptor(istream *is) : IStreamAdaptorBase(), m_is(is)
c731eb47
RD
292 {
293 wxASSERT(m_is != NULL);
294 }
1e4a197e 295 ~IStreamAdaptor()
c731eb47
RD
296 {
297 delete m_is;
298 }
299
300 // ISequentialStream
301 HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
302 {
303 m_is->read((char *) pv, cb);
304 if (pcbRead)
305 *pcbRead = m_is->gcount();
306
307 return S_OK;
308 };
309};
310
d3b55102
RD
311class IwxStreamAdaptor : public IStreamAdaptorBase
312{
313private:
314 wxInputStream *m_is;
315
316public:
1e4a197e
RD
317
318 IwxStreamAdaptor(wxInputStream *is) : IStreamAdaptorBase(), m_is(is)
d3b55102
RD
319 {
320 wxASSERT(m_is != NULL);
321 }
1e4a197e 322 ~IwxStreamAdaptor()
d3b55102
RD
323 {
324 delete m_is;
325 }
326
327 // ISequentialStream
328 HRESULT STDMETHODCALLTYPE Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
329 {
330 m_is->Read((char *) pv, cb);
331 if (pcbRead)
332 *pcbRead = m_is->LastRead();
333
334 return S_OK;
335 };
336};
c731eb47
RD
337
338void wxIEHtmlWin::LoadUrl(const wxString& url)
339{
340 VARIANTARG navFlag, targetFrame, postData, headers;
1e4a197e 341 navFlag.vt = VT_EMPTY;
c731eb47
RD
342 navFlag.vt = VT_I2;
343 navFlag.iVal = navNoReadFromCache;
344 targetFrame.vt = VT_EMPTY;
345 postData.vt = VT_EMPTY;
346 headers.vt = VT_EMPTY;
347
348 HRESULT hret = 0;
1e4a197e
RD
349 hret = m_webBrowser->Navigate((BSTR) (const wchar_t *) url.wc_str(wxConvUTF8),
350 &navFlag, &targetFrame, &postData, &headers);
c731eb47
RD
351};
352
d3b55102
RD
353class wxOwnedMemInputStream : public wxMemoryInputStream
354{
355public:
356 char *m_data;
357
358 wxOwnedMemInputStream(char *data, size_t len) :
359 wxMemoryInputStream(data, len), m_data(data)
360 {}
1e4a197e 361 ~wxOwnedMemInputStream()
d3b55102
RD
362 {
363 free(m_data);
364 }
365};
c731eb47
RD
366
367bool wxIEHtmlWin::LoadString(wxString html)
368{
d3b55102
RD
369 char *data = NULL;
370 size_t len = html.length();
371#ifdef UNICODE
372 len *= 2;
373#endif
374 data = (char *) malloc(len);
375 memcpy(data, html.c_str(), len);
376 return LoadStream(new wxOwnedMemInputStream(data, len));
c731eb47
RD
377};
378
d3b55102 379bool wxIEHtmlWin::LoadStream(IStreamAdaptorBase *pstrm)
c731eb47 380{
c731eb47
RD
381 wxAutoOleInterface<IStream> strm(pstrm);
382
383 // Document Interface
384 IDispatch *pDisp = NULL;
385 HRESULT hret = m_webBrowser->get_Document(&pDisp);
386 if (! pDisp)
387 return false;
388 wxAutoOleInterface<IDispatch> disp(pDisp);
389
390
391 // get IPersistStreamInit
392 wxAutoOleInterface<IPersistStreamInit>
393 pPersistStreamInit(IID_IPersistStreamInit, disp);
394
395 if (pPersistStreamInit.Ok())
396 {
397 HRESULT hr = pPersistStreamInit->InitNew();
398 if (SUCCEEDED(hr))
399 hr = pPersistStreamInit->Load(strm);
c731eb47 400
83a73288
RD
401 return SUCCEEDED(hr);
402 }
403 else
404 return false;
c731eb47
RD
405};
406
d3b55102
RD
407bool wxIEHtmlWin::LoadStream(istream *is)
408{
409 // wrap reference around stream
410 IStreamAdaptor *pstrm = new IStreamAdaptor(is);
411 pstrm->AddRef();
412
413 return LoadStream(pstrm);
414};
415
416bool wxIEHtmlWin::LoadStream(wxInputStream *is)
417{
418 // wrap reference around stream
419 IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
420 pstrm->AddRef();
421
422 return LoadStream(pstrm);
423};
424
425
c731eb47
RD
426bool wxIEHtmlWin::GoBack()
427{
428 HRESULT hret = 0;
429 hret = m_webBrowser->GoBack();
430 return hret == S_OK;
431}
432
433bool wxIEHtmlWin::GoForward()
434{
435 HRESULT hret = 0;
436 hret = m_webBrowser->GoForward();
437 return hret == S_OK;
438}
439
440bool wxIEHtmlWin::GoHome()
441{
442 HRESULT hret = 0;
443 hret = m_webBrowser->GoHome();
444 return hret == S_OK;
445}
446
447bool wxIEHtmlWin::GoSearch()
448{
449 HRESULT hret = 0;
450 hret = m_webBrowser->GoSearch();
451 return hret == S_OK;
452}
453
454bool wxIEHtmlWin::Refresh(wxIEHtmlRefreshLevel level)
455{
456 VARIANTARG levelArg;
457 HRESULT hret = 0;
458
459 levelArg.vt = VT_I2;
460 levelArg.iVal = level;
461 hret = m_webBrowser->Refresh2(&levelArg);
462 return hret == S_OK;
463}
464
465bool wxIEHtmlWin::Stop()
466{
467 HRESULT hret = 0;
468 hret = m_webBrowser->Stop();
469 return hret == S_OK;
470}
471
83a73288 472
c731eb47
RD
473///////////////////////////////////////////////////////////////////////////////
474
475static wxAutoOleInterface<IHTMLSelectionObject> GetSelObject(IOleObject *oleObject)
476{
477 // Query for IWebBrowser interface
478 wxAutoOleInterface<IWebBrowser2> wb(IID_IWebBrowser2, oleObject);
479 if (! wb.Ok())
480 return wxAutoOleInterface<IHTMLSelectionObject>();
481
482 IDispatch *iDisp = NULL;
483 HRESULT hr = wb->get_Document(&iDisp);
484 if (hr != S_OK)
485 return wxAutoOleInterface<IHTMLSelectionObject>();
486
487 // Query for Document Interface
488 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
489 iDisp->Release();
490
491 if (! hd.Ok())
492 return wxAutoOleInterface<IHTMLSelectionObject>();
493
494 IHTMLSelectionObject *_so = NULL;
495 hr = hd->get_selection(&_so);
496
497 // take ownership of selection object
498 wxAutoOleInterface<IHTMLSelectionObject> so(_so);
499
500 return so;
501};
502
503static wxAutoOleInterface<IHTMLTxtRange> GetSelRange(IOleObject *oleObject)
504{
505 wxAutoOleInterface<IHTMLTxtRange> tr;
506
507 wxAutoOleInterface<IHTMLSelectionObject> so(GetSelObject(oleObject));
508 if (! so)
509 return tr;
510
511 IDispatch *iDisp = NULL;
512 HRESULT hr = so->createRange(&iDisp);
513 if (hr != S_OK)
514 return tr;
515
516 // Query for IHTMLTxtRange interface
517 tr.QueryInterface(IID_IHTMLTxtRange, iDisp);
518 iDisp->Release();
519 return tr;
520};
521
522
523wxString wxIEHtmlWin::GetStringSelection(bool asHTML)
524{
525 wxAutoOleInterface<IHTMLTxtRange> tr(GetSelRange(m_oleObject));
526 if (! tr)
1e4a197e 527 return wxEmptyString;
c731eb47
RD
528
529 BSTR text = NULL;
530 HRESULT hr = E_FAIL;
1e4a197e 531
c731eb47
RD
532 if (asHTML)
533 hr = tr->get_htmlText(&text);
534 else
535 hr = tr->get_text(&text);
536 if (hr != S_OK)
1e4a197e 537 return wxEmptyString;
c731eb47
RD
538
539 wxString s = text;
540 SysFreeString(text);
541
542 return s;
543};
544
545wxString wxIEHtmlWin::GetText(bool asHTML)
546{
547 if (! m_webBrowser.Ok())
1e4a197e 548 return wxEmptyString;
c731eb47
RD
549
550 // get document dispatch interface
551 IDispatch *iDisp = NULL;
552 HRESULT hr = m_webBrowser->get_Document(&iDisp);
553 if (hr != S_OK)
1e4a197e 554 return wxEmptyString;
c731eb47
RD
555
556 // Query for Document Interface
557 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
558 iDisp->Release();
559
560 if (! hd.Ok())
1e4a197e 561 return wxEmptyString;
c731eb47
RD
562
563 // get body element
564 IHTMLElement *_body = NULL;
565 hd->get_body(&_body);
566 if (! _body)
1e4a197e 567 return wxEmptyString;
c731eb47
RD
568 wxAutoOleInterface<IHTMLElement> body(_body);
569
570 // get inner text
571 BSTR text = NULL;
572 hr = E_FAIL;
1e4a197e 573
c731eb47
RD
574 if (asHTML)
575 hr = body->get_innerHTML(&text);
576 else
577 hr = body->get_innerText(&text);
578 if (hr != S_OK)
1e4a197e 579 return wxEmptyString;
c731eb47
RD
580
581 wxString s = text;
582 SysFreeString(text);
583
1e4a197e
RD
584 return s;
585};