]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/helpers.cpp
add artprov sample to the list
[wxWidgets.git] / wxPython / src / helpers.cpp
index bf1d3402f31995eb63c6605e65c36ac01facbd82..8d602244e0c5dd772c83afbc37e73a2823b20671 100644 (file)
 #endif
 
 
+//----------------------------------------------------------------------
+
+#if PYTHON_API_VERSION <= 1007 && wxUSE_UNICODE
+#error Python must support Unicode to use wxWindows Unicode
+#endif
+
 //----------------------------------------------------------------------
 
 #ifdef __WXGTK__
@@ -120,6 +126,42 @@ int  wxPyApp::MainLoop() {
 //----------------------------------------------------------------------
 
 
+static char* wxPyCopyCString(const wxChar* src)
+{
+    wxWX2MBbuf buff = (wxWX2MBbuf)wxConvCurrent->cWX2MB(src);
+    size_t len = strlen(buff);
+    char*  dest = new char[len+1];
+    strcpy(dest, buff);
+    return dest;
+}
+
+#if wxUSE_UNICODE
+static char* wxPyCopyCString(const char* src)   // we need a char version too
+{
+    size_t len = strlen(src);
+    char*  dest = new char[len+1];
+    strcpy(dest, src);
+    return dest;
+}
+#endif
+
+static wxChar* wxPyCopyWString(const char *src)
+{
+    //wxMB2WXbuf buff = wxConvCurrent->cMB2WX(src);
+    wxString str(src, *wxConvCurrent);
+    return copystring(str);
+}
+
+#if wxUSE_UNICODE
+static wxChar* wxPyCopyWString(const wxChar *src)
+{
+    return copystring(src);
+}
+#endif
+
+
+//----------------------------------------------------------------------
+
 // This is where we pick up the first part of the wxEntry functionality...
 // The rest is in __wxStart and  __wxCleanup.  This function is called when
 // wxcmodule is imported.  (Before there is a wxApp object.)
@@ -150,8 +192,15 @@ void __wxPreStart()
         argc = PyList_Size(sysargv);
         argv = new char*[argc+1];
         int x;
-        for(x=0; x<argc; x++)
-            argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
+        for(x=0; x<argc; x++) {
+           PyObject *item = PyList_GetItem(sysargv, x);
+#if wxUSE_UNICODE
+           if (PyUnicode_Check(item))
+               argv[x] = wxPyCopyCString(PyUnicode_AS_UNICODE(item));
+            else
+#endif
+                argv[x] = wxPyCopyCString(PyString_AsString(item));
+       }
         argv[argc] = NULL;
     }
 
@@ -181,16 +230,24 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args)
 
     // This is the next part of the wxEntry functionality...
     int argc = 0;
-    char** argv = NULL;
+    wxChar** argv = NULL;
     PyObject* sysargv = PySys_GetObject("argv");
     if (sysargv != NULL) {
         argc = PyList_Size(sysargv);
-        argv = new char*[argc+1];
+        argv = new wxChar*[argc+1];
         int x;
-        for(x=0; x<argc; x++)
-            argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
+        for(x=0; x<argc; x++) {
+            PyObject *pyArg = PyList_GetItem(sysargv, x);
+#if wxUSE_UNICODE
+            if (PyUnicode_Check(pyArg))
+                argv[x] = wxPyCopyWString(PyUnicode_AS_UNICODE(pyArg));
+            else
+#endif
+                argv[x] = wxPyCopyWString(PyString_AsString(pyArg));
+        }
         argv[argc] = NULL;
     }
+
     wxPythonApp->argc = argc;
     wxPythonApp->argv = argv;
 
@@ -271,6 +328,7 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
 #endif
 
     PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
+    PyDict_SetItemString(wxPython_dict, "wxUSE_UNICODE", PyInt_FromLong(wxUSE_UNICODE));
 
     Py_INCREF(Py_None);
     return Py_None;
@@ -296,14 +354,14 @@ void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) {
 
 
 
-PyObject* wxPyClassExists(const char* className) {
+PyObject* wxPyClassExists(const wxString& className) {
 
     if (!className)
         return NULL;
 
     char    buff[64];               // should always be big enough...
 
-    sprintf(buff, "%sPtr", className);
+    sprintf(buff, "%sPtr", className.mbc_str());
     PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
 
     return classobj;  // returns NULL if not found
@@ -346,7 +404,7 @@ PyObject*  wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) {
             } else {
                 wxString msg("wxPython class not found for ");
                 msg += source->GetClassInfo()->GetClassName();
-                PyErr_SetString(PyExc_NameError, msg.c_str());
+                PyErr_SetString(PyExc_NameError, msg.mbc_str());
                 target = NULL;
             }
         }
@@ -384,20 +442,21 @@ PyObject*  wxPyMake_wxSizer(wxSizer* source) {
 //---------------------------------------------------------------------------
 
 PyObject* wxPyConstructObject(void* ptr,
-                              const char* className,
+                              const wxString& className,
                               PyObject* klass,
                               int setThisOwn) {
 
     PyObject* obj;
     PyObject* arg;
     PyObject* item;
+    wxString  name(className);
     char      swigptr[64];      // should always be big enough...
     char      buff[64];
 
-    if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)className)) != NULL) {
-        className = PyString_AsString(item);
+    if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)(const char*)name.mbc_str())) != NULL) {
+        name = wxString(PyString_AsString(item), *wxConvCurrent);
     }
-    sprintf(buff, "_%s_p", className);
+    sprintf(buff, "_%s_p", (const char*)name.mbc_str());
     SWIG_MakePtr(swigptr, ptr, buff);
 
     arg = Py_BuildValue("(s)", swigptr);
@@ -415,7 +474,7 @@ PyObject* wxPyConstructObject(void* ptr,
 
 
 PyObject* wxPyConstructObject(void* ptr,
-                              const char* className,
+                              const wxString& className,
                               int setThisOwn) {
     PyObject* obj;
 
@@ -425,9 +484,9 @@ PyObject* wxPyConstructObject(void* ptr,
     }
 
     char    buff[64];               // should always be big enough...
-    sprintf(buff, "%sPtr", className);
+    sprintf(buff, "%sPtr", (const char*)className.mbc_str());
 
-    wxASSERT_MSG(wxPython_dict, "wxPython_dict is not set yet!!");
+    wxASSERT_MSG(wxPython_dict, wxT("wxPython_dict is not set yet!!"));
 
     PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
     if (! classobj) {
@@ -442,6 +501,7 @@ PyObject* wxPyConstructObject(void* ptr,
     return wxPyConstructObject(ptr, className, classobj, setThisOwn);
 }
 
+
 //---------------------------------------------------------------------------
 
 
@@ -469,7 +529,7 @@ PyThreadState* wxPyGetThreadState() {
         }
     }
     wxPyTMutex->Unlock();
-    wxASSERT_MSG(tstate, "PyThreadState should not be NULL!");
+    wxASSERT_MSG(tstate, wxT("PyThreadState should not be NULL!"));
     return tstate;
 }
 
@@ -540,16 +600,13 @@ void wxPyEndBlockThreads() {
 //---------------------------------------------------------------------------
 // wxPyInputStream and wxPyCBInputStream methods
 
-#include <wx/listimpl.cpp>
-WX_DEFINE_LIST(wxStringPtrList);
-
 
 void wxPyInputStream::close() {
-    /* do nothing */
+    /* do nothing for now */
 }
 
 void wxPyInputStream::flush() {
-    /* do nothing */
+    /* do nothing for now */
 }
 
 bool wxPyInputStream::eof() {
@@ -563,8 +620,12 @@ wxPyInputStream::~wxPyInputStream() {
     /* do nothing */
 }
 
-wxString* wxPyInputStream::read(int size) {
-    wxString* s = NULL;
+
+
+
+PyObject* wxPyInputStream::read(int size) {
+    PyObject* obj = NULL;
+    wxMemoryBuffer buf;
     const int BUFSIZE = 1024;
 
     // check if we have a real wxInputStream to work with
@@ -574,88 +635,62 @@ wxString* wxPyInputStream::read(int size) {
     }
 
     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;
+            m_wxis->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE);
+            buf.UngetAppendBuf(m_wxis->LastRead());
         }
 
     } 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());
+        m_wxis->Read(buf.GetWriteBuf(size), size);
+        buf.UngetWriteBuf(m_wxis->LastRead());
+    }
 
-        // error check
-        if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
-            delete s;
-            PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
-            return NULL;
-        }
+    // error check
+    if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
+        PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
+    }
+    else {
+        // We use only strings for the streams, not unicode
+        obj = PyString_FromStringAndSize(buf, buf.GetDataLen());
     }
-    return s;
+    return obj;
 }
 
 
-wxString* wxPyInputStream::readline (int size) {
+PyObject* wxPyInputStream::readline(int size) {
+    PyObject* obj = NULL;
+    wxMemoryBuffer buf;
+    int i;
+    char ch;
+
     // 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();
+        ch = m_wxis->GetC();
+        buf.AppendByte(ch);
     }
 
     // errorcheck
     if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
-        delete s;
         PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
-        return NULL;
     }
-    return s;
+    else {
+        // We use only strings for the streams, not unicode
+        obj = PyString_FromStringAndSize((char*)buf.GetData(), buf.GetDataLen());
+    }
+    return obj;
 }
 
 
-wxStringPtrList* wxPyInputStream::readlines (int sizehint) {
+PyObject* wxPyInputStream::readlines(int sizehint) {
+    PyObject* pylist;
+
     // check if we have a real wxInputStream to work with
     if (!m_wxis) {
         PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream below");
@@ -663,8 +698,8 @@ wxStringPtrList* wxPyInputStream::readlines (int sizehint) {
     }
 
     // init list
-    wxStringPtrList* l = new wxStringPtrList();
-    if (!l) {
+    pylist = PyList_New(0);
+    if (!pylist) {
         PyErr_NoMemory();
         return NULL;
     }
@@ -672,24 +707,23 @@ wxStringPtrList* wxPyInputStream::readlines (int sizehint) {
     // read sizehint bytes or until EOF
     int i;
     for (i=0; (!m_wxis->Eof()) && ((sizehint < 0) || (i < sizehint));) {
-        wxString* s = readline();
+        PyObject* s = this->readline();
         if (s == NULL) {
-            l->DeleteContents(TRUE);
-            l->Clear();
+            Py_DECREF(pylist);
             return NULL;
         }
-        l->Append(s);
-        i = i + s->Length();
+        PyList_Append(pylist, s);
+        i += PyString_Size(s);
     }
 
     // error check
     if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
-        l->DeleteContents(TRUE);
-        l->Clear();
+        Py_DECREF(pylist);
         PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
         return NULL;
     }
-    return l;
+
+    return pylist;
 }
 
 
@@ -776,13 +810,13 @@ size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
     Py_DECREF(arglist);
 
     size_t o = 0;
-    if ((result != NULL) && PyString_Check(result)) {  // TODO: unicode?
+    if ((result != NULL) && PyString_Check(result)) {
         o = PyString_Size(result);
         if (o == 0)
             m_lasterror = wxSTREAM_EOF;
         if (o > bufsize)
             o = bufsize;
-        memcpy((char*)buffer, PyString_AsString(result), o);
+        memcpy((char*)buffer, PyString_AsString(result), o);  // strings only, not unicode...
         Py_DECREF(result);
 
     }
@@ -860,8 +894,9 @@ void wxPyCallback::EventThunker(wxEvent& event) {
         arg = ((wxPyEvent*)&event)->GetSelf();
     else if (className == "wxPyCommandEvent")
         arg = ((wxPyCommandEvent*)&event)->GetSelf();
-    else
+    else {
         arg = wxPyConstructObject((void*)&event, className);
+    }
 
     tuple = PyTuple_New(1);
     PyTuple_SET_ITEM(tuple, 0, arg);
@@ -1225,7 +1260,108 @@ long wxPyGetWinHandle(wxWindow* win) {
 
 //----------------------------------------------------------------------
 // Some helper functions for typemaps in my_typemaps.i, so they won't be
-// included in every file...
+// included in every file over and over again...
+
+#if PYTHON_API_VERSION >= 1009
+    static char* wxStringErrorMsg = "String or Unicode type required";
+#else
+    static char* wxStringErrorMsg = "String type required";
+#endif
+
+
+wxString* wxString_in_helper(PyObject* source) {
+    wxString* target;
+#if PYTHON_API_VERSION >= 1009  // Have Python unicode API
+    if (!PyString_Check(source) && !PyUnicode_Check(source)) {
+        PyErr_SetString(PyExc_TypeError, wxStringErrorMsg);
+        return NULL;
+    }
+#if wxUSE_UNICODE
+    if (PyUnicode_Check(source)) {
+        target = new wxString(PyUnicode_AS_UNICODE(source));
+    } else {
+        // It is a string, get pointers to it and transform to unicode
+        char* tmpPtr; int tmpSize;
+        PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
+        target = new wxString(tmpPtr, *wxConvCurrent, tmpSize);
+    }
+#else
+    char* tmpPtr; int tmpSize;
+    if (PyString_AsStringAndSize(source, &tmpPtr, &tmpSize) == -1) {
+        PyErr_SetString(PyExc_TypeError, "Unable to convert string");
+        return NULL;
+    }
+    target = new wxString(tmpPtr, tmpSize);
+#endif // wxUSE_UNICODE
+
+#else  // No Python unicode API (1.5.2)
+    if (!PyString_Check(source)) {
+        PyErr_SetString(PyExc_TypeError, wxStringErrorMsg);
+        return NULL;
+    }
+    target = new wxString(PyString_AS_STRING(source), PyString_GET_SIZE(source));
+#endif
+    return target;
+}
+
+
+// Similar to above except doesn't use "new" and doesn't set an exception
+wxString Py2wxString(PyObject* source)
+{
+    wxString target;
+    bool     doDecRef = FALSE;
+
+#if PYTHON_API_VERSION >= 1009  // Have Python unicode API
+    if (!PyString_Check(source) && !PyUnicode_Check(source)) {
+        // Convert to String if not one already...  (TODO: Unicode too?)
+        source = PyObject_Str(source);
+        doDecRef = TRUE;
+    }
+
+#if wxUSE_UNICODE
+    if (PyUnicode_Check(source)) {
+        target = PyUnicode_AS_UNICODE(source);
+    } else {
+        // It is a string, get pointers to it and transform to unicode
+        char* tmpPtr; int tmpSize;
+        PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
+        target = wxString(tmpPtr, *wxConvCurrent, tmpSize);
+    }
+#else
+    char* tmpPtr; int tmpSize;
+    PyString_AsStringAndSize(source, &tmpPtr, &tmpSize);
+    target = wxString(tmpPtr, tmpSize);
+#endif // wxUSE_UNICODE
+
+#else  // No Python unicode API (1.5.2)
+    if (!PyString_Check(source)) {
+        // Convert to String if not one already...
+        source = PyObject_Str(source);
+        doDecRef = TRUE;
+    }
+    target = wxString(PyString_AS_STRING(source), PyString_GET_SIZE(source));
+#endif
+
+    if (doDecRef)
+        Py_DECREF(source);
+    return target;
+}
+
+
+// Make either a Python String or Unicode object, depending on build mode
+PyObject* wx2PyString(const wxString& src)
+{
+    PyObject* str;
+#if wxUSE_UNICODE
+    str = PyUnicode_FromUnicode(src.c_str(), src.Len());
+#else
+    str = PyString_FromStringAndSize(src.c_str(), src.Len());
+#endif
+    return str;
+}
+
+
+//----------------------------------------------------------------------
 
 
 byte* byte_LIST_helper(PyObject* source) {
@@ -1480,19 +1616,16 @@ wxString* wxString_LIST_helper(PyObject* source) {
             PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects.");
             return NULL;
         }
-
-        char* buff;
-        int   length;
-        if (PyString_AsStringAndSize(o, &buff, &length) == -1)
-            return NULL;
-        temp[x] = wxString(buff, length);
 #else
         if (! PyString_Check(o)) {
             PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
             return NULL;
         }
-        temp[x] = PyString_AsString(o);
 #endif
+
+        wxString* pStr = wxString_in_helper(o);
+        temp[x] = *pStr;
+        delete pStr;
     }
     return temp;
 }
@@ -1751,12 +1884,14 @@ bool wxColour_helper(PyObject* source, wxColour** obj) {
     }
     // otherwise a string is expected
     else if (PyString_Check(source)) {
-        wxString spec = PyString_AS_STRING(source);
-        if (spec[0U] == '#' && spec.Length() == 7) {  // It's  #RRGGBB
-            char* junk;
-            int red   = strtol(spec.Mid(1,2), &junk, 16);
-            int green = strtol(spec.Mid(3,2), &junk, 16);
-            int blue  = strtol(spec.Mid(5,2), &junk, 16);
+        wxString spec(PyString_AS_STRING(source), *wxConvCurrent);
+        if (spec.GetChar(0) == '#' && spec.Length() == 7) {  // It's  #RRGGBB
+            long red, green, blue;
+            red = green = blue = 0;
+            spec.Mid(1,2).ToLong(&red,   16);
+            spec.Mid(3,2).ToLong(&green, 16);
+            spec.Mid(5,2).ToLong(&blue,  16);
+
             **obj = wxColour(red, green, blue);
             return TRUE;
         }
@@ -1767,7 +1902,9 @@ bool wxColour_helper(PyObject* source, wxColour** obj) {
     }
 
  error:
-    PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
+    PyErr_SetString(PyExc_TypeError,
+                    "Expected a wxColour object or a string containing a colour "
+                    "name or '#RRGGBB'.");
     return FALSE;
 }
 
@@ -1778,7 +1915,11 @@ PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
 
     PyObject* list = PyList_New(0);
     for (size_t i=0; i < arr.GetCount(); i++) {
-        PyObject* str = PyString_FromString(arr[i].c_str());
+#if wxUSE_UNICODE
+        PyObject* str = PyUnicode_FromUnicode(arr[i].c_str(), arr[i].Len());
+#else
+       PyObject* str = PyString_FromStringAndSize(arr[i].c_str(), arr[i].Len());
+#endif
         PyList_Append(list, str);
         Py_DECREF(str);
     }