$search
00001 00002 // Name: helpers.cpp 00003 // Purpose: Helper functions/classes for the wxPython extension module 00004 // 00005 // Author: Robin Dunn 00006 // 00007 // Created: 1-July-1997 00008 // RCS-ID: $Id: helpers.cpp,v 1.145 2006/12/05 18:11:15 RD Exp $ 00009 // Copyright: (c) 1998 by Total Control Software 00010 // Licence: wxWindows license 00012 00013 00014 #undef DEBUG 00015 #include <Python.h> 00016 #include "wx/wxPython/wxPython_int.h" 00017 #include "wx/wxPython/pyistream.h" 00018 #include "wx/wxPython/swigver.h" 00019 #include "wx/wxPython/twoitem.h" 00020 00021 #ifdef __WXMSW__ 00022 #include <wx/msw/private.h> 00023 #include <wx/msw/winundef.h> 00024 #include <wx/msw/msvcrt.h> 00025 #endif 00026 00027 #ifdef __WXGTK__ 00028 #include <gdk/gdk.h> 00029 #include <gdk/gdkx.h> 00030 #include <gtk/gtk.h> 00031 #include <gdk/gdkprivate.h> 00032 #ifdef __WXGTK20__ 00033 #include <wx/gtk/win_gtk.h> 00034 #else 00035 #include <wx/gtk1/win_gtk.h> 00036 #endif 00037 #define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \ 00038 GDK_WINDOW_XWINDOW(GTK_PIZZA((wxwin)->m_wxwindow)->bin_window) : \ 00039 GDK_WINDOW_XWINDOW((wxwin)->m_widget->window) 00040 #include <locale.h> 00041 #endif 00042 00043 #ifdef __WXX11__ 00044 #include "wx/x11/privx.h" 00045 #define GetXWindow(wxwin) ((Window)(wxwin)->GetHandle()) 00046 #endif 00047 00048 #ifdef __WXMAC__ 00049 #include <wx/mac/private.h> 00050 #endif 00051 00052 #include <wx/clipbrd.h> 00053 #include <wx/mimetype.h> 00054 #include <wx/image.h> 00055 00056 //---------------------------------------------------------------------- 00057 00058 #if PYTHON_API_VERSION < 1009 && wxUSE_UNICODE 00059 #error Python must support Unicode to use wxWindows Unicode 00060 #endif 00061 00062 //---------------------------------------------------------------------- 00063 00064 wxPyApp* wxPythonApp = NULL; // Global instance of application object 00065 bool wxPyDoCleanup = false; 00066 bool wxPyDoingCleanup = false; 00067 00068 00069 #ifdef WXP_WITH_THREAD 00070 #if !wxPyUSE_GIL_STATE 00071 struct wxPyThreadState { 00072 unsigned long tid; 00073 PyThreadState* tstate; 00074 00075 wxPyThreadState(unsigned long _tid=0, PyThreadState* _tstate=NULL) 00076 : tid(_tid), tstate(_tstate) {} 00077 }; 00078 00079 #include <wx/dynarray.h> 00080 WX_DECLARE_OBJARRAY(wxPyThreadState, wxPyThreadStateArray); 00081 #include <wx/arrimpl.cpp> 00082 WX_DEFINE_OBJARRAY(wxPyThreadStateArray); 00083 00084 wxPyThreadStateArray* wxPyTStates = NULL; 00085 wxMutex* wxPyTMutex = NULL; 00086 00087 #endif 00088 #endif 00089 00090 00091 #define DEFAULTENCODING_SIZE 64 00092 static char wxPyDefaultEncoding[DEFAULTENCODING_SIZE] = "ascii"; 00093 00094 static PyObject* wxPython_dict = NULL; 00095 static PyObject* wxPyAssertionError = NULL; 00096 static PyObject* wxPyNoAppError = NULL; 00097 00098 PyObject* wxPyPtrTypeMap = NULL; 00099 00100 00101 #ifdef __WXMSW__ // If building for win32... 00102 //---------------------------------------------------------------------- 00103 // This gets run when the DLL is loaded. We just need to save a handle. 00104 //---------------------------------------------------------------------- 00105 00106 extern "C" 00107 BOOL WINAPI DllMain( 00108 HINSTANCE hinstDLL, // handle to DLL module 00109 DWORD fdwReason, // reason for calling function 00110 LPVOID lpvReserved // reserved 00111 ) 00112 { 00113 // If wxPython is embedded in another wxWidgets app then 00114 // the instance has already been set. 00115 if (! wxGetInstance()) 00116 wxSetInstance(hinstDLL); 00117 return true; 00118 } 00119 #endif 00120 00121 //---------------------------------------------------------------------- 00122 // Classes for implementing the wxp main application shell. 00123 //---------------------------------------------------------------------- 00124 00125 IMPLEMENT_ABSTRACT_CLASS(wxPyApp, wxApp); 00126 00127 00128 wxPyApp::wxPyApp() { 00129 m_assertMode = wxPYAPP_ASSERT_EXCEPTION; 00130 m_startupComplete = false; 00131 } 00132 00133 00134 wxPyApp::~wxPyApp() { 00135 wxPythonApp = NULL; 00136 wxApp::SetInstance(NULL); 00137 } 00138 00139 00140 // This one isn't acutally called... We fake it with _BootstrapApp 00141 bool wxPyApp::OnInit() { 00142 return false; 00143 } 00144 00145 00146 int wxPyApp::MainLoop() { 00147 int retval = 0; 00148 00149 DeletePendingObjects(); 00150 bool initialized = wxTopLevelWindows.GetCount() != 0; 00151 if (initialized) { 00152 if ( m_exitOnFrameDelete == Later ) { 00153 m_exitOnFrameDelete = Yes; 00154 } 00155 00156 retval = wxApp::MainLoop(); 00157 OnExit(); 00158 } 00159 return retval; 00160 } 00161 00162 00163 bool wxPyApp::OnInitGui() { 00164 bool rval=true; 00165 wxApp::OnInitGui(); // in this case always call the base class version 00166 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00167 if (wxPyCBH_findCallback(m_myInst, "OnInitGui")) 00168 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); 00169 wxPyEndBlockThreads(blocked); 00170 return rval; 00171 } 00172 00173 00174 int wxPyApp::OnExit() { 00175 int rval=0; 00176 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00177 if (wxPyCBH_findCallback(m_myInst, "OnExit")) 00178 rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); 00179 wxPyEndBlockThreads(blocked); 00180 wxApp::OnExit(); // in this case always call the base class version 00181 return rval; 00182 } 00183 00184 00185 00186 void wxPyApp::ExitMainLoop() { 00187 bool found; 00188 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00189 if ((found = wxPyCBH_findCallback(m_myInst, "ExitMainLoop"))) 00190 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); 00191 wxPyEndBlockThreads(blocked); 00192 if (! found) 00193 wxApp::ExitMainLoop(); 00194 } 00195 00196 00197 #ifdef __WXDEBUG__ 00198 void wxPyApp::OnAssertFailure(const wxChar *file, 00199 int line, 00200 const wxChar *func, 00201 const wxChar *cond, 00202 const wxChar *msg) 00203 { 00204 // if we're not fully initialized then just log the error 00205 if (! m_startupComplete) { 00206 wxString buf; 00207 buf.Alloc(4096); 00208 buf.Printf(wxT("%s(%d): assert \"%s\" failed"), 00209 file, line, cond); 00210 if ( func && *func ) 00211 buf << wxT(" in ") << func << wxT("()"); 00212 if (msg != NULL) 00213 buf << wxT(": ") << msg; 00214 00215 wxLogDebug(buf); 00216 return; 00217 } 00218 00219 // If the OnAssert is overloaded in the Python class then call it... 00220 bool found; 00221 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00222 if ((found = wxPyCBH_findCallback(m_myInst, "OnAssert"))) { 00223 PyObject* fso = wx2PyString(file); 00224 PyObject* cso = wx2PyString(file); 00225 PyObject* mso; 00226 if (msg != NULL) 00227 mso = wx2PyString(file); 00228 else { 00229 mso = Py_None; Py_INCREF(Py_None); 00230 } 00231 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(OiOO)", fso, line, cso, mso)); 00232 Py_DECREF(fso); 00233 Py_DECREF(cso); 00234 Py_DECREF(mso); 00235 } 00236 wxPyEndBlockThreads(blocked); 00237 00238 // ...otherwise do our own thing with it 00239 if (! found) { 00240 // ignore it? 00241 if (m_assertMode & wxPYAPP_ASSERT_SUPPRESS) 00242 return; 00243 00244 // turn it into a Python exception? 00245 if (m_assertMode & wxPYAPP_ASSERT_EXCEPTION) { 00246 wxString buf; 00247 buf.Alloc(4096); 00248 buf.Printf(wxT("C++ assertion \"%s\" failed at %s(%d)"), cond, file, line); 00249 if ( func && *func ) 00250 buf << wxT(" in ") << func << wxT("()"); 00251 if (msg != NULL) 00252 buf << wxT(": ") << msg; 00253 00254 00255 // set the exception 00256 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00257 PyObject* s = wx2PyString(buf); 00258 PyErr_SetObject(wxPyAssertionError, s); 00259 Py_DECREF(s); 00260 wxPyEndBlockThreads(blocked); 00261 00262 // Now when control returns to whatever API wrapper was called from 00263 // Python it should detect that an exception is set and will return 00264 // NULL, signalling the exception to Python. 00265 } 00266 00267 // Send it to the normal log destination, but only if 00268 // not _DIALOG because it will call this too 00269 if ( (m_assertMode & wxPYAPP_ASSERT_LOG) && !(m_assertMode & wxPYAPP_ASSERT_DIALOG)) { 00270 wxString buf; 00271 buf.Alloc(4096); 00272 buf.Printf(wxT("%s(%d): assert \"%s\" failed"), 00273 file, line, cond); 00274 if ( func && *func ) 00275 buf << wxT(" in ") << func << wxT("()"); 00276 if (msg != NULL) 00277 buf << wxT(": ") << msg; 00278 wxLogDebug(buf); 00279 } 00280 00281 // do the normal wx assert dialog? 00282 if (m_assertMode & wxPYAPP_ASSERT_DIALOG) 00283 wxApp::OnAssertFailure(file, line, func, cond, msg); 00284 } 00285 } 00286 #endif 00287 00288 // For catching Apple Events 00289 void wxPyApp::MacOpenFile(const wxString &fileName) 00290 { 00291 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00292 if (wxPyCBH_findCallback(m_myInst, "MacOpenFile")) { 00293 PyObject* s = wx2PyString(fileName); 00294 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s)); 00295 Py_DECREF(s); 00296 } 00297 wxPyEndBlockThreads(blocked); 00298 } 00299 00300 void wxPyApp::MacPrintFile(const wxString &fileName) 00301 { 00302 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00303 if (wxPyCBH_findCallback(m_myInst, "MacPrintFile")) { 00304 PyObject* s = wx2PyString(fileName); 00305 wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", s)); 00306 Py_DECREF(s); 00307 } 00308 wxPyEndBlockThreads(blocked); 00309 } 00310 00311 void wxPyApp::MacNewFile() 00312 { 00313 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00314 if (wxPyCBH_findCallback(m_myInst, "MacNewFile")) 00315 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); 00316 wxPyEndBlockThreads(blocked); 00317 } 00318 00319 void wxPyApp::MacReopenApp() 00320 { 00321 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00322 if (wxPyCBH_findCallback(m_myInst, "MacReopenApp")) 00323 wxPyCBH_callCallback(m_myInst, Py_BuildValue("()")); 00324 wxPyEndBlockThreads(blocked); 00325 } 00326 00327 00328 /*static*/ 00329 bool wxPyApp::GetMacSupportPCMenuShortcuts() { 00330 return 0; 00331 } 00332 00333 /*static*/ 00334 long wxPyApp::GetMacAboutMenuItemId() { 00335 #ifdef __WXMAC__ 00336 return s_macAboutMenuItemId; 00337 #else 00338 return 0; 00339 #endif 00340 } 00341 00342 /*static*/ 00343 long wxPyApp::GetMacPreferencesMenuItemId() { 00344 #ifdef __WXMAC__ 00345 return s_macPreferencesMenuItemId; 00346 #else 00347 return 0; 00348 #endif 00349 } 00350 00351 /*static*/ 00352 long wxPyApp::GetMacExitMenuItemId() { 00353 #ifdef __WXMAC__ 00354 return s_macExitMenuItemId; 00355 #else 00356 return 0; 00357 #endif 00358 } 00359 00360 /*static*/ 00361 wxString wxPyApp::GetMacHelpMenuTitleName() { 00362 #ifdef __WXMAC__ 00363 return s_macHelpMenuTitleName; 00364 #else 00365 return wxEmptyString; 00366 #endif 00367 } 00368 00369 /*static*/ 00370 void wxPyApp::SetMacSupportPCMenuShortcuts(bool) { 00371 } 00372 00373 /*static*/ 00374 void wxPyApp::SetMacAboutMenuItemId(long val) { 00375 #ifdef __WXMAC__ 00376 s_macAboutMenuItemId = val; 00377 #endif 00378 } 00379 00380 /*static*/ 00381 void wxPyApp::SetMacPreferencesMenuItemId(long val) { 00382 #ifdef __WXMAC__ 00383 s_macPreferencesMenuItemId = val; 00384 #endif 00385 } 00386 00387 /*static*/ 00388 void wxPyApp::SetMacExitMenuItemId(long val) { 00389 #ifdef __WXMAC__ 00390 s_macExitMenuItemId = val; 00391 #endif 00392 } 00393 00394 /*static*/ 00395 void wxPyApp::SetMacHelpMenuTitleName(const wxString& val) { 00396 #ifdef __WXMAC__ 00397 s_macHelpMenuTitleName = val; 00398 #endif 00399 } 00400 00401 00402 // This finishes the initialization of wxWindows and then calls the OnInit 00403 // that should be present in the derived (Python) class. 00404 void wxPyApp::_BootstrapApp() 00405 { 00406 static bool haveInitialized = false; 00407 bool result; 00408 wxPyBlock_t blocked; 00409 PyObject* retval = NULL; 00410 PyObject* pyint = NULL; 00411 00412 00413 // Only initialize wxWidgets once 00414 if (! haveInitialized) { 00415 00416 // Get any command-line args passed to this program from the sys module 00417 int argc = 0; 00418 char** argv = NULL; 00419 blocked = wxPyBeginBlockThreads(); 00420 00421 PyObject* sysargv = PySys_GetObject("argv"); 00422 PyObject* executable = PySys_GetObject("executable"); 00423 00424 if (sysargv != NULL && executable != NULL) { 00425 argc = PyList_Size(sysargv) + 1; 00426 argv = new char*[argc+1]; 00427 argv[0] = strdup(PyString_AsString(executable)); 00428 int x; 00429 for(x=1; x<argc; x++) { 00430 PyObject *pyArg = PyList_GetItem(sysargv, x-1); 00431 argv[x] = strdup(PyString_AsString(pyArg)); 00432 } 00433 argv[argc] = NULL; 00434 } 00435 wxPyEndBlockThreads(blocked); 00436 00437 // Initialize wxWidgets 00438 result = wxEntryStart(argc, argv); 00439 // wxApp takes ownership of the argv array, don't delete it here 00440 00441 blocked = wxPyBeginBlockThreads(); 00442 if (! result) { 00443 PyErr_SetString(PyExc_SystemError, 00444 "wxEntryStart failed, unable to initialize wxWidgets!" 00445 #ifdef __WXGTK__ 00446 " (Is DISPLAY set properly?)" 00447 #endif 00448 ); 00449 goto error; 00450 } 00451 00452 // On wxGTK the locale will be changed to match the system settings, 00453 // but Python before 2.4 needs to have LC_NUMERIC set to "C" in order 00454 // for the floating point conversions and such to work right. 00455 #if defined(__WXGTK__) && PY_VERSION_HEX < 0x02040000 00456 setlocale(LC_NUMERIC, "C"); 00457 #endif 00458 00459 // wxSystemOptions::SetOption(wxT("mac.textcontrol-use-mlte"), 1); 00460 00461 wxPyEndBlockThreads(blocked); 00462 haveInitialized = true; 00463 } 00464 else { 00465 this->argc = 0; 00466 this->argv = NULL; 00467 } 00468 00469 00470 // It's now ok to generate exceptions for assertion errors. 00471 wxPythonApp->SetStartupComplete(true); 00472 00473 00474 // Call the Python wxApp's OnPreInit and OnInit functions 00475 blocked = wxPyBeginBlockThreads(); 00476 if (wxPyCBH_findCallback(m_myInst, "OnPreInit")) { 00477 PyObject* method = m_myInst.GetLastFound(); 00478 PyObject* argTuple = PyTuple_New(0); 00479 retval = PyEval_CallObject(method, argTuple); 00480 m_myInst.clearRecursionGuard(method); 00481 Py_DECREF(argTuple); 00482 Py_DECREF(method); 00483 if (retval == NULL) 00484 goto error; 00485 } 00486 if (wxPyCBH_findCallback(m_myInst, "OnInit")) { 00487 00488 PyObject* method = m_myInst.GetLastFound(); 00489 PyObject* argTuple = PyTuple_New(0); 00490 retval = PyEval_CallObject(method, argTuple); 00491 m_myInst.clearRecursionGuard(method); 00492 Py_DECREF(argTuple); 00493 Py_DECREF(method); 00494 if (retval == NULL) 00495 // Don't PyErr_Print here, let the exception in this case go back 00496 // up to the wx.PyApp.__init__ scope. 00497 goto error; 00498 00499 pyint = PyNumber_Int(retval); 00500 if (! pyint) { 00501 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value"); 00502 goto error; 00503 } 00504 result = PyInt_AS_LONG(pyint); 00505 } 00506 else { 00507 // Is it okay if there is no OnInit? Probably so... 00508 result = true; 00509 } 00510 00511 if (! result) { 00512 PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting..."); 00513 } 00514 00515 error: 00516 Py_XDECREF(retval); 00517 Py_XDECREF(pyint); 00518 00519 wxPyEndBlockThreads(blocked); 00520 }; 00521 00522 //--------------------------------------------------------------------- 00523 //---------------------------------------------------------------------- 00524 00525 00526 #if 0 00527 static char* wxPyCopyCString(const wxChar* src) 00528 { 00529 wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(src); 00530 size_t len = strlen(buff); 00531 char* dest = new char[len+1]; 00532 strcpy(dest, buff); 00533 return dest; 00534 } 00535 00536 #if wxUSE_UNICODE 00537 static char* wxPyCopyCString(const char* src) // we need a char version too 00538 { 00539 size_t len = strlen(src); 00540 char* dest = new char[len+1]; 00541 strcpy(dest, src); 00542 return dest; 00543 } 00544 #endif 00545 00546 static wxChar* wxPyCopyWString(const char *src) 00547 { 00548 //wxMB2WXbuf buff = wxConvCurrent->cMB2WX(src); 00549 wxString str(src, *wxConvCurrent); 00550 return copystring(str); 00551 } 00552 00553 #if wxUSE_UNICODE 00554 static wxChar* wxPyCopyWString(const wxChar *src) 00555 { 00556 return copystring(src); 00557 } 00558 #endif 00559 #endif 00560 00561 00562 inline const char* dropwx(const char* name) { 00563 if (name[0] == 'w' && name[1] == 'x') 00564 return name+2; 00565 else 00566 return name; 00567 } 00568 00569 //---------------------------------------------------------------------- 00570 00571 // This function is called when the wx._core_ module is imported to do some 00572 // initial setup. (Before there is a wxApp object.) The rest happens in 00573 // wxPyApp::_BootstrapApp 00574 void __wxPyPreStart(PyObject* moduleDict) 00575 { 00576 00577 #ifdef __WXMSW__ 00578 // wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF 00579 // | _CRTDBG_CHECK_ALWAYS_DF 00580 // | _CRTDBG_DELAY_FREE_MEM_DF 00581 // ); 00582 #endif 00583 00584 #ifdef WXP_WITH_THREAD 00585 #if wxPyUSE_GIL_STATE 00586 PyEval_InitThreads(); 00587 #else 00588 PyEval_InitThreads(); 00589 wxPyTStates = new wxPyThreadStateArray; 00590 wxPyTMutex = new wxMutex; 00591 00592 // Save the current (main) thread state in our array 00593 PyThreadState* tstate = wxPyBeginAllowThreads(); 00594 wxPyEndAllowThreads(tstate); 00595 #endif 00596 #endif 00597 00598 // Ensure that the build options in the DLL (or whatever) match this build 00599 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython"); 00600 00601 wxInitAllImageHandlers(); 00602 } 00603 00604 00605 00606 void __wxPyCleanup() { 00607 wxPyDoingCleanup = true; 00608 if (wxPyDoCleanup) { 00609 wxPyDoCleanup = false; 00610 wxEntryCleanup(); 00611 } 00612 #ifdef WXP_WITH_THREAD 00613 #if !wxPyUSE_GIL_STATE 00614 delete wxPyTMutex; 00615 wxPyTMutex = NULL; 00616 wxPyTStates->Empty(); 00617 delete wxPyTStates; 00618 wxPyTStates = NULL; 00619 #endif 00620 #endif 00621 } 00622 00623 00624 // Save a reference to the dictionary of the wx._core module, and inject 00625 // a few more things into it. 00626 PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args) 00627 { 00628 00629 if (!PyArg_ParseTuple(args, "O", &wxPython_dict)) 00630 return NULL; 00631 00632 if (!PyDict_Check(wxPython_dict)) { 00633 PyErr_SetString(PyExc_TypeError, 00634 "_wxPySetDictionary must have dictionary object!"); 00635 return NULL; 00636 } 00637 00638 if (! wxPyPtrTypeMap) 00639 wxPyPtrTypeMap = PyDict_New(); 00640 PyDict_SetItemString(wxPython_dict, "__wxPyPtrTypeMap", wxPyPtrTypeMap); 00641 00642 // Create an exception object to use for wxASSERTions 00643 wxPyAssertionError = PyErr_NewException("wx._core.PyAssertionError", 00644 PyExc_AssertionError, NULL); 00645 PyDict_SetItemString(wxPython_dict, "PyAssertionError", wxPyAssertionError); 00646 00647 // Create an exception object to use when the app object hasn't been created yet 00648 wxPyNoAppError = PyErr_NewException("wx._core.PyNoAppError", 00649 PyExc_RuntimeError, NULL); 00650 PyDict_SetItemString(wxPython_dict, "PyNoAppError", wxPyNoAppError); 00651 00652 00653 00654 #ifdef __WXMOTIF__ 00655 #define wxPlatform "__WXMOTIF__" 00656 #define wxPlatName "wxMotif" 00657 #endif 00658 #ifdef __WXX11__ 00659 #define wxPlatform "__WXX11__" 00660 #define wxPlatName "wxX11" 00661 #endif 00662 #ifdef __WXGTK__ 00663 #define wxPlatform "__WXGTK__" 00664 #define wxPlatName "wxGTK" 00665 #endif 00666 #ifdef __WXMSW__ 00667 #define wxPlatform "__WXMSW__" 00668 #define wxPlatName "wxMSW" 00669 #endif 00670 #ifdef __WXMAC__ 00671 #define wxPlatform "__WXMAC__" 00672 #define wxPlatName "wxMac" 00673 #endif 00674 00675 #ifdef __WXDEBUG__ 00676 int wxdebug = 1; 00677 #else 00678 int wxdebug = 0; 00679 #endif 00680 00681 // These should be deprecated in favor of the PlatformInfo tuple built below... 00682 PyDict_SetItemString(wxPython_dict, "Platform", PyString_FromString(wxPlatform)); 00683 PyDict_SetItemString(wxPython_dict, "USE_UNICODE", PyInt_FromLong(wxUSE_UNICODE)); 00684 PyDict_SetItemString(wxPython_dict, "__WXDEBUG__", PyInt_FromLong(wxdebug)); 00685 00686 // Make a tuple of strings that gives more info about the platform. 00687 PyObject* PlatInfo = PyList_New(0); 00688 PyObject* obj; 00689 00690 #define _AddInfoString(st) \ 00691 obj = PyString_FromString(st); \ 00692 PyList_Append(PlatInfo, obj); \ 00693 Py_DECREF(obj) 00694 00695 _AddInfoString(wxPlatform); 00696 _AddInfoString(wxPlatName); 00697 #if wxUSE_UNICODE 00698 _AddInfoString("unicode"); 00699 #else 00700 _AddInfoString("ansi"); 00701 #endif 00702 #ifdef __WXGTK__ 00703 #ifdef __WXGTK20__ 00704 _AddInfoString("gtk2"); 00705 #else 00706 _AddInfoString("gtk1"); 00707 #endif 00708 #endif 00709 #ifdef __WXDEBUG__ 00710 _AddInfoString("wx-assertions-on"); 00711 #else 00712 _AddInfoString("wx-assertions-off"); 00713 #endif 00714 _AddInfoString(wxPy_SWIG_VERSION); 00715 #ifdef __WXMAC__ 00716 #if wxMAC_USE_CORE_GRAPHICS 00717 _AddInfoString("mac-cg"); 00718 #else 00719 _AddInfoString("mac-qd"); 00720 #endif 00721 #if wxMAC_USE_NATIVE_TOOLBAR 00722 _AddInfoString("mac-native-tb"); 00723 #else 00724 _AddInfoString("mac-no-native-tb"); 00725 #endif 00726 #endif 00727 00728 #undef _AddInfoString 00729 00730 PyObject* PlatInfoTuple = PyList_AsTuple(PlatInfo); 00731 Py_DECREF(PlatInfo); 00732 PyDict_SetItemString(wxPython_dict, "PlatformInfo", PlatInfoTuple); 00733 00734 RETURN_NONE(); 00735 } 00736 00737 00738 00739 //--------------------------------------------------------------------------- 00740 00741 // Check for existence of a wxApp, setting an exception if there isn't one. 00742 // This doesn't need to aquire the GIL because it should only be called from 00743 // an %exception before the lock is released. 00744 00745 bool wxPyCheckForApp() { 00746 if (wxTheApp != NULL) 00747 return true; 00748 else { 00749 PyErr_SetString(wxPyNoAppError, "The wx.App object must be created first!"); 00750 return false; 00751 } 00752 } 00753 00754 //--------------------------------------------------------------------------- 00755 00756 void wxPyUserData_dtor(wxPyUserData* self) { 00757 if (! wxPyDoingCleanup) { 00758 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00759 Py_DECREF(self->m_obj); 00760 self->m_obj = NULL; 00761 wxPyEndBlockThreads(blocked); 00762 } 00763 } 00764 00765 00766 void wxPyClientData_dtor(wxPyClientData* self) { 00767 if (! wxPyDoingCleanup) { // Don't do it during cleanup as Python 00768 // may have already garbage collected the object... 00769 if (self->m_incRef) { 00770 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00771 Py_DECREF(self->m_obj); 00772 wxPyEndBlockThreads(blocked); 00773 } 00774 self->m_obj = NULL; 00775 } 00776 } 00777 00778 00779 00780 // This is called when an OOR controled object is being destroyed. Although 00781 // the C++ object is going away there is no way to force the Python object 00782 // (and all references to it) to die too. This causes problems (crashes) in 00783 // wxPython when a python shadow object attempts to call a C++ method using 00784 // the now bogus pointer... So to try and prevent this we'll do a little black 00785 // magic and change the class of the python instance to a class that will 00786 // raise an exception for any attempt to call methods with it. See 00787 // _wxPyDeadObject in _core_ex.py for the implementation of this class. 00788 void wxPyOORClientData_dtor(wxPyOORClientData* self) { 00789 00790 static PyObject* deadObjectClass = NULL; 00791 00792 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 00793 if (deadObjectClass == NULL) { 00794 deadObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyDeadObject"); 00795 // TODO: Can not wxASSERT here because inside a wxPyBeginBlock Threads, 00796 // will lead to a deadlock when it tries to aquire the GIL again. 00797 //wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!")); 00798 Py_INCREF(deadObjectClass); 00799 } 00800 00801 00802 // Only if there is more than one reference to the object and we are 00803 // holding the OOR reference: 00804 if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 && self->m_incRef) { 00805 // bool isInstance = wxPyInstance_Check(self->m_obj); 00806 // TODO same here 00807 //wxASSERT_MSG(isInstance, wxT("m_obj not an instance!?!?!")); 00808 00809 // Call __del__, if there is one. 00810 PyObject* func = PyObject_GetAttrString(self->m_obj, "__del__"); 00811 if (func) { 00812 PyObject* rv = PyObject_CallMethod(self->m_obj, "__del__", NULL); 00813 Py_XDECREF(rv); 00814 Py_DECREF(func); 00815 } 00816 if (PyErr_Occurred()) 00817 PyErr_Clear(); // just ignore it for now 00818 00819 00820 PyObject* dict = PyObject_GetAttrString(self->m_obj, "__dict__"); 00821 if (dict) { 00822 // Clear the instance's dictionary 00823 PyDict_Clear(dict); 00824 00825 // put the name of the old class into the instance, and then reset the 00826 // class to be the dead class. 00827 PyObject* klass = PyObject_GetAttrString(self->m_obj, "__class__"); 00828 PyObject* name = PyObject_GetAttrString(klass, "__name__"); 00829 PyDict_SetItemString(dict, "_name", name); 00830 PyObject_SetAttrString(self->m_obj, "__class__", deadObjectClass); 00831 //Py_INCREF(deadObjectClass); 00832 Py_DECREF(klass); 00833 Py_DECREF(name); 00834 } 00835 } 00836 00837 // m_obj is DECREF'd in the base class dtor... 00838 wxPyEndBlockThreads(blocked); 00839 } 00840 00841 00842 //--------------------------------------------------------------------------- 00843 // Stuff used by OOR to find the right wxPython class type to return and to 00844 // build it. 00845 00846 00847 // The pointer type map is used when the "pointer" type name generated by SWIG 00848 // is not the same as the shadow class name, for example wxPyTreeCtrl 00849 // vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++, 00850 // so we'll just make it a Python dictionary in the wx module's namespace. 00851 // (See __wxSetDictionary) 00852 void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) { 00853 if (! wxPyPtrTypeMap) 00854 wxPyPtrTypeMap = PyDict_New(); 00855 PyDict_SetItemString(wxPyPtrTypeMap, 00856 (char*)commonName, 00857 PyString_FromString((char*)ptrName)); 00858 } 00859 00860 00861 00862 00863 PyObject* wxPyMake_wxObject(wxObject* source, bool setThisOwn, bool checkEvtHandler) { 00864 PyObject* target = NULL; 00865 bool isEvtHandler = false; 00866 bool isSizer = false; 00867 00868 if (source) { 00869 // If it's derived from wxEvtHandler then there may 00870 // already be a pointer to a Python object that we can use 00871 // in the OOR data. 00872 if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) { 00873 isEvtHandler = true; 00874 wxEvtHandler* eh = (wxEvtHandler*)source; 00875 wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject(); 00876 if (data) { 00877 target = data->m_obj; 00878 if (target) 00879 Py_INCREF(target); 00880 } 00881 } 00882 00883 // Also check for wxSizer 00884 if (!target && wxIsKindOf(source, wxSizer)) { 00885 isSizer = true; 00886 wxSizer* sz = (wxSizer*)source; 00887 wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject(); 00888 if (data) { 00889 target = data->m_obj; 00890 if (target) 00891 Py_INCREF(target); 00892 } 00893 } 00894 00895 if (! target) { 00896 // Otherwise make it the old fashioned way by making a new shadow 00897 // object and putting this pointer in it. Look up the class 00898 // heirarchy until we find a class name that is located in the 00899 // python module. 00900 const wxClassInfo* info = source->GetClassInfo(); 00901 wxString name = info->GetClassName(); 00902 bool exists = wxPyCheckSwigType(name); 00903 while (info && !exists) { 00904 info = info->GetBaseClass1(); 00905 name = info->GetClassName(); 00906 exists = wxPyCheckSwigType(name); 00907 } 00908 if (info) { 00909 target = wxPyConstructObject((void*)source, name, setThisOwn); 00910 if (target && isEvtHandler) 00911 ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target)); 00912 if (target && isSizer) 00913 ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target)); 00914 } else { 00915 wxString msg(wxT("wxPython class not found for ")); 00916 msg += source->GetClassInfo()->GetClassName(); 00917 PyErr_SetString(PyExc_NameError, msg.mbc_str()); 00918 target = NULL; 00919 } 00920 } 00921 } else { // source was NULL so return None. 00922 Py_INCREF(Py_None); target = Py_None; 00923 } 00924 return target; 00925 } 00926 00927 00928 PyObject* wxPyMake_wxSizer(wxSizer* source, bool setThisOwn) { 00929 00930 return wxPyMake_wxObject(source, setThisOwn); 00931 } 00932 00933 00934 //--------------------------------------------------------------------------- 00935 00936 00937 #ifdef WXP_WITH_THREAD 00938 #if !wxPyUSE_GIL_STATE 00939 00940 inline 00941 unsigned long wxPyGetCurrentThreadId() { 00942 return wxThread::GetCurrentId(); 00943 } 00944 00945 static wxPyThreadState gs_shutdownTState; 00946 00947 static 00948 wxPyThreadState* wxPyGetThreadState() { 00949 if (wxPyTMutex == NULL) // Python is shutting down... 00950 return &gs_shutdownTState; 00951 00952 unsigned long ctid = wxPyGetCurrentThreadId(); 00953 wxPyThreadState* tstate = NULL; 00954 00955 wxPyTMutex->Lock(); 00956 for(size_t i=0; i < wxPyTStates->GetCount(); i++) { 00957 wxPyThreadState& info = wxPyTStates->Item(i); 00958 if (info.tid == ctid) { 00959 tstate = &info; 00960 break; 00961 } 00962 } 00963 wxPyTMutex->Unlock(); 00964 wxASSERT_MSG(tstate, wxT("PyThreadState should not be NULL!")); 00965 return tstate; 00966 } 00967 00968 00969 static 00970 void wxPySaveThreadState(PyThreadState* tstate) { 00971 if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread... 00972 gs_shutdownTState.tstate = tstate; 00973 return; 00974 } 00975 unsigned long ctid = wxPyGetCurrentThreadId(); 00976 wxPyTMutex->Lock(); 00977 for(size_t i=0; i < wxPyTStates->GetCount(); i++) { 00978 wxPyThreadState& info = wxPyTStates->Item(i); 00979 if (info.tid == ctid) { 00980 #if 0 00981 if (info.tstate != tstate) 00982 wxLogMessage("*** tstate mismatch!???"); 00983 #endif 00984 info.tstate = tstate; // allow for transient tstates 00985 // Normally it will never change, but apparently COM callbacks 00986 // (i.e. ActiveX controls) will (incorrectly IMHO) use a transient 00987 // tstate which will then be garbage the next time we try to use 00988 // it... 00989 00990 wxPyTMutex->Unlock(); 00991 return; 00992 } 00993 } 00994 // not found, so add it... 00995 wxPyTStates->Add(new wxPyThreadState(ctid, tstate)); 00996 wxPyTMutex->Unlock(); 00997 } 00998 00999 #endif 01000 #endif 01001 01002 01003 01004 // Calls from Python to wxWindows code are wrapped in calls to these 01005 // functions: 01006 01007 PyThreadState* wxPyBeginAllowThreads() { 01008 #ifdef WXP_WITH_THREAD 01009 PyThreadState* saved = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS; 01010 #if !wxPyUSE_GIL_STATE 01011 wxPySaveThreadState(saved); 01012 #endif 01013 return saved; 01014 #else 01015 return NULL; 01016 #endif 01017 } 01018 01019 void wxPyEndAllowThreads(PyThreadState* saved) { 01020 #ifdef WXP_WITH_THREAD 01021 PyEval_RestoreThread(saved); // Py_END_ALLOW_THREADS; 01022 #endif 01023 } 01024 01025 01026 01027 // Calls from wxWindows back to Python code, or even any PyObject 01028 // manipulations, PyDECREF's and etc. are wrapped in calls to these functions: 01029 01030 wxPyBlock_t wxPyBeginBlockThreads() { 01031 #ifdef WXP_WITH_THREAD 01032 if (! Py_IsInitialized()) { 01033 return (wxPyBlock_t)0; 01034 } 01035 #if wxPyUSE_GIL_STATE 01036 PyGILState_STATE state = PyGILState_Ensure(); 01037 return state; 01038 #else 01039 PyThreadState *current = _PyThreadState_Current; 01040 01041 // Only block if there wasn't already a tstate, or if the current one is 01042 // not the one we are wanting to change to. This should prevent deadlock 01043 // if there are nested calls to wxPyBeginBlockThreads 01044 wxPyBlock_t blocked = false; 01045 wxPyThreadState* tstate = wxPyGetThreadState(); 01046 if (current != tstate->tstate) { 01047 PyEval_RestoreThread(tstate->tstate); 01048 blocked = true; 01049 } 01050 return blocked; 01051 #endif 01052 #else 01053 return (wxPyBlock_t)0; 01054 #endif 01055 } 01056 01057 01058 void wxPyEndBlockThreads(wxPyBlock_t blocked) { 01059 #ifdef WXP_WITH_THREAD 01060 if (! Py_IsInitialized()) { 01061 return; 01062 } 01063 #if wxPyUSE_GIL_STATE 01064 PyGILState_Release(blocked); 01065 #else 01066 // Only unblock if we blocked in the last call to wxPyBeginBlockThreads. 01067 // The value of blocked passed in needs to be the same as that returned 01068 // from wxPyBeginBlockThreads at the same nesting level. 01069 if ( blocked ) { 01070 PyEval_SaveThread(); 01071 } 01072 #endif 01073 #endif 01074 } 01075 01076 01077 //--------------------------------------------------------------------------- 01078 // wxPyInputStream and wxPyCBInputStream methods 01079 01080 01081 void wxPyInputStream::close() { 01082 /* do nothing for now */ 01083 } 01084 01085 void wxPyInputStream::flush() { 01086 /* do nothing for now */ 01087 } 01088 01089 bool wxPyInputStream::eof() { 01090 if (m_wxis) 01091 return m_wxis->Eof(); 01092 else 01093 return true; 01094 } 01095 01096 wxPyInputStream::~wxPyInputStream() { 01097 if (m_wxis) 01098 delete m_wxis; 01099 } 01100 01101 01102 01103 01104 PyObject* wxPyInputStream::read(int size) { 01105 PyObject* obj = NULL; 01106 wxMemoryBuffer buf; 01107 const int BUFSIZE = 1024; 01108 01109 // check if we have a real wxInputStream to work with 01110 if (!m_wxis) { 01111 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01112 PyErr_SetString(PyExc_IOError, "no valid C-wxInputStream"); 01113 wxPyEndBlockThreads(blocked); 01114 return NULL; 01115 } 01116 01117 if (size < 0) { 01118 // read while bytes are available on the stream 01119 while ( m_wxis->CanRead() ) { 01120 m_wxis->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE); 01121 buf.UngetAppendBuf(m_wxis->LastRead()); 01122 } 01123 01124 } else { // Read only size number of characters 01125 m_wxis->Read(buf.GetWriteBuf(size), size); 01126 buf.UngetWriteBuf(m_wxis->LastRead()); 01127 } 01128 01129 // error check 01130 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01131 wxStreamError err = m_wxis->GetLastError(); 01132 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) { 01133 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); 01134 } 01135 else { 01136 // We use only strings for the streams, not unicode 01137 obj = PyString_FromStringAndSize(buf, buf.GetDataLen()); 01138 } 01139 wxPyEndBlockThreads(blocked); 01140 return obj; 01141 } 01142 01143 01144 PyObject* wxPyInputStream::readline(int size) { 01145 PyObject* obj = NULL; 01146 wxMemoryBuffer buf; 01147 int i; 01148 char ch; 01149 01150 // check if we have a real wxInputStream to work with 01151 if (!m_wxis) { 01152 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01153 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream"); 01154 wxPyEndBlockThreads(blocked); 01155 return NULL; 01156 } 01157 01158 // read until \n or byte limit reached 01159 for (i=ch=0; (ch != '\n') && (m_wxis->CanRead()) && ((size < 0) || (i < size)); i++) { 01160 ch = m_wxis->GetC(); 01161 buf.AppendByte(ch); 01162 } 01163 01164 // errorcheck 01165 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01166 wxStreamError err = m_wxis->GetLastError(); 01167 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) { 01168 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); 01169 } 01170 else { 01171 // We use only strings for the streams, not unicode 01172 obj = PyString_FromStringAndSize((char*)buf.GetData(), buf.GetDataLen()); 01173 } 01174 wxPyEndBlockThreads(blocked); 01175 return obj; 01176 } 01177 01178 01179 PyObject* wxPyInputStream::readlines(int sizehint) { 01180 PyObject* pylist; 01181 01182 // check if we have a real wxInputStream to work with 01183 if (!m_wxis) { 01184 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01185 PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream"); 01186 wxPyEndBlockThreads(blocked); 01187 return NULL; 01188 } 01189 01190 // init list 01191 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01192 pylist = PyList_New(0); 01193 wxPyEndBlockThreads(blocked); 01194 01195 if (!pylist) { 01196 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01197 PyErr_NoMemory(); 01198 wxPyEndBlockThreads(blocked); 01199 return NULL; 01200 } 01201 01202 // read sizehint bytes or until EOF 01203 int i; 01204 for (i=0; (m_wxis->CanRead()) && ((sizehint < 0) || (i < sizehint));) { 01205 PyObject* s = this->readline(); 01206 if (s == NULL) { 01207 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01208 Py_DECREF(pylist); 01209 wxPyEndBlockThreads(blocked); 01210 return NULL; 01211 } 01212 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01213 PyList_Append(pylist, s); 01214 i += PyString_Size(s); 01215 wxPyEndBlockThreads(blocked); 01216 } 01217 01218 // error check 01219 wxStreamError err = m_wxis->GetLastError(); 01220 if (err != wxSTREAM_NO_ERROR && err != wxSTREAM_EOF) { 01221 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01222 Py_DECREF(pylist); 01223 PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); 01224 wxPyEndBlockThreads(blocked); 01225 return NULL; 01226 } 01227 01228 return pylist; 01229 } 01230 01231 01232 void wxPyInputStream::seek(int offset, int whence) { 01233 if (m_wxis) 01234 m_wxis->SeekI(offset, wxSeekMode(whence)); 01235 } 01236 01237 int wxPyInputStream::tell(){ 01238 if (m_wxis) 01239 return m_wxis->TellI(); 01240 else return 0; 01241 } 01242 01243 01244 01245 01246 wxPyCBInputStream::wxPyCBInputStream(PyObject *r, PyObject *s, PyObject *t, bool block) 01247 : wxInputStream(), m_read(r), m_seek(s), m_tell(t), m_block(block) 01248 {} 01249 01250 wxPyCBInputStream::wxPyCBInputStream(const wxPyCBInputStream& other) 01251 { 01252 m_read = other.m_read; 01253 m_seek = other.m_seek; 01254 m_tell = other.m_tell; 01255 m_block = other.m_block; 01256 Py_INCREF(m_read); 01257 Py_INCREF(m_seek); 01258 Py_INCREF(m_tell); 01259 } 01260 01261 01262 wxPyCBInputStream::~wxPyCBInputStream() { 01263 wxPyBlock_t blocked = wxPyBlock_t_default; 01264 if (m_block) blocked = wxPyBeginBlockThreads(); 01265 Py_XDECREF(m_read); 01266 Py_XDECREF(m_seek); 01267 Py_XDECREF(m_tell); 01268 if (m_block) wxPyEndBlockThreads(blocked); 01269 } 01270 01271 01272 wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) { 01273 wxPyBlock_t blocked = wxPyBlock_t_default; 01274 if (block) blocked = wxPyBeginBlockThreads(); 01275 01276 PyObject* read = getMethod(py, "read"); 01277 PyObject* seek = getMethod(py, "seek"); 01278 PyObject* tell = getMethod(py, "tell"); 01279 01280 if (!read) { 01281 PyErr_SetString(PyExc_TypeError, "Not a file-like object"); 01282 Py_XDECREF(read); 01283 Py_XDECREF(seek); 01284 Py_XDECREF(tell); 01285 if (block) wxPyEndBlockThreads(blocked); 01286 return NULL; 01287 } 01288 01289 if (block) wxPyEndBlockThreads(blocked); 01290 return new wxPyCBInputStream(read, seek, tell, block); 01291 } 01292 01293 01294 wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block) { 01295 return wxPyCBInputStream::create(py, block); 01296 } 01297 01298 wxPyCBInputStream* wxPyCBInputStream_copy(wxPyCBInputStream* other) { 01299 return new wxPyCBInputStream(*other); 01300 } 01301 01302 PyObject* wxPyCBInputStream::getMethod(PyObject* py, char* name) { 01303 if (!PyObject_HasAttrString(py, name)) 01304 return NULL; 01305 PyObject* o = PyObject_GetAttrString(py, name); 01306 if (!PyMethod_Check(o) && !PyCFunction_Check(o)) { 01307 Py_DECREF(o); 01308 return NULL; 01309 } 01310 return o; 01311 } 01312 01313 01314 wxFileOffset wxPyCBInputStream::GetLength() const { 01315 wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const 01316 if (m_seek && m_tell) { 01317 wxFileOffset temp = self->OnSysTell(); 01318 wxFileOffset ret = self->OnSysSeek(0, wxFromEnd); 01319 self->OnSysSeek(temp, wxFromStart); 01320 return ret; 01321 } 01322 else 01323 return wxInvalidOffset; 01324 } 01325 01326 01327 size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) { 01328 if (bufsize == 0) 01329 return 0; 01330 01331 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01332 PyObject* arglist = Py_BuildValue("(i)", bufsize); 01333 PyObject* result = PyEval_CallObject(m_read, arglist); 01334 Py_DECREF(arglist); 01335 01336 size_t o = 0; 01337 if ((result != NULL) && PyString_Check(result)) { 01338 o = PyString_Size(result); 01339 if (o == 0) 01340 m_lasterror = wxSTREAM_EOF; 01341 if (o > bufsize) 01342 o = bufsize; 01343 memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode... 01344 Py_DECREF(result); 01345 01346 } 01347 else 01348 m_lasterror = wxSTREAM_READ_ERROR; 01349 wxPyEndBlockThreads(blocked); 01350 return o; 01351 } 01352 01353 size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) { 01354 m_lasterror = wxSTREAM_WRITE_ERROR; 01355 return 0; 01356 } 01357 01358 01359 wxFileOffset wxPyCBInputStream::OnSysSeek(wxFileOffset off, wxSeekMode mode) { 01360 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01361 PyObject* arglist = PyTuple_New(2); 01362 01363 if (sizeof(wxFileOffset) > sizeof(long)) 01364 // wxFileOffset is a 64-bit value... 01365 PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off)); 01366 else 01367 PyTuple_SET_ITEM(arglist, 0, PyInt_FromLong(off)); 01368 01369 PyTuple_SET_ITEM(arglist, 1, PyInt_FromLong(mode)); 01370 01371 01372 PyObject* result = PyEval_CallObject(m_seek, arglist); 01373 Py_DECREF(arglist); 01374 Py_XDECREF(result); 01375 wxPyEndBlockThreads(blocked); 01376 return OnSysTell(); 01377 } 01378 01379 01380 wxFileOffset wxPyCBInputStream::OnSysTell() const { 01381 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01382 PyObject* arglist = Py_BuildValue("()"); 01383 PyObject* result = PyEval_CallObject(m_tell, arglist); 01384 Py_DECREF(arglist); 01385 wxFileOffset o = 0; 01386 if (result != NULL) { 01387 if (PyLong_Check(result)) 01388 o = PyLong_AsLongLong(result); 01389 else 01390 o = PyInt_AsLong(result); 01391 Py_DECREF(result); 01392 }; 01393 wxPyEndBlockThreads(blocked); 01394 return o; 01395 } 01396 01397 //---------------------------------------------------------------------- 01398 01399 IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject); 01400 01401 wxPyCallback::wxPyCallback(PyObject* func) { 01402 m_func = func; 01403 Py_INCREF(m_func); 01404 } 01405 01406 wxPyCallback::wxPyCallback(const wxPyCallback& other) { 01407 m_func = other.m_func; 01408 Py_INCREF(m_func); 01409 } 01410 01411 wxPyCallback::~wxPyCallback() { 01412 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01413 Py_DECREF(m_func); 01414 wxPyEndBlockThreads(blocked); 01415 } 01416 01417 01418 #define wxPy_PRECALLINIT "_preCallInit" 01419 #define wxPy_POSTCALLCLEANUP "_postCallCleanup" 01420 01421 // This function is used for all events destined for Python event handlers. 01422 void wxPyCallback::EventThunker(wxEvent& event) { 01423 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData; 01424 PyObject* func = cb->m_func; 01425 PyObject* result; 01426 PyObject* arg; 01427 PyObject* tuple; 01428 bool checkSkip = false; 01429 01430 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01431 wxString className = event.GetClassInfo()->GetClassName(); 01432 01433 // If the event is one of these types then pass the original 01434 // event object instead of the one passed to us. 01435 if ( className == wxT("wxPyEvent") ) { 01436 arg = ((wxPyEvent*)&event)->GetSelf(); 01437 checkSkip = ((wxPyEvent*)&event)->GetCloned(); 01438 } 01439 else if ( className == wxT("wxPyCommandEvent") ) { 01440 arg = ((wxPyCommandEvent*)&event)->GetSelf(); 01441 checkSkip = ((wxPyCommandEvent*)&event)->GetCloned(); 01442 } 01443 else { 01444 arg = wxPyConstructObject((void*)&event, className); 01445 } 01446 01447 if (!arg) { 01448 PyErr_Print(); 01449 } else { 01450 // "intern" the pre/post method names to speed up the HasAttr 01451 static PyObject* s_preName = NULL; 01452 static PyObject* s_postName = NULL; 01453 if (s_preName == NULL) { 01454 s_preName = PyString_FromString(wxPy_PRECALLINIT); 01455 s_postName = PyString_FromString(wxPy_POSTCALLCLEANUP); 01456 } 01457 01458 // Check if the event object needs some preinitialization 01459 if (PyObject_HasAttr(arg, s_preName)) { 01460 result = PyObject_CallMethodObjArgs(arg, s_preName, arg, NULL); 01461 if ( result ) { 01462 Py_DECREF(result); // result is ignored, but we still need to decref it 01463 PyErr_Clear(); // Just in case... 01464 } else { 01465 PyErr_Print(); 01466 } 01467 } 01468 01469 // Call the event handler, passing the event object 01470 tuple = PyTuple_New(1); 01471 PyTuple_SET_ITEM(tuple, 0, arg); // steals ref to arg 01472 result = PyEval_CallObject(func, tuple); 01473 if ( result ) { 01474 Py_DECREF(result); // result is ignored, but we still need to decref it 01475 PyErr_Clear(); // Just in case... 01476 } else { 01477 PyErr_Print(); 01478 } 01479 01480 // Check if the event object needs some post cleanup 01481 if (PyObject_HasAttr(arg, s_postName)) { 01482 result = PyObject_CallMethodObjArgs(arg, s_postName, arg, NULL); 01483 if ( result ) { 01484 Py_DECREF(result); // result is ignored, but we still need to decref it 01485 PyErr_Clear(); // Just in case... 01486 } else { 01487 PyErr_Print(); 01488 } 01489 } 01490 01491 if ( checkSkip ) { 01492 // if the event object was one of our special types and 01493 // it had been cloned, then we need to extract the Skipped 01494 // value from the original and set it in the clone. 01495 result = PyObject_CallMethod(arg, "GetSkipped", ""); 01496 if ( result ) { 01497 event.Skip(PyInt_AsLong(result)); 01498 Py_DECREF(result); 01499 } else { 01500 PyErr_Print(); 01501 } 01502 } 01503 Py_DECREF(tuple); 01504 } 01505 wxPyEndBlockThreads(blocked); 01506 } 01507 01508 01509 //---------------------------------------------------------------------- 01510 01511 wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) { 01512 m_lastFound = NULL; 01513 m_self = other.m_self; 01514 m_class = other.m_class; 01515 if (m_self) { 01516 Py_INCREF(m_self); 01517 Py_INCREF(m_class); 01518 } 01519 } 01520 01521 01522 void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) { 01523 m_self = self; 01524 m_class = klass; 01525 m_incRef = incref; 01526 if (incref) { 01527 Py_INCREF(m_self); 01528 Py_INCREF(m_class); 01529 } 01530 } 01531 01532 01533 #if PYTHON_API_VERSION >= 1011 01534 01535 // Prior to Python 2.2 PyMethod_GetClass returned the class object 01536 // in which the method was defined. Starting with 2.2 it returns 01537 // "class that asked for the method" which seems totally bogus to me 01538 // but apprently it fixes some obscure problem waiting to happen in 01539 // Python. Since the API was not documented Guido and the gang felt 01540 // safe in changing it. Needless to say that totally screwed up the 01541 // logic below in wxPyCallbackHelper::findCallback, hence this icky 01542 // code to find the class where the method is actually defined... 01543 01544 static 01545 PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name) 01546 { 01547 int i, n; 01548 01549 if (PyType_Check(klass)) { // new style classes 01550 // This code is borrowed/adapted from _PyType_Lookup in typeobject.c 01551 PyTypeObject* type = (PyTypeObject*)klass; 01552 PyObject *mro, *res, *base, *dict; 01553 /* Look in tp_dict of types in MRO */ 01554 mro = type->tp_mro; 01555 assert(PyTuple_Check(mro)); 01556 n = PyTuple_GET_SIZE(mro); 01557 for (i = 0; i < n; i++) { 01558 base = PyTuple_GET_ITEM(mro, i); 01559 if (PyClass_Check(base)) 01560 dict = ((PyClassObject *)base)->cl_dict; 01561 else { 01562 assert(PyType_Check(base)); 01563 dict = ((PyTypeObject *)base)->tp_dict; 01564 } 01565 assert(dict && PyDict_Check(dict)); 01566 res = PyDict_GetItem(dict, name); 01567 if (res != NULL) 01568 return base; 01569 } 01570 return NULL; 01571 } 01572 01573 else if (PyClass_Check(klass)) { // old style classes 01574 // This code is borrowed/adapted from class_lookup in classobject.c 01575 PyClassObject* cp = (PyClassObject*)klass; 01576 PyObject *value = PyDict_GetItem(cp->cl_dict, name); 01577 if (value != NULL) { 01578 return (PyObject*)cp; 01579 } 01580 n = PyTuple_Size(cp->cl_bases); 01581 for (i = 0; i < n; i++) { 01582 PyObject* base = PyTuple_GetItem(cp->cl_bases, i); 01583 PyObject *v = PyFindClassWithAttr(base, name); 01584 if (v != NULL) 01585 return v; 01586 } 01587 return NULL; 01588 } 01589 return NULL; 01590 } 01591 #endif 01592 01593 01594 static 01595 PyObject* PyMethod_GetDefiningClass(PyObject* method, PyObject* nameo) 01596 { 01597 PyObject* mgc = PyMethod_GET_CLASS(method); 01598 01599 #if PYTHON_API_VERSION <= 1010 // prior to Python 2.2, the easy way 01600 return mgc; 01601 #else // 2.2 and after, the hard way... 01602 return PyFindClassWithAttr(mgc, nameo); 01603 #endif 01604 } 01605 01606 01607 01608 // To avoid recursion when an overridden virtual method wants to call the base 01609 // class version, temporarily set an attribute in the instance with the same 01610 // name as the method. Then the PyObject_GetAttr in the next findCallback 01611 // will return this attribute and the PyMethod_Check will fail. 01612 01613 void wxPyCallbackHelper::setRecursionGuard(PyObject* method) const 01614 { 01615 PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method); 01616 PyObject_SetAttr(m_self, func->func_name, Py_None); 01617 } 01618 01619 void wxPyCallbackHelper::clearRecursionGuard(PyObject* method) const 01620 { 01621 PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method); 01622 if (PyObject_HasAttr(m_self, func->func_name)) { 01623 PyObject_DelAttr(m_self, func->func_name); 01624 } 01625 } 01626 01627 // bool wxPyCallbackHelper::hasRecursionGuard(PyObject* method) const 01628 // { 01629 // PyFunctionObject* func = (PyFunctionObject*)PyMethod_Function(method); 01630 // if (PyObject_HasAttr(m_self, func->func_name)) { 01631 // PyObject* attr = PyObject_GetAttr(m_self, func->func_name); 01632 // bool retval = (attr == Py_None); 01633 // Py_DECREF(attr); 01634 // return retval; 01635 // } 01636 // return false; 01637 // } 01638 01639 01640 bool wxPyCallbackHelper::findCallback(const char* name, bool setGuard) const { 01641 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const 01642 PyObject *method, *klass; 01643 PyObject* nameo = PyString_FromString(name); 01644 self->m_lastFound = NULL; 01645 01646 // If the object (m_self) has an attibute of the given name... 01647 if (m_self && PyObject_HasAttr(m_self, nameo)) { 01648 method = PyObject_GetAttr(m_self, nameo); 01649 01650 // ...and if that attribute is a method, and if that method's class is 01651 // not from the registered class or a base class... 01652 if (PyMethod_Check(method) && 01653 (klass = PyMethod_GetDefiningClass(method, nameo)) != NULL && 01654 (klass != m_class) && 01655 PyObject_IsSubclass(klass, m_class)) { 01656 01657 // ...then we'll save a pointer to the method so callCallback can 01658 // call it. But first, set a recursion guard in case the 01659 // overridden method wants to call the base class version. 01660 if (setGuard) 01661 setRecursionGuard(method); 01662 self->m_lastFound = method; 01663 } 01664 else { 01665 Py_DECREF(method); 01666 } 01667 } 01668 01669 Py_DECREF(nameo); 01670 return m_lastFound != NULL; 01671 } 01672 01673 01674 int wxPyCallbackHelper::callCallback(PyObject* argTuple) const { 01675 PyObject* result; 01676 int retval = false; 01677 01678 result = callCallbackObj(argTuple); 01679 if (result) { // Assumes an integer return type... 01680 retval = PyInt_AsLong(result); 01681 Py_DECREF(result); 01682 PyErr_Clear(); // forget about it if it's not... 01683 } 01684 return retval; 01685 } 01686 01687 // Invoke the Python callable object, returning the raw PyObject return 01688 // value. Caller should DECREF the return value and also manage the GIL. 01689 PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const { 01690 PyObject* result; 01691 01692 // Save a copy of the pointer in case the callback generates another 01693 // callback. In that case m_lastFound will have a different value when 01694 // it gets back here... 01695 PyObject* method = m_lastFound; 01696 01697 result = PyEval_CallObject(method, argTuple); 01698 clearRecursionGuard(method); 01699 01700 Py_DECREF(argTuple); 01701 Py_DECREF(method); 01702 if (!result) { 01703 PyErr_Print(); 01704 } 01705 return result; 01706 } 01707 01708 01709 void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) { 01710 cbh.setSelf(self, klass, incref); 01711 } 01712 01713 bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name, bool setGuard) { 01714 return cbh.findCallback(name, setGuard); 01715 } 01716 01717 int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) { 01718 return cbh.callCallback(argTuple); 01719 } 01720 01721 PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) { 01722 return cbh.callCallbackObj(argTuple); 01723 } 01724 01725 01726 void wxPyCBH_delete(wxPyCallbackHelper* cbh) { 01727 if (cbh->m_incRef && Py_IsInitialized()) { 01728 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01729 Py_XDECREF(cbh->m_self); 01730 Py_XDECREF(cbh->m_class); 01731 wxPyEndBlockThreads(blocked); 01732 } 01733 } 01734 01735 //--------------------------------------------------------------------------- 01736 //--------------------------------------------------------------------------- 01737 // These event classes can be derived from in Python and passed through the event 01738 // system without losing anything. They do this by keeping a reference to 01739 // themselves and some special case handling in wxPyCallback::EventThunker. 01740 01741 01742 wxPyEvtSelfRef::wxPyEvtSelfRef() { 01743 //m_self = Py_None; // **** We don't do normal ref counting to prevent 01744 //Py_INCREF(m_self); // circular loops... 01745 m_cloned = false; 01746 } 01747 01748 wxPyEvtSelfRef::~wxPyEvtSelfRef() { 01749 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01750 if (m_cloned) 01751 Py_DECREF(m_self); 01752 wxPyEndBlockThreads(blocked); 01753 } 01754 01755 void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) { 01756 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01757 if (m_cloned) 01758 Py_DECREF(m_self); 01759 m_self = self; 01760 if (clone) { 01761 Py_INCREF(m_self); 01762 m_cloned = true; 01763 } 01764 wxPyEndBlockThreads(blocked); 01765 } 01766 01767 PyObject* wxPyEvtSelfRef::GetSelf() const { 01768 Py_INCREF(m_self); 01769 return m_self; 01770 } 01771 01772 01773 IMPLEMENT_ABSTRACT_CLASS(wxPyEvent, wxEvent); 01774 IMPLEMENT_ABSTRACT_CLASS(wxPyCommandEvent, wxCommandEvent); 01775 01776 01777 wxPyEvent::wxPyEvent(int winid, wxEventType commandType) 01778 : wxEvent(winid, commandType) { 01779 } 01780 01781 01782 wxPyEvent::wxPyEvent(const wxPyEvent& evt) 01783 : wxEvent(evt) 01784 { 01785 SetSelf(evt.m_self, true); 01786 } 01787 01788 01789 wxPyEvent::~wxPyEvent() { 01790 } 01791 01792 01793 wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id) 01794 : wxCommandEvent(commandType, id) { 01795 } 01796 01797 01798 wxPyCommandEvent::wxPyCommandEvent(const wxPyCommandEvent& evt) 01799 : wxCommandEvent(evt) 01800 { 01801 SetSelf(evt.m_self, true); 01802 } 01803 01804 01805 wxPyCommandEvent::~wxPyCommandEvent() { 01806 } 01807 01808 01809 01810 01811 01812 //--------------------------------------------------------------------------- 01813 //--------------------------------------------------------------------------- 01814 // Convert a wxList to a Python List, only works for lists of wxObjects 01815 01816 PyObject* wxPy_ConvertList(wxListBase* listbase) { 01817 wxList* list = (wxList*)listbase; // this is probably bad... 01818 PyObject* pyList; 01819 PyObject* pyObj; 01820 wxObject* wxObj; 01821 wxNode* node = list->GetFirst(); 01822 01823 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 01824 pyList = PyList_New(0); 01825 while (node) { 01826 wxObj = node->GetData(); 01827 pyObj = wxPyMake_wxObject(wxObj,false); 01828 PyList_Append(pyList, pyObj); 01829 Py_DECREF(pyObj); // the Append also does an INCREF, that's one more than we need. 01830 node = node->GetNext(); 01831 } 01832 wxPyEndBlockThreads(blocked); 01833 return pyList; 01834 } 01835 01836 //---------------------------------------------------------------------- 01837 01838 long wxPyGetWinHandle(wxWindow* win) { 01839 01840 #ifdef __WXMSW__ 01841 return (long)win->GetHandle(); 01842 #endif 01843 01844 #if defined(__WXGTK__) || defined(__WXX11) 01845 return (long)GetXWindow(win); 01846 #endif 01847 01848 #ifdef __WXMAC__ 01849 //return (long)MAC_WXHWND(win->MacGetTopLevelWindowRef()); 01850 return (long)win->GetHandle(); 01851 #endif 01852 01853 return 0; 01854 } 01855 01856 //---------------------------------------------------------------------- 01857 // Some helper functions for typemaps in my_typemaps.i, so they won't be 01858 // included in every file over and over again... 01859 01860 wxString* wxString_in_helper(PyObject* source) { 01861 wxString* target = NULL; 01862 01863 if (!PyString_Check(source) && !PyUnicode_Check(source)) { 01864 PyErr_SetString(PyExc_TypeError, "String or Unicode type required"); 01865 return NULL; 01866 } 01867 #if wxUSE_UNICODE 01868 PyObject* uni = source; 01869 if (PyString_Check(source)) { 01870 uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict"); 01871 if (PyErr_Occurred()) return NULL; 01872 } 01873 target = new wxString(); 01874 size_t len = PyUnicode_GET_SIZE(uni); 01875 if (len) { 01876 PyUnicode_AsWideChar((PyUnicodeObject*)uni, target->GetWriteBuf(len), len); 01877 target->UngetWriteBuf(len); 01878 } 01879 01880 if (PyString_Check(source)) 01881 Py_DECREF(uni); 01882 #else 01883 // Convert to a string object if it isn't already, then to wxString 01884 PyObject* str = source; 01885 if (PyUnicode_Check(source)) { 01886 str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict"); 01887 if (PyErr_Occurred()) return NULL; 01888 } 01889 else if (!PyString_Check(source)) { 01890 str = PyObject_Str(source); 01891 if (PyErr_Occurred()) return NULL; 01892 } 01893 char* tmpPtr; Py_ssize_t tmpSize; 01894 PyString_AsStringAndSize(str, &tmpPtr, &tmpSize); 01895 target = new wxString(tmpPtr, tmpSize); 01896 01897 if (!PyString_Check(source)) 01898 Py_DECREF(str); 01899 #endif // wxUSE_UNICODE 01900 01901 return target; 01902 } 01903 01904 01905 // Similar to above except doesn't use "new" and doesn't set an exception 01906 wxString Py2wxString(PyObject* source) 01907 { 01908 wxString target; 01909 01910 #if wxUSE_UNICODE 01911 // Convert to a unicode object, if not already, then to a wxString 01912 PyObject* uni = source; 01913 if (!PyUnicode_Check(source)) { 01914 uni = PyUnicode_FromEncodedObject(source, wxPyDefaultEncoding, "strict"); 01915 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear? 01916 } 01917 size_t len = PyUnicode_GET_SIZE(uni); 01918 if (len) { 01919 PyUnicode_AsWideChar((PyUnicodeObject*)uni, target.GetWriteBuf(len), len); 01920 target.UngetWriteBuf(); 01921 } 01922 01923 if (!PyUnicode_Check(source)) 01924 Py_DECREF(uni); 01925 #else 01926 // Convert to a string object if it isn't already, then to wxString 01927 PyObject* str = source; 01928 if (PyUnicode_Check(source)) { 01929 str = PyUnicode_AsEncodedString(source, wxPyDefaultEncoding, "strict"); 01930 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear? 01931 } 01932 else if (!PyString_Check(source)) { 01933 str = PyObject_Str(source); 01934 if (PyErr_Occurred()) return wxEmptyString; // TODO: should we PyErr_Clear? 01935 } 01936 char* tmpPtr; Py_ssize_t tmpSize; 01937 PyString_AsStringAndSize(str, &tmpPtr, &tmpSize); 01938 target = wxString(tmpPtr, tmpSize); 01939 01940 if (!PyString_Check(source)) 01941 Py_DECREF(str); 01942 #endif // wxUSE_UNICODE 01943 01944 return target; 01945 } 01946 01947 01948 // Make either a Python String or Unicode object, depending on build mode 01949 PyObject* wx2PyString(const wxString& src) 01950 { 01951 PyObject* str; 01952 #if wxUSE_UNICODE 01953 str = PyUnicode_FromWideChar(src.c_str(), src.Len()); 01954 #else 01955 str = PyString_FromStringAndSize(src.c_str(), src.Len()); 01956 #endif 01957 return str; 01958 } 01959 01960 01961 01962 void wxSetDefaultPyEncoding(const char* encoding) 01963 { 01964 strncpy(wxPyDefaultEncoding, encoding, DEFAULTENCODING_SIZE); 01965 } 01966 01967 const char* wxGetDefaultPyEncoding() 01968 { 01969 return wxPyDefaultEncoding; 01970 } 01971 01972 //---------------------------------------------------------------------- 01973 01974 01975 byte* byte_LIST_helper(PyObject* source) { 01976 if (!PyList_Check(source)) { 01977 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 01978 return NULL; 01979 } 01980 int count = PyList_Size(source); 01981 byte* temp = new byte[count]; 01982 if (! temp) { 01983 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 01984 return NULL; 01985 } 01986 for (int x=0; x<count; x++) { 01987 PyObject* o = PyList_GetItem(source, x); 01988 if (! PyInt_Check(o)) { 01989 PyErr_SetString(PyExc_TypeError, "Expected a list of integers."); 01990 return NULL; 01991 } 01992 temp[x] = (byte)PyInt_AsLong(o); 01993 } 01994 return temp; 01995 } 01996 01997 01998 int* int_LIST_helper(PyObject* source) { 01999 if (!PyList_Check(source)) { 02000 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02001 return NULL; 02002 } 02003 int count = PyList_Size(source); 02004 int* temp = new int[count]; 02005 if (! temp) { 02006 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02007 return NULL; 02008 } 02009 for (int x=0; x<count; x++) { 02010 PyObject* o = PyList_GetItem(source, x); 02011 if (! PyInt_Check(o)) { 02012 PyErr_SetString(PyExc_TypeError, "Expected a list of integers."); 02013 return NULL; 02014 } 02015 temp[x] = PyInt_AsLong(o); 02016 } 02017 return temp; 02018 } 02019 02020 02021 long* long_LIST_helper(PyObject* source) { 02022 if (!PyList_Check(source)) { 02023 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02024 return NULL; 02025 } 02026 int count = PyList_Size(source); 02027 long* temp = new long[count]; 02028 if (! temp) { 02029 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02030 return NULL; 02031 } 02032 for (int x=0; x<count; x++) { 02033 PyObject* o = PyList_GetItem(source, x); 02034 if (! PyInt_Check(o)) { 02035 PyErr_SetString(PyExc_TypeError, "Expected a list of integers."); 02036 return NULL; 02037 } 02038 temp[x] = PyInt_AsLong(o); 02039 } 02040 return temp; 02041 } 02042 02043 02044 char** string_LIST_helper(PyObject* source) { 02045 if (!PyList_Check(source)) { 02046 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02047 return NULL; 02048 } 02049 int count = PyList_Size(source); 02050 char** temp = new char*[count]; 02051 if (! temp) { 02052 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02053 return NULL; 02054 } 02055 for (int x=0; x<count; x++) { 02056 PyObject* o = PyList_GetItem(source, x); 02057 if (! PyString_Check(o)) { 02058 PyErr_SetString(PyExc_TypeError, "Expected a list of strings."); 02059 return NULL; 02060 } 02061 temp[x] = PyString_AsString(o); 02062 } 02063 return temp; 02064 } 02065 02066 //--------------------------------------------------------------------------- 02067 // NOTE: The following functions could really use some refactoring using 02068 // templates to make things somewhat simpler... 02069 02070 inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) 02071 { 02072 // get the x value 02073 if (PyInt_Check(o1)) 02074 point->x = (int)PyInt_AS_LONG(o1); 02075 else if (PyFloat_Check(o1)) 02076 point->x = (int)PyFloat_AS_DOUBLE(o1); 02077 else if (PyNumber_Check(o1)) 02078 point->x = (int)PyInt_AsLong(o1); 02079 else 02080 return false; 02081 02082 // get the y value 02083 if (PyInt_Check(o2)) 02084 point->y = (int)PyInt_AS_LONG(o2); 02085 else if (PyFloat_Check(o2)) 02086 point->y = (int)PyFloat_AS_DOUBLE(o2); 02087 else if (PyNumber_Check(o2)) 02088 point->y = (int)PyInt_AsLong(o2); 02089 else 02090 return false; 02091 02092 return true; 02093 02094 // NOTE: This function used to have this code in it, but I don't know why it 02095 // is a problem nor what havok it will cause, so removing for now... 02096 // if (wxPySwigInstance_Check(o1) || wxPySwigInstance_Check(o2)) { 02097 // // Disallow instances because they can cause havok 02098 // return false; 02099 // } 02100 } 02101 02102 02103 inline bool wxPoint2DFromObjects(PyObject* o1, PyObject* o2, wxPoint2D* point) 02104 { 02105 // get the x value 02106 if (PyInt_Check(o1)) 02107 point->m_x = (double)PyInt_AS_LONG(o1); 02108 else if (PyFloat_Check(o1)) 02109 point->m_x = (double)PyFloat_AS_DOUBLE(o1); 02110 else if (PyNumber_Check(o1)) 02111 point->m_x = (double)PyFloat_AsDouble(o1); 02112 else 02113 return false; 02114 02115 // get the y value 02116 if (PyInt_Check(o2)) 02117 point->m_y = (double)PyInt_AS_LONG(o2); 02118 else if (PyFloat_Check(o2)) 02119 point->m_y = (double)PyFloat_AS_DOUBLE(o2); 02120 else if (PyNumber_Check(o2)) 02121 point->m_y = (double)PyFloat_AsDouble(o2); 02122 else 02123 return false; 02124 02125 return true; 02126 } 02127 02128 02129 02130 wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) 02131 { 02132 int idx; 02133 wxPoint* temp; 02134 PyObject *o, *o1, *o2; 02135 bool isFast = PyList_Check(source) || PyTuple_Check(source); 02136 02137 if (!PySequence_Check(source)) { 02138 goto error0; 02139 } 02140 02141 // The length of the sequence is returned in count. 02142 *count = PySequence_Length(source); 02143 if (*count < 0) { 02144 goto error0; 02145 } 02146 02147 temp = new wxPoint[*count]; 02148 if (!temp) { 02149 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02150 return NULL; 02151 } 02152 for (idx=0; idx<*count; idx++) { 02153 // Get an item: try fast way first. 02154 if (isFast) { 02155 o = PySequence_Fast_GET_ITEM(source, idx); 02156 } 02157 else { 02158 o = PySequence_GetItem(source, idx); 02159 if (o == NULL) { 02160 goto error1; 02161 } 02162 } 02163 02164 // Convert o to wxPoint. 02165 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) || 02166 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) { 02167 o1 = PySequence_Fast_GET_ITEM(o, 0); 02168 o2 = PySequence_Fast_GET_ITEM(o, 1); 02169 if (!wxPointFromObjects(o1, o2, &temp[idx])) { 02170 goto error2; 02171 } 02172 } 02173 else if (wxPySwigInstance_Check(o)) { 02174 wxPoint* pt; 02175 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint"))) { 02176 goto error2; 02177 } 02178 temp[idx] = *pt; 02179 } 02180 else if (PySequence_Check(o) && PySequence_Length(o) == 2) { 02181 o1 = PySequence_GetItem(o, 0); 02182 o2 = PySequence_GetItem(o, 1); 02183 if (!wxPointFromObjects(o1, o2, &temp[idx])) { 02184 goto error3; 02185 } 02186 Py_DECREF(o1); 02187 Py_DECREF(o2); 02188 } 02189 else { 02190 goto error2; 02191 } 02192 // Clean up. 02193 if (!isFast) 02194 Py_DECREF(o); 02195 } 02196 return temp; 02197 02198 error3: 02199 Py_DECREF(o1); 02200 Py_DECREF(o2); 02201 error2: 02202 if (!isFast) 02203 Py_DECREF(o); 02204 error1: 02205 delete [] temp; 02206 error0: 02207 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints."); 02208 return NULL; 02209 } 02210 02211 02212 02213 wxPoint2D* wxPoint2D_LIST_helper(PyObject* source, size_t *count) 02214 { 02215 size_t idx; 02216 wxPoint2D* temp; 02217 PyObject *o, *o1, *o2; 02218 bool isFast = PyList_Check(source) || PyTuple_Check(source); 02219 02220 if (!PySequence_Check(source)) { 02221 goto error0; 02222 } 02223 02224 // The length of the sequence is returned in count. 02225 *count = PySequence_Length(source); 02226 if (*count < 0) { 02227 goto error0; 02228 } 02229 02230 temp = new wxPoint2D[*count]; 02231 if (!temp) { 02232 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02233 return NULL; 02234 } 02235 for (idx=0; idx<*count; idx++) { 02236 // Get an item: try fast way first. 02237 if (isFast) { 02238 o = PySequence_Fast_GET_ITEM(source, idx); 02239 } 02240 else { 02241 o = PySequence_GetItem(source, idx); 02242 if (o == NULL) { 02243 goto error1; 02244 } 02245 } 02246 02247 // Convert o to wxPoint. 02248 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) || 02249 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) { 02250 o1 = PySequence_Fast_GET_ITEM(o, 0); 02251 o2 = PySequence_Fast_GET_ITEM(o, 1); 02252 if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) { 02253 goto error2; 02254 } 02255 } 02256 else if (wxPySwigInstance_Check(o)) { 02257 wxPoint2D* pt; 02258 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint2D"))) { 02259 goto error2; 02260 } 02261 temp[idx] = *pt; 02262 } 02263 else if (PySequence_Check(o) && PySequence_Length(o) == 2) { 02264 o1 = PySequence_GetItem(o, 0); 02265 o2 = PySequence_GetItem(o, 1); 02266 if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) { 02267 goto error3; 02268 } 02269 Py_DECREF(o1); 02270 Py_DECREF(o2); 02271 } 02272 else { 02273 goto error2; 02274 } 02275 // Clean up. 02276 if (!isFast) 02277 Py_DECREF(o); 02278 } 02279 return temp; 02280 02281 error3: 02282 Py_DECREF(o1); 02283 Py_DECREF(o2); 02284 error2: 02285 if (!isFast) 02286 Py_DECREF(o); 02287 error1: 02288 delete [] temp; 02289 error0: 02290 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoint2Ds."); 02291 return NULL; 02292 } 02293 02294 //--------------------------------------------------------------------------- 02295 02296 02297 wxBitmap** wxBitmap_LIST_helper(PyObject* source) { 02298 if (!PyList_Check(source)) { 02299 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02300 return NULL; 02301 } 02302 int count = PyList_Size(source); 02303 wxBitmap** temp = new wxBitmap*[count]; 02304 if (! temp) { 02305 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02306 return NULL; 02307 } 02308 for (int x=0; x<count; x++) { 02309 PyObject* o = PyList_GetItem(source, x); 02310 if (wxPySwigInstance_Check(o)) { 02311 wxBitmap* pt; 02312 if (! wxPyConvertSwigPtr(o, (void **) &pt, wxT("wxBitmap"))) { 02313 PyErr_SetString(PyExc_TypeError,"Expected wxBitmap."); 02314 return NULL; 02315 } 02316 temp[x] = pt; 02317 } 02318 else { 02319 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps."); 02320 return NULL; 02321 } 02322 } 02323 return temp; 02324 } 02325 02326 02327 02328 wxString* wxString_LIST_helper(PyObject* source) { 02329 if (!PyList_Check(source)) { 02330 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02331 return NULL; 02332 } 02333 int count = PyList_Size(source); 02334 wxString* temp = new wxString[count]; 02335 if (! temp) { 02336 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02337 return NULL; 02338 } 02339 for (int x=0; x<count; x++) { 02340 PyObject* o = PyList_GetItem(source, x); 02341 #if PYTHON_API_VERSION >= 1009 02342 if (! PyString_Check(o) && ! PyUnicode_Check(o)) { 02343 PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects."); 02344 return NULL; 02345 } 02346 #else 02347 if (! PyString_Check(o)) { 02348 PyErr_SetString(PyExc_TypeError, "Expected a list of strings."); 02349 return NULL; 02350 } 02351 #endif 02352 02353 wxString* pStr = wxString_in_helper(o); 02354 temp[x] = *pStr; 02355 delete pStr; 02356 } 02357 return temp; 02358 } 02359 02360 02361 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) { 02362 if (!PyList_Check(source)) { 02363 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02364 return NULL; 02365 } 02366 int count = PyList_Size(source); 02367 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count]; 02368 if (! temp) { 02369 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02370 return NULL; 02371 } 02372 for (int x=0; x<count; x++) { 02373 PyObject* o = PyList_GetItem(source, x); 02374 if (wxPySwigInstance_Check(o)) { 02375 wxAcceleratorEntry* ae; 02376 if (! wxPyConvertSwigPtr(o, (void **) &ae, wxT("wxAcceleratorEntry"))) { 02377 PyErr_SetString(PyExc_TypeError,"Expected wxAcceleratorEntry."); 02378 return NULL; 02379 } 02380 temp[x] = *ae; 02381 } 02382 else if (PyTuple_Check(o)) { 02383 PyObject* o1 = PyTuple_GetItem(o, 0); 02384 PyObject* o2 = PyTuple_GetItem(o, 1); 02385 PyObject* o3 = PyTuple_GetItem(o, 2); 02386 temp[x].Set(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3)); 02387 } 02388 else { 02389 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects."); 02390 return NULL; 02391 } 02392 } 02393 return temp; 02394 } 02395 02396 02397 wxPen** wxPen_LIST_helper(PyObject* source) { 02398 if (!PyList_Check(source)) { 02399 PyErr_SetString(PyExc_TypeError, "Expected a list object."); 02400 return NULL; 02401 } 02402 int count = PyList_Size(source); 02403 wxPen** temp = new wxPen*[count]; 02404 if (!temp) { 02405 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); 02406 return NULL; 02407 } 02408 for (int x=0; x<count; x++) { 02409 PyObject* o = PyList_GetItem(source, x); 02410 if (wxPySwigInstance_Check(o)) { 02411 wxPen* pt; 02412 if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPen"))) { 02413 delete temp; 02414 PyErr_SetString(PyExc_TypeError,"Expected wxPen."); 02415 return NULL; 02416 } 02417 temp[x] = pt; 02418 } 02419 else { 02420 delete temp; 02421 PyErr_SetString(PyExc_TypeError, "Expected a list of wxPens."); 02422 return NULL; 02423 } 02424 } 02425 return temp; 02426 } 02427 02428 02429 bool wxPy2int_seq_helper(PyObject* source, int* i1, int* i2) { 02430 bool isFast = PyList_Check(source) || PyTuple_Check(source); 02431 PyObject *o1, *o2; 02432 02433 if (!PySequence_Check(source) || PySequence_Length(source) != 2) 02434 return false; 02435 02436 if (isFast) { 02437 o1 = PySequence_Fast_GET_ITEM(source, 0); 02438 o2 = PySequence_Fast_GET_ITEM(source, 1); 02439 } 02440 else { 02441 o1 = PySequence_GetItem(source, 0); 02442 o2 = PySequence_GetItem(source, 1); 02443 } 02444 02445 *i1 = PyInt_AsLong(o1); 02446 *i2 = PyInt_AsLong(o2); 02447 02448 if (! isFast) { 02449 Py_DECREF(o1); 02450 Py_DECREF(o2); 02451 } 02452 return true; 02453 } 02454 02455 02456 bool wxPy4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4) { 02457 bool isFast = PyList_Check(source) || PyTuple_Check(source); 02458 PyObject *o1, *o2, *o3, *o4; 02459 02460 if (!PySequence_Check(source) || PySequence_Length(source) != 4) 02461 return false; 02462 02463 if (isFast) { 02464 o1 = PySequence_Fast_GET_ITEM(source, 0); 02465 o2 = PySequence_Fast_GET_ITEM(source, 1); 02466 o3 = PySequence_Fast_GET_ITEM(source, 2); 02467 o4 = PySequence_Fast_GET_ITEM(source, 3); 02468 } 02469 else { 02470 o1 = PySequence_GetItem(source, 0); 02471 o2 = PySequence_GetItem(source, 1); 02472 o3 = PySequence_GetItem(source, 2); 02473 o4 = PySequence_GetItem(source, 3); 02474 } 02475 02476 *i1 = PyInt_AsLong(o1); 02477 *i2 = PyInt_AsLong(o2); 02478 *i3 = PyInt_AsLong(o3); 02479 *i4 = PyInt_AsLong(o4); 02480 02481 if (! isFast) { 02482 Py_DECREF(o1); 02483 Py_DECREF(o2); 02484 Py_DECREF(o3); 02485 Py_DECREF(o4); 02486 } 02487 return true; 02488 } 02489 02490 02491 //---------------------------------------------------------------------- 02492 02493 bool wxPySimple_typecheck(PyObject* source, const wxChar* classname, int seqLen) 02494 { 02495 void* ptr; 02496 02497 if (wxPySwigInstance_Check(source) && 02498 wxPyConvertSwigPtr(source, (void **)&ptr, classname)) 02499 return true; 02500 02501 PyErr_Clear(); 02502 if (PySequence_Check(source) && PySequence_Length(source) == seqLen) 02503 return true; 02504 02505 return false; 02506 } 02507 02508 bool wxSize_helper(PyObject* source, wxSize** obj) 02509 { 02510 if (source == Py_None) { 02511 **obj = wxSize(-1,-1); 02512 return true; 02513 } 02514 return wxPyTwoIntItem_helper(source, obj, wxT("wxSize")); 02515 } 02516 02517 02518 bool wxPoint_helper(PyObject* source, wxPoint** obj) 02519 { 02520 if (source == Py_None) { 02521 **obj = wxPoint(-1,-1); 02522 return true; 02523 } 02524 return wxPyTwoIntItem_helper(source, obj, wxT("wxPoint")); 02525 } 02526 02527 02528 02529 bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) { 02530 02531 if (source == Py_None) { 02532 **obj = wxRealPoint(-1,-1); 02533 return true; 02534 } 02535 02536 // If source is an object instance then it may already be the right type 02537 if (wxPySwigInstance_Check(source)) { 02538 wxRealPoint* ptr; 02539 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRealPoint"))) 02540 goto error; 02541 *obj = ptr; 02542 return true; 02543 } 02544 // otherwise a 2-tuple of floats is expected 02545 else if (PySequence_Check(source) && PyObject_Length(source) == 2) { 02546 PyObject* o1 = PySequence_GetItem(source, 0); 02547 PyObject* o2 = PySequence_GetItem(source, 1); 02548 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) { 02549 Py_DECREF(o1); 02550 Py_DECREF(o2); 02551 goto error; 02552 } 02553 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2)); 02554 Py_DECREF(o1); 02555 Py_DECREF(o2); 02556 return true; 02557 } 02558 02559 error: 02560 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object."); 02561 return false; 02562 } 02563 02564 02565 02566 bool wxRect_helper(PyObject* source, wxRect** obj) { 02567 02568 if (source == Py_None) { 02569 **obj = wxRect(-1,-1,-1,-1); 02570 return true; 02571 } 02572 02573 // If source is an object instance then it may already be the right type 02574 if (wxPySwigInstance_Check(source)) { 02575 wxRect* ptr; 02576 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRect"))) 02577 goto error; 02578 *obj = ptr; 02579 return true; 02580 } 02581 // otherwise a 4-tuple of integers is expected 02582 else if (PySequence_Check(source) && PyObject_Length(source) == 4) { 02583 PyObject* o1 = PySequence_GetItem(source, 0); 02584 PyObject* o2 = PySequence_GetItem(source, 1); 02585 PyObject* o3 = PySequence_GetItem(source, 2); 02586 PyObject* o4 = PySequence_GetItem(source, 3); 02587 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || 02588 !PyNumber_Check(o3) || !PyNumber_Check(o4)) { 02589 Py_DECREF(o1); 02590 Py_DECREF(o2); 02591 Py_DECREF(o3); 02592 Py_DECREF(o4); 02593 goto error; 02594 } 02595 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2), 02596 PyInt_AsLong(o3), PyInt_AsLong(o4)); 02597 Py_DECREF(o1); 02598 Py_DECREF(o2); 02599 Py_DECREF(o3); 02600 Py_DECREF(o4); 02601 return true; 02602 } 02603 02604 error: 02605 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object."); 02606 return false; 02607 } 02608 02609 02610 02611 bool wxColour_helper(PyObject* source, wxColour** obj) { 02612 02613 if (source == Py_None) { 02614 **obj = wxNullColour; 02615 return true; 02616 } 02617 02618 // If source is an object instance then it may already be the right type 02619 if (wxPySwigInstance_Check(source)) { 02620 wxColour* ptr; 02621 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxColour"))) 02622 goto error; 02623 *obj = ptr; 02624 return true; 02625 } 02626 // otherwise check for a string 02627 else if (PyString_Check(source) || PyUnicode_Check(source)) { 02628 wxString spec = Py2wxString(source); 02629 if (spec.GetChar(0) == '#' && spec.Length() == 7) { // It's #RRGGBB 02630 long red, green, blue; 02631 red = green = blue = 0; 02632 spec.Mid(1,2).ToLong(&red, 16); 02633 spec.Mid(3,2).ToLong(&green, 16); 02634 spec.Mid(5,2).ToLong(&blue, 16); 02635 02636 **obj = wxColour(red, green, blue); 02637 return true; 02638 } 02639 else { // it's a colour name 02640 **obj = wxColour(spec); 02641 return true; 02642 } 02643 } 02644 // last chance: 3-tuple or 4-tuple of integers is expected 02645 else if (PySequence_Check(source) && PyObject_Length(source) == 3) { 02646 PyObject* o1 = PySequence_GetItem(source, 0); 02647 PyObject* o2 = PySequence_GetItem(source, 1); 02648 PyObject* o3 = PySequence_GetItem(source, 2); 02649 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3)) { 02650 Py_DECREF(o1); 02651 Py_DECREF(o2); 02652 Py_DECREF(o3); 02653 goto error; 02654 } 02655 **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3)); 02656 Py_DECREF(o1); 02657 Py_DECREF(o2); 02658 Py_DECREF(o3); 02659 return true; 02660 } 02661 else if (PySequence_Check(source) && PyObject_Length(source) == 4) { 02662 PyObject* o1 = PySequence_GetItem(source, 0); 02663 PyObject* o2 = PySequence_GetItem(source, 1); 02664 PyObject* o3 = PySequence_GetItem(source, 2); 02665 PyObject* o4 = PySequence_GetItem(source, 3); 02666 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4)) { 02667 Py_DECREF(o1); 02668 Py_DECREF(o2); 02669 Py_DECREF(o3); 02670 Py_DECREF(o4); 02671 goto error; 02672 } 02673 **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3), PyInt_AsLong(o4)); 02674 Py_DECREF(o1); 02675 Py_DECREF(o2); 02676 Py_DECREF(o3); 02677 Py_DECREF(o4); 02678 return true; 02679 } 02680 02681 error: 02682 PyErr_SetString(PyExc_TypeError, 02683 "Expected a wxColour object, a string containing a colour name or '#RRGGBB', or a 3- or 4-tuple of integers."); 02684 return false; 02685 } 02686 02687 02688 bool wxColour_typecheck(PyObject* source) { 02689 02690 if (wxPySimple_typecheck(source, wxT("wxColour"), 3)) 02691 return true; 02692 02693 if (PyString_Check(source) || PyUnicode_Check(source)) 02694 return true; 02695 02696 return false; 02697 } 02698 02699 02700 02701 bool wxPoint2D_helper(PyObject* source, wxPoint2D** obj) { 02702 02703 if (source == Py_None) { 02704 **obj = wxPoint2D(-1,-1); 02705 return true; 02706 } 02707 02708 // If source is an object instance then it may already be the right type 02709 if (wxPySwigInstance_Check(source)) { 02710 wxPoint2D* ptr; 02711 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxPoint2D"))) 02712 goto error; 02713 *obj = ptr; 02714 return true; 02715 } 02716 // otherwise a length-2 sequence of floats is expected 02717 if (PySequence_Check(source) && PySequence_Length(source) == 2) { 02718 PyObject* o1 = PySequence_GetItem(source, 0); 02719 PyObject* o2 = PySequence_GetItem(source, 1); 02720 // This should really check for floats, not numbers -- but that would break code. 02721 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) { 02722 Py_DECREF(o1); 02723 Py_DECREF(o2); 02724 goto error; 02725 } 02726 **obj = wxPoint2D(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2)); 02727 Py_DECREF(o1); 02728 Py_DECREF(o2); 02729 return true; 02730 } 02731 error: 02732 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wx.Point2D object."); 02733 return false; 02734 } 02735 02736 02737 02738 bool wxRect2D_helper(PyObject* source, wxRect2D** obj) { 02739 02740 if (source == Py_None) { 02741 **obj = wxRect2D(-1,-1,-1,-1); 02742 return true; 02743 } 02744 02745 // If source is an object instance then it may already be the right type 02746 if (wxPySwigInstance_Check(source)) { 02747 wxRect2D* ptr; 02748 if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRect2D"))) 02749 goto error; 02750 *obj = ptr; 02751 return true; 02752 } 02753 // otherwise a length-4 sequence of floats is expected 02754 if (PySequence_Check(source) && PySequence_Length(source) == 4) { 02755 PyObject* o1 = PySequence_GetItem(source, 0); 02756 PyObject* o2 = PySequence_GetItem(source, 1); 02757 PyObject* o3 = PySequence_GetItem(source, 2); 02758 PyObject* o4 = PySequence_GetItem(source, 3); 02759 // This should really check for floats, not numbers -- but that would break code. 02760 if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || 02761 !PyNumber_Check(o3) || !PyNumber_Check(o4)) { 02762 Py_DECREF(o1); 02763 Py_DECREF(o2); 02764 Py_DECREF(o3); 02765 Py_DECREF(o4); 02766 goto error; 02767 } 02768 **obj = wxRect2D(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2), 02769 PyFloat_AsDouble(o3), PyFloat_AsDouble(o4)); 02770 Py_DECREF(o1); 02771 Py_DECREF(o2); 02772 Py_DECREF(o3); 02773 Py_DECREF(o4); 02774 return true; 02775 } 02776 error: 02777 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of floats or a wx.Rect2D object."); 02778 return false; 02779 } 02780 02781 02782 //---------------------------------------------------------------------- 02783 02784 PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) 02785 { 02786 PyObject* list = PyList_New(0); 02787 for (size_t i=0; i < arr.GetCount(); i++) { 02788 #if wxUSE_UNICODE 02789 PyObject* str = PyUnicode_FromWideChar(arr[i].c_str(), arr[i].Len()); 02790 #else 02791 PyObject* str = PyString_FromStringAndSize(arr[i].c_str(), arr[i].Len()); 02792 #endif 02793 PyList_Append(list, str); 02794 Py_DECREF(str); 02795 } 02796 return list; 02797 } 02798 02799 02800 PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) 02801 { 02802 PyObject* list = PyList_New(0); 02803 for (size_t i=0; i < arr.GetCount(); i++) { 02804 PyObject* number = PyInt_FromLong(arr[i]); 02805 PyList_Append(list, number); 02806 Py_DECREF(number); 02807 } 02808 return list; 02809 } 02810 02811 02812 PyObject* wxArrayDouble2PyList_helper(const wxArrayDouble& arr) 02813 { 02814 PyObject* list = PyList_New(0); 02815 for (size_t i=0; i < arr.GetCount(); i++) { 02816 PyObject* number = PyFloat_FromDouble(arr[i]); 02817 PyList_Append(list, number); 02818 Py_DECREF(number); 02819 } 02820 return list; 02821 } 02822 02823 02824 //---------------------------------------------------------------------- 02825 // wxPyImageHandler methods 02826 // 02827 // TODO: Switch these to use wxPython's standard macros and helper classes 02828 // for calling callbacks. 02829 02830 PyObject* wxPyImageHandler::m_DoCanRead_Name = NULL; 02831 PyObject* wxPyImageHandler::m_GetImageCount_Name = NULL; 02832 PyObject* wxPyImageHandler::m_LoadFile_Name = NULL; 02833 PyObject* wxPyImageHandler::m_SaveFile_Name = NULL; 02834 02835 PyObject* wxPyImageHandler::py_InputStream(wxInputStream* stream) { 02836 return wxPyConstructObject(new wxPyInputStream(stream), 02837 wxT("wxPyInputStream"), 0); 02838 } 02839 02840 PyObject* wxPyImageHandler::py_Image(wxImage* image) { 02841 return wxPyConstructObject(image, wxT("wxImage"), 0); 02842 } 02843 02844 PyObject* wxPyImageHandler::py_OutputStream(wxOutputStream* stream) { 02845 return wxPyConstructObject(stream, wxT("wxOutputStream"), 0); 02846 } 02847 02848 wxPyImageHandler::wxPyImageHandler(): 02849 m_self(NULL) 02850 { 02851 if (!m_DoCanRead_Name) { 02852 m_DoCanRead_Name = PyString_FromString("DoCanRead"); 02853 m_GetImageCount_Name = PyString_FromString("GetImageCount"); 02854 m_LoadFile_Name = PyString_FromString("LoadFile"); 02855 m_SaveFile_Name = PyString_FromString("SaveFile"); 02856 } 02857 } 02858 02859 wxPyImageHandler::~wxPyImageHandler() { 02860 if (m_self) { 02861 Py_DECREF(m_self); 02862 m_self = NULL; 02863 } 02864 } 02865 02866 void wxPyImageHandler::_SetSelf(PyObject *self) { 02867 // should check here for isinstance(PyImageHandler) ?? 02868 m_self = self; 02869 Py_INCREF(m_self); 02870 } 02871 02872 bool wxPyImageHandler::DoCanRead(wxInputStream& stream) { 02873 // check if our object has this method 02874 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 02875 if (!m_self || !PyObject_HasAttr(m_self, m_DoCanRead_Name)) { 02876 wxPyEndBlockThreads(blocked); 02877 return false; 02878 } 02879 02880 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_DoCanRead_Name, 02881 py_InputStream(&stream), NULL); 02882 bool retval = false; 02883 if (res) { 02884 retval = PyInt_AsLong(res); 02885 Py_DECREF(res); 02886 PyErr_Clear(); 02887 } 02888 else 02889 PyErr_Print(); 02890 wxPyEndBlockThreads(blocked); 02891 return retval; 02892 } 02893 02894 bool wxPyImageHandler::LoadFile( wxImage* image, wxInputStream& stream, 02895 bool verbose, int index ) { 02896 // check if our object has this method 02897 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 02898 if (!m_self || !PyObject_HasAttr(m_self, m_LoadFile_Name)) { 02899 wxPyEndBlockThreads(blocked); 02900 return false; 02901 } 02902 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_LoadFile_Name, 02903 py_Image(image), 02904 py_InputStream(&stream), 02905 PyInt_FromLong(verbose), 02906 PyInt_FromLong(index), 02907 NULL); 02908 bool retval = false; 02909 if (res) { 02910 retval = PyInt_AsLong(res); 02911 Py_DECREF(res); 02912 PyErr_Clear(); 02913 } else 02914 PyErr_Print(); 02915 wxPyEndBlockThreads(blocked); 02916 return retval; 02917 } 02918 02919 bool wxPyImageHandler::SaveFile( wxImage* image, wxOutputStream& stream, 02920 bool verbose ) { 02921 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 02922 if (!m_self || !PyObject_HasAttr(m_self, m_SaveFile_Name)) { 02923 wxPyEndBlockThreads(blocked); 02924 return false; 02925 } 02926 PyObject* res = PyObject_CallMethodObjArgs(m_self, m_SaveFile_Name, 02927 py_Image(image), 02928 py_OutputStream(&stream), 02929 PyInt_FromLong(verbose), 02930 NULL); 02931 bool retval = false; 02932 if(res) { 02933 retval=PyInt_AsLong(res); 02934 Py_DECREF(res); 02935 PyErr_Clear(); 02936 } else 02937 PyErr_Print(); 02938 wxPyEndBlockThreads(blocked); 02939 return retval; 02940 } 02941 02942 int wxPyImageHandler::GetImageCount( wxInputStream& stream ) { 02943 wxPyBlock_t blocked = wxPyBeginBlockThreads(); 02944 if (!m_self || !PyObject_HasAttr(m_self, m_GetImageCount_Name)) { 02945 wxPyEndBlockThreads(blocked); 02946 return 1; 02947 } 02948 PyObject *res=PyObject_CallMethodObjArgs(m_self, m_GetImageCount_Name, 02949 py_InputStream(&stream), 02950 NULL); 02951 int retval = 1; 02952 if(res) { 02953 retval=PyInt_AsLong(res); 02954 Py_DECREF(res); 02955 PyErr_Clear(); 02956 } else 02957 PyErr_Print(); 02958 wxPyEndBlockThreads(blocked); 02959 return retval; 02960 } 02961 02962 02963 //---------------------------------------------------------------------- 02964 // Function to test if the Display (or whatever is the platform equivallent) 02965 // can be connected to. This is accessable from wxPython as a staticmethod of 02966 // wx.App called DisplayAvailable(). 02967 02968 02969 bool wxPyTestDisplayAvailable() 02970 { 02971 #ifdef __WXGTK__ 02972 Display* display; 02973 display = XOpenDisplay(NULL); 02974 if (display == NULL) 02975 return false; 02976 XCloseDisplay(display); 02977 return true; 02978 #endif 02979 02980 #ifdef __WXMAC__ 02981 // This is adapted from Python's Mac/Modules/MacOS.c in the 02982 // MacOS_WMAvailable function. 02983 bool rv; 02984 ProcessSerialNumber psn; 02985 02986 /* 02987 ** This is a fairly innocuous call to make if we don't have a window 02988 ** manager, or if we have no permission to talk to it. It will print 02989 ** a message on stderr, but at least it won't abort the process. 02990 ** It appears the function caches the result itself, and it's cheap, so 02991 ** no need for us to cache. 02992 */ 02993 #ifdef kCGNullDirectDisplay 02994 /* On 10.1 CGMainDisplayID() isn't available, and 02995 ** kCGNullDirectDisplay isn't defined. 02996 */ 02997 if (CGMainDisplayID() == 0) { 02998 rv = false; 02999 } else 03000 #endif 03001 { 03002 // Also foreground the application on the first call as a side-effect. 03003 if (GetCurrentProcess(&psn) < 0 || SetFrontProcess(&psn) < 0) { 03004 rv = false; 03005 } else { 03006 rv = true; 03007 } 03008 } 03009 return rv; 03010 #endif 03011 03012 #ifdef __WXMSW__ 03013 // TODO... 03014 return true; 03015 #endif 03016 } 03017 03018 03019 //---------------------------------------------------------------------- 03020 //---------------------------------------------------------------------- 03021 03022 03023 03024