]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/helpers.cpp
d&d implementation and checklistbox enabled
[wxWidgets.git] / wxPython / src / helpers.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: helpers.cpp
3 // Purpose: Helper functions/classes for the wxPython extension module
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
13 #include <stdio.h> // get the correct definition of NULL
14
15 #undef DEBUG
16 #include <Python.h>
17 #include "helpers.h"
18
19 #ifdef __WXMSW__
20 #include <wx/msw/private.h>
21 #include <wx/msw/winundef.h>
22 #include <wx/msw/msvcrt.h>
23 #endif
24
25 #ifdef __WXGTK__
26 #include <gtk/gtk.h>
27 #include <gdk/gdkprivate.h>
28 #include <wx/gtk/win_gtk.h>
29 #endif
30
31
32 //----------------------------------------------------------------------
33
34
35 int WXDLLEXPORT wxEntryStart( int argc, char** argv );
36 int WXDLLEXPORT wxEntryInitGui();
37 void WXDLLEXPORT wxEntryCleanup();
38
39 wxPyApp* wxPythonApp = NULL; // Global instance of application object
40
41
42 #ifdef WXP_WITH_THREAD
43 struct 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>
52 WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray);
53 #include <wx/arrimpl.cpp>
54 WX_DEFINE_OBJARRAY(wxPyThreadStateArray);
55
56 wxPyThreadStateArray* wxPyTStates = NULL;
57 wxMutex* wxPyTMutex = NULL;
58 #endif
59
60
61 #ifdef __WXMSW__ // If building for win32...
62 //----------------------------------------------------------------------
63 // This gets run when the DLL is loaded. We just need to save a handle.
64 //----------------------------------------------------------------------
65
66 BOOL WINAPI DllMain(
67 HINSTANCE hinstDLL, // handle to DLL module
68 DWORD fdwReason, // reason for calling function
69 LPVOID lpvReserved // reserved
70 )
71 {
72 wxSetInstance(hinstDLL);
73 return 1;
74 }
75 #endif
76
77 //----------------------------------------------------------------------
78 // Classes for implementing the wxp main application shell.
79 //----------------------------------------------------------------------
80
81
82 wxPyApp::wxPyApp() {
83 // printf("**** ctor\n");
84 }
85
86 wxPyApp::~wxPyApp() {
87 // printf("**** dtor\n");
88 }
89
90
91 // This one isn't acutally called... See __wxStart()
92 bool wxPyApp::OnInit() {
93 return FALSE;
94 }
95
96
97 int wxPyApp::MainLoop() {
98 int retval = 0;
99
100 DeletePendingObjects();
101 bool initialized = wxTopLevelWindows.GetCount() != 0;
102 #ifdef __WXGTK__
103 m_initialized = initialized;
104 #endif
105
106 if (initialized) {
107 retval = wxApp::MainLoop();
108 OnExit();
109 }
110 return retval;
111 }
112
113
114
115 //---------------------------------------------------------------------
116 //----------------------------------------------------------------------
117
118
119 // This is where we pick up the first part of the wxEntry functionality...
120 // The rest is in __wxStart and __wxCleanup. This function is called when
121 // wxcmodule is imported. (Before there is a wxApp object.)
122 void __wxPreStart()
123 {
124
125 #ifdef __WXMSW__
126 // wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
127 #endif
128
129 #ifdef WXP_WITH_THREAD
130 PyEval_InitThreads();
131 wxPyTStates = new wxPyThreadStateArray;
132 wxPyTMutex = new wxMutex;
133 #endif
134
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;
140
141
142 int argc = 0;
143 char** argv = NULL;
144 PyObject* sysargv = PySys_GetObject("argv");
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 }
153
154 wxEntryStart(argc, argv);
155 delete [] argv;
156 }
157
158
159
160 // Start the user application, user App's OnInit method is a parameter here
161 PyObject* __wxStart(PyObject* /* self */, PyObject* args)
162 {
163 PyObject* onInitFunc = NULL;
164 PyObject* arglist;
165 PyObject* result;
166 long bResult;
167
168 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
169 return NULL;
170
171 #if 0 // Try it out without this check, see how it does...
172 if (wxTopLevelWindows.Number() > 0) {
173 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
174 return NULL;
175 }
176 #endif
177
178 // This is the next part of the wxEntry functionality...
179 int argc = 0;
180 char** argv = NULL;
181 PyObject* sysargv = PySys_GetObject("argv");
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 }
190 wxPythonApp->argc = argc;
191 wxPythonApp->argv = argv;
192
193 wxEntryInitGui();
194
195 // Call the Python App's OnInit function
196 arglist = PyTuple_New(0);
197 result = PyEval_CallObject(onInitFunc, arglist);
198 if (!result) { // an exception was raised.
199 return NULL;
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) {
208 PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
209 return NULL;
210 }
211
212 #ifdef __WXGTK__
213 wxTheApp->m_initialized = (wxTopLevelWindows.GetCount() > 0);
214 #endif
215
216 Py_INCREF(Py_None);
217 return Py_None;
218 }
219
220
221 void __wxCleanup() {
222 wxEntryCleanup();
223 delete wxPyTMutex;
224 wxPyTMutex = NULL;
225 wxPyTStates->Empty();
226 delete wxPyTStates;
227 wxPyTStates = NULL;
228 }
229
230
231
232 static PyObject* wxPython_dict = NULL;
233 static PyObject* wxPyPtrTypeMap = NULL;
234
235 PyObject* __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 }
245
246 if (! wxPyPtrTypeMap)
247 wxPyPtrTypeMap = PyDict_New();
248 PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap);
249
250
251 #ifdef __WXMOTIF__
252 #define wxPlatform "__WXMOTIF__"
253 #endif
254 #ifdef __WXQT__
255 #define wxPlatform "__WXQT__"
256 #endif
257 #ifdef __WXGTK__
258 #define wxPlatform "__WXGTK__"
259 #endif
260 #if defined(__WIN32__) || defined(__WXMSW__)
261 #define wxPlatform "__WXMSW__"
262 #endif
263 #ifdef __WXMAC__
264 #define wxPlatform "__WXMAC__"
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
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.
283 void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
284 if (! wxPyPtrTypeMap)
285 wxPyPtrTypeMap = PyDict_New();
286 PyDict_SetItemString(wxPyPtrTypeMap,
287 (char*)commonName,
288 PyString_FromString((char*)ptrName));
289 }
290
291
292
293 PyObject* 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
307 PyObject* wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) {
308 PyObject* target = NULL;
309 bool isEvtHandler = FALSE;
310
311 if (source) {
312 // If it's derived from wxEvtHandler then there may
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;
317 wxEvtHandler* eh = (wxEvtHandler*)source;
318 wxPyClientData* data = (wxPyClientData*)eh->GetClientObject();
319 if (data) {
320 target = data->m_obj;
321 Py_INCREF(target);
322 }
323 }
324
325 if (! target) {
326 // Otherwise make it the old fashioned way by making a
327 // new shadow object and putting this pointer in it.
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 }
346 }
347 } else { // source was NULL so return None.
348 Py_INCREF(Py_None); target = Py_None;
349 }
350 return target;
351 }
352
353
354 PyObject* 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
378 //---------------------------------------------------------------------------
379
380 PyObject* wxPyConstructObject(void* ptr,
381 const char* className,
382 PyObject* klass,
383 int setThisOwn) {
384
385 PyObject* obj;
386 PyObject* arg;
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
411 PyObject* wxPyConstructObject(void* ptr,
412 const char* className,
413 int setThisOwn) {
414 PyObject* obj;
415
416 if (!ptr) {
417 Py_INCREF(Py_None);
418 return Py_None;
419 }
420
421 char buff[64]; // should always be big enough...
422 sprintf(buff, "%sPtr", className);
423
424 wxASSERT_MSG(wxPython_dict, "wxPython_dict is not set yet!!");
425
426 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
427 if (! classobj) {
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;
434 }
435
436 return wxPyConstructObject(ptr, className, classobj, setThisOwn);
437 }
438
439 //---------------------------------------------------------------------------
440
441 // TODO: This should really be wxThread::GetCurrentId(), and I will do so
442 // after I make a quick 2.3.2.1 release.
443 #ifdef WXP_WITH_THREAD
444 #ifdef __WXGTK__ // does wxGTK always use pthreads?
445 #include <unistd.h>
446 #include <pthread.h>
447 #endif
448 inline
449 unsigned 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 ThreadID current ;
458 MacGetCurrentThread( &current ) ;
459 return (unsigned long)current;
460 #endif
461 }
462
463
464
465 static
466 PyThreadState* 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
483 static
484 void 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 }
494 }
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
506 PyThreadState* 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
516 void wxPyEndAllowThreads(PyThreadState* saved) {
517 #ifdef WXP_WITH_THREAD
518 PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS;
519 #endif
520 }
521
522
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
527 void wxPyBeginBlockThreads() {
528 #ifdef WXP_WITH_THREAD
529 PyThreadState* tstate = wxPyGetThreadState();
530 PyEval_RestoreThread(tstate);
531 #endif
532 }
533
534
535 void wxPyEndBlockThreads() {
536 #ifdef WXP_WITH_THREAD
537 PyThreadState* tstate = PyEval_SaveThread();
538 // Is there any need to save it again?
539 #endif
540 }
541
542
543 //---------------------------------------------------------------------------
544
545 IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
546
547 wxPyCallback::wxPyCallback(PyObject* func) {
548 m_func = func;
549 Py_INCREF(m_func);
550 }
551
552 wxPyCallback::wxPyCallback(const wxPyCallback& other) {
553 m_func = other.m_func;
554 Py_INCREF(m_func);
555 }
556
557 wxPyCallback::~wxPyCallback() {
558 wxPyBeginBlockThreads();
559 Py_DECREF(m_func);
560 wxPyEndBlockThreads();
561 }
562
563
564
565 // This function is used for all events destined for Python event handlers.
566 void 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
573
574 wxPyBeginBlockThreads();
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);
583
584 tuple = PyTuple_New(1);
585 PyTuple_SET_ITEM(tuple, 0, arg);
586 result = PyEval_CallObject(func, tuple);
587 Py_DECREF(tuple);
588 if (result) {
589 Py_DECREF(result);
590 PyErr_Clear(); // Just in case...
591 } else {
592 PyErr_Print();
593 }
594 wxPyEndBlockThreads();
595 }
596
597
598 //----------------------------------------------------------------------
599
600 wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
601 m_lastFound = NULL;
602 m_self = other.m_self;
603 m_class = other.m_class;
604 if (m_self) {
605 Py_INCREF(m_self);
606 Py_INCREF(m_class);
607 }
608 }
609
610
611 void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
612 m_self = self;
613 m_class = klass;
614 m_incRef = incref;
615 if (incref) {
616 Py_INCREF(m_self);
617 Py_INCREF(m_class);
618 }
619 }
620
621
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
633 static
634 PyObject* 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
640 // (TODO: This part is not tested yet, so I'm not sure it is correct...)
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)
658 return base;
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
683 static
684 PyObject* 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
701 bool wxPyCallbackHelper::findCallback(const char* name) const {
702 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
703 self->m_lastFound = NULL;
704
705 // If the object (m_self) has an attibute of the given name...
706 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
707 PyObject *method, *klass;
708 method = PyObject_GetAttrString(m_self, (char*)name);
709
710 // ...and if that attribute is a method, and if that method's class is
711 // not from a base class...
712 if (PyMethod_Check(method) &&
713 (klass = PyMethod_GetDefiningClass(method, (char*)name)) != NULL &&
714 ((klass == m_class) || PyClass_IsSubclass(klass, m_class))) {
715
716 // ...then we'll save a pointer to the method so callCallback can call it.
717 self->m_lastFound = method;
718 }
719 else {
720 Py_DECREF(method);
721 }
722 }
723 return m_lastFound != NULL;
724 }
725
726
727 int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
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.
742 PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
743 PyObject* result;
744
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);
751 Py_DECREF(argTuple);
752 Py_DECREF(method);
753 if (!result) {
754 PyErr_Print();
755 }
756 return result;
757 }
758
759
760 void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
761 cbh.setSelf(self, klass, incref);
762 }
763
764 bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
765 return cbh.findCallback(name);
766 }
767
768 int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
769 return cbh.callCallback(argTuple);
770 }
771
772 PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
773 return cbh.callCallbackObj(argTuple);
774 }
775
776
777 void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
778 if (cbh->m_incRef) {
779 wxPyBeginBlockThreads();
780 Py_XDECREF(cbh->m_self);
781 Py_XDECREF(cbh->m_class);
782 wxPyEndBlockThreads();
783 }
784 }
785
786 //---------------------------------------------------------------------------
787 //---------------------------------------------------------------------------
788 // These event classes can be derived from in Python and passed through the event
789 // system without losing anything. They do this by keeping a reference to
790 // themselves and some special case handling in wxPyCallback::EventThunker.
791
792
793 wxPyEvtSelfRef::wxPyEvtSelfRef() {
794 //m_self = Py_None; // **** We don't do normal ref counting to prevent
795 //Py_INCREF(m_self); // circular loops...
796 m_cloned = FALSE;
797 }
798
799 wxPyEvtSelfRef::~wxPyEvtSelfRef() {
800 wxPyBeginBlockThreads();
801 if (m_cloned)
802 Py_DECREF(m_self);
803 wxPyEndBlockThreads();
804 }
805
806 void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
807 wxPyBeginBlockThreads();
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 }
815 wxPyEndBlockThreads();
816 }
817
818 PyObject* wxPyEvtSelfRef::GetSelf() const {
819 Py_INCREF(m_self);
820 return m_self;
821 }
822
823
824 IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
825 IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
826
827
828 wxPyEvent::wxPyEvent(int id)
829 : wxEvent(id) {
830 }
831
832
833 wxPyEvent::wxPyEvent(const wxPyEvent& evt)
834 : wxEvent(evt)
835 {
836 SetSelf(evt.m_self, TRUE);
837 }
838
839
840 wxPyEvent::~wxPyEvent() {
841 }
842
843
844 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
845 : wxCommandEvent(commandType, id) {
846 }
847
848
849 wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
850 : wxCommandEvent(evt)
851 {
852 SetSelf(evt.m_self, TRUE);
853 }
854
855
856 wxPyCommandEvent::~wxPyCommandEvent() {
857 }
858
859
860
861
862 //---------------------------------------------------------------------------
863 //---------------------------------------------------------------------------
864
865
866 wxPyTimer::wxPyTimer(PyObject* callback) {
867 func = callback;
868 Py_INCREF(func);
869 }
870
871 wxPyTimer::~wxPyTimer() {
872 wxPyBeginBlockThreads();
873 Py_DECREF(func);
874 wxPyEndBlockThreads();
875 }
876
877 void wxPyTimer::Notify() {
878 if (!func || func == Py_None) {
879 wxTimer::Notify();
880 }
881 else {
882 wxPyBeginBlockThreads();
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 }
895
896 wxPyEndBlockThreads();
897 }
898 }
899
900
901
902 //---------------------------------------------------------------------------
903 //---------------------------------------------------------------------------
904 // Convert a wxList to a Python List
905
906 PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
907 PyObject* pyList;
908 PyObject* pyObj;
909 wxObject* wxObj;
910 wxNode* node = list->First();
911
912 wxPyBeginBlockThreads();
913 pyList = PyList_New(0);
914 while (node) {
915 wxObj = node->Data();
916 pyObj = wxPyMake_wxObject(wxObj); //wxPyConstructObject(wxObj, className);
917 PyList_Append(pyList, pyObj);
918 node = node->Next();
919 }
920 wxPyEndBlockThreads();
921 return pyList;
922 }
923
924 //----------------------------------------------------------------------
925
926 long 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
943 //----------------------------------------------------------------------
944 // Some helper functions for typemaps in my_typemaps.i, so they won't be
945 // included in every file...
946
947
948 byte* byte_LIST_helper(PyObject* source) {
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
971 int* int_LIST_helper(PyObject* source) {
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
994 long* long_LIST_helper(PyObject* source) {
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
1017 char** string_LIST_helper(PyObject* source) {
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
1039 //--------------------------------
1040 // Part of patch from Tim Hochberg
1041 static 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 }
1064
1065
1066 wxPoint* 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;
1072 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1073
1074 if (!PySequence_Check(source)) {
1075 goto error0;
1076 }
1077
1078 // The length of the sequence is returned in count.
1079 *count = PySequence_Length(source);
1080 if (*count < 0) {
1081 goto error0;
1082 }
1083
1084 temp = new wxPoint[*count];
1085 if (!temp) {
1086 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1087 return NULL;
1088 }
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 }
1100
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 }
1109 }
1110 else if (PyInstance_Check(o)) {
1111 wxPoint* pt;
1112 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
1113 goto error2;
1114 }
1115 temp[x] = *pt;
1116 }
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 }
1126 else {
1127 goto error2;
1128 }
1129 // Clean up.
1130 if (!isFast)
1131 Py_DECREF(o);
1132 }
1133 return temp;
1134
1135 error3:
1136 Py_DECREF(o1);
1137 Py_DECREF(o2);
1138 error2:
1139 if (!isFast)
1140 Py_DECREF(o);
1141 error1:
1142 delete temp;
1143 error0:
1144 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
1145 return NULL;
1146 }
1147 // end of patch
1148 //------------------------------
1149
1150
1151 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
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);
1164 if (PyInstance_Check(o)) {
1165 wxBitmap* pt;
1166 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
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
1182 wxString* wxString_LIST_helper(PyObject* source) {
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);
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
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);
1212 #endif
1213 }
1214 return temp;
1215 }
1216
1217
1218 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
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);
1231 if (PyInstance_Check(o)) {
1232 wxAcceleratorEntry* ae;
1233 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
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);
1243 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
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
1253
1254 wxPen** 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
1286 bool _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
1313 bool _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
1347
1348 //----------------------------------------------------------------------
1349
1350 bool 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
1373 bool 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 }
1383 // otherwise a length-2 sequence of integers is expected
1384 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
1385 PyObject* o1 = PySequence_GetItem(source, 0);
1386 PyObject* o2 = PySequence_GetItem(source, 1);
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);
1396 return TRUE;
1397 }
1398 error:
1399 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1400 return FALSE;
1401 }
1402
1403
1404
1405 bool 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
1431 bool 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
1459 bool 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);
1472 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
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:
1487 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
1488 return FALSE;
1489 }
1490
1491
1492 //----------------------------------------------------------------------
1493
1494 PyObject* 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);
1500 Py_DECREF(str);
1501 }
1502 return list;
1503 }
1504
1505
1506 //----------------------------------------------------------------------
1507 //----------------------------------------------------------------------
1508
1509
1510
1511