#include <gtk/gtk.h>
#include <gdk/gdkprivate.h>
#include <wx/gtk/win_gtk.h>
-//#include <gdk/gdk.h>
-//#include <gdk/gdkx.h>
-//#include <gtk/gtkwindow.h>
-
-//extern GtkWidget *wxRootWindow;
-
#endif
-//---------------------------------------------------------------------------
-
-//wxHashTable* wxPyWindows = NULL;
-
-
-wxPoint wxPyDefaultPosition; //wxDefaultPosition);
-wxSize wxPyDefaultSize; //wxDefaultSize);
-wxString wxPyEmptyStr("");
-
#ifdef __WXMSW__ // If building for win32...
//---------------------------------------------------------------------
//----------------------------------------------------------------------
+#ifdef __WXMSW__
+#include "wx/msw/msvcrt.h"
+#endif
+
+
int WXDLLEXPORT wxEntryStart( int argc, char** argv );
int WXDLLEXPORT wxEntryInitGui();
void WXDLLEXPORT wxEntryCleanup();
#ifdef WXP_WITH_THREAD
PyThreadState* wxPyEventThreadState = NULL;
#endif
-static char* __nullArgv[1] = { 0 };
// This is where we pick up the first part of the wxEntry functionality...
// wxcmodule is imported. (Before there is a wxApp object.)
void __wxPreStart()
{
+
+#ifdef __WXMSW__
+// wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
+#endif
+
#ifdef WXP_WITH_THREAD
PyEval_InitThreads();
- wxPyEventThreadState = PyThreadState_Get();
+ wxPyEventThreadState = PyThreadState_Get(); // PyThreadState_New(PyThreadState_Get()->interp);
#endif
// Bail out if there is already windows created. This means that the
return;
+ int argc = 0;
+ char** argv = NULL;
PyObject* sysargv = PySys_GetObject("argv");
- int argc = PyList_Size(sysargv);
- char** argv = new char*[argc+1];
- int x;
- for(x=0; x<argc; x++)
- argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
- argv[argc] = NULL;
+ if (sysargv != NULL) {
+ argc = PyList_Size(sysargv);
+ argv = new char*[argc+1];
+ int x;
+ for(x=0; x<argc; x++)
+ argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
+ argv[argc] = NULL;
+ }
wxEntryStart(argc, argv);
delete [] argv;
if (!PyArg_ParseTuple(args, "O", &onInitFunc))
return NULL;
+#if 0 // Try it out without this check, see how it does...
if (wxTopLevelWindows.Number() > 0) {
PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
return NULL;
}
-
+#endif
// This is the next part of the wxEntry functionality...
+ int argc = 0;
+ char** argv = NULL;
PyObject* sysargv = PySys_GetObject("argv");
- int argc = PyList_Size(sysargv);
- char** argv = new char*[argc+1];
- int x;
- for(x=0; x<argc; x++)
- argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
- argv[argc] = NULL;
-
+ if (sysargv != NULL) {
+ argc = PyList_Size(sysargv);
+ argv = new char*[argc+1];
+ int x;
+ for(x=0; x<argc; x++)
+ argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
+ argv[argc] = NULL;
+ }
wxPythonApp->argc = argc;
wxPythonApp->argv = argv;
-PyObject* wxPython_dict;
+static PyObject* wxPython_dict = NULL;
+static PyObject* wxPyPtrTypeMap = NULL;
+
PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
{
PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
return NULL;
}
+
+ if (! wxPyPtrTypeMap)
+ wxPyPtrTypeMap = PyDict_New();
+ PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap);
+
+
#ifdef __WXMOTIF__
#define wxPlatform "__WXMOTIF__"
#endif
}
+//---------------------------------------------------------------------------
+// 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.
+void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
+ if (! wxPyPtrTypeMap)
+ wxPyPtrTypeMap = PyDict_New();
+
+ PyDict_SetItemString(wxPyPtrTypeMap,
+ (char*)commonName,
+ PyString_FromString((char*)ptrName));
+}
+
+
+
+PyObject* wxPyClassExists(const char* className) {
+
+ if (!className)
+ return NULL;
+
+ char buff[64]; // should always be big enough...
+
+ sprintf(buff, "%sPtr", className);
+ PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
+
+ return classobj; // returns NULL if not found
+}
+
+
+PyObject* wxPyMake_wxObject(wxObject* source) {
+ PyObject* target;
+
+ if (source) {
+ wxClassInfo* info = source->GetClassInfo();
+ wxChar* name = (wxChar*)info->GetClassName();
+ PyObject* klass = wxPyClassExists(name);
+ while (info && !klass) {
+ name = (wxChar*)info->GetBaseClassName1();
+ info = wxClassInfo::FindClass(name);
+ klass = wxPyClassExists(name);
+ }
+ if (info) {
+ target = wxPyConstructObject(source, name, klass, FALSE);
+ } else {
+ wxString msg("wxPython class not found for ");
+ msg += source->GetClassInfo()->GetClassName();
+ PyErr_SetString(PyExc_NameError, msg.c_str());
+ target = NULL;
+ }
+ } else { // source was NULL so return None.
+ Py_INCREF(Py_None); target = Py_None;
+ }
+ return target;
+}
+
//---------------------------------------------------------------------------
PyObject* wxPyConstructObject(void* ptr,
const char* className,
+ PyObject* klass,
int setThisOwn) {
- char buff[64]; // should always be big enough...
- char swigptr[64];
+ PyObject* obj;
+ PyObject* arg;
+ PyObject* item;
+ char swigptr[64]; // should always be big enough...
+ char buff[64];
+
+ if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)className)) != NULL) {
+ className = PyString_AsString(item);
+ }
sprintf(buff, "_%s_p", className);
SWIG_MakePtr(swigptr, ptr, buff);
- sprintf(buff, "%sPtr", className);
- PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
- if (! classobj) {
+ arg = Py_BuildValue("(s)", swigptr);
+ obj = PyInstance_New(klass, arg, NULL);
+ Py_DECREF(arg);
+
+ if (setThisOwn) {
+ PyObject* one = PyInt_FromLong(1);
+ PyObject_SetAttrString(obj, "thisown", one);
+ Py_DECREF(one);
+ }
+
+ return obj;
+}
+
+
+PyObject* wxPyConstructObject(void* ptr,
+ const char* className,
+ int setThisOwn) {
+ PyObject* obj;
+
+ if (!ptr) {
Py_INCREF(Py_None);
return Py_None;
}
- PyObject* arg = Py_BuildValue("(s)", swigptr);
- PyObject* obj = PyInstance_New(classobj, arg, NULL);
- Py_DECREF(arg);
+ char buff[64]; // should always be big enough...
- if (setThisOwn) {
- PyObject_SetAttrString(obj, "thisown", PyInt_FromLong(1));
+ sprintf(buff, "%sPtr", className);
+ PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
+ if (! classobj) {
+ char temp[128];
+ sprintf(temp,
+ "*** Unknown class name %s, tell Robin about it please ***",
+ buff);
+ obj = PyString_FromString(temp);
+ return obj;
}
- return obj;
+ return wxPyConstructObject(ptr, className, classobj, setThisOwn);
}
//---------------------------------------------------------------------------
-static unsigned int _wxPyNestCount = 0;
-
static PyThreadState* myPyThreadState_Get() {
PyThreadState* current;
current = PyThreadState_Swap(NULL);
}
-HELPEREXPORT bool wxPyRestoreThread() {
+bool wxPyRestoreThread() {
// NOTE: The Python API docs state that if a thread already has the
// interpreter lock and calls PyEval_RestoreThread again a deadlock
// occurs, so I put in this code as a guard condition since there are
// already have the lock. (I hope!)
//
#ifdef WXP_WITH_THREAD
- _wxPyNestCount += 1;
if (wxPyEventThreadState != myPyThreadState_Get()) {
- PyEval_RestoreThread(wxPyEventThreadState);
+ PyEval_AcquireThread(wxPyEventThreadState);
return TRUE;
}
else
}
-HELPEREXPORT void wxPySaveThread(bool doSave) {
+void wxPySaveThread(bool doSave) {
#ifdef WXP_WITH_THREAD
if (doSave) {
- wxPyEventThreadState = PyEval_SaveThread();
+ PyEval_ReleaseThread(wxPyEventThreadState);
}
- _wxPyNestCount -= 1;
#endif
}
Py_DECREF(tuple);
if (result) {
Py_DECREF(result);
- PyErr_Clear();
+ PyErr_Clear(); // Just in case...
} else {
PyErr_Print();
}
//----------------------------------------------------------------------
-wxPyCallbackHelper::wxPyCallbackHelper() {
- m_class = NULL;
- m_self = NULL;
- m_lastFound = NULL;
- m_incRef = FALSE;
-}
-
-
-wxPyCallbackHelper::~wxPyCallbackHelper() {
- bool doSave = wxPyRestoreThread();
- if (m_incRef) {
- Py_XDECREF(m_self);
- Py_XDECREF(m_class);
- }
- wxPySaveThread(doSave);
-}
-
wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
m_lastFound = NULL;
m_self = other.m_self;
}
-void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* _class, int incref) {
+void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
m_self = self;
- m_class = _class;
+ m_class = klass;
m_incRef = incref;
if (incref) {
Py_INCREF(m_self);
// If the object (m_self) has an attibute of the given name, and if that
// attribute is a method, and if that method's class is not from a base class,
// then we'll save a pointer to the method so callCallback can call it.
-bool wxPyCallbackHelper::findCallback(const wxString& name) const {
+bool wxPyCallbackHelper::findCallback(const char* name) const {
wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
self->m_lastFound = NULL;
- if (m_self && PyObject_HasAttrString(m_self, (char*)name.c_str())) {
+ if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
PyObject* method;
- method = PyObject_GetAttrString(m_self, (char*)name.c_str());
+ method = PyObject_GetAttrString(m_self, (char*)name);
if (PyMethod_Check(method) &&
((PyMethod_GET_CLASS(method) == m_class) ||
self->m_lastFound = method;
}
+ else {
+ Py_DECREF(method);
+ }
}
return m_lastFound != NULL;
}
// Invoke the Python callable object, returning the raw PyObject return
// value. Caller should DECREF the return value and also call PyEval_SaveThread.
PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
- PyObject* result;
+ PyObject* result;
- result = PyEval_CallObject(m_lastFound, argTuple);
+ // Save a copy of the pointer in case the callback generates another
+ // callback. In that case m_lastFound will have a different value when
+ // it gets back here...
+ PyObject* method = m_lastFound;
+
+ result = PyEval_CallObject(method, argTuple);
Py_DECREF(argTuple);
+ Py_DECREF(method);
if (!result) {
PyErr_Print();
}
}
+void wxPyCBH_setSelf(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
+ cbh.setSelf(self, klass, incref);
+}
+
+bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
+ return cbh.findCallback(name);
+}
+
+int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
+ return cbh.callCallback(argTuple);
+}
+
+PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
+ return cbh.callCallbackObj(argTuple);
+}
+
+
+void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
+ bool doSave = wxPyRestoreThread();
+ if (cbh->m_incRef) {
+ Py_XDECREF(cbh->m_self);
+ Py_XDECREF(cbh->m_class);
+ }
+ wxPySaveThread(doSave);
+}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
}
void wxPyTimer::Notify() {
- bool doSave = wxPyRestoreThread();
-
- PyObject* result;
- PyObject* args = Py_BuildValue("()");
+ if (!func || func == Py_None) {
+ wxTimer::Notify();
+ }
+ else {
+ bool doSave = wxPyRestoreThread();
+
+ PyObject* result;
+ PyObject* args = Py_BuildValue("()");
+
+ result = PyEval_CallObject(func, args);
+ Py_DECREF(args);
+ if (result) {
+ Py_DECREF(result);
+ PyErr_Clear();
+ } else {
+ PyErr_Print();
+ }
- result = PyEval_CallObject(func, args);
- Py_DECREF(args);
- if (result) {
- Py_DECREF(result);
- PyErr_Clear();
- } else {
- PyErr_Print();
+ wxPySaveThread(doSave);
}
- wxPySaveThread(doSave);
}
pyList = PyList_New(0);
while (node) {
wxObj = node->Data();
- pyObj = wxPyConstructObject(wxObj, className);
+ pyObj = wxPyMake_wxObject(wxObj); //wxPyConstructObject(wxObj, className);
PyList_Append(pyList, pyObj);
node = node->Next();
}
return temp;
}
+//--------------------------------
+// Part of patch from Tim Hochberg
+static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
+ if (PyInt_Check(o1) && PyInt_Check(o2)) {
+ point->x = PyInt_AS_LONG(o1);
+ point->y = PyInt_AS_LONG(o2);
+ return true;
+ }
+ if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
+ point->x = (int)PyFloat_AS_DOUBLE(o1);
+ point->y = (int)PyFloat_AS_DOUBLE(o2);
+ return true;
+ }
+ if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
+ // Disallow instances because they can cause havok
+ return false;
+ }
+ if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
+ // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
+ point->x = PyInt_AsLong(o1);
+ point->y = PyInt_AsLong(o2);
+ return true;
+ }
+ return false;
+}
-wxPoint* wxPoint_LIST_helper(PyObject* source) {
- if (!PyList_Check(source)) {
- PyErr_SetString(PyExc_TypeError, "Expected a list object.");
- return NULL;
+#if PYTHON_API_VERSION < 1009
+#define PySequence_Fast_GET_ITEM(o, i)\
+ (PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
+#endif
+
+wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
+ // Putting all of the declarations here allows
+ // us to put the error handling all in one place.
+ int x;
+ wxPoint* temp;
+ PyObject *o, *o1, *o2;
+ int isFast = PyList_Check(source) || PyTuple_Check(source);
+
+ // The length of the sequence is returned in count.
+ if (!PySequence_Check(source)) {
+ goto error0;
}
- int count = PyList_Size(source);
- wxPoint* temp = new wxPoint[count];
- if (! temp) {
+ *count = PySequence_Length(source);
+ if (*count < 0) {
+ goto error0;
+ }
+
+ temp = new wxPoint[*count];
+ if (!temp) {
PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
return NULL;
}
- for (int x=0; x<count; x++) {
- PyObject* o = PyList_GetItem(source, x);
- if (PyTuple_Check(o)) {
- PyObject* o1 = PyTuple_GetItem(o, 0);
- PyObject* o2 = PyTuple_GetItem(o, 1);
+ for (x=0; x<*count; x++) {
+ // Get an item: try fast way first.
+ if (isFast) {
+ o = PySequence_Fast_GET_ITEM(source, x);
+ }
+ else {
+ o = PySequence_GetItem(source, x);
+ if (o == NULL) {
+ goto error1;
+ }
+ }
- temp[x].x = PyInt_AsLong(o1);
- temp[x].y = PyInt_AsLong(o2);
+ // Convert o to wxPoint.
+ if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
+ (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
+ o1 = PySequence_Fast_GET_ITEM(o, 0);
+ o2 = PySequence_Fast_GET_ITEM(o, 1);
+ if (!wxPointFromObjects(o1, o2, &temp[x])) {
+ goto error2;
+ }
}
else if (PyInstance_Check(o)) {
wxPoint* pt;
- if (SWIG_GetPtrObj(o,(void **) &pt,"_wxPoint_p")) {
- PyErr_SetString(PyExc_TypeError,"Expected _wxPoint_p.");
- return NULL;
+ if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
+ goto error2;
}
temp[x] = *pt;
}
+ else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
+ o1 = PySequence_GetItem(o, 0);
+ o2 = PySequence_GetItem(o, 1);
+ if (!wxPointFromObjects(o1, o2, &temp[x])) {
+ goto error3;
+ }
+ Py_DECREF(o1);
+ Py_DECREF(o2);
+ }
else {
- PyErr_SetString(PyExc_TypeError, "Expected a list of 2-tuples or wxPoints.");
- return NULL;
+ goto error2;
}
+ // Clean up.
+ if (!isFast)
+ Py_DECREF(o);
}
return temp;
+
+error3:
+ Py_DECREF(o1);
+ Py_DECREF(o2);
+error2:
+ if (!isFast)
+ Py_DECREF(o);
+error1:
+ delete temp;
+error0:
+ PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
+ return NULL;
}
+// end of patch
+//------------------------------
wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
*obj = ptr;
return TRUE;
}
- // otherwise a 2-tuple of integers is expected
- else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
+ // otherwise a length-2 sequence of integers is expected
+ if (PySequence_Check(source) && PySequence_Length(source) == 2) {
PyObject* o1 = PySequence_GetItem(source, 0);
PyObject* o2 = PySequence_GetItem(source, 1);
- **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
+ // This should really check for integers, not numbers -- but that would break code.
+ if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
+ Py_DECREF(o1);
+ Py_DECREF(o2);
+ goto error;
+ }
+ **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
+ Py_DECREF(o1);
+ Py_DECREF(o2);
return TRUE;
}
-
error:
PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
return FALSE;
// otherwise a string is expected
else if (PyString_Check(source)) {
wxString spec = PyString_AS_STRING(source);
- if (spec[0] == '#' && spec.Length() == 7) { // It's #RRGGBB
+ if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
char* junk;
int red = strtol(spec.Mid(1,2), &junk, 16);
int green = strtol(spec.Mid(3,2), &junk, 16);
}
error:
- PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or #RRGGBB.");
+ PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
return FALSE;
}
+