]> git.saurik.com Git - wxWidgets.git/blob - wxPython/contrib/activex/wxie/IEHtmlWin.cpp
fix for self.root == None
[wxWidgets.git] / wxPython / contrib / activex / wxie / IEHtmlWin.cpp
1 /*
2 wxActiveX Library Licence, Version 3
3 ====================================
4
5 Copyright (C) 2003 Lindsay Mathieson [, ...]
6
7 Everyone is permitted to copy and distribute verbatim copies
8 of this licence document, but changing it is not allowed.
9
10 wxActiveX LIBRARY LICENCE
11 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
13 This library is free software; you can redistribute it and/or modify it
14 under the terms of the GNU Library General Public Licence as published by
15 the Free Software Foundation; either version 2 of the Licence, or (at
16 your option) any later version.
17
18 This library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
21 General Public Licence for more details.
22
23 You should have received a copy of the GNU Library General Public Licence
24 along with this software, usually in a file named COPYING.LIB. If not,
25 write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
26 Boston, MA 02111-1307 USA.
27
28 EXCEPTION NOTICE
29
30 1. As a special exception, the copyright holders of this library give
31 permission for additional uses of the text contained in this release of
32 the library as licenced under the wxActiveX Library Licence, applying
33 either version 3 of the Licence, or (at your option) any later version of
34 the Licence as published by the copyright holders of version 3 of the
35 Licence document.
36
37 2. The exception is that you may use, copy, link, modify and distribute
38 under the user's own terms, binary object code versions of works based
39 on the Library.
40
41 3. If you copy code from files distributed under the terms of the GNU
42 General Public Licence or the GNU Library General Public Licence into a
43 copy of this library, as this licence permits, the exception does not
44 apply to the code that you add in this way. To avoid misleading anyone as
45 to the status of such modified files, you must delete this exception
46 notice from such code and/or adjust the licensing conditions notice
47 accordingly.
48
49 4. If you write modifications of your own for this library, it is your
50 choice whether to permit this exception to apply to your modifications.
51 If you do not wish that, you must delete the exception notice from such
52 code and/or adjust the licensing conditions notice accordingly.
53 */
54
55 #include "IEHtmlWin.h"
56 #include <wx/strconv.h>
57 #include <wx/string.h>
58 #include <wx/event.h>
59 #include <wx/listctrl.h>
60 #include <wx/mstream.h>
61 #include <oleidl.h>
62 #include <winerror.h>
63 #include <exdispid.h>
64 #include <exdisp.h>
65 #include <olectl.h>
66 #include <Mshtml.h>
67 #include <sstream>
68 #include <IEHtmlStream.h>
69 using namespace std;
70
71
72
73 //////////////////////////////////////////////////////////////////////
74 // Stream adapters and such
75
76 HRESULT STDMETHODCALLTYPE IStreamAdaptorBase::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead)
77 {
78 if (prepend.size() > 0)
79 {
80 int n = min(prepend.size(), cb);
81 prepend.copy((char *) pv, n);
82 prepend = prepend.substr(n);
83 if (pcbRead)
84 *pcbRead = n;
85
86 return S_OK;
87 };
88
89 int rc = Read((char *) pv, cb);
90 if (pcbRead)
91 *pcbRead = rc;
92
93 return S_OK;
94 };
95
96 DEFINE_OLE_TABLE(IStreamAdaptorBase)
97 OLE_IINTERFACE(IUnknown)
98 OLE_IINTERFACE(ISequentialStream)
99 OLE_IINTERFACE(IStream)
100 END_OLE_TABLE;
101
102
103 IStreamAdaptor::IStreamAdaptor(istream *is)
104 : IStreamAdaptorBase(), m_is(is)
105 {
106 wxASSERT(m_is != NULL);
107 }
108
109 IStreamAdaptor::~IStreamAdaptor()
110 {
111 delete m_is;
112 }
113
114 int IStreamAdaptor::Read(char *buf, int cb)
115 {
116 m_is->read(buf, cb);
117 return m_is->gcount();
118 }
119
120
121 IwxStreamAdaptor::IwxStreamAdaptor(wxInputStream *is)
122 : IStreamAdaptorBase(), m_is(is)
123 {
124 wxASSERT(m_is != NULL);
125 }
126 IwxStreamAdaptor::~IwxStreamAdaptor()
127 {
128 delete m_is;
129 }
130
131 // ISequentialStream
132 int IwxStreamAdaptor::Read(char *buf, int cb)
133 {
134 m_is->Read(buf, cb);
135 return m_is->LastRead();
136 };
137
138 wxOwnedMemInputStream::wxOwnedMemInputStream(char *data, size_t len)
139 : wxMemoryInputStream(data, len), m_data(data)
140 {}
141
142 wxOwnedMemInputStream::~wxOwnedMemInputStream()
143 {
144 free(m_data);
145 }
146
147
148 //////////////////////////////////////////////////////////////////////
149 BEGIN_EVENT_TABLE(wxIEHtmlWin, wxActiveX)
150 END_EVENT_TABLE()
151
152
153 static const CLSID CLSID_MozillaBrowser =
154 { 0x1339B54C, 0x3453, 0x11D2,
155 { 0x93, 0xB9, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00 } };
157
158
159 //#define PROGID "Shell.Explorer"
160 #define PROGID CLSID_WebBrowser
161 //#define PROGID CLSID_MozillaBrowser
162 //#define PROGID CLSID_HTMLDocument
163 //#define PROGID "MSCAL.Calendar"
164 //#define PROGID ""
165 //#define PROGID "SoftwareFX.ChartFX.20"
166
167 wxIEHtmlWin::wxIEHtmlWin(wxWindow * parent, wxWindowID id,
168 const wxPoint& pos,
169 const wxSize& size,
170 long style,
171 const wxString& name) :
172 wxActiveX(parent, PROGID, id, pos, size, style, name)
173 {
174 SetupBrowser();
175 }
176
177
178 wxIEHtmlWin::~wxIEHtmlWin()
179 {
180 }
181
182 void wxIEHtmlWin::SetupBrowser()
183 {
184 HRESULT hret;
185
186 // Get IWebBrowser2 Interface
187 hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
188 assert(SUCCEEDED(hret));
189
190 // web browser setup
191 m_webBrowser->put_MenuBar(VARIANT_FALSE);
192 m_webBrowser->put_AddressBar(VARIANT_FALSE);
193 m_webBrowser->put_StatusBar(VARIANT_FALSE);
194 m_webBrowser->put_ToolBar(VARIANT_FALSE);
195
196 m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
197 m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
198
199 m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
200 }
201
202
203 void wxIEHtmlWin::SetEditMode(bool seton)
204 {
205 m_bAmbientUserMode = ! seton;
206 AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
207 };
208
209 bool wxIEHtmlWin::GetEditMode()
210 {
211 return ! m_bAmbientUserMode;
212 };
213
214
215 void wxIEHtmlWin::SetCharset(const wxString& charset)
216 {
217 // HTML Document ?
218 IDispatch *pDisp = NULL;
219 HRESULT hret = m_webBrowser->get_Document(&pDisp);
220 wxAutoOleInterface<IDispatch> disp(pDisp);
221
222 if (disp.Ok())
223 {
224 wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
225 if (doc.Ok())
226 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
227 //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
228 };
229 };
230
231
232 void wxIEHtmlWin::LoadUrl(const wxString& url)
233 {
234 VARIANTARG navFlag, targetFrame, postData, headers;
235 navFlag.vt = VT_EMPTY;
236 navFlag.vt = VT_I2;
237 navFlag.iVal = navNoReadFromCache;
238 targetFrame.vt = VT_EMPTY;
239 postData.vt = VT_EMPTY;
240 headers.vt = VT_EMPTY;
241
242 HRESULT hret = 0;
243 hret = m_webBrowser->Navigate((BSTR) (const wchar_t *) url.wc_str(wxConvUTF8),
244 &navFlag, &targetFrame, &postData, &headers);
245 };
246
247
248 bool wxIEHtmlWin::LoadString(const wxString& html)
249 {
250 char *data = NULL;
251 size_t len = html.length();
252 #ifdef UNICODE
253 len *= 2;
254 #endif
255 data = (char *) malloc(len);
256 memcpy(data, html.c_str(), len);
257 return LoadStream(new wxOwnedMemInputStream(data, len));
258 };
259
260 bool wxIEHtmlWin::LoadStream(IStreamAdaptorBase *pstrm)
261 {
262 // need to prepend this as poxy MSHTML will not recognise a HTML comment
263 // as starting a html document and treats it as plain text
264 // Does nayone know how to force it to html mode ?
265 pstrm->prepend = "<html>";
266
267 // strip leading whitespace as it can confuse MSHTML
268 wxAutoOleInterface<IStream> strm(pstrm);
269
270 // Document Interface
271 IDispatch *pDisp = NULL;
272 HRESULT hret = m_webBrowser->get_Document(&pDisp);
273 if (! pDisp)
274 return false;
275 wxAutoOleInterface<IDispatch> disp(pDisp);
276
277
278 // get IPersistStreamInit
279 wxAutoOleInterface<IPersistStreamInit>
280 pPersistStreamInit(IID_IPersistStreamInit, disp);
281
282 if (pPersistStreamInit.Ok())
283 {
284 HRESULT hr = pPersistStreamInit->InitNew();
285 if (SUCCEEDED(hr))
286 hr = pPersistStreamInit->Load(strm);
287
288 return SUCCEEDED(hr);
289 }
290 else
291 return false;
292 };
293
294 bool wxIEHtmlWin::LoadStream(istream *is)
295 {
296 // wrap reference around stream
297 IStreamAdaptor *pstrm = new IStreamAdaptor(is);
298 pstrm->AddRef();
299
300 return LoadStream(pstrm);
301 };
302
303 bool wxIEHtmlWin::LoadStream(wxInputStream *is)
304 {
305 // wrap reference around stream
306 IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
307 pstrm->AddRef();
308
309 return LoadStream(pstrm);
310 };
311
312
313 bool wxIEHtmlWin::GoBack()
314 {
315 HRESULT hret = 0;
316 hret = m_webBrowser->GoBack();
317 return hret == S_OK;
318 }
319
320 bool wxIEHtmlWin::GoForward()
321 {
322 HRESULT hret = 0;
323 hret = m_webBrowser->GoForward();
324 return hret == S_OK;
325 }
326
327 bool wxIEHtmlWin::GoHome()
328 {
329 try
330 {
331 CallMethod(_T("GoHome"));
332 return true;
333 }
334 catch(exception&)
335 {
336 return false;
337 };
338 }
339
340 bool wxIEHtmlWin::GoSearch()
341 {
342 HRESULT hret = 0;
343 hret = m_webBrowser->GoSearch();
344 return hret == S_OK;
345 }
346
347 bool wxIEHtmlWin::Refresh(wxIEHtmlRefreshLevel level)
348 {
349 VARIANTARG levelArg;
350 HRESULT hret = 0;
351
352 levelArg.vt = VT_I2;
353 levelArg.iVal = level;
354 hret = m_webBrowser->Refresh2(&levelArg);
355 return hret == S_OK;
356 }
357
358 bool wxIEHtmlWin::Stop()
359 {
360 HRESULT hret = 0;
361 hret = m_webBrowser->Stop();
362 return hret == S_OK;
363 }
364
365
366 ///////////////////////////////////////////////////////////////////////////////
367
368 static wxAutoOleInterface<IHTMLSelectionObject> GetSelObject(IOleObject *oleObject)
369 {
370 // Query for IWebBrowser interface
371 wxAutoOleInterface<IWebBrowser2> wb(IID_IWebBrowser2, oleObject);
372 if (! wb.Ok())
373 return wxAutoOleInterface<IHTMLSelectionObject>();
374
375 IDispatch *iDisp = NULL;
376 HRESULT hr = wb->get_Document(&iDisp);
377 if (hr != S_OK)
378 return wxAutoOleInterface<IHTMLSelectionObject>();
379
380 // Query for Document Interface
381 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
382 iDisp->Release();
383
384 if (! hd.Ok())
385 return wxAutoOleInterface<IHTMLSelectionObject>();
386
387 IHTMLSelectionObject *_so = NULL;
388 hr = hd->get_selection(&_so);
389
390 // take ownership of selection object
391 wxAutoOleInterface<IHTMLSelectionObject> so(_so);
392
393 return so;
394 };
395
396 wxAutoOleInterface<IHTMLTxtRange> wxieGetSelRange(IOleObject *oleObject)
397 {
398 wxAutoOleInterface<IHTMLTxtRange> tr;
399
400 wxAutoOleInterface<IHTMLSelectionObject> so(GetSelObject(oleObject));
401 if (! so)
402 return tr;
403
404 IDispatch *iDisp = NULL;
405 HRESULT hr = so->createRange(&iDisp);
406 if (hr != S_OK)
407 return tr;
408
409 // Query for IHTMLTxtRange interface
410 tr.QueryInterface(IID_IHTMLTxtRange, iDisp);
411 iDisp->Release();
412 return tr;
413 };
414
415
416 wxString wxIEHtmlWin::GetStringSelection(bool asHTML)
417 {
418 wxAutoOleInterface<IHTMLTxtRange> tr(wxieGetSelRange(m_oleObject));
419 if (! tr)
420 return wxEmptyString;
421
422 BSTR text = NULL;
423 HRESULT hr = E_FAIL;
424
425 if (asHTML)
426 hr = tr->get_htmlText(&text);
427 else
428 hr = tr->get_text(&text);
429 if (hr != S_OK)
430 return wxEmptyString;
431
432 wxString s = text;
433 SysFreeString(text);
434
435 return s;
436 };
437
438 wxString wxIEHtmlWin::GetText(bool asHTML)
439 {
440 if (! m_webBrowser.Ok())
441 return wxEmptyString;
442
443 // get document dispatch interface
444 IDispatch *iDisp = NULL;
445 HRESULT hr = m_webBrowser->get_Document(&iDisp);
446 if (hr != S_OK)
447 return wxEmptyString;
448
449 // Query for Document Interface
450 wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
451 iDisp->Release();
452
453 if (! hd.Ok())
454 return wxEmptyString;
455
456 // get body element
457 IHTMLElement *_body = NULL;
458 hd->get_body(&_body);
459 if (! _body)
460 return wxEmptyString;
461 wxAutoOleInterface<IHTMLElement> body(_body);
462
463 // get inner text
464 BSTR text = NULL;
465 hr = E_FAIL;
466
467 if (asHTML)
468 hr = body->get_innerHTML(&text);
469 else
470 hr = body->get_innerText(&text);
471 if (hr != S_OK)
472 return wxEmptyString;
473
474 wxString s = text;
475 SysFreeString(text);
476
477 return s;
478 };