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