X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1e4a197e4c60e461b8068b0619692ea083e30b8b..6bb000ec67f671142ba67feaddbaeddd2b575811:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index c47bd837c5..57b971ae57 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -28,6 +28,10 @@ #include #endif +#include +#include +#include + //---------------------------------------------------------------------- #if PYTHON_API_VERSION <= 1007 && wxUSE_UNICODE @@ -36,14 +40,6 @@ //---------------------------------------------------------------------- -#ifdef __WXGTK__ -int WXDLLEXPORT wxEntryStart( int& argc, char** argv ); -#else -int WXDLLEXPORT wxEntryStart( int argc, char** argv ); -#endif -int WXDLLEXPORT wxEntryInitGui(); -void WXDLLEXPORT wxEntryCleanup(); - wxPyApp* wxPythonApp = NULL; // Global instance of application object bool wxPyDoCleanup = FALSE; bool wxPyDoingCleanup = FALSE; @@ -334,6 +330,7 @@ void wxPyApp::SetMacHelpMenuTitleName(const wxString& val) { //---------------------------------------------------------------------- +#if 0 static char* wxPyCopyCString(const wxChar* src) { wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(src); @@ -366,13 +363,13 @@ static wxChar* wxPyCopyWString(const wxChar *src) return copystring(src); } #endif +#endif //---------------------------------------------------------------------- -// This is where we pick up the first part of the wxEntry functionality... -// The rest is in __wxStart and __wxCleanup. This function is called when -// wxcmodule is imported. (Before there is a wxApp object.) +// This function is called when the wxc module is imported to do some initial +// setup. (Before there is a wxApp object.) void __wxPreStart(PyObject* moduleDict) { @@ -386,72 +383,60 @@ void __wxPreStart(PyObject* moduleDict) wxPyTMutex = new wxMutex; #endif - wxApp::CheckBuildOptions(wxBuildOptions()); + // Ensure that the build options in the DLL (or whatever) match this build + wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython"); + // Create an exception object to use for wxASSERTions wxPyAssertionError = PyErr_NewException("wxPython.wxc.wxPyAssertionError", PyExc_AssertionError, NULL); PyDict_SetItemString(moduleDict, "wxPyAssertionError", wxPyAssertionError); - - - // Bail out if there is already a wxApp created. This means that the - // toolkit has already been initialized, as in embedding wxPython in - // a C++ wxWindows app, so we don't need to call wxEntryStart. - if (wxTheApp != NULL) { - return; - } - wxPyDoCleanup = TRUE; - - int argc = 0; - char** argv = NULL; - PyObject* sysargv = PySys_GetObject("argv"); - if (sysargv != NULL) { - argc = PyList_Size(sysargv); - argv = new char*[argc+1]; - int x; - for(x=0; xargc = argc; - wxPythonApp->argv = argv; + if (! wxEntryStart(argc, argv) ) { + PyErr_SetString(PyExc_SystemError, // is this the right one? + "wxEntryStart failed!"); + goto error; + } + delete [] argv; + + + // The stock objects were all NULL when they were loaded into + // SWIG generated proxies, so re-init those now... + wxPy_ReinitStockObjects(); - wxEntryInitGui(); - // Call the Python App's OnInit function + // Call the Python wxApp's OnInit function arglist = PyTuple_New(0); result = PyEval_CallObject(onInitFunc, arglist); Py_DECREF(arglist); @@ -459,7 +444,7 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args) return NULL; } - PyObject* pyint = PyNumber_Int(result); + pyint = PyNumber_Int(result); if (! pyint) { PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value"); goto error; @@ -486,6 +471,7 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args) } + void __wxCleanup() { wxPyDoingCleanup = TRUE; if (wxPyDoCleanup) @@ -548,6 +534,102 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) return Py_None; } + +//--------------------------------------------------------------------------- + +// The stock objects are no longer created when the wxc module is imported, but +// only after the app object has been created. This function will be called before +// OnInit is called so we can hack the new pointer values into the obj.this attributes. + +void wxPy_ReinitStockObjects() +{ + char ptrbuf[128]; + PyObject* obj; + PyObject* ptrobj; + + + +#define REINITOBJ(name, type) \ + obj = PyDict_GetItemString(wxPython_dict, #name); \ + wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \ + SWIG_MakePtr(ptrbuf, (char *) name, "_" #type "_p"); \ + ptrobj = PyString_FromString(ptrbuf); \ + PyObject_SetAttrString(obj, "this", ptrobj); \ + Py_DECREF(ptrobj) + +#define REINITOBJ2(name, type) \ + obj = PyDict_GetItemString(wxPython_dict, #name); \ + wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \ + SWIG_MakePtr(ptrbuf, (char *) &name, "_" #type "_p"); \ + ptrobj = PyString_FromString(ptrbuf); \ + PyObject_SetAttrString(obj, "this", ptrobj); \ + Py_DECREF(ptrobj) + + + 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); + + + REINITOBJ(wxTheClipboard, wxClipboard); + REINITOBJ(wxTheMimeTypesManager, wxMimeTypesManager); + REINITOBJ2(wxDefaultValidator, wxValidator); + REINITOBJ2(wxNullImage, wxImage); + REINITOBJ2(wxNullAcceleratorTable, wxAcceleratorTable); + +#undef REINITOBJ +#undef REINITOBJ2 +} + //--------------------------------------------------------------------------- void wxPyClientData_dtor(wxPyClientData* self) { @@ -587,21 +669,37 @@ void wxPyOORClientData_dtor(wxPyOORClientData* self) { Py_INCREF(deadObjectClass); } - // TODO: If wxPyDOingCleanup, should we skip the code below? - // Clear the instance's dictionary, put the name of the old class into the - // instance, and then reset the class to be the dead class. - if (self->m_obj->ob_refcnt > 1) { // but only if there is more than one reference + // Only if there is more than one reference to the object + if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 ) { wxASSERT_MSG(PyInstance_Check(self->m_obj), 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 + + // Clear the instance's dictionary PyInstanceObject* inst = (PyInstanceObject*)self->m_obj; PyDict_Clear(inst->in_dict); + + // put the name of the old class into the instance, and then reset the + // class to be the dead class. PyDict_SetItemString(inst->in_dict, "_name", inst->in_class->cl_name); inst->in_class = (PyClassObject*)deadObjectClass; Py_INCREF(deadObjectClass); } + + // m_obj is DECREF's in the base class dtor... wxPyEndBlockThreads(); } + //--------------------------------------------------------------------------- // Stuff used by OOR to find the right wxPython class type to return and to // build it. @@ -1145,7 +1243,12 @@ size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) { off_t wxPyCBInputStream::OnSysSeek(off_t off, wxSeekMode mode) { wxPyBeginBlockThreads(); +#ifdef _LARGE_FILES + // off_t is a 64-bit value... + PyObject* arglist = Py_BuildValue("(Li)", off, mode); +#else PyObject* arglist = Py_BuildValue("(ii)", off, mode); +#endif PyObject* result = PyEval_CallObject(m_seek, arglist); Py_DECREF(arglist); Py_XDECREF(result); @@ -1153,6 +1256,7 @@ off_t wxPyCBInputStream::OnSysSeek(off_t off, wxSeekMode mode) { return OnSysTell(); } + off_t wxPyCBInputStream::OnSysTell() const { wxPyBeginBlockThreads(); PyObject* arglist = Py_BuildValue("()"); @@ -1160,7 +1264,13 @@ off_t wxPyCBInputStream::OnSysTell() const { Py_DECREF(arglist); off_t o = 0; if (result != NULL) { +#ifdef _LARGE_FILES + if (PyLong_Check(result)) + o = PyLong_AsLongLong(result); + else +#else o = PyInt_AsLong(result); +#endif Py_DECREF(result); }; wxPyEndBlockThreads(); @@ -1196,29 +1306,50 @@ void wxPyCallback::EventThunker(wxEvent& event) { PyObject* result; PyObject* arg; PyObject* tuple; - + bool checkSkip = FALSE; wxPyBeginBlockThreads(); wxString className = event.GetClassInfo()->GetClassName(); - if (className == wxT("wxPyEvent")) - arg = ((wxPyEvent*)&event)->GetSelf(); - else if (className == wxT("wxPyCommandEvent")) - arg = ((wxPyCommandEvent*)&event)->GetSelf(); + // If the event is one of these types then pass the original + // event object instead of the one passed to us. + if ( className == wxT("wxPyEvent") ) { + arg = ((wxPyEvent*)&event)->GetSelf(); + checkSkip = ((wxPyEvent*)&event)->GetCloned(); + } + else if ( className == wxT("wxPyCommandEvent") ) { + arg = ((wxPyCommandEvent*)&event)->GetSelf(); + checkSkip = ((wxPyCommandEvent*)&event)->GetCloned(); + } else { arg = wxPyConstructObject((void*)&event, className); } + // Call the event handler, passing the event object tuple = PyTuple_New(1); - PyTuple_SET_ITEM(tuple, 0, arg); + PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg result = PyEval_CallObject(func, tuple); - Py_DECREF(tuple); - if (result) { - Py_DECREF(result); + if ( result ) { + Py_DECREF(result); // result is ignored, but we still need to decref it PyErr_Clear(); // Just in case... } else { PyErr_Print(); } + + if ( checkSkip ) { + // if the event object was one of our special types and + // it had been cloned, then we need to extract the Skipped + // value from the original and set it in the clone. + result = PyObject_CallMethod(arg, "GetSkipped", ""); + if ( result ) { + event.Skip(PyInt_AsLong(result)); + Py_DECREF(result); + } else { + PyErr_Print(); + } + } + + Py_DECREF(tuple); wxPyEndBlockThreads(); } @@ -1454,8 +1585,8 @@ IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent); IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent); -wxPyEvent::wxPyEvent(int id) - : wxEvent(id) { +wxPyEvent::wxPyEvent(int winid, wxEventType commandType) + : wxEvent(winid, commandType) { }