#include <wx/gtk/win_gtk.h>
#endif
+#include <wx/clipbrd.h>
+#include <wx/mimetype.h>
+#include <wx/image.h>
+
//----------------------------------------------------------------------
#if PYTHON_API_VERSION <= 1007 && wxUSE_UNICODE
//----------------------------------------------------------------------
-#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;
//----------------------------------------------------------------------
+#if 0
static char* wxPyCopyCString(const wxChar* src)
{
wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(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)
{
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; x<argc; x++) {
- PyObject *item = PyList_GetItem(sysargv, x);
- argv[x] = wxPyCopyCString(Py2wxString(item));
- }
- argv[argc] = NULL;
- }
-
- wxEntryStart(argc, argv);
- delete [] argv;
}
-// Start the user application, user App's OnInit method is a parameter here
+
+// Initialize wxWindows and bootstrap the user application by calling the
+// wxApp's OnInit, which is a parameter to this funciton. See wxApp.__init__
+// in _extras.py to learn how the bootstrap is started.
PyObject* __wxStart(PyObject* /* self */, PyObject* args)
{
PyObject* onInitFunc = NULL;
- PyObject* arglist;
- PyObject* result;
+ PyObject* arglist= NULL;
+ PyObject* result = NULL;
+ PyObject* pyint = NULL;
long bResult;
if (!PyArg_ParseTuple(args, "O", &onInitFunc))
return NULL;
- // This is the next part of the wxEntry functionality...
+ // Get any command-line args passed to this program from the sys module
int argc = 0;
- wxChar** argv = NULL;
+ char** argv = NULL;
PyObject* sysargv = PySys_GetObject("argv");
if (sysargv != NULL) {
argc = PyList_Size(sysargv);
- argv = new wxChar*[argc+1];
+ argv = new char*[argc+1];
int x;
for(x=0; x<argc; x++) {
PyObject *pyArg = PyList_GetItem(sysargv, x);
- argv[x] = wxPyCopyWString(Py2wxString(pyArg));
+ argv[x] = PyString_AsString(pyArg);
}
argv[argc] = NULL;
}
- wxPythonApp->argc = 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);
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;
}
+
void __wxCleanup() {
wxPyDoingCleanup = TRUE;
if (wxPyDoCleanup)
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) {
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.
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);
return OnSysTell();
}
+
off_t wxPyCBInputStream::OnSysTell() const {
wxPyBeginBlockThreads();
PyObject* arglist = Py_BuildValue("()");
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();
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();
}
IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
-wxPyEvent::wxPyEvent(int id)
- : wxEvent(id) {
+wxPyEvent::wxPyEvent(int winid, wxEventType commandType)
+ : wxEvent(winid, commandType) {
}