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