X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1893b029458c15069855bde50889d2a1a82a44e9..5cd16c0c458adbe2ba948d2114ca9005bec4808d:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index c8cf22a045..bf1d3402f3 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -15,6 +15,7 @@ #undef DEBUG #include #include "helpers.h" +#include "pyistream.h" #ifdef __WXMSW__ #include @@ -223,11 +224,13 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args) void __wxCleanup() { wxEntryCleanup(); +#ifdef WXP_WITH_THREAD delete wxPyTMutex; wxPyTMutex = NULL; wxPyTStates->Empty(); delete wxPyTStates; wxPyTStates = NULL; +#endif } @@ -254,8 +257,8 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) #ifdef __WXMOTIF__ #define wxPlatform "__WXMOTIF__" #endif -#ifdef __WXQT__ -#define wxPlatform "__WXQT__" +#ifdef __WXX11__ +#define wxPlatform "__WXX11__" #endif #ifdef __WXGTK__ #define wxPlatform "__WXGTK__" @@ -441,32 +444,19 @@ PyObject* wxPyConstructObject(void* ptr, //--------------------------------------------------------------------------- -// TODO: This should really be wxThread::GetCurrentId(), and I will do so -// after I make a quick 2.3.2.1 release. + #ifdef WXP_WITH_THREAD -#ifdef __WXGTK__ // does wxGTK always use pthreads? -#include -#include -#endif inline unsigned long wxPyGetCurrentThreadId() { -#ifdef __WXMSW__ - return (unsigned long)::GetCurrentThreadId(); -#endif -#ifdef __WXGTK__ // does wxGTK always use pthreads? - return (unsigned long)pthread_self(); -#endif -#ifdef __WXMAC__ - ThreadID current ; - MacGetCurrentThread( ¤t ) ; - return (unsigned long)current; -#endif + return wxThread::GetCurrentId(); } - - +static PyThreadState* gs_shutdownTState; static PyThreadState* wxPyGetThreadState() { + if (wxPyTMutex == NULL) // Python is shutting down... + return gs_shutdownTState; + unsigned long ctid = wxPyGetCurrentThreadId(); PyThreadState* tstate = NULL; @@ -485,6 +475,10 @@ PyThreadState* wxPyGetThreadState() { static void wxPySaveThreadState(PyThreadState* tstate) { + if (wxPyTMutex == NULL) { // Python is shutting down, assume a single thread... + gs_shutdownTState = tstate; + return; + } unsigned long ctid = wxPyGetCurrentThreadId(); wxPyTMutex->Lock(); for(size_t i=0; i < wxPyTStates->GetCount(); i++) { @@ -544,6 +538,291 @@ void wxPyEndBlockThreads() { //--------------------------------------------------------------------------- +// wxPyInputStream and wxPyCBInputStream methods + +#include +WX_DEFINE_LIST(wxStringPtrList); + + +void wxPyInputStream::close() { + /* do nothing */ +} + +void wxPyInputStream::flush() { + /* do nothing */ +} + +bool wxPyInputStream::eof() { + if (m_wxis) + return m_wxis->Eof(); + else + return TRUE; +} + +wxPyInputStream::~wxPyInputStream() { + /* do nothing */ +} + +wxString* wxPyInputStream::read(int size) { + wxString* s = NULL; + const int BUFSIZE = 1024; + + // check if we have a real wxInputStream to work with + if (!m_wxis) { + PyErr_SetString(PyExc_IOError, "no valid C-wxInputStream"); + return NULL; + } + + if (size < 0) { + // init buffers + char * buf = new char[BUFSIZE]; + if (!buf) { + PyErr_NoMemory(); + return NULL; + } + + s = new wxString(); + if (!s) { + delete buf; + PyErr_NoMemory(); + return NULL; + } + + // read until EOF + while (! m_wxis->Eof()) { + m_wxis->Read(buf, BUFSIZE); + s->Append(buf, m_wxis->LastRead()); + } + delete buf; + + // error check + if (m_wxis->LastError() == wxSTREAM_READ_ERROR) { + delete s; + PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); + return NULL; + } + + } else { // Read only size number of characters + s = new wxString; + if (!s) { + PyErr_NoMemory(); + return NULL; + } + + // read size bytes + m_wxis->Read(s->GetWriteBuf(size+1), size); + s->UngetWriteBuf(m_wxis->LastRead()); + + // error check + if (m_wxis->LastError() == wxSTREAM_READ_ERROR) { + delete s; + PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); + return NULL; + } + } + return s; +} + + +wxString* wxPyInputStream::readline (int size) { + // check if we have a real wxInputStream to work with + if (!m_wxis) { + PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream"); + return NULL; + } + + // init buffer + int i; + char ch; + wxString* s = new wxString; + if (!s) { + PyErr_NoMemory(); + return NULL; + } + + // read until \n or byte limit reached + for (i=ch=0; (ch != '\n') && (!m_wxis->Eof()) && ((size < 0) || (i < size)); i++) { + *s += ch = m_wxis->GetC(); + } + + // errorcheck + if (m_wxis->LastError() == wxSTREAM_READ_ERROR) { + delete s; + PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); + return NULL; + } + return s; +} + + +wxStringPtrList* wxPyInputStream::readlines (int sizehint) { + // check if we have a real wxInputStream to work with + if (!m_wxis) { + PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream below"); + return NULL; + } + + // init list + wxStringPtrList* l = new wxStringPtrList(); + if (!l) { + PyErr_NoMemory(); + return NULL; + } + + // read sizehint bytes or until EOF + int i; + for (i=0; (!m_wxis->Eof()) && ((sizehint < 0) || (i < sizehint));) { + wxString* s = readline(); + if (s == NULL) { + l->DeleteContents(TRUE); + l->Clear(); + return NULL; + } + l->Append(s); + i = i + s->Length(); + } + + // error check + if (m_wxis->LastError() == wxSTREAM_READ_ERROR) { + l->DeleteContents(TRUE); + l->Clear(); + PyErr_SetString(PyExc_IOError,"IOError in wxInputStream"); + return NULL; + } + return l; +} + + +void wxPyInputStream::seek(int offset, int whence) { + if (m_wxis) + m_wxis->SeekI(offset, wxSeekMode(whence)); +} + +int wxPyInputStream::tell(){ + if (m_wxis) + return m_wxis->TellI(); + else return 0; +} + + + + +wxPyCBInputStream::wxPyCBInputStream(PyObject *r, PyObject *s, PyObject *t, bool block) + : wxInputStream(), m_read(r), m_seek(s), m_tell(t), m_block(block) +{} + + +wxPyCBInputStream::~wxPyCBInputStream() { + if (m_block) wxPyBeginBlockThreads(); + Py_XDECREF(m_read); + Py_XDECREF(m_seek); + Py_XDECREF(m_tell); + if (m_block) wxPyEndBlockThreads(); +} + + +wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) { + if (block) wxPyBeginBlockThreads(); + + PyObject* read = getMethod(py, "read"); + PyObject* seek = getMethod(py, "seek"); + PyObject* tell = getMethod(py, "tell"); + + if (!read) { + PyErr_SetString(PyExc_TypeError, "Not a file-like object"); + Py_XDECREF(read); + Py_XDECREF(seek); + Py_XDECREF(tell); + if (block) wxPyEndBlockThreads(); + return NULL; + } + + if (block) wxPyEndBlockThreads(); + return new wxPyCBInputStream(read, seek, tell, block); +} + +PyObject* wxPyCBInputStream::getMethod(PyObject* py, char* name) { + if (!PyObject_HasAttrString(py, name)) + return NULL; + PyObject* o = PyObject_GetAttrString(py, name); + if (!PyMethod_Check(o) && !PyCFunction_Check(o)) { + Py_DECREF(o); + return NULL; + } + return o; +} + + +size_t wxPyCBInputStream::GetSize() const { + wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const + if (m_seek && m_tell) { + off_t temp = self->OnSysTell(); + off_t ret = self->OnSysSeek(0, wxFromEnd); + self->OnSysSeek(temp, wxFromStart); + return ret; + } + else + return 0; +} + + +size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) { + if (bufsize == 0) + return 0; + + wxPyBeginBlockThreads(); + PyObject* arglist = Py_BuildValue("(i)", bufsize); + PyObject* result = PyEval_CallObject(m_read, arglist); + Py_DECREF(arglist); + + size_t o = 0; + if ((result != NULL) && PyString_Check(result)) { // TODO: unicode? + o = PyString_Size(result); + if (o == 0) + m_lasterror = wxSTREAM_EOF; + if (o > bufsize) + o = bufsize; + memcpy((char*)buffer, PyString_AsString(result), o); + Py_DECREF(result); + + } + else + m_lasterror = wxSTREAM_READ_ERROR; + wxPyEndBlockThreads(); + m_lastcount = o; + return o; +} + +size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) { + m_lasterror = wxSTREAM_WRITE_ERROR; + return 0; +} + +off_t wxPyCBInputStream::OnSysSeek(off_t off, wxSeekMode mode) { + wxPyBeginBlockThreads(); + PyObject* arglist = Py_BuildValue("(ii)", off, mode); + PyObject* result = PyEval_CallObject(m_seek, arglist); + Py_DECREF(arglist); + Py_XDECREF(result); + wxPyEndBlockThreads(); + return OnSysTell(); +} + +off_t wxPyCBInputStream::OnSysTell() const { + wxPyBeginBlockThreads(); + PyObject* arglist = Py_BuildValue("()"); + PyObject* result = PyEval_CallObject(m_tell, arglist); + Py_DECREF(arglist); + off_t o = 0; + if (result != NULL) { + o = PyInt_AsLong(result); + Py_DECREF(result); + }; + wxPyEndBlockThreads(); + return o; +} + +//---------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject); @@ -627,11 +906,11 @@ void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) { // Prior to Python 2.2 PyMethod_GetClass returned the class object // in which the method was defined. Starting with 2.2 it returns // "class that asked for the method" which seems totally bogus to me -// but apprently if fixes some obscure problem waiting to happen in +// but apprently it fixes some obscure problem waiting to happen in // Python. Since the API was not documented Guido and the gang felt // safe in changing it. Needless to say that totally screwed up the // logic below in wxPyCallbackHelper::findCallback, hence this icky -// code to find the class where the method is actuallt defined... +// code to find the class where the method is actually defined... static PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name) @@ -679,6 +958,7 @@ PyObject* PyFindClassWithAttr(PyObject *klass, PyObject *name) } return NULL; } + return NULL; } #endif @@ -1506,6 +1786,18 @@ PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) { } +PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) { + + PyObject* list = PyList_New(0); + for (size_t i=0; i < arr.GetCount(); i++) { + PyObject* number = PyInt_FromLong(arr[i]); + PyList_Append(list, number); + Py_DECREF(number); + } + return list; +} + + //---------------------------------------------------------------------- //----------------------------------------------------------------------