]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/helpers.cpp
f653ed1c417440f5e844318dda13919b4fa9d4d6
[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 if 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 actuallt 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 }
962 #endif
963
964
965 static
966 PyObject* PyMethod_GetDefiningClass(PyObject* method, const char* name)
967 {
968 PyObject* mgc = PyMethod_GET_CLASS(method);
969
970 #if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
971 return mgc;
972 #else // 2.2 and after, the hard way...
973
974 PyObject* nameo = PyString_FromString(name);
975 PyObject* klass = PyFindClassWithAttr(mgc, nameo);
976 Py_DECREF(nameo);
977 return klass;
978 #endif
979 }
980
981
982
983 bool wxPyCallbackHelper::findCallback(const char* name) const {
984 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
985 self->m_lastFound = NULL;
986
987 // If the object (m_self) has an attibute of the given name...
988 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
989 PyObject *method, *klass;
990 method = PyObject_GetAttrString(m_self, (char*)name);
991
992 // ...and if that attribute is a method, and if that method's class is
993 // not from a base class...
994 if (PyMethod_Check(method) &&
995 (klass = PyMethod_GetDefiningClass(method, (char*)name)) != NULL &&
996 ((klass == m_class) || PyClass_IsSubclass(klass, m_class))) {
997
998 // ...then we'll save a pointer to the method so callCallback can call it.
999 self->m_lastFound = method;
1000 }
1001 else {
1002 Py_DECREF(method);
1003 }
1004 }
1005 return m_lastFound != NULL;
1006 }
1007
1008
1009 int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
1010 PyObject* result;
1011 int retval = FALSE;
1012
1013 result = callCallbackObj(argTuple);
1014 if (result) { // Assumes an integer return type...
1015 retval = PyInt_AsLong(result);
1016 Py_DECREF(result);
1017 PyErr_Clear(); // forget about it if it's not...
1018 }
1019 return retval;
1020 }
1021
1022 // Invoke the Python callable object, returning the raw PyObject return
1023 // value. Caller should DECREF the return value and also call PyEval_SaveThread.
1024 PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
1025 PyObject* result;
1026
1027 // Save a copy of the pointer in case the callback generates another
1028 // callback. In that case m_lastFound will have a different value when
1029 // it gets back here...
1030 PyObject* method = m_lastFound;
1031
1032 result = PyEval_CallObject(method, argTuple);
1033 Py_DECREF(argTuple);
1034 Py_DECREF(method);
1035 if (!result) {
1036 PyErr_Print();
1037 }
1038 return result;
1039 }
1040
1041
1042 void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
1043 cbh.setSelf(self, klass, incref);
1044 }
1045
1046 bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
1047 return cbh.findCallback(name);
1048 }
1049
1050 int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1051 return cbh.callCallback(argTuple);
1052 }
1053
1054 PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1055 return cbh.callCallbackObj(argTuple);
1056 }
1057
1058
1059 void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
1060 if (cbh->m_incRef) {
1061 wxPyBeginBlockThreads();
1062 Py_XDECREF(cbh->m_self);
1063 Py_XDECREF(cbh->m_class);
1064 wxPyEndBlockThreads();
1065 }
1066 }
1067
1068 //---------------------------------------------------------------------------
1069 //---------------------------------------------------------------------------
1070 // These event classes can be derived from in Python and passed through the event
1071 // system without losing anything. They do this by keeping a reference to
1072 // themselves and some special case handling in wxPyCallback::EventThunker.
1073
1074
1075 wxPyEvtSelfRef::wxPyEvtSelfRef() {
1076 //m_self = Py_None; // **** We don't do normal ref counting to prevent
1077 //Py_INCREF(m_self); // circular loops...
1078 m_cloned = FALSE;
1079 }
1080
1081 wxPyEvtSelfRef::~wxPyEvtSelfRef() {
1082 wxPyBeginBlockThreads();
1083 if (m_cloned)
1084 Py_DECREF(m_self);
1085 wxPyEndBlockThreads();
1086 }
1087
1088 void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
1089 wxPyBeginBlockThreads();
1090 if (m_cloned)
1091 Py_DECREF(m_self);
1092 m_self = self;
1093 if (clone) {
1094 Py_INCREF(m_self);
1095 m_cloned = TRUE;
1096 }
1097 wxPyEndBlockThreads();
1098 }
1099
1100 PyObject* wxPyEvtSelfRef::GetSelf() const {
1101 Py_INCREF(m_self);
1102 return m_self;
1103 }
1104
1105
1106 IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
1107 IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
1108
1109
1110 wxPyEvent::wxPyEvent(int id)
1111 : wxEvent(id) {
1112 }
1113
1114
1115 wxPyEvent::wxPyEvent(const wxPyEvent& evt)
1116 : wxEvent(evt)
1117 {
1118 SetSelf(evt.m_self, TRUE);
1119 }
1120
1121
1122 wxPyEvent::~wxPyEvent() {
1123 }
1124
1125
1126 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
1127 : wxCommandEvent(commandType, id) {
1128 }
1129
1130
1131 wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
1132 : wxCommandEvent(evt)
1133 {
1134 SetSelf(evt.m_self, TRUE);
1135 }
1136
1137
1138 wxPyCommandEvent::~wxPyCommandEvent() {
1139 }
1140
1141
1142
1143
1144 //---------------------------------------------------------------------------
1145 //---------------------------------------------------------------------------
1146
1147
1148 wxPyTimer::wxPyTimer(PyObject* callback) {
1149 func = callback;
1150 Py_INCREF(func);
1151 }
1152
1153 wxPyTimer::~wxPyTimer() {
1154 wxPyBeginBlockThreads();
1155 Py_DECREF(func);
1156 wxPyEndBlockThreads();
1157 }
1158
1159 void wxPyTimer::Notify() {
1160 if (!func || func == Py_None) {
1161 wxTimer::Notify();
1162 }
1163 else {
1164 wxPyBeginBlockThreads();
1165
1166 PyObject* result;
1167 PyObject* args = Py_BuildValue("()");
1168
1169 result = PyEval_CallObject(func, args);
1170 Py_DECREF(args);
1171 if (result) {
1172 Py_DECREF(result);
1173 PyErr_Clear();
1174 } else {
1175 PyErr_Print();
1176 }
1177
1178 wxPyEndBlockThreads();
1179 }
1180 }
1181
1182
1183
1184 //---------------------------------------------------------------------------
1185 //---------------------------------------------------------------------------
1186 // Convert a wxList to a Python List
1187
1188 PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
1189 PyObject* pyList;
1190 PyObject* pyObj;
1191 wxObject* wxObj;
1192 wxNode* node = list->First();
1193
1194 wxPyBeginBlockThreads();
1195 pyList = PyList_New(0);
1196 while (node) {
1197 wxObj = node->Data();
1198 pyObj = wxPyMake_wxObject(wxObj); //wxPyConstructObject(wxObj, className);
1199 PyList_Append(pyList, pyObj);
1200 node = node->Next();
1201 }
1202 wxPyEndBlockThreads();
1203 return pyList;
1204 }
1205
1206 //----------------------------------------------------------------------
1207
1208 long wxPyGetWinHandle(wxWindow* win) {
1209 #ifdef __WXMSW__
1210 return (long)win->GetHandle();
1211 #endif
1212
1213 // Find and return the actual X-Window.
1214 #ifdef __WXGTK__
1215 if (win->m_wxwindow) {
1216 GdkWindowPrivate* bwin = (GdkWindowPrivate*)GTK_PIZZA(win->m_wxwindow)->bin_window;
1217 if (bwin) {
1218 return (long)bwin->xwindow;
1219 }
1220 }
1221 #endif
1222 return 0;
1223 }
1224
1225 //----------------------------------------------------------------------
1226 // Some helper functions for typemaps in my_typemaps.i, so they won't be
1227 // included in every file...
1228
1229
1230 byte* byte_LIST_helper(PyObject* source) {
1231 if (!PyList_Check(source)) {
1232 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1233 return NULL;
1234 }
1235 int count = PyList_Size(source);
1236 byte* temp = new byte[count];
1237 if (! temp) {
1238 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1239 return NULL;
1240 }
1241 for (int x=0; x<count; x++) {
1242 PyObject* o = PyList_GetItem(source, x);
1243 if (! PyInt_Check(o)) {
1244 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1245 return NULL;
1246 }
1247 temp[x] = (byte)PyInt_AsLong(o);
1248 }
1249 return temp;
1250 }
1251
1252
1253 int* int_LIST_helper(PyObject* source) {
1254 if (!PyList_Check(source)) {
1255 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1256 return NULL;
1257 }
1258 int count = PyList_Size(source);
1259 int* temp = new int[count];
1260 if (! temp) {
1261 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1262 return NULL;
1263 }
1264 for (int x=0; x<count; x++) {
1265 PyObject* o = PyList_GetItem(source, x);
1266 if (! PyInt_Check(o)) {
1267 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1268 return NULL;
1269 }
1270 temp[x] = PyInt_AsLong(o);
1271 }
1272 return temp;
1273 }
1274
1275
1276 long* long_LIST_helper(PyObject* source) {
1277 if (!PyList_Check(source)) {
1278 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1279 return NULL;
1280 }
1281 int count = PyList_Size(source);
1282 long* temp = new long[count];
1283 if (! temp) {
1284 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1285 return NULL;
1286 }
1287 for (int x=0; x<count; x++) {
1288 PyObject* o = PyList_GetItem(source, x);
1289 if (! PyInt_Check(o)) {
1290 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1291 return NULL;
1292 }
1293 temp[x] = PyInt_AsLong(o);
1294 }
1295 return temp;
1296 }
1297
1298
1299 char** string_LIST_helper(PyObject* source) {
1300 if (!PyList_Check(source)) {
1301 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1302 return NULL;
1303 }
1304 int count = PyList_Size(source);
1305 char** temp = new char*[count];
1306 if (! temp) {
1307 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1308 return NULL;
1309 }
1310 for (int x=0; x<count; x++) {
1311 PyObject* o = PyList_GetItem(source, x);
1312 if (! PyString_Check(o)) {
1313 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
1314 return NULL;
1315 }
1316 temp[x] = PyString_AsString(o);
1317 }
1318 return temp;
1319 }
1320
1321 //--------------------------------
1322 // Part of patch from Tim Hochberg
1323 static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
1324 if (PyInt_Check(o1) && PyInt_Check(o2)) {
1325 point->x = PyInt_AS_LONG(o1);
1326 point->y = PyInt_AS_LONG(o2);
1327 return true;
1328 }
1329 if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
1330 point->x = (int)PyFloat_AS_DOUBLE(o1);
1331 point->y = (int)PyFloat_AS_DOUBLE(o2);
1332 return true;
1333 }
1334 if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
1335 // Disallow instances because they can cause havok
1336 return false;
1337 }
1338 if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
1339 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
1340 point->x = PyInt_AsLong(o1);
1341 point->y = PyInt_AsLong(o2);
1342 return true;
1343 }
1344 return false;
1345 }
1346
1347
1348 wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
1349 // Putting all of the declarations here allows
1350 // us to put the error handling all in one place.
1351 int x;
1352 wxPoint* temp;
1353 PyObject *o, *o1, *o2;
1354 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1355
1356 if (!PySequence_Check(source)) {
1357 goto error0;
1358 }
1359
1360 // The length of the sequence is returned in count.
1361 *count = PySequence_Length(source);
1362 if (*count < 0) {
1363 goto error0;
1364 }
1365
1366 temp = new wxPoint[*count];
1367 if (!temp) {
1368 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1369 return NULL;
1370 }
1371 for (x=0; x<*count; x++) {
1372 // Get an item: try fast way first.
1373 if (isFast) {
1374 o = PySequence_Fast_GET_ITEM(source, x);
1375 }
1376 else {
1377 o = PySequence_GetItem(source, x);
1378 if (o == NULL) {
1379 goto error1;
1380 }
1381 }
1382
1383 // Convert o to wxPoint.
1384 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
1385 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
1386 o1 = PySequence_Fast_GET_ITEM(o, 0);
1387 o2 = PySequence_Fast_GET_ITEM(o, 1);
1388 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1389 goto error2;
1390 }
1391 }
1392 else if (PyInstance_Check(o)) {
1393 wxPoint* pt;
1394 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
1395 goto error2;
1396 }
1397 temp[x] = *pt;
1398 }
1399 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
1400 o1 = PySequence_GetItem(o, 0);
1401 o2 = PySequence_GetItem(o, 1);
1402 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1403 goto error3;
1404 }
1405 Py_DECREF(o1);
1406 Py_DECREF(o2);
1407 }
1408 else {
1409 goto error2;
1410 }
1411 // Clean up.
1412 if (!isFast)
1413 Py_DECREF(o);
1414 }
1415 return temp;
1416
1417 error3:
1418 Py_DECREF(o1);
1419 Py_DECREF(o2);
1420 error2:
1421 if (!isFast)
1422 Py_DECREF(o);
1423 error1:
1424 delete temp;
1425 error0:
1426 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
1427 return NULL;
1428 }
1429 // end of patch
1430 //------------------------------
1431
1432
1433 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
1434 if (!PyList_Check(source)) {
1435 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1436 return NULL;
1437 }
1438 int count = PyList_Size(source);
1439 wxBitmap** temp = new wxBitmap*[count];
1440 if (! temp) {
1441 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1442 return NULL;
1443 }
1444 for (int x=0; x<count; x++) {
1445 PyObject* o = PyList_GetItem(source, x);
1446 if (PyInstance_Check(o)) {
1447 wxBitmap* pt;
1448 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
1449 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
1450 return NULL;
1451 }
1452 temp[x] = pt;
1453 }
1454 else {
1455 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
1456 return NULL;
1457 }
1458 }
1459 return temp;
1460 }
1461
1462
1463
1464 wxString* wxString_LIST_helper(PyObject* source) {
1465 if (!PyList_Check(source)) {
1466 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1467 return NULL;
1468 }
1469 int count = PyList_Size(source);
1470 wxString* temp = new wxString[count];
1471 if (! temp) {
1472 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1473 return NULL;
1474 }
1475 for (int x=0; x<count; x++) {
1476 PyObject* o = PyList_GetItem(source, x);
1477 #if PYTHON_API_VERSION >= 1009
1478 if (! PyString_Check(o) && ! PyUnicode_Check(o)) {
1479 PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects.");
1480 return NULL;
1481 }
1482
1483 char* buff;
1484 int length;
1485 if (PyString_AsStringAndSize(o, &buff, &length) == -1)
1486 return NULL;
1487 temp[x] = wxString(buff, length);
1488 #else
1489 if (! PyString_Check(o)) {
1490 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
1491 return NULL;
1492 }
1493 temp[x] = PyString_AsString(o);
1494 #endif
1495 }
1496 return temp;
1497 }
1498
1499
1500 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
1501 if (!PyList_Check(source)) {
1502 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1503 return NULL;
1504 }
1505 int count = PyList_Size(source);
1506 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
1507 if (! temp) {
1508 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1509 return NULL;
1510 }
1511 for (int x=0; x<count; x++) {
1512 PyObject* o = PyList_GetItem(source, x);
1513 if (PyInstance_Check(o)) {
1514 wxAcceleratorEntry* ae;
1515 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
1516 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
1517 return NULL;
1518 }
1519 temp[x] = *ae;
1520 }
1521 else if (PyTuple_Check(o)) {
1522 PyObject* o1 = PyTuple_GetItem(o, 0);
1523 PyObject* o2 = PyTuple_GetItem(o, 1);
1524 PyObject* o3 = PyTuple_GetItem(o, 2);
1525 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
1526 }
1527 else {
1528 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
1529 return NULL;
1530 }
1531 }
1532 return temp;
1533 }
1534
1535
1536 wxPen** wxPen_LIST_helper(PyObject* source) {
1537 if (!PyList_Check(source)) {
1538 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1539 return NULL;
1540 }
1541 int count = PyList_Size(source);
1542 wxPen** temp = new wxPen*[count];
1543 if (!temp) {
1544 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1545 return NULL;
1546 }
1547 for (int x=0; x<count; x++) {
1548 PyObject* o = PyList_GetItem(source, x);
1549 if (PyInstance_Check(o)) {
1550 wxPen* pt;
1551 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxPen_p")) {
1552 delete temp;
1553 PyErr_SetString(PyExc_TypeError,"Expected _wxPen_p.");
1554 return NULL;
1555 }
1556 temp[x] = pt;
1557 }
1558 else {
1559 delete temp;
1560 PyErr_SetString(PyExc_TypeError, "Expected a list of wxPens.");
1561 return NULL;
1562 }
1563 }
1564 return temp;
1565 }
1566
1567
1568 bool _2int_seq_helper(PyObject* source, int* i1, int* i2) {
1569 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1570 PyObject *o1, *o2;
1571
1572 if (!PySequence_Check(source) || PySequence_Length(source) != 2)
1573 return FALSE;
1574
1575 if (isFast) {
1576 o1 = PySequence_Fast_GET_ITEM(source, 0);
1577 o2 = PySequence_Fast_GET_ITEM(source, 1);
1578 }
1579 else {
1580 o1 = PySequence_GetItem(source, 0);
1581 o2 = PySequence_GetItem(source, 1);
1582 }
1583
1584 *i1 = PyInt_AsLong(o1);
1585 *i2 = PyInt_AsLong(o2);
1586
1587 if (! isFast) {
1588 Py_DECREF(o1);
1589 Py_DECREF(o2);
1590 }
1591 return TRUE;
1592 }
1593
1594
1595 bool _4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) {
1596 bool isFast = PyList_Check(source) || PyTuple_Check(source);
1597 PyObject *o1, *o2, *o3, *o4;
1598
1599 if (!PySequence_Check(source) || PySequence_Length(source) != 4)
1600 return FALSE;
1601
1602 if (isFast) {
1603 o1 = PySequence_Fast_GET_ITEM(source, 0);
1604 o2 = PySequence_Fast_GET_ITEM(source, 1);
1605 o3 = PySequence_Fast_GET_ITEM(source, 2);
1606 o4 = PySequence_Fast_GET_ITEM(source, 3);
1607 }
1608 else {
1609 o1 = PySequence_GetItem(source, 0);
1610 o2 = PySequence_GetItem(source, 1);
1611 o3 = PySequence_GetItem(source, 2);
1612 o4 = PySequence_GetItem(source, 3);
1613 }
1614
1615 *i1 = PyInt_AsLong(o1);
1616 *i2 = PyInt_AsLong(o2);
1617 *i3 = PyInt_AsLong(o3);
1618 *i4 = PyInt_AsLong(o4);
1619
1620 if (! isFast) {
1621 Py_DECREF(o1);
1622 Py_DECREF(o2);
1623 Py_DECREF(o3);
1624 Py_DECREF(o4);
1625 }
1626 return TRUE;
1627 }
1628
1629
1630 //----------------------------------------------------------------------
1631
1632 bool wxSize_helper(PyObject* source, wxSize** obj) {
1633
1634 // If source is an object instance then it may already be the right type
1635 if (PyInstance_Check(source)) {
1636 wxSize* ptr;
1637 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
1638 goto error;
1639 *obj = ptr;
1640 return TRUE;
1641 }
1642 // otherwise a 2-tuple of integers is expected
1643 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1644 PyObject* o1 = PySequence_GetItem(source, 0);
1645 PyObject* o2 = PySequence_GetItem(source, 1);
1646 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
1647 return TRUE;
1648 }
1649
1650 error:
1651 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
1652 return FALSE;
1653 }
1654
1655 bool wxPoint_helper(PyObject* source, wxPoint** obj) {
1656
1657 // If source is an object instance then it may already be the right type
1658 if (PyInstance_Check(source)) {
1659 wxPoint* ptr;
1660 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
1661 goto error;
1662 *obj = ptr;
1663 return TRUE;
1664 }
1665 // otherwise a length-2 sequence of integers is expected
1666 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
1667 PyObject* o1 = PySequence_GetItem(source, 0);
1668 PyObject* o2 = PySequence_GetItem(source, 1);
1669 // This should really check for integers, not numbers -- but that would break code.
1670 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
1671 Py_DECREF(o1);
1672 Py_DECREF(o2);
1673 goto error;
1674 }
1675 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
1676 Py_DECREF(o1);
1677 Py_DECREF(o2);
1678 return TRUE;
1679 }
1680 error:
1681 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1682 return FALSE;
1683 }
1684
1685
1686
1687 bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
1688
1689 // If source is an object instance then it may already be the right type
1690 if (PyInstance_Check(source)) {
1691 wxRealPoint* ptr;
1692 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
1693 goto error;
1694 *obj = ptr;
1695 return TRUE;
1696 }
1697 // otherwise a 2-tuple of floats is expected
1698 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1699 PyObject* o1 = PySequence_GetItem(source, 0);
1700 PyObject* o2 = PySequence_GetItem(source, 1);
1701 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
1702 return TRUE;
1703 }
1704
1705 error:
1706 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
1707 return FALSE;
1708 }
1709
1710
1711
1712
1713 bool wxRect_helper(PyObject* source, wxRect** obj) {
1714
1715 // If source is an object instance then it may already be the right type
1716 if (PyInstance_Check(source)) {
1717 wxRect* ptr;
1718 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
1719 goto error;
1720 *obj = ptr;
1721 return TRUE;
1722 }
1723 // otherwise a 4-tuple of integers is expected
1724 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
1725 PyObject* o1 = PySequence_GetItem(source, 0);
1726 PyObject* o2 = PySequence_GetItem(source, 1);
1727 PyObject* o3 = PySequence_GetItem(source, 2);
1728 PyObject* o4 = PySequence_GetItem(source, 3);
1729 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
1730 PyInt_AsLong(o3), PyInt_AsLong(o4));
1731 return TRUE;
1732 }
1733
1734 error:
1735 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
1736 return FALSE;
1737 }
1738
1739
1740
1741 bool wxColour_helper(PyObject* source, wxColour** obj) {
1742
1743 // If source is an object instance then it may already be the right type
1744 if (PyInstance_Check(source)) {
1745 wxColour* ptr;
1746 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
1747 goto error;
1748 *obj = ptr;
1749 return TRUE;
1750 }
1751 // otherwise a string is expected
1752 else if (PyString_Check(source)) {
1753 wxString spec = PyString_AS_STRING(source);
1754 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
1755 char* junk;
1756 int red = strtol(spec.Mid(1,2), &junk, 16);
1757 int green = strtol(spec.Mid(3,2), &junk, 16);
1758 int blue = strtol(spec.Mid(5,2), &junk, 16);
1759 **obj = wxColour(red, green, blue);
1760 return TRUE;
1761 }
1762 else { // it's a colour name
1763 **obj = wxColour(spec);
1764 return TRUE;
1765 }
1766 }
1767
1768 error:
1769 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
1770 return FALSE;
1771 }
1772
1773
1774 //----------------------------------------------------------------------
1775
1776 PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
1777
1778 PyObject* list = PyList_New(0);
1779 for (size_t i=0; i < arr.GetCount(); i++) {
1780 PyObject* str = PyString_FromString(arr[i].c_str());
1781 PyList_Append(list, str);
1782 Py_DECREF(str);
1783 }
1784 return list;
1785 }
1786
1787
1788 PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
1789
1790 PyObject* list = PyList_New(0);
1791 for (size_t i=0; i < arr.GetCount(); i++) {
1792 PyObject* number = PyInt_FromLong(arr[i]);
1793 PyList_Append(list, number);
1794 Py_DECREF(number);
1795 }
1796 return list;
1797 }
1798
1799
1800 //----------------------------------------------------------------------
1801 //----------------------------------------------------------------------
1802
1803
1804
1805