]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/helpers.cpp
3aa1ae21d97d04ba53e59fae0c1b9ba671feac3f
[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 wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
788 // Putting all of the declarations here allows
789 // us to put the error handling all in one place.
790 int x;
791 wxPoint* temp;
792 PyObject *o, *o1, *o2;
793 int isFast = PyList_Check(source) || PyTuple_Check(source);
794
795 // The length of the sequence is returned in count.
796 if (!PySequence_Check(source)) {
797 goto error0;
798 }
799 *count = PySequence_Length(source);
800 if (*count < 0) {
801 goto error0;
802 }
803
804 temp = new wxPoint[*count];
805 if (!temp) {
806 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
807 return NULL;
808 }
809 for (x=0; x<*count; x++) {
810 // Get an item: try fast way first.
811 if (isFast) {
812 o = PySequence_Fast_GET_ITEM(source, x);
813 }
814 else {
815 o = PySequence_GetItem(source, x);
816 if (o == NULL) {
817 goto error1;
818 }
819 }
820
821 // Convert o to wxPoint.
822 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
823 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
824 o1 = PySequence_Fast_GET_ITEM(o, 0);
825 o2 = PySequence_Fast_GET_ITEM(o, 1);
826 if (!wxPointFromObjects(o1, o2, &temp[x])) {
827 goto error2;
828 }
829 }
830 else if (PyInstance_Check(o)) {
831 wxPoint* pt;
832 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
833 goto error2;
834 }
835 temp[x] = *pt;
836 }
837 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
838 o1 = PySequence_GetItem(o, 0);
839 o2 = PySequence_GetItem(o, 1);
840 if (!wxPointFromObjects(o1, o2, &temp[x])) {
841 goto error3;
842 }
843 Py_DECREF(o1);
844 Py_DECREF(o2);
845 }
846 else {
847 goto error2;
848 }
849 // Clean up.
850 if (!isFast)
851 Py_DECREF(o);
852 }
853 return temp;
854
855 error3:
856 Py_DECREF(o1);
857 Py_DECREF(o2);
858 error2:
859 if (!isFast)
860 Py_DECREF(o);
861 error1:
862 delete temp;
863 error0:
864 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
865 return NULL;
866 }
867 // end of patch
868 //------------------------------
869
870
871 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
872 if (!PyList_Check(source)) {
873 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
874 return NULL;
875 }
876 int count = PyList_Size(source);
877 wxBitmap** temp = new wxBitmap*[count];
878 if (! temp) {
879 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
880 return NULL;
881 }
882 for (int x=0; x<count; x++) {
883 PyObject* o = PyList_GetItem(source, x);
884 if (PyInstance_Check(o)) {
885 wxBitmap* pt;
886 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
887 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
888 return NULL;
889 }
890 temp[x] = pt;
891 }
892 else {
893 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
894 return NULL;
895 }
896 }
897 return temp;
898 }
899
900
901
902 wxString* wxString_LIST_helper(PyObject* source) {
903 if (!PyList_Check(source)) {
904 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
905 return NULL;
906 }
907 int count = PyList_Size(source);
908 wxString* temp = new wxString[count];
909 if (! temp) {
910 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
911 return NULL;
912 }
913 for (int x=0; x<count; x++) {
914 PyObject* o = PyList_GetItem(source, x);
915 if (! PyString_Check(o)) {
916 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
917 return NULL;
918 }
919 temp[x] = PyString_AsString(o);
920 }
921 return temp;
922 }
923
924
925 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
926 if (!PyList_Check(source)) {
927 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
928 return NULL;
929 }
930 int count = PyList_Size(source);
931 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
932 if (! temp) {
933 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
934 return NULL;
935 }
936 for (int x=0; x<count; x++) {
937 PyObject* o = PyList_GetItem(source, x);
938 if (PyInstance_Check(o)) {
939 wxAcceleratorEntry* ae;
940 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
941 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
942 return NULL;
943 }
944 temp[x] = *ae;
945 }
946 else if (PyTuple_Check(o)) {
947 PyObject* o1 = PyTuple_GetItem(o, 0);
948 PyObject* o2 = PyTuple_GetItem(o, 1);
949 PyObject* o3 = PyTuple_GetItem(o, 2);
950
951 temp[x].m_flags = PyInt_AsLong(o1);
952 temp[x].m_keyCode = PyInt_AsLong(o2);
953 temp[x].m_command = PyInt_AsLong(o3);
954 }
955 else {
956 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
957 return NULL;
958 }
959 }
960 return temp;
961 }
962
963
964
965 //----------------------------------------------------------------------
966
967 bool wxSize_helper(PyObject* source, wxSize** obj) {
968
969 // If source is an object instance then it may already be the right type
970 if (PyInstance_Check(source)) {
971 wxSize* ptr;
972 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
973 goto error;
974 *obj = ptr;
975 return TRUE;
976 }
977 // otherwise a 2-tuple of integers is expected
978 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
979 PyObject* o1 = PySequence_GetItem(source, 0);
980 PyObject* o2 = PySequence_GetItem(source, 1);
981 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
982 return TRUE;
983 }
984
985 error:
986 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
987 return FALSE;
988 }
989
990 bool wxPoint_helper(PyObject* source, wxPoint** obj) {
991
992 // If source is an object instance then it may already be the right type
993 if (PyInstance_Check(source)) {
994 wxPoint* ptr;
995 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
996 goto error;
997 *obj = ptr;
998 return TRUE;
999 }
1000 // otherwise a length-2 sequence of integers is expected
1001 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
1002 PyObject* o1 = PySequence_GetItem(source, 0);
1003 PyObject* o2 = PySequence_GetItem(source, 1);
1004 // This should really check for integers, not numbers -- but that would break code.
1005 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
1006 Py_DECREF(o1);
1007 Py_DECREF(o2);
1008 goto error;
1009 }
1010 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
1011 Py_DECREF(o1);
1012 Py_DECREF(o2);
1013 return TRUE;
1014 }
1015 error:
1016 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1017 return FALSE;
1018 }
1019
1020
1021
1022 bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
1023
1024 // If source is an object instance then it may already be the right type
1025 if (PyInstance_Check(source)) {
1026 wxRealPoint* ptr;
1027 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
1028 goto error;
1029 *obj = ptr;
1030 return TRUE;
1031 }
1032 // otherwise a 2-tuple of floats is expected
1033 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1034 PyObject* o1 = PySequence_GetItem(source, 0);
1035 PyObject* o2 = PySequence_GetItem(source, 1);
1036 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
1037 return TRUE;
1038 }
1039
1040 error:
1041 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
1042 return FALSE;
1043 }
1044
1045
1046
1047
1048 bool wxRect_helper(PyObject* source, wxRect** obj) {
1049
1050 // If source is an object instance then it may already be the right type
1051 if (PyInstance_Check(source)) {
1052 wxRect* ptr;
1053 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
1054 goto error;
1055 *obj = ptr;
1056 return TRUE;
1057 }
1058 // otherwise a 4-tuple of integers is expected
1059 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
1060 PyObject* o1 = PySequence_GetItem(source, 0);
1061 PyObject* o2 = PySequence_GetItem(source, 1);
1062 PyObject* o3 = PySequence_GetItem(source, 2);
1063 PyObject* o4 = PySequence_GetItem(source, 3);
1064 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
1065 PyInt_AsLong(o3), PyInt_AsLong(o4));
1066 return TRUE;
1067 }
1068
1069 error:
1070 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
1071 return FALSE;
1072 }
1073
1074
1075
1076 bool wxColour_helper(PyObject* source, wxColour** obj) {
1077
1078 // If source is an object instance then it may already be the right type
1079 if (PyInstance_Check(source)) {
1080 wxColour* ptr;
1081 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
1082 goto error;
1083 *obj = ptr;
1084 return TRUE;
1085 }
1086 // otherwise a string is expected
1087 else if (PyString_Check(source)) {
1088 wxString spec = PyString_AS_STRING(source);
1089 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
1090 char* junk;
1091 int red = strtol(spec.Mid(1,2), &junk, 16);
1092 int green = strtol(spec.Mid(3,2), &junk, 16);
1093 int blue = strtol(spec.Mid(5,2), &junk, 16);
1094 **obj = wxColour(red, green, blue);
1095 return TRUE;
1096 }
1097 else { // it's a colour name
1098 **obj = wxColour(spec);
1099 return TRUE;
1100 }
1101 }
1102
1103 error:
1104 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
1105 return FALSE;
1106 }
1107
1108
1109 //----------------------------------------------------------------------
1110 //----------------------------------------------------------------------
1111 //----------------------------------------------------------------------
1112
1113
1114
1115