1 /////////////////////////////////////////////////////////////////////////////
 
   3 // Purpose:     ActiveX controls (such as Internet Explorer) in a wxWindow
 
   7 // Created:     18-Mar-2004
 
   9 // Copyright:   (c) 2004 by Total Control Software
 
  10 // Licence:     wxWindows license
 
  11 /////////////////////////////////////////////////////////////////////////////
 
  17 #include "wx/wxPython/wxPython.h"
 
  18 #include "wx/wxPython/pyclasses.h"
 
  19 #include "wx/wxPython/pyistream.h"
 
  21 #include "wxactivex.h"
 
  24 //---------------------------------------------------------------------------
 
  27 %pythoncode { wx = core }
 
  29 MAKE_CONST_WXSTRING_NOSWIG(PanelNameStr);
 
  31 %include _activex_rename.i
 
  34 //---------------------------------------------------------------------------
 
  36 typedef unsigned short  USHORT;
 
  38 typedef long            MEMBERID;
 
  39 typedef unsigned short  VARTYPE;
 
  43 // Since SWIG doesn't support nested classes, we need to fool it a bit
 
  44 // and make them look like global classes.  These defines make the C++ code
 
  45 // know what we are doing.
 
  46 #define wxParamX        wxActiveX::ParamX
 
  47 #define wxFuncX         wxActiveX::FuncX
 
  48 #define wxPropX         wxActiveX::PropX
 
  49 #define wxParamXArray   wxActiveX::ParamXArray
 
  50 #define wxFuncXArray    wxActiveX::FuncXArray
 
  51 #define wxPropXArray    wxActiveX::PropXArray
 
  56 // Some conversion helpers
 
  57 static wxVariant _PyObj2Variant(PyObject* value);
 
  58 static bool  _PyObj2Variant(PyObject* value, wxVariant& wv);
 
  59 static PyObject* _Variant2PyObj(wxVariant& value, bool useNone=False);
 
  60 static wxString  _VARTYPEname(VARTYPE vt);
 
  62 // Check if an exception has been raised  (blocking threads)
 
  63 inline bool wxPyErr_Occurred()
 
  66     bool blocked = wxPyBeginBlockThreads();
 
  67     rval = PyErr_Occurred() != NULL;
 
  68     wxPyEndBlockThreads(blocked);
 
  74 //---------------------------------------------------------------------------
 
  78 "This class wraps the Windows CLSID structure and is used to
 
  79 specify the class of the ActiveX object that is to be created.  A
 
  80 CLSID can be constructed from either a ProgID string, (such as
 
  81 'WordPad.Document.1') or a classID string, (such as
 
  82 '{CA8A9783-280D-11CF-A24D-444553540000}').");
 
  87         CLSID(const wxString& id)
 
  90             CLSID* self = new CLSID;
 
  91             memset(self, 0, sizeof(CLSID));
 
  93             if (id[0] == _T('{')) {
 
  94                 // Looks like a classID string
 
  97                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 103                         (LPOLESTR)(const wchar_t *)id.wc_str(wxConvUTF8),
 
 106             if (result != NOERROR) {
 
 107                 wxPyErr_SetString(PyExc_ValueError, "Not a recognized classID or progID");
 
 114         ~CLSID() { delete self; }
 
 116         wxString GetCLSIDString()
 
 120             if (StringFromCLSID(*self, &s) == S_OK) {
 
 125                 str = _T("Error!");  // TODO: raise exception?
 
 129         wxString GetProgIDString()
 
 133             if (ProgIDFromCLSID(*self, &s) == S_OK) {
 
 138                 str = _T("Error!"); // TODO: raise exception?
 
 143     %pythoncode { def __str__(self):   return self.GetCLSIDString() }
 
 147 //---------------------------------------------------------------------------
 
 150 %define MAKE_ARRAY_WRAPPER(basetype, arrayname)
 
 155         bool __nonzero__()          { return self->size() > 0; }
 
 156         int  __len__()              { return self->size(); }
 
 158         const basetype& __getitem__(int idx) {
 
 159             if ( idx >= 0 && idx < self->size() )
 
 162                 static basetype BadVal;
 
 163                 wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 172 //---------------------------------------------------------------------------
 
 186     %feature("shadow") vt_type_get "vt_type = property(_activex.ParamX_vt_type_get)";
 
 187     %extend { wxString vt_type_get() { return _VARTYPEname(self->vt); } }
 
 189     %feature("shadow") IsIn     "isIn = property(_activex.ParamX_IsIn)";
 
 190     %feature("shadow") IsOut    "isOut = property(_activex.ParamX_IsOut)";
 
 191     %feature("shadow") IsRetVal "isRetVal = property(_activex.ParamX_IsRetVal)";
 
 194     bool IsRetVal() const;
 
 207     wxParamXArray params;
 
 220     %feature("shadow") CanGet "canGet = property(_activex.PropX_CanGet)";
 
 221     %feature("shadow") CanSet "canSet = property(_activex.PropX_CanSet)";
 
 228 MAKE_ARRAY_WRAPPER(wxParamX, wxParamXArray);
 
 229 MAKE_ARRAY_WRAPPER(wxFuncX, wxFuncXArray);
 
 230 MAKE_ARRAY_WRAPPER(wxPropX, wxPropXArray);
 
 233 //---------------------------------------------------------------------------
 
 237 // C++ version of a Python-aware wxActiveX    
 
 238 class wxActiveXWindow : public wxActiveX
 
 243     wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 244                      const wxPoint& pos = wxDefaultPosition,
 
 245                      const wxSize& size = wxDefaultSize,
 
 247                      const wxString& name = wxPyPanelNameStr)
 
 248         : wxActiveX(parent, clsId, id, pos, size, style, name)
 
 253     const CLSID& GetCLSID() const { return m_CLSID; }
 
 256     // Renamed versions of some base class methods that delegate
 
 257     // to the base where appropriate, and raise Python exceptions
 
 259     int GetAXEventCount() const  { return wxActiveX::GetEventCount(); }
 
 260     int GetAXPropCount() const   { return wxActiveX::GetPropCount(); }
 
 261     int GetAXMethodCount() const { return wxActiveX::GetMethodCount(); }
 
 263     const wxFuncX& GetAXEventDesc(int idx) const
 
 265         static wxFuncX BadVal;
 
 266         if (idx < 0 || idx >= GetAXEventCount()) {
 
 267             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 270         return m_events[idx];
 
 272     const wxFuncX& GetAXMethodDesc(int idx) const
 
 274         static wxFuncX BadVal;
 
 275         if (idx < 0 || idx >= GetAXMethodCount()) {
 
 276             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 279         return m_methods[idx];
 
 281     const wxPropX& GetAXPropDesc(int idx) const
 
 283         static wxPropX BadVal;
 
 284         if (idx < 0 || idx >= GetAXPropCount()) {
 
 285             wxPyErr_SetString(PyExc_IndexError, "Index out of range");
 
 291     const wxFuncX& GetAXMethodDesc(const wxString& name) const
 
 293         NameMap::const_iterator it = m_methodNames.find(name);
 
 294         if (it == m_methodNames.end())     {
 
 296             msg << _T("method <") << name << _T("> not found");
 
 297             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 298             static wxFuncX BadVal;
 
 301         return GetAXMethodDesc(it->second);
 
 303     const wxPropX& GetAXPropDesc(const wxString& name) const
 
 305         NameMap::const_iterator it = m_propNames.find(name);
 
 306         if (it == m_propNames.end())     {
 
 308             msg << _T("property <") << name << _T("> not found");
 
 309             wxPyErr_SetString(PyExc_KeyError, msg.mb_str());
 
 310             static wxPropX BadVal;
 
 313         return GetAXPropDesc(it->second);
 
 316     // Accessors for the internal vectors of events, methods and
 
 317     // proprties.  Can be used as sequence like objects from
 
 319     const wxFuncXArray& GetAXEvents()      { return m_events; }
 
 320     const wxFuncXArray& GetAXMethods()     { return m_methods; }
 
 321     const wxPropXArray& GetAXProperties()  { return m_props; }
 
 324     // Set a property from a Python object
 
 325     void SetAXProp(const wxString& name, PyObject* value)
 
 327         const wxPropX& prop = GetAXPropDesc(name);
 
 328         bool blocked = wxPyBeginBlockThreads();
 
 329         if (! PyErr_Occurred() ) {
 
 330             if (! prop.CanSet()) {
 
 332                 msg << _T("property <") << name << _T("> is readonly");
 
 333                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 336                 wxVariant wxV = _PyObj2Variant(value);
 
 337                 if (PyErr_Occurred())
 
 339                 VARIANT v = {prop.arg.vt};
 
 340                 if (!VariantToMSWVariant(wxV, v) || PyErr_Occurred()) {
 
 342                     msg << _T("Unable to convert value to expected type: (")
 
 343                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 345                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 348                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 349                 SetProp(prop.memid, v);
 
 351                 wxPyEndAllowThreads(tstate);
 
 355         wxPyEndBlockThreads(blocked);
 
 359     // Get a property and convert it to a Python object
 
 360     PyObject* GetAXProp(const wxString& name)
 
 362         PyObject* rval = NULL;
 
 363         const wxPropX& prop = GetAXPropDesc(name);
 
 364         bool blocked = wxPyBeginBlockThreads();
 
 365         if (! PyErr_Occurred() ) {
 
 366             if (! prop.CanGet()) {
 
 368                 msg << _T("property <") << name << _T("> is writeonly");
 
 369                 PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 372                 PyThreadState* tstate = wxPyBeginAllowThreads();
 
 373                 VARIANT v = GetPropAsVariant(prop.memid);
 
 374                 wxPyEndAllowThreads(tstate);
 
 376                 if (!MSWVariantToVariant(v, wv) || PyErr_Occurred()) {
 
 378                     msg << _T("Unable to convert value to expected type: (")
 
 379                         << _VARTYPEname(prop.arg.vt) << _T(") for property <")
 
 381                     PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 384                 rval = _Variant2PyObj(wv);
 
 389         wxPyEndBlockThreads(blocked);
 
 394     // If both IsIn and isOut are false, assume it is actually an
 
 396     bool paramIsIn(const wxParamX& p)
 
 398         return p.IsIn() || (!p.IsIn() && !p.IsOut());
 
 402     // Call a method of the ActiveX object
 
 403     PyObject* _CallAXMethod(const wxString& name, PyObject* args)
 
 405         VARIANTARG *vargs = NULL;
 
 407         PyObject* rval = NULL;
 
 408         const wxFuncX& func = GetAXMethodDesc(name);
 
 410         bool blocked = wxPyBeginBlockThreads();
 
 411         if (! PyErr_Occurred() ) {
 
 412             nargs = func.params.size();
 
 414                 vargs = new VARIANTARG[nargs];
 
 417                 // init type of vargs, in reverse order
 
 419                 for (i = 0; i < nargs; i++)
 
 420                     vargs[nargs - i - 1].vt = func.params[i].vt;
 
 422                 // Map the args coming from Python to the input parameters in vargs
 
 425                 while ( i<nargs && pi<PyTuple_Size(args) ) {
 
 426                     // Move to the next input param. 
 
 427                     if (! paramIsIn(func.params[i])) {
 
 431                     // convert the python object
 
 432                     PyObject* obj = PyTuple_GetItem(args, pi);
 
 433                     if (obj == Py_None) // special-case None?
 
 434                         vargs[nargs - i - 1].vt = VT_EMPTY;
 
 436                         wxVariant wxV = _PyObj2Variant(obj);
 
 437                         if (PyErr_Occurred())
 
 439                         if (!VariantToMSWVariant(wxV, vargs[nargs - i - 1]) || PyErr_Occurred()) {
 
 441                             msg << _T("Unable to convert value to expected type: (")
 
 442                                 << _VARTYPEname(vargs[nargs - i - 1].vt)
 
 443                                 << _T(") for parameter ") << i;
 
 444                             PyErr_SetString(PyExc_TypeError, msg.mb_str());
 
 454             PyThreadState* tstate = wxPyBeginAllowThreads();
 
 455             VARIANT rv = CallMethod(func.memid, vargs, nargs);
 
 456             wxPyEndAllowThreads(tstate);
 
 458             // Convert the return value and any out-params, ignoring
 
 459             // conversion errors for now
 
 461             MSWVariantToVariant(rv, wv);
 
 462             rval = _Variant2PyObj(wv, True);
 
 466                 // make a list and put the rval in it if it is not None
 
 467                 PyObject* lst = PyList_New(0);
 
 469                     PyList_Append(lst, rval);
 
 473                 // find the out params and convert them
 
 474                 for (int i = 0; i < nargs; i++) {
 
 475                     VARIANTARG& va = vargs[nargs - i - 1];
 
 476                     const wxParamX &px = func.params[i];
 
 478                         MSWVariantToVariant(va, wv);
 
 479                         PyObject* obj = _Variant2PyObj(wv, True);
 
 480                         PyList_Append(lst, obj);
 
 483                 rval = PyList_AsTuple(lst);
 
 486             if (PyErr_Occurred())
 
 490         wxPyEndBlockThreads(blocked);
 
 492             for (int i = 0; i < nargs; i++)
 
 493                 VariantClear(&vargs[i]);
 
 503 // Now tell SWIG about this new class that is implemented above.
 
 505 DocStr(wxActiveXWindow,
 
 506 "ActiveXWindow derives from wxWindow and the constructor accepts a
 
 507 CLSID for the ActiveX Control that should be created.  The
 
 508 ActiveXWindow class simply adds methods that allow you to query
 
 509 some of the TypeInfo exposed by the ActiveX object, and also to
 
 510 get/set properties or call methods by name.  The Python
 
 511 implementation automatically handles converting parameters and
 
 512 return values to/from the types expected by the ActiveX code as
 
 513 specified by the TypeInfo.
 
 517 class wxActiveXWindow : public wxWindow
 
 520     %pythonAppend wxActiveXWindow      "self._setOORInfo(self)"
 
 523         wxActiveXWindow( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 524                          const wxPoint& pos = wxDefaultPosition,
 
 525                          const wxSize& size = wxDefaultSize,
 
 527                          const wxString& name = wxPyPanelNameStr),
 
 528         "Creates an ActiveX control from the clsID given and makes it act
 
 529 as much like a regular wx.Window as possible.");
 
 532         const CLSID& , GetCLSID() const,
 
 533         "Return the CLSID used to construct this ActiveX window");
 
 537         int , GetAXEventCount() const,
 
 538         "Number of events defined for this control");
 
 541         const wxFuncX& , GetAXEventDesc(int idx) const,
 
 542         "Returns event description by index");
 
 546         int , GetAXPropCount() const,
 
 547         "Number of properties defined for this control");
 
 549     %nokwargs GetAXPropDesc;
 
 550     DocStr(GetPropDesc, "Returns property description by index or by name");
 
 551     const wxPropX& GetAXPropDesc(int idx) const;
 
 552     const wxPropX& GetAXPropDesc(const wxString& name) const;
 
 557         int , GetAXMethodCount() const,
 
 558         "Number of methods defined for this control");
 
 560     %nokwargs GetAXMethodDesc;
 
 561     DocStr(GetMethodDesc, "Returns method description by index or name");
 
 562     const wxFuncX& GetAXMethodDesc(int idx) const;
 
 563     const wxFuncX& GetAXMethodDesc(const wxString& name) const;
 
 567         const wxFuncXArray& , GetAXEvents(),
 
 568         "Returns a sequence of FuncX objects describing the events
 
 569 available for this ActiveX object.");
 
 572         const wxFuncXArray& , GetAXMethods(),
 
 573         "Returns a sequence of FuncX objects describing the methods
 
 574 available for this ActiveX object.");
 
 577         const wxPropXArray& , GetAXProperties(),
 
 578         "Returns a sequence of PropX objects describing the properties
 
 579 available for this ActiveX object.");
 
 584         void , SetAXProp(const wxString& name, PyObject* value),
 
 585         "Set a property of the ActiveX object by name.");
 
 589         PyObject* , GetAXProp(const wxString& name),
 
 590         "Get the value of an ActiveX property by name.");
 
 593     %nokwargs _CallAXMethod;
 
 595         PyObject* , _CallAXMethod(const wxString& name, PyObject* args),
 
 596         "The implementation for CallMethod.  Calls an ActiveX method, by
 
 597 name passing the parameters given in args.");
 
 599         def CallAXMethod(self, name, *args):
 
 601             Front-end for _CallMethod.  Simply passes all positional args
 
 602             after the name as a single tuple to _CallMethod.
 
 604             return self._CallAXMethod(name, args)
 
 608 //---------------------------------------------------------------------------
 
 612     wxEventType , RegisterActiveXEvent(const wxString& eventName),
 
 613     "Creates a standard wx event ID for the given eventName.");
 
 617 DocStr(wxActiveXEvent,
 
 618 "An instance of ActiveXEvent is sent to the handler for all bound
 
 619 ActiveX events.  Any event parameters from the ActiveX cntrol are
 
 620 turned into attributes of the Python proxy for this event object.
 
 621 Additionally, there is a property called eventName that will
 
 622 return (suprizingly <wink>) the name of the ActiveX event.");
 
 624 class wxActiveXEvent : public wxCommandEvent
 
 627     %feature("shadow") EventName "eventName = property(_activex.ActiveXEvent_EventName)";
 
 628     wxString EventName();
 
 632         // This is called by the EventThunker before calling the
 
 633         // handler. We'll convert and load the ActiveX event parameters into
 
 634         // attributes of the Python event object.
 
 635         void _preCallInit(PyObject* pyself) {
 
 636             bool blocked = wxPyBeginBlockThreads();
 
 637             PyObject* pList = PyList_New(0);
 
 638             PyObject_SetAttrString(pyself, "paramList", pList);
 
 640             for (int i=0; i<self->ParamCount(); i+=1) {
 
 641                 PyObject* name = PyString_FromString((char*)(const char*)self->ParamName(i).mb_str());
 
 642                 PyObject* val = _Variant2PyObj((*self)[i], True);
 
 643                 PyObject_SetAttr(pyself, name, val);
 
 644                 PyList_Append(pList, name);
 
 648             wxPyEndBlockThreads(blocked);
 
 651         // This one is called by the EventThunker after calling the
 
 652         // handler. It reloads any "out" parameters from the python attributes
 
 653         // back into the wxVariant they came from.        
 
 654         void _postCallCleanup(PyObject* pyself) {
 
 655             bool blocked = wxPyBeginBlockThreads();
 
 656             for (int i=0; i<self->ParamCount(); i+=1) {
 
 657                 PyObject* val = PyObject_GetAttrString(
 
 658                     pyself, (char*)(const char*)self->ParamName(i).mb_str());
 
 659                 _PyObj2Variant(val, (*self)[i]);
 
 662             wxPyEndBlockThreads(blocked);
 
 669 //---------------------------------------------------------------------------
 
 673 // Caller should already have the GIL!
 
 674 wxVariant _PyObj2Variant(PyObject* value)
 
 678     if (value == Py_None)
 
 681 #if PYTHON_API_VERSION >= 1012  // Python 2.3+
 
 682     else if (PyBool_Check(value))
 
 683         rval = (value == Py_True) ? true : false;
 
 686     else if (PyInt_Check(value))
 
 687         rval = PyInt_AS_LONG(value);
 
 689     else if (PyFloat_Check(value))
 
 690         rval = PyFloat_AS_DOUBLE(value);
 
 692     else if (PyString_Check(value) || PyUnicode_Check(value))
 
 693         rval = Py2wxString(value);
 
 695     // TODO:    PyList of strings --> wxArrayString
 
 701         PyErr_SetString(PyExc_TypeError, "Unsupported object type in _PyObj2Variant");
 
 708 // This one uses the type of the variant to try and force the conversion
 
 709 bool  _PyObj2Variant(PyObject* value, wxVariant& wv)
 
 711     wxString type = wv.GetType();
 
 713     if ( type == _T("long") || type == _T("bool") || type == _T("char") )
 
 714         wv = PyInt_AsLong(value);
 
 716     else if ( type == _T("string") )
 
 717         wv = Py2wxString(value);
 
 719     else if ( type == _T("double") )
 
 720         wv  = PyFloat_AsDouble(value);
 
 723         // it's some other type that we dont' handle yet.  Log it?
 
 729 // Caller should already have the GIL!
 
 730 PyObject* _Variant2PyObj(wxVariant& value, bool useNone)
 
 732     PyObject* rval = NULL;
 
 734     if (value.IsNull()) {
 
 739     // should "char" be treated as an int or as a string?
 
 740     else if (value.IsType(_T("char")) || value.IsType(_T("long")))
 
 741         rval = PyInt_FromLong(value);
 
 743     else if (value.IsType(_T("double")))
 
 744         rval = PyFloat_FromDouble(value);
 
 746     else if (value.IsType(_T("bool"))) {
 
 747         rval = (bool)value ? Py_True : Py_False;
 
 751     else if (value.IsType(_T("string")))
 
 752         rval = wx2PyString(value);
 
 760             PyErr_SetString(PyExc_TypeError, "Unsupported object type in _Variant2PyObj");
 
 767 wxString _VARTYPEname(VARTYPE vt)
 
 774         return _T("VT_VARIANT");
 
 794     // decimals are converted from doubles too
 
 802         return _T("wx.DateTime");
 
 808         return _T("VT_UNKNOWN");
 
 811         return _T("VT_DISPATCH");
 
 814         return _T("VT_EMPTY");
 
 817         return _T("VT_NULL");
 
 820         return _T("VT_VOID");
 
 824         msg << _T("unsupported type ") << vt;
 
 831 //---------------------------------------------------------------------------
 
 832 //---------------------------------------------------------------------------
 
 837 // A class derived from out wxActiveXWindow for the IE WebBrowser
 
 838 // control that will serve as a base class for a Python
 
 839 // implementation.  This is done so we can "eat our own dog food"
 
 840 // and use a class at least mostly generated by genaxmodule, but
 
 841 // also get some of the extra stuff like loading a document from
 
 842 // a string or a stream, getting text contents, etc. that
 
 843 // Lindsay's version gives us.
 
 846 #include <wx/mstream.h>
 
 848 #include <winerror.h>
 
 849 #include <exdispid.h>
 
 855 #include "IEHtmlStream.h"
 
 857 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
 859     wxAutoOleInterface<IWebBrowser2>  m_webBrowser;
 
 863     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
 864                          const wxPoint& pos = wxDefaultPosition,
 
 865                          const wxSize& size = wxDefaultSize,
 
 867                          const wxString& name = wxPyPanelNameStr)
 
 868         : wxActiveXWindow(parent, clsId, id, pos, size, style, name)
 
 872         // Get IWebBrowser2 Interface
 
 873         hret = m_webBrowser.QueryInterface(IID_IWebBrowser2, m_ActiveX);
 
 874         wxASSERT(SUCCEEDED(hret));
 
 877         m_webBrowser->put_MenuBar(VARIANT_FALSE);
 
 878         m_webBrowser->put_AddressBar(VARIANT_FALSE);
 
 879         m_webBrowser->put_StatusBar(VARIANT_FALSE);
 
 880         m_webBrowser->put_ToolBar(VARIANT_FALSE);
 
 882         m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE);
 
 883         m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE);
 
 885         m_webBrowser->Navigate( L"about:blank", NULL, NULL, NULL, NULL );
 
 889     void SetCharset(const wxString& charset)
 
 894         IDispatch *pDisp = NULL;
 
 895         hret = m_webBrowser->get_Document(&pDisp);
 
 896         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 900             wxAutoOleInterface<IHTMLDocument2> doc(IID_IHTMLDocument2, disp);
 
 902                 doc->put_charset((BSTR) (const wchar_t *) charset.wc_str(wxConvUTF8));
 
 903             //doc->put_charset((BSTR) wxConvUTF8.cMB2WC(charset).data());
 
 908     bool LoadString(const wxString& html)
 
 911         size_t len = html.length();
 
 912         len *= sizeof(wxChar);
 
 913         data = (char *) malloc(len);
 
 914         memcpy(data, html.c_str(), len);
 
 915         return LoadStream(new wxOwnedMemInputStream(data, len));
 
 919     bool LoadStream(IStreamAdaptorBase *pstrm)
 
 921         // need to prepend this as poxy MSHTML will not recognise a HTML comment
 
 922         // as starting a html document and treats it as plain text
 
 923         // Does nayone know how to force it to html mode ?
 
 925         // TODO: What to do in this case???
 
 927         pstrm->prepend = _T("<html>");
 
 930         // strip leading whitespace as it can confuse MSHTML
 
 931         wxAutoOleInterface<IStream> strm(pstrm);
 
 933         // Document Interface
 
 934         IDispatch *pDisp = NULL;
 
 935         HRESULT hret = m_webBrowser->get_Document(&pDisp);
 
 938         wxAutoOleInterface<IDispatch> disp(pDisp);
 
 941         // get IPersistStreamInit
 
 942         wxAutoOleInterface<IPersistStreamInit>
 
 943             pPersistStreamInit(IID_IPersistStreamInit, disp);
 
 945         if (pPersistStreamInit.Ok())
 
 947             HRESULT hr = pPersistStreamInit->InitNew();
 
 949                 hr = pPersistStreamInit->Load(strm);
 
 951             return SUCCEEDED(hr);
 
 957     bool LoadStream(wxInputStream *is)
 
 959         // wrap reference around stream
 
 960         IwxStreamAdaptor *pstrm = new IwxStreamAdaptor(is);
 
 963         return LoadStream(pstrm);
 
 967     wxString GetStringSelection(bool asHTML)
 
 969         wxAutoOleInterface<IHTMLTxtRange> tr(wxieGetSelRange(m_oleObject));
 
 971             return wxEmptyString;
 
 977             hr = tr->get_htmlText(&text);
 
 979             hr = tr->get_text(&text);
 
 981             return wxEmptyString;
 
 989     wxString GetText(bool asHTML)
 
 991         if (! m_webBrowser.Ok())
 
 992             return wxEmptyString;
 
 994         // get document dispatch interface
 
 995         IDispatch *iDisp = NULL;
 
 996         HRESULT hr = m_webBrowser->get_Document(&iDisp);
 
 998             return wxEmptyString;
 
1000         // Query for Document Interface
 
1001         wxAutoOleInterface<IHTMLDocument2> hd(IID_IHTMLDocument2, iDisp);
 
1005             return wxEmptyString;
 
1008         IHTMLElement *_body = NULL;
 
1009         hd->get_body(&_body);
 
1011             return wxEmptyString;
 
1012         wxAutoOleInterface<IHTMLElement> body(_body);
 
1019             hr = body->get_innerHTML(&text);
 
1021             hr = body->get_innerText(&text);
 
1023             return wxEmptyString;
 
1026         SysFreeString(text);
 
1032 //     void wxIEHtmlWin::SetEditMode(bool seton)
 
1034 //         m_bAmbientUserMode = ! seton;
 
1035 //         AmbientPropertyChanged(DISPID_AMBIENT_USERMODE);
 
1038 //     bool wxIEHtmlWin::GetEditMode()
 
1040 //         return ! m_bAmbientUserMode;
 
1046 // we'll document it in the derived Python class
 
1047 %feature("noautodoc") wxIEHtmlWindowBase;
 
1048 %feature("noautodoc") wxIEHtmlWindowBase::SetCharset;
 
1049 %feature("noautodoc") wxIEHtmlWindowBase::LoadString;
 
1050 %feature("noautodoc") wxIEHtmlWindowBase::LoadStream;
 
1051 %feature("noautodoc") wxIEHtmlWindowBase::GetStringSelection;
 
1052 %feature("noautodoc") wxIEHtmlWindowBase::GetText;
 
1055 class wxIEHtmlWindowBase : public wxActiveXWindow {
 
1058     wxIEHtmlWindowBase ( wxWindow* parent, const CLSID& clsId, wxWindowID id = -1,
 
1059                          const wxPoint& pos = wxDefaultPosition,
 
1060                          const wxSize& size = wxDefaultSize,
 
1062                          const wxString& name = wxPyPanelNameStr);
 
1064     void SetCharset(const wxString& charset);
 
1065     bool LoadString(const wxString& html);
 
1066     bool LoadStream(wxInputStream *is);
 
1067     wxString GetStringSelection(bool asHTML);
 
1068     wxString GetText(bool asHTML);
 
1082 enum wxIEHtmlRefreshLevel
 
1084     wxIEHTML_REFRESH_NORMAL = 0,
 
1085     wxIEHTML_REFRESH_IFEXPIRED = 1,
 
1086     wxIEHTML_REFRESH_CONTINUE = 2,
 
1087     wxIEHTML_REFRESH_COMPLETELY = 3
 
1092 class wxIEHtmlWin : public wxWindow 
 
1095     %pythonAppend wxIEHtmlWin      "self._setOORInfo(self)"
 
1097     wxIEHtmlWin(wxWindow * parent, wxWindowID id = -1,
 
1098                 const wxPoint& pos = wxDefaultPosition,
 
1099                 const wxSize& size = wxDefaultSize,
 
1101                 const wxString& name = wxPyPanelNameStr);
 
1103     void LoadUrl(const wxString& url);
 
1104     bool LoadString(wxString html);
 
1105     bool LoadStream(wxInputStream *is);
 
1107     %pythoncode { Navigate = LoadUrl }
 
1109     void SetCharset(wxString charset);
 
1110     void SetEditMode(bool seton);
 
1112     wxString GetStringSelection(bool asHTML = false);
 
1113     wxString GetText(bool asHTML = false);
 
1119     %name(RefreshPage)bool Refresh(wxIEHtmlRefreshLevel level);
 
1126 wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2  = RegisterActiveXEvent('BeforeNavigate2')
 
1127 wxEVT_COMMAND_MSHTML_NEWWINDOW2       = RegisterActiveXEvent('NewWindow2')
 
1128 wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE = RegisterActiveXEvent('DocumentComplete')
 
1129 wxEVT_COMMAND_MSHTML_PROGRESSCHANGE   = RegisterActiveXEvent('ProgressChange')
 
1130 wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE = RegisterActiveXEvent('StatusTextChange')
 
1131 wxEVT_COMMAND_MSHTML_TITLECHANGE      = RegisterActiveXEvent('TitleChange')
 
1133 EVT_MSHTML_BEFORENAVIGATE2      = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_BEFORENAVIGATE2, 1)
 
1134 EVT_MSHTML_NEWWINDOW2           = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_NEWWINDOW2, 1)
 
1135 EVT_MSHTML_DOCUMENTCOMPLETE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_DOCUMENTCOMPLETE, 1)
 
1136 EVT_MSHTML_PROGRESSCHANGE       = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_PROGRESSCHANGE, 1)
 
1137 EVT_MSHTML_STATUSTEXTCHANGE     = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_STATUSTEXTCHANGE, 1)
 
1138 EVT_MSHTML_TITLECHANGE          = wx.PyEventBinder(wxEVT_COMMAND_MSHTML_TITLECHANGE, 1)
 
1143 //---------------------------------------------------------------------------
 
1144 // Include some extra Python code into the proxy module
 
1146 %pythoncode "_activex_ex.py"
 
1148 //---------------------------------------------------------------------------