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