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