1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Helper functions/classes for the wxPython extension module
7 // Created: 1-July-1997
9 // Copyright: (c) 1998 by Total Control Software
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
16 #include "wx/wxPython/wxPython_int.h"
17 #include "wx/wxPython/pyistream.h"
18 #include "wx/wxPython/swigver.h"
21 #include <wx/msw/private.h>
22 #include <wx/msw/winundef.h>
23 #include <wx/msw/msvcrt.h>
30 #include <gdk/gdkprivate.h>
31 #include <wx/gtk/win_gtk.h>
32 #define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \
33 GDK_WINDOW_XWINDOW(GTK_PIZZA((wxwin)->m_wxwindow)->bin_window) : \
34 GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
39 #include "wx/x11/privx.h"
40 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle())
44 #include <wx/mac/private.h>
47 #include <wx/clipbrd.h>
48 #include <wx/mimetype.h>
51 //----------------------------------------------------------------------
53 #if PYTHON_API_VERSION < 1009 && wxUSE_UNICODE
54 #error Python must support Unicode to use wxWindows Unicode
57 //----------------------------------------------------------------------
59 wxPyApp
* wxPythonApp
= NULL
; // Global instance of application object
60 bool wxPyDoCleanup
= false;
61 bool wxPyDoingCleanup
= false;
64 #ifdef WXP_WITH_THREAD
65 #if !wxPyUSE_GIL_STATE
66 struct wxPyThreadState
{
68 PyThreadState
* tstate
;
70 wxPyThreadState(unsigned long _tid
=0, PyThreadState
* _tstate
=NULL
)
71 : tid(_tid
), tstate(_tstate
) {}
74 #include <wx/dynarray.h>
75 WX_DECLARE_OBJARRAY(wxPyThreadState
, wxPyThreadStateArray
);
76 #include <wx/arrimpl.cpp>
77 WX_DEFINE_OBJARRAY(wxPyThreadStateArray
);
79 wxPyThreadStateArray
* wxPyTStates
= NULL
;
80 wxMutex
* wxPyTMutex
= NULL
;
86 #define DEFAULTENCODING_SIZE 64
87 static char wxPyDefaultEncoding
[DEFAULTENCODING_SIZE
] = "ascii";
89 static PyObject
* wxPython_dict
= NULL
;
90 static PyObject
* wxPyAssertionError
= NULL
;
91 static PyObject
* wxPyNoAppError
= NULL
;
93 PyObject
* wxPyPtrTypeMap
= NULL
;
96 #ifdef __WXMSW__ // If building for win32...
97 //----------------------------------------------------------------------
98 // This gets run when the DLL is loaded. We just need to save a handle.
99 //----------------------------------------------------------------------
103 HINSTANCE hinstDLL
, // handle to DLL module
104 DWORD fdwReason
, // reason for calling function
105 LPVOID lpvReserved
// reserved
108 // If wxPython is embedded in another wxWidgets app then
109 // the instance has already been set.
110 if (! wxGetInstance())
111 wxSetInstance(hinstDLL
);
116 //----------------------------------------------------------------------
117 // Classes for implementing the wxp main application shell.
118 //----------------------------------------------------------------------
120 IMPLEMENT_ABSTRACT_CLASS(wxPyApp
, wxApp
);
124 m_assertMode
= wxPYAPP_ASSERT_EXCEPTION
;
125 m_startupComplete
= false;
129 wxPyApp::~wxPyApp() {
131 wxApp::SetInstance(NULL
);
135 // This one isn't acutally called... We fake it with _BootstrapApp
136 bool wxPyApp::OnInit() {
141 int wxPyApp::MainLoop() {
144 DeletePendingObjects();
145 bool initialized
= wxTopLevelWindows
.GetCount() != 0;
147 if ( m_exitOnFrameDelete
== Later
) {
148 m_exitOnFrameDelete
= Yes
;
151 retval
= wxApp::MainLoop();
158 bool wxPyApp::OnInitGui() {
160 wxApp::OnInitGui(); // in this case always call the base class version
161 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
162 if (wxPyCBH_findCallback(m_myInst
, "OnInitGui"))
163 rval
= wxPyCBH_callCallback(m_myInst
, Py_BuildValue("()"));
164 wxPyEndBlockThreads(blocked
);
169 int wxPyApp::OnExit() {
171 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
172 if (wxPyCBH_findCallback(m_myInst
, "OnExit"))
173 rval
= wxPyCBH_callCallback(m_myInst
, Py_BuildValue("()"));
174 wxPyEndBlockThreads(blocked
);
175 wxApp::OnExit(); // in this case always call the base class version
181 void wxPyApp::OnAssert(const wxChar
*file
,
186 // if we're not fully initialized then just log the error
187 if (! m_startupComplete
) {
190 buf
.Printf(wxT("%s(%d): assert \"%s\" failed"),
200 // If the OnAssert is overloaded in the Python class then call it...
202 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
203 if ((found
= wxPyCBH_findCallback(m_myInst
, "OnAssert"))) {
204 PyObject
* fso
= wx2PyString(file
);
205 PyObject
* cso
= wx2PyString(file
);
208 mso
= wx2PyString(file
);
210 mso
= Py_None
; Py_INCREF(Py_None
);
212 wxPyCBH_callCallback(m_myInst
, Py_BuildValue("(OiOO)", fso
, line
, cso
, mso
));
217 wxPyEndBlockThreads(blocked
);
219 // ...otherwise do our own thing with it
222 if (m_assertMode
& wxPYAPP_ASSERT_SUPPRESS
)
225 // turn it into a Python exception?
226 if (m_assertMode
& wxPYAPP_ASSERT_EXCEPTION
) {
229 buf
.Printf(wxT("C++ assertion \"%s\" failed in %s(%d)"), cond
, file
, line
);
236 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
237 PyObject
* s
= wx2PyString(buf
);
238 PyErr_SetObject(wxPyAssertionError
, s
);
240 wxPyEndBlockThreads(blocked
);
242 // Now when control returns to whatever API wrapper was called from
243 // Python it should detect that an exception is set and will return
244 // NULL, signalling the exception to Python.
247 // Send it to the normal log destination, but only if
248 // not _DIALOG because it will call this too
249 if ( (m_assertMode
& wxPYAPP_ASSERT_LOG
) && !(m_assertMode
& wxPYAPP_ASSERT_DIALOG
)) {
252 buf
.Printf(wxT("%s(%d): assert \"%s\" failed"),
261 // do the normal wx assert dialog?
262 if (m_assertMode
& wxPYAPP_ASSERT_DIALOG
)
263 wxApp::OnAssert(file
, line
, cond
, msg
);
268 // For catching Apple Events
269 void wxPyApp::MacOpenFile(const wxString
&fileName
)
271 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
272 if (wxPyCBH_findCallback(m_myInst
, "MacOpenFile")) {
273 PyObject
* s
= wx2PyString(fileName
);
274 wxPyCBH_callCallback(m_myInst
, Py_BuildValue("(O)", s
));
277 wxPyEndBlockThreads(blocked
);
280 void wxPyApp::MacPrintFile(const wxString
&fileName
)
282 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
283 if (wxPyCBH_findCallback(m_myInst
, "MacPrintFile")) {
284 PyObject
* s
= wx2PyString(fileName
);
285 wxPyCBH_callCallback(m_myInst
, Py_BuildValue("(O)", s
));
288 wxPyEndBlockThreads(blocked
);
291 void wxPyApp::MacNewFile()
293 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
294 if (wxPyCBH_findCallback(m_myInst
, "MacNewFile"))
295 wxPyCBH_callCallback(m_myInst
, Py_BuildValue("()"));
296 wxPyEndBlockThreads(blocked
);
299 void wxPyApp::MacReopenApp()
301 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
302 if (wxPyCBH_findCallback(m_myInst
, "MacReopenApp"))
303 wxPyCBH_callCallback(m_myInst
, Py_BuildValue("()"));
304 wxPyEndBlockThreads(blocked
);
309 bool wxPyApp::GetMacSupportPCMenuShortcuts() {
311 return s_macSupportPCMenuShortcuts
;
318 long wxPyApp::GetMacAboutMenuItemId() {
320 return s_macAboutMenuItemId
;
327 long wxPyApp::GetMacPreferencesMenuItemId() {
329 return s_macPreferencesMenuItemId
;
336 long wxPyApp::GetMacExitMenuItemId() {
338 return s_macExitMenuItemId
;
345 wxString
wxPyApp::GetMacHelpMenuTitleName() {
347 return s_macHelpMenuTitleName
;
349 return wxEmptyString
;
354 void wxPyApp::SetMacSupportPCMenuShortcuts(bool val
) {
356 s_macSupportPCMenuShortcuts
= val
;
361 void wxPyApp::SetMacAboutMenuItemId(long val
) {
363 s_macAboutMenuItemId
= val
;
368 void wxPyApp::SetMacPreferencesMenuItemId(long val
) {
370 s_macPreferencesMenuItemId
= val
;
375 void wxPyApp::SetMacExitMenuItemId(long val
) {
377 s_macExitMenuItemId
= val
;
382 void wxPyApp::SetMacHelpMenuTitleName(const wxString
& val
) {
384 s_macHelpMenuTitleName
= val
;
389 // This finishes the initialization of wxWindows and then calls the OnInit
390 // that should be present in the derived (Python) class.
391 void wxPyApp::_BootstrapApp()
393 static bool haveInitialized
= false;
396 PyObject
* retval
= NULL
;
397 PyObject
* pyint
= NULL
;
400 // Only initialize wxWidgets once
401 if (! haveInitialized
) {
403 // Get any command-line args passed to this program from the sys module
406 blocked
= wxPyBeginBlockThreads();
408 PyObject
* sysargv
= PySys_GetObject("argv");
409 PyObject
* executable
= PySys_GetObject("executable");
411 if (sysargv
!= NULL
&& executable
!= NULL
) {
412 argc
= PyList_Size(sysargv
) + 1;
413 argv
= new char*[argc
+1];
414 argv
[0] = strdup(PyString_AsString(executable
));
416 for(x
=1; x
<argc
; x
++) {
417 PyObject
*pyArg
= PyList_GetItem(sysargv
, x
-1);
418 argv
[x
] = strdup(PyString_AsString(pyArg
));
422 wxPyEndBlockThreads(blocked
);
424 // Initialize wxWidgets
425 result
= wxEntryStart(argc
, argv
);
426 // wxApp takes ownership of the argv array, don't delete it here
428 blocked
= wxPyBeginBlockThreads();
430 PyErr_SetString(PyExc_SystemError
,
431 "wxEntryStart failed, unable to initialize wxWidgets!"
433 " (Is DISPLAY set properly?)"
439 // On wxGTK the locale will be changed to match the system settings,
440 // but Python before 2.4 needs to have LC_NUMERIC set to "C" in order
441 // for the floating point conversions and such to work right.
442 #if defined(__WXGTK__) && PY_VERSION_HEX < 0x02040000
443 setlocale(LC_NUMERIC
, "C");
446 // wxSystemOptions::SetOption(wxT("mac.textcontrol-use-mlte"), 1);
448 // The stock objects were all NULL when they were loaded into
449 // SWIG generated proxies, so re-init those now...
450 wxPy_ReinitStockObjects(3);
452 wxPyEndBlockThreads(blocked
);
453 haveInitialized
= true;
461 // It's now ok to generate exceptions for assertion errors.
462 wxPythonApp
->SetStartupComplete(true);
464 // Call the Python wxApp's OnInit function
465 blocked
= wxPyBeginBlockThreads();
466 if (wxPyCBH_findCallback(m_myInst
, "OnInit")) {
468 PyObject
* method
= m_myInst
.GetLastFound();
469 PyObject
* argTuple
= PyTuple_New(0);
470 retval
= PyEval_CallObject(method
, argTuple
);
476 pyint
= PyNumber_Int(retval
);
478 PyErr_SetString(PyExc_TypeError
, "OnInit should return a boolean value");
481 result
= PyInt_AS_LONG(pyint
);
484 // Is it okay if there is no OnInit? Probably so...
489 PyErr_SetString(PyExc_SystemExit
, "OnInit returned false, exiting...");
496 wxPyEndBlockThreads(blocked
);
499 //---------------------------------------------------------------------
500 //----------------------------------------------------------------------
504 static char* wxPyCopyCString(const wxChar
* src
)
506 wxWX2MBbuf buff
= (wxWX2MBbuf
)wxConvCurrent
->cWX2MB(src
);
507 size_t len
= strlen(buff
);
508 char* dest
= new char[len
+1];
514 static char* wxPyCopyCString(const char* src
) // we need a char version too
516 size_t len
= strlen(src
);
517 char* dest
= new char[len
+1];
523 static wxChar
* wxPyCopyWString(const char *src
)
525 //wxMB2WXbuf buff = wxConvCurrent->cMB2WX(src);
526 wxString
str(src
, *wxConvCurrent
);
527 return copystring(str
);
531 static wxChar
* wxPyCopyWString(const wxChar
*src
)
533 return copystring(src
);
539 inline const char* dropwx(const char* name
) {
540 if (name
[0] == 'w' && name
[1] == 'x')
546 //----------------------------------------------------------------------
548 // This function is called when the wx._core_ module is imported to do some
549 // initial setup. (Before there is a wxApp object.) The rest happens in
550 // wxPyApp::_BootstrapApp
551 void __wxPyPreStart(PyObject
* moduleDict
)
555 // wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
556 // | _CRTDBG_CHECK_ALWAYS_DF
557 // | _CRTDBG_DELAY_FREE_MEM_DF
561 #ifdef WXP_WITH_THREAD
562 #if wxPyUSE_GIL_STATE
563 PyEval_InitThreads();
565 PyEval_InitThreads();
566 wxPyTStates
= new wxPyThreadStateArray
;
567 wxPyTMutex
= new wxMutex
;
569 // Save the current (main) thread state in our array
570 PyThreadState
* tstate
= wxPyBeginAllowThreads();
571 wxPyEndAllowThreads(tstate
);
575 // Ensure that the build options in the DLL (or whatever) match this build
576 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "wxPython");
578 // Init the stock objects to a non-NULL value so SWIG doesn't create them as None
579 wxPy_ReinitStockObjects(1);
581 wxInitAllImageHandlers();
586 void __wxPyCleanup() {
587 wxPyDoingCleanup
= true;
589 wxPyDoCleanup
= false;
592 #ifdef WXP_WITH_THREAD
593 #if !wxPyUSE_GIL_STATE
596 wxPyTStates
->Empty();
604 // Save a reference to the dictionary of the wx._core module, and inject
605 // a few more things into it.
606 PyObject
* __wxPySetDictionary(PyObject
* /* self */, PyObject
* args
)
609 if (!PyArg_ParseTuple(args
, "O", &wxPython_dict
))
612 if (!PyDict_Check(wxPython_dict
)) {
613 PyErr_SetString(PyExc_TypeError
,
614 "_wxPySetDictionary must have dictionary object!");
618 if (! wxPyPtrTypeMap
)
619 wxPyPtrTypeMap
= PyDict_New();
620 PyDict_SetItemString(wxPython_dict
, "__wxPyPtrTypeMap", wxPyPtrTypeMap
);
622 // Create an exception object to use for wxASSERTions
623 wxPyAssertionError
= PyErr_NewException("wx._core.PyAssertionError",
624 PyExc_AssertionError
, NULL
);
625 PyDict_SetItemString(wxPython_dict
, "PyAssertionError", wxPyAssertionError
);
627 // Create an exception object to use when the app object hasn't been created yet
628 wxPyNoAppError
= PyErr_NewException("wx._core.PyNoAppError",
629 PyExc_RuntimeError
, NULL
);
630 PyDict_SetItemString(wxPython_dict
, "PyNoAppError", wxPyNoAppError
);
635 #define wxPlatform "__WXMOTIF__"
636 #define wxPlatName "wxMotif"
639 #define wxPlatform "__WXX11__"
640 #define wxPlatName "wxX11"
643 #define wxPlatform "__WXGTK__"
644 #define wxPlatName "wxGTK"
647 #define wxPlatform "__WXMSW__"
648 #define wxPlatName "wxMSW"
651 #define wxPlatform "__WXMAC__"
652 #define wxPlatName "wxMac"
661 // These should be deprecated in favor of the PlatformInfo tuple built below...
662 PyDict_SetItemString(wxPython_dict
, "Platform", PyString_FromString(wxPlatform
));
663 PyDict_SetItemString(wxPython_dict
, "USE_UNICODE", PyInt_FromLong(wxUSE_UNICODE
));
664 PyDict_SetItemString(wxPython_dict
, "__WXDEBUG__", PyInt_FromLong(wxdebug
));
666 // Make a tuple of strings that gives more info about the platform.
667 PyObject
* PlatInfo
= PyList_New(0);
670 #define _AddInfoString(st) \
671 obj = PyString_FromString(st); \
672 PyList_Append(PlatInfo, obj); \
675 _AddInfoString(wxPlatform
);
676 _AddInfoString(wxPlatName
);
678 _AddInfoString("unicode");
680 _AddInfoString("ansi");
684 _AddInfoString("gtk2");
686 _AddInfoString("gtk1");
690 _AddInfoString("wx-assertions-on");
692 _AddInfoString("wx-assertions-off");
694 _AddInfoString(wxPy_SWIG_VERSION
);
696 #undef _AddInfoString
698 PyObject
* PlatInfoTuple
= PyList_AsTuple(PlatInfo
);
700 PyDict_SetItemString(wxPython_dict
, "PlatformInfo", PlatInfoTuple
);
707 //---------------------------------------------------------------------------
709 // The stock objects are no longer created when the wx._core_ module is
710 // imported, but only after the app object has been created. The
711 // wxPy_ReinitStockObjects function will be called 3 times to pass the stock
712 // objects though various stages of evolution:
714 // pass 1: Set all the pointers to a non-NULL value so the Python proxy
715 // object will be created (otherwise SWIG will just use None.)
717 // pass 2: After the module has been imported and the python proxys have
718 // been created, then set the __class__ to be _wxPyUnbornObject so
719 // it will catch any access to the object and will raise an exception.
721 // pass 3: Finally, from BootstrapApp patch things up so the stock objects
725 PyObject
* __wxPyFixStockObjects(PyObject
* /* self */, PyObject
* args
)
727 wxPy_ReinitStockObjects(2);
732 static void rsoPass2(const char* name
)
734 static PyObject
* unbornObjectClass
= NULL
;
737 if (unbornObjectClass
== NULL
) {
738 unbornObjectClass
= PyDict_GetItemString(wxPython_dict
, "_wxPyUnbornObject");
739 Py_INCREF(unbornObjectClass
);
742 // Find the object instance
743 obj
= PyDict_GetItemString(wxPython_dict
, (char*)dropwx(name
));
744 wxCHECK_RET(obj
!= NULL
, wxT("Unable to find stock object"));
745 wxCHECK_RET(wxPySwigInstance_Check(obj
), wxT("Not a swig instance"));
748 PyObject_SetAttrString(obj
, "__class__", unbornObjectClass
);
752 static void rsoPass3(const char* name
, const char* classname
, void* ptr
)
758 // Find the object instance
759 obj
= PyDict_GetItemString(wxPython_dict
, (char*)dropwx(name
));
760 wxCHECK_RET(obj
!= NULL
, wxT("Unable to find stock object"));
761 wxCHECK_RET(wxPySwigInstance_Check(obj
), wxT("Not a swig instance"));
763 // Find the class object and put it back in the instance
764 classobj
= PyDict_GetItemString(wxPython_dict
, (char*)dropwx(classname
));
765 wxCHECK_RET(classobj
!= NULL
, wxT("Unable to find stock class object"));
766 PyObject_SetAttrString(obj
, "__class__", classobj
);
768 // Rebuild the .this swigified pointer with the new value of the C++ pointer
769 ptrobj
= wxPyMakeSwigPtr(ptr
, wxString(classname
, *wxConvCurrent
));
770 PyObject_SetAttrString(obj
, "this", ptrobj
);
776 void wxPy_ReinitStockObjects(int pass
)
779 // If there is already an App object then wxPython is probably embedded in
780 // a wx C++ application, so there is no need to do all this.
781 static bool embedded
= false;
782 if ((pass
== 1 || pass
== 2) && wxTheApp
) {
786 if (pass
== 3 && embedded
)
790 #define REINITOBJ(name, classname) \
791 if (pass == 1) { name = (classname*)0xC0C0C0C0; } \
792 else if (pass == 2) { rsoPass2(#name); } \
793 else if (pass == 3) { rsoPass3(#name, #classname, (void*)name); }
796 #define REINITOBJ2(name, classname) \
798 else if (pass == 2) { rsoPass2(#name); } \
799 else if (pass == 3) { rsoPass3(#name, #classname, (void*)&name); }
802 REINITOBJ(wxNORMAL_FONT
, wxFont
);
803 REINITOBJ(wxSMALL_FONT
, wxFont
);
804 REINITOBJ(wxITALIC_FONT
, wxFont
);
805 REINITOBJ(wxSWISS_FONT
, wxFont
);
807 REINITOBJ(wxRED_PEN
, wxPen
);
808 REINITOBJ(wxCYAN_PEN
, wxPen
);
809 REINITOBJ(wxGREEN_PEN
, wxPen
);
810 REINITOBJ(wxBLACK_PEN
, wxPen
);
811 REINITOBJ(wxWHITE_PEN
, wxPen
);
812 REINITOBJ(wxTRANSPARENT_PEN
, wxPen
);
813 REINITOBJ(wxBLACK_DASHED_PEN
, wxPen
);
814 REINITOBJ(wxGREY_PEN
, wxPen
);
815 REINITOBJ(wxMEDIUM_GREY_PEN
, wxPen
);
816 REINITOBJ(wxLIGHT_GREY_PEN
, wxPen
);
818 REINITOBJ(wxBLUE_BRUSH
, wxBrush
);
819 REINITOBJ(wxGREEN_BRUSH
, wxBrush
);
820 REINITOBJ(wxWHITE_BRUSH
, wxBrush
);
821 REINITOBJ(wxBLACK_BRUSH
, wxBrush
);
822 REINITOBJ(wxTRANSPARENT_BRUSH
, wxBrush
);
823 REINITOBJ(wxCYAN_BRUSH
, wxBrush
);
824 REINITOBJ(wxRED_BRUSH
, wxBrush
);
825 REINITOBJ(wxGREY_BRUSH
, wxBrush
);
826 REINITOBJ(wxMEDIUM_GREY_BRUSH
, wxBrush
);
827 REINITOBJ(wxLIGHT_GREY_BRUSH
, wxBrush
);
829 REINITOBJ(wxBLACK
, wxColour
);
830 REINITOBJ(wxWHITE
, wxColour
);
831 REINITOBJ(wxRED
, wxColour
);
832 REINITOBJ(wxBLUE
, wxColour
);
833 REINITOBJ(wxGREEN
, wxColour
);
834 REINITOBJ(wxCYAN
, wxColour
);
835 REINITOBJ(wxLIGHT_GREY
, wxColour
);
837 REINITOBJ(wxSTANDARD_CURSOR
, wxCursor
);
838 REINITOBJ(wxHOURGLASS_CURSOR
, wxCursor
);
839 REINITOBJ(wxCROSS_CURSOR
, wxCursor
);
841 REINITOBJ2(wxNullBitmap
, wxBitmap
);
842 REINITOBJ2(wxNullIcon
, wxIcon
);
843 REINITOBJ2(wxNullCursor
, wxCursor
);
844 REINITOBJ2(wxNullPen
, wxPen
);
845 REINITOBJ2(wxNullBrush
, wxBrush
);
846 REINITOBJ2(wxNullPalette
, wxPalette
);
847 REINITOBJ2(wxNullFont
, wxFont
);
848 REINITOBJ2(wxNullColour
, wxColour
);
850 REINITOBJ(wxTheFontList
, wxFontList
);
851 REINITOBJ(wxThePenList
, wxPenList
);
852 REINITOBJ(wxTheBrushList
, wxBrushList
);
853 REINITOBJ(wxTheColourDatabase
, wxColourDatabase
);
856 REINITOBJ2(wxDefaultValidator
, wxValidator
);
857 REINITOBJ2(wxNullImage
, wxImage
);
858 REINITOBJ2(wxNullAcceleratorTable
, wxAcceleratorTable
);
864 //---------------------------------------------------------------------------
866 // Check for existence of a wxApp, setting an exception if there isn't one.
867 // This doesn't need to aquire the GIL because it should only be called from
868 // an %exception before the lock is released.
870 bool wxPyCheckForApp() {
871 if (wxTheApp
!= NULL
)
874 PyErr_SetString(wxPyNoAppError
, "The wx.App object must be created first!");
879 //---------------------------------------------------------------------------
881 void wxPyUserData_dtor(wxPyUserData
* self
) {
882 if (! wxPyDoingCleanup
) {
883 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
884 Py_DECREF(self
->m_obj
);
886 wxPyEndBlockThreads(blocked
);
891 void wxPyClientData_dtor(wxPyClientData
* self
) {
892 if (! wxPyDoingCleanup
) { // Don't do it during cleanup as Python
893 // may have already garbage collected the object...
894 if (self
->m_incRef
) {
895 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
896 Py_DECREF(self
->m_obj
);
897 wxPyEndBlockThreads(blocked
);
905 // This is called when an OOR controled object is being destroyed. Although
906 // the C++ object is going away there is no way to force the Python object
907 // (and all references to it) to die too. This causes problems (crashes) in
908 // wxPython when a python shadow object attempts to call a C++ method using
909 // the now bogus pointer... So to try and prevent this we'll do a little black
910 // magic and change the class of the python instance to a class that will
911 // raise an exception for any attempt to call methods with it. See
912 // _wxPyDeadObject in _core_ex.py for the implementation of this class.
913 void wxPyOORClientData_dtor(wxPyOORClientData
* self
) {
915 static PyObject
* deadObjectClass
= NULL
;
917 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
918 if (deadObjectClass
== NULL
) {
919 deadObjectClass
= PyDict_GetItemString(wxPython_dict
, "_wxPyDeadObject");
920 // TODO: Can not wxASSERT here because inside a wxPyBeginBlock Threads,
921 // will lead to a deadlock when it tries to aquire the GIL again.
922 //wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!"));
923 Py_INCREF(deadObjectClass
);
927 // Only if there is more than one reference to the object and we are
928 // holding the OOR reference:
929 if ( !wxPyDoingCleanup
&& self
->m_obj
->ob_refcnt
> 1 && self
->m_incRef
) {
930 // bool isInstance = wxPyInstance_Check(self->m_obj);
932 //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!"));
934 // Call __del__, if there is one.
935 PyObject
* func
= PyObject_GetAttrString(self
->m_obj
, "__del__");
937 PyObject
* rv
= PyObject_CallMethod(self
->m_obj
, "__del__", NULL
);
941 if (PyErr_Occurred())
942 PyErr_Clear(); // just ignore it for now
945 PyObject
* dict
= PyObject_GetAttrString(self
->m_obj
, "__dict__");
947 // Clear the instance's dictionary
950 // put the name of the old class into the instance, and then reset the
951 // class to be the dead class.
952 PyObject
* klass
= PyObject_GetAttrString(self
->m_obj
, "__class__");
953 PyObject
* name
= PyObject_GetAttrString(klass
, "__name__");
954 PyDict_SetItemString(dict
, "_name", name
);
955 PyObject_SetAttrString(self
->m_obj
, "__class__", deadObjectClass
);
956 //Py_INCREF(deadObjectClass);
962 // m_obj is DECREF'd in the base class dtor...
963 wxPyEndBlockThreads(blocked
);
967 //---------------------------------------------------------------------------
968 // Stuff used by OOR to find the right wxPython class type to return and to
972 // The pointer type map is used when the "pointer" type name generated by SWIG
973 // is not the same as the shadow class name, for example wxPyTreeCtrl
974 // vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++,
975 // so we'll just make it a Python dictionary in the wx module's namespace.
976 // (See __wxSetDictionary)
977 void wxPyPtrTypeMap_Add(const char* commonName
, const char* ptrName
) {
978 if (! wxPyPtrTypeMap
)
979 wxPyPtrTypeMap
= PyDict_New();
980 PyDict_SetItemString(wxPyPtrTypeMap
,
982 PyString_FromString((char*)ptrName
));
988 PyObject
* wxPyMake_wxObject(wxObject
* source
, bool setThisOwn
, bool checkEvtHandler
) {
989 PyObject
* target
= NULL
;
990 bool isEvtHandler
= false;
991 bool isSizer
= false;
994 // If it's derived from wxEvtHandler then there may
995 // already be a pointer to a Python object that we can use
997 if (checkEvtHandler
&& wxIsKindOf(source
, wxEvtHandler
)) {
999 wxEvtHandler
* eh
= (wxEvtHandler
*)source
;
1000 wxPyOORClientData
* data
= (wxPyOORClientData
*)eh
->GetClientObject();
1002 target
= data
->m_obj
;
1008 // Also check for wxSizer
1009 if (!target
&& wxIsKindOf(source
, wxSizer
)) {
1011 wxSizer
* sz
= (wxSizer
*)source
;
1012 wxPyOORClientData
* data
= (wxPyOORClientData
*)sz
->GetClientObject();
1014 target
= data
->m_obj
;
1021 // Otherwise make it the old fashioned way by making a new shadow
1022 // object and putting this pointer in it. Look up the class
1023 // heirarchy until we find a class name that is located in the
1025 const wxClassInfo
* info
= source
->GetClassInfo();
1026 wxString name
= info
->GetClassName();
1027 bool exists
= wxPyCheckSwigType(name
);
1028 while (info
&& !exists
) {
1029 info
= info
->GetBaseClass1();
1030 name
= info
->GetClassName();
1031 exists
= wxPyCheckSwigType(name
);
1034 target
= wxPyConstructObject((void*)source
, name
, setThisOwn
);
1035 if (target
&& isEvtHandler
)
1036 ((wxEvtHandler
*)source
)->SetClientObject(new wxPyOORClientData(target
));
1037 if (target
&& isSizer
)
1038 ((wxSizer
*)source
)->SetClientObject(new wxPyOORClientData(target
));
1040 wxString
msg(wxT("wxPython class not found for "));
1041 msg
+= source
->GetClassInfo()->GetClassName();
1042 PyErr_SetString(PyExc_NameError
, msg
.mbc_str());
1046 } else { // source was NULL so return None.
1047 Py_INCREF(Py_None
); target
= Py_None
;
1053 PyObject
* wxPyMake_wxSizer(wxSizer
* source
, bool setThisOwn
) {
1055 return wxPyMake_wxObject(source
, setThisOwn
);
1059 //---------------------------------------------------------------------------
1062 #ifdef WXP_WITH_THREAD
1063 #if !wxPyUSE_GIL_STATE
1066 unsigned long wxPyGetCurrentThreadId() {
1067 return wxThread::GetCurrentId();
1070 static wxPyThreadState gs_shutdownTState
;
1073 wxPyThreadState
* wxPyGetThreadState() {
1074 if (wxPyTMutex
== NULL
) // Python is shutting down...
1075 return &gs_shutdownTState
;
1077 unsigned long ctid
= wxPyGetCurrentThreadId();
1078 wxPyThreadState
* tstate
= NULL
;
1081 for(size_t i
=0; i
< wxPyTStates
->GetCount(); i
++) {
1082 wxPyThreadState
& info
= wxPyTStates
->Item(i
);
1083 if (info
.tid
== ctid
) {
1088 wxPyTMutex
->Unlock();
1089 wxASSERT_MSG(tstate
, wxT("PyThreadState should not be NULL!"));
1095 void wxPySaveThreadState(PyThreadState
* tstate
) {
1096 if (wxPyTMutex
== NULL
) { // Python is shutting down, assume a single thread...
1097 gs_shutdownTState
.tstate
= tstate
;
1100 unsigned long ctid
= wxPyGetCurrentThreadId();
1102 for(size_t i
=0; i
< wxPyTStates
->GetCount(); i
++) {
1103 wxPyThreadState
& info
= wxPyTStates
->Item(i
);
1104 if (info
.tid
== ctid
) {
1106 if (info
.tstate
!= tstate
)
1107 wxLogMessage("*** tstate mismatch!???");
1109 info
.tstate
= tstate
; // allow for transient tstates
1110 // Normally it will never change, but apparently COM callbacks
1111 // (i.e. ActiveX controls) will (incorrectly IMHO) use a transient
1112 // tstate which will then be garbage the next time we try to use
1115 wxPyTMutex
->Unlock();
1119 // not found, so add it...
1120 wxPyTStates
->Add(new wxPyThreadState(ctid
, tstate
));
1121 wxPyTMutex
->Unlock();
1129 // Calls from Python to wxWindows code are wrapped in calls to these
1132 PyThreadState
* wxPyBeginAllowThreads() {
1133 #ifdef WXP_WITH_THREAD
1134 PyThreadState
* saved
= PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS;
1135 #if !wxPyUSE_GIL_STATE
1136 wxPySaveThreadState(saved
);
1144 void wxPyEndAllowThreads(PyThreadState
* saved
) {
1145 #ifdef WXP_WITH_THREAD
1146 PyEval_RestoreThread(saved
); // Py_END_ALLOW_THREADS;
1152 // Calls from wxWindows back to Python code, or even any PyObject
1153 // manipulations, PyDECREF's and etc. are wrapped in calls to these functions:
1155 wxPyBlock_t
wxPyBeginBlockThreads() {
1156 #ifdef WXP_WITH_THREAD
1157 if (! Py_IsInitialized()) {
1158 return (wxPyBlock_t
)0;
1160 #if wxPyUSE_GIL_STATE
1161 PyGILState_STATE state
= PyGILState_Ensure();
1164 PyThreadState
*current
= _PyThreadState_Current
;
1166 // Only block if there wasn't already a tstate, or if the current one is
1167 // not the one we are wanting to change to. This should prevent deadlock
1168 // if there are nested calls to wxPyBeginBlockThreads
1169 wxPyBlock_t blocked
= false;
1170 wxPyThreadState
* tstate
= wxPyGetThreadState();
1171 if (current
!= tstate
->tstate
) {
1172 PyEval_RestoreThread(tstate
->tstate
);
1178 return (wxPyBlock_t
)0;
1183 void wxPyEndBlockThreads(wxPyBlock_t blocked
) {
1184 #ifdef WXP_WITH_THREAD
1185 if (! Py_IsInitialized()) {
1188 #if wxPyUSE_GIL_STATE
1189 PyGILState_Release(blocked
);
1191 // Only unblock if we blocked in the last call to wxPyBeginBlockThreads.
1192 // The value of blocked passed in needs to be the same as that returned
1193 // from wxPyBeginBlockThreads at the same nesting level.
1195 PyEval_SaveThread();
1202 //---------------------------------------------------------------------------
1203 // wxPyInputStream and wxPyCBInputStream methods
1206 void wxPyInputStream::close() {
1207 /* do nothing for now */
1210 void wxPyInputStream::flush() {
1211 /* do nothing for now */
1214 bool wxPyInputStream::eof() {
1216 return m_wxis
->Eof();
1221 wxPyInputStream::~wxPyInputStream() {
1229 PyObject
* wxPyInputStream::read(int size
) {
1230 PyObject
* obj
= NULL
;
1232 const int BUFSIZE
= 1024;
1234 // check if we have a real wxInputStream to work with
1236 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1237 PyErr_SetString(PyExc_IOError
, "no valid C-wxInputStream");
1238 wxPyEndBlockThreads(blocked
);
1243 // read while bytes are available on the stream
1244 while ( m_wxis
->CanRead() ) {
1245 m_wxis
->Read(buf
.GetAppendBuf(BUFSIZE
), BUFSIZE
);
1246 buf
.UngetAppendBuf(m_wxis
->LastRead());
1249 } else { // Read only size number of characters
1250 m_wxis
->Read(buf
.GetWriteBuf(size
), size
);
1251 buf
.UngetWriteBuf(m_wxis
->LastRead());
1255 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1256 wxStreamError err
= m_wxis
->GetLastError();
1257 if (err
!= wxSTREAM_NO_ERROR
&& err
!= wxSTREAM_EOF
) {
1258 PyErr_SetString(PyExc_IOError
,"IOError in wxInputStream");
1261 // We use only strings for the streams, not unicode
1262 obj
= PyString_FromStringAndSize(buf
, buf
.GetDataLen());
1264 wxPyEndBlockThreads(blocked
);
1269 PyObject
* wxPyInputStream::readline(int size
) {
1270 PyObject
* obj
= NULL
;
1275 // check if we have a real wxInputStream to work with
1277 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1278 PyErr_SetString(PyExc_IOError
,"no valid C-wxInputStream");
1279 wxPyEndBlockThreads(blocked
);
1283 // read until \n or byte limit reached
1284 for (i
=ch
=0; (ch
!= '\n') && (m_wxis
->CanRead()) && ((size
< 0) || (i
< size
)); i
++) {
1285 ch
= m_wxis
->GetC();
1290 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1291 wxStreamError err
= m_wxis
->GetLastError();
1292 if (err
!= wxSTREAM_NO_ERROR
&& err
!= wxSTREAM_EOF
) {
1293 PyErr_SetString(PyExc_IOError
,"IOError in wxInputStream");
1296 // We use only strings for the streams, not unicode
1297 obj
= PyString_FromStringAndSize((char*)buf
.GetData(), buf
.GetDataLen());
1299 wxPyEndBlockThreads(blocked
);
1304 PyObject
* wxPyInputStream::readlines(int sizehint
) {
1307 // check if we have a real wxInputStream to work with
1309 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1310 PyErr_SetString(PyExc_IOError
,"no valid C-wxInputStream");
1311 wxPyEndBlockThreads(blocked
);
1316 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1317 pylist
= PyList_New(0);
1318 wxPyEndBlockThreads(blocked
);
1321 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1323 wxPyEndBlockThreads(blocked
);
1327 // read sizehint bytes or until EOF
1329 for (i
=0; (m_wxis
->CanRead()) && ((sizehint
< 0) || (i
< sizehint
));) {
1330 PyObject
* s
= this->readline();
1332 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1334 wxPyEndBlockThreads(blocked
);
1337 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1338 PyList_Append(pylist
, s
);
1339 i
+= PyString_Size(s
);
1340 wxPyEndBlockThreads(blocked
);
1344 wxStreamError err
= m_wxis
->GetLastError();
1345 if (err
!= wxSTREAM_NO_ERROR
&& err
!= wxSTREAM_EOF
) {
1346 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1348 PyErr_SetString(PyExc_IOError
,"IOError in wxInputStream");
1349 wxPyEndBlockThreads(blocked
);
1357 void wxPyInputStream::seek(int offset
, int whence
) {
1359 m_wxis
->SeekI(offset
, wxSeekMode(whence
));
1362 int wxPyInputStream::tell(){
1364 return m_wxis
->TellI();
1371 wxPyCBInputStream::wxPyCBInputStream(PyObject
*r
, PyObject
*s
, PyObject
*t
, bool block
)
1372 : wxInputStream(), m_read(r
), m_seek(s
), m_tell(t
), m_block(block
)
1375 wxPyCBInputStream::wxPyCBInputStream(const wxPyCBInputStream
& other
)
1377 m_read
= other
.m_read
;
1378 m_seek
= other
.m_seek
;
1379 m_tell
= other
.m_tell
;
1380 m_block
= other
.m_block
;
1387 wxPyCBInputStream::~wxPyCBInputStream() {
1388 wxPyBlock_t blocked
;
1389 if (m_block
) blocked
= wxPyBeginBlockThreads();
1393 if (m_block
) wxPyEndBlockThreads(blocked
);
1397 wxPyCBInputStream
* wxPyCBInputStream::create(PyObject
*py
, bool block
) {
1398 wxPyBlock_t blocked
;
1399 if (block
) blocked
= wxPyBeginBlockThreads();
1401 PyObject
* read
= getMethod(py
, "read");
1402 PyObject
* seek
= getMethod(py
, "seek");
1403 PyObject
* tell
= getMethod(py
, "tell");
1406 PyErr_SetString(PyExc_TypeError
, "Not a file-like object");
1410 if (block
) wxPyEndBlockThreads(blocked
);
1414 if (block
) wxPyEndBlockThreads(blocked
);
1415 return new wxPyCBInputStream(read
, seek
, tell
, block
);
1419 wxPyCBInputStream
* wxPyCBInputStream_create(PyObject
*py
, bool block
) {
1420 return wxPyCBInputStream::create(py
, block
);
1423 wxPyCBInputStream
* wxPyCBInputStream_copy(wxPyCBInputStream
* other
) {
1424 return new wxPyCBInputStream(*other
);
1427 PyObject
* wxPyCBInputStream::getMethod(PyObject
* py
, char* name
) {
1428 if (!PyObject_HasAttrString(py
, name
))
1430 PyObject
* o
= PyObject_GetAttrString(py
, name
);
1431 if (!PyMethod_Check(o
) && !PyCFunction_Check(o
)) {
1439 wxFileOffset
wxPyCBInputStream::GetLength() const {
1440 wxPyCBInputStream
* self
= (wxPyCBInputStream
*)this; // cast off const
1441 if (m_seek
&& m_tell
) {
1442 wxFileOffset temp
= self
->OnSysTell();
1443 wxFileOffset ret
= self
->OnSysSeek(0, wxFromEnd
);
1444 self
->OnSysSeek(temp
, wxFromStart
);
1448 return wxInvalidOffset
;
1452 size_t wxPyCBInputStream::OnSysRead(void *buffer
, size_t bufsize
) {
1456 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1457 PyObject
* arglist
= Py_BuildValue("(i)", bufsize
);
1458 PyObject
* result
= PyEval_CallObject(m_read
, arglist
);
1462 if ((result
!= NULL
) && PyString_Check(result
)) {
1463 o
= PyString_Size(result
);
1465 m_lasterror
= wxSTREAM_EOF
;
1468 memcpy((char*)buffer
, PyString_AsString(result
), o
); // strings only, not unicode...
1473 m_lasterror
= wxSTREAM_READ_ERROR
;
1474 wxPyEndBlockThreads(blocked
);
1478 size_t wxPyCBInputStream::OnSysWrite(const void *buffer
, size_t bufsize
) {
1479 m_lasterror
= wxSTREAM_WRITE_ERROR
;
1484 wxFileOffset
wxPyCBInputStream::OnSysSeek(wxFileOffset off
, wxSeekMode mode
) {
1485 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1486 PyObject
* arglist
= PyTuple_New(2);
1488 if (sizeof(wxFileOffset
) > sizeof(long))
1489 // wxFileOffset is a 64-bit value...
1490 PyTuple_SET_ITEM(arglist
, 0, PyLong_FromLongLong(off
));
1492 PyTuple_SET_ITEM(arglist
, 0, PyInt_FromLong(off
));
1494 PyTuple_SET_ITEM(arglist
, 1, PyInt_FromLong(mode
));
1497 PyObject
* result
= PyEval_CallObject(m_seek
, arglist
);
1500 wxPyEndBlockThreads(blocked
);
1505 wxFileOffset
wxPyCBInputStream::OnSysTell() const {
1506 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1507 PyObject
* arglist
= Py_BuildValue("()");
1508 PyObject
* result
= PyEval_CallObject(m_tell
, arglist
);
1511 if (result
!= NULL
) {
1512 if (PyLong_Check(result
))
1513 o
= PyLong_AsLongLong(result
);
1515 o
= PyInt_AsLong(result
);
1518 wxPyEndBlockThreads(blocked
);
1522 //----------------------------------------------------------------------
1524 IMPLEMENT_ABSTRACT_CLASS(wxPyCallback
, wxObject
);
1526 wxPyCallback::wxPyCallback(PyObject
* func
) {
1531 wxPyCallback::wxPyCallback(const wxPyCallback
& other
) {
1532 m_func
= other
.m_func
;
1536 wxPyCallback::~wxPyCallback() {
1537 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1539 wxPyEndBlockThreads(blocked
);
1543 #define wxPy_PRECALLINIT "_preCallInit"
1544 #define wxPy_POSTCALLCLEANUP "_postCallCleanup"
1546 // This function is used for all events destined for Python event handlers.
1547 void wxPyCallback::EventThunker(wxEvent
& event
) {
1548 wxPyCallback
* cb
= (wxPyCallback
*)event
.m_callbackUserData
;
1549 PyObject
* func
= cb
->m_func
;
1553 bool checkSkip
= false;
1555 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1556 wxString className
= event
.GetClassInfo()->GetClassName();
1558 // If the event is one of these types then pass the original
1559 // event object instead of the one passed to us.
1560 if ( className
== wxT("wxPyEvent") ) {
1561 arg
= ((wxPyEvent
*)&event
)->GetSelf();
1562 checkSkip
= ((wxPyEvent
*)&event
)->GetCloned();
1564 else if ( className
== wxT("wxPyCommandEvent") ) {
1565 arg
= ((wxPyCommandEvent
*)&event
)->GetSelf();
1566 checkSkip
= ((wxPyCommandEvent
*)&event
)->GetCloned();
1569 arg
= wxPyConstructObject((void*)&event
, className
);
1575 // "intern" the pre/post method names to speed up the HasAttr
1576 static PyObject
* s_preName
= NULL
;
1577 static PyObject
* s_postName
= NULL
;
1578 if (s_preName
== NULL
) {
1579 s_preName
= PyString_FromString(wxPy_PRECALLINIT
);
1580 s_postName
= PyString_FromString(wxPy_POSTCALLCLEANUP
);
1583 // Check if the event object needs some preinitialization
1584 if (PyObject_HasAttr(arg
, s_preName
)) {
1585 result
= PyObject_CallMethodObjArgs(arg
, s_preName
, arg
, NULL
);
1587 Py_DECREF(result
); // result is ignored, but we still need to decref it
1588 PyErr_Clear(); // Just in case...
1594 // Call the event handler, passing the event object
1595 tuple
= PyTuple_New(1);
1596 PyTuple_SET_ITEM(tuple
, 0, arg
); // steals ref to arg
1597 result
= PyEval_CallObject(func
, tuple
);
1599 Py_DECREF(result
); // result is ignored, but we still need to decref it
1600 PyErr_Clear(); // Just in case...
1605 // Check if the event object needs some post cleanup
1606 if (PyObject_HasAttr(arg
, s_postName
)) {
1607 result
= PyObject_CallMethodObjArgs(arg
, s_postName
, arg
, NULL
);
1609 Py_DECREF(result
); // result is ignored, but we still need to decref it
1610 PyErr_Clear(); // Just in case...
1617 // if the event object was one of our special types and
1618 // it had been cloned, then we need to extract the Skipped
1619 // value from the original and set it in the clone.
1620 result
= PyObject_CallMethod(arg
, "GetSkipped", "");
1622 event
.Skip(PyInt_AsLong(result
));
1630 wxPyEndBlockThreads(blocked
);
1634 //----------------------------------------------------------------------
1636 wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper
& other
) {
1638 m_self
= other
.m_self
;
1639 m_class
= other
.m_class
;
1647 void wxPyCallbackHelper::setSelf(PyObject
* self
, PyObject
* klass
, int incref
) {
1658 #if PYTHON_API_VERSION >= 1011
1660 // Prior to Python 2.2 PyMethod_GetClass returned the class object
1661 // in which the method was defined. Starting with 2.2 it returns
1662 // "class that asked for the method" which seems totally bogus to me
1663 // but apprently it fixes some obscure problem waiting to happen in
1664 // Python. Since the API was not documented Guido and the gang felt
1665 // safe in changing it. Needless to say that totally screwed up the
1666 // logic below in wxPyCallbackHelper::findCallback, hence this icky
1667 // code to find the class where the method is actually defined...
1670 PyObject
* PyFindClassWithAttr(PyObject
*klass
, PyObject
*name
)
1674 if (PyType_Check(klass
)) { // new style classes
1675 // This code is borrowed/adapted from _PyType_Lookup in typeobject.c
1676 PyTypeObject
* type
= (PyTypeObject
*)klass
;
1677 PyObject
*mro
, *res
, *base
, *dict
;
1678 /* Look in tp_dict of types in MRO */
1680 assert(PyTuple_Check(mro
));
1681 n
= PyTuple_GET_SIZE(mro
);
1682 for (i
= 0; i
< n
; i
++) {
1683 base
= PyTuple_GET_ITEM(mro
, i
);
1684 if (PyClass_Check(base
))
1685 dict
= ((PyClassObject
*)base
)->cl_dict
;
1687 assert(PyType_Check(base
));
1688 dict
= ((PyTypeObject
*)base
)->tp_dict
;
1690 assert(dict
&& PyDict_Check(dict
));
1691 res
= PyDict_GetItem(dict
, name
);
1698 else if (PyClass_Check(klass
)) { // old style classes
1699 // This code is borrowed/adapted from class_lookup in classobject.c
1700 PyClassObject
* cp
= (PyClassObject
*)klass
;
1701 PyObject
*value
= PyDict_GetItem(cp
->cl_dict
, name
);
1702 if (value
!= NULL
) {
1703 return (PyObject
*)cp
;
1705 n
= PyTuple_Size(cp
->cl_bases
);
1706 for (i
= 0; i
< n
; i
++) {
1707 PyObject
* base
= PyTuple_GetItem(cp
->cl_bases
, i
);
1708 PyObject
*v
= PyFindClassWithAttr(base
, name
);
1720 PyObject
* PyMethod_GetDefiningClass(PyObject
* method
, const char* name
)
1722 PyObject
* mgc
= PyMethod_GET_CLASS(method
);
1724 #if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way
1726 #else // 2.2 and after, the hard way...
1728 PyObject
* nameo
= PyString_FromString(name
);
1729 PyObject
* klass
= PyFindClassWithAttr(mgc
, nameo
);
1737 bool wxPyCallbackHelper::findCallback(const char* name
) const {
1738 wxPyCallbackHelper
* self
= (wxPyCallbackHelper
*)this; // cast away const
1739 self
->m_lastFound
= NULL
;
1741 // If the object (m_self) has an attibute of the given name...
1742 if (m_self
&& PyObject_HasAttrString(m_self
, (char*)name
)) {
1743 PyObject
*method
, *klass
;
1744 method
= PyObject_GetAttrString(m_self
, (char*)name
);
1746 // ...and if that attribute is a method, and if that method's class is
1747 // not from a base class...
1748 if (PyMethod_Check(method
) &&
1749 (klass
= PyMethod_GetDefiningClass(method
, (char*)name
)) != NULL
&&
1750 ((klass
== m_class
) || PyObject_IsSubclass(klass
, m_class
))) {
1752 // ...then we'll save a pointer to the method so callCallback can call it.
1753 self
->m_lastFound
= method
;
1759 return m_lastFound
!= NULL
;
1763 int wxPyCallbackHelper::callCallback(PyObject
* argTuple
) const {
1767 result
= callCallbackObj(argTuple
);
1768 if (result
) { // Assumes an integer return type...
1769 retval
= PyInt_AsLong(result
);
1771 PyErr_Clear(); // forget about it if it's not...
1776 // Invoke the Python callable object, returning the raw PyObject return
1777 // value. Caller should DECREF the return value and also manage the GIL.
1778 PyObject
* wxPyCallbackHelper::callCallbackObj(PyObject
* argTuple
) const {
1781 // Save a copy of the pointer in case the callback generates another
1782 // callback. In that case m_lastFound will have a different value when
1783 // it gets back here...
1784 PyObject
* method
= m_lastFound
;
1786 result
= PyEval_CallObject(method
, argTuple
);
1787 Py_DECREF(argTuple
);
1796 void wxPyCBH_setCallbackInfo(wxPyCallbackHelper
& cbh
, PyObject
* self
, PyObject
* klass
, int incref
) {
1797 cbh
.setSelf(self
, klass
, incref
);
1800 bool wxPyCBH_findCallback(const wxPyCallbackHelper
& cbh
, const char* name
) {
1801 return cbh
.findCallback(name
);
1804 int wxPyCBH_callCallback(const wxPyCallbackHelper
& cbh
, PyObject
* argTuple
) {
1805 return cbh
.callCallback(argTuple
);
1808 PyObject
* wxPyCBH_callCallbackObj(const wxPyCallbackHelper
& cbh
, PyObject
* argTuple
) {
1809 return cbh
.callCallbackObj(argTuple
);
1813 void wxPyCBH_delete(wxPyCallbackHelper
* cbh
) {
1814 if (cbh
->m_incRef
) {
1815 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1816 Py_XDECREF(cbh
->m_self
);
1817 Py_XDECREF(cbh
->m_class
);
1818 wxPyEndBlockThreads(blocked
);
1822 //---------------------------------------------------------------------------
1823 //---------------------------------------------------------------------------
1824 // These event classes can be derived from in Python and passed through the event
1825 // system without losing anything. They do this by keeping a reference to
1826 // themselves and some special case handling in wxPyCallback::EventThunker.
1829 wxPyEvtSelfRef::wxPyEvtSelfRef() {
1830 //m_self = Py_None; // **** We don't do normal ref counting to prevent
1831 //Py_INCREF(m_self); // circular loops...
1835 wxPyEvtSelfRef::~wxPyEvtSelfRef() {
1836 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1839 wxPyEndBlockThreads(blocked
);
1842 void wxPyEvtSelfRef::SetSelf(PyObject
* self
, bool clone
) {
1843 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1851 wxPyEndBlockThreads(blocked
);
1854 PyObject
* wxPyEvtSelfRef::GetSelf() const {
1860 IMPLEMENT_ABSTRACT_CLASS(wxPyEvent
, wxEvent
);
1861 IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent
, wxCommandEvent
);
1864 wxPyEvent::wxPyEvent(int winid
, wxEventType commandType
)
1865 : wxEvent(winid
, commandType
) {
1869 wxPyEvent::wxPyEvent(const wxPyEvent
& evt
)
1872 SetSelf(evt
.m_self
, true);
1876 wxPyEvent::~wxPyEvent() {
1880 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType
, int id
)
1881 : wxCommandEvent(commandType
, id
) {
1885 wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent
& evt
)
1886 : wxCommandEvent(evt
)
1888 SetSelf(evt
.m_self
, true);
1892 wxPyCommandEvent::~wxPyCommandEvent() {
1899 //---------------------------------------------------------------------------
1900 //---------------------------------------------------------------------------
1901 // Convert a wxList to a Python List, only works for lists of wxObjects
1903 PyObject
* wxPy_ConvertList(wxListBase
* listbase
) {
1904 wxList
* list
= (wxList
*)listbase
; // this is probably bad...
1908 wxNode
* node
= list
->GetFirst();
1910 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
1911 pyList
= PyList_New(0);
1913 wxObj
= node
->GetData();
1914 pyObj
= wxPyMake_wxObject(wxObj
,false);
1915 PyList_Append(pyList
, pyObj
);
1916 node
= node
->GetNext();
1918 wxPyEndBlockThreads(blocked
);
1922 //----------------------------------------------------------------------
1924 long wxPyGetWinHandle(wxWindow
* win
) {
1927 return (long)win
->GetHandle();
1930 #if defined(__WXGTK__) || defined(__WXX11)
1931 return (long)GetXWindow(win
);
1935 //return (long)MAC_WXHWND(win->MacGetTopLevelWindowRef());
1936 return (long)win
->GetHandle();
1942 //----------------------------------------------------------------------
1943 // Some helper functions for typemaps in my_typemaps.i, so they won't be
1944 // included in every file over and over again...
1946 wxString
* wxString_in_helper(PyObject
* source
) {
1947 wxString
* target
= NULL
;
1949 if (!PyString_Check(source
) && !PyUnicode_Check(source
)) {
1950 PyErr_SetString(PyExc_TypeError
, "String or Unicode type required");
1954 PyObject
* uni
= source
;
1955 if (PyString_Check(source
)) {
1956 uni
= PyUnicode_FromEncodedObject(source
, wxPyDefaultEncoding
, "strict");
1957 if (PyErr_Occurred()) return NULL
;
1959 target
= new wxString();
1960 size_t len
= PyUnicode_GET_SIZE(uni
);
1962 PyUnicode_AsWideChar((PyUnicodeObject
*)uni
, target
->GetWriteBuf(len
), len
);
1963 target
->UngetWriteBuf(len
);
1966 if (PyString_Check(source
))
1969 // Convert to a string object if it isn't already, then to wxString
1970 PyObject
* str
= source
;
1971 if (PyUnicode_Check(source
)) {
1972 str
= PyUnicode_AsEncodedString(source
, wxPyDefaultEncoding
, "strict");
1973 if (PyErr_Occurred()) return NULL
;
1975 else if (!PyString_Check(source
)) {
1976 str
= PyObject_Str(source
);
1977 if (PyErr_Occurred()) return NULL
;
1979 char* tmpPtr
; int tmpSize
;
1980 PyString_AsStringAndSize(str
, &tmpPtr
, &tmpSize
);
1981 target
= new wxString(tmpPtr
, tmpSize
);
1983 if (!PyString_Check(source
))
1985 #endif // wxUSE_UNICODE
1991 // Similar to above except doesn't use "new" and doesn't set an exception
1992 wxString
Py2wxString(PyObject
* source
)
1997 // Convert to a unicode object, if not already, then to a wxString
1998 PyObject
* uni
= source
;
1999 if (!PyUnicode_Check(source
)) {
2000 uni
= PyUnicode_FromEncodedObject(source
, wxPyDefaultEncoding
, "strict");
2001 if (PyErr_Occurred()) return wxEmptyString
; // TODO: should we PyErr_Clear?
2003 size_t len
= PyUnicode_GET_SIZE(uni
);
2005 PyUnicode_AsWideChar((PyUnicodeObject
*)uni
, target
.GetWriteBuf(len
), len
);
2006 target
.UngetWriteBuf();
2009 if (!PyUnicode_Check(source
))
2012 // Convert to a string object if it isn't already, then to wxString
2013 PyObject
* str
= source
;
2014 if (PyUnicode_Check(source
)) {
2015 str
= PyUnicode_AsEncodedString(source
, wxPyDefaultEncoding
, "strict");
2016 if (PyErr_Occurred()) return wxEmptyString
; // TODO: should we PyErr_Clear?
2018 else if (!PyString_Check(source
)) {
2019 str
= PyObject_Str(source
);
2020 if (PyErr_Occurred()) return wxEmptyString
; // TODO: should we PyErr_Clear?
2022 char* tmpPtr
; int tmpSize
;
2023 PyString_AsStringAndSize(str
, &tmpPtr
, &tmpSize
);
2024 target
= wxString(tmpPtr
, tmpSize
);
2026 if (!PyString_Check(source
))
2028 #endif // wxUSE_UNICODE
2034 // Make either a Python String or Unicode object, depending on build mode
2035 PyObject
* wx2PyString(const wxString
& src
)
2039 str
= PyUnicode_FromWideChar(src
.c_str(), src
.Len());
2041 str
= PyString_FromStringAndSize(src
.c_str(), src
.Len());
2048 void wxSetDefaultPyEncoding(const char* encoding
)
2050 strncpy(wxPyDefaultEncoding
, encoding
, DEFAULTENCODING_SIZE
);
2053 const char* wxGetDefaultPyEncoding()
2055 return wxPyDefaultEncoding
;
2058 //----------------------------------------------------------------------
2061 byte
* byte_LIST_helper(PyObject
* source
) {
2062 if (!PyList_Check(source
)) {
2063 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2066 int count
= PyList_Size(source
);
2067 byte
* temp
= new byte
[count
];
2069 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2072 for (int x
=0; x
<count
; x
++) {
2073 PyObject
* o
= PyList_GetItem(source
, x
);
2074 if (! PyInt_Check(o
)) {
2075 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
2078 temp
[x
] = (byte
)PyInt_AsLong(o
);
2084 int* int_LIST_helper(PyObject
* source
) {
2085 if (!PyList_Check(source
)) {
2086 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2089 int count
= PyList_Size(source
);
2090 int* temp
= new int[count
];
2092 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2095 for (int x
=0; x
<count
; x
++) {
2096 PyObject
* o
= PyList_GetItem(source
, x
);
2097 if (! PyInt_Check(o
)) {
2098 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
2101 temp
[x
] = PyInt_AsLong(o
);
2107 long* long_LIST_helper(PyObject
* source
) {
2108 if (!PyList_Check(source
)) {
2109 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2112 int count
= PyList_Size(source
);
2113 long* temp
= new long[count
];
2115 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2118 for (int x
=0; x
<count
; x
++) {
2119 PyObject
* o
= PyList_GetItem(source
, x
);
2120 if (! PyInt_Check(o
)) {
2121 PyErr_SetString(PyExc_TypeError
, "Expected a list of integers.");
2124 temp
[x
] = PyInt_AsLong(o
);
2130 char** string_LIST_helper(PyObject
* source
) {
2131 if (!PyList_Check(source
)) {
2132 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2135 int count
= PyList_Size(source
);
2136 char** temp
= new char*[count
];
2138 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2141 for (int x
=0; x
<count
; x
++) {
2142 PyObject
* o
= PyList_GetItem(source
, x
);
2143 if (! PyString_Check(o
)) {
2144 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
2147 temp
[x
] = PyString_AsString(o
);
2152 //--------------------------------
2153 // Part of patch from Tim Hochberg
2154 static inline bool wxPointFromObjects(PyObject
* o1
, PyObject
* o2
, wxPoint
* point
) {
2155 if (PyInt_Check(o1
) && PyInt_Check(o2
)) {
2156 point
->x
= PyInt_AS_LONG(o1
);
2157 point
->y
= PyInt_AS_LONG(o2
);
2160 if (PyFloat_Check(o1
) && PyFloat_Check(o2
)) {
2161 point
->x
= (int)PyFloat_AS_DOUBLE(o1
);
2162 point
->y
= (int)PyFloat_AS_DOUBLE(o2
);
2165 if (wxPySwigInstance_Check(o1
) || wxPySwigInstance_Check(o2
)) { // TODO: Why???
2166 // Disallow instances because they can cause havok
2169 if (PyNumber_Check(o1
) && PyNumber_Check(o2
)) {
2170 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
2171 point
->x
= PyInt_AsLong(o1
);
2172 point
->y
= PyInt_AsLong(o2
);
2179 wxPoint
* wxPoint_LIST_helper(PyObject
* source
, int *count
) {
2180 // Putting all of the declarations here allows
2181 // us to put the error handling all in one place.
2184 PyObject
*o
, *o1
, *o2
;
2185 bool isFast
= PyList_Check(source
) || PyTuple_Check(source
);
2187 if (!PySequence_Check(source
)) {
2191 // The length of the sequence is returned in count.
2192 *count
= PySequence_Length(source
);
2197 temp
= new wxPoint
[*count
];
2199 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2202 for (x
=0; x
<*count
; x
++) {
2203 // Get an item: try fast way first.
2205 o
= PySequence_Fast_GET_ITEM(source
, x
);
2208 o
= PySequence_GetItem(source
, x
);
2214 // Convert o to wxPoint.
2215 if ((PyTuple_Check(o
) && PyTuple_GET_SIZE(o
) == 2) ||
2216 (PyList_Check(o
) && PyList_GET_SIZE(o
) == 2)) {
2217 o1
= PySequence_Fast_GET_ITEM(o
, 0);
2218 o2
= PySequence_Fast_GET_ITEM(o
, 1);
2219 if (!wxPointFromObjects(o1
, o2
, &temp
[x
])) {
2223 else if (wxPySwigInstance_Check(o
)) {
2225 if (! wxPyConvertSwigPtr(o
, (void **)&pt
, wxT("wxPoint"))) {
2230 else if (PySequence_Check(o
) && PySequence_Length(o
) == 2) {
2231 o1
= PySequence_GetItem(o
, 0);
2232 o2
= PySequence_GetItem(o
, 1);
2233 if (!wxPointFromObjects(o1
, o2
, &temp
[x
])) {
2257 PyErr_SetString(PyExc_TypeError
, "Expected a sequence of length-2 sequences or wxPoints.");
2261 //------------------------------
2264 wxBitmap
** wxBitmap_LIST_helper(PyObject
* source
) {
2265 if (!PyList_Check(source
)) {
2266 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2269 int count
= PyList_Size(source
);
2270 wxBitmap
** temp
= new wxBitmap
*[count
];
2272 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2275 for (int x
=0; x
<count
; x
++) {
2276 PyObject
* o
= PyList_GetItem(source
, x
);
2277 if (wxPySwigInstance_Check(o
)) {
2279 if (! wxPyConvertSwigPtr(o
, (void **) &pt
, wxT("wxBitmap"))) {
2280 PyErr_SetString(PyExc_TypeError
,"Expected wxBitmap.");
2286 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxBitmaps.");
2295 wxString
* wxString_LIST_helper(PyObject
* source
) {
2296 if (!PyList_Check(source
)) {
2297 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2300 int count
= PyList_Size(source
);
2301 wxString
* temp
= new wxString
[count
];
2303 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2306 for (int x
=0; x
<count
; x
++) {
2307 PyObject
* o
= PyList_GetItem(source
, x
);
2308 #if PYTHON_API_VERSION >= 1009
2309 if (! PyString_Check(o
) && ! PyUnicode_Check(o
)) {
2310 PyErr_SetString(PyExc_TypeError
, "Expected a list of string or unicode objects.");
2314 if (! PyString_Check(o
)) {
2315 PyErr_SetString(PyExc_TypeError
, "Expected a list of strings.");
2320 wxString
* pStr
= wxString_in_helper(o
);
2328 wxAcceleratorEntry
* wxAcceleratorEntry_LIST_helper(PyObject
* source
) {
2329 if (!PyList_Check(source
)) {
2330 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2333 int count
= PyList_Size(source
);
2334 wxAcceleratorEntry
* temp
= new wxAcceleratorEntry
[count
];
2336 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2339 for (int x
=0; x
<count
; x
++) {
2340 PyObject
* o
= PyList_GetItem(source
, x
);
2341 if (wxPySwigInstance_Check(o
)) {
2342 wxAcceleratorEntry
* ae
;
2343 if (! wxPyConvertSwigPtr(o
, (void **) &ae
, wxT("wxAcceleratorEntry"))) {
2344 PyErr_SetString(PyExc_TypeError
,"Expected wxAcceleratorEntry.");
2349 else if (PyTuple_Check(o
)) {
2350 PyObject
* o1
= PyTuple_GetItem(o
, 0);
2351 PyObject
* o2
= PyTuple_GetItem(o
, 1);
2352 PyObject
* o3
= PyTuple_GetItem(o
, 2);
2353 temp
[x
].Set(PyInt_AsLong(o1
), PyInt_AsLong(o2
), PyInt_AsLong(o3
));
2356 PyErr_SetString(PyExc_TypeError
, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
2364 wxPen
** wxPen_LIST_helper(PyObject
* source
) {
2365 if (!PyList_Check(source
)) {
2366 PyErr_SetString(PyExc_TypeError
, "Expected a list object.");
2369 int count
= PyList_Size(source
);
2370 wxPen
** temp
= new wxPen
*[count
];
2372 PyErr_SetString(PyExc_MemoryError
, "Unable to allocate temporary array");
2375 for (int x
=0; x
<count
; x
++) {
2376 PyObject
* o
= PyList_GetItem(source
, x
);
2377 if (wxPySwigInstance_Check(o
)) {
2379 if (! wxPyConvertSwigPtr(o
, (void **)&pt
, wxT("wxPen"))) {
2381 PyErr_SetString(PyExc_TypeError
,"Expected wxPen.");
2388 PyErr_SetString(PyExc_TypeError
, "Expected a list of wxPens.");
2396 bool wxPy2int_seq_helper(PyObject
* source
, int* i1
, int* i2
) {
2397 bool isFast
= PyList_Check(source
) || PyTuple_Check(source
);
2400 if (!PySequence_Check(source
) || PySequence_Length(source
) != 2)
2404 o1
= PySequence_Fast_GET_ITEM(source
, 0);
2405 o2
= PySequence_Fast_GET_ITEM(source
, 1);
2408 o1
= PySequence_GetItem(source
, 0);
2409 o2
= PySequence_GetItem(source
, 1);
2412 *i1
= PyInt_AsLong(o1
);
2413 *i2
= PyInt_AsLong(o2
);
2423 bool wxPy4int_seq_helper(PyObject
* source
, int* i1
, int* i2
, int* i3
, int* i4
) {
2424 bool isFast
= PyList_Check(source
) || PyTuple_Check(source
);
2425 PyObject
*o1
, *o2
, *o3
, *o4
;
2427 if (!PySequence_Check(source
) || PySequence_Length(source
) != 4)
2431 o1
= PySequence_Fast_GET_ITEM(source
, 0);
2432 o2
= PySequence_Fast_GET_ITEM(source
, 1);
2433 o3
= PySequence_Fast_GET_ITEM(source
, 2);
2434 o4
= PySequence_Fast_GET_ITEM(source
, 3);
2437 o1
= PySequence_GetItem(source
, 0);
2438 o2
= PySequence_GetItem(source
, 1);
2439 o3
= PySequence_GetItem(source
, 2);
2440 o4
= PySequence_GetItem(source
, 3);
2443 *i1
= PyInt_AsLong(o1
);
2444 *i2
= PyInt_AsLong(o2
);
2445 *i3
= PyInt_AsLong(o3
);
2446 *i4
= PyInt_AsLong(o4
);
2458 //----------------------------------------------------------------------
2460 bool wxPySimple_typecheck(PyObject
* source
, const wxChar
* classname
, int seqLen
)
2464 if (wxPySwigInstance_Check(source
) &&
2465 wxPyConvertSwigPtr(source
, (void **)&ptr
, classname
))
2469 if (PySequence_Check(source
) && PySequence_Length(source
) == seqLen
)
2475 bool wxSize_helper(PyObject
* source
, wxSize
** obj
)
2477 if (source
== Py_None
) {
2478 **obj
= wxSize(-1,-1);
2481 return wxPyTwoIntItem_helper(source
, obj
, wxT("wxSize"));
2485 bool wxPoint_helper(PyObject
* source
, wxPoint
** obj
)
2487 if (source
== Py_None
) {
2488 **obj
= wxPoint(-1,-1);
2491 return wxPyTwoIntItem_helper(source
, obj
, wxT("wxPoint"));
2496 bool wxRealPoint_helper(PyObject
* source
, wxRealPoint
** obj
) {
2498 if (source
== Py_None
) {
2499 **obj
= wxRealPoint(-1,-1);
2503 // If source is an object instance then it may already be the right type
2504 if (wxPySwigInstance_Check(source
)) {
2506 if (! wxPyConvertSwigPtr(source
, (void **)&ptr
, wxT("wxRealPoint")))
2511 // otherwise a 2-tuple of floats is expected
2512 else if (PySequence_Check(source
) && PyObject_Length(source
) == 2) {
2513 PyObject
* o1
= PySequence_GetItem(source
, 0);
2514 PyObject
* o2
= PySequence_GetItem(source
, 1);
2515 if (!PyNumber_Check(o1
) || !PyNumber_Check(o2
)) {
2520 **obj
= wxRealPoint(PyFloat_AsDouble(o1
), PyFloat_AsDouble(o2
));
2527 PyErr_SetString(PyExc_TypeError
, "Expected a 2-tuple of floats or a wxRealPoint object.");
2533 bool wxRect_helper(PyObject
* source
, wxRect
** obj
) {
2535 if (source
== Py_None
) {
2536 **obj
= wxRect(-1,-1,-1,-1);
2540 // If source is an object instance then it may already be the right type
2541 if (wxPySwigInstance_Check(source
)) {
2543 if (! wxPyConvertSwigPtr(source
, (void **)&ptr
, wxT("wxRect")))
2548 // otherwise a 4-tuple of integers is expected
2549 else if (PySequence_Check(source
) && PyObject_Length(source
) == 4) {
2550 PyObject
* o1
= PySequence_GetItem(source
, 0);
2551 PyObject
* o2
= PySequence_GetItem(source
, 1);
2552 PyObject
* o3
= PySequence_GetItem(source
, 2);
2553 PyObject
* o4
= PySequence_GetItem(source
, 3);
2554 if (!PyNumber_Check(o1
) || !PyNumber_Check(o2
) ||
2555 !PyNumber_Check(o3
) || !PyNumber_Check(o4
)) {
2562 **obj
= wxRect(PyInt_AsLong(o1
), PyInt_AsLong(o2
),
2563 PyInt_AsLong(o3
), PyInt_AsLong(o4
));
2572 PyErr_SetString(PyExc_TypeError
, "Expected a 4-tuple of integers or a wxRect object.");
2578 bool wxColour_helper(PyObject
* source
, wxColour
** obj
) {
2580 if (source
== Py_None
) {
2581 **obj
= wxNullColour
;
2585 // If source is an object instance then it may already be the right type
2586 if (wxPySwigInstance_Check(source
)) {
2588 if (! wxPyConvertSwigPtr(source
, (void **)&ptr
, wxT("wxColour")))
2593 // otherwise check for a string
2594 else if (PyString_Check(source
) || PyUnicode_Check(source
)) {
2595 wxString spec
= Py2wxString(source
);
2596 if (spec
.GetChar(0) == '#' && spec
.Length() == 7) { // It's #RRGGBB
2597 long red
, green
, blue
;
2598 red
= green
= blue
= 0;
2599 spec
.Mid(1,2).ToLong(&red
, 16);
2600 spec
.Mid(3,2).ToLong(&green
, 16);
2601 spec
.Mid(5,2).ToLong(&blue
, 16);
2603 **obj
= wxColour(red
, green
, blue
);
2606 else { // it's a colour name
2607 **obj
= wxColour(spec
);
2611 // last chance: 3-tuple of integers is expected
2612 else if (PySequence_Check(source
) && PyObject_Length(source
) == 3) {
2613 PyObject
* o1
= PySequence_GetItem(source
, 0);
2614 PyObject
* o2
= PySequence_GetItem(source
, 1);
2615 PyObject
* o3
= PySequence_GetItem(source
, 2);
2616 if (!PyNumber_Check(o1
) || !PyNumber_Check(o2
) || !PyNumber_Check(o3
)) {
2622 **obj
= wxColour(PyInt_AsLong(o1
), PyInt_AsLong(o2
), PyInt_AsLong(o3
));
2630 PyErr_SetString(PyExc_TypeError
,
2631 "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
2636 bool wxColour_typecheck(PyObject
* source
) {
2638 if (wxPySimple_typecheck(source
, wxT("wxColour"), 3))
2641 if (PyString_Check(source
) || PyUnicode_Check(source
))
2649 bool wxPoint2D_helper(PyObject
* source
, wxPoint2D
** obj
) {
2651 if (source
== Py_None
) {
2652 **obj
= wxPoint2D(-1,-1);
2656 // If source is an object instance then it may already be the right type
2657 if (wxPySwigInstance_Check(source
)) {
2659 if (! wxPyConvertSwigPtr(source
, (void **)&ptr
, wxT("wxPoint2D")))
2664 // otherwise a length-2 sequence of floats is expected
2665 if (PySequence_Check(source
) && PySequence_Length(source
) == 2) {
2666 PyObject
* o1
= PySequence_GetItem(source
, 0);
2667 PyObject
* o2
= PySequence_GetItem(source
, 1);
2668 // This should really check for floats, not numbers -- but that would break code.
2669 if (!PyNumber_Check(o1
) || !PyNumber_Check(o2
)) {
2674 **obj
= wxPoint2D(PyFloat_AsDouble(o1
), PyFloat_AsDouble(o2
));
2680 PyErr_SetString(PyExc_TypeError
, "Expected a 2-tuple of floats or a wxPoint2D object.");
2685 //----------------------------------------------------------------------
2687 PyObject
* wxArrayString2PyList_helper(const wxArrayString
& arr
) {
2689 PyObject
* list
= PyList_New(0);
2690 for (size_t i
=0; i
< arr
.GetCount(); i
++) {
2692 PyObject
* str
= PyUnicode_FromWideChar(arr
[i
].c_str(), arr
[i
].Len());
2694 PyObject
* str
= PyString_FromStringAndSize(arr
[i
].c_str(), arr
[i
].Len());
2696 PyList_Append(list
, str
);
2703 PyObject
* wxArrayInt2PyList_helper(const wxArrayInt
& arr
) {
2705 PyObject
* list
= PyList_New(0);
2706 for (size_t i
=0; i
< arr
.GetCount(); i
++) {
2707 PyObject
* number
= PyInt_FromLong(arr
[i
]);
2708 PyList_Append(list
, number
);
2715 //----------------------------------------------------------------------
2716 // wxPyImageHandler methods
2718 // TODO: Switch these to use wxPython's standard macros and helper classes
2719 // for calling callbacks.
2721 PyObject
* wxPyImageHandler::m_DoCanRead_Name
= NULL
;
2722 PyObject
* wxPyImageHandler::m_GetImageCount_Name
= NULL
;
2723 PyObject
* wxPyImageHandler::m_LoadFile_Name
= NULL
;
2724 PyObject
* wxPyImageHandler::m_SaveFile_Name
= NULL
;
2726 PyObject
* wxPyImageHandler::py_InputStream(wxInputStream
* stream
) {
2727 return wxPyConstructObject(new wxPyInputStream(stream
),
2728 wxT("wxPyInputStream"), 0);
2731 PyObject
* wxPyImageHandler::py_Image(wxImage
* image
) {
2732 return wxPyConstructObject(image
, wxT("wxImage"), 0);
2735 PyObject
* wxPyImageHandler::py_OutputStream(wxOutputStream
* stream
) {
2736 return wxPyConstructObject(stream
, wxT("wxOutputStream"), 0);
2739 wxPyImageHandler::wxPyImageHandler():
2742 if (!m_DoCanRead_Name
) {
2743 m_DoCanRead_Name
= PyString_FromString("DoCanRead");
2744 m_GetImageCount_Name
= PyString_FromString("GetImageCount");
2745 m_LoadFile_Name
= PyString_FromString("LoadFile");
2746 m_SaveFile_Name
= PyString_FromString("SaveFile");
2750 wxPyImageHandler::~wxPyImageHandler() {
2757 void wxPyImageHandler::_SetSelf(PyObject
*self
) {
2758 // should check here for isinstance(PyImageHandler) ??
2763 bool wxPyImageHandler::DoCanRead(wxInputStream
& stream
) {
2764 // check if our object has this method
2765 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
2766 if (!m_self
|| !PyObject_HasAttr(m_self
, m_DoCanRead_Name
)) {
2767 wxPyEndBlockThreads(blocked
);
2771 PyObject
* res
= PyObject_CallMethodObjArgs(m_self
, m_DoCanRead_Name
,
2772 py_InputStream(&stream
), NULL
);
2773 bool retval
= false;
2775 retval
= PyInt_AsLong(res
);
2781 wxPyEndBlockThreads(blocked
);
2785 bool wxPyImageHandler::LoadFile( wxImage
* image
, wxInputStream
& stream
,
2786 bool verbose
, int index
) {
2787 // check if our object has this method
2788 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
2789 if (!m_self
|| !PyObject_HasAttr(m_self
, m_LoadFile_Name
)) {
2790 wxPyEndBlockThreads(blocked
);
2793 PyObject
* res
= PyObject_CallMethodObjArgs(m_self
, m_LoadFile_Name
,
2795 py_InputStream(&stream
),
2796 PyInt_FromLong(verbose
),
2797 PyInt_FromLong(index
),
2799 bool retval
= false;
2801 retval
= PyInt_AsLong(res
);
2806 wxPyEndBlockThreads(blocked
);
2810 bool wxPyImageHandler::SaveFile( wxImage
* image
, wxOutputStream
& stream
,
2812 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
2813 if (!m_self
|| !PyObject_HasAttr(m_self
, m_SaveFile_Name
)) {
2814 wxPyEndBlockThreads(blocked
);
2817 PyObject
* res
= PyObject_CallMethodObjArgs(m_self
, m_SaveFile_Name
,
2819 py_OutputStream(&stream
),
2820 PyInt_FromLong(verbose
),
2822 bool retval
= false;
2824 retval
=PyInt_AsLong(res
);
2829 wxPyEndBlockThreads(blocked
);
2833 int wxPyImageHandler::GetImageCount( wxInputStream
& stream
) {
2834 wxPyBlock_t blocked
= wxPyBeginBlockThreads();
2835 if (!m_self
|| !PyObject_HasAttr(m_self
, m_GetImageCount_Name
)) {
2836 wxPyEndBlockThreads(blocked
);
2839 PyObject
*res
=PyObject_CallMethodObjArgs(m_self
, m_GetImageCount_Name
,
2840 py_InputStream(&stream
),
2844 retval
=PyInt_AsLong(res
);
2849 wxPyEndBlockThreads(blocked
);
2854 //----------------------------------------------------------------------
2855 //----------------------------------------------------------------------