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