]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/helpers.cpp
warning fixed
[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 #undef FindWindow
22 #undef GetCharWidth
23 #undef LoadAccelerators
24 #undef GetClassInfo
25 #undef GetClassName
26 #endif
27
28 #ifdef __WXGTK__
29 #include <gtk/gtk.h>
30 #include <gdk/gdkprivate.h>
31 #include <wx/gtk/win_gtk.h>
32 //#include <gdk/gdk.h>
33 //#include <gdk/gdkx.h>
34 //#include <gtk/gtkwindow.h>
35
36 //extern GtkWidget *wxRootWindow;
37
38 #endif
39
40
41
42
43 #ifdef __WXMSW__ // If building for win32...
44 //----------------------------------------------------------------------
45 // This gets run when the DLL is loaded. We just need to save a handle.
46 //----------------------------------------------------------------------
47
48 BOOL WINAPI DllMain(
49 HINSTANCE hinstDLL, // handle to DLL module
50 DWORD fdwReason, // reason for calling function
51 LPVOID lpvReserved // reserved
52 )
53 {
54 wxSetInstance(hinstDLL);
55 return 1;
56 }
57 #endif
58
59 //----------------------------------------------------------------------
60 // Class for implementing the wxp main application shell.
61 //----------------------------------------------------------------------
62
63 wxPyApp *wxPythonApp = NULL; // Global instance of application object
64
65
66 wxPyApp::wxPyApp() {
67 // printf("**** ctor\n");
68 }
69
70 wxPyApp::~wxPyApp() {
71 // printf("**** dtor\n");
72 }
73
74
75 // This one isn't acutally called... See __wxStart()
76 bool wxPyApp::OnInit(void) {
77 return FALSE;
78 }
79
80 int wxPyApp::MainLoop(void) {
81 int retval = 0;
82
83 DeletePendingObjects();
84 #ifdef __WXGTK__
85 m_initialized = wxTopLevelWindows.GetCount() != 0;
86 #endif
87
88 if (Initialized()) {
89 retval = wxApp::MainLoop();
90 wxPythonApp->OnExit();
91 }
92 return retval;
93 }
94
95
96 //---------------------------------------------------------------------
97 //----------------------------------------------------------------------
98
99 #ifdef __WXMSW__
100 #include "wx/msw/msvcrt.h"
101 #endif
102
103
104 int WXDLLEXPORT wxEntryStart( int argc, char** argv );
105 int WXDLLEXPORT wxEntryInitGui();
106 void WXDLLEXPORT wxEntryCleanup();
107
108
109 #ifdef WXP_WITH_THREAD
110 PyThreadState* wxPyEventThreadState = NULL;
111 #endif
112
113
114 // This is where we pick up the first part of the wxEntry functionality...
115 // The rest is in __wxStart and __wxCleanup. This function is called when
116 // wxcmodule is imported. (Before there is a wxApp object.)
117 void __wxPreStart()
118 {
119
120 #ifdef __WXMSW__
121 // wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
122 #endif
123
124 #ifdef WXP_WITH_THREAD
125 #if 0 // OLD THREAD STUFF
126 PyEval_InitThreads();
127 wxPyEventThreadState = PyThreadState_Get();
128 #else
129 PyEval_InitThreads();
130 wxPyEventThreadState = PyThreadState_New(PyThreadState_Get()->interp);
131 #endif
132 #endif
133
134 // Bail out if there is already windows created. This means that the
135 // toolkit has already been initialized, as in embedding wxPython in
136 // a C++ wxWindows app.
137 if (wxTopLevelWindows.Number() > 0)
138 return;
139
140
141 PyObject* sysargv = PySys_GetObject("argv");
142 int argc = PyList_Size(sysargv);
143 char** argv = new char*[argc+1];
144 int x;
145 for(x=0; x<argc; x++)
146 argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
147 argv[argc] = NULL;
148
149 wxEntryStart(argc, argv);
150 delete [] argv;
151 }
152
153
154
155 // Start the user application, user App's OnInit method is a parameter here
156 PyObject* __wxStart(PyObject* /* self */, PyObject* args)
157 {
158 PyObject* onInitFunc = NULL;
159 PyObject* arglist;
160 PyObject* result;
161 long bResult;
162
163 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
164 return NULL;
165
166 #if 0 // Try it out without this check, see how it does...
167 if (wxTopLevelWindows.Number() > 0) {
168 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
169 return NULL;
170 }
171 #endif
172
173 // This is the next part of the wxEntry functionality...
174 PyObject* sysargv = PySys_GetObject("argv");
175 int argc = PyList_Size(sysargv);
176 char** argv = new char*[argc+1];
177 int x;
178 for(x=0; x<argc; x++)
179 argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
180 argv[argc] = NULL;
181
182 wxPythonApp->argc = argc;
183 wxPythonApp->argv = argv;
184
185 wxEntryInitGui();
186
187 // Call the Python App's OnInit function
188 arglist = PyTuple_New(0);
189 result = PyEval_CallObject(onInitFunc, arglist);
190 if (!result) { // an exception was raised.
191 return NULL;
192 }
193
194 if (! PyInt_Check(result)) {
195 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
196 return NULL;
197 }
198 bResult = PyInt_AS_LONG(result);
199 if (! bResult) {
200 PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
201 return NULL;
202 }
203
204 #ifdef __WXGTK__
205 wxTheApp->m_initialized = (wxTopLevelWindows.GetCount() > 0);
206 #endif
207
208 Py_INCREF(Py_None);
209 return Py_None;
210 }
211
212 void __wxCleanup() {
213 wxEntryCleanup();
214 }
215
216
217
218 PyObject* wxPython_dict;
219 PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
220 {
221
222 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
223 return NULL;
224
225 if (!PyDict_Check(wxPython_dict)) {
226 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
227 return NULL;
228 }
229 #ifdef __WXMOTIF__
230 #define wxPlatform "__WXMOTIF__"
231 #endif
232 #ifdef __WXQT__
233 #define wxPlatform "__WXQT__"
234 #endif
235 #ifdef __WXGTK__
236 #define wxPlatform "__WXGTK__"
237 #endif
238 #if defined(__WIN32__) || defined(__WXMSW__)
239 #define wxPlatform "__WXMSW__"
240 #endif
241 #ifdef __WXMAC__
242 #define wxPlatform "__WXMAC__"
243 #endif
244
245 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
246
247 Py_INCREF(Py_None);
248 return Py_None;
249 }
250
251
252 //---------------------------------------------------------------------------
253
254 PyObject* wxPyConstructObject(void* ptr,
255 const char* className,
256 int setThisOwn) {
257 PyObject* obj;
258 PyObject* arg;
259
260 if (!ptr) {
261 Py_INCREF(Py_None);
262 return Py_None;
263 }
264
265 char buff[64]; // should always be big enough...
266 char swigptr[64];
267
268 sprintf(buff, "_%s_p", className);
269 SWIG_MakePtr(swigptr, ptr, buff);
270
271 sprintf(buff, "%sPtr", className);
272 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
273 if (! classobj) {
274 //Py_INCREF(Py_None);
275 //return Py_None;
276 char temp[128];
277 sprintf(temp,
278 "*** Unknown class name %s, tell Robin about it please ***",
279 buff);
280 obj = PyString_FromString(temp);
281 return obj;
282 }
283
284 arg = Py_BuildValue("(s)", swigptr);
285 obj = PyInstance_New(classobj, arg, NULL);
286 Py_DECREF(arg);
287
288 if (setThisOwn) {
289 PyObject* one = PyInt_FromLong(1);
290 PyObject_SetAttrString(obj, "thisown", one);
291 Py_DECREF(one);
292 }
293
294 return obj;
295 }
296
297 //---------------------------------------------------------------------------
298
299 static PyThreadState* myPyThreadState_Get() {
300 PyThreadState* current;
301 current = PyThreadState_Swap(NULL);
302 PyThreadState_Swap(current);
303 return current;
304 }
305
306
307 bool wxPyRestoreThread() {
308 // NOTE: The Python API docs state that if a thread already has the
309 // interpreter lock and calls PyEval_RestoreThread again a deadlock
310 // occurs, so I put in this code as a guard condition since there are
311 // many possibilites for nested events and callbacks in wxPython. If
312 // The current thread is our thread, then we can assume that we
313 // already have the lock. (I hope!)
314 //
315 #ifdef WXP_WITH_THREAD
316 #if 0 // OLD THREAD STUFF
317 if (wxPyEventThreadState != myPyThreadState_Get()) {
318 PyEval_RestoreThread(wxPyEventThreadState);
319 return TRUE;
320 }
321 else
322 #else
323 if (wxPyEventThreadState != myPyThreadState_Get()) {
324 PyEval_AcquireThread(wxPyEventThreadState);
325 return TRUE;
326 }
327 else
328 #endif
329 #endif
330 return FALSE;
331 }
332
333
334 void wxPySaveThread(bool doSave) {
335 #ifdef WXP_WITH_THREAD
336 #if 0 // OLD THREAD STUFF
337 if (doSave) {
338 wxPyEventThreadState = PyEval_SaveThread();
339 }
340 #else
341 if (doSave) {
342 PyEval_ReleaseThread(wxPyEventThreadState);
343 }
344 #endif
345 #endif
346 }
347
348 //---------------------------------------------------------------------------
349
350
351 IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
352
353 wxPyCallback::wxPyCallback(PyObject* func) {
354 m_func = func;
355 Py_INCREF(m_func);
356 }
357
358 wxPyCallback::wxPyCallback(const wxPyCallback& other) {
359 m_func = other.m_func;
360 Py_INCREF(m_func);
361 }
362
363 wxPyCallback::~wxPyCallback() {
364 bool doSave = wxPyRestoreThread();
365 Py_DECREF(m_func);
366 wxPySaveThread(doSave);
367 }
368
369
370
371 // This function is used for all events destined for Python event handlers.
372 void wxPyCallback::EventThunker(wxEvent& event) {
373 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
374 PyObject* func = cb->m_func;
375 PyObject* result;
376 PyObject* arg;
377 PyObject* tuple;
378
379
380 bool doSave = wxPyRestoreThread();
381 wxString className = event.GetClassInfo()->GetClassName();
382
383 if (className == "wxPyEvent")
384 arg = ((wxPyEvent*)&event)->GetSelf();
385 else if (className == "wxPyCommandEvent")
386 arg = ((wxPyCommandEvent*)&event)->GetSelf();
387 else
388 arg = wxPyConstructObject((void*)&event, className);
389
390 tuple = PyTuple_New(1);
391 PyTuple_SET_ITEM(tuple, 0, arg);
392 result = PyEval_CallObject(func, tuple);
393 Py_DECREF(tuple);
394 if (result) {
395 Py_DECREF(result);
396 PyErr_Clear();
397 } else {
398 PyErr_Print();
399 }
400 wxPySaveThread(doSave);
401 }
402
403
404 //----------------------------------------------------------------------
405
406 wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
407 m_lastFound = NULL;
408 m_self = other.m_self;
409 m_class = other.m_class;
410 if (m_self) {
411 Py_INCREF(m_self);
412 Py_INCREF(m_class);
413 }
414 }
415
416
417 void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
418 m_self = self;
419 m_class = klass;
420 m_incRef = incref;
421 if (incref) {
422 Py_INCREF(m_self);
423 Py_INCREF(m_class);
424 }
425 }
426
427
428 // If the object (m_self) has an attibute of the given name, and if that
429 // attribute is a method, and if that method's class is not from a base class,
430 // then we'll save a pointer to the method so callCallback can call it.
431 bool wxPyCallbackHelper::findCallback(const char* name) const {
432 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
433 self->m_lastFound = NULL;
434 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
435 PyObject* method;
436 method = PyObject_GetAttrString(m_self, (char*)name);
437
438 if (PyMethod_Check(method) &&
439 ((PyMethod_GET_CLASS(method) == m_class) ||
440 PyClass_IsSubclass(PyMethod_GET_CLASS(method), m_class))) {
441
442 self->m_lastFound = method;
443 }
444 else {
445 Py_DECREF(method);
446 }
447 }
448 return m_lastFound != NULL;
449 }
450
451
452 int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
453 PyObject* result;
454 int retval = FALSE;
455
456 result = callCallbackObj(argTuple);
457 if (result) { // Assumes an integer return type...
458 retval = PyInt_AsLong(result);
459 Py_DECREF(result);
460 PyErr_Clear(); // forget about it if it's not...
461 }
462 return retval;
463 }
464
465 // Invoke the Python callable object, returning the raw PyObject return
466 // value. Caller should DECREF the return value and also call PyEval_SaveThread.
467 PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
468 PyObject* result;
469
470 // Save a copy of the pointer in case the callback generates another
471 // callback. In that case m_lastFound will have a different value when
472 // it gets back here...
473 PyObject* method = m_lastFound;
474
475 result = PyEval_CallObject(method, argTuple);
476 Py_DECREF(argTuple);
477 Py_DECREF(method);
478 if (!result) {
479 PyErr_Print();
480 }
481 return result;
482 }
483
484
485 void wxPyCBH_setSelf(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
486 cbh.setSelf(self, klass, incref);
487 }
488
489 bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
490 return cbh.findCallback(name);
491 }
492
493 int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
494 return cbh.callCallback(argTuple);
495 }
496
497 PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
498 return cbh.callCallbackObj(argTuple);
499 }
500
501
502 void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
503 bool doSave = wxPyRestoreThread();
504 if (cbh->m_incRef) {
505 Py_XDECREF(cbh->m_self);
506 Py_XDECREF(cbh->m_class);
507 }
508 wxPySaveThread(doSave);
509 }
510
511 //---------------------------------------------------------------------------
512 //---------------------------------------------------------------------------
513 // These classes can be derived from in Python and passed through the event
514 // system without losing anything. They do this by keeping a reference to
515 // themselves and some special case handling in wxPyCallback::EventThunker.
516
517
518 wxPyEvtSelfRef::wxPyEvtSelfRef() {
519 //m_self = Py_None; // **** We don't do normal ref counting to prevent
520 //Py_INCREF(m_self); // circular loops...
521 m_cloned = FALSE;
522 }
523
524 wxPyEvtSelfRef::~wxPyEvtSelfRef() {
525 bool doSave = wxPyRestoreThread();
526 if (m_cloned)
527 Py_DECREF(m_self);
528 wxPySaveThread(doSave);
529 }
530
531 void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
532 bool doSave = wxPyRestoreThread();
533 if (m_cloned)
534 Py_DECREF(m_self);
535 m_self = self;
536 if (clone) {
537 Py_INCREF(m_self);
538 m_cloned = TRUE;
539 }
540 wxPySaveThread(doSave);
541 }
542
543 PyObject* wxPyEvtSelfRef::GetSelf() const {
544 Py_INCREF(m_self);
545 return m_self;
546 }
547
548
549 wxPyEvent::wxPyEvent(int id)
550 : wxEvent(id) {
551 }
552
553 wxPyEvent::~wxPyEvent() {
554 }
555
556 // This one is so the event object can be Cloned...
557 void wxPyEvent::CopyObject(wxObject& dest) const {
558 wxEvent::CopyObject(dest);
559 ((wxPyEvent*)&dest)->SetSelf(m_self, TRUE);
560 }
561
562
563 IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);
564
565
566 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
567 : wxCommandEvent(commandType, id) {
568 }
569
570 wxPyCommandEvent::~wxPyCommandEvent() {
571 }
572
573 void wxPyCommandEvent::CopyObject(wxObject& dest) const {
574 wxCommandEvent::CopyObject(dest);
575 ((wxPyCommandEvent*)&dest)->SetSelf(m_self, TRUE);
576 }
577
578
579 IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);
580
581
582
583 //---------------------------------------------------------------------------
584 //---------------------------------------------------------------------------
585
586
587 wxPyTimer::wxPyTimer(PyObject* callback) {
588 func = callback;
589 Py_INCREF(func);
590 }
591
592 wxPyTimer::~wxPyTimer() {
593 bool doSave = wxPyRestoreThread();
594 Py_DECREF(func);
595 wxPySaveThread(doSave);
596 }
597
598 void wxPyTimer::Notify() {
599 if (!func || func == Py_None) {
600 wxTimer::Notify();
601 }
602 else {
603 bool doSave = wxPyRestoreThread();
604
605 PyObject* result;
606 PyObject* args = Py_BuildValue("()");
607
608 result = PyEval_CallObject(func, args);
609 Py_DECREF(args);
610 if (result) {
611 Py_DECREF(result);
612 PyErr_Clear();
613 } else {
614 PyErr_Print();
615 }
616
617 wxPySaveThread(doSave);
618 }
619 }
620
621
622
623 //---------------------------------------------------------------------------
624 //---------------------------------------------------------------------------
625 // Convert a wxList to a Python List
626
627 PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
628 PyObject* pyList;
629 PyObject* pyObj;
630 wxObject* wxObj;
631 wxNode* node = list->First();
632
633 bool doSave = wxPyRestoreThread();
634 pyList = PyList_New(0);
635 while (node) {
636 wxObj = node->Data();
637 pyObj = wxPyConstructObject(wxObj, className);
638 PyList_Append(pyList, pyObj);
639 node = node->Next();
640 }
641 wxPySaveThread(doSave);
642 return pyList;
643 }
644
645 //----------------------------------------------------------------------
646
647 long wxPyGetWinHandle(wxWindow* win) {
648 #ifdef __WXMSW__
649 return (long)win->GetHandle();
650 #endif
651
652 // Find and return the actual X-Window.
653 #ifdef __WXGTK__
654 if (win->m_wxwindow) {
655 GdkWindowPrivate* bwin = (GdkWindowPrivate*)GTK_PIZZA(win->m_wxwindow)->bin_window;
656 if (bwin) {
657 return (long)bwin->xwindow;
658 }
659 }
660 #endif
661 return 0;
662 }
663
664 //----------------------------------------------------------------------
665 // Some helper functions for typemaps in my_typemaps.i, so they won't be
666 // included in every file...
667
668
669 byte* byte_LIST_helper(PyObject* source) {
670 if (!PyList_Check(source)) {
671 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
672 return NULL;
673 }
674 int count = PyList_Size(source);
675 byte* temp = new byte[count];
676 if (! temp) {
677 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
678 return NULL;
679 }
680 for (int x=0; x<count; x++) {
681 PyObject* o = PyList_GetItem(source, x);
682 if (! PyInt_Check(o)) {
683 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
684 return NULL;
685 }
686 temp[x] = (byte)PyInt_AsLong(o);
687 }
688 return temp;
689 }
690
691
692 int* int_LIST_helper(PyObject* source) {
693 if (!PyList_Check(source)) {
694 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
695 return NULL;
696 }
697 int count = PyList_Size(source);
698 int* temp = new int[count];
699 if (! temp) {
700 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
701 return NULL;
702 }
703 for (int x=0; x<count; x++) {
704 PyObject* o = PyList_GetItem(source, x);
705 if (! PyInt_Check(o)) {
706 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
707 return NULL;
708 }
709 temp[x] = PyInt_AsLong(o);
710 }
711 return temp;
712 }
713
714
715 long* long_LIST_helper(PyObject* source) {
716 if (!PyList_Check(source)) {
717 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
718 return NULL;
719 }
720 int count = PyList_Size(source);
721 long* temp = new long[count];
722 if (! temp) {
723 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
724 return NULL;
725 }
726 for (int x=0; x<count; x++) {
727 PyObject* o = PyList_GetItem(source, x);
728 if (! PyInt_Check(o)) {
729 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
730 return NULL;
731 }
732 temp[x] = PyInt_AsLong(o);
733 }
734 return temp;
735 }
736
737
738 char** string_LIST_helper(PyObject* source) {
739 if (!PyList_Check(source)) {
740 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
741 return NULL;
742 }
743 int count = PyList_Size(source);
744 char** temp = new char*[count];
745 if (! temp) {
746 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
747 return NULL;
748 }
749 for (int x=0; x<count; x++) {
750 PyObject* o = PyList_GetItem(source, x);
751 if (! PyString_Check(o)) {
752 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
753 return NULL;
754 }
755 temp[x] = PyString_AsString(o);
756 }
757 return temp;
758 }
759
760 //--------------------------------
761 // Part of patch from Tim Hochberg
762 static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
763 if (PyInt_Check(o1) && PyInt_Check(o2)) {
764 point->x = PyInt_AS_LONG(o1);
765 point->y = PyInt_AS_LONG(o2);
766 return true;
767 }
768 if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
769 point->x = (int)PyFloat_AS_DOUBLE(o1);
770 point->y = (int)PyFloat_AS_DOUBLE(o2);
771 return true;
772 }
773 if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
774 // Disallow instances because they can cause havok
775 return false;
776 }
777 if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
778 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
779 point->x = PyInt_AsLong(o1);
780 point->y = PyInt_AsLong(o2);
781 return true;
782 }
783 return false;
784 }
785
786
787 #if PYTHON_API_VERSION < 1009
788 #define PySequence_Fast_GET_ITEM(o, i)\
789 (PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
790 #endif
791
792 wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
793 // Putting all of the declarations here allows
794 // us to put the error handling all in one place.
795 int x;
796 wxPoint* temp;
797 PyObject *o, *o1, *o2;
798 int isFast = PyList_Check(source) || PyTuple_Check(source);
799
800 // The length of the sequence is returned in count.
801 if (!PySequence_Check(source)) {
802 goto error0;
803 }
804 *count = PySequence_Length(source);
805 if (*count < 0) {
806 goto error0;
807 }
808
809 temp = new wxPoint[*count];
810 if (!temp) {
811 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
812 return NULL;
813 }
814 for (x=0; x<*count; x++) {
815 // Get an item: try fast way first.
816 if (isFast) {
817 o = PySequence_Fast_GET_ITEM(source, x);
818 }
819 else {
820 o = PySequence_GetItem(source, x);
821 if (o == NULL) {
822 goto error1;
823 }
824 }
825
826 // Convert o to wxPoint.
827 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
828 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
829 o1 = PySequence_Fast_GET_ITEM(o, 0);
830 o2 = PySequence_Fast_GET_ITEM(o, 1);
831 if (!wxPointFromObjects(o1, o2, &temp[x])) {
832 goto error2;
833 }
834 }
835 else if (PyInstance_Check(o)) {
836 wxPoint* pt;
837 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
838 goto error2;
839 }
840 temp[x] = *pt;
841 }
842 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
843 o1 = PySequence_GetItem(o, 0);
844 o2 = PySequence_GetItem(o, 1);
845 if (!wxPointFromObjects(o1, o2, &temp[x])) {
846 goto error3;
847 }
848 Py_DECREF(o1);
849 Py_DECREF(o2);
850 }
851 else {
852 goto error2;
853 }
854 // Clean up.
855 if (!isFast)
856 Py_DECREF(o);
857 }
858 return temp;
859
860 error3:
861 Py_DECREF(o1);
862 Py_DECREF(o2);
863 error2:
864 if (!isFast)
865 Py_DECREF(o);
866 error1:
867 delete temp;
868 error0:
869 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
870 return NULL;
871 }
872 // end of patch
873 //------------------------------
874
875
876 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
877 if (!PyList_Check(source)) {
878 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
879 return NULL;
880 }
881 int count = PyList_Size(source);
882 wxBitmap** temp = new wxBitmap*[count];
883 if (! temp) {
884 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
885 return NULL;
886 }
887 for (int x=0; x<count; x++) {
888 PyObject* o = PyList_GetItem(source, x);
889 if (PyInstance_Check(o)) {
890 wxBitmap* pt;
891 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
892 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
893 return NULL;
894 }
895 temp[x] = pt;
896 }
897 else {
898 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
899 return NULL;
900 }
901 }
902 return temp;
903 }
904
905
906
907 wxString* wxString_LIST_helper(PyObject* source) {
908 if (!PyList_Check(source)) {
909 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
910 return NULL;
911 }
912 int count = PyList_Size(source);
913 wxString* temp = new wxString[count];
914 if (! temp) {
915 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
916 return NULL;
917 }
918 for (int x=0; x<count; x++) {
919 PyObject* o = PyList_GetItem(source, x);
920 if (! PyString_Check(o)) {
921 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
922 return NULL;
923 }
924 temp[x] = PyString_AsString(o);
925 }
926 return temp;
927 }
928
929
930 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
931 if (!PyList_Check(source)) {
932 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
933 return NULL;
934 }
935 int count = PyList_Size(source);
936 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
937 if (! temp) {
938 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
939 return NULL;
940 }
941 for (int x=0; x<count; x++) {
942 PyObject* o = PyList_GetItem(source, x);
943 if (PyInstance_Check(o)) {
944 wxAcceleratorEntry* ae;
945 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
946 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
947 return NULL;
948 }
949 temp[x] = *ae;
950 }
951 else if (PyTuple_Check(o)) {
952 PyObject* o1 = PyTuple_GetItem(o, 0);
953 PyObject* o2 = PyTuple_GetItem(o, 1);
954 PyObject* o3 = PyTuple_GetItem(o, 2);
955
956 temp[x].m_flags = PyInt_AsLong(o1);
957 temp[x].m_keyCode = PyInt_AsLong(o2);
958 temp[x].m_command = PyInt_AsLong(o3);
959 }
960 else {
961 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
962 return NULL;
963 }
964 }
965 return temp;
966 }
967
968
969
970 //----------------------------------------------------------------------
971
972 bool wxSize_helper(PyObject* source, wxSize** obj) {
973
974 // If source is an object instance then it may already be the right type
975 if (PyInstance_Check(source)) {
976 wxSize* ptr;
977 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
978 goto error;
979 *obj = ptr;
980 return TRUE;
981 }
982 // otherwise a 2-tuple of integers is expected
983 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
984 PyObject* o1 = PySequence_GetItem(source, 0);
985 PyObject* o2 = PySequence_GetItem(source, 1);
986 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
987 return TRUE;
988 }
989
990 error:
991 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
992 return FALSE;
993 }
994
995 bool wxPoint_helper(PyObject* source, wxPoint** obj) {
996
997 // If source is an object instance then it may already be the right type
998 if (PyInstance_Check(source)) {
999 wxPoint* ptr;
1000 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
1001 goto error;
1002 *obj = ptr;
1003 return TRUE;
1004 }
1005 // otherwise a length-2 sequence of integers is expected
1006 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
1007 PyObject* o1 = PySequence_GetItem(source, 0);
1008 PyObject* o2 = PySequence_GetItem(source, 1);
1009 // This should really check for integers, not numbers -- but that would break code.
1010 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
1011 Py_DECREF(o1);
1012 Py_DECREF(o2);
1013 goto error;
1014 }
1015 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
1016 Py_DECREF(o1);
1017 Py_DECREF(o2);
1018 return TRUE;
1019 }
1020 error:
1021 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1022 return FALSE;
1023 }
1024
1025
1026
1027 bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
1028
1029 // If source is an object instance then it may already be the right type
1030 if (PyInstance_Check(source)) {
1031 wxRealPoint* ptr;
1032 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
1033 goto error;
1034 *obj = ptr;
1035 return TRUE;
1036 }
1037 // otherwise a 2-tuple of floats is expected
1038 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1039 PyObject* o1 = PySequence_GetItem(source, 0);
1040 PyObject* o2 = PySequence_GetItem(source, 1);
1041 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
1042 return TRUE;
1043 }
1044
1045 error:
1046 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
1047 return FALSE;
1048 }
1049
1050
1051
1052
1053 bool wxRect_helper(PyObject* source, wxRect** obj) {
1054
1055 // If source is an object instance then it may already be the right type
1056 if (PyInstance_Check(source)) {
1057 wxRect* ptr;
1058 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
1059 goto error;
1060 *obj = ptr;
1061 return TRUE;
1062 }
1063 // otherwise a 4-tuple of integers is expected
1064 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
1065 PyObject* o1 = PySequence_GetItem(source, 0);
1066 PyObject* o2 = PySequence_GetItem(source, 1);
1067 PyObject* o3 = PySequence_GetItem(source, 2);
1068 PyObject* o4 = PySequence_GetItem(source, 3);
1069 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
1070 PyInt_AsLong(o3), PyInt_AsLong(o4));
1071 return TRUE;
1072 }
1073
1074 error:
1075 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
1076 return FALSE;
1077 }
1078
1079
1080
1081 bool wxColour_helper(PyObject* source, wxColour** obj) {
1082
1083 // If source is an object instance then it may already be the right type
1084 if (PyInstance_Check(source)) {
1085 wxColour* ptr;
1086 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
1087 goto error;
1088 *obj = ptr;
1089 return TRUE;
1090 }
1091 // otherwise a string is expected
1092 else if (PyString_Check(source)) {
1093 wxString spec = PyString_AS_STRING(source);
1094 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
1095 char* junk;
1096 int red = strtol(spec.Mid(1,2), &junk, 16);
1097 int green = strtol(spec.Mid(3,2), &junk, 16);
1098 int blue = strtol(spec.Mid(5,2), &junk, 16);
1099 **obj = wxColour(red, green, blue);
1100 return TRUE;
1101 }
1102 else { // it's a colour name
1103 **obj = wxColour(spec);
1104 return TRUE;
1105 }
1106 }
1107
1108 error:
1109 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
1110 return FALSE;
1111 }
1112
1113
1114 //----------------------------------------------------------------------
1115 //----------------------------------------------------------------------
1116 //----------------------------------------------------------------------
1117
1118
1119
1120