]> git.saurik.com Git - wxWidgets.git/blame - wxPython/src/helpers.cpp
A fix for Python 2.2 which can sometimes call __wxCleanup before all
[wxWidgets.git] / wxPython / src / helpers.cpp
CommitLineData
7bf85405
RD
1/////////////////////////////////////////////////////////////////////////////
2// Name: helpers.cpp
03e9bead 3// Purpose: Helper functions/classes for the wxPython extension module
7bf85405
RD
4//
5// Author: Robin Dunn
6//
7// Created: 7/1/97
8// RCS-ID: $Id$
9// Copyright: (c) 1998 by Total Control Software
10// Licence: wxWindows license
11/////////////////////////////////////////////////////////////////////////////
12
694759cf 13#include <stdio.h> // get the correct definition of NULL
08127323 14
7bf85405
RD
15#undef DEBUG
16#include <Python.h>
17#include "helpers.h"
694759cf 18
af309447
RD
19#ifdef __WXMSW__
20#include <wx/msw/private.h>
78b57918 21#include <wx/msw/winundef.h>
4268f798 22#include <wx/msw/msvcrt.h>
af309447 23#endif
694759cf
RD
24
25#ifdef __WXGTK__
26#include <gtk/gtk.h>
54b96882
RD
27#include <gdk/gdkprivate.h>
28#include <wx/gtk/win_gtk.h>
694759cf 29#endif
7bf85405 30
cf694132 31
4268f798
RD
32//----------------------------------------------------------------------
33
1893b029
RD
34#ifdef __WXGTK__
35int WXDLLEXPORT wxEntryStart( int& argc, char** argv );
36#else
4268f798 37int WXDLLEXPORT wxEntryStart( int argc, char** argv );
1893b029 38#endif
4268f798
RD
39int WXDLLEXPORT wxEntryInitGui();
40void WXDLLEXPORT wxEntryCleanup();
41
42wxPyApp* wxPythonApp = NULL; // Global instance of application object
43
44
45#ifdef WXP_WITH_THREAD
46struct wxPyThreadState {
47 unsigned long tid;
48 PyThreadState* tstate;
49
50 wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL)
51 : tid(_tid), tstate(_tstate) {}
52};
53
54#include <wx/dynarray.h>
55WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray);
56#include <wx/arrimpl.cpp>
57WX_DEFINE_OBJARRAY(wxPyThreadStateArray);
58
59wxPyThreadStateArray* wxPyTStates = NULL;
60wxMutex* wxPyTMutex = NULL;
61#endif
7bf85405
RD
62
63
21f4bf45 64#ifdef __WXMSW__ // If building for win32...
21f4bf45
RD
65//----------------------------------------------------------------------
66// This gets run when the DLL is loaded. We just need to save a handle.
67//----------------------------------------------------------------------
9c039d08 68
21f4bf45
RD
69BOOL WINAPI DllMain(
70 HINSTANCE hinstDLL, // handle to DLL module
71 DWORD fdwReason, // reason for calling function
72 LPVOID lpvReserved // reserved
73 )
74{
af309447 75 wxSetInstance(hinstDLL);
21f4bf45
RD
76 return 1;
77}
78#endif
79
7bf85405 80//----------------------------------------------------------------------
4268f798 81// Classes for implementing the wxp main application shell.
7bf85405
RD
82//----------------------------------------------------------------------
83
7bf85405 84
cf694132
RD
85wxPyApp::wxPyApp() {
86// printf("**** ctor\n");
87}
88
89wxPyApp::~wxPyApp() {
90// printf("**** dtor\n");
91}
92
93
7bf85405 94// This one isn't acutally called... See __wxStart()
4268f798 95bool wxPyApp::OnInit() {
6999b0d8 96 return FALSE;
7bf85405
RD
97}
98
4268f798
RD
99
100int wxPyApp::MainLoop() {
7ff49f0c 101 int retval = 0;
af309447 102
7ff49f0c 103 DeletePendingObjects();
4268f798 104 bool initialized = wxTopLevelWindows.GetCount() != 0;
7ff49f0c 105#ifdef __WXGTK__
4268f798 106 m_initialized = initialized;
7ff49f0c 107#endif
7bf85405 108
4268f798 109 if (initialized) {
7ff49f0c 110 retval = wxApp::MainLoop();
4268f798 111 OnExit();
7ff49f0c
RD
112 }
113 return retval;
114}
7bf85405
RD
115
116
4268f798 117
fb5e0af0 118//---------------------------------------------------------------------
7bf85405
RD
119//----------------------------------------------------------------------
120
f6bcfd97 121
0d6f9504 122// This is where we pick up the first part of the wxEntry functionality...
f6bcfd97 123// The rest is in __wxStart and __wxCleanup. This function is called when
8bf5d46e 124// wxcmodule is imported. (Before there is a wxApp object.)
0d6f9504 125void __wxPreStart()
7bf85405 126{
de20db99
RD
127
128#ifdef __WXMSW__
44f68505 129// wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
de20db99
RD
130#endif
131
9d8bd15f 132#ifdef WXP_WITH_THREAD
1112b0c6 133 PyEval_InitThreads();
4268f798
RD
134 wxPyTStates = new wxPyThreadStateArray;
135 wxPyTMutex = new wxMutex;
9d8bd15f
RD
136#endif
137
0d6f9504
RD
138 // Bail out if there is already windows created. This means that the
139 // toolkit has already been initialized, as in embedding wxPython in
140 // a C++ wxWindows app.
141 if (wxTopLevelWindows.Number() > 0)
142 return;
7bf85405 143
7ff49f0c 144
9416aa89
RD
145 int argc = 0;
146 char** argv = NULL;
7ff49f0c 147 PyObject* sysargv = PySys_GetObject("argv");
9416aa89
RD
148 if (sysargv != NULL) {
149 argc = PyList_Size(sysargv);
150 argv = new char*[argc+1];
151 int x;
152 for(x=0; x<argc; x++)
153 argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
154 argv[argc] = NULL;
155 }
7bf85405 156
7ff49f0c 157 wxEntryStart(argc, argv);
f6bcfd97 158 delete [] argv;
0d6f9504
RD
159}
160
161
7ff49f0c 162
0d6f9504
RD
163// Start the user application, user App's OnInit method is a parameter here
164PyObject* __wxStart(PyObject* /* self */, PyObject* args)
165{
166 PyObject* onInitFunc = NULL;
167 PyObject* arglist;
168 PyObject* result;
169 long bResult;
170
0d6f9504
RD
171 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
172 return NULL;
173
83b18bab 174#if 0 // Try it out without this check, see how it does...
0d6f9504
RD
175 if (wxTopLevelWindows.Number() > 0) {
176 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
177 return NULL;
178 }
de20db99 179#endif
0d6f9504
RD
180
181 // This is the next part of the wxEntry functionality...
9416aa89
RD
182 int argc = 0;
183 char** argv = NULL;
f6bcfd97 184 PyObject* sysargv = PySys_GetObject("argv");
9416aa89
RD
185 if (sysargv != NULL) {
186 argc = PyList_Size(sysargv);
187 argv = new char*[argc+1];
188 int x;
189 for(x=0; x<argc; x++)
190 argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
191 argv[argc] = NULL;
192 }
f6bcfd97
BP
193 wxPythonApp->argc = argc;
194 wxPythonApp->argv = argv;
0d6f9504 195
7ff49f0c 196 wxEntryInitGui();
7bf85405
RD
197
198 // Call the Python App's OnInit function
199 arglist = PyTuple_New(0);
200 result = PyEval_CallObject(onInitFunc, arglist);
8bf5d46e
RD
201 if (!result) { // an exception was raised.
202 return NULL;
7bf85405
RD
203 }
204
205 if (! PyInt_Check(result)) {
206 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
207 return NULL;
208 }
209 bResult = PyInt_AS_LONG(result);
210 if (! bResult) {
194fa2ac 211 PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
7bf85405
RD
212 return NULL;
213 }
214
13dfc243 215#ifdef __WXGTK__
7ff49f0c 216 wxTheApp->m_initialized = (wxTopLevelWindows.GetCount() > 0);
13dfc243 217#endif
fb5e0af0 218
7bf85405
RD
219 Py_INCREF(Py_None);
220 return Py_None;
221}
222
4268f798 223
7ff49f0c
RD
224void __wxCleanup() {
225 wxEntryCleanup();
7faa9591 226#ifdef WXP_WITH_THREAD
4268f798
RD
227 delete wxPyTMutex;
228 wxPyTMutex = NULL;
229 wxPyTStates->Empty();
230 delete wxPyTStates;
231 wxPyTStates = NULL;
7faa9591 232#endif
7ff49f0c 233}
7bf85405
RD
234
235
236
9416aa89
RD
237static PyObject* wxPython_dict = NULL;
238static PyObject* wxPyPtrTypeMap = NULL;
239
7bf85405
RD
240PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
241{
242
243 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
244 return NULL;
245
246 if (!PyDict_Check(wxPython_dict)) {
247 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
248 return NULL;
249 }
9416aa89
RD
250
251 if (! wxPyPtrTypeMap)
252 wxPyPtrTypeMap = PyDict_New();
253 PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap);
254
255
7bf85405 256#ifdef __WXMOTIF__
21f4bf45
RD
257#define wxPlatform "__WXMOTIF__"
258#endif
be43cc44
RD
259#ifdef __WXX11__
260#define wxPlatform "__WXX11__"
7bf85405
RD
261#endif
262#ifdef __WXGTK__
21f4bf45 263#define wxPlatform "__WXGTK__"
7bf85405
RD
264#endif
265#if defined(__WIN32__) || defined(__WXMSW__)
fb5e0af0 266#define wxPlatform "__WXMSW__"
7bf85405
RD
267#endif
268#ifdef __WXMAC__
21f4bf45 269#define wxPlatform "__WXMAC__"
7bf85405
RD
270#endif
271
272 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
273
274 Py_INCREF(Py_None);
275 return Py_None;
276}
277
278
9416aa89
RD
279//---------------------------------------------------------------------------
280// Stuff used by OOR to find the right wxPython class type to return and to
281// build it.
282
283
284// The pointer type map is used when the "pointer" type name generated by SWIG
285// is not the same as the shadow class name, for example wxPyTreeCtrl
286// vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++,
287// so we'll just make it a Python dictionary in the wx module's namespace.
288void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
289 if (! wxPyPtrTypeMap)
290 wxPyPtrTypeMap = PyDict_New();
9416aa89
RD
291 PyDict_SetItemString(wxPyPtrTypeMap,
292 (char*)commonName,
293 PyString_FromString((char*)ptrName));
294}
295
296
297
298PyObject* wxPyClassExists(const char* className) {
299
300 if (!className)
301 return NULL;
302
303 char buff[64]; // should always be big enough...
304
305 sprintf(buff, "%sPtr", className);
306 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
307
308 return classobj; // returns NULL if not found
309}
310
311
2f4e9287 312PyObject* wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) {
0122b7e3
RD
313 PyObject* target = NULL;
314 bool isEvtHandler = FALSE;
9416aa89
RD
315
316 if (source) {
2aab8f16 317 // If it's derived from wxEvtHandler then there may
2f4e9287
RD
318 // already be a pointer to a Python object that we can use
319 // in the OOR data.
320 if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) {
321 isEvtHandler = TRUE;
0122b7e3
RD
322 wxEvtHandler* eh = (wxEvtHandler*)source;
323 wxPyClientData* data = (wxPyClientData*)eh->GetClientObject();
324 if (data) {
325 target = data->m_obj;
326 Py_INCREF(target);
327 }
9416aa89 328 }
0122b7e3
RD
329
330 if (! target) {
2aab8f16
RD
331 // Otherwise make it the old fashioned way by making a
332 // new shadow object and putting this pointer in it.
0122b7e3
RD
333 wxClassInfo* info = source->GetClassInfo();
334 wxChar* name = (wxChar*)info->GetClassName();
335 PyObject* klass = wxPyClassExists(name);
336 while (info && !klass) {
337 name = (wxChar*)info->GetBaseClassName1();
338 info = wxClassInfo::FindClass(name);
339 klass = wxPyClassExists(name);
340 }
341 if (info) {
342 target = wxPyConstructObject(source, name, klass, FALSE);
343 if (target && isEvtHandler)
344 ((wxEvtHandler*)source)->SetClientObject(new wxPyClientData(target));
345 } else {
346 wxString msg("wxPython class not found for ");
347 msg += source->GetClassInfo()->GetClassName();
348 PyErr_SetString(PyExc_NameError, msg.c_str());
349 target = NULL;
350 }
9416aa89
RD
351 }
352 } else { // source was NULL so return None.
353 Py_INCREF(Py_None); target = Py_None;
354 }
355 return target;
356}
357
0122b7e3 358
2f4e9287
RD
359PyObject* wxPyMake_wxSizer(wxSizer* source) {
360 PyObject* target = NULL;
361
362 if (source && wxIsKindOf(source, wxSizer)) {
363 // If it's derived from wxSizer then there may
364 // already be a pointer to a Python object that we can use
365 // in the OOR data.
366 wxSizer* sz = (wxSizer*)source;
367 wxPyClientData* data = (wxPyClientData*)sz->GetClientObject();
368 if (data) {
369 target = data->m_obj;
370 Py_INCREF(target);
371 }
372 }
373 if (! target) {
374 target = wxPyMake_wxObject(source, FALSE);
375 if (target != Py_None)
376 ((wxSizer*)source)->SetClientObject(new wxPyClientData(target));
377 }
378 return target;
379}
380
381
382
7bf85405
RD
383//---------------------------------------------------------------------------
384
c368d904 385PyObject* wxPyConstructObject(void* ptr,
1e7ecb7b 386 const char* className,
9416aa89 387 PyObject* klass,
1e7ecb7b 388 int setThisOwn) {
9416aa89 389
33510773
RD
390 PyObject* obj;
391 PyObject* arg;
9416aa89
RD
392 PyObject* item;
393 char swigptr[64]; // should always be big enough...
394 char buff[64];
395
396 if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)className)) != NULL) {
397 className = PyString_AsString(item);
398 }
399 sprintf(buff, "_%s_p", className);
400 SWIG_MakePtr(swigptr, ptr, buff);
401
402 arg = Py_BuildValue("(s)", swigptr);
403 obj = PyInstance_New(klass, arg, NULL);
404 Py_DECREF(arg);
405
406 if (setThisOwn) {
407 PyObject* one = PyInt_FromLong(1);
408 PyObject_SetAttrString(obj, "thisown", one);
409 Py_DECREF(one);
410 }
411
412 return obj;
413}
414
415
416PyObject* wxPyConstructObject(void* ptr,
417 const char* className,
418 int setThisOwn) {
419 PyObject* obj;
33510773
RD
420
421 if (!ptr) {
422 Py_INCREF(Py_None);
423 return Py_None;
424 }
425
9c039d08 426 char buff[64]; // should always be big enough...
7bf85405 427 sprintf(buff, "%sPtr", className);
c5943253 428
4268f798 429 wxASSERT_MSG(wxPython_dict, "wxPython_dict is not set yet!!");
c5943253 430
7bf85405
RD
431 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
432 if (! classobj) {
33510773
RD
433 char temp[128];
434 sprintf(temp,
435 "*** Unknown class name %s, tell Robin about it please ***",
436 buff);
437 obj = PyString_FromString(temp);
438 return obj;
7bf85405
RD
439 }
440
9416aa89 441 return wxPyConstructObject(ptr, className, classobj, setThisOwn);
7bf85405
RD
442}
443
d559219f 444//---------------------------------------------------------------------------
7bf85405 445
4958ea8f 446
cf694132 447#ifdef WXP_WITH_THREAD
4268f798
RD
448inline
449unsigned long wxPyGetCurrentThreadId() {
4958ea8f 450 return wxThread::GetCurrentId();
4268f798
RD
451}
452
be43cc44 453static PyThreadState* gs_shutdownTState;
4268f798
RD
454static
455PyThreadState* wxPyGetThreadState() {
be43cc44
RD
456 if (wxPyTMutex == NULL) // Python is shutting down...
457 return gs_shutdownTState;
458
4268f798
RD
459 unsigned long ctid = wxPyGetCurrentThreadId();
460 PyThreadState* tstate = NULL;
461
462 wxPyTMutex->Lock();
463 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
464 wxPyThreadState& info = wxPyTStates->Item(i);
465 if (info.tid == ctid) {
466 tstate = info.tstate;
467 break;
468 }
469 }
470 wxPyTMutex->Unlock();
471 wxASSERT_MSG(tstate, "PyThreadState should not be NULL!");
472 return tstate;
473}
474
475static
476void wxPySaveThreadState(PyThreadState* tstate) {
be43cc44
RD
477 if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread...
478 gs_shutdownTState = tstate;
479 return;
480 }
4268f798
RD
481 unsigned long ctid = wxPyGetCurrentThreadId();
482 wxPyTMutex->Lock();
483 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
484 wxPyThreadState& info = wxPyTStates->Item(i);
485 if (info.tid == ctid) {
486 info.tstate = tstate;
487 wxPyTMutex->Unlock();
488 return;
489 }
1112b0c6 490 }
4268f798
RD
491 // not found, so add it...
492 wxPyTStates->Add(new wxPyThreadState(ctid, tstate));
493 wxPyTMutex->Unlock();
494}
495
496#endif
497
498
499// Calls from Python to wxWindows code are wrapped in calls to these
500// functions:
501
502PyThreadState* wxPyBeginAllowThreads() {
503#ifdef WXP_WITH_THREAD
504 PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS;
505 wxPySaveThreadState(saved);
506 return saved;
507#else
508 return NULL;
509#endif
510}
511
512void wxPyEndAllowThreads(PyThreadState* saved) {
513#ifdef WXP_WITH_THREAD
514 PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS;
cf694132 515#endif
d559219f 516}
cf694132 517
cf694132 518
4268f798
RD
519
520// Calls from wxWindows back to Python code, or even any PyObject
521// manipulations, PyDECREF's and etc. are wrapped in calls to these functions:
522
523void wxPyBeginBlockThreads() {
cf694132 524#ifdef WXP_WITH_THREAD
4268f798
RD
525 PyThreadState* tstate = wxPyGetThreadState();
526 PyEval_RestoreThread(tstate);
527#endif
528}
529
530
531void wxPyEndBlockThreads() {
532#ifdef WXP_WITH_THREAD
533 PyThreadState* tstate = PyEval_SaveThread();
534 // Is there any need to save it again?
1112b0c6 535#endif
cf694132
RD
536}
537
19a97bd6 538
d559219f
RD
539//---------------------------------------------------------------------------
540
2f90df85
RD
541IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
542
d559219f
RD
543wxPyCallback::wxPyCallback(PyObject* func) {
544 m_func = func;
545 Py_INCREF(m_func);
546}
547
2f90df85
RD
548wxPyCallback::wxPyCallback(const wxPyCallback& other) {
549 m_func = other.m_func;
550 Py_INCREF(m_func);
551}
552
d559219f 553wxPyCallback::~wxPyCallback() {
4268f798 554 wxPyBeginBlockThreads();
d559219f 555 Py_DECREF(m_func);
4268f798 556 wxPyEndBlockThreads();
d559219f
RD
557}
558
cf694132
RD
559
560
7bf85405
RD
561// This function is used for all events destined for Python event handlers.
562void wxPyCallback::EventThunker(wxEvent& event) {
563 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
564 PyObject* func = cb->m_func;
565 PyObject* result;
566 PyObject* arg;
567 PyObject* tuple;
568
cf694132 569
4268f798 570 wxPyBeginBlockThreads();
65dd82cb
RD
571 wxString className = event.GetClassInfo()->GetClassName();
572
573 if (className == "wxPyEvent")
574 arg = ((wxPyEvent*)&event)->GetSelf();
575 else if (className == "wxPyCommandEvent")
576 arg = ((wxPyCommandEvent*)&event)->GetSelf();
577 else
578 arg = wxPyConstructObject((void*)&event, className);
7bf85405
RD
579
580 tuple = PyTuple_New(1);
581 PyTuple_SET_ITEM(tuple, 0, arg);
582 result = PyEval_CallObject(func, tuple);
7bf85405
RD
583 Py_DECREF(tuple);
584 if (result) {
585 Py_DECREF(result);
ac346f50 586 PyErr_Clear(); // Just in case...
7bf85405
RD
587 } else {
588 PyErr_Print();
589 }
4268f798 590 wxPyEndBlockThreads();
7bf85405
RD
591}
592
593
d559219f 594//----------------------------------------------------------------------
7bf85405 595
2f90df85
RD
596wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
597 m_lastFound = NULL;
598 m_self = other.m_self;
f6bcfd97
BP
599 m_class = other.m_class;
600 if (m_self) {
2f90df85 601 Py_INCREF(m_self);
f6bcfd97
BP
602 Py_INCREF(m_class);
603 }
2f90df85
RD
604}
605
606
33510773 607void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
d559219f 608 m_self = self;
33510773 609 m_class = klass;
b7312675 610 m_incRef = incref;
f6bcfd97 611 if (incref) {
2f90df85 612 Py_INCREF(m_self);
f6bcfd97
BP
613 Py_INCREF(m_class);
614 }
d559219f 615}
8bf5d46e 616
8bf5d46e 617
78b57918
RD
618#if PYTHON_API_VERSION >= 1011
619
620// Prior to Python 2.2 PyMethod_GetClass returned the class object
621// in which the method was defined. Starting with 2.2 it returns
622// "class that asked for the method" which seems totally bogus to me
623// but apprently if fixes some obscure problem waiting to happen in
624// Python. Since the API was not documented Guido and the gang felt
625// safe in changing it. Needless to say that totally screwed up the
626// logic below in wxPyCallbackHelper::findCallback, hence this icky
627// code to find the class where the method is actuallt defined...
628
629static
630PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name)
631{
632 int i, n;
633
634 if (PyType_Check(klass)) { // new style classes
635 // This code is borrowed/adapted from _PyType_Lookup in typeobject.c
4a98c806 636 // (TODO: This part is not tested yet, so I'm not sure it is correct...)
78b57918
RD
637 PyTypeObject* type = (PyTypeObject*)klass;
638 PyObject *mro, *res, *base, *dict;
639 /* Look in tp_dict of types in MRO */
640 mro = type->tp_mro;
641 assert(PyTuple_Check(mro));
642 n = PyTuple_GET_SIZE(mro);
643 for (i = 0; i < n; i++) {
644 base = PyTuple_GET_ITEM(mro, i);
645 if (PyClass_Check(base))
646 dict = ((PyClassObject *)base)->cl_dict;
647 else {
648 assert(PyType_Check(base));
649 dict = ((PyTypeObject *)base)->tp_dict;
650 }
651 assert(dict && PyDict_Check(dict));
652 res = PyDict_GetItem(dict, name);
653 if (res != NULL)
4a98c806 654 return base;
78b57918
RD
655 }
656 return NULL;
657 }
658
659 else if (PyClass_Check(klass)) { // old style classes
660 // This code is borrowed/adapted from class_lookup in classobject.c
661 PyClassObject* cp = (PyClassObject*)klass;
662 PyObject *value = PyDict_GetItem(cp->cl_dict, name);
663 if (value != NULL) {
664 return (PyObject*)cp;
665 }
666 n = PyTuple_Size(cp->cl_bases);
667 for (i = 0; i < n; i++) {
668 PyObject* base = PyTuple_GetItem(cp->cl_bases, i);
669 PyObject *v = PyFindClassWithAttr(base, name);
670 if (v != NULL)
671 return v;
672 }
673 return NULL;
674 }
675}
676#endif
677
678
679static
680PyObject* PyMethod_GetDefiningClass(PyObject* method, const char* name)
681{
682 PyObject* mgc = PyMethod_GET_CLASS(method);
683
684#if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
685 return mgc;
686#else // 2.2 and after, the hard way...
687
688 PyObject* nameo = PyString_FromString(name);
689 PyObject* klass = PyFindClassWithAttr(mgc, nameo);
690 Py_DECREF(nameo);
691 return klass;
692#endif
693}
694
695
696
de20db99 697bool wxPyCallbackHelper::findCallback(const char* name) const {
f6bcfd97
BP
698 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
699 self->m_lastFound = NULL;
78b57918
RD
700
701 // If the object (m_self) has an attibute of the given name...
de20db99 702 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
78b57918 703 PyObject *method, *klass;
de20db99 704 method = PyObject_GetAttrString(m_self, (char*)name);
f6bcfd97 705
78b57918
RD
706 // ...and if that attribute is a method, and if that method's class is
707 // not from a base class...
f6bcfd97 708 if (PyMethod_Check(method) &&
78b57918
RD
709 (klass = PyMethod_GetDefiningClass(method, (char*)name)) != NULL &&
710 ((klass == m_class) || PyClass_IsSubclass(klass, m_class))) {
8bf5d46e 711
78b57918 712 // ...then we'll save a pointer to the method so callCallback can call it.
f6bcfd97
BP
713 self->m_lastFound = method;
714 }
de20db99
RD
715 else {
716 Py_DECREF(method);
717 }
f6bcfd97 718 }
d559219f
RD
719 return m_lastFound != NULL;
720}
8bf5d46e 721
d559219f 722
f6bcfd97 723int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
d559219f
RD
724 PyObject* result;
725 int retval = FALSE;
726
727 result = callCallbackObj(argTuple);
728 if (result) { // Assumes an integer return type...
729 retval = PyInt_AsLong(result);
730 Py_DECREF(result);
731 PyErr_Clear(); // forget about it if it's not...
732 }
733 return retval;
734}
735
736// Invoke the Python callable object, returning the raw PyObject return
737// value. Caller should DECREF the return value and also call PyEval_SaveThread.
f6bcfd97 738PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
de20db99 739 PyObject* result;
d559219f 740
de20db99
RD
741 // Save a copy of the pointer in case the callback generates another
742 // callback. In that case m_lastFound will have a different value when
743 // it gets back here...
744 PyObject* method = m_lastFound;
745
746 result = PyEval_CallObject(method, argTuple);
d559219f 747 Py_DECREF(argTuple);
de20db99 748 Py_DECREF(method);
d559219f
RD
749 if (!result) {
750 PyErr_Print();
751 }
752 return result;
753}
714e6a9e 754
7bf85405 755
0122b7e3 756void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
1e7ecb7b
RD
757 cbh.setSelf(self, klass, incref);
758}
759
760bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
761 return cbh.findCallback(name);
762}
763
764int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
765 return cbh.callCallback(argTuple);
766}
767
768PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
769 return cbh.callCallbackObj(argTuple);
770}
771
772
773void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
1e7ecb7b 774 if (cbh->m_incRef) {
4268f798 775 wxPyBeginBlockThreads();
1e7ecb7b
RD
776 Py_XDECREF(cbh->m_self);
777 Py_XDECREF(cbh->m_class);
4268f798 778 wxPyEndBlockThreads();
1e7ecb7b 779 }
1e7ecb7b 780}
d559219f 781
65dd82cb
RD
782//---------------------------------------------------------------------------
783//---------------------------------------------------------------------------
2aab8f16 784// These event classes can be derived from in Python and passed through the event
c368d904 785// system without losing anything. They do this by keeping a reference to
65dd82cb
RD
786// themselves and some special case handling in wxPyCallback::EventThunker.
787
788
e19b7164 789wxPyEvtSelfRef::wxPyEvtSelfRef() {
65dd82cb
RD
790 //m_self = Py_None; // **** We don't do normal ref counting to prevent
791 //Py_INCREF(m_self); // circular loops...
194fa2ac 792 m_cloned = FALSE;
65dd82cb
RD
793}
794
e19b7164 795wxPyEvtSelfRef::~wxPyEvtSelfRef() {
4268f798 796 wxPyBeginBlockThreads();
65dd82cb
RD
797 if (m_cloned)
798 Py_DECREF(m_self);
4268f798 799 wxPyEndBlockThreads();
65dd82cb
RD
800}
801
e19b7164 802void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
4268f798 803 wxPyBeginBlockThreads();
65dd82cb
RD
804 if (m_cloned)
805 Py_DECREF(m_self);
806 m_self = self;
807 if (clone) {
808 Py_INCREF(m_self);
809 m_cloned = TRUE;
810 }
4268f798 811 wxPyEndBlockThreads();
65dd82cb
RD
812}
813
e19b7164 814PyObject* wxPyEvtSelfRef::GetSelf() const {
65dd82cb
RD
815 Py_INCREF(m_self);
816 return m_self;
817}
818
819
07b2e1cd
RD
820IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
821IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
822
823
65dd82cb
RD
824wxPyEvent::wxPyEvent(int id)
825 : wxEvent(id) {
826}
827
65dd82cb 828
07b2e1cd
RD
829wxPyEvent::wxPyEvent(const wxPyEvent& evt)
830 : wxEvent(evt)
831{
832 SetSelf(evt.m_self, TRUE);
65dd82cb
RD
833}
834
835
07b2e1cd
RD
836wxPyEvent::~wxPyEvent() {
837}
65dd82cb
RD
838
839
840wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
841 : wxCommandEvent(commandType, id) {
842}
843
65dd82cb 844
07b2e1cd
RD
845wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
846 : wxCommandEvent(evt)
847{
848 SetSelf(evt.m_self, TRUE);
65dd82cb
RD
849}
850
851
07b2e1cd
RD
852wxPyCommandEvent::~wxPyCommandEvent() {
853}
854
65dd82cb
RD
855
856
857
d559219f 858//---------------------------------------------------------------------------
7bf85405
RD
859//---------------------------------------------------------------------------
860
d559219f 861
7bf85405
RD
862wxPyTimer::wxPyTimer(PyObject* callback) {
863 func = callback;
864 Py_INCREF(func);
865}
866
867wxPyTimer::~wxPyTimer() {
4268f798 868 wxPyBeginBlockThreads();
7bf85405 869 Py_DECREF(func);
4268f798 870 wxPyEndBlockThreads();
7bf85405
RD
871}
872
873void wxPyTimer::Notify() {
185d7c3e
RD
874 if (!func || func == Py_None) {
875 wxTimer::Notify();
876 }
877 else {
4268f798 878 wxPyBeginBlockThreads();
185d7c3e
RD
879
880 PyObject* result;
881 PyObject* args = Py_BuildValue("()");
882
883 result = PyEval_CallObject(func, args);
884 Py_DECREF(args);
885 if (result) {
886 Py_DECREF(result);
887 PyErr_Clear();
888 } else {
889 PyErr_Print();
890 }
7bf85405 891
4268f798 892 wxPyEndBlockThreads();
7bf85405
RD
893 }
894}
895
896
cf694132 897
2f90df85 898//---------------------------------------------------------------------------
389c5527
RD
899//---------------------------------------------------------------------------
900// Convert a wxList to a Python List
901
65dd82cb 902PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
389c5527
RD
903 PyObject* pyList;
904 PyObject* pyObj;
905 wxObject* wxObj;
906 wxNode* node = list->First();
907
4268f798 908 wxPyBeginBlockThreads();
389c5527
RD
909 pyList = PyList_New(0);
910 while (node) {
911 wxObj = node->Data();
9416aa89 912 pyObj = wxPyMake_wxObject(wxObj); //wxPyConstructObject(wxObj, className);
389c5527
RD
913 PyList_Append(pyList, pyObj);
914 node = node->Next();
915 }
4268f798 916 wxPyEndBlockThreads();
389c5527
RD
917 return pyList;
918}
919
54b96882
RD
920//----------------------------------------------------------------------
921
922long wxPyGetWinHandle(wxWindow* win) {
923#ifdef __WXMSW__
924 return (long)win->GetHandle();
925#endif
926
927 // Find and return the actual X-Window.
928#ifdef __WXGTK__
929 if (win->m_wxwindow) {
930 GdkWindowPrivate* bwin = (GdkWindowPrivate*)GTK_PIZZA(win->m_wxwindow)->bin_window;
931 if (bwin) {
932 return (long)bwin->xwindow;
933 }
934 }
935#endif
936 return 0;
937}
938
7bf85405
RD
939//----------------------------------------------------------------------
940// Some helper functions for typemaps in my_typemaps.i, so they won't be
389c5527 941// included in every file...
7bf85405
RD
942
943
2f90df85 944byte* byte_LIST_helper(PyObject* source) {
b639c3c5
RD
945 if (!PyList_Check(source)) {
946 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
947 return NULL;
948 }
949 int count = PyList_Size(source);
950 byte* temp = new byte[count];
951 if (! temp) {
952 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
953 return NULL;
954 }
955 for (int x=0; x<count; x++) {
956 PyObject* o = PyList_GetItem(source, x);
957 if (! PyInt_Check(o)) {
958 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
959 return NULL;
960 }
961 temp[x] = (byte)PyInt_AsLong(o);
962 }
963 return temp;
964}
965
966
2f90df85 967int* int_LIST_helper(PyObject* source) {
7bf85405
RD
968 if (!PyList_Check(source)) {
969 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
970 return NULL;
971 }
972 int count = PyList_Size(source);
973 int* temp = new int[count];
974 if (! temp) {
975 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
976 return NULL;
977 }
978 for (int x=0; x<count; x++) {
979 PyObject* o = PyList_GetItem(source, x);
980 if (! PyInt_Check(o)) {
981 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
982 return NULL;
983 }
984 temp[x] = PyInt_AsLong(o);
985 }
986 return temp;
987}
988
989
2f90df85 990long* long_LIST_helper(PyObject* source) {
7bf85405
RD
991 if (!PyList_Check(source)) {
992 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
993 return NULL;
994 }
995 int count = PyList_Size(source);
996 long* temp = new long[count];
997 if (! temp) {
998 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
999 return NULL;
1000 }
1001 for (int x=0; x<count; x++) {
1002 PyObject* o = PyList_GetItem(source, x);
1003 if (! PyInt_Check(o)) {
1004 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1005 return NULL;
1006 }
1007 temp[x] = PyInt_AsLong(o);
1008 }
1009 return temp;
1010}
1011
1012
2f90df85 1013char** string_LIST_helper(PyObject* source) {
7bf85405
RD
1014 if (!PyList_Check(source)) {
1015 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1016 return NULL;
1017 }
1018 int count = PyList_Size(source);
1019 char** temp = new char*[count];
1020 if (! temp) {
1021 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1022 return NULL;
1023 }
1024 for (int x=0; x<count; x++) {
1025 PyObject* o = PyList_GetItem(source, x);
1026 if (! PyString_Check(o)) {
1027 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
1028 return NULL;
1029 }
1030 temp[x] = PyString_AsString(o);
1031 }
1032 return temp;
1033}
1034
e0672e2f
RD
1035//--------------------------------
1036// Part of patch from Tim Hochberg
1037static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
1038 if (PyInt_Check(o1) && PyInt_Check(o2)) {
1039 point->x = PyInt_AS_LONG(o1);
1040 point->y = PyInt_AS_LONG(o2);
1041 return true;
1042 }
1043 if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
1044 point->x = (int)PyFloat_AS_DOUBLE(o1);
1045 point->y = (int)PyFloat_AS_DOUBLE(o2);
1046 return true;
1047 }
1048 if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
1049 // Disallow instances because they can cause havok
1050 return false;
1051 }
1052 if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
1053 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
1054 point->x = PyInt_AsLong(o1);
1055 point->y = PyInt_AsLong(o2);
1056 return true;
1057 }
1058 return false;
1059}
7bf85405
RD
1060
1061
e0672e2f
RD
1062wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
1063 // Putting all of the declarations here allows
1064 // us to put the error handling all in one place.
1065 int x;
1066 wxPoint* temp;
1067 PyObject *o, *o1, *o2;
9d37f964 1068 bool isFast = PyList_Check(source) || PyTuple_Check(source);
e0672e2f 1069
e0672e2f
RD
1070 if (!PySequence_Check(source)) {
1071 goto error0;
7bf85405 1072 }
9d37f964
RD
1073
1074 // The length of the sequence is returned in count.
e0672e2f
RD
1075 *count = PySequence_Length(source);
1076 if (*count < 0) {
1077 goto error0;
1078 }
1079
1080 temp = new wxPoint[*count];
1081 if (!temp) {
7bf85405
RD
1082 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1083 return NULL;
1084 }
e0672e2f
RD
1085 for (x=0; x<*count; x++) {
1086 // Get an item: try fast way first.
1087 if (isFast) {
1088 o = PySequence_Fast_GET_ITEM(source, x);
1089 }
1090 else {
1091 o = PySequence_GetItem(source, x);
1092 if (o == NULL) {
1093 goto error1;
1094 }
1095 }
7bf85405 1096
e0672e2f
RD
1097 // Convert o to wxPoint.
1098 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
1099 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
1100 o1 = PySequence_Fast_GET_ITEM(o, 0);
1101 o2 = PySequence_Fast_GET_ITEM(o, 1);
1102 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1103 goto error2;
1104 }
7bf85405 1105 }
d559219f
RD
1106 else if (PyInstance_Check(o)) {
1107 wxPoint* pt;
e0672e2f
RD
1108 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
1109 goto error2;
d559219f
RD
1110 }
1111 temp[x] = *pt;
1112 }
e0672e2f
RD
1113 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
1114 o1 = PySequence_GetItem(o, 0);
1115 o2 = PySequence_GetItem(o, 1);
1116 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1117 goto error3;
1118 }
1119 Py_DECREF(o1);
1120 Py_DECREF(o2);
1121 }
7bf85405 1122 else {
e0672e2f 1123 goto error2;
7bf85405 1124 }
e0672e2f
RD
1125 // Clean up.
1126 if (!isFast)
1127 Py_DECREF(o);
7bf85405
RD
1128 }
1129 return temp;
e0672e2f
RD
1130
1131error3:
1132 Py_DECREF(o1);
1133 Py_DECREF(o2);
1134error2:
1135 if (!isFast)
1136 Py_DECREF(o);
1137error1:
1138 delete temp;
1139error0:
1140 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
1141 return NULL;
7bf85405 1142}
e0672e2f
RD
1143// end of patch
1144//------------------------------
7bf85405
RD
1145
1146
2f90df85 1147wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
7bf85405
RD
1148 if (!PyList_Check(source)) {
1149 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1150 return NULL;
1151 }
1152 int count = PyList_Size(source);
1153 wxBitmap** temp = new wxBitmap*[count];
1154 if (! temp) {
1155 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1156 return NULL;
1157 }
1158 for (int x=0; x<count; x++) {
1159 PyObject* o = PyList_GetItem(source, x);
e166644c 1160 if (PyInstance_Check(o)) {
7bf85405 1161 wxBitmap* pt;
e166644c 1162 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
7bf85405
RD
1163 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
1164 return NULL;
1165 }
1166 temp[x] = pt;
1167 }
1168 else {
1169 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
1170 return NULL;
1171 }
1172 }
1173 return temp;
1174}
1175
1176
1177
2f90df85 1178wxString* wxString_LIST_helper(PyObject* source) {
7bf85405
RD
1179 if (!PyList_Check(source)) {
1180 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1181 return NULL;
1182 }
1183 int count = PyList_Size(source);
1184 wxString* temp = new wxString[count];
1185 if (! temp) {
1186 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1187 return NULL;
1188 }
1189 for (int x=0; x<count; x++) {
1190 PyObject* o = PyList_GetItem(source, x);
ecc08ead
RD
1191#if PYTHON_API_VERSION >= 1009
1192 if (! PyString_Check(o) && ! PyUnicode_Check(o)) {
1193 PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects.");
1194 return NULL;
1195 }
1196
1197 char* buff;
1198 int length;
1199 if (PyString_AsStringAndSize(o, &buff, &length) == -1)
1200 return NULL;
1201 temp[x] = wxString(buff, length);
1202#else
7bf85405
RD
1203 if (! PyString_Check(o)) {
1204 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
1205 return NULL;
1206 }
1207 temp[x] = PyString_AsString(o);
ecc08ead 1208#endif
7bf85405
RD
1209 }
1210 return temp;
1211}
1212
1213
2f90df85 1214wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
7bf85405
RD
1215 if (!PyList_Check(source)) {
1216 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1217 return NULL;
1218 }
1219 int count = PyList_Size(source);
1220 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
1221 if (! temp) {
1222 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1223 return NULL;
1224 }
1225 for (int x=0; x<count; x++) {
1226 PyObject* o = PyList_GetItem(source, x);
e166644c 1227 if (PyInstance_Check(o)) {
7bf85405 1228 wxAcceleratorEntry* ae;
e166644c 1229 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
7bf85405
RD
1230 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
1231 return NULL;
1232 }
1233 temp[x] = *ae;
1234 }
1235 else if (PyTuple_Check(o)) {
1236 PyObject* o1 = PyTuple_GetItem(o, 0);
1237 PyObject* o2 = PyTuple_GetItem(o, 1);
1238 PyObject* o3 = PyTuple_GetItem(o, 2);
0adbc166 1239 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
7bf85405
RD
1240 }
1241 else {
1242 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
1243 return NULL;
1244 }
1245 }
1246 return temp;
1247}
1248
bb0054cd 1249
9d37f964
RD
1250wxPen** wxPen_LIST_helper(PyObject* source) {
1251 if (!PyList_Check(source)) {
1252 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1253 return NULL;
1254 }
1255 int count = PyList_Size(source);
1256 wxPen** temp = new wxPen*[count];
1257 if (!temp) {
1258 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1259 return NULL;
1260 }
1261 for (int x=0; x<count; x++) {
1262 PyObject* o = PyList_GetItem(source, x);
1263 if (PyInstance_Check(o)) {
1264 wxPen* pt;
1265 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxPen_p")) {
1266 delete temp;
1267 PyErr_SetString(PyExc_TypeError,"Expected _wxPen_p.");
1268 return NULL;
1269 }
1270 temp[x] = pt;
1271 }
1272 else {
1273 delete temp;
1274 PyErr_SetString(PyExc_TypeError, "Expected a list of wxPens.");
1275 return NULL;
1276 }
1277 }
1278 return temp;
1279}
1280
1281
1282bool _2int_seq_helper(PyObject* source, int* i1, int* i2) {
1283 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1284 PyObject *o1, *o2;
1285
1286 if (!PySequence_Check(source) || PySequence_Length(source) != 2)
1287 return FALSE;
1288
1289 if (isFast) {
1290 o1 = PySequence_Fast_GET_ITEM(source, 0);
1291 o2 = PySequence_Fast_GET_ITEM(source, 1);
1292 }
1293 else {
1294 o1 = PySequence_GetItem(source, 0);
1295 o2 = PySequence_GetItem(source, 1);
1296 }
1297
1298 *i1 = PyInt_AsLong(o1);
1299 *i2 = PyInt_AsLong(o2);
1300
1301 if (! isFast) {
1302 Py_DECREF(o1);
1303 Py_DECREF(o2);
1304 }
1305 return TRUE;
1306}
1307
1308
1309bool _4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) {
1310 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1311 PyObject *o1, *o2, *o3, *o4;
1312
1313 if (!PySequence_Check(source) || PySequence_Length(source) != 4)
1314 return FALSE;
1315
1316 if (isFast) {
1317 o1 = PySequence_Fast_GET_ITEM(source, 0);
1318 o2 = PySequence_Fast_GET_ITEM(source, 1);
1319 o3 = PySequence_Fast_GET_ITEM(source, 2);
1320 o4 = PySequence_Fast_GET_ITEM(source, 3);
1321 }
1322 else {
1323 o1 = PySequence_GetItem(source, 0);
1324 o2 = PySequence_GetItem(source, 1);
1325 o3 = PySequence_GetItem(source, 2);
1326 o4 = PySequence_GetItem(source, 3);
1327 }
1328
1329 *i1 = PyInt_AsLong(o1);
1330 *i2 = PyInt_AsLong(o2);
1331 *i3 = PyInt_AsLong(o3);
1332 *i4 = PyInt_AsLong(o4);
1333
1334 if (! isFast) {
1335 Py_DECREF(o1);
1336 Py_DECREF(o2);
1337 Py_DECREF(o3);
1338 Py_DECREF(o4);
1339 }
1340 return TRUE;
1341}
1342
bb0054cd
RD
1343
1344//----------------------------------------------------------------------
bb0054cd 1345
2f90df85
RD
1346bool wxSize_helper(PyObject* source, wxSize** obj) {
1347
1348 // If source is an object instance then it may already be the right type
1349 if (PyInstance_Check(source)) {
1350 wxSize* ptr;
1351 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
1352 goto error;
1353 *obj = ptr;
1354 return TRUE;
1355 }
1356 // otherwise a 2-tuple of integers is expected
1357 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1358 PyObject* o1 = PySequence_GetItem(source, 0);
1359 PyObject* o2 = PySequence_GetItem(source, 1);
1360 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
1361 return TRUE;
1362 }
1363
1364 error:
1365 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
1366 return FALSE;
1367}
1368
1369bool wxPoint_helper(PyObject* source, wxPoint** obj) {
1370
1371 // If source is an object instance then it may already be the right type
1372 if (PyInstance_Check(source)) {
1373 wxPoint* ptr;
1374 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
1375 goto error;
1376 *obj = ptr;
1377 return TRUE;
1378 }
e0672e2f
RD
1379 // otherwise a length-2 sequence of integers is expected
1380 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
2f90df85
RD
1381 PyObject* o1 = PySequence_GetItem(source, 0);
1382 PyObject* o2 = PySequence_GetItem(source, 1);
78b57918
RD
1383 // This should really check for integers, not numbers -- but that would break code.
1384 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
1385 Py_DECREF(o1);
1386 Py_DECREF(o2);
1387 goto error;
1388 }
1389 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
1390 Py_DECREF(o1);
1391 Py_DECREF(o2);
2f90df85
RD
1392 return TRUE;
1393 }
2f90df85
RD
1394 error:
1395 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1396 return FALSE;
1397}
1398
1399
1400
1401bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
1402
1403 // If source is an object instance then it may already be the right type
1404 if (PyInstance_Check(source)) {
1405 wxRealPoint* ptr;
1406 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
1407 goto error;
1408 *obj = ptr;
1409 return TRUE;
1410 }
1411 // otherwise a 2-tuple of floats is expected
1412 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1413 PyObject* o1 = PySequence_GetItem(source, 0);
1414 PyObject* o2 = PySequence_GetItem(source, 1);
1415 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
1416 return TRUE;
1417 }
1418
1419 error:
1420 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
1421 return FALSE;
1422}
1423
1424
1425
1426
1427bool wxRect_helper(PyObject* source, wxRect** obj) {
1428
1429 // If source is an object instance then it may already be the right type
1430 if (PyInstance_Check(source)) {
1431 wxRect* ptr;
1432 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
1433 goto error;
1434 *obj = ptr;
1435 return TRUE;
1436 }
1437 // otherwise a 4-tuple of integers is expected
1438 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
1439 PyObject* o1 = PySequence_GetItem(source, 0);
1440 PyObject* o2 = PySequence_GetItem(source, 1);
1441 PyObject* o3 = PySequence_GetItem(source, 2);
1442 PyObject* o4 = PySequence_GetItem(source, 3);
1443 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
1444 PyInt_AsLong(o3), PyInt_AsLong(o4));
1445 return TRUE;
1446 }
1447
1448 error:
1449 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
1450 return FALSE;
1451}
1452
1453
1454
f6bcfd97
BP
1455bool wxColour_helper(PyObject* source, wxColour** obj) {
1456
1457 // If source is an object instance then it may already be the right type
1458 if (PyInstance_Check(source)) {
1459 wxColour* ptr;
1460 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
1461 goto error;
1462 *obj = ptr;
1463 return TRUE;
1464 }
1465 // otherwise a string is expected
1466 else if (PyString_Check(source)) {
1467 wxString spec = PyString_AS_STRING(source);
1112b0c6 1468 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
f6bcfd97
BP
1469 char* junk;
1470 int red = strtol(spec.Mid(1,2), &junk, 16);
1471 int green = strtol(spec.Mid(3,2), &junk, 16);
1472 int blue = strtol(spec.Mid(5,2), &junk, 16);
1473 **obj = wxColour(red, green, blue);
1474 return TRUE;
1475 }
1476 else { // it's a colour name
1477 **obj = wxColour(spec);
1478 return TRUE;
1479 }
1480 }
1481
1482 error:
de20db99 1483 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
f6bcfd97
BP
1484 return FALSE;
1485}
1486
1487
bb0054cd 1488//----------------------------------------------------------------------
b37c7e1d
RD
1489
1490PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
1491
1492 PyObject* list = PyList_New(0);
1493 for (size_t i=0; i < arr.GetCount(); i++) {
1494 PyObject* str = PyString_FromString(arr[i].c_str());
1495 PyList_Append(list, str);
8af26133 1496 Py_DECREF(str);
b37c7e1d
RD
1497 }
1498 return list;
1499}
1500
1501
293a0a86
RD
1502PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
1503
1504 PyObject* list = PyList_New(0);
1505 for (size_t i=0; i < arr.GetCount(); i++) {
1506 PyObject* number = PyInt_FromLong(arr[i]);
1507 PyList_Append(list, number);
1508 Py_DECREF(number);
1509 }
1510 return list;
1511}
1512
1513
bb0054cd 1514//----------------------------------------------------------------------
7bf85405 1515//----------------------------------------------------------------------
7bf85405 1516
7bf85405 1517
7bf85405 1518
de20db99 1519