#endif
-//---------------------------------------------------------------------------
-
-//wxHashTable* wxPyWindows = NULL;
-
-
-wxPoint wxPyDefaultPosition; //wxDefaultPosition);
-wxSize wxPyDefaultSize; //wxDefaultSize);
-wxString wxPyEmptyStr("");
-
#ifdef __WXMSW__ // If building for win32...
#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...
#endif
#ifdef WXP_WITH_THREAD
+#if 0 // OLD THREAD STUFF
PyEval_InitThreads();
wxPyEventThreadState = PyThreadState_Get();
+#else
+ PyEval_InitThreads();
+ wxPyEventThreadState = PyThreadState_New(PyThreadState_Get()->interp);
+#endif
#endif
// Bail out if there is already windows created. This means that the
if (!PyArg_ParseTuple(args, "O", &onInitFunc))
return NULL;
-#if 0 // Try it out without this check, soo how it does...
+#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;
//---------------------------------------------------------------------------
PyObject* wxPyConstructObject(void* ptr,
- const char* className,
- int setThisOwn) {
+ const char* className,
+ int setThisOwn) {
PyObject* obj;
PyObject* arg;
//---------------------------------------------------------------------------
-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 0 // OLD THREAD STUFF
if (wxPyEventThreadState != myPyThreadState_Get()) {
PyEval_RestoreThread(wxPyEventThreadState);
return TRUE;
}
else
+#else
+ if (wxPyEventThreadState != myPyThreadState_Get()) {
+ PyEval_AcquireThread(wxPyEventThreadState);
+ return TRUE;
+ }
+ else
+#endif
#endif
return FALSE;
}
-HELPEREXPORT void wxPySaveThread(bool doSave) {
+void wxPySaveThread(bool doSave) {
#ifdef WXP_WITH_THREAD
+#if 0 // OLD THREAD STUFF
if (doSave) {
wxPyEventThreadState = PyEval_SaveThread();
}
- _wxPyNestCount -= 1;
+#else
+ if (doSave) {
+ PyEval_ReleaseThread(wxPyEventThreadState);
+ }
+#endif
#endif
}
//----------------------------------------------------------------------
-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;
// 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 {
- wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
PyObject* result;
// Save a copy of the pointer in case the callback generates another
}
+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);
+}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
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);