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