]> git.saurik.com Git - wxWidgets.git/blob - wxPython/src/helpers.cpp
fixed wxVsnprintf() to write as much as it can if the output buffer is too short
[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: 1-July-1997
8 // RCS-ID: $Id$
9 // Copyright: (c) 1998 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
12
13
14 #undef DEBUG
15 #include <Python.h>
16 #include "wx/wxPython/wxPython_int.h"
17 #include "wx/wxPython/pyistream.h"
18 #include "wx/wxPython/swigver.h"
19 #include "wx/wxPython/twoitem.h"
20
21 #ifdef __WXMSW__
22 #include <wx/msw/private.h>
23 #include <wx/msw/winundef.h>
24 #include <wx/msw/msvcrt.h>
25 #endif
26
27 #ifdef __WXGTK__
28 #include <gdk/gdk.h>
29 #include <gdk/gdkx.h>
30 #include <gtk/gtk.h>
31 #include <gdk/gdkprivate.h>
32 #ifdef __WXGTK20__
33 #include <wx/gtk/win_gtk.h>
34 #else
35 #include <wx/gtk1/win_gtk.h>
36 #endif
37 #define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \
38 GDK_WINDOW_XWINDOW(GTK_PIZZA((wxwin)->m_wxwindow)->bin_window) : \
39 GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
40 #include <locale.h>
41 #endif
42
43 #ifdef __WXX11__
44 #include "wx/x11/privx.h"
45 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
46 #endif
47
48 #ifdef __WXMAC__
49 #include <wx/mac/private.h>
50 #endif
51
52 #include <wx/clipbrd.h>
53 #include <wx/mimetype.h>
54 #include <wx/image.h>
55
56 //----------------------------------------------------------------------
57
58 #if PYTHON_API_VERSION < 1009 && wxUSE_UNICODE
59 #error Python must support Unicode to use wxWindows Unicode
60 #endif
61
62 //----------------------------------------------------------------------
63
64 wxPyApp* wxPythonApp = NULL; // Global instance of application object
65 bool wxPyDoCleanup = false;
66 bool wxPyDoingCleanup = false;
67
68
69 #ifdef WXP_WITH_THREAD
70 #if !wxPyUSE_GIL_STATE
71 struct wxPyThreadState {
72 unsigned long tid;
73 PyThreadState* tstate;
74
75 wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL)
76 : tid(_tid), tstate(_tstate) {}
77 };
78
79 #include <wx/dynarray.h>
80 WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray);
81 #include <wx/arrimpl.cpp>
82 WX_DEFINE_OBJARRAY(wxPyThreadStateArray);
83
84 wxPyThreadStateArray* wxPyTStates = NULL;
85 wxMutex* wxPyTMutex = NULL;
86
87 #endif
88 #endif
89
90
91 #define DEFAULTENCODING_SIZE 64
92 static char wxPyDefaultEncoding[DEFAULTENCODING_SIZE] = "ascii";
93
94 static PyObject* wxPython_dict = NULL;
95 static PyObject* wxPyAssertionError = NULL;
96 static PyObject* wxPyNoAppError = NULL;
97
98 PyObject* wxPyPtrTypeMap = NULL;
99
100
101 #ifdef __WXMSW__ // If building for win32...
102 //----------------------------------------------------------------------
103 // This gets run when the DLL is loaded. We just need to save a handle.
104 //----------------------------------------------------------------------
105
106 extern "C"
107 BOOL WINAPI DllMain(
108 HINSTANCE hinstDLL, // handle to DLL module
109 DWORD fdwReason, // reason for calling function
110 LPVOID lpvReserved // reserved
111 )
112 {
113 // If wxPython is embedded in another wxWidgets app then
114 // the instance has already been set.
115 if (! wxGetInstance())
116 wxSetInstance(hinstDLL);
117 return true;
118 }
119 #endif
120
121 //----------------------------------------------------------------------
122 // Classes for implementing the wxp main application shell.
123 //----------------------------------------------------------------------
124
125 IMPLEMENT_ABSTRACT_CLASS(wxPyApp, wxApp);
126
127
128 wxPyApp::wxPyApp() {
129 m_assertMode = wxPYAPP_ASSERT_EXCEPTION;
130 m_startupComplete = false;
131 }
132
133
134 wxPyApp::~wxPyApp() {
135 wxPythonApp = NULL;
136 wxApp::SetInstance(NULL);
137 }
138
139
140 // This one isn't acutally called... We fake it with _BootstrapApp
141 bool wxPyApp::OnInit() {
142 return false;
143 }
144
145
146 int wxPyApp::MainLoop() {
147 int retval = 0;
148
149 DeletePendingObjects();
150 bool initialized = wxTopLevelWindows.GetCount() != 0;
151 if (initialized) {
152 if ( m_exitOnFrameDelete == Later ) {
153 m_exitOnFrameDelete = Yes;
154 }
155
156 retval = wxApp::MainLoop();
157 OnExit();
158 }
159 return retval;
160 }
161
162
163 bool wxPyApp::OnInitGui() {
164 bool rval=true;
165 wxApp::OnInitGui(); // in this case always call the base class version
166 wxPyBlock_t blocked = wxPyBeginBlockThreads();
167 if (wxPyCBH_findCallback(m_myInst, "OnInitGui"))
168 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
169 wxPyEndBlockThreads(blocked);
170 return rval;
171 }
172
173
174 int wxPyApp::OnExit() {
175 int rval=0;
176 wxPyBlock_t blocked = wxPyBeginBlockThreads();
177 if (wxPyCBH_findCallback(m_myInst, "OnExit"))
178 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
179 wxPyEndBlockThreads(blocked);
180 wxApp::OnExit(); // in this case always call the base class version
181 return rval;
182 }
183
184
185
186 void wxPyApp::ExitMainLoop() {
187 bool found;
188 wxPyBlock_t blocked = wxPyBeginBlockThreads();
189 if ((found = wxPyCBH_findCallback(m_myInst, "ExitMainLoop")))
190 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
191 wxPyEndBlockThreads(blocked);
192 if (! found)
193 wxApp::ExitMainLoop();
194 }
195
196
197 #ifdef __WXDEBUG__
198 void wxPyApp::OnAssertFailure(const wxChar *file,
199 int line,
200 const wxChar *func,
201 const wxChar *cond,
202 const wxChar *msg)
203 {
204 // if we're not fully initialized then just log the error
205 if (! m_startupComplete) {
206 wxString buf;
207 buf.Alloc(4096);
208 buf.Printf(wxT("%s(%d): assert \"%s\" failed"),
209 file, line, cond);
210 if ( func && *func )
211 buf << wxT(" in ") << func << wxT("()");
212 if (msg != NULL)
213 buf << wxT(": ") << msg;
214
215 wxLogDebug(buf);
216 return;
217 }
218
219 // If the OnAssert is overloaded in the Python class then call it...
220 bool found;
221 wxPyBlock_t blocked = wxPyBeginBlockThreads();
222 if ((found = wxPyCBH_findCallback(m_myInst, "OnAssert"))) {
223 PyObject* fso = wx2PyString(file);
224 PyObject* cso = wx2PyString(file);
225 PyObject* mso;
226 if (msg != NULL)
227 mso = wx2PyString(file);
228 else {
229 mso = Py_None; Py_INCREF(Py_None);
230 }
231 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(OiOO)", fso, line, cso, mso));
232 Py_DECREF(fso);
233 Py_DECREF(cso);
234 Py_DECREF(mso);
235 }
236 wxPyEndBlockThreads(blocked);
237
238 // ...otherwise do our own thing with it
239 if (! found) {
240 // ignore it?
241 if (m_assertMode & wxPYAPP_ASSERT_SUPPRESS)
242 return;
243
244 // turn it into a Python exception?
245 if (m_assertMode & wxPYAPP_ASSERT_EXCEPTION) {
246 wxString buf;
247 buf.Alloc(4096);
248 buf.Printf(wxT("C++ assertion \"%s\" failed at %s(%d)"), cond, file, line);
249 if ( func && *func )
250 buf << wxT(" in ") << func << wxT("()");
251 if (msg != NULL)
252 buf << wxT(": ") << msg;
253
254
255 // set the exception
256 wxPyBlock_t blocked = wxPyBeginBlockThreads();
257 PyObject* s = wx2PyString(buf);
258 PyErr_SetObject(wxPyAssertionError, s);
259 Py_DECREF(s);
260 wxPyEndBlockThreads(blocked);
261
262 // Now when control returns to whatever API wrapper was called from
263 // Python it should detect that an exception is set and will return
264 // NULL, signalling the exception to Python.
265 }
266
267 // Send it to the normal log destination, but only if
268 // not _DIALOG because it will call this too
269 if ( (m_assertMode & wxPYAPP_ASSERT_LOG) && !(m_assertMode & wxPYAPP_ASSERT_DIALOG)) {
270 wxString buf;
271 buf.Alloc(4096);
272 buf.Printf(wxT("%s(%d): assert \"%s\" failed"),
273 file, line, cond);
274 if ( func && *func )
275 buf << wxT(" in ") << func << wxT("()");
276 if (msg != NULL)
277 buf << wxT(": ") << msg;
278 wxLogDebug(buf);
279 }
280
281 // do the normal wx assert dialog?
282 if (m_assertMode & wxPYAPP_ASSERT_DIALOG)
283 wxApp::OnAssertFailure(file, line, func, cond, msg);
284 }
285 }
286 #endif
287
288 // For catching Apple Events
289 void wxPyApp::MacOpenFile(const wxString &fileName)
290 {
291 wxPyBlock_t blocked = wxPyBeginBlockThreads();
292 if (wxPyCBH_findCallback(m_myInst, "MacOpenFile")) {
293 PyObject* s = wx2PyString(fileName);
294 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s));
295 Py_DECREF(s);
296 }
297 wxPyEndBlockThreads(blocked);
298 }
299
300 void wxPyApp::MacOpenURL(const wxString &url)
301 {
302 wxPyBlock_t blocked = wxPyBeginBlockThreads();
303 if (wxPyCBH_findCallback(m_myInst, "MacOpenURL")) {
304 PyObject* s = wx2PyString(url);
305 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s));
306 Py_DECREF(s);
307 }
308 wxPyEndBlockThreads(blocked);
309 }
310
311 void wxPyApp::MacPrintFile(const wxString &fileName)
312 {
313 wxPyBlock_t blocked = wxPyBeginBlockThreads();
314 if (wxPyCBH_findCallback(m_myInst, "MacPrintFile")) {
315 PyObject* s = wx2PyString(fileName);
316 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s));
317 Py_DECREF(s);
318 }
319 wxPyEndBlockThreads(blocked);
320 }
321
322 void wxPyApp::MacNewFile()
323 {
324 wxPyBlock_t blocked = wxPyBeginBlockThreads();
325 if (wxPyCBH_findCallback(m_myInst, "MacNewFile"))
326 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
327 wxPyEndBlockThreads(blocked);
328 }
329
330 void wxPyApp::MacReopenApp()
331 {
332 wxPyBlock_t blocked = wxPyBeginBlockThreads();
333 if (wxPyCBH_findCallback(m_myInst, "MacReopenApp"))
334 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()"));
335 wxPyEndBlockThreads(blocked);
336 }
337
338
339 /*static*/
340 bool wxPyApp::GetMacSupportPCMenuShortcuts() {
341 return 0;
342 }
343
344 /*static*/
345 long wxPyApp::GetMacAboutMenuItemId() {
346 #ifdef __WXMAC__
347 return s_macAboutMenuItemId;
348 #else
349 return 0;
350 #endif
351 }
352
353 /*static*/
354 long wxPyApp::GetMacPreferencesMenuItemId() {
355 #ifdef __WXMAC__
356 return s_macPreferencesMenuItemId;
357 #else
358 return 0;
359 #endif
360 }
361
362 /*static*/
363 long wxPyApp::GetMacExitMenuItemId() {
364 #ifdef __WXMAC__
365 return s_macExitMenuItemId;
366 #else
367 return 0;
368 #endif
369 }
370
371 /*static*/
372 wxString wxPyApp::GetMacHelpMenuTitleName() {
373 #ifdef __WXMAC__
374 return s_macHelpMenuTitleName;
375 #else
376 return wxEmptyString;
377 #endif
378 }
379
380 /*static*/
381 void wxPyApp::SetMacSupportPCMenuShortcuts(bool) {
382 }
383
384 /*static*/
385 void wxPyApp::SetMacAboutMenuItemId(long val) {
386 #ifdef __WXMAC__
387 s_macAboutMenuItemId = val;
388 #endif
389 }
390
391 /*static*/
392 void wxPyApp::SetMacPreferencesMenuItemId(long val) {
393 #ifdef __WXMAC__
394 s_macPreferencesMenuItemId = val;
395 #endif
396 }
397
398 /*static*/
399 void wxPyApp::SetMacExitMenuItemId(long val) {
400 #ifdef __WXMAC__
401 s_macExitMenuItemId = val;
402 #endif
403 }
404
405 /*static*/
406 void wxPyApp::SetMacHelpMenuTitleName(const wxString& val) {
407 #ifdef __WXMAC__
408 s_macHelpMenuTitleName = val;
409 #endif
410 }
411
412
413 // This finishes the initialization of wxWindows and then calls the OnInit
414 // that should be present in the derived (Python) class.
415 void wxPyApp::_BootstrapApp()
416 {
417 static bool haveInitialized = false;
418 bool result;
419 wxPyBlock_t blocked;
420 PyObject* retval = NULL;
421 PyObject* pyint = NULL;
422
423
424 // Only initialize wxWidgets once
425 if (! haveInitialized) {
426
427 // Get any command-line args passed to this program from the sys module
428 int argc = 0;
429 char** argv = NULL;
430 blocked = wxPyBeginBlockThreads();
431
432 PyObject* sysargv = PySys_GetObject("argv");
433 PyObject* executable = PySys_GetObject("executable");
434
435 if (sysargv != NULL && executable != NULL) {
436 argc = PyList_Size(sysargv) + 1;
437 argv = new char*[argc+1];
438 argv[0] = strdup(PyString_AsString(executable));
439 int x;
440 for(x=1; x<argc; x++) {
441 PyObject *pyArg = PyList_GetItem(sysargv, x-1);
442 argv[x] = strdup(PyString_AsString(pyArg));
443 }
444 argv[argc] = NULL;
445 }
446 wxPyEndBlockThreads(blocked);
447
448 // Initialize wxWidgets
449 result = wxEntryStart(argc, argv);
450 // wxApp takes ownership of the argv array, don't delete it here
451
452 blocked = wxPyBeginBlockThreads();
453 if (! result) {
454 PyErr_SetString(PyExc_SystemError,
455 "wxEntryStart failed, unable to initialize wxWidgets!"
456 #ifdef __WXGTK__
457 " (Is DISPLAY set properly?)"
458 #endif
459 );
460 goto error;
461 }
462
463 // On wxGTK the locale will be changed to match the system settings,
464 // but Python before 2.4 needs to have LC_NUMERIC set to "C" in order
465 // for the floating point conversions and such to work right.
466 #if defined(__WXGTK__) && PY_VERSION_HEX < 0x02040000
467 setlocale(LC_NUMERIC, "C");
468 #endif
469
470 // wxSystemOptions::SetOption(wxT("mac.textcontrol-use-mlte"), 1);
471
472 wxPyEndBlockThreads(blocked);
473 haveInitialized = true;
474 }
475 else {
476 this->argc = 0;
477 this->argv = NULL;
478 }
479
480
481 // It's now ok to generate exceptions for assertion errors.
482 wxPythonApp->SetStartupComplete(true);
483
484
485 // Call the Python wxApp's OnPreInit and OnInit functions
486 blocked = wxPyBeginBlockThreads();
487 if (wxPyCBH_findCallback(m_myInst, "OnPreInit")) {
488 PyObject* method = m_myInst.GetLastFound();
489 PyObject* argTuple = PyTuple_New(0);
490 retval = PyEval_CallObject(method, argTuple);
491 m_myInst.clearRecursionGuard(method);
492 Py_DECREF(argTuple);
493 Py_DECREF(method);
494 if (retval == NULL)
495 goto error;
496 }
497 if (wxPyCBH_findCallback(m_myInst, "OnInit")) {
498
499 PyObject* method = m_myInst.GetLastFound();
500 PyObject* argTuple = PyTuple_New(0);
501 retval = PyEval_CallObject(method, argTuple);
502 m_myInst.clearRecursionGuard(method);
503 Py_DECREF(argTuple);
504 Py_DECREF(method);
505 if (retval == NULL)
506 // Don't PyErr_Print here, let the exception in this case go back
507 // up to the wx.PyApp.__init__ scope.
508 goto error;
509
510 pyint = PyNumber_Int(retval);
511 if (! pyint) {
512 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
513 goto error;
514 }
515 result = PyInt_AS_LONG(pyint);
516 }
517 else {
518 // Is it okay if there is no OnInit? Probably so...
519 result = true;
520 }
521
522 if (! result) {
523 PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
524 }
525
526 error:
527 Py_XDECREF(retval);
528 Py_XDECREF(pyint);
529
530 wxPyEndBlockThreads(blocked);
531 };
532
533 //---------------------------------------------------------------------
534 //----------------------------------------------------------------------
535
536
537 #if 0
538 static char* wxPyCopyCString(const wxChar* src)
539 {
540 wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(src);
541 size_t len = strlen(buff);
542 char* dest = new char[len+1];
543 strcpy(dest, buff);
544 return dest;
545 }
546
547 #if wxUSE_UNICODE
548 static char* wxPyCopyCString(const char* src) // we need a char version too
549 {
550 size_t len = strlen(src);
551 char* dest = new char[len+1];
552 strcpy(dest, src);
553 return dest;
554 }
555 #endif
556
557 static wxChar* wxPyCopyWString(const char *src)
558 {
559 //wxMB2WXbuf buff = wxConvCurrent->cMB2WX(src);
560 wxString str(src, *wxConvCurrent);
561 return copystring(str);
562 }
563
564 #if wxUSE_UNICODE
565 static wxChar* wxPyCopyWString(const wxChar *src)
566 {
567 return copystring(src);
568 }
569 #endif
570 #endif
571
572
573 inline const char* dropwx(const char* name) {
574 if (name[0] == 'w' && name[1] == 'x')
575 return name+2;
576 else
577 return name;
578 }
579
580 //----------------------------------------------------------------------
581
582 // This function is called when the wx._core_ module is imported to do some
583 // initial setup. (Before there is a wxApp object.) The rest happens in
584 // wxPyApp::_BootstrapApp
585 void __wxPyPreStart(PyObject* moduleDict)
586 {
587
588 #ifdef __WXMSW__
589 // wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
590 // | _CRTDBG_CHECK_ALWAYS_DF
591 // | _CRTDBG_DELAY_FREE_MEM_DF
592 // );
593 #endif
594
595 #ifdef WXP_WITH_THREAD
596 #if wxPyUSE_GIL_STATE
597 PyEval_InitThreads();
598 #else
599 PyEval_InitThreads();
600 wxPyTStates = new wxPyThreadStateArray;
601 wxPyTMutex = new wxMutex;
602
603 // Save the current (main) thread state in our array
604 PyThreadState* tstate = wxPyBeginAllowThreads();
605 wxPyEndAllowThreads(tstate);
606 #endif
607 #endif
608
609 // Ensure that the build options in the DLL (or whatever) match this build
610 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython");
611
612 wxInitAllImageHandlers();
613 }
614
615
616
617 void __wxPyCleanup() {
618 wxPyDoingCleanup = true;
619 if (wxPyDoCleanup) {
620 wxPyDoCleanup = false;
621 wxEntryCleanup();
622 }
623 #ifdef WXP_WITH_THREAD
624 #if !wxPyUSE_GIL_STATE
625 delete wxPyTMutex;
626 wxPyTMutex = NULL;
627 wxPyTStates->Empty();
628 delete wxPyTStates;
629 wxPyTStates = NULL;
630 #endif
631 #endif
632 }
633
634
635 // Save a reference to the dictionary of the wx._core module, and inject
636 // a few more things into it.
637 PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args)
638 {
639
640 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
641 return NULL;
642
643 if (!PyDict_Check(wxPython_dict)) {
644 PyErr_SetString(PyExc_TypeError,
645 "_wxPySetDictionary must have dictionary object!");
646 return NULL;
647 }
648
649 if (! wxPyPtrTypeMap)
650 wxPyPtrTypeMap = PyDict_New();
651 PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap);
652
653 // Create an exception object to use for wxASSERTions
654 wxPyAssertionError = PyErr_NewException("wx._core.PyAssertionError",
655 PyExc_AssertionError, NULL);
656 PyDict_SetItemString(wxPython_dict, "PyAssertionError", wxPyAssertionError);
657
658 // Create an exception object to use when the app object hasn't been created yet
659 wxPyNoAppError = PyErr_NewException("wx._core.PyNoAppError",
660 PyExc_RuntimeError, NULL);
661 PyDict_SetItemString(wxPython_dict, "PyNoAppError", wxPyNoAppError);
662
663
664
665 #ifdef __WXMOTIF__
666 #define wxPlatform "__WXMOTIF__"
667 #define wxPlatName "wxMotif"
668 #endif
669 #ifdef __WXX11__
670 #define wxPlatform "__WXX11__"
671 #define wxPlatName "wxX11"
672 #endif
673 #ifdef __WXGTK__
674 #define wxPlatform "__WXGTK__"
675 #define wxPlatName "wxGTK"
676 #endif
677 #ifdef __WXMSW__
678 #define wxPlatform "__WXMSW__"
679 #define wxPlatName "wxMSW"
680 #endif
681 #ifdef __WXMAC__
682 #define wxPlatform "__WXMAC__"
683 #define wxPlatName "wxMac"
684 #endif
685
686 #ifdef __WXDEBUG__
687 int wxdebug = 1;
688 #else
689 int wxdebug = 0;
690 #endif
691
692 // These should be deprecated in favor of the PlatformInfo tuple built below...
693 PyDict_SetItemString(wxPython_dict, "Platform", PyString_FromString(wxPlatform));
694 PyDict_SetItemString(wxPython_dict, "USE_UNICODE", PyInt_FromLong(wxUSE_UNICODE));
695 PyDict_SetItemString(wxPython_dict, "__WXDEBUG__", PyInt_FromLong(wxdebug));
696
697 // Make a tuple of strings that gives more info about the platform.
698 PyObject* PlatInfo = PyList_New(0);
699 PyObject* obj;
700
701 #define _AddInfoString(st) \
702 obj = PyString_FromString(st); \
703 PyList_Append(PlatInfo, obj); \
704 Py_DECREF(obj)
705
706 _AddInfoString(wxPlatform);
707 _AddInfoString(wxPlatName);
708 #if wxUSE_UNICODE
709 _AddInfoString("unicode");
710 #else
711 _AddInfoString("ansi");
712 #endif
713 #ifdef __WXGTK__
714 #ifdef __WXGTK20__
715 _AddInfoString("gtk2");
716 #else
717 _AddInfoString("gtk1");
718 #endif
719 #endif
720 #ifdef __WXDEBUG__
721 _AddInfoString("wx-assertions-on");
722 #else
723 _AddInfoString("wx-assertions-off");
724 #endif
725 _AddInfoString(wxPy_SWIG_VERSION);
726 #ifdef __WXMAC__
727 #if wxMAC_USE_CORE_GRAPHICS
728 _AddInfoString("mac-cg");
729 #else
730 _AddInfoString("mac-qd");
731 #endif
732 #if wxMAC_USE_NATIVE_TOOLBAR
733 _AddInfoString("mac-native-tb");
734 #else
735 _AddInfoString("mac-no-native-tb");
736 #endif
737 #endif
738
739 #undef _AddInfoString
740
741 PyObject* PlatInfoTuple = PyList_AsTuple(PlatInfo);
742 Py_DECREF(PlatInfo);
743 PyDict_SetItemString(wxPython_dict, "PlatformInfo", PlatInfoTuple);
744
745 RETURN_NONE();
746 }
747
748
749
750 //---------------------------------------------------------------------------
751
752 // Check for existence of a wxApp, setting an exception if there isn't one.
753 // This doesn't need to aquire the GIL because it should only be called from
754 // an %exception before the lock is released.
755
756 bool wxPyCheckForApp() {
757 if (wxTheApp != NULL)
758 return true;
759 else {
760 PyErr_SetString(wxPyNoAppError, "The wx.App object must be created first!");
761 return false;
762 }
763 }
764
765 //---------------------------------------------------------------------------
766
767 void wxPyUserData_dtor(wxPyUserData* self) {
768 if (! wxPyDoingCleanup) {
769 wxPyBlock_t blocked = wxPyBeginBlockThreads();
770 Py_DECREF(self->m_obj);
771 self->m_obj = NULL;
772 wxPyEndBlockThreads(blocked);
773 }
774 }
775
776
777 void wxPyClientData_dtor(wxPyClientData* self) {
778 if (! wxPyDoingCleanup) { // Don't do it during cleanup as Python
779 // may have already garbage collected the object...
780 if (self->m_incRef) {
781 wxPyBlock_t blocked = wxPyBeginBlockThreads();
782 Py_DECREF(self->m_obj);
783 wxPyEndBlockThreads(blocked);
784 }
785 self->m_obj = NULL;
786 }
787 }
788
789
790
791 // This is called when an OOR controled object is being destroyed. Although
792 // the C++ object is going away there is no way to force the Python object
793 // (and all references to it) to die too. This causes problems (crashes) in
794 // wxPython when a python shadow object attempts to call a C++ method using
795 // the now bogus pointer... So to try and prevent this we'll do a little black
796 // magic and change the class of the python instance to a class that will
797 // raise an exception for any attempt to call methods with it. See
798 // _wxPyDeadObject in _core_ex.py for the implementation of this class.
799 void wxPyOORClientData_dtor(wxPyOORClientData* self) {
800
801 static PyObject* deadObjectClass = NULL;
802
803 wxPyBlock_t blocked = wxPyBeginBlockThreads();
804 if (deadObjectClass == NULL) {
805 deadObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyDeadObject");
806 // TODO: Can not wxASSERT here because inside a wxPyBeginBlock Threads,
807 // will lead to a deadlock when it tries to aquire the GIL again.
808 //wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!"));
809 Py_INCREF(deadObjectClass);
810 }
811
812
813 // Only if there is more than one reference to the object and we are
814 // holding the OOR reference:
815 if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 && self->m_incRef) {
816 // bool isInstance = wxPyInstance_Check(self->m_obj);
817 // TODO same here
818 //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));
819
820 // Call __del__, if there is one.
821 PyObject* func = PyObject_GetAttrString(self->m_obj, "__del__");
822 if (func) {
823 PyObject* rv = PyObject_CallMethod(self->m_obj, "__del__", NULL);
824 Py_XDECREF(rv);
825 Py_DECREF(func);
826 }
827 if (PyErr_Occurred())
828 PyErr_Clear(); // just ignore it for now
829
830
831 PyObject* dict = PyObject_GetAttrString(self->m_obj, "__dict__");
832 if (dict) {
833 // Clear the instance's dictionary
834 PyDict_Clear(dict);
835
836 // put the name of the old class into the instance, and then reset the
837 // class to be the dead class.
838 PyObject* klass = PyObject_GetAttrString(self->m_obj, "__class__");
839 PyObject* name = PyObject_GetAttrString(klass, "__name__");
840 PyDict_SetItemString(dict, "_name", name);
841 PyObject_SetAttrString(self->m_obj, "__class__", deadObjectClass);
842 //Py_INCREF(deadObjectClass);
843 Py_DECREF(klass);
844 Py_DECREF(name);
845 Py_DECREF(dict);
846 }
847 }
848
849 // m_obj is DECREF'd in the base class dtor...
850 wxPyEndBlockThreads(blocked);
851 }
852
853
854 //---------------------------------------------------------------------------
855 // Stuff used by OOR to find the right wxPython class type to return and to
856 // build it.
857
858
859 // The pointer type map is used when the "pointer" type name generated by SWIG
860 // is not the same as the shadow class name, for example wxPyTreeCtrl
861 // vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++,
862 // so we'll just make it a Python dictionary in the wx module's namespace.
863 // (See __wxSetDictionary)
864 void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
865 if (! wxPyPtrTypeMap)
866 wxPyPtrTypeMap = PyDict_New();
867 PyDict_SetItemString(wxPyPtrTypeMap,
868 (char*)commonName,
869 PyString_FromString((char*)ptrName));
870 }
871
872
873
874
875 PyObject* wxPyMake_wxObject(wxObject* source, bool setThisOwn, bool checkEvtHandler) {
876 PyObject* target = NULL;
877 bool isEvtHandler = false;
878 bool isSizer = false;
879
880 if (source) {
881 // If it's derived from wxEvtHandler then there may
882 // already be a pointer to a Python object that we can use
883 // in the OOR data.
884 if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) {
885 isEvtHandler = true;
886 wxEvtHandler* eh = (wxEvtHandler*)source;
887 wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject();
888 if (data) {
889 target = data->m_obj;
890 if (target)
891 Py_INCREF(target);
892 }
893 }
894
895 // Also check for wxSizer
896 if (!target && wxIsKindOf(source, wxSizer)) {
897 isSizer = true;
898 wxSizer* sz = (wxSizer*)source;
899 wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject();
900 if (data) {
901 target = data->m_obj;
902 if (target)
903 Py_INCREF(target);
904 }
905 }
906
907 if (! target) {
908 // Otherwise make it the old fashioned way by making a new shadow
909 // object and putting this pointer in it. Look up the class
910 // heirarchy until we find a class name that is located in the
911 // python module.
912 const wxClassInfo* info = source->GetClassInfo();
913 wxString name = info->GetClassName();
914 bool exists = wxPyCheckSwigType(name);
915 while (info && !exists) {
916 info = info->GetBaseClass1();
917 name = info->GetClassName();
918 exists = wxPyCheckSwigType(name);
919 }
920 if (info) {
921 target = wxPyConstructObject((void*)source, name, setThisOwn);
922 if (target && isEvtHandler)
923 ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
924 if (target && isSizer)
925 ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target));
926 } else {
927 wxString msg(wxT("wxPython class not found for "));
928 msg += source->GetClassInfo()->GetClassName();
929 PyErr_SetString(PyExc_NameError, msg.mbc_str());
930 target = NULL;
931 }
932 }
933 } else { // source was NULL so return None.
934 Py_INCREF(Py_None); target = Py_None;
935 }
936 return target;
937 }
938
939
940 PyObject* wxPyMake_wxSizer(wxSizer* source, bool setThisOwn) {
941
942 return wxPyMake_wxObject(source, setThisOwn);
943 }
944
945
946 //---------------------------------------------------------------------------
947
948
949 #ifdef WXP_WITH_THREAD
950 #if !wxPyUSE_GIL_STATE
951
952 inline
953 unsigned long wxPyGetCurrentThreadId() {
954 return wxThread::GetCurrentId();
955 }
956
957 static wxPyThreadState gs_shutdownTState;
958
959 static
960 wxPyThreadState* wxPyGetThreadState() {
961 if (wxPyTMutex == NULL) // Python is shutting down...
962 return &gs_shutdownTState;
963
964 unsigned long ctid = wxPyGetCurrentThreadId();
965 wxPyThreadState* tstate = NULL;
966
967 wxPyTMutex->Lock();
968 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
969 wxPyThreadState& info = wxPyTStates->Item(i);
970 if (info.tid == ctid) {
971 tstate = &info;
972 break;
973 }
974 }
975 wxPyTMutex->Unlock();
976 wxASSERT_MSG(tstate, wxT("PyThreadState should not be NULL!"));
977 return tstate;
978 }
979
980
981 static
982 void wxPySaveThreadState(PyThreadState* tstate) {
983 if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread...
984 gs_shutdownTState.tstate = tstate;
985 return;
986 }
987 unsigned long ctid = wxPyGetCurrentThreadId();
988 wxPyTMutex->Lock();
989 for(size_t i=0; i < wxPyTStates->GetCount(); i++) {
990 wxPyThreadState& info = wxPyTStates->Item(i);
991 if (info.tid == ctid) {
992 #if 0
993 if (info.tstate != tstate)
994 wxLogMessage("*** tstate mismatch!???");
995 #endif
996 info.tstate = tstate; // allow for transient tstates
997 // Normally it will never change, but apparently COM callbacks
998 // (i.e. ActiveX controls) will (incorrectly IMHO) use a transient
999 // tstate which will then be garbage the next time we try to use
1000 // it...
1001
1002 wxPyTMutex->Unlock();
1003 return;
1004 }
1005 }
1006 // not found, so add it...
1007 wxPyTStates->Add(new wxPyThreadState(ctid, tstate));
1008 wxPyTMutex->Unlock();
1009 }
1010
1011 #endif
1012 #endif
1013
1014
1015
1016 // Calls from Python to wxWindows code are wrapped in calls to these
1017 // functions:
1018
1019 PyThreadState* wxPyBeginAllowThreads() {
1020 #ifdef WXP_WITH_THREAD
1021 PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS;
1022 #if !wxPyUSE_GIL_STATE
1023 wxPySaveThreadState(saved);
1024 #endif
1025 return saved;
1026 #else
1027 return NULL;
1028 #endif
1029 }
1030
1031 void wxPyEndAllowThreads(PyThreadState* saved) {
1032 #ifdef WXP_WITH_THREAD
1033 PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS;
1034 #endif
1035 }
1036
1037
1038
1039 // Calls from wxWindows back to Python code, or even any PyObject
1040 // manipulations, PyDECREF's and etc. are wrapped in calls to these functions:
1041
1042 wxPyBlock_t wxPyBeginBlockThreads() {
1043 #ifdef WXP_WITH_THREAD
1044 if (! Py_IsInitialized()) {
1045 return (wxPyBlock_t)0;
1046 }
1047 #if wxPyUSE_GIL_STATE
1048 PyGILState_STATE state = PyGILState_Ensure();
1049 return state;
1050 #else
1051 PyThreadState *current = _PyThreadState_Current;
1052
1053 // Only block if there wasn't already a tstate, or if the current one is
1054 // not the one we are wanting to change to. This should prevent deadlock
1055 // if there are nested calls to wxPyBeginBlockThreads
1056 wxPyBlock_t blocked = false;
1057 wxPyThreadState* tstate = wxPyGetThreadState();
1058 if (current != tstate->tstate) {
1059 PyEval_RestoreThread(tstate->tstate);
1060 blocked = true;
1061 }
1062 return blocked;
1063 #endif
1064 #else
1065 return (wxPyBlock_t)0;
1066 #endif
1067 }
1068
1069
1070 void wxPyEndBlockThreads(wxPyBlock_t blocked) {
1071 #ifdef WXP_WITH_THREAD
1072 if (! Py_IsInitialized()) {
1073 return;
1074 }
1075 #if wxPyUSE_GIL_STATE
1076 PyGILState_Release(blocked);
1077 #else
1078 // Only unblock if we blocked in the last call to wxPyBeginBlockThreads.
1079 // The value of blocked passed in needs to be the same as that returned
1080 // from wxPyBeginBlockThreads at the same nesting level.
1081 if ( blocked ) {
1082 PyEval_SaveThread();
1083 }
1084 #endif
1085 #endif
1086 }
1087
1088
1089 //---------------------------------------------------------------------------
1090 // wxPyInputStream and wxPyCBInputStream methods
1091
1092
1093 static PyObject* wxPyGetMethod(PyObject* py, char* name)
1094 {
1095 if (!PyObject_HasAttrString(py, name))
1096 return NULL;
1097 PyObject* o = PyObject_GetAttrString(py, name);
1098 if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
1099 Py_DECREF(o);
1100 return NULL;
1101 }
1102 return o;
1103 }
1104
1105
1106
1107
1108 void wxPyInputStream::close() {
1109 /* do nothing for now */
1110 }
1111
1112 void wxPyInputStream::flush() {
1113 /* do nothing for now */
1114 }
1115
1116 bool wxPyInputStream::eof() {
1117 if (m_wxis)
1118 return m_wxis->Eof();
1119 else
1120 return true;
1121 }
1122
1123 wxPyInputStream::~wxPyInputStream() {
1124 if (m_wxis)
1125 delete m_wxis;
1126 }
1127
1128
1129
1130
1131 PyObject* wxPyInputStream::read(int size) {
1132 PyObject* obj = NULL;
1133 wxMemoryBuffer buf;
1134 const int BUFSIZE = 1024;
1135
1136 // check if we have a real wxInputStream to work with
1137 if (!m_wxis) {
1138 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1139 PyErr_SetString(PyExc_IOError, "no valid C-wxInputStream");
1140 wxPyEndBlockThreads(blocked);
1141 return NULL;
1142 }
1143
1144 if (size < 0) {
1145 // read while bytes are available on the stream
1146 while ( m_wxis->CanRead() ) {
1147 m_wxis->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE);
1148 buf.UngetAppendBuf(m_wxis->LastRead());
1149 }
1150
1151 } else { // Read only size number of characters
1152 m_wxis->Read(buf.GetWriteBuf(size), size);
1153 buf.UngetWriteBuf(m_wxis->LastRead());
1154 }
1155
1156 // error check
1157 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1158 wxStreamError err = m_wxis->GetLastError();
1159 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
1160 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
1161 }
1162 else {
1163 // We use only strings for the streams, not unicode
1164 obj = PyString_FromStringAndSize(buf, buf.GetDataLen());
1165 }
1166 wxPyEndBlockThreads(blocked);
1167 return obj;
1168 }
1169
1170
1171 PyObject* wxPyInputStream::readline(int size) {
1172 PyObject* obj = NULL;
1173 wxMemoryBuffer buf;
1174 int i;
1175 char ch;
1176
1177 // check if we have a real wxInputStream to work with
1178 if (!m_wxis) {
1179 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1180 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream");
1181 wxPyEndBlockThreads(blocked);
1182 return NULL;
1183 }
1184
1185 // read until \n or byte limit reached
1186 for (i=ch=0; (ch != '\n') && (m_wxis->CanRead()) && ((size < 0) || (i < size)); i++) {
1187 ch = m_wxis->GetC();
1188 buf.AppendByte(ch);
1189 }
1190
1191 // errorcheck
1192 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1193 wxStreamError err = m_wxis->GetLastError();
1194 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
1195 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
1196 }
1197 else {
1198 // We use only strings for the streams, not unicode
1199 obj = PyString_FromStringAndSize((char*)buf.GetData(), buf.GetDataLen());
1200 }
1201 wxPyEndBlockThreads(blocked);
1202 return obj;
1203 }
1204
1205
1206 PyObject* wxPyInputStream::readlines(int sizehint) {
1207 PyObject* pylist;
1208
1209 // check if we have a real wxInputStream to work with
1210 if (!m_wxis) {
1211 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1212 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream");
1213 wxPyEndBlockThreads(blocked);
1214 return NULL;
1215 }
1216
1217 // init list
1218 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1219 pylist = PyList_New(0);
1220 wxPyEndBlockThreads(blocked);
1221
1222 if (!pylist) {
1223 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1224 PyErr_NoMemory();
1225 wxPyEndBlockThreads(blocked);
1226 return NULL;
1227 }
1228
1229 // read sizehint bytes or until EOF
1230 int i;
1231 for (i=0; (m_wxis->CanRead()) && ((sizehint < 0) || (i < sizehint));) {
1232 PyObject* s = this->readline();
1233 if (s == NULL) {
1234 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1235 Py_DECREF(pylist);
1236 wxPyEndBlockThreads(blocked);
1237 return NULL;
1238 }
1239 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1240 PyList_Append(pylist, s);
1241 i += PyString_Size(s);
1242 wxPyEndBlockThreads(blocked);
1243 }
1244
1245 // error check
1246 wxStreamError err = m_wxis->GetLastError();
1247 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) {
1248 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1249 Py_DECREF(pylist);
1250 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
1251 wxPyEndBlockThreads(blocked);
1252 return NULL;
1253 }
1254
1255 return pylist;
1256 }
1257
1258
1259 void wxPyInputStream::seek(int offset, int whence) {
1260 if (m_wxis)
1261 m_wxis->SeekI(offset, wxSeekMode(whence));
1262 }
1263
1264 int wxPyInputStream::tell() {
1265 if (m_wxis)
1266 return m_wxis->TellI();
1267 else return 0;
1268 }
1269
1270
1271
1272
1273 wxPyCBInputStream::wxPyCBInputStream(PyObject *r, PyObject *s, PyObject *t, bool block)
1274 : wxInputStream(), m_read(r), m_seek(s), m_tell(t), m_block(block)
1275 {}
1276
1277 wxPyCBInputStream::wxPyCBInputStream(const wxPyCBInputStream& other)
1278 {
1279 m_read = other.m_read;
1280 m_seek = other.m_seek;
1281 m_tell = other.m_tell;
1282 m_block = other.m_block;
1283 Py_INCREF(m_read);
1284 Py_INCREF(m_seek);
1285 Py_INCREF(m_tell);
1286 }
1287
1288
1289 wxPyCBInputStream::~wxPyCBInputStream() {
1290 wxPyBlock_t blocked = wxPyBlock_t_default;
1291 if (m_block) blocked = wxPyBeginBlockThreads();
1292 Py_XDECREF(m_read);
1293 Py_XDECREF(m_seek);
1294 Py_XDECREF(m_tell);
1295 if (m_block) wxPyEndBlockThreads(blocked);
1296 }
1297
1298
1299 wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) {
1300 wxPyBlock_t blocked = wxPyBlock_t_default;
1301 if (block) blocked = wxPyBeginBlockThreads();
1302
1303 PyObject* read = wxPyGetMethod(py, "read");
1304 PyObject* seek = wxPyGetMethod(py, "seek");
1305 PyObject* tell = wxPyGetMethod(py, "tell");
1306
1307 if (!read) {
1308 PyErr_SetString(PyExc_TypeError, "Not a file-like object");
1309 Py_XDECREF(read);
1310 Py_XDECREF(seek);
1311 Py_XDECREF(tell);
1312 if (block) wxPyEndBlockThreads(blocked);
1313 return NULL;
1314 }
1315
1316 if (block) wxPyEndBlockThreads(blocked);
1317 return new wxPyCBInputStream(read, seek, tell, block);
1318 }
1319
1320
1321 wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block) {
1322 return wxPyCBInputStream::create(py, block);
1323 }
1324
1325 wxPyCBInputStream* wxPyCBInputStream_copy(wxPyCBInputStream* other) {
1326 return new wxPyCBInputStream(*other);
1327 }
1328
1329
1330 wxFileOffset wxPyCBInputStream::GetLength() const {
1331 wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const
1332 if (m_seek && m_tell) {
1333 wxFileOffset temp = self->OnSysTell();
1334 wxFileOffset ret = self->OnSysSeek(0, wxFromEnd);
1335 self->OnSysSeek(temp, wxFromStart);
1336 return ret;
1337 }
1338 else
1339 return wxInvalidOffset;
1340 }
1341
1342
1343 size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
1344 if (bufsize == 0)
1345 return 0;
1346
1347 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1348 PyObject* arglist = Py_BuildValue("(i)", bufsize);
1349 PyObject* result = PyEval_CallObject(m_read, arglist);
1350 Py_DECREF(arglist);
1351
1352 size_t o = 0;
1353 if ((result != NULL) && PyString_Check(result)) {
1354 o = PyString_Size(result);
1355 if (o == 0)
1356 m_lasterror = wxSTREAM_EOF;
1357 if (o > bufsize)
1358 o = bufsize;
1359 memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode...
1360 Py_DECREF(result);
1361
1362 }
1363 else
1364 m_lasterror = wxSTREAM_READ_ERROR;
1365 wxPyEndBlockThreads(blocked);
1366 return o;
1367 }
1368
1369 size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) {
1370 m_lasterror = wxSTREAM_WRITE_ERROR;
1371 return 0;
1372 }
1373
1374
1375 wxFileOffset wxPyCBInputStream::OnSysSeek(wxFileOffset off, wxSeekMode mode) {
1376 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1377 PyObject* arglist = PyTuple_New(2);
1378
1379 if (sizeof(wxFileOffset) > sizeof(long))
1380 // wxFileOffset is a 64-bit value...
1381 PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
1382 else
1383 PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off));
1384
1385 PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode));
1386
1387
1388 PyObject* result = PyEval_CallObject(m_seek, arglist);
1389 Py_DECREF(arglist);
1390 Py_XDECREF(result);
1391 wxPyEndBlockThreads(blocked);
1392 return OnSysTell();
1393 }
1394
1395
1396 wxFileOffset wxPyCBInputStream::OnSysTell() const {
1397 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1398 PyObject* arglist = Py_BuildValue("()");
1399 PyObject* result = PyEval_CallObject(m_tell, arglist);
1400 Py_DECREF(arglist);
1401 wxFileOffset o = 0;
1402 if (result != NULL) {
1403 if (PyLong_Check(result))
1404 o = PyLong_AsLongLong(result);
1405 else
1406 o = PyInt_AsLong(result);
1407 Py_DECREF(result);
1408 };
1409 wxPyEndBlockThreads(blocked);
1410 return o;
1411 }
1412
1413 //----------------------------------------------------------------------
1414 // Output stream
1415
1416 wxPyOutputStream::~wxPyOutputStream()
1417 {
1418 if (m_wxos)
1419 delete m_wxos;
1420 }
1421
1422 void wxPyOutputStream::close()
1423 {
1424 }
1425
1426 void wxPyOutputStream::flush()
1427 {
1428 }
1429
1430 bool wxPyOutputStream::eof()
1431 {
1432 return false;
1433 }
1434
1435 void wxPyOutputStream::seek(int offset, int whence)
1436 {
1437 if (m_wxos)
1438 m_wxos->SeekO(offset, wxSeekMode(whence));
1439 }
1440
1441 int wxPyOutputStream::tell()
1442 {
1443 if (m_wxos)
1444 return m_wxos->TellO();
1445 else return 0;
1446 }
1447
1448 void wxPyOutputStream::write(PyObject* data)
1449 {
1450 if (!m_wxos)
1451 return;
1452
1453 // We use only strings for the streams, not unicode
1454 PyObject* str = PyObject_Str(data);
1455 if (! str) {
1456 PyErr_SetString(PyExc_TypeError, "Unable to convert to string");
1457 return;
1458 }
1459 m_wxos->Write(PyString_AS_STRING(str), PyString_GET_SIZE(str));
1460 Py_DECREF(str);
1461 }
1462
1463
1464
1465
1466
1467
1468 wxPyCBOutputStream::wxPyCBOutputStream(PyObject *w, PyObject *s, PyObject *t, bool block)
1469 : wxOutputStream(), m_write(w), m_seek(s), m_tell(t), m_block(block)
1470 {}
1471
1472 wxPyCBOutputStream::wxPyCBOutputStream(const wxPyCBOutputStream& other)
1473 {
1474 m_write = other.m_write;
1475 m_seek = other.m_seek;
1476 m_tell = other.m_tell;
1477 m_block = other.m_block;
1478 Py_INCREF(m_write);
1479 Py_INCREF(m_seek);
1480 Py_INCREF(m_tell);
1481 }
1482
1483
1484 wxPyCBOutputStream::~wxPyCBOutputStream() {
1485 wxPyBlock_t blocked = wxPyBlock_t_default;
1486 if (m_block) blocked = wxPyBeginBlockThreads();
1487 Py_XDECREF(m_write);
1488 Py_XDECREF(m_seek);
1489 Py_XDECREF(m_tell);
1490 if (m_block) wxPyEndBlockThreads(blocked);
1491 }
1492
1493
1494 wxPyCBOutputStream* wxPyCBOutputStream::create(PyObject *py, bool block) {
1495 wxPyBlock_t blocked = wxPyBlock_t_default;
1496 if (block) blocked = wxPyBeginBlockThreads();
1497
1498 PyObject* write = wxPyGetMethod(py, "write");
1499 PyObject* seek = wxPyGetMethod(py, "seek");
1500 PyObject* tell = wxPyGetMethod(py, "tell");
1501
1502 if (!write) {
1503 PyErr_SetString(PyExc_TypeError, "Not a file-like object");
1504 Py_XDECREF(write);
1505 Py_XDECREF(seek);
1506 Py_XDECREF(tell);
1507 if (block) wxPyEndBlockThreads(blocked);
1508 return NULL;
1509 }
1510
1511 if (block) wxPyEndBlockThreads(blocked);
1512 return new wxPyCBOutputStream(write, seek, tell, block);
1513 }
1514
1515
1516 wxPyCBOutputStream* wxPyCBOutputStream_create(PyObject *py, bool block) {
1517 return wxPyCBOutputStream::create(py, block);
1518 }
1519
1520 wxPyCBOutputStream* wxPyCBOutputStream_copy(wxPyCBOutputStream* other) {
1521 return new wxPyCBOutputStream(*other);
1522 }
1523
1524
1525 wxFileOffset wxPyCBOutputStream::GetLength() const {
1526 wxPyCBOutputStream* self = (wxPyCBOutputStream*)this; // cast off const
1527 if (m_seek && m_tell) {
1528 wxFileOffset temp = self->OnSysTell();
1529 wxFileOffset ret = self->OnSysSeek(0, wxFromEnd);
1530 self->OnSysSeek(temp, wxFromStart);
1531 return ret;
1532 }
1533 else
1534 return wxInvalidOffset;
1535 }
1536
1537
1538 size_t wxPyCBOutputStream::OnSysRead(void *buffer, size_t bufsize) {
1539 m_lasterror = wxSTREAM_READ_ERROR;
1540 return 0;
1541 }
1542
1543 size_t wxPyCBOutputStream::OnSysWrite(const void *buffer, size_t bufsize) {
1544 if (bufsize == 0)
1545 return 0;
1546
1547 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1548 PyObject* arglist = PyTuple_New(1);
1549 PyTuple_SET_ITEM(arglist, 0, PyString_FromStringAndSize((char*)buffer, bufsize));
1550
1551 PyObject* result = PyEval_CallObject(m_write, arglist);
1552 Py_DECREF(arglist);
1553
1554 if (result != NULL)
1555 Py_DECREF(result);
1556 else
1557 m_lasterror = wxSTREAM_WRITE_ERROR;
1558 wxPyEndBlockThreads(blocked);
1559 return bufsize;
1560 }
1561
1562
1563 wxFileOffset wxPyCBOutputStream::OnSysSeek(wxFileOffset off, wxSeekMode mode) {
1564 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1565 PyObject* arglist = PyTuple_New(2);
1566
1567 if (sizeof(wxFileOffset) > sizeof(long))
1568 // wxFileOffset is a 64-bit value...
1569 PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
1570 else
1571 PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off));
1572
1573 PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode));
1574
1575
1576 PyObject* result = PyEval_CallObject(m_seek, arglist);
1577 Py_DECREF(arglist);
1578 Py_XDECREF(result);
1579 wxPyEndBlockThreads(blocked);
1580 return OnSysTell();
1581 }
1582
1583
1584 wxFileOffset wxPyCBOutputStream::OnSysTell() const {
1585 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1586 PyObject* arglist = Py_BuildValue("()");
1587 PyObject* result = PyEval_CallObject(m_tell, arglist);
1588 Py_DECREF(arglist);
1589 wxFileOffset o = 0;
1590 if (result != NULL) {
1591 if (PyLong_Check(result))
1592 o = PyLong_AsLongLong(result);
1593 else
1594 o = PyInt_AsLong(result);
1595 Py_DECREF(result);
1596 };
1597 wxPyEndBlockThreads(blocked);
1598 return o;
1599 }
1600
1601
1602
1603 //----------------------------------------------------------------------
1604
1605 IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
1606
1607 wxPyCallback::wxPyCallback(PyObject* func) {
1608 m_func = func;
1609 Py_INCREF(m_func);
1610 }
1611
1612 wxPyCallback::wxPyCallback(const wxPyCallback& other) {
1613 m_func = other.m_func;
1614 Py_INCREF(m_func);
1615 }
1616
1617 wxPyCallback::~wxPyCallback() {
1618 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1619 Py_DECREF(m_func);
1620 wxPyEndBlockThreads(blocked);
1621 }
1622
1623
1624 #define wxPy_PRECALLINIT "_preCallInit"
1625 #define wxPy_POSTCALLCLEANUP "_postCallCleanup"
1626
1627 // This function is used for all events destined for Python event handlers.
1628 void wxPyCallback::EventThunker(wxEvent& event) {
1629 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
1630 PyObject* func = cb->m_func;
1631 PyObject* result;
1632 PyObject* arg;
1633 PyObject* tuple;
1634 bool checkSkip = false;
1635
1636 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1637 wxString className = event.GetClassInfo()->GetClassName();
1638
1639 // If the event is one of these types then pass the original
1640 // event object instead of the one passed to us.
1641 if ( className == wxT("wxPyEvent") ) {
1642 arg = ((wxPyEvent*)&event)->GetSelf();
1643 checkSkip = ((wxPyEvent*)&event)->GetCloned();
1644 }
1645 else if ( className == wxT("wxPyCommandEvent") ) {
1646 arg = ((wxPyCommandEvent*)&event)->GetSelf();
1647 checkSkip = ((wxPyCommandEvent*)&event)->GetCloned();
1648 }
1649 else {
1650 arg = wxPyConstructObject((void*)&event, className);
1651 }
1652
1653 if (!arg) {
1654 PyErr_Print();
1655 } else {
1656 // "intern" the pre/post method names to speed up the HasAttr
1657 static PyObject* s_preName = NULL;
1658 static PyObject* s_postName = NULL;
1659 if (s_preName == NULL) {
1660 s_preName = PyString_FromString(wxPy_PRECALLINIT);
1661 s_postName = PyString_FromString(wxPy_POSTCALLCLEANUP);
1662 }
1663
1664 // Check if the event object needs some preinitialization
1665 if (PyObject_HasAttr(arg, s_preName)) {
1666 result = PyObject_CallMethodObjArgs(arg, s_preName, arg, NULL);
1667 if ( result ) {
1668 Py_DECREF(result); // result is ignored, but we still need to decref it
1669 PyErr_Clear(); // Just in case...
1670 } else {
1671 PyErr_Print();
1672 }
1673 }
1674
1675 // Call the event handler, passing the event object
1676 tuple = PyTuple_New(1);
1677 PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg
1678 result = PyEval_CallObject(func, tuple);
1679 if ( result ) {
1680 Py_DECREF(result); // result is ignored, but we still need to decref it
1681 PyErr_Clear(); // Just in case...
1682 } else {
1683 PyErr_Print();
1684 }
1685
1686 // Check if the event object needs some post cleanup
1687 if (PyObject_HasAttr(arg, s_postName)) {
1688 result = PyObject_CallMethodObjArgs(arg, s_postName, arg, NULL);
1689 if ( result ) {
1690 Py_DECREF(result); // result is ignored, but we still need to decref it
1691 PyErr_Clear(); // Just in case...
1692 } else {
1693 PyErr_Print();
1694 }
1695 }
1696
1697 if ( checkSkip ) {
1698 // if the event object was one of our special types and
1699 // it had been cloned, then we need to extract the Skipped
1700 // value from the original and set it in the clone.
1701 result = PyObject_CallMethod(arg, "GetSkipped", "");
1702 if ( result ) {
1703 event.Skip(PyInt_AsLong(result));
1704 Py_DECREF(result);
1705 } else {
1706 PyErr_Print();
1707 }
1708 }
1709 Py_DECREF(tuple);
1710 }
1711 wxPyEndBlockThreads(blocked);
1712 }
1713
1714
1715 //----------------------------------------------------------------------
1716
1717 wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
1718 m_lastFound = NULL;
1719 m_self = other.m_self;
1720 m_class = other.m_class;
1721 if (m_self) {
1722 Py_INCREF(m_self);
1723 Py_INCREF(m_class);
1724 }
1725 }
1726
1727
1728 void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
1729 m_self = self;
1730 m_class = klass;
1731 m_incRef = incref;
1732 if (incref) {
1733 Py_INCREF(m_self);
1734 Py_INCREF(m_class);
1735 }
1736 }
1737
1738
1739 #if PYTHON_API_VERSION >= 1011
1740
1741 // Prior to Python 2.2 PyMethod_GetClass returned the class object
1742 // in which the method was defined. Starting with 2.2 it returns
1743 // "class that asked for the method" which seems totally bogus to me
1744 // but apprently it fixes some obscure problem waiting to happen in
1745 // Python. Since the API was not documented Guido and the gang felt
1746 // safe in changing it. Needless to say that totally screwed up the
1747 // logic below in wxPyCallbackHelper::findCallback, hence this icky
1748 // code to find the class where the method is actually defined...
1749
1750 static
1751 PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name)
1752 {
1753 int i, n;
1754
1755 if (PyType_Check(klass)) { // new style classes
1756 // This code is borrowed/adapted from _PyType_Lookup in typeobject.c
1757 PyTypeObject* type = (PyTypeObject*)klass;
1758 PyObject *mro, *res, *base, *dict;
1759 /* Look in tp_dict of types in MRO */
1760 mro = type->tp_mro;
1761 assert(PyTuple_Check(mro));
1762 n = PyTuple_GET_SIZE(mro);
1763 for (i = 0; i < n; i++) {
1764 base = PyTuple_GET_ITEM(mro, i);
1765 if (PyClass_Check(base))
1766 dict = ((PyClassObject *)base)->cl_dict;
1767 else {
1768 assert(PyType_Check(base));
1769 dict = ((PyTypeObject *)base)->tp_dict;
1770 }
1771 assert(dict && PyDict_Check(dict));
1772 res = PyDict_GetItem(dict, name);
1773 if (res != NULL)
1774 return base;
1775 }
1776 return NULL;
1777 }
1778
1779 else if (PyClass_Check(klass)) { // old style classes
1780 // This code is borrowed/adapted from class_lookup in classobject.c
1781 PyClassObject* cp = (PyClassObject*)klass;
1782 PyObject *value = PyDict_GetItem(cp->cl_dict, name);
1783 if (value != NULL) {
1784 return (PyObject*)cp;
1785 }
1786 n = PyTuple_Size(cp->cl_bases);
1787 for (i = 0; i < n; i++) {
1788 PyObject* base = PyTuple_GetItem(cp->cl_bases, i);
1789 PyObject *v = PyFindClassWithAttr(base, name);
1790 if (v != NULL)
1791 return v;
1792 }
1793 return NULL;
1794 }
1795 return NULL;
1796 }
1797 #endif
1798
1799
1800 static
1801 PyObject* PyMethod_GetDefiningClass(PyObject* method, PyObject* nameo)
1802 {
1803 PyObject* mgc = PyMethod_GET_CLASS(method);
1804
1805 #if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
1806 return mgc;
1807 #else // 2.2 and after, the hard way...
1808 return PyFindClassWithAttr(mgc, nameo);
1809 #endif
1810 }
1811
1812
1813
1814 // To avoid recursion when an overridden virtual method wants to call the base
1815 // class version, temporarily set an attribute in the instance with the same
1816 // name as the method. Then the PyObject_GetAttr in the next findCallback
1817 // will return this attribute and the PyMethod_Check will fail.
1818
1819 void wxPyCallbackHelper::setRecursionGuard(PyObject* method) const
1820 {
1821 PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
1822 PyObject_SetAttr(m_self, func->func_name, Py_None);
1823 }
1824
1825 void wxPyCallbackHelper::clearRecursionGuard(PyObject* method) const
1826 {
1827 PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
1828 if (PyObject_HasAttr(m_self, func->func_name)) {
1829 PyObject_DelAttr(m_self, func->func_name);
1830 }
1831 }
1832
1833 // bool wxPyCallbackHelper::hasRecursionGuard(PyObject* method) const
1834 // {
1835 // PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method);
1836 // if (PyObject_HasAttr(m_self, func->func_name)) {
1837 // PyObject* attr = PyObject_GetAttr(m_self, func->func_name);
1838 // bool retval = (attr == Py_None);
1839 // Py_DECREF(attr);
1840 // return retval;
1841 // }
1842 // return false;
1843 // }
1844
1845
1846 bool wxPyCallbackHelper::findCallback(const char* name, bool setGuard) const {
1847 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
1848 PyObject *method, *klass;
1849 PyObject* nameo = PyString_FromString(name);
1850 self->m_lastFound = NULL;
1851
1852 // If the object (m_self) has an attibute of the given name...
1853 if (m_self && PyObject_HasAttr(m_self, nameo)) {
1854 method = PyObject_GetAttr(m_self, nameo);
1855
1856 // ...and if that attribute is a method, and if that method's class is
1857 // not from the registered class or a base class...
1858 if (PyMethod_Check(method) &&
1859 (klass = PyMethod_GetDefiningClass(method, nameo)) != NULL &&
1860 (klass != m_class) &&
1861 PyObject_IsSubclass(klass, m_class)) {
1862
1863 // ...then we'll save a pointer to the method so callCallback can
1864 // call it. But first, set a recursion guard in case the
1865 // overridden method wants to call the base class version.
1866 if (setGuard)
1867 setRecursionGuard(method);
1868 self->m_lastFound = method;
1869 }
1870 else {
1871 Py_DECREF(method);
1872 }
1873 }
1874
1875 Py_DECREF(nameo);
1876 return m_lastFound != NULL;
1877 }
1878
1879
1880 int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
1881 PyObject* result;
1882 int retval = false;
1883
1884 result = callCallbackObj(argTuple);
1885 if (result) { // Assumes an integer return type...
1886 retval = PyInt_AsLong(result);
1887 Py_DECREF(result);
1888 PyErr_Clear(); // forget about it if it's not...
1889 }
1890 return retval;
1891 }
1892
1893 // Invoke the Python callable object, returning the raw PyObject return
1894 // value. Caller should DECREF the return value and also manage the GIL.
1895 PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
1896 PyObject* result;
1897
1898 // Save a copy of the pointer in case the callback generates another
1899 // callback. In that case m_lastFound will have a different value when
1900 // it gets back here...
1901 PyObject* method = m_lastFound;
1902
1903 result = PyEval_CallObject(method, argTuple);
1904 clearRecursionGuard(method);
1905
1906 Py_DECREF(argTuple);
1907 Py_DECREF(method);
1908 if (!result) {
1909 PyErr_Print();
1910 }
1911 return result;
1912 }
1913
1914
1915 void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
1916 cbh.setSelf(self, klass, incref);
1917 }
1918
1919 bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name, bool setGuard) {
1920 return cbh.findCallback(name, setGuard);
1921 }
1922
1923 int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1924 return cbh.callCallback(argTuple);
1925 }
1926
1927 PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
1928 return cbh.callCallbackObj(argTuple);
1929 }
1930
1931
1932 void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
1933 if (cbh->m_incRef && Py_IsInitialized()) {
1934 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1935 Py_XDECREF(cbh->m_self);
1936 Py_XDECREF(cbh->m_class);
1937 wxPyEndBlockThreads(blocked);
1938 }
1939 }
1940
1941 //---------------------------------------------------------------------------
1942 //---------------------------------------------------------------------------
1943 // These event classes can be derived from in Python and passed through the event
1944 // system without losing anything. They do this by keeping a reference to
1945 // themselves and some special case handling in wxPyCallback::EventThunker.
1946
1947
1948 wxPyEvtSelfRef::wxPyEvtSelfRef() {
1949 //m_self = Py_None; // **** We don't do normal ref counting to prevent
1950 //Py_INCREF(m_self); // circular loops...
1951 m_cloned = false;
1952 }
1953
1954 wxPyEvtSelfRef::~wxPyEvtSelfRef() {
1955 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1956 if (m_cloned)
1957 Py_DECREF(m_self);
1958 wxPyEndBlockThreads(blocked);
1959 }
1960
1961 void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
1962 wxPyBlock_t blocked = wxPyBeginBlockThreads();
1963 if (m_cloned)
1964 Py_DECREF(m_self);
1965 m_self = self;
1966 if (clone) {
1967 Py_INCREF(m_self);
1968 m_cloned = true;
1969 }
1970 wxPyEndBlockThreads(blocked);
1971 }
1972
1973 PyObject* wxPyEvtSelfRef::GetSelf() const {
1974 Py_INCREF(m_self);
1975 return m_self;
1976 }
1977
1978
1979 IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent);
1980 IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent);
1981
1982
1983 wxPyEvent::wxPyEvent(int winid, wxEventType commandType)
1984 : wxEvent(winid, commandType) {
1985 }
1986
1987
1988 wxPyEvent::wxPyEvent(const wxPyEvent& evt)
1989 : wxEvent(evt)
1990 {
1991 SetSelf(evt.m_self, true);
1992 }
1993
1994
1995 wxPyEvent::~wxPyEvent() {
1996 }
1997
1998
1999 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
2000 : wxCommandEvent(commandType, id) {
2001 }
2002
2003
2004 wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt)
2005 : wxCommandEvent(evt)
2006 {
2007 SetSelf(evt.m_self, true);
2008 }
2009
2010
2011 wxPyCommandEvent::~wxPyCommandEvent() {
2012 }
2013
2014
2015
2016
2017
2018 //---------------------------------------------------------------------------
2019 //---------------------------------------------------------------------------
2020 // Convert a wxList to a Python List, only works for lists of wxObjects
2021
2022 PyObject* wxPy_ConvertList(wxListBase* listbase) {
2023 wxList* list = (wxList*)listbase; // this is probably bad...
2024 PyObject* pyList;
2025 PyObject* pyObj;
2026 wxObject* wxObj;
2027 wxNode* node = list->GetFirst();
2028
2029 wxPyBlock_t blocked = wxPyBeginBlockThreads();
2030 pyList = PyList_New(0);
2031 while (node) {
2032 wxObj = node->GetData();
2033 pyObj = wxPyMake_wxObject(wxObj,false);
2034 PyList_Append(pyList, pyObj);
2035 Py_DECREF(pyObj); // the Append also does an INCREF, that's one more than we need.
2036 node = node->GetNext();
2037 }
2038 wxPyEndBlockThreads(blocked);
2039 return pyList;
2040 }
2041
2042 //----------------------------------------------------------------------
2043
2044 long wxPyGetWinHandle(wxWindow* win) {
2045
2046 #ifdef __WXMSW__
2047 return (long)win->GetHandle();
2048 #endif
2049
2050 #if defined(__WXGTK__) || defined(__WXX11)
2051 return (long)GetXWindow(win);
2052 #endif
2053
2054 #ifdef __WXMAC__
2055 //return (long)MAC_WXHWND(win->MacGetTopLevelWindowRef());
2056 return (long)win->GetHandle();
2057 #endif
2058
2059 return 0;
2060 }
2061
2062 //----------------------------------------------------------------------
2063 // Some helper functions for typemaps in my_typemaps.i, so they won't be
2064 // included in every file over and over again...
2065
2066 wxString* wxString_in_helper(PyObject* source) {
2067 wxString* target = NULL;
2068
2069 if (!PyString_Check(source) && !PyUnicode_Check(source)) {
2070 PyErr_SetString(PyExc_TypeError, "String or Unicode type required");
2071 return NULL;
2072 }
2073 #if wxUSE_UNICODE
2074 PyObject* uni = source;
2075 if (PyString_Check(source)) {
2076 uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict");
2077 if (PyErr_Occurred()) return NULL;
2078 }
2079 target = new wxString();
2080 size_t len = PyUnicode_GET_SIZE(uni);
2081 if (len) {
2082 PyUnicode_AsWideChar((PyUnicodeObject*)uni, wxStringBuffer(*target, len), len);
2083 }
2084
2085 if (PyString_Check(source))
2086 Py_DECREF(uni);
2087 #else
2088 // Convert to a string object if it isn't already, then to wxString
2089 PyObject* str = source;
2090 if (PyUnicode_Check(source)) {
2091 str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict");
2092 if (PyErr_Occurred()) return NULL;
2093 }
2094 else if (!PyString_Check(source)) {
2095 str = PyObject_Str(source);
2096 if (PyErr_Occurred()) return NULL;
2097 }
2098 char* tmpPtr; Py_ssize_t tmpSize;
2099 PyString_AsStringAndSize(str, &tmpPtr, &tmpSize);
2100 target = new wxString(tmpPtr, tmpSize);
2101
2102 if (!PyString_Check(source))
2103 Py_DECREF(str);
2104 #endif // wxUSE_UNICODE
2105
2106 return target;
2107 }
2108
2109
2110 // Similar to above except doesn't use "new" and doesn't set an exception
2111 wxString Py2wxString(PyObject* source)
2112 {
2113 wxString target;
2114
2115 #if wxUSE_UNICODE
2116 // Convert to a unicode object, if not already, then to a wxString
2117 PyObject* uni = source;
2118 if (!PyUnicode_Check(source)) {
2119 uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict");
2120 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
2121 }
2122 size_t len = PyUnicode_GET_SIZE(uni);
2123 if (len) {
2124 PyUnicode_AsWideChar((PyUnicodeObject*)uni, wxStringBuffer(target, len), len);
2125 }
2126
2127 if (!PyUnicode_Check(source))
2128 Py_DECREF(uni);
2129 #else
2130 // Convert to a string object if it isn't already, then to wxString
2131 PyObject* str = source;
2132 if (PyUnicode_Check(source)) {
2133 str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict");
2134 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
2135 }
2136 else if (!PyString_Check(source)) {
2137 str = PyObject_Str(source);
2138 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear?
2139 }
2140 char* tmpPtr; Py_ssize_t tmpSize;
2141 PyString_AsStringAndSize(str, &tmpPtr, &tmpSize);
2142 target = wxString(tmpPtr, tmpSize);
2143
2144 if (!PyString_Check(source))
2145 Py_DECREF(str);
2146 #endif // wxUSE_UNICODE
2147
2148 return target;
2149 }
2150
2151
2152 // Make either a Python String or Unicode object, depending on build mode
2153 PyObject* wx2PyString(const wxString& src)
2154 {
2155 PyObject* str;
2156 #if wxUSE_UNICODE
2157 str = PyUnicode_FromWideChar(src.c_str(), src.Len());
2158 #else
2159 str = PyString_FromStringAndSize(src.c_str(), src.Len());
2160 #endif
2161 return str;
2162 }
2163
2164
2165
2166 void wxSetDefaultPyEncoding(const char* encoding)
2167 {
2168 strncpy(wxPyDefaultEncoding, encoding, DEFAULTENCODING_SIZE);
2169 }
2170
2171 const char* wxGetDefaultPyEncoding()
2172 {
2173 return wxPyDefaultEncoding;
2174 }
2175
2176 //----------------------------------------------------------------------
2177
2178
2179 byte* byte_LIST_helper(PyObject* source) {
2180 if (!PyList_Check(source)) {
2181 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2182 return NULL;
2183 }
2184 int count = PyList_Size(source);
2185 byte* temp = new byte[count];
2186 if (! temp) {
2187 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2188 return NULL;
2189 }
2190 for (int x=0; x<count; x++) {
2191 PyObject* o = PyList_GetItem(source, x);
2192 if (! PyInt_Check(o)) {
2193 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
2194 return NULL;
2195 }
2196 temp[x] = (byte)PyInt_AsLong(o);
2197 }
2198 return temp;
2199 }
2200
2201
2202 int* int_LIST_helper(PyObject* source) {
2203 if (!PyList_Check(source)) {
2204 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2205 return NULL;
2206 }
2207 int count = PyList_Size(source);
2208 int* temp = new int[count];
2209 if (! temp) {
2210 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2211 return NULL;
2212 }
2213 for (int x=0; x<count; x++) {
2214 PyObject* o = PyList_GetItem(source, x);
2215 if (! PyInt_Check(o)) {
2216 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
2217 return NULL;
2218 }
2219 temp[x] = PyInt_AsLong(o);
2220 }
2221 return temp;
2222 }
2223
2224
2225 long* long_LIST_helper(PyObject* source) {
2226 if (!PyList_Check(source)) {
2227 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2228 return NULL;
2229 }
2230 int count = PyList_Size(source);
2231 long* temp = new long[count];
2232 if (! temp) {
2233 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2234 return NULL;
2235 }
2236 for (int x=0; x<count; x++) {
2237 PyObject* o = PyList_GetItem(source, x);
2238 if (! PyInt_Check(o)) {
2239 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
2240 return NULL;
2241 }
2242 temp[x] = PyInt_AsLong(o);
2243 }
2244 return temp;
2245 }
2246
2247
2248 char** string_LIST_helper(PyObject* source) {
2249 if (!PyList_Check(source)) {
2250 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2251 return NULL;
2252 }
2253 int count = PyList_Size(source);
2254 char** temp = new char*[count];
2255 if (! temp) {
2256 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2257 return NULL;
2258 }
2259 for (int x=0; x<count; x++) {
2260 PyObject* o = PyList_GetItem(source, x);
2261 if (! PyString_Check(o)) {
2262 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
2263 return NULL;
2264 }
2265 temp[x] = PyString_AsString(o);
2266 }
2267 return temp;
2268 }
2269
2270 //---------------------------------------------------------------------------
2271 // NOTE: The following functions could really use some refactoring using
2272 // templates to make things somewhat simpler...
2273
2274 inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point)
2275 {
2276 // get the x value
2277 if (PyInt_Check(o1))
2278 point->x = (int)PyInt_AS_LONG(o1);
2279 else if (PyFloat_Check(o1))
2280 point->x = (int)PyFloat_AS_DOUBLE(o1);
2281 else if (PyNumber_Check(o1))
2282 point->x = (int)PyInt_AsLong(o1);
2283 else
2284 return false;
2285
2286 // get the y value
2287 if (PyInt_Check(o2))
2288 point->y = (int)PyInt_AS_LONG(o2);
2289 else if (PyFloat_Check(o2))
2290 point->y = (int)PyFloat_AS_DOUBLE(o2);
2291 else if (PyNumber_Check(o2))
2292 point->y = (int)PyInt_AsLong(o2);
2293 else
2294 return false;
2295
2296 return true;
2297
2298 // NOTE: This function used to have this code in it, but I don't know why it
2299 // is a problem nor what havok it will cause, so removing for now...
2300 // if (wxPySwigInstance_Check(o1) || wxPySwigInstance_Check(o2)) {
2301 // // Disallow instances because they can cause havok
2302 // return false;
2303 // }
2304 }
2305
2306
2307 inline bool wxPoint2DFromObjects(PyObject* o1, PyObject* o2, wxPoint2D* point)
2308 {
2309 // get the x value
2310 if (PyInt_Check(o1))
2311 point->m_x = (double)PyInt_AS_LONG(o1);
2312 else if (PyFloat_Check(o1))
2313 point->m_x = (double)PyFloat_AS_DOUBLE(o1);
2314 else if (PyNumber_Check(o1))
2315 point->m_x = (double)PyFloat_AsDouble(o1);
2316 else
2317 return false;
2318
2319 // get the y value
2320 if (PyInt_Check(o2))
2321 point->m_y = (double)PyInt_AS_LONG(o2);
2322 else if (PyFloat_Check(o2))
2323 point->m_y = (double)PyFloat_AS_DOUBLE(o2);
2324 else if (PyNumber_Check(o2))
2325 point->m_y = (double)PyFloat_AsDouble(o2);
2326 else
2327 return false;
2328
2329 return true;
2330 }
2331
2332
2333
2334 wxPoint* wxPoint_LIST_helper(PyObject* source, int *count)
2335 {
2336 int idx;
2337 wxPoint* temp;
2338 PyObject *o, *o1, *o2;
2339 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2340
2341 if (!PySequence_Check(source)) {
2342 goto error0;
2343 }
2344
2345 // The length of the sequence is returned in count.
2346 *count = PySequence_Length(source);
2347 if (*count < 0) {
2348 goto error0;
2349 }
2350
2351 temp = new wxPoint[*count];
2352 if (!temp) {
2353 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2354 return NULL;
2355 }
2356 for (idx=0; idx<*count; idx++) {
2357 // Get an item: try fast way first.
2358 if (isFast) {
2359 o = PySequence_Fast_GET_ITEM(source, idx);
2360 }
2361 else {
2362 o = PySequence_GetItem(source, idx);
2363 if (o == NULL) {
2364 goto error1;
2365 }
2366 }
2367
2368 // Convert o to wxPoint.
2369 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
2370 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
2371 o1 = PySequence_Fast_GET_ITEM(o, 0);
2372 o2 = PySequence_Fast_GET_ITEM(o, 1);
2373 if (!wxPointFromObjects(o1, o2, &temp[idx])) {
2374 goto error2;
2375 }
2376 }
2377 else if (wxPySwigInstance_Check(o)) {
2378 wxPoint* pt;
2379 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint"))) {
2380 goto error2;
2381 }
2382 temp[idx] = *pt;
2383 }
2384 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
2385 o1 = PySequence_GetItem(o, 0);
2386 o2 = PySequence_GetItem(o, 1);
2387 if (!wxPointFromObjects(o1, o2, &temp[idx])) {
2388 goto error3;
2389 }
2390 Py_DECREF(o1);
2391 Py_DECREF(o2);
2392 }
2393 else {
2394 goto error2;
2395 }
2396 // Clean up.
2397 if (!isFast)
2398 Py_DECREF(o);
2399 }
2400 return temp;
2401
2402 error3:
2403 Py_DECREF(o1);
2404 Py_DECREF(o2);
2405 error2:
2406 if (!isFast)
2407 Py_DECREF(o);
2408 error1:
2409 delete [] temp;
2410 error0:
2411 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
2412 return NULL;
2413 }
2414
2415
2416
2417 wxPoint2D* wxPoint2D_LIST_helper(PyObject* source, size_t *count)
2418 {
2419 size_t idx;
2420 wxPoint2D* temp;
2421 PyObject *o, *o1, *o2;
2422 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2423
2424 if (!PySequence_Check(source)) {
2425 goto error0;
2426 }
2427
2428 // The length of the sequence is returned in count.
2429 *count = PySequence_Length(source);
2430 if (*count < 0) {
2431 goto error0;
2432 }
2433
2434 temp = new wxPoint2D[*count];
2435 if (!temp) {
2436 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2437 return NULL;
2438 }
2439 for (idx=0; idx<*count; idx++) {
2440 // Get an item: try fast way first.
2441 if (isFast) {
2442 o = PySequence_Fast_GET_ITEM(source, idx);
2443 }
2444 else {
2445 o = PySequence_GetItem(source, idx);
2446 if (o == NULL) {
2447 goto error1;
2448 }
2449 }
2450
2451 // Convert o to wxPoint.
2452 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
2453 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
2454 o1 = PySequence_Fast_GET_ITEM(o, 0);
2455 o2 = PySequence_Fast_GET_ITEM(o, 1);
2456 if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) {
2457 goto error2;
2458 }
2459 }
2460 else if (wxPySwigInstance_Check(o)) {
2461 wxPoint2D* pt;
2462 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint2D"))) {
2463 goto error2;
2464 }
2465 temp[idx] = *pt;
2466 }
2467 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
2468 o1 = PySequence_GetItem(o, 0);
2469 o2 = PySequence_GetItem(o, 1);
2470 if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) {
2471 goto error3;
2472 }
2473 Py_DECREF(o1);
2474 Py_DECREF(o2);
2475 }
2476 else {
2477 goto error2;
2478 }
2479 // Clean up.
2480 if (!isFast)
2481 Py_DECREF(o);
2482 }
2483 return temp;
2484
2485 error3:
2486 Py_DECREF(o1);
2487 Py_DECREF(o2);
2488 error2:
2489 if (!isFast)
2490 Py_DECREF(o);
2491 error1:
2492 delete [] temp;
2493 error0:
2494 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoint2Ds.");
2495 return NULL;
2496 }
2497
2498 //---------------------------------------------------------------------------
2499
2500
2501 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
2502 if (!PyList_Check(source)) {
2503 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2504 return NULL;
2505 }
2506 int count = PyList_Size(source);
2507 wxBitmap** temp = new wxBitmap*[count];
2508 if (! temp) {
2509 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2510 return NULL;
2511 }
2512 for (int x=0; x<count; x++) {
2513 PyObject* o = PyList_GetItem(source, x);
2514 if (wxPySwigInstance_Check(o)) {
2515 wxBitmap* pt;
2516 if (! wxPyConvertSwigPtr(o, (void **) &pt, wxT("wxBitmap"))) {
2517 PyErr_SetString(PyExc_TypeError,"Expected wxBitmap.");
2518 return NULL;
2519 }
2520 temp[x] = pt;
2521 }
2522 else {
2523 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
2524 return NULL;
2525 }
2526 }
2527 return temp;
2528 }
2529
2530
2531
2532 wxString* wxString_LIST_helper(PyObject* source) {
2533 if (!PyList_Check(source)) {
2534 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2535 return NULL;
2536 }
2537 int count = PyList_Size(source);
2538 wxString* temp = new wxString[count];
2539 if (! temp) {
2540 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2541 return NULL;
2542 }
2543 for (int x=0; x<count; x++) {
2544 PyObject* o = PyList_GetItem(source, x);
2545 #if PYTHON_API_VERSION >= 1009
2546 if (! PyString_Check(o) && ! PyUnicode_Check(o)) {
2547 PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects.");
2548 return NULL;
2549 }
2550 #else
2551 if (! PyString_Check(o)) {
2552 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
2553 return NULL;
2554 }
2555 #endif
2556
2557 wxString* pStr = wxString_in_helper(o);
2558 temp[x] = *pStr;
2559 delete pStr;
2560 }
2561 return temp;
2562 }
2563
2564
2565 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
2566 if (!PyList_Check(source)) {
2567 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2568 return NULL;
2569 }
2570 int count = PyList_Size(source);
2571 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
2572 if (! temp) {
2573 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2574 return NULL;
2575 }
2576 for (int x=0; x<count; x++) {
2577 PyObject* o = PyList_GetItem(source, x);
2578 if (wxPySwigInstance_Check(o)) {
2579 wxAcceleratorEntry* ae;
2580 if (! wxPyConvertSwigPtr(o, (void **) &ae, wxT("wxAcceleratorEntry"))) {
2581 PyErr_SetString(PyExc_TypeError,"Expected wxAcceleratorEntry.");
2582 return NULL;
2583 }
2584 temp[x] = *ae;
2585 }
2586 else if (PyTuple_Check(o)) {
2587 PyObject* o1 = PyTuple_GetItem(o, 0);
2588 PyObject* o2 = PyTuple_GetItem(o, 1);
2589 PyObject* o3 = PyTuple_GetItem(o, 2);
2590 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
2591 }
2592 else {
2593 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
2594 return NULL;
2595 }
2596 }
2597 return temp;
2598 }
2599
2600
2601 wxPen** wxPen_LIST_helper(PyObject* source) {
2602 if (!PyList_Check(source)) {
2603 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
2604 return NULL;
2605 }
2606 int count = PyList_Size(source);
2607 wxPen** temp = new wxPen*[count];
2608 if (!temp) {
2609 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
2610 return NULL;
2611 }
2612 for (int x=0; x<count; x++) {
2613 PyObject* o = PyList_GetItem(source, x);
2614 if (wxPySwigInstance_Check(o)) {
2615 wxPen* pt;
2616 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPen"))) {
2617 delete temp;
2618 PyErr_SetString(PyExc_TypeError,"Expected wxPen.");
2619 return NULL;
2620 }
2621 temp[x] = pt;
2622 }
2623 else {
2624 delete temp;
2625 PyErr_SetString(PyExc_TypeError, "Expected a list of wxPens.");
2626 return NULL;
2627 }
2628 }
2629 return temp;
2630 }
2631
2632
2633 bool wxPy2int_seq_helper(PyObject* source, int* i1, int* i2) {
2634 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2635 PyObject *o1, *o2;
2636
2637 if (!PySequence_Check(source) || PySequence_Length(source) != 2)
2638 return false;
2639
2640 if (isFast) {
2641 o1 = PySequence_Fast_GET_ITEM(source, 0);
2642 o2 = PySequence_Fast_GET_ITEM(source, 1);
2643 }
2644 else {
2645 o1 = PySequence_GetItem(source, 0);
2646 o2 = PySequence_GetItem(source, 1);
2647 }
2648
2649 *i1 = PyInt_AsLong(o1);
2650 *i2 = PyInt_AsLong(o2);
2651
2652 if (! isFast) {
2653 Py_DECREF(o1);
2654 Py_DECREF(o2);
2655 }
2656 return true;
2657 }
2658
2659
2660 bool wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) {
2661 bool isFast = PyList_Check(source) || PyTuple_Check(source);
2662 PyObject *o1, *o2, *o3, *o4;
2663
2664 if (!PySequence_Check(source) || PySequence_Length(source) != 4)
2665 return false;
2666
2667 if (isFast) {
2668 o1 = PySequence_Fast_GET_ITEM(source, 0);
2669 o2 = PySequence_Fast_GET_ITEM(source, 1);
2670 o3 = PySequence_Fast_GET_ITEM(source, 2);
2671 o4 = PySequence_Fast_GET_ITEM(source, 3);
2672 }
2673 else {
2674 o1 = PySequence_GetItem(source, 0);
2675 o2 = PySequence_GetItem(source, 1);
2676 o3 = PySequence_GetItem(source, 2);
2677 o4 = PySequence_GetItem(source, 3);
2678 }
2679
2680 *i1 = PyInt_AsLong(o1);
2681 *i2 = PyInt_AsLong(o2);
2682 *i3 = PyInt_AsLong(o3);
2683 *i4 = PyInt_AsLong(o4);
2684
2685 if (! isFast) {
2686 Py_DECREF(o1);
2687 Py_DECREF(o2);
2688 Py_DECREF(o3);
2689 Py_DECREF(o4);
2690 }
2691 return true;
2692 }
2693
2694
2695 //----------------------------------------------------------------------
2696
2697 bool wxPySimple_typecheck(PyObject* source, const wxChar* classname, int seqLen)
2698 {
2699 void* ptr;
2700
2701 if (wxPySwigInstance_Check(source) &&
2702 wxPyConvertSwigPtr(source, (void **)&ptr, classname))
2703 return true;
2704
2705 PyErr_Clear();
2706 if (PySequence_Check(source) && PySequence_Length(source) == seqLen)
2707 return true;
2708
2709 return false;
2710 }
2711
2712 bool wxSize_helper(PyObject* source, wxSize** obj)
2713 {
2714 if (source == Py_None) {
2715 **obj = wxSize(-1,-1);
2716 return true;
2717 }
2718 return wxPyTwoIntItem_helper(source, obj, wxT("wxSize"));
2719 }
2720
2721
2722 bool wxPoint_helper(PyObject* source, wxPoint** obj)
2723 {
2724 if (source == Py_None) {
2725 **obj = wxPoint(-1,-1);
2726 return true;
2727 }
2728 return wxPyTwoIntItem_helper(source, obj, wxT("wxPoint"));
2729 }
2730
2731
2732
2733 bool wxPosition_helper(PyObject* source, wxPosition** obj)
2734 {
2735 if (source == Py_None) {
2736 **obj = wxPosition(-1,-1);
2737 return true;
2738 }
2739 return wxPyTwoIntItem_helper(source, obj, wxT("wxPosition"));
2740 }
2741
2742
2743
2744 bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
2745
2746 if (source == Py_None) {
2747 **obj = wxRealPoint(-1,-1);
2748 return true;
2749 }
2750
2751 // If source is an object instance then it may already be the right type
2752 if (wxPySwigInstance_Check(source)) {
2753 wxRealPoint* ptr;
2754 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRealPoint")))
2755 goto error;
2756 *obj = ptr;
2757 return true;
2758 }
2759 // otherwise a 2-tuple of floats is expected
2760 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
2761 PyObject* o1 = PySequence_GetItem(source, 0);
2762 PyObject* o2 = PySequence_GetItem(source, 1);
2763 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2764 Py_DECREF(o1);
2765 Py_DECREF(o2);
2766 goto error;
2767 }
2768 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
2769 Py_DECREF(o1);
2770 Py_DECREF(o2);
2771 return true;
2772 }
2773
2774 error:
2775 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
2776 return false;
2777 }
2778
2779
2780
2781 bool wxRect_helper(PyObject* source, wxRect** obj) {
2782
2783 if (source == Py_None) {
2784 **obj = wxRect(-1,-1,-1,-1);
2785 return true;
2786 }
2787
2788 // If source is an object instance then it may already be the right type
2789 if (wxPySwigInstance_Check(source)) {
2790 wxRect* ptr;
2791 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRect")))
2792 goto error;
2793 *obj = ptr;
2794 return true;
2795 }
2796 // otherwise a 4-tuple of integers is expected
2797 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
2798 PyObject* o1 = PySequence_GetItem(source, 0);
2799 PyObject* o2 = PySequence_GetItem(source, 1);
2800 PyObject* o3 = PySequence_GetItem(source, 2);
2801 PyObject* o4 = PySequence_GetItem(source, 3);
2802 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) ||
2803 !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
2804 Py_DECREF(o1);
2805 Py_DECREF(o2);
2806 Py_DECREF(o3);
2807 Py_DECREF(o4);
2808 goto error;
2809 }
2810 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
2811 PyInt_AsLong(o3), PyInt_AsLong(o4));
2812 Py_DECREF(o1);
2813 Py_DECREF(o2);
2814 Py_DECREF(o3);
2815 Py_DECREF(o4);
2816 return true;
2817 }
2818
2819 error:
2820 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
2821 return false;
2822 }
2823
2824
2825
2826 bool wxColour_helper(PyObject* source, wxColour** obj) {
2827
2828 if (source == Py_None) {
2829 **obj = wxNullColour;
2830 return true;
2831 }
2832
2833 // If source is an object instance then it may already be the right type
2834 if (wxPySwigInstance_Check(source)) {
2835 wxColour* ptr;
2836 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxColour")))
2837 goto error;
2838 *obj = ptr;
2839 return true;
2840 }
2841 // otherwise check for a string
2842 else if (PyString_Check(source) || PyUnicode_Check(source)) {
2843 wxString spec = Py2wxString(source);
2844 if (spec.GetChar(0) == '#' && spec.Length() == 7) { // It's #RRGGBB
2845 long red, green, blue;
2846 red = green = blue = 0;
2847 spec.Mid(1,2).ToLong(&red, 16);
2848 spec.Mid(3,2).ToLong(&green, 16);
2849 spec.Mid(5,2).ToLong(&blue, 16);
2850
2851 **obj = wxColour(red, green, blue);
2852 return true;
2853 }
2854 else { // it's a colour name
2855 **obj = wxColour(spec);
2856 return true;
2857 }
2858 }
2859 // last chance: 3-tuple or 4-tuple of integers is expected
2860 else if (PySequence_Check(source) && PyObject_Length(source) == 3) {
2861 PyObject* o1 = PySequence_GetItem(source, 0);
2862 PyObject* o2 = PySequence_GetItem(source, 1);
2863 PyObject* o3 = PySequence_GetItem(source, 2);
2864 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3)) {
2865 Py_DECREF(o1);
2866 Py_DECREF(o2);
2867 Py_DECREF(o3);
2868 goto error;
2869 }
2870 **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3));
2871 Py_DECREF(o1);
2872 Py_DECREF(o2);
2873 Py_DECREF(o3);
2874 return true;
2875 }
2876 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
2877 PyObject* o1 = PySequence_GetItem(source, 0);
2878 PyObject* o2 = PySequence_GetItem(source, 1);
2879 PyObject* o3 = PySequence_GetItem(source, 2);
2880 PyObject* o4 = PySequence_GetItem(source, 3);
2881 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
2882 Py_DECREF(o1);
2883 Py_DECREF(o2);
2884 Py_DECREF(o3);
2885 Py_DECREF(o4);
2886 goto error;
2887 }
2888 **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3), PyInt_AsLong(o4));
2889 Py_DECREF(o1);
2890 Py_DECREF(o2);
2891 Py_DECREF(o3);
2892 Py_DECREF(o4);
2893 return true;
2894 }
2895
2896 error:
2897 PyErr_SetString(PyExc_TypeError,
2898 "Expected a wxColour object, a string containing a colour name or '#RRGGBB', or a 3- or 4-tuple of integers.");
2899 return false;
2900 }
2901
2902
2903 bool wxColour_typecheck(PyObject* source) {
2904
2905 if (wxPySimple_typecheck(source, wxT("wxColour"), 3))
2906 return true;
2907
2908 if (PyString_Check(source) || PyUnicode_Check(source))
2909 return true;
2910
2911 return false;
2912 }
2913
2914
2915
2916 bool wxPoint2D_helper(PyObject* source, wxPoint2D** obj) {
2917
2918 if (source == Py_None) {
2919 **obj = wxPoint2D(-1,-1);
2920 return true;
2921 }
2922
2923 // If source is an object instance then it may already be the right type
2924 if (wxPySwigInstance_Check(source)) {
2925 wxPoint2D* ptr;
2926 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxPoint2D")))
2927 goto error;
2928 *obj = ptr;
2929 return true;
2930 }
2931 // otherwise a length-2 sequence of floats is expected
2932 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
2933 PyObject* o1 = PySequence_GetItem(source, 0);
2934 PyObject* o2 = PySequence_GetItem(source, 1);
2935 // This should really check for floats, not numbers -- but that would break code.
2936 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
2937 Py_DECREF(o1);
2938 Py_DECREF(o2);
2939 goto error;
2940 }
2941 **obj = wxPoint2D(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
2942 Py_DECREF(o1);
2943 Py_DECREF(o2);
2944 return true;
2945 }
2946 error:
2947 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wx.Point2D object.");
2948 return false;
2949 }
2950
2951
2952
2953 bool wxRect2D_helper(PyObject* source, wxRect2D** obj) {
2954
2955 if (source == Py_None) {
2956 **obj = wxRect2D(-1,-1,-1,-1);
2957 return true;
2958 }
2959
2960 // If source is an object instance then it may already be the right type
2961 if (wxPySwigInstance_Check(source)) {
2962 wxRect2D* ptr;
2963 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRect2D")))
2964 goto error;
2965 *obj = ptr;
2966 return true;
2967 }
2968 // otherwise a length-4 sequence of floats is expected
2969 if (PySequence_Check(source) && PySequence_Length(source) == 4) {
2970 PyObject* o1 = PySequence_GetItem(source, 0);
2971 PyObject* o2 = PySequence_GetItem(source, 1);
2972 PyObject* o3 = PySequence_GetItem(source, 2);
2973 PyObject* o4 = PySequence_GetItem(source, 3);
2974 // This should really check for floats, not numbers -- but that would break code.
2975 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) ||
2976 !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
2977 Py_DECREF(o1);
2978 Py_DECREF(o2);
2979 Py_DECREF(o3);
2980 Py_DECREF(o4);
2981 goto error;
2982 }
2983 **obj = wxRect2D(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2),
2984 PyFloat_AsDouble(o3), PyFloat_AsDouble(o4));
2985 Py_DECREF(o1);
2986 Py_DECREF(o2);
2987 Py_DECREF(o3);
2988 Py_DECREF(o4);
2989 return true;
2990 }
2991 error:
2992 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of floats or a wx.Rect2D object.");
2993 return false;
2994 }
2995
2996
2997 //----------------------------------------------------------------------
2998
2999 PyObject* wxArrayString2PyList_helper(const wxArrayString& arr)
3000 {
3001 PyObject* list = PyList_New(0);
3002 for (size_t i=0; i < arr.GetCount(); i++) {
3003 #if wxUSE_UNICODE
3004 PyObject* str = PyUnicode_FromWideChar(arr[i].c_str(), arr[i].Len());
3005 #else
3006 PyObject* str = PyString_FromStringAndSize(arr[i].c_str(), arr[i].Len());
3007 #endif
3008 PyList_Append(list, str);
3009 Py_DECREF(str);
3010 }
3011 return list;
3012 }
3013
3014
3015 PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr)
3016 {
3017 PyObject* list = PyList_New(0);
3018 for (size_t i=0; i < arr.GetCount(); i++) {
3019 PyObject* number = PyInt_FromLong(arr[i]);
3020 PyList_Append(list, number);
3021 Py_DECREF(number);
3022 }
3023 return list;
3024 }
3025
3026
3027 PyObject* wxArrayDouble2PyList_helper(const wxArrayDouble& arr)
3028 {
3029 PyObject* list = PyList_New(0);
3030 for (size_t i=0; i < arr.GetCount(); i++) {
3031 PyObject* number = PyFloat_FromDouble(arr[i]);
3032 PyList_Append(list, number);
3033 Py_DECREF(number);
3034 }
3035 return list;
3036 }
3037
3038
3039 //----------------------------------------------------------------------
3040 // wxPyImageHandler methods
3041 //
3042 // TODO: Switch these to use wxPython's standard macros and helper classes
3043 // for calling callbacks.
3044
3045 PyObject* wxPyImageHandler::m_DoCanRead_Name = NULL;
3046 PyObject* wxPyImageHandler::m_GetImageCount_Name = NULL;
3047 PyObject* wxPyImageHandler::m_LoadFile_Name = NULL;
3048 PyObject* wxPyImageHandler::m_SaveFile_Name = NULL;
3049
3050 PyObject* wxPyImageHandler::py_InputStream(wxInputStream* stream) {
3051 return wxPyConstructObject(new wxPyInputStream(stream),
3052 wxT("wxPyInputStream"), 0);
3053 }
3054
3055 PyObject* wxPyImageHandler::py_Image(wxImage* image) {
3056 return wxPyConstructObject(image, wxT("wxImage"), 0);
3057 }
3058
3059 PyObject* wxPyImageHandler::py_OutputStream(wxOutputStream* stream) {
3060 return wxPyConstructObject(stream, wxT("wxOutputStream"), 0);
3061 }
3062
3063 wxPyImageHandler::wxPyImageHandler():
3064 m_self(NULL)
3065 {
3066 if (!m_DoCanRead_Name) {
3067 m_DoCanRead_Name = PyString_FromString("DoCanRead");
3068 m_GetImageCount_Name = PyString_FromString("GetImageCount");
3069 m_LoadFile_Name = PyString_FromString("LoadFile");
3070 m_SaveFile_Name = PyString_FromString("SaveFile");
3071 }
3072 }
3073
3074 wxPyImageHandler::~wxPyImageHandler() {
3075 if (m_self) {
3076 Py_DECREF(m_self);
3077 m_self = NULL;
3078 }
3079 }
3080
3081 void wxPyImageHandler::_SetSelf(PyObject *self) {
3082 // should check here for isinstance(PyImageHandler) ??
3083 m_self = self;
3084 Py_INCREF(m_self);
3085 }
3086
3087 bool wxPyImageHandler::DoCanRead(wxInputStream& stream) {
3088 // check if our object has this method
3089 wxPyBlock_t blocked = wxPyBeginBlockThreads();
3090 if (!m_self || !PyObject_HasAttr(m_self, m_DoCanRead_Name)) {
3091 wxPyEndBlockThreads(blocked);
3092 return false;
3093 }
3094
3095 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_DoCanRead_Name,
3096 py_InputStream(&stream), NULL);
3097 bool retval = false;
3098 if (res) {
3099 retval = PyInt_AsLong(res);
3100 Py_DECREF(res);
3101 PyErr_Clear();
3102 }
3103 else
3104 PyErr_Print();
3105 wxPyEndBlockThreads(blocked);
3106 return retval;
3107 }
3108
3109 bool wxPyImageHandler::LoadFile( wxImage* image, wxInputStream& stream,
3110 bool verbose, int index ) {
3111 // check if our object has this method
3112 wxPyBlock_t blocked = wxPyBeginBlockThreads();
3113 if (!m_self || !PyObject_HasAttr(m_self, m_LoadFile_Name)) {
3114 wxPyEndBlockThreads(blocked);
3115 return false;
3116 }
3117 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_LoadFile_Name,
3118 py_Image(image),
3119 py_InputStream(&stream),
3120 PyInt_FromLong(verbose),
3121 PyInt_FromLong(index),
3122 NULL);
3123 bool retval = false;
3124 if (res) {
3125 retval = PyInt_AsLong(res);
3126 Py_DECREF(res);
3127 PyErr_Clear();
3128 } else
3129 PyErr_Print();
3130 wxPyEndBlockThreads(blocked);
3131 return retval;
3132 }
3133
3134 bool wxPyImageHandler::SaveFile( wxImage* image, wxOutputStream& stream,
3135 bool verbose ) {
3136 wxPyBlock_t blocked = wxPyBeginBlockThreads();
3137 if (!m_self || !PyObject_HasAttr(m_self, m_SaveFile_Name)) {
3138 wxPyEndBlockThreads(blocked);
3139 return false;
3140 }
3141 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_SaveFile_Name,
3142 py_Image(image),
3143 py_OutputStream(&stream),
3144 PyInt_FromLong(verbose),
3145 NULL);
3146 bool retval = false;
3147 if(res) {
3148 retval=PyInt_AsLong(res);
3149 Py_DECREF(res);
3150 PyErr_Clear();
3151 } else
3152 PyErr_Print();
3153 wxPyEndBlockThreads(blocked);
3154 return retval;
3155 }
3156
3157 int wxPyImageHandler::GetImageCount( wxInputStream& stream ) {
3158 wxPyBlock_t blocked = wxPyBeginBlockThreads();
3159 if (!m_self || !PyObject_HasAttr(m_self, m_GetImageCount_Name)) {
3160 wxPyEndBlockThreads(blocked);
3161 return 1;
3162 }
3163 PyObject *res=PyObject_CallMethodObjArgs(m_self, m_GetImageCount_Name,
3164 py_InputStream(&stream),
3165 NULL);
3166 int retval = 1;
3167 if(res) {
3168 retval=PyInt_AsLong(res);
3169 Py_DECREF(res);
3170 PyErr_Clear();
3171 } else
3172 PyErr_Print();
3173 wxPyEndBlockThreads(blocked);
3174 return retval;
3175 }
3176
3177
3178 //----------------------------------------------------------------------
3179 // Function to test if the Display (or whatever is the platform equivallent)
3180 // can be connected to. This is accessable from wxPython as a staticmethod of
3181 // wx.App called DisplayAvailable().
3182
3183
3184 bool wxPyTestDisplayAvailable()
3185 {
3186 #ifdef __WXGTK__
3187 Display* display;
3188 display = XOpenDisplay(NULL);
3189 if (display == NULL)
3190 return false;
3191 XCloseDisplay(display);
3192 return true;
3193 #endif
3194
3195 #ifdef __WXMAC__
3196 // This is adapted from Python's Mac/Modules/MacOS.c in the
3197 // MacOS_WMAvailable function.
3198 bool rv;
3199 ProcessSerialNumber psn;
3200
3201 /*
3202 ** This is a fairly innocuous call to make if we don't have a window
3203 ** manager, or if we have no permission to talk to it. It will print
3204 ** a message on stderr, but at least it won't abort the process.
3205 ** It appears the function caches the result itself, and it's cheap, so
3206 ** no need for us to cache.
3207 */
3208 #ifdef kCGNullDirectDisplay
3209 /* On 10.1 CGMainDisplayID() isn't available, and
3210 ** kCGNullDirectDisplay isn't defined.
3211 */
3212 if (CGMainDisplayID() == 0) {
3213 rv = false;
3214 } else
3215 #endif
3216 {
3217 // Also foreground the application on the first call as a side-effect.
3218 if (GetCurrentProcess(&psn) < 0 || SetFrontProcess(&psn) < 0) {
3219 rv = false;
3220 } else {
3221 rv = true;
3222 }
3223 }
3224 return rv;
3225 #endif
3226
3227 #ifdef __WXMSW__
3228 // TODO...
3229 return true;
3230 #endif
3231 }
3232
3233
3234 //----------------------------------------------------------------------
3235 //----------------------------------------------------------------------
3236
3237
3238
3239