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