]> git.saurik.com Git - wxWidgets.git/blame - wxPython/src/helpers.cpp
Minimal changes needed to build/run wxPython on the 2.5 branch after
[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
08127323 13
7bf85405
RD
14#undef DEBUG
15#include <Python.h>
16#include "helpers.h"
cbf60e09 17#include "pyistream.h"
694759cf 18
af309447
RD
19#ifdef __WXMSW__
20#include <wx/msw/private.h>
78b57918 21#include <wx/msw/winundef.h>
4268f798 22#include <wx/msw/msvcrt.h>
af309447 23#endif
694759cf
RD
24
25#ifdef __WXGTK__
26#include <gtk/gtk.h>
54b96882
RD
27#include <gdk/gdkprivate.h>
28#include <wx/gtk/win_gtk.h>
694759cf 29#endif
7bf85405 30
dd116e73
RD
31#include <wx/clipbrd.h>
32#include <wx/mimetype.h>
33
c8bc7bb8
RD
34//----------------------------------------------------------------------
35
36#if PYTHON_API_VERSION <= 1007 && wxUSE_UNICODE
37#error Python must support Unicode to use wxWindows Unicode
38#endif
39
4268f798
RD
40//----------------------------------------------------------------------
41
4268f798 42wxPyApp* wxPythonApp = NULL; // Global instance of application object
e3dbf593 43bool wxPyDoCleanup = FALSE;
1e4a197e 44bool wxPyDoingCleanup = FALSE;
4268f798
RD
45
46
47#ifdef WXP_WITH_THREAD
48struct wxPyThreadState {
49 unsigned long tid;
50 PyThreadState* tstate;
51
52 wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL)
53 : tid(_tid), tstate(_tstate) {}
54};
55
56#include <wx/dynarray.h>
57WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray);
58#include <wx/arrimpl.cpp>
59WX_DEFINE_OBJARRAY(wxPyThreadStateArray);
60
61wxPyThreadStateArray* wxPyTStates = NULL;
62wxMutex* wxPyTMutex = NULL;
63#endif
7bf85405
RD
64
65
1e4a197e
RD
66static PyObject* wxPython_dict = NULL;
67static PyObject* wxPyPtrTypeMap = NULL;
68static PyObject* wxPyAssertionError = NULL;
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{
a2426843
RD
82 // If wxPython is embedded in another wxWindows app then
83 // the inatance has already been set.
84 if (! wxGetInstance())
85 wxSetInstance(hinstDLL);
86 return TRUE;
21f4bf45
RD
87}
88#endif
89
7bf85405 90//----------------------------------------------------------------------
4268f798 91// Classes for implementing the wxp main application shell.
7bf85405
RD
92//----------------------------------------------------------------------
93
1e4a197e
RD
94IMPLEMENT_ABSTRACT_CLASS(wxPyApp, wxApp);
95
7bf85405 96
cf694132 97wxPyApp::wxPyApp() {
1e4a197e 98 m_assertMode = wxPYAPP_ASSERT_EXCEPTION;
cf694132
RD
99}
100
1e4a197e 101
cf694132 102wxPyApp::~wxPyApp() {
cf694132
RD
103}
104
105
1e4a197e 106// This one isn't acutally called... We fake it with __wxStart()
4268f798 107bool wxPyApp::OnInit() {
6999b0d8 108 return FALSE;
7bf85405
RD
109}
110
4268f798
RD
111
112int wxPyApp::MainLoop() {
7ff49f0c 113 int retval = 0;
af309447 114
7ff49f0c 115 DeletePendingObjects();
4268f798 116 bool initialized = wxTopLevelWindows.GetCount() != 0;
7ff49f0c 117#ifdef __WXGTK__
4268f798 118 m_initialized = initialized;
7ff49f0c 119#endif
7bf85405 120
4268f798 121 if (initialized) {
098be78d
RD
122 if ( m_exitOnFrameDelete == Later ) {
123 m_exitOnFrameDelete = Yes;
124 }
125
7ff49f0c 126 retval = wxApp::MainLoop();
4268f798 127 OnExit();
7ff49f0c
RD
128 }
129 return retval;
130}
7bf85405
RD
131
132
1e4a197e
RD
133bool wxPyApp::OnInitGui() {
134 bool rval=TRUE;
135 wxApp::OnInitGui(); // in this case always call the base class version
136 // wxPyBeginBlockThreads(); *** only called from within __wxStart so we already have the GIL
137 if (wxPyCBH_findCallback(m_myInst, "OnInitGui"))
138 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
139 // wxPyEndBlockThreads(); ***
140 return rval;
141}
142
143
144int wxPyApp::OnExit() {
145 int rval=0;
146 wxPyBeginBlockThreads();
147 if (wxPyCBH_findCallback(m_myInst, "OnExit"))
148 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
149 wxPyEndBlockThreads();
150 wxApp::OnExit(); // in this case always call the base class version
151 return rval;
152}
153
154
155#ifdef __WXDEBUG__
156void wxPyApp::OnAssert(const wxChar *file,
157 int line,
158 const wxChar *cond,
159 const wxChar *msg) {
160
161 // If the OnAssert is overloaded in the Python class then call it...
162 bool found;
163 wxPyBeginBlockThreads();
164 if ((found = wxPyCBH_findCallback(m_myInst, "OnAssert"))) {
165 PyObject* fso = wx2PyString(file);
166 PyObject* cso = wx2PyString(file);
167 PyObject* mso;
168 if (msg != NULL)
169 mso = wx2PyString(file);
170 else {
171 mso = Py_None; Py_INCREF(Py_None);
172 }
173 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(OiOO)", fso, line, cso, mso));
174 Py_DECREF(fso);
175 Py_DECREF(cso);
176 Py_DECREF(mso);
177 }
178 wxPyEndBlockThreads();
179
180 // ...otherwise do our own thing with it
181 if (! found) {
182 // ignore it?
183 if (m_assertMode & wxPYAPP_ASSERT_SUPPRESS)
184 return;
185
186 // turn it into a Python exception?
187 if (m_assertMode & wxPYAPP_ASSERT_EXCEPTION) {
188 wxString buf;
189 buf.Alloc(4096);
190 buf.Printf(wxT("C++ assertion \"%s\" failed in %s(%d)"), cond, file, line);
191 if (msg != NULL) {
192 buf += wxT(": ");
193 buf += msg;
194 }
195
196 // set the exception
197 wxPyBeginBlockThreads();
198 PyObject* s = wx2PyString(buf);
199 PyErr_SetObject(wxPyAssertionError, s);
200 Py_DECREF(s);
201 wxPyEndBlockThreads();
202
203 // Now when control returns to whatever API wrapper was called from
204 // Python it should detect that an exception is set and will return
205 // NULL, signalling the exception to Python.
206 }
207
208 // Send it to the normal log destination, but only if
209 // not _DIALOG because it will call this too
210 if ( (m_assertMode & wxPYAPP_ASSERT_LOG) && !(m_assertMode & wxPYAPP_ASSERT_DIALOG)) {
211 wxString buf;
212 buf.Alloc(4096);
213 buf.Printf(wxT("%s(%d): assert \"%s\" failed"),
214 file, line, cond);
215 if (msg != NULL) {
216 buf += wxT(": ");
217 buf += msg;
218 }
219 wxLogDebug(buf);
220 }
221
222 // do the normal wx assert dialog?
223 if (m_assertMode & wxPYAPP_ASSERT_DIALOG)
224 wxApp::OnAssert(file, line, cond, msg);
225 }
226}
227#endif
228
229
230/*static*/
231bool wxPyApp::GetMacDefaultEncodingIsPC() {
232#ifdef __WXMAC__
233 return s_macDefaultEncodingIsPC;
234#else
235 return 0;
236#endif
237}
238
239/*static*/
240bool wxPyApp::GetMacSupportPCMenuShortcuts() {
241#ifdef __WXMAC__
242 return s_macSupportPCMenuShortcuts;
243#else
244 return 0;
245#endif
246}
247
248/*static*/
249long wxPyApp::GetMacAboutMenuItemId() {
250#ifdef __WXMAC__
251 return s_macAboutMenuItemId;
252#else
253 return 0;
254#endif
255}
256
257/*static*/
258long wxPyApp::GetMacPreferencesMenuItemId() {
259#ifdef __WXMAC__
260 return s_macPreferencesMenuItemId;
261#else
262 return 0;
263#endif
264}
265
266/*static*/
267long wxPyApp::GetMacExitMenuItemId() {
268#ifdef __WXMAC__
269 return s_macExitMenuItemId;
270#else
271 return 0;
272#endif
273}
274
275/*static*/
276wxString wxPyApp::GetMacHelpMenuTitleName() {
277#ifdef __WXMAC__
278 return s_macHelpMenuTitleName;
279#else
280 return wxEmptyString;
281#endif
282}
283
284/*static*/
285void wxPyApp::SetMacDefaultEncodingIsPC(bool val) {
286#ifdef __WXMAC__
287 s_macDefaultEncodingIsPC = val;
288#endif
289}
290
291/*static*/
292void wxPyApp::SetMacSupportPCMenuShortcuts(bool val) {
293#ifdef __WXMAC__
294 s_macSupportPCMenuShortcuts = val;
295#endif
296}
297
298/*static*/
299void wxPyApp::SetMacAboutMenuItemId(long val) {
300#ifdef __WXMAC__
301 s_macAboutMenuItemId = val;
302#endif
303}
304
305/*static*/
306void wxPyApp::SetMacPreferencesMenuItemId(long val) {
307#ifdef __WXMAC__
308 s_macPreferencesMenuItemId = val;
309#endif
310}
311
312/*static*/
313void wxPyApp::SetMacExitMenuItemId(long val) {
314#ifdef __WXMAC__
315 s_macExitMenuItemId = val;
316#endif
317}
318
319/*static*/
320void wxPyApp::SetMacHelpMenuTitleName(const wxString& val) {
321#ifdef __WXMAC__
322 s_macHelpMenuTitleName = val;
323#endif
324}
325
326
4268f798 327
fb5e0af0 328//---------------------------------------------------------------------
7bf85405
RD
329//----------------------------------------------------------------------
330
a541c325 331
dd116e73 332#if 0
a541c325
RD
333static char* wxPyCopyCString(const wxChar* src)
334{
335 wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(src);
336 size_t len = strlen(buff);
337 char* dest = new char[len+1];
338 strcpy(dest, buff);
339 return dest;
340}
341
c8bc7bb8 342#if wxUSE_UNICODE
a541c325 343static char* wxPyCopyCString(const char* src) // we need a char version too
c8bc7bb8 344{
a541c325
RD
345 size_t len = strlen(src);
346 char* dest = new char[len+1];
347 strcpy(dest, src);
348 return dest;
c8bc7bb8 349}
a541c325 350#endif
c8bc7bb8 351
a541c325 352static wxChar* wxPyCopyWString(const char *src)
c8bc7bb8 353{
a541c325
RD
354 //wxMB2WXbuf buff = wxConvCurrent->cMB2WX(src);
355 wxString str(src, *wxConvCurrent);
356 return copystring(str);
c8bc7bb8
RD
357}
358
a541c325
RD
359#if wxUSE_UNICODE
360static wxChar* wxPyCopyWString(const wxChar *src)
c8bc7bb8 361{
a541c325 362 return copystring(src);
c8bc7bb8
RD
363}
364#endif
dd116e73 365#endif
f6bcfd97 366
a541c325
RD
367
368//----------------------------------------------------------------------
369
dd116e73
RD
370// This function is called when the wxc module is imported to do some initial
371// setup. (Before there is a wxApp object.)
1e4a197e 372void __wxPreStart(PyObject* moduleDict)
7bf85405 373{
de20db99
RD
374
375#ifdef __WXMSW__
44f68505 376// wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
de20db99
RD
377#endif
378
9d8bd15f 379#ifdef WXP_WITH_THREAD
1112b0c6 380 PyEval_InitThreads();
4268f798
RD
381 wxPyTStates = new wxPyThreadStateArray;
382 wxPyTMutex = new wxMutex;
9d8bd15f
RD
383#endif
384
dd116e73 385 // Ensure that the build options in the DLL (or whatever) match this build
0b85cc38
RD
386 wxApp::CheckBuildOptions(wxBuildOptions());
387
dd116e73 388 // Create an exception object to use for wxASSERTions
1e4a197e
RD
389 wxPyAssertionError = PyErr_NewException("wxPython.wxc.wxPyAssertionError",
390 PyExc_AssertionError, NULL);
391 PyDict_SetItemString(moduleDict, "wxPyAssertionError", wxPyAssertionError);
0d6f9504
RD
392}
393
394
dd116e73
RD
395
396// Initialize wxWindows and bootstrap the user application by calling the
397// wxApp's OnInit, which is a parameter to this funciton. See wxApp.__init__
398// in _extras.py to learn how the bootstrap is started.
0d6f9504
RD
399PyObject* __wxStart(PyObject* /* self */, PyObject* args)
400{
401 PyObject* onInitFunc = NULL;
dd116e73
RD
402 PyObject* arglist= NULL;
403 PyObject* result = NULL;
404 PyObject* pyint = NULL;
0d6f9504
RD
405 long bResult;
406
0d6f9504
RD
407 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
408 return NULL;
409
dd116e73 410 // Get any command-line args passed to this program from the sys module
9416aa89 411 int argc = 0;
dd116e73 412 char** argv = NULL;
f6bcfd97 413 PyObject* sysargv = PySys_GetObject("argv");
9416aa89
RD
414 if (sysargv != NULL) {
415 argc = PyList_Size(sysargv);
dd116e73 416 argv = new char*[argc+1];
9416aa89 417 int x;
c8bc7bb8
RD
418 for(x=0; x<argc; x++) {
419 PyObject *pyArg = PyList_GetItem(sysargv, x);
dd116e73 420 argv[x] = PyString_AsString(pyArg);
c8bc7bb8 421 }
9416aa89
RD
422 argv[argc] = NULL;
423 }
c8bc7bb8 424
dd116e73
RD
425 if (! wxEntryStart(argc, argv) ) {
426 PyErr_SetString(PyExc_SystemError, // is this the right one?
427 "wxEntryStart failed!");
428 goto error;
429 }
430 delete [] argv;
431
0d6f9504 432
dd116e73
RD
433 // The stock objects were all NULL when they were loaded into
434 // SWIG generated proxies, so re-init those now...
435 wxPy_ReinitStockObjects();
7bf85405 436
dd116e73
RD
437
438 // Call the Python wxApp's OnInit function
7bf85405
RD
439 arglist = PyTuple_New(0);
440 result = PyEval_CallObject(onInitFunc, arglist);
1e4a197e 441 Py_DECREF(arglist);
8bf5d46e
RD
442 if (!result) { // an exception was raised.
443 return NULL;
7bf85405
RD
444 }
445
dd116e73 446 pyint = PyNumber_Int(result);
1e4a197e 447 if (! pyint) {
7bf85405 448 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
1e4a197e 449 goto error;
7bf85405 450 }
1e4a197e 451 bResult = PyInt_AS_LONG(pyint);
7bf85405 452 if (! bResult) {
194fa2ac 453 PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
1e4a197e 454 goto error;
7bf85405
RD
455 }
456
13dfc243 457#ifdef __WXGTK__
7ff49f0c 458 wxTheApp->m_initialized = (wxTopLevelWindows.GetCount() > 0);
13dfc243 459#endif
fb5e0af0 460
1e4a197e
RD
461 Py_DECREF(result);
462 Py_DECREF(pyint);
7bf85405
RD
463 Py_INCREF(Py_None);
464 return Py_None;
1e4a197e
RD
465
466 error:
467 Py_XDECREF(result);
468 Py_XDECREF(pyint);
469 return NULL;
7bf85405
RD
470}
471
4268f798 472
dd116e73 473
7ff49f0c 474void __wxCleanup() {
1e4a197e 475 wxPyDoingCleanup = TRUE;
e3dbf593
RD
476 if (wxPyDoCleanup)
477 wxEntryCleanup();
7faa9591 478#ifdef WXP_WITH_THREAD
4268f798
RD
479 delete wxPyTMutex;
480 wxPyTMutex = NULL;
481 wxPyTStates->Empty();
482 delete wxPyTStates;
483 wxPyTStates = NULL;
7faa9591 484#endif
7ff49f0c 485}
7bf85405
RD
486
487
488
4acff284 489
7bf85405
RD
490PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
491{
492
493 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
494 return NULL;
495
496 if (!PyDict_Check(wxPython_dict)) {
497 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
498 return NULL;
499 }
9416aa89
RD
500
501 if (! wxPyPtrTypeMap)
502 wxPyPtrTypeMap = PyDict_New();
503 PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap);
504
505
7bf85405 506#ifdef __WXMOTIF__
21f4bf45
RD
507#define wxPlatform "__WXMOTIF__"
508#endif
be43cc44
RD
509#ifdef __WXX11__
510#define wxPlatform "__WXX11__"
7bf85405
RD
511#endif
512#ifdef __WXGTK__
21f4bf45 513#define wxPlatform "__WXGTK__"
7bf85405
RD
514#endif
515#if defined(__WIN32__) || defined(__WXMSW__)
fb5e0af0 516#define wxPlatform "__WXMSW__"
7bf85405
RD
517#endif
518#ifdef __WXMAC__
21f4bf45 519#define wxPlatform "__WXMAC__"
7bf85405
RD
520#endif
521
249a57f4
RD
522#ifdef __WXDEBUG__
523 int wxdebug = 1;
524#else
525 int wxdebug = 0;
526#endif
527
7bf85405 528 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
c8bc7bb8 529 PyDict_SetItemString(wxPython_dict, "wxUSE_UNICODE", PyInt_FromLong(wxUSE_UNICODE));
249a57f4 530 PyDict_SetItemString(wxPython_dict, "__WXDEBUG__", PyInt_FromLong(wxdebug));
c8bc7bb8 531
7bf85405
RD
532 Py_INCREF(Py_None);
533 return Py_None;
534}
535
dd116e73
RD
536
537//---------------------------------------------------------------------------
538
539// The stock objects are no longer created when the wxc module is imported, but
540// only after the app object has been created. This function will be called before
541// OnInit is called so we can hack the new pointer values into the obj.this attributes.
542
543void wxPy_ReinitStockObjects()
544{
545 char ptrbuf[128];
546 PyObject* obj;
547 PyObject* ptrobj;
548
549
550
551#define REINITOBJ(name, type) \
552 obj = PyDict_GetItemString(wxPython_dict, #name); \
553 wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \
554 SWIG_MakePtr(ptrbuf, (char *) name, "_" #type "_p"); \
555 ptrobj = PyString_FromString(ptrbuf); \
556 PyObject_SetAttrString(obj, "this", ptrobj); \
557 Py_DECREF(ptrobj)
558
559#define REINITOBJ2(name, type) \
560 obj = PyDict_GetItemString(wxPython_dict, #name); \
561 wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \
562 SWIG_MakePtr(ptrbuf, (char *) &name, "_" #type "_p"); \
563 ptrobj = PyString_FromString(ptrbuf); \
564 PyObject_SetAttrString(obj, "this", ptrobj); \
565 Py_DECREF(ptrobj)
566
567
568 REINITOBJ(wxNORMAL_FONT, wxFont);
569 REINITOBJ(wxSMALL_FONT, wxFont);
570 REINITOBJ(wxITALIC_FONT, wxFont);
571 REINITOBJ(wxSWISS_FONT, wxFont);
572
573 REINITOBJ(wxRED_PEN, wxPen);
574 REINITOBJ(wxCYAN_PEN, wxPen);
575 REINITOBJ(wxGREEN_PEN, wxPen);
576 REINITOBJ(wxBLACK_PEN, wxPen);
577 REINITOBJ(wxWHITE_PEN, wxPen);
578 REINITOBJ(wxTRANSPARENT_PEN, wxPen);
579 REINITOBJ(wxBLACK_DASHED_PEN, wxPen);
580 REINITOBJ(wxGREY_PEN, wxPen);
581 REINITOBJ(wxMEDIUM_GREY_PEN, wxPen);
582 REINITOBJ(wxLIGHT_GREY_PEN, wxPen);
583
584 REINITOBJ(wxBLUE_BRUSH, wxBrush);
585 REINITOBJ(wxGREEN_BRUSH, wxBrush);
586 REINITOBJ(wxWHITE_BRUSH, wxBrush);
587 REINITOBJ(wxBLACK_BRUSH, wxBrush);
588 REINITOBJ(wxTRANSPARENT_BRUSH, wxBrush);
589 REINITOBJ(wxCYAN_BRUSH, wxBrush);
590 REINITOBJ(wxRED_BRUSH, wxBrush);
591 REINITOBJ(wxGREY_BRUSH, wxBrush);
592 REINITOBJ(wxMEDIUM_GREY_BRUSH, wxBrush);
593 REINITOBJ(wxLIGHT_GREY_BRUSH, wxBrush);
594
595 REINITOBJ(wxBLACK, wxColour);
596 REINITOBJ(wxWHITE, wxColour);
597 REINITOBJ(wxRED, wxColour);
598 REINITOBJ(wxBLUE, wxColour);
599 REINITOBJ(wxGREEN, wxColour);
600 REINITOBJ(wxCYAN, wxColour);
601 REINITOBJ(wxLIGHT_GREY, wxColour);
602
603 REINITOBJ(wxSTANDARD_CURSOR, wxCursor);
604 REINITOBJ(wxHOURGLASS_CURSOR, wxCursor);
605 REINITOBJ(wxCROSS_CURSOR, wxCursor);
606
607 REINITOBJ2(wxNullBitmap, wxBitmap);
608 REINITOBJ2(wxNullIcon, wxIcon);
609 REINITOBJ2(wxNullCursor, wxCursor);
610 REINITOBJ2(wxNullPen, wxPen);
611 REINITOBJ2(wxNullBrush, wxBrush);
612 REINITOBJ2(wxNullPalette, wxPalette);
613 REINITOBJ2(wxNullFont, wxFont);
614 REINITOBJ2(wxNullColour, wxColour);
615
616 REINITOBJ(wxTheFontList, wxFontList);
617 REINITOBJ(wxThePenList, wxPenList);
618 REINITOBJ(wxTheBrushList, wxBrushList);
619 REINITOBJ(wxTheColourDatabase, wxColourDatabase);
620
621
622 REINITOBJ(wxTheClipboard, wxClipboard);
623 REINITOBJ(wxTheMimeTypesManager, wxMimeTypesManager);
624 REINITOBJ2(wxDefaultValidator, wxValidator);
625 REINITOBJ2(wxNullImage, wxImage);
626 REINITOBJ2(wxNullAcceleratorTable, wxAcceleratorTable);
627
628#undef REINITOBJ
629#undef REINITOBJ2
630}
631
4acff284
RD
632//---------------------------------------------------------------------------
633
634void wxPyClientData_dtor(wxPyClientData* self) {
1e4a197e
RD
635 if (! wxPyDoingCleanup) { // Don't do it during cleanup as Python
636 // may have already garbage collected the object...
637 wxPyBeginBlockThreads();
638 Py_DECREF(self->m_obj);
639 wxPyEndBlockThreads();
640 }
4acff284
RD
641}
642
643void wxPyUserData_dtor(wxPyUserData* self) {
1e4a197e
RD
644 if (! wxPyDoingCleanup) {
645 wxPyBeginBlockThreads();
646 Py_DECREF(self->m_obj);
647 wxPyEndBlockThreads();
648 }
4acff284
RD
649}
650
651
652// This is called when an OOR controled object is being destroyed. Although
653// the C++ object is going away there is no way to force the Python object
654// (and all references to it) to die too. This causes problems (crashes) in
655// wxPython when a python shadow object attempts to call a C++ method using
656// the now bogus pointer... So to try and prevent this we'll do a little black
657// magic and change the class of the python instance to a class that will
658// raise an exception for any attempt to call methods with it. See
659// _wxPyDeadObject in _extras.py for the implementation of this class.
660void wxPyOORClientData_dtor(wxPyOORClientData* self) {
661
662 static PyObject* deadObjectClass = NULL;
663
664 wxPyBeginBlockThreads();
665 if (deadObjectClass == NULL) {
666 deadObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyDeadObject");
667 wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!"));
668 Py_INCREF(deadObjectClass);
669 }
670
1e4a197e 671
1fded56b
RD
672 // Only if there is more than one reference to the object
673 if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 ) {
4acff284 674 wxASSERT_MSG(PyInstance_Check(self->m_obj), wxT("m_obj not an instance!?!?!"));
1fded56b
RD
675
676 // Call __del__, if there is one.
677 PyObject* func = PyObject_GetAttrString(self->m_obj, "__del__");
678 if (func) {
679 PyObject* rv = PyObject_CallMethod(self->m_obj, "__del__", NULL);
680 Py_XDECREF(rv);
681 Py_DECREF(func);
682 }
683 if (PyErr_Occurred())
684 PyErr_Clear(); // just ignore it for now
685
686 // Clear the instance's dictionary
4acff284
RD
687 PyInstanceObject* inst = (PyInstanceObject*)self->m_obj;
688 PyDict_Clear(inst->in_dict);
1fded56b
RD
689
690 // put the name of the old class into the instance, and then reset the
691 // class to be the dead class.
4acff284
RD
692 PyDict_SetItemString(inst->in_dict, "_name", inst->in_class->cl_name);
693 inst->in_class = (PyClassObject*)deadObjectClass;
694 Py_INCREF(deadObjectClass);
695 }
1fded56b
RD
696
697 // m_obj is DECREF's in the base class dtor...
4acff284
RD
698 wxPyEndBlockThreads();
699}
7bf85405 700
1fded56b 701
9416aa89
RD
702//---------------------------------------------------------------------------
703// Stuff used by OOR to find the right wxPython class type to return and to
704// build it.
705
706
707// The pointer type map is used when the "pointer" type name generated by SWIG
708// is not the same as the shadow class name, for example wxPyTreeCtrl
709// vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++,
710// so we'll just make it a Python dictionary in the wx module's namespace.
4acff284 711// (See __wxSetDictionary)
9416aa89
RD
712void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
713 if (! wxPyPtrTypeMap)
714 wxPyPtrTypeMap = PyDict_New();
9416aa89
RD
715 PyDict_SetItemString(wxPyPtrTypeMap,
716 (char*)commonName,
717 PyString_FromString((char*)ptrName));
718}
719
720
721
a541c325 722PyObject* wxPyClassExists(const wxString& className) {
9416aa89 723
1e4a197e
RD
724 PyObject* item;
725 wxString name(className);
726 char buff[64]; // should always be big enough...
727
9416aa89
RD
728 if (!className)
729 return NULL;
730
1e4a197e
RD
731 // Try the name as-is first
732 sprintf(buff, "%sPtr", (const char*)name.mbc_str());
9416aa89
RD
733 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
734
1e4a197e
RD
735 // if not found see if there is a mapped name for it
736 if ( ! classobj) {
737 if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)(const char*)name.mbc_str())) != NULL) {
738 name = wxString(PyString_AsString(item), *wxConvCurrent);
739 sprintf(buff, "%sPtr", (const char*)name.mbc_str());
740 classobj = PyDict_GetItemString(wxPython_dict, buff);
741 }
742 }
743
9416aa89
RD
744 return classobj; // returns NULL if not found
745}
746
747
2f4e9287 748PyObject* wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) {
0122b7e3
RD
749 PyObject* target = NULL;
750 bool isEvtHandler = FALSE;
9416aa89
RD
751
752 if (source) {
2aab8f16 753 // If it's derived from wxEvtHandler then there may
2f4e9287
RD
754 // already be a pointer to a Python object that we can use
755 // in the OOR data.
756 if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) {
757 isEvtHandler = TRUE;
0122b7e3 758 wxEvtHandler* eh = (wxEvtHandler*)source;
4acff284 759 wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject();
0122b7e3
RD
760 if (data) {
761 target = data->m_obj;
762 Py_INCREF(target);
763 }
9416aa89 764 }
0122b7e3
RD
765
766 if (! target) {
2aab8f16
RD
767 // Otherwise make it the old fashioned way by making a
768 // new shadow object and putting this pointer in it.
1e4a197e
RD
769 wxClassInfo* info = source->GetClassInfo();
770 wxString name = info->GetClassName();
0122b7e3
RD
771 PyObject* klass = wxPyClassExists(name);
772 while (info && !klass) {
773 name = (wxChar*)info->GetBaseClassName1();
774 info = wxClassInfo::FindClass(name);
775 klass = wxPyClassExists(name);
776 }
777 if (info) {
778 target = wxPyConstructObject(source, name, klass, FALSE);
779 if (target && isEvtHandler)
4acff284 780 ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
0122b7e3 781 } else {
4acff284 782 wxString msg(wxT("wxPython class not found for "));
0122b7e3 783 msg += source->GetClassInfo()->GetClassName();
a541c325 784 PyErr_SetString(PyExc_NameError, msg.mbc_str());
0122b7e3
RD
785 target = NULL;
786 }
9416aa89
RD
787 }
788 } else { // source was NULL so return None.
789 Py_INCREF(Py_None); target = Py_None;
790 }
791 return target;
792}
793
0122b7e3 794
2f4e9287
RD
795PyObject* wxPyMake_wxSizer(wxSizer* source) {
796 PyObject* target = NULL;
797
798 if (source && wxIsKindOf(source, wxSizer)) {
799 // If it's derived from wxSizer then there may
800 // already be a pointer to a Python object that we can use
801 // in the OOR data.
802 wxSizer* sz = (wxSizer*)source;
4acff284 803 wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject();
2f4e9287
RD
804 if (data) {
805 target = data->m_obj;
806 Py_INCREF(target);
807 }
808 }
809 if (! target) {
810 target = wxPyMake_wxObject(source, FALSE);
811 if (target != Py_None)
4acff284 812 ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target));
2f4e9287
RD
813 }
814 return target;
815}
816
817
818
7bf85405
RD
819//---------------------------------------------------------------------------
820
c368d904 821PyObject* wxPyConstructObject(void* ptr,
a541c325 822 const wxString& className,
9416aa89 823 PyObject* klass,
1e7ecb7b 824 int setThisOwn) {
9416aa89 825
33510773
RD
826 PyObject* obj;
827 PyObject* arg;
9416aa89 828 PyObject* item;
a541c325 829 wxString name(className);
9416aa89
RD
830 char swigptr[64]; // should always be big enough...
831 char buff[64];
832
a541c325
RD
833 if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)(const char*)name.mbc_str())) != NULL) {
834 name = wxString(PyString_AsString(item), *wxConvCurrent);
9416aa89 835 }
a541c325 836 sprintf(buff, "_%s_p", (const char*)name.mbc_str());
9416aa89
RD
837 SWIG_MakePtr(swigptr, ptr, buff);
838
839 arg = Py_BuildValue("(s)", swigptr);
840 obj = PyInstance_New(klass, arg, NULL);
841 Py_DECREF(arg);
842
843 if (setThisOwn) {
844 PyObject* one = PyInt_FromLong(1);
845 PyObject_SetAttrString(obj, "thisown", one);
846 Py_DECREF(one);
847 }
848
849 return obj;
850}
851
852
853PyObject* wxPyConstructObject(void* ptr,
a541c325 854 const wxString& className,
9416aa89 855 int setThisOwn) {
33510773
RD
856 if (!ptr) {
857 Py_INCREF(Py_None);
858 return Py_None;
859 }
860
9c039d08 861 char buff[64]; // should always be big enough...
a541c325 862 sprintf(buff, "%sPtr", (const char*)className.mbc_str());
c5943253 863
a541c325 864 wxASSERT_MSG(wxPython_dict, wxT("wxPython_dict is not set yet!!"));
c5943253 865
7bf85405
RD
866 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
867 if (! classobj) {
e3dbf593
RD
868 wxString msg(wxT("wxPython class not found for "));
869 msg += className;
870 PyErr_SetString(PyExc_NameError, msg.mbc_str());
871 return NULL;
7bf85405
RD
872 }
873
9416aa89 874 return wxPyConstructObject(ptr, className, classobj, setThisOwn);
7bf85405
RD
875}
876
a541c325 877
d559219f 878//---------------------------------------------------------------------------
7bf85405 879
4958ea8f 880
cf694132 881#ifdef WXP_WITH_THREAD
4268f798
RD
882inline
883unsigned long wxPyGetCurrentThreadId() {
4958ea8f 884 return wxThread::GetCurrentId();
4268f798
RD
885}
886
be43cc44 887static PyThreadState* gs_shutdownTState;
4268f798
RD
888static
889PyThreadState* wxPyGetThreadState() {
be43cc44
RD
890 if (wxPyTMutex == NULL) // Python is shutting down...
891 return gs_shutdownTState;
892
4268f798
RD
893 unsigned long ctid = wxPyGetCurrentThreadId();
894 PyThreadState* tstate = NULL;
895
896 wxPyTMutex->Lock();
897 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
898 wxPyThreadState& info = wxPyTStates->Item(i);
899 if (info.tid == ctid) {
900 tstate = info.tstate;
901 break;
902 }
903 }
904 wxPyTMutex->Unlock();
a541c325 905 wxASSERT_MSG(tstate, wxT("PyThreadState should not be NULL!"));
4268f798
RD
906 return tstate;
907}
908
909static
910void wxPySaveThreadState(PyThreadState* tstate) {
be43cc44
RD
911 if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread...
912 gs_shutdownTState = tstate;
913 return;
914 }
4268f798
RD
915 unsigned long ctid = wxPyGetCurrentThreadId();
916 wxPyTMutex->Lock();
917 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
918 wxPyThreadState& info = wxPyTStates->Item(i);
919 if (info.tid == ctid) {
763d71e4
RD
920#if 0
921 if (info.tstate != tstate)
922 wxLogMessage("*** tstate mismatch!???");
923#endif
46e10fde 924 // info.tstate = tstate; *** DO NOT update existing ones???
763d71e4
RD
925 // Normally it will never change, but apparently COM callbacks
926 // (i.e. ActiveX controls) will (incorrectly IMHO) use a transient
46e10fde 927 // tstate which will then be garbage the next time we try to use
763d71e4 928 // it...
4268f798
RD
929 wxPyTMutex->Unlock();
930 return;
931 }
1112b0c6 932 }
4268f798
RD
933 // not found, so add it...
934 wxPyTStates->Add(new wxPyThreadState(ctid, tstate));
935 wxPyTMutex->Unlock();
936}
937
938#endif
939
940
941// Calls from Python to wxWindows code are wrapped in calls to these
942// functions:
943
944PyThreadState* wxPyBeginAllowThreads() {
945#ifdef WXP_WITH_THREAD
946 PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS;
947 wxPySaveThreadState(saved);
948 return saved;
949#else
950 return NULL;
951#endif
952}
953
954void wxPyEndAllowThreads(PyThreadState* saved) {
955#ifdef WXP_WITH_THREAD
956 PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS;
cf694132 957#endif
d559219f 958}
cf694132 959
cf694132 960
4268f798
RD
961
962// Calls from wxWindows back to Python code, or even any PyObject
963// manipulations, PyDECREF's and etc. are wrapped in calls to these functions:
964
965void wxPyBeginBlockThreads() {
cf694132 966#ifdef WXP_WITH_THREAD
4268f798
RD
967 PyThreadState* tstate = wxPyGetThreadState();
968 PyEval_RestoreThread(tstate);
969#endif
970}
971
972
973void wxPyEndBlockThreads() {
974#ifdef WXP_WITH_THREAD
4268f798 975 // Is there any need to save it again?
c4770edd
RD
976 // PyThreadState* tstate =
977 PyEval_SaveThread();
1112b0c6 978#endif
cf694132
RD
979}
980
19a97bd6 981
d559219f 982//---------------------------------------------------------------------------
f74ff5ef
RD
983// wxPyInputStream and wxPyCBInputStream methods
984
f74ff5ef
RD
985
986void wxPyInputStream::close() {
a541c325 987 /* do nothing for now */
f74ff5ef
RD
988}
989
990void wxPyInputStream::flush() {
a541c325 991 /* do nothing for now */
f74ff5ef
RD
992}
993
994bool wxPyInputStream::eof() {
995 if (m_wxis)
996 return m_wxis->Eof();
997 else
998 return TRUE;
999}
1000
1001wxPyInputStream::~wxPyInputStream() {
1002 /* do nothing */
1003}
1004
a541c325
RD
1005
1006
1007
1008PyObject* wxPyInputStream::read(int size) {
1009 PyObject* obj = NULL;
1010 wxMemoryBuffer buf;
f74ff5ef
RD
1011 const int BUFSIZE = 1024;
1012
1013 // check if we have a real wxInputStream to work with
1014 if (!m_wxis) {
1e4a197e 1015 wxPyBeginBlockThreads();
f74ff5ef 1016 PyErr_SetString(PyExc_IOError, "no valid C-wxInputStream");
1e4a197e 1017 wxPyEndBlockThreads();
f74ff5ef
RD
1018 return NULL;
1019 }
1020
1021 if (size < 0) {
1e4a197e
RD
1022 // read while bytes are available on the stream
1023 while ( m_wxis->CanRead() ) {
a541c325
RD
1024 m_wxis->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE);
1025 buf.UngetAppendBuf(m_wxis->LastRead());
f74ff5ef
RD
1026 }
1027
1028 } else { // Read only size number of characters
a541c325
RD
1029 m_wxis->Read(buf.GetWriteBuf(size), size);
1030 buf.UngetWriteBuf(m_wxis->LastRead());
1031 }
f74ff5ef 1032
a541c325 1033 // error check
1e4a197e
RD
1034 wxPyBeginBlockThreads();
1035 wxStreamError err = m_wxis->GetLastError();
1036 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
a541c325
RD
1037 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
1038 }
1039 else {
1040 // We use only strings for the streams, not unicode
1041 obj = PyString_FromStringAndSize(buf, buf.GetDataLen());
f74ff5ef 1042 }
1e4a197e 1043 wxPyEndBlockThreads();
a541c325 1044 return obj;
f74ff5ef
RD
1045}
1046
1047
a541c325
RD
1048PyObject* wxPyInputStream::readline(int size) {
1049 PyObject* obj = NULL;
1050 wxMemoryBuffer buf;
1051 int i;
1052 char ch;
1053
f74ff5ef
RD
1054 // check if we have a real wxInputStream to work with
1055 if (!m_wxis) {
1e4a197e 1056 wxPyBeginBlockThreads();
f74ff5ef 1057 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream");
1e4a197e 1058 wxPyEndBlockThreads();
f74ff5ef
RD
1059 return NULL;
1060 }
1061
f74ff5ef 1062 // read until \n or byte limit reached
1e4a197e 1063 for (i=ch=0; (ch != '\n') && (m_wxis->CanRead()) && ((size < 0) || (i < size)); i++) {
a541c325
RD
1064 ch = m_wxis->GetC();
1065 buf.AppendByte(ch);
f74ff5ef
RD
1066 }
1067
1068 // errorcheck
1e4a197e
RD
1069 wxPyBeginBlockThreads();
1070 wxStreamError err = m_wxis->GetLastError();
1071 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
f74ff5ef 1072 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
f74ff5ef 1073 }
a541c325
RD
1074 else {
1075 // We use only strings for the streams, not unicode
1076 obj = PyString_FromStringAndSize((char*)buf.GetData(), buf.GetDataLen());
1077 }
1e4a197e 1078 wxPyEndBlockThreads();
a541c325 1079 return obj;
f74ff5ef
RD
1080}
1081
1082
a541c325
RD
1083PyObject* wxPyInputStream::readlines(int sizehint) {
1084 PyObject* pylist;
1085
f74ff5ef
RD
1086 // check if we have a real wxInputStream to work with
1087 if (!m_wxis) {
1e4a197e
RD
1088 wxPyBeginBlockThreads();
1089 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream");
1090 wxPyEndBlockThreads();
f74ff5ef
RD
1091 return NULL;
1092 }
1093
1094 // init list
1e4a197e 1095 wxPyBeginBlockThreads();
a541c325
RD
1096 pylist = PyList_New(0);
1097 if (!pylist) {
1e4a197e 1098 wxPyBeginBlockThreads();
f74ff5ef 1099 PyErr_NoMemory();
1e4a197e 1100 wxPyEndBlockThreads();
f74ff5ef
RD
1101 return NULL;
1102 }
1103
1104 // read sizehint bytes or until EOF
1105 int i;
1e4a197e 1106 for (i=0; (m_wxis->CanRead()) && ((sizehint < 0) || (i < sizehint));) {
a541c325 1107 PyObject* s = this->readline();
f74ff5ef 1108 if (s == NULL) {
1e4a197e 1109 wxPyBeginBlockThreads();
a541c325 1110 Py_DECREF(pylist);
1e4a197e 1111 wxPyEndBlockThreads();
f74ff5ef
RD
1112 return NULL;
1113 }
1e4a197e 1114 wxPyBeginBlockThreads();
a541c325
RD
1115 PyList_Append(pylist, s);
1116 i += PyString_Size(s);
1e4a197e 1117 wxPyEndBlockThreads();
f74ff5ef
RD
1118 }
1119
1120 // error check
1e4a197e
RD
1121 wxStreamError err = m_wxis->GetLastError();
1122 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
1123 wxPyBeginBlockThreads();
a541c325 1124 Py_DECREF(pylist);
f74ff5ef 1125 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
1e4a197e 1126 wxPyEndBlockThreads();
f74ff5ef
RD
1127 return NULL;
1128 }
a541c325
RD
1129
1130 return pylist;
f74ff5ef
RD
1131}
1132
1133
1134void wxPyInputStream::seek(int offset, int whence) {
1135 if (m_wxis)
1136 m_wxis->SeekI(offset, wxSeekMode(whence));
1137}
1138
1139int wxPyInputStream::tell(){
1140 if (m_wxis)
1141 return m_wxis->TellI();
1142 else return 0;
1143}
1144
1145
1146
1147
1148wxPyCBInputStream::wxPyCBInputStream(PyObject *r, PyObject *s, PyObject *t, bool block)
1149 : wxInputStream(), m_read(r), m_seek(s), m_tell(t), m_block(block)
1150{}
1151
1152
1153wxPyCBInputStream::~wxPyCBInputStream() {
1154 if (m_block) wxPyBeginBlockThreads();
1155 Py_XDECREF(m_read);
1156 Py_XDECREF(m_seek);
1157 Py_XDECREF(m_tell);
1158 if (m_block) wxPyEndBlockThreads();
1159}
1160
1161
1162wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) {
1163 if (block) wxPyBeginBlockThreads();
1164
1165 PyObject* read = getMethod(py, "read");
1166 PyObject* seek = getMethod(py, "seek");
1167 PyObject* tell = getMethod(py, "tell");
1168
1169 if (!read) {
1170 PyErr_SetString(PyExc_TypeError, "Not a file-like object");
1171 Py_XDECREF(read);
1172 Py_XDECREF(seek);
1173 Py_XDECREF(tell);
1174 if (block) wxPyEndBlockThreads();
1175 return NULL;
1176 }
1177
1178 if (block) wxPyEndBlockThreads();
1179 return new wxPyCBInputStream(read, seek, tell, block);
1180}
1181
249a57f4
RD
1182
1183wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block) {
1184 return wxPyCBInputStream::create(py, block);
1185}
1186
f74ff5ef
RD
1187PyObject* wxPyCBInputStream::getMethod(PyObject* py, char* name) {
1188 if (!PyObject_HasAttrString(py, name))
1189 return NULL;
1190 PyObject* o = PyObject_GetAttrString(py, name);
1191 if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
1192 Py_DECREF(o);
1193 return NULL;
1194 }
1195 return o;
1196}
1197
1198
1199size_t wxPyCBInputStream::GetSize() const {
1200 wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const
1201 if (m_seek && m_tell) {
1202 off_t temp = self->OnSysTell();
1203 off_t ret = self->OnSysSeek(0, wxFromEnd);
1204 self->OnSysSeek(temp, wxFromStart);
1205 return ret;
1206 }
1207 else
1208 return 0;
1209}
1210
1211
1212size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
1213 if (bufsize == 0)
1214 return 0;
1215
1216 wxPyBeginBlockThreads();
1217 PyObject* arglist = Py_BuildValue("(i)", bufsize);
1218 PyObject* result = PyEval_CallObject(m_read, arglist);
1219 Py_DECREF(arglist);
1220
1221 size_t o = 0;
a541c325 1222 if ((result != NULL) && PyString_Check(result)) {
f74ff5ef
RD
1223 o = PyString_Size(result);
1224 if (o == 0)
1225 m_lasterror = wxSTREAM_EOF;
1226 if (o > bufsize)
1227 o = bufsize;
a541c325 1228 memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode...
f74ff5ef
RD
1229 Py_DECREF(result);
1230
1231 }
1232 else
1233 m_lasterror = wxSTREAM_READ_ERROR;
1234 wxPyEndBlockThreads();
f74ff5ef
RD
1235 return o;
1236}
1237
1238size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) {
1239 m_lasterror = wxSTREAM_WRITE_ERROR;
1240 return 0;
1241}
1242
1243off_t wxPyCBInputStream::OnSysSeek(off_t off, wxSeekMode mode) {
1244 wxPyBeginBlockThreads();
1fded56b
RD
1245#ifdef _LARGE_FILES
1246 // off_t is a 64-bit value...
1247 PyObject* arglist = Py_BuildValue("(Li)", off, mode);
1248#else
f74ff5ef 1249 PyObject* arglist = Py_BuildValue("(ii)", off, mode);
1fded56b 1250#endif
f74ff5ef
RD
1251 PyObject* result = PyEval_CallObject(m_seek, arglist);
1252 Py_DECREF(arglist);
1253 Py_XDECREF(result);
1254 wxPyEndBlockThreads();
1255 return OnSysTell();
1256}
1257
1fded56b 1258
f74ff5ef
RD
1259off_t wxPyCBInputStream::OnSysTell() const {
1260 wxPyBeginBlockThreads();
1261 PyObject* arglist = Py_BuildValue("()");
1262 PyObject* result = PyEval_CallObject(m_tell, arglist);
1263 Py_DECREF(arglist);
1264 off_t o = 0;
1265 if (result != NULL) {
1fded56b
RD
1266#ifdef _LARGE_FILES
1267 if (PyLong_Check(result))
1268 o = PyLong_AsLongLong(result);
1269 else
1270#else
f74ff5ef 1271 o = PyInt_AsLong(result);
1fded56b 1272#endif
f74ff5ef
RD
1273 Py_DECREF(result);
1274 };
1275 wxPyEndBlockThreads();
1276 return o;
1277}
1278
1279//----------------------------------------------------------------------
d559219f 1280
2f90df85
RD
1281IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
1282
d559219f
RD
1283wxPyCallback::wxPyCallback(PyObject* func) {
1284 m_func = func;
1285 Py_INCREF(m_func);
1286}
1287
2f90df85
RD
1288wxPyCallback::wxPyCallback(const wxPyCallback& other) {
1289 m_func = other.m_func;
1290 Py_INCREF(m_func);
1291}
1292
d559219f 1293wxPyCallback::~wxPyCallback() {
4268f798 1294 wxPyBeginBlockThreads();
d559219f 1295 Py_DECREF(m_func);
4268f798 1296 wxPyEndBlockThreads();
d559219f
RD
1297}
1298
cf694132
RD
1299
1300
7bf85405
RD
1301// This function is used for all events destined for Python event handlers.
1302void wxPyCallback::EventThunker(wxEvent& event) {
1303 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
1304 PyObject* func = cb->m_func;
1305 PyObject* result;
1306 PyObject* arg;
1307 PyObject* tuple;
1308
cf694132 1309
4268f798 1310 wxPyBeginBlockThreads();
65dd82cb
RD
1311 wxString className = event.GetClassInfo()->GetClassName();
1312
1e4a197e 1313 if (className == wxT("wxPyEvent"))
65dd82cb 1314 arg = ((wxPyEvent*)&event)->GetSelf();
1e4a197e 1315 else if (className == wxT("wxPyCommandEvent"))
65dd82cb 1316 arg = ((wxPyCommandEvent*)&event)->GetSelf();
c8bc7bb8 1317 else {
a541c325 1318 arg = wxPyConstructObject((void*)&event, className);
c8bc7bb8 1319 }
7bf85405
RD
1320
1321 tuple = PyTuple_New(1);
1322 PyTuple_SET_ITEM(tuple, 0, arg);
1323 result = PyEval_CallObject(func, tuple);
7bf85405
RD
1324 Py_DECREF(tuple);
1325 if (result) {
1326 Py_DECREF(result);
ac346f50 1327 PyErr_Clear(); // Just in case...
7bf85405
RD
1328 } else {
1329 PyErr_Print();
1330 }
4268f798 1331 wxPyEndBlockThreads();
7bf85405
RD
1332}
1333
1334
d559219f 1335//----------------------------------------------------------------------
7bf85405 1336
2f90df85
RD
1337wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
1338 m_lastFound = NULL;
1339 m_self = other.m_self;
f6bcfd97
BP
1340 m_class = other.m_class;
1341 if (m_self) {
2f90df85 1342 Py_INCREF(m_self);
f6bcfd97
BP
1343 Py_INCREF(m_class);
1344 }
2f90df85
RD
1345}
1346
1347
33510773 1348void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
d559219f 1349 m_self = self;
33510773 1350 m_class = klass;
b7312675 1351 m_incRef = incref;
f6bcfd97 1352 if (incref) {
2f90df85 1353 Py_INCREF(m_self);
f6bcfd97
BP
1354 Py_INCREF(m_class);
1355 }
d559219f 1356}
8bf5d46e 1357
8bf5d46e 1358
78b57918
RD
1359#if PYTHON_API_VERSION >= 1011
1360
1361// Prior to Python 2.2 PyMethod_GetClass returned the class object
1362// in which the method was defined. Starting with 2.2 it returns
1363// "class that asked for the method" which seems totally bogus to me
4152e8b9 1364// but apprently it fixes some obscure problem waiting to happen in
78b57918
RD
1365// Python. Since the API was not documented Guido and the gang felt
1366// safe in changing it. Needless to say that totally screwed up the
1367// logic below in wxPyCallbackHelper::findCallback, hence this icky
4152e8b9 1368// code to find the class where the method is actually defined...
78b57918
RD
1369
1370static
1371PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name)
1372{
1373 int i, n;
1374
1375 if (PyType_Check(klass)) { // new style classes
1376 // This code is borrowed/adapted from _PyType_Lookup in typeobject.c
4a98c806 1377 // (TODO: This part is not tested yet, so I'm not sure it is correct...)
78b57918
RD
1378 PyTypeObject* type = (PyTypeObject*)klass;
1379 PyObject *mro, *res, *base, *dict;
1380 /* Look in tp_dict of types in MRO */
1381 mro = type->tp_mro;
1382 assert(PyTuple_Check(mro));
1383 n = PyTuple_GET_SIZE(mro);
1384 for (i = 0; i < n; i++) {
1385 base = PyTuple_GET_ITEM(mro, i);
1386 if (PyClass_Check(base))
1387 dict = ((PyClassObject *)base)->cl_dict;
1388 else {
1389 assert(PyType_Check(base));
1390 dict = ((PyTypeObject *)base)->tp_dict;
1391 }
1392 assert(dict && PyDict_Check(dict));
1393 res = PyDict_GetItem(dict, name);
1394 if (res != NULL)
4a98c806 1395 return base;
78b57918
RD
1396 }
1397 return NULL;
1398 }
1399
1400 else if (PyClass_Check(klass)) { // old style classes
1401 // This code is borrowed/adapted from class_lookup in classobject.c
1402 PyClassObject* cp = (PyClassObject*)klass;
1403 PyObject *value = PyDict_GetItem(cp->cl_dict, name);
1404 if (value != NULL) {
1405 return (PyObject*)cp;
1406 }
1407 n = PyTuple_Size(cp->cl_bases);
1408 for (i = 0; i < n; i++) {
1409 PyObject* base = PyTuple_GetItem(cp->cl_bases, i);
1410 PyObject *v = PyFindClassWithAttr(base, name);
1411 if (v != NULL)
1412 return v;
1413 }
1414 return NULL;
1415 }
4152e8b9 1416 return NULL;
78b57918
RD
1417}
1418#endif
1419
1420
1421static
1422PyObject* PyMethod_GetDefiningClass(PyObject* method, const char* name)
1423{
1424 PyObject* mgc = PyMethod_GET_CLASS(method);
1425
1426#if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
1427 return mgc;
1428#else // 2.2 and after, the hard way...
1429
1430 PyObject* nameo = PyString_FromString(name);
1431 PyObject* klass = PyFindClassWithAttr(mgc, nameo);
1432 Py_DECREF(nameo);
1433 return klass;
1434#endif
1435}
1436
1437
1438
de20db99 1439bool wxPyCallbackHelper::findCallback(const char* name) const {
f6bcfd97
BP
1440 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
1441 self->m_lastFound = NULL;
78b57918
RD
1442
1443 // If the object (m_self) has an attibute of the given name...
de20db99 1444 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
78b57918 1445 PyObject *method, *klass;
de20db99 1446 method = PyObject_GetAttrString(m_self, (char*)name);
f6bcfd97 1447
78b57918
RD
1448 // ...and if that attribute is a method, and if that method's class is
1449 // not from a base class...
f6bcfd97 1450 if (PyMethod_Check(method) &&
78b57918
RD
1451 (klass = PyMethod_GetDefiningClass(method, (char*)name)) != NULL &&
1452 ((klass == m_class) || PyClass_IsSubclass(klass, m_class))) {
8bf5d46e 1453
78b57918 1454 // ...then we'll save a pointer to the method so callCallback can call it.
f6bcfd97
BP
1455 self->m_lastFound = method;
1456 }
de20db99
RD
1457 else {
1458 Py_DECREF(method);
1459 }
f6bcfd97 1460 }
d559219f
RD
1461 return m_lastFound != NULL;
1462}
8bf5d46e 1463
d559219f 1464
f6bcfd97 1465int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
d559219f
RD
1466 PyObject* result;
1467 int retval = FALSE;
1468
1469 result = callCallbackObj(argTuple);
1470 if (result) { // Assumes an integer return type...
1471 retval = PyInt_AsLong(result);
1472 Py_DECREF(result);
1473 PyErr_Clear(); // forget about it if it's not...
1474 }
1475 return retval;
1476}
1477
1478// Invoke the Python callable object, returning the raw PyObject return
1479// value. Caller should DECREF the return value and also call PyEval_SaveThread.
f6bcfd97 1480PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
de20db99 1481 PyObject* result;
d559219f 1482
de20db99
RD
1483 // Save a copy of the pointer in case the callback generates another
1484 // callback. In that case m_lastFound will have a different value when
1485 // it gets back here...
1486 PyObject* method = m_lastFound;
1487
1488 result = PyEval_CallObject(method, argTuple);
d559219f 1489 Py_DECREF(argTuple);
de20db99 1490 Py_DECREF(method);
d559219f
RD
1491 if (!result) {
1492 PyErr_Print();
1493 }
1494 return result;
1495}
714e6a9e 1496
7bf85405 1497
0122b7e3 1498void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
1e7ecb7b
RD
1499 cbh.setSelf(self, klass, incref);
1500}
1501
1502bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
1503 return cbh.findCallback(name);
1504}
1505
1506int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1507 return cbh.callCallback(argTuple);
1508}
1509
1510PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1511 return cbh.callCallbackObj(argTuple);
1512}
1513
1514
1515void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
1e7ecb7b 1516 if (cbh->m_incRef) {
4268f798 1517 wxPyBeginBlockThreads();
1e7ecb7b
RD
1518 Py_XDECREF(cbh->m_self);
1519 Py_XDECREF(cbh->m_class);
4268f798 1520 wxPyEndBlockThreads();
1e7ecb7b 1521 }
1e7ecb7b 1522}
d559219f 1523
65dd82cb
RD
1524//---------------------------------------------------------------------------
1525//---------------------------------------------------------------------------
2aab8f16 1526// These event classes can be derived from in Python and passed through the event
c368d904 1527// system without losing anything. They do this by keeping a reference to
65dd82cb
RD
1528// themselves and some special case handling in wxPyCallback::EventThunker.
1529
1530
e19b7164 1531wxPyEvtSelfRef::wxPyEvtSelfRef() {
65dd82cb
RD
1532 //m_self = Py_None; // **** We don't do normal ref counting to prevent
1533 //Py_INCREF(m_self); // circular loops...
194fa2ac 1534 m_cloned = FALSE;
65dd82cb
RD
1535}
1536
e19b7164 1537wxPyEvtSelfRef::~wxPyEvtSelfRef() {
4268f798 1538 wxPyBeginBlockThreads();
65dd82cb
RD
1539 if (m_cloned)
1540 Py_DECREF(m_self);
4268f798 1541 wxPyEndBlockThreads();
65dd82cb
RD
1542}
1543
e19b7164 1544void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
4268f798 1545 wxPyBeginBlockThreads();
65dd82cb
RD
1546 if (m_cloned)
1547 Py_DECREF(m_self);
1548 m_self = self;
1549 if (clone) {
1550 Py_INCREF(m_self);
1551 m_cloned = TRUE;
1552 }
4268f798 1553 wxPyEndBlockThreads();
65dd82cb
RD
1554}
1555
e19b7164 1556PyObject* wxPyEvtSelfRef::GetSelf() const {
65dd82cb
RD
1557 Py_INCREF(m_self);
1558 return m_self;
1559}
1560
1561
07b2e1cd
RD
1562IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
1563IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
1564
1565
65dd82cb
RD
1566wxPyEvent::wxPyEvent(int id)
1567 : wxEvent(id) {
1568}
1569
65dd82cb 1570
07b2e1cd
RD
1571wxPyEvent::wxPyEvent(const wxPyEvent& evt)
1572 : wxEvent(evt)
1573{
1574 SetSelf(evt.m_self, TRUE);
65dd82cb
RD
1575}
1576
1577
07b2e1cd
RD
1578wxPyEvent::~wxPyEvent() {
1579}
65dd82cb
RD
1580
1581
1582wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
1583 : wxCommandEvent(commandType, id) {
1584}
1585
65dd82cb 1586
07b2e1cd
RD
1587wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
1588 : wxCommandEvent(evt)
1589{
1590 SetSelf(evt.m_self, TRUE);
65dd82cb
RD
1591}
1592
1593
07b2e1cd
RD
1594wxPyCommandEvent::~wxPyCommandEvent() {
1595}
1596
65dd82cb
RD
1597
1598
1599
d559219f 1600//---------------------------------------------------------------------------
7bf85405
RD
1601//---------------------------------------------------------------------------
1602
d559219f 1603
7bf85405
RD
1604wxPyTimer::wxPyTimer(PyObject* callback) {
1605 func = callback;
1606 Py_INCREF(func);
1607}
1608
1609wxPyTimer::~wxPyTimer() {
4268f798 1610 wxPyBeginBlockThreads();
7bf85405 1611 Py_DECREF(func);
4268f798 1612 wxPyEndBlockThreads();
7bf85405
RD
1613}
1614
1615void wxPyTimer::Notify() {
185d7c3e
RD
1616 if (!func || func == Py_None) {
1617 wxTimer::Notify();
1618 }
1619 else {
4268f798 1620 wxPyBeginBlockThreads();
185d7c3e
RD
1621
1622 PyObject* result;
1623 PyObject* args = Py_BuildValue("()");
1624
1625 result = PyEval_CallObject(func, args);
1626 Py_DECREF(args);
1627 if (result) {
1628 Py_DECREF(result);
1629 PyErr_Clear();
1630 } else {
1631 PyErr_Print();
1632 }
7bf85405 1633
4268f798 1634 wxPyEndBlockThreads();
7bf85405
RD
1635 }
1636}
1637
1638
cf694132 1639
2f90df85 1640//---------------------------------------------------------------------------
389c5527
RD
1641//---------------------------------------------------------------------------
1642// Convert a wxList to a Python List
1643
1e4a197e
RD
1644PyObject* wxPy_ConvertList(wxListBase* listbase, const char* className) {
1645 wxList* list = (wxList*)listbase; // this is probably bad...
389c5527
RD
1646 PyObject* pyList;
1647 PyObject* pyObj;
1648 wxObject* wxObj;
1e4a197e 1649 wxNode* node = list->GetFirst();
389c5527 1650
4268f798 1651 wxPyBeginBlockThreads();
389c5527
RD
1652 pyList = PyList_New(0);
1653 while (node) {
1e4a197e 1654 wxObj = node->GetData();
9416aa89 1655 pyObj = wxPyMake_wxObject(wxObj); //wxPyConstructObject(wxObj, className);
389c5527 1656 PyList_Append(pyList, pyObj);
1e4a197e 1657 node = node->GetNext();
389c5527 1658 }
4268f798 1659 wxPyEndBlockThreads();
389c5527
RD
1660 return pyList;
1661}
1662
54b96882
RD
1663//----------------------------------------------------------------------
1664
1665long wxPyGetWinHandle(wxWindow* win) {
1666#ifdef __WXMSW__
1667 return (long)win->GetHandle();
1668#endif
1669
1670 // Find and return the actual X-Window.
1671#ifdef __WXGTK__
1672 if (win->m_wxwindow) {
1e4a197e
RD
1673#ifdef __WXGTK20__
1674 return (long) GDK_WINDOW_XWINDOW(GTK_PIZZA(win->m_wxwindow)->bin_window);
1675#else
54b96882
RD
1676 GdkWindowPrivate* bwin = (GdkWindowPrivate*)GTK_PIZZA(win->m_wxwindow)->bin_window;
1677 if (bwin) {
1678 return (long)bwin->xwindow;
1679 }
1e4a197e 1680#endif
54b96882
RD
1681 }
1682#endif
1683 return 0;
1684}
1685
7bf85405
RD
1686//----------------------------------------------------------------------
1687// Some helper functions for typemaps in my_typemaps.i, so they won't be
c8bc7bb8
RD
1688// included in every file over and over again...
1689
1690#if PYTHON_API_VERSION >= 1009
1691 static char* wxStringErrorMsg = "String or Unicode type required";
1692#else
1693 static char* wxStringErrorMsg = "String type required";
1694#endif
1695
1696
1697wxString* wxString_in_helper(PyObject* source) {
1698 wxString* target;
1699#if PYTHON_API_VERSION >= 1009 // Have Python unicode API
1700 if (!PyString_Check(source) && !PyUnicode_Check(source)) {
1701 PyErr_SetString(PyExc_TypeError, wxStringErrorMsg);
1702 return NULL;
1703 }
1704#if wxUSE_UNICODE
1705 if (PyUnicode_Check(source)) {
1e4a197e
RD
1706 target = new wxString();
1707 size_t len = PyUnicode_GET_SIZE(source);
1708 if (len) {
1709 PyUnicode_AsWideChar((PyUnicodeObject*)source, target->GetWriteBuf(len), len);
1710 target->UngetWriteBuf();
1711 }
c8bc7bb8 1712 } else {
a541c325
RD
1713 // It is a string, get pointers to it and transform to unicode
1714 char* tmpPtr; int tmpSize;
1715 PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
1716 target = new wxString(tmpPtr, *wxConvCurrent, tmpSize);
c8bc7bb8
RD
1717 }
1718#else
1719 char* tmpPtr; int tmpSize;
1720 if (PyString_AsStringAndSize(source, &tmpPtr, &tmpSize) == -1) {
1721 PyErr_SetString(PyExc_TypeError, "Unable to convert string");
1722 return NULL;
1723 }
1724 target = new wxString(tmpPtr, tmpSize);
1725#endif // wxUSE_UNICODE
1726
1727#else // No Python unicode API (1.5.2)
1728 if (!PyString_Check(source)) {
1729 PyErr_SetString(PyExc_TypeError, wxStringErrorMsg);
1730 return NULL;
1731 }
1732 target = new wxString(PyString_AS_STRING(source), PyString_GET_SIZE(source));
1733#endif
1734 return target;
1735}
1736
7bf85405 1737
a541c325
RD
1738// Similar to above except doesn't use "new" and doesn't set an exception
1739wxString Py2wxString(PyObject* source)
1740{
1741 wxString target;
1742 bool doDecRef = FALSE;
1743
1744#if PYTHON_API_VERSION >= 1009 // Have Python unicode API
1745 if (!PyString_Check(source) && !PyUnicode_Check(source)) {
1746 // Convert to String if not one already... (TODO: Unicode too?)
1747 source = PyObject_Str(source);
1748 doDecRef = TRUE;
1749 }
1750
1751#if wxUSE_UNICODE
1752 if (PyUnicode_Check(source)) {
1e4a197e
RD
1753 size_t len = PyUnicode_GET_SIZE(source);
1754 if (len) {
1755 PyUnicode_AsWideChar((PyUnicodeObject*)source, target.GetWriteBuf(len), len);
1756 target.UngetWriteBuf();
1757 }
a541c325
RD
1758 } else {
1759 // It is a string, get pointers to it and transform to unicode
1760 char* tmpPtr; int tmpSize;
1761 PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
1762 target = wxString(tmpPtr, *wxConvCurrent, tmpSize);
1763 }
1764#else
1765 char* tmpPtr; int tmpSize;
1766 PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
1767 target = wxString(tmpPtr, tmpSize);
1768#endif // wxUSE_UNICODE
1769
1770#else // No Python unicode API (1.5.2)
1771 if (!PyString_Check(source)) {
1772 // Convert to String if not one already...
1773 source = PyObject_Str(source);
1774 doDecRef = TRUE;
1775 }
1776 target = wxString(PyString_AS_STRING(source), PyString_GET_SIZE(source));
1777#endif
1778
1779 if (doDecRef)
1780 Py_DECREF(source);
1781 return target;
1782}
1783
1784
1785// Make either a Python String or Unicode object, depending on build mode
1786PyObject* wx2PyString(const wxString& src)
1787{
1788 PyObject* str;
1789#if wxUSE_UNICODE
1e4a197e 1790 str = PyUnicode_FromWideChar(src.c_str(), src.Len());
a541c325
RD
1791#else
1792 str = PyString_FromStringAndSize(src.c_str(), src.Len());
1793#endif
1794 return str;
1795}
1796
1797
1798//----------------------------------------------------------------------
1799
7bf85405 1800
2f90df85 1801byte* byte_LIST_helper(PyObject* source) {
b639c3c5
RD
1802 if (!PyList_Check(source)) {
1803 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1804 return NULL;
1805 }
1806 int count = PyList_Size(source);
1807 byte* temp = new byte[count];
1808 if (! temp) {
1809 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1810 return NULL;
1811 }
1812 for (int x=0; x<count; x++) {
1813 PyObject* o = PyList_GetItem(source, x);
1814 if (! PyInt_Check(o)) {
1815 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1816 return NULL;
1817 }
1818 temp[x] = (byte)PyInt_AsLong(o);
1819 }
1820 return temp;
1821}
1822
1823
2f90df85 1824int* int_LIST_helper(PyObject* source) {
7bf85405
RD
1825 if (!PyList_Check(source)) {
1826 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1827 return NULL;
1828 }
1829 int count = PyList_Size(source);
1830 int* temp = new int[count];
1831 if (! temp) {
1832 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1833 return NULL;
1834 }
1835 for (int x=0; x<count; x++) {
1836 PyObject* o = PyList_GetItem(source, x);
1837 if (! PyInt_Check(o)) {
1838 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1839 return NULL;
1840 }
1841 temp[x] = PyInt_AsLong(o);
1842 }
1843 return temp;
1844}
1845
1846
2f90df85 1847long* long_LIST_helper(PyObject* source) {
7bf85405
RD
1848 if (!PyList_Check(source)) {
1849 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1850 return NULL;
1851 }
1852 int count = PyList_Size(source);
1853 long* temp = new long[count];
1854 if (! temp) {
1855 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1856 return NULL;
1857 }
1858 for (int x=0; x<count; x++) {
1859 PyObject* o = PyList_GetItem(source, x);
1860 if (! PyInt_Check(o)) {
1861 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
1862 return NULL;
1863 }
1864 temp[x] = PyInt_AsLong(o);
1865 }
1866 return temp;
1867}
1868
1869
2f90df85 1870char** string_LIST_helper(PyObject* source) {
7bf85405
RD
1871 if (!PyList_Check(source)) {
1872 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
1873 return NULL;
1874 }
1875 int count = PyList_Size(source);
1876 char** temp = new char*[count];
1877 if (! temp) {
1878 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1879 return NULL;
1880 }
1881 for (int x=0; x<count; x++) {
1882 PyObject* o = PyList_GetItem(source, x);
1883 if (! PyString_Check(o)) {
1884 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
1885 return NULL;
1886 }
1887 temp[x] = PyString_AsString(o);
1888 }
1889 return temp;
1890}
1891
e0672e2f
RD
1892//--------------------------------
1893// Part of patch from Tim Hochberg
1894static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
1895 if (PyInt_Check(o1) && PyInt_Check(o2)) {
1896 point->x = PyInt_AS_LONG(o1);
1897 point->y = PyInt_AS_LONG(o2);
1898 return true;
1899 }
1900 if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
1901 point->x = (int)PyFloat_AS_DOUBLE(o1);
1902 point->y = (int)PyFloat_AS_DOUBLE(o2);
1903 return true;
1904 }
1905 if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
1906 // Disallow instances because they can cause havok
1907 return false;
1908 }
1909 if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
1910 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
1911 point->x = PyInt_AsLong(o1);
1912 point->y = PyInt_AsLong(o2);
1913 return true;
1914 }
1915 return false;
1916}
7bf85405
RD
1917
1918
e0672e2f
RD
1919wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
1920 // Putting all of the declarations here allows
1921 // us to put the error handling all in one place.
1922 int x;
1923 wxPoint* temp;
1924 PyObject *o, *o1, *o2;
9d37f964 1925 bool isFast = PyList_Check(source) || PyTuple_Check(source);
e0672e2f 1926
e0672e2f
RD
1927 if (!PySequence_Check(source)) {
1928 goto error0;
7bf85405 1929 }
9d37f964
RD
1930
1931 // The length of the sequence is returned in count.
e0672e2f
RD
1932 *count = PySequence_Length(source);
1933 if (*count < 0) {
1934 goto error0;
1935 }
1936
1937 temp = new wxPoint[*count];
1938 if (!temp) {
7bf85405
RD
1939 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
1940 return NULL;
1941 }
e0672e2f
RD
1942 for (x=0; x<*count; x++) {
1943 // Get an item: try fast way first.
1944 if (isFast) {
1945 o = PySequence_Fast_GET_ITEM(source, x);
1946 }
1947 else {
1948 o = PySequence_GetItem(source, x);
1949 if (o == NULL) {
1950 goto error1;
1951 }
1952 }
7bf85405 1953
e0672e2f
RD
1954 // Convert o to wxPoint.
1955 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
1956 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
1957 o1 = PySequence_Fast_GET_ITEM(o, 0);
1958 o2 = PySequence_Fast_GET_ITEM(o, 1);
1959 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1960 goto error2;
1961 }
7bf85405 1962 }
d559219f
RD
1963 else if (PyInstance_Check(o)) {
1964 wxPoint* pt;
e0672e2f
RD
1965 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
1966 goto error2;
d559219f
RD
1967 }
1968 temp[x] = *pt;
1969 }
e0672e2f
RD
1970 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
1971 o1 = PySequence_GetItem(o, 0);
1972 o2 = PySequence_GetItem(o, 1);
1973 if (!wxPointFromObjects(o1, o2, &temp[x])) {
1974 goto error3;
1975 }
1976 Py_DECREF(o1);
1977 Py_DECREF(o2);
1978 }
7bf85405 1979 else {
e0672e2f 1980 goto error2;
7bf85405 1981 }
e0672e2f
RD
1982 // Clean up.
1983 if (!isFast)
1984 Py_DECREF(o);
7bf85405
RD
1985 }
1986 return temp;
e0672e2f
RD
1987
1988error3:
1989 Py_DECREF(o1);
1990 Py_DECREF(o2);
1991error2:
1992 if (!isFast)
1993 Py_DECREF(o);
1994error1:
1e4a197e 1995 delete [] temp;
e0672e2f
RD
1996error0:
1997 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
1998 return NULL;
7bf85405 1999}
e0672e2f
RD
2000// end of patch
2001//------------------------------
7bf85405
RD
2002
2003
2f90df85 2004wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
7bf85405
RD
2005 if (!PyList_Check(source)) {
2006 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2007 return NULL;
2008 }
2009 int count = PyList_Size(source);
2010 wxBitmap** temp = new wxBitmap*[count];
2011 if (! temp) {
2012 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2013 return NULL;
2014 }
2015 for (int x=0; x<count; x++) {
2016 PyObject* o = PyList_GetItem(source, x);
e166644c 2017 if (PyInstance_Check(o)) {
7bf85405 2018 wxBitmap* pt;
e166644c 2019 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
7bf85405
RD
2020 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
2021 return NULL;
2022 }
2023 temp[x] = pt;
2024 }
2025 else {
2026 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
2027 return NULL;
2028 }
2029 }
2030 return temp;
2031}
2032
2033
2034
2f90df85 2035wxString* wxString_LIST_helper(PyObject* source) {
7bf85405
RD
2036 if (!PyList_Check(source)) {
2037 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2038 return NULL;
2039 }
2040 int count = PyList_Size(source);
2041 wxString* temp = new wxString[count];
2042 if (! temp) {
2043 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2044 return NULL;
2045 }
2046 for (int x=0; x<count; x++) {
2047 PyObject* o = PyList_GetItem(source, x);
ecc08ead
RD
2048#if PYTHON_API_VERSION >= 1009
2049 if (! PyString_Check(o) && ! PyUnicode_Check(o)) {
2050 PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects.");
2051 return NULL;
2052 }
ecc08ead 2053#else
7bf85405
RD
2054 if (! PyString_Check(o)) {
2055 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
2056 return NULL;
2057 }
ecc08ead 2058#endif
a541c325
RD
2059
2060 wxString* pStr = wxString_in_helper(o);
2061 temp[x] = *pStr;
2062 delete pStr;
7bf85405
RD
2063 }
2064 return temp;
2065}
2066
2067
2f90df85 2068wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
7bf85405
RD
2069 if (!PyList_Check(source)) {
2070 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2071 return NULL;
2072 }
2073 int count = PyList_Size(source);
2074 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
2075 if (! temp) {
2076 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2077 return NULL;
2078 }
2079 for (int x=0; x<count; x++) {
2080 PyObject* o = PyList_GetItem(source, x);
e166644c 2081 if (PyInstance_Check(o)) {
7bf85405 2082 wxAcceleratorEntry* ae;
e166644c 2083 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
7bf85405
RD
2084 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
2085 return NULL;
2086 }
2087 temp[x] = *ae;
2088 }
2089 else if (PyTuple_Check(o)) {
2090 PyObject* o1 = PyTuple_GetItem(o, 0);
2091 PyObject* o2 = PyTuple_GetItem(o, 1);
2092 PyObject* o3 = PyTuple_GetItem(o, 2);
0adbc166 2093 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
7bf85405
RD
2094 }
2095 else {
2096 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
2097 return NULL;
2098 }
2099 }
2100 return temp;
2101}
2102
bb0054cd 2103
9d37f964
RD
2104wxPen** wxPen_LIST_helper(PyObject* source) {
2105 if (!PyList_Check(source)) {
2106 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2107 return NULL;
2108 }
2109 int count = PyList_Size(source);
2110 wxPen** temp = new wxPen*[count];
2111 if (!temp) {
2112 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2113 return NULL;
2114 }
2115 for (int x=0; x<count; x++) {
2116 PyObject* o = PyList_GetItem(source, x);
2117 if (PyInstance_Check(o)) {
2118 wxPen* pt;
2119 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxPen_p")) {
2120 delete temp;
2121 PyErr_SetString(PyExc_TypeError,"Expected _wxPen_p.");
2122 return NULL;
2123 }
2124 temp[x] = pt;
2125 }
2126 else {
2127 delete temp;
2128 PyErr_SetString(PyExc_TypeError, "Expected a list of wxPens.");
2129 return NULL;
2130 }
2131 }
2132 return temp;
2133}
2134
2135
1e4a197e 2136bool wxPy2int_seq_helper(PyObject* source, int* i1, int* i2) {
9d37f964
RD
2137 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2138 PyObject *o1, *o2;
2139
2140 if (!PySequence_Check(source) || PySequence_Length(source) != 2)
2141 return FALSE;
2142
2143 if (isFast) {
2144 o1 = PySequence_Fast_GET_ITEM(source, 0);
2145 o2 = PySequence_Fast_GET_ITEM(source, 1);
2146 }
2147 else {
2148 o1 = PySequence_GetItem(source, 0);
2149 o2 = PySequence_GetItem(source, 1);
2150 }
2151
2152 *i1 = PyInt_AsLong(o1);
2153 *i2 = PyInt_AsLong(o2);
2154
2155 if (! isFast) {
2156 Py_DECREF(o1);
2157 Py_DECREF(o2);
2158 }
2159 return TRUE;
2160}
2161
2162
1e4a197e 2163bool wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) {
9d37f964
RD
2164 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2165 PyObject *o1, *o2, *o3, *o4;
2166
2167 if (!PySequence_Check(source) || PySequence_Length(source) != 4)
2168 return FALSE;
2169
2170 if (isFast) {
2171 o1 = PySequence_Fast_GET_ITEM(source, 0);
2172 o2 = PySequence_Fast_GET_ITEM(source, 1);
2173 o3 = PySequence_Fast_GET_ITEM(source, 2);
2174 o4 = PySequence_Fast_GET_ITEM(source, 3);
2175 }
2176 else {
2177 o1 = PySequence_GetItem(source, 0);
2178 o2 = PySequence_GetItem(source, 1);
2179 o3 = PySequence_GetItem(source, 2);
2180 o4 = PySequence_GetItem(source, 3);
2181 }
2182
2183 *i1 = PyInt_AsLong(o1);
2184 *i2 = PyInt_AsLong(o2);
2185 *i3 = PyInt_AsLong(o3);
2186 *i4 = PyInt_AsLong(o4);
2187
2188 if (! isFast) {
2189 Py_DECREF(o1);
2190 Py_DECREF(o2);
2191 Py_DECREF(o3);
2192 Py_DECREF(o4);
2193 }
2194 return TRUE;
2195}
2196
bb0054cd
RD
2197
2198//----------------------------------------------------------------------
bb0054cd 2199
2f90df85
RD
2200bool wxSize_helper(PyObject* source, wxSize** obj) {
2201
2202 // If source is an object instance then it may already be the right type
2203 if (PyInstance_Check(source)) {
2204 wxSize* ptr;
2205 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
2206 goto error;
2207 *obj = ptr;
2208 return TRUE;
2209 }
2210 // otherwise a 2-tuple of integers is expected
2211 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
2212 PyObject* o1 = PySequence_GetItem(source, 0);
2213 PyObject* o2 = PySequence_GetItem(source, 1);
db0ff83e
RD
2214 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2215 Py_DECREF(o1);
2216 Py_DECREF(o2);
2217 goto error;
2218 }
2f90df85 2219 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
db0ff83e
RD
2220 Py_DECREF(o1);
2221 Py_DECREF(o2);
2f90df85
RD
2222 return TRUE;
2223 }
2224
2225 error:
2226 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
2227 return FALSE;
2228}
2229
1e4a197e 2230
2f90df85
RD
2231bool wxPoint_helper(PyObject* source, wxPoint** obj) {
2232
2233 // If source is an object instance then it may already be the right type
2234 if (PyInstance_Check(source)) {
2235 wxPoint* ptr;
2236 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
2237 goto error;
2238 *obj = ptr;
2239 return TRUE;
2240 }
e0672e2f
RD
2241 // otherwise a length-2 sequence of integers is expected
2242 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
2f90df85
RD
2243 PyObject* o1 = PySequence_GetItem(source, 0);
2244 PyObject* o2 = PySequence_GetItem(source, 1);
db0ff83e
RD
2245 // This should really check for integers, not numbers -- but that would break code.
2246 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2247 Py_DECREF(o1);
2248 Py_DECREF(o2);
2249 goto error;
2250 }
2251 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
2252 Py_DECREF(o1);
2253 Py_DECREF(o2);
2f90df85
RD
2254 return TRUE;
2255 }
2f90df85
RD
2256 error:
2257 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
2258 return FALSE;
2259}
2260
2261
2262
2263bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
2264
2265 // If source is an object instance then it may already be the right type
2266 if (PyInstance_Check(source)) {
2267 wxRealPoint* ptr;
2268 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
2269 goto error;
2270 *obj = ptr;
2271 return TRUE;
2272 }
2273 // otherwise a 2-tuple of floats is expected
2274 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
2275 PyObject* o1 = PySequence_GetItem(source, 0);
2276 PyObject* o2 = PySequence_GetItem(source, 1);
db0ff83e
RD
2277 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2278 Py_DECREF(o1);
2279 Py_DECREF(o2);
2280 goto error;
2281 }
2f90df85 2282 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
db0ff83e
RD
2283 Py_DECREF(o1);
2284 Py_DECREF(o2);
2f90df85
RD
2285 return TRUE;
2286 }
2287
2288 error:
2289 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
2290 return FALSE;
2291}
2292
2293
2294
2295
2296bool wxRect_helper(PyObject* source, wxRect** obj) {
2297
2298 // If source is an object instance then it may already be the right type
2299 if (PyInstance_Check(source)) {
2300 wxRect* ptr;
2301 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
2302 goto error;
2303 *obj = ptr;
2304 return TRUE;
2305 }
2306 // otherwise a 4-tuple of integers is expected
2307 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
2308 PyObject* o1 = PySequence_GetItem(source, 0);
2309 PyObject* o2 = PySequence_GetItem(source, 1);
2310 PyObject* o3 = PySequence_GetItem(source, 2);
2311 PyObject* o4 = PySequence_GetItem(source, 3);
db0ff83e
RD
2312 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) ||
2313 !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
2314 Py_DECREF(o1);
2315 Py_DECREF(o2);
2316 Py_DECREF(o3);
2317 Py_DECREF(o4);
2318 goto error;
2319 }
2f90df85 2320 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
db0ff83e
RD
2321 PyInt_AsLong(o3), PyInt_AsLong(o4));
2322 Py_DECREF(o1);
2323 Py_DECREF(o2);
2324 Py_DECREF(o3);
2325 Py_DECREF(o4);
2f90df85
RD
2326 return TRUE;
2327 }
2328
2329 error:
2330 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
2331 return FALSE;
2332}
2333
2334
2335
f6bcfd97
BP
2336bool wxColour_helper(PyObject* source, wxColour** obj) {
2337
2338 // If source is an object instance then it may already be the right type
2339 if (PyInstance_Check(source)) {
2340 wxColour* ptr;
2341 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
2342 goto error;
2343 *obj = ptr;
2344 return TRUE;
2345 }
1e4a197e
RD
2346 // otherwise check for a string
2347 else if (PyString_Check(source) || PyUnicode_Check(source)) {
2348 wxString spec = Py2wxString(source);
a541c325
RD
2349 if (spec.GetChar(0) == '#' && spec.Length() == 7) { // It's #RRGGBB
2350 long red, green, blue;
2351 red = green = blue = 0;
a541c325
RD
2352 spec.Mid(1,2).ToLong(&red, 16);
2353 spec.Mid(3,2).ToLong(&green, 16);
2354 spec.Mid(5,2).ToLong(&blue, 16);
2355
f6bcfd97
BP
2356 **obj = wxColour(red, green, blue);
2357 return TRUE;
2358 }
2359 else { // it's a colour name
2360 **obj = wxColour(spec);
2361 return TRUE;
2362 }
2363 }
1e4a197e
RD
2364 // last chance: 3-tuple of integers is expected
2365 else if (PySequence_Check(source) && PyObject_Length(source) == 3) {
2366 PyObject* o1 = PySequence_GetItem(source, 0);
2367 PyObject* o2 = PySequence_GetItem(source, 1);
2368 PyObject* o3 = PySequence_GetItem(source, 2);
2369 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3)) {
2370 Py_DECREF(o1);
2371 Py_DECREF(o2);
2372 Py_DECREF(o3);
2373 goto error;
2374 }
2375 **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
2376 Py_DECREF(o1);
2377 Py_DECREF(o2);
2378 Py_DECREF(o3);
2379 return TRUE;
2380 }
f6bcfd97
BP
2381
2382 error:
a541c325 2383 PyErr_SetString(PyExc_TypeError,
1e4a197e
RD
2384 "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
2385 return FALSE;
2386}
2387
2388
2389
2390bool wxPoint2DDouble_helper(PyObject* source, wxPoint2DDouble** obj) {
2391 // If source is an object instance then it may already be the right type
2392 if (PyInstance_Check(source)) {
2393 wxPoint2DDouble* ptr;
2394 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint2DDouble_p"))
2395 goto error;
2396 *obj = ptr;
2397 return TRUE;
2398 }
2399 // otherwise a length-2 sequence of floats is expected
2400 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
2401 PyObject* o1 = PySequence_GetItem(source, 0);
2402 PyObject* o2 = PySequence_GetItem(source, 1);
2403 // This should really check for integers, not numbers -- but that would break code.
2404 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2405 Py_DECREF(o1);
2406 Py_DECREF(o2);
2407 goto error;
2408 }
2409 **obj = wxPoint2DDouble(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
2410 Py_DECREF(o1);
2411 Py_DECREF(o2);
2412 return TRUE;
2413 }
2414 error:
2415 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxPoint2DDouble object.");
f6bcfd97
BP
2416 return FALSE;
2417}
2418
2419
1e4a197e 2420
bb0054cd 2421//----------------------------------------------------------------------
b37c7e1d
RD
2422
2423PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
2424
2425 PyObject* list = PyList_New(0);
2426 for (size_t i=0; i < arr.GetCount(); i++) {
c8bc7bb8 2427#if wxUSE_UNICODE
1e4a197e 2428 PyObject* str = PyUnicode_FromWideChar(arr[i].c_str(), arr[i].Len());
c8bc7bb8
RD
2429#else
2430 PyObject* str = PyString_FromStringAndSize(arr[i].c_str(), arr[i].Len());
2431#endif
b37c7e1d 2432 PyList_Append(list, str);
8af26133 2433 Py_DECREF(str);
b37c7e1d
RD
2434 }
2435 return list;
2436}
2437
2438
293a0a86
RD
2439PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
2440
2441 PyObject* list = PyList_New(0);
2442 for (size_t i=0; i < arr.GetCount(); i++) {
2443 PyObject* number = PyInt_FromLong(arr[i]);
2444 PyList_Append(list, number);
2445 Py_DECREF(number);
2446 }
2447 return list;
2448}
2449
2450
bb0054cd 2451//----------------------------------------------------------------------
7bf85405 2452//----------------------------------------------------------------------
7bf85405 2453
7bf85405 2454
7bf85405 2455
de20db99 2456