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