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