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