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