+#define wxPlatform "__WXMSW__"
+#define wxPlatName "wxMSW"
+#endif
+#ifdef __WXMAC__
+#define wxPlatform "__WXMAC__"
+#define wxPlatName "wxMac"
+#endif
+
+#ifdef __WXDEBUG__
+    int wxdebug = 1;
+#else
+    int wxdebug = 0;
+#endif
+
+    // These should be deprecated in favor of the PlatformInfo tuple built below...
+    PyDict_SetItemString(wxPython_dict, "Platform", PyString_FromString(wxPlatform));
+    PyDict_SetItemString(wxPython_dict, "USE_UNICODE", PyInt_FromLong(wxUSE_UNICODE));
+    PyDict_SetItemString(wxPython_dict, "__WXDEBUG__", PyInt_FromLong(wxdebug));
+
+    // Make a tuple of strings that gives more info about the platform.
+    PyObject* PlatInfo = PyList_New(0);
+    PyObject* obj;
+
+#define _AddInfoString(st) \
+    obj = PyString_FromString(st); \
+    PyList_Append(PlatInfo, obj); \
+    Py_DECREF(obj)
+
+    _AddInfoString(wxPlatform);
+    _AddInfoString(wxPlatName);
+#if wxUSE_UNICODE
+    _AddInfoString("unicode");
+#else
+    _AddInfoString("ansi");
+#endif
+#ifdef __WXGTK__
+#ifdef __WXGTK20__
+    _AddInfoString("gtk2");
+#else
+    _AddInfoString("gtk1");
+#endif
+#endif
+#ifdef __WXDEBUG__
+    _AddInfoString("wx-assertions-on");
+#else
+    _AddInfoString("wx-assertions-off");
+#endif
+    _AddInfoString(wxPy_SWIG_VERSION);    
+    
+#undef _AddInfoString
+
+    PyObject* PlatInfoTuple = PyList_AsTuple(PlatInfo);
+    Py_DECREF(PlatInfo);
+    PyDict_SetItemString(wxPython_dict, "PlatformInfo", PlatInfoTuple);
+
+    RETURN_NONE();
+}
+
+
+
+//---------------------------------------------------------------------------
+
+// The stock objects are no longer created when the wx._core_ module is
+// imported, but only after the app object has been created.  The
+// wxPy_ReinitStockObjects function will be called 3 times to pass the stock
+// objects though various stages of evolution:
+//
+//   pass 1: Set all the pointers to a non-NULL value so the Python proxy
+//           object will be created (otherwise SWIG will just use None.)
+//
+//   pass 2: After the module has been imported and the python proxys have
+//           been created, then set the __class__ to be _wxPyUnbornObject so
+//           it will catch any access to the object and will raise an exception.
+//
+//   pass 3: Finally, from BootstrapApp patch things up so the stock objects
+//           can be used.
+
+
+PyObject* __wxPyFixStockObjects(PyObject* /* self */, PyObject* args)
+{
+    wxPy_ReinitStockObjects(2);
+    RETURN_NONE();
+}
+
+
+static void rsoPass2(const char* name)
+{
+    static PyObject* unbornObjectClass = NULL;
+    PyObject* obj;
+
+    if (unbornObjectClass == NULL) {
+        unbornObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyUnbornObject");
+        Py_INCREF(unbornObjectClass);
+    }
+
+    // Find the object instance
+    obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name));
+    wxCHECK_RET(obj != NULL, wxT("Unable to find stock object"));
+    wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance"));
+
+    // Change its class
+    PyObject_SetAttrString(obj, "__class__",  unbornObjectClass);
+
+}
+
+static void rsoPass3(const char* name, const char* classname, void* ptr)
+{
+    PyObject* obj;
+    PyObject* classobj;
+    PyObject* ptrobj;
+
+    // Find the object instance
+    obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name));
+    wxCHECK_RET(obj != NULL, wxT("Unable to find stock object"));
+    wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance"));
+
+    // Find the class object and put it back in the instance
+    classobj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(classname));
+    wxCHECK_RET(classobj != NULL, wxT("Unable to find stock class object"));
+    PyObject_SetAttrString(obj, "__class__",  classobj);
+
+    // Rebuild the .this swigified pointer with the new value of the C++ pointer
+    ptrobj = wxPyMakeSwigPtr(ptr, wxString(classname, *wxConvCurrent));
+    PyObject_SetAttrString(obj, "this", ptrobj);
+    Py_DECREF(ptrobj);
+}
+
+
+
+void wxPy_ReinitStockObjects(int pass)
+{
+
+    // If there is already an App object then wxPython is probably embedded in
+    // a wx C++ application, so there is no need to do all this.
+    static bool embedded = false;
+    if ((pass == 1 || pass == 2) && wxTheApp) {
+        embedded = true;
+        return;
+    }
+    if (pass == 3 && embedded)
+        return;
+
+
+#define REINITOBJ(name, classname) \
+    if (pass == 1) { name = (classname*)0xC0C0C0C0; } \
+    else if (pass == 2) { rsoPass2(#name); } \
+    else if (pass == 3) { rsoPass3(#name, #classname, (void*)name); }
+
+
+#define REINITOBJ2(name, classname) \
+    if (pass == 1) { } \
+    else if (pass == 2) { rsoPass2(#name); } \
+    else if (pass == 3) { rsoPass3(#name, #classname, (void*)&name); }
+
+
+    REINITOBJ(wxNORMAL_FONT, wxFont);
+    REINITOBJ(wxSMALL_FONT, wxFont);
+    REINITOBJ(wxITALIC_FONT, wxFont);
+    REINITOBJ(wxSWISS_FONT, wxFont);
+
+    REINITOBJ(wxRED_PEN, wxPen);
+    REINITOBJ(wxCYAN_PEN, wxPen);
+    REINITOBJ(wxGREEN_PEN, wxPen);
+    REINITOBJ(wxBLACK_PEN, wxPen);
+    REINITOBJ(wxWHITE_PEN, wxPen);
+    REINITOBJ(wxTRANSPARENT_PEN, wxPen);
+    REINITOBJ(wxBLACK_DASHED_PEN, wxPen);
+    REINITOBJ(wxGREY_PEN, wxPen);
+    REINITOBJ(wxMEDIUM_GREY_PEN, wxPen);
+    REINITOBJ(wxLIGHT_GREY_PEN, wxPen);
+
+    REINITOBJ(wxBLUE_BRUSH, wxBrush);
+    REINITOBJ(wxGREEN_BRUSH, wxBrush);
+    REINITOBJ(wxWHITE_BRUSH, wxBrush);
+    REINITOBJ(wxBLACK_BRUSH, wxBrush);
+    REINITOBJ(wxTRANSPARENT_BRUSH, wxBrush);
+    REINITOBJ(wxCYAN_BRUSH, wxBrush);
+    REINITOBJ(wxRED_BRUSH, wxBrush);
+    REINITOBJ(wxGREY_BRUSH, wxBrush);
+    REINITOBJ(wxMEDIUM_GREY_BRUSH, wxBrush);
+    REINITOBJ(wxLIGHT_GREY_BRUSH, wxBrush);
+
+    REINITOBJ(wxBLACK, wxColour);
+    REINITOBJ(wxWHITE, wxColour);
+    REINITOBJ(wxRED, wxColour);
+    REINITOBJ(wxBLUE, wxColour);
+    REINITOBJ(wxGREEN, wxColour);
+    REINITOBJ(wxCYAN, wxColour);
+    REINITOBJ(wxLIGHT_GREY, wxColour);
+
+    REINITOBJ(wxSTANDARD_CURSOR, wxCursor);
+    REINITOBJ(wxHOURGLASS_CURSOR, wxCursor);
+    REINITOBJ(wxCROSS_CURSOR, wxCursor);
+
+    REINITOBJ2(wxNullBitmap, wxBitmap);
+    REINITOBJ2(wxNullIcon, wxIcon);
+    REINITOBJ2(wxNullCursor, wxCursor);
+    REINITOBJ2(wxNullPen, wxPen);
+    REINITOBJ2(wxNullBrush, wxBrush);
+    REINITOBJ2(wxNullPalette, wxPalette);
+    REINITOBJ2(wxNullFont, wxFont);
+    REINITOBJ2(wxNullColour, wxColour);
+
+    REINITOBJ(wxTheFontList, wxFontList);
+    REINITOBJ(wxThePenList, wxPenList);
+    REINITOBJ(wxTheBrushList, wxBrushList);
+    REINITOBJ(wxTheColourDatabase, wxColourDatabase);
+
+
+    REINITOBJ2(wxDefaultValidator, wxValidator);
+    REINITOBJ2(wxNullImage, wxImage);
+    REINITOBJ2(wxNullAcceleratorTable, wxAcceleratorTable);
+
+#undef REINITOBJ
+#undef REINITOBJ2
+}
+
+//---------------------------------------------------------------------------
+
+// Check for existence of a wxApp, setting an exception if there isn't one.
+// This doesn't need to aquire the GIL because it should only be called from
+// an %exception before the lock is released.
+
+bool wxPyCheckForApp() {
+    if (wxTheApp != NULL)
+        return true;
+    else {
+        PyErr_SetString(wxPyNoAppError, "The wx.App object must be created first!");
+        return false;
+    }
+}
+
+//---------------------------------------------------------------------------
+
+void wxPyUserData_dtor(wxPyUserData* self) {
+    if (! wxPyDoingCleanup) {
+        wxPyBlock_t blocked = wxPyBeginBlockThreads();
+        Py_DECREF(self->m_obj);
+        self->m_obj = NULL;
+        wxPyEndBlockThreads(blocked);
+    }
+}
+
+
+void wxPyClientData_dtor(wxPyClientData* self) {
+    if (! wxPyDoingCleanup) {           // Don't do it during cleanup as Python
+                                        // may have already garbage collected the object...
+        if (self->m_incRef) {
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            Py_DECREF(self->m_obj);
+            wxPyEndBlockThreads(blocked);
+        }
+        self->m_obj = NULL;
+    }
+}
+
+
+
+// This is called when an OOR controled object is being destroyed.  Although
+// the C++ object is going away there is no way to force the Python object
+// (and all references to it) to die too.  This causes problems (crashes) in
+// wxPython when a python shadow object attempts to call a C++ method using
+// the now bogus pointer... So to try and prevent this we'll do a little black
+// magic and change the class of the python instance to a class that will
+// raise an exception for any attempt to call methods with it.  See
+// _wxPyDeadObject in _core_ex.py for the implementation of this class.
+void wxPyOORClientData_dtor(wxPyOORClientData* self) {
+
+    static PyObject* deadObjectClass = NULL;
+
+    wxPyBlock_t blocked = wxPyBeginBlockThreads();
+    if (deadObjectClass == NULL) {
+        deadObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyDeadObject");
+        // TODO:  Can not wxASSERT here because inside a wxPyBeginBlock Threads,
+        // will lead to a deadlock when it tries to aquire the GIL again.
+        //wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!"));
+        Py_INCREF(deadObjectClass);
+    }
+
+
+    // Only if there is more than one reference to the object and we are
+    // holding the OOR reference:
+    if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 && self->m_incRef) {
+        // bool isInstance = wxPyInstance_Check(self->m_obj);
+        // TODO same here
+        //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));
+
+        // Call __del__, if there is one.
+        PyObject* func = PyObject_GetAttrString(self->m_obj, "__del__");
+        if (func) {
+            PyObject* rv = PyObject_CallMethod(self->m_obj, "__del__", NULL);
+            Py_XDECREF(rv);
+            Py_DECREF(func);
+        }
+        if (PyErr_Occurred())
+            PyErr_Clear();      // just ignore it for now
+
+
+        PyObject* dict = PyObject_GetAttrString(self->m_obj, "__dict__");
+        if (dict) {
+            // Clear the instance's dictionary
+            PyDict_Clear(dict);
+
+            // put the name of the old class into the instance, and then reset the
+            // class to be the dead class.
+            PyObject* klass = PyObject_GetAttrString(self->m_obj, "__class__");
+            PyObject* name =  PyObject_GetAttrString(klass, "__name__");
+            PyDict_SetItemString(dict, "_name", name);
+            PyObject_SetAttrString(self->m_obj, "__class__",  deadObjectClass);
+            //Py_INCREF(deadObjectClass);
+            Py_DECREF(klass);
+            Py_DECREF(name);
+        }
+    }
+
+    // m_obj is DECREF'd in the base class dtor...
+    wxPyEndBlockThreads(blocked);
+}
+
+
+//---------------------------------------------------------------------------
+// Stuff used by OOR to find the right wxPython class type to return and to
+// build it.
+
+
+// The pointer type map is used when the "pointer" type name generated by SWIG
+// is not the same as the shadow class name, for example wxPyTreeCtrl
+// vs. wxTreeCtrl.  It needs to be referenced in Python as well as from C++,
+// so we'll just make it a Python dictionary in the wx module's namespace.
+// (See __wxSetDictionary)
+void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
+    if (! wxPyPtrTypeMap)
+        wxPyPtrTypeMap = PyDict_New();
+    PyDict_SetItemString(wxPyPtrTypeMap,
+                         (char*)commonName,
+                         PyString_FromString((char*)ptrName));
+}
+
+
+
+
+PyObject*  wxPyMake_wxObject(wxObject* source, bool setThisOwn, bool checkEvtHandler) {
+    PyObject* target = NULL;
+    bool      isEvtHandler = false;
+    bool      isSizer = false;
+
+    if (source) {
+        // If it's derived from wxEvtHandler then there may
+        // already be a pointer to a Python object that we can use
+        // in the OOR data.
+        if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) {
+            isEvtHandler = true;
+            wxEvtHandler* eh = (wxEvtHandler*)source;
+            wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject();
+            if (data) {
+                target = data->m_obj;
+                if (target)
+                    Py_INCREF(target);
+            }
+        }
+
+        // Also check for wxSizer
+        if (!target && wxIsKindOf(source, wxSizer)) {
+            isSizer = true;
+            wxSizer* sz = (wxSizer*)source;
+            wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject();
+            if (data) {
+                target = data->m_obj;
+                if (target)
+                    Py_INCREF(target);
+            }
+        }
+        
+        if (! target) {
+            // Otherwise make it the old fashioned way by making a new shadow
+            // object and putting this pointer in it.  Look up the class
+            // heirarchy until we find a class name that is located in the
+            // python module.
+            const wxClassInfo* info   = source->GetClassInfo();
+            wxString           name   = info->GetClassName();
+            bool               exists = wxPyCheckSwigType(name);
+            while (info && !exists) {
+                info = info->GetBaseClass1();
+                name = info->GetClassName();
+                exists = wxPyCheckSwigType(name);
+            }
+            if (info) {
+                target = wxPyConstructObject((void*)source, name, setThisOwn);
+                if (target && isEvtHandler)
+                    ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
+                if (target && isSizer)
+                    ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target));
+            } else {
+                wxString msg(wxT("wxPython class not found for "));
+                msg += source->GetClassInfo()->GetClassName();
+                PyErr_SetString(PyExc_NameError, msg.mbc_str());
+                target = NULL;
+            }
+        }
+    } else {  // source was NULL so return None.
+        Py_INCREF(Py_None); target = Py_None;
+    }
+    return target;
+}
+
+
+PyObject*  wxPyMake_wxSizer(wxSizer* source, bool setThisOwn) {
+
+    return wxPyMake_wxObject(source, setThisOwn);
+}
+
+
+//---------------------------------------------------------------------------
+
+
+#ifdef WXP_WITH_THREAD
+#if !wxPyUSE_GIL_STATE
+
+inline
+unsigned long wxPyGetCurrentThreadId() {
+    return wxThread::GetCurrentId();
+}
+
+static wxPyThreadState gs_shutdownTState;
+
+static
+wxPyThreadState* wxPyGetThreadState() {
+    if (wxPyTMutex == NULL) // Python is shutting down...
+        return &gs_shutdownTState;
+
+    unsigned long ctid = wxPyGetCurrentThreadId();
+    wxPyThreadState* tstate = NULL;
+
+    wxPyTMutex->Lock();
+    for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
+        wxPyThreadState& info = wxPyTStates->Item(i);
+        if (info.tid == ctid) {
+            tstate = &info;
+            break;
+        }
+    }
+    wxPyTMutex->Unlock();
+    wxASSERT_MSG(tstate, wxT("PyThreadState should not be NULL!"));
+    return tstate;
+}
+
+
+static
+void wxPySaveThreadState(PyThreadState* tstate) {
+    if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread...
+        gs_shutdownTState.tstate = tstate;
+        return;
+    }
+    unsigned long ctid = wxPyGetCurrentThreadId();
+    wxPyTMutex->Lock();
+    for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
+        wxPyThreadState& info = wxPyTStates->Item(i);
+        if (info.tid == ctid) {
+#if 0
+            if (info.tstate != tstate)
+                wxLogMessage("*** tstate mismatch!???");
+#endif
+            info.tstate = tstate;    // allow for transient tstates
+            // Normally it will never change, but apparently COM callbacks
+            // (i.e. ActiveX controls) will (incorrectly IMHO) use a transient
+            // tstate which will then be garbage the next time we try to use
+            // it...
+
+            wxPyTMutex->Unlock();
+            return;
+        }
+    }
+    // not found, so add it...
+    wxPyTStates->Add(new wxPyThreadState(ctid, tstate));
+    wxPyTMutex->Unlock();
+}
+
+#endif
+#endif
+
+
+
+// Calls from Python to wxWindows code are wrapped in calls to these
+// functions:
+
+PyThreadState* wxPyBeginAllowThreads() {
+#ifdef WXP_WITH_THREAD
+    PyThreadState* saved = PyEval_SaveThread();  // Py_BEGIN_ALLOW_THREADS;
+#if !wxPyUSE_GIL_STATE
+    wxPySaveThreadState(saved);
+#endif
+    return saved;
+#else
+    return NULL;
+#endif
+}
+
+void wxPyEndAllowThreads(PyThreadState* saved) {
+#ifdef WXP_WITH_THREAD
+    PyEval_RestoreThread(saved);   // Py_END_ALLOW_THREADS;