helpers.cpp
Go to the documentation of this file.
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 


wxpython_swig_interface
Author(s):
autogenerated on Mon Oct 6 2014 07:25:55