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