Mercurial > vim
diff src/if_py_both.h @ 4589:fa39483a1363 v7.3.1042
updated for version 7.3.1042
Problem: Python: can't assign to vim.Buffer.name.
Solution: Python patch 3. (ZyX)
author | Bram Moolenaar <bram@vim.org> |
---|---|
date | Wed, 29 May 2013 22:02:22 +0200 |
parents | 63c9b681c3db |
children | 0cf552b325b5 |
line wrap: on
line diff
--- a/src/if_py_both.h +++ b/src/if_py_both.h @@ -30,6 +30,14 @@ typedef int Py_ssize_t; /* Python 2.4 a #define INVALID_WINDOW_VALUE ((win_T *)(-1)) #define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1)) +#define DICTKEY_DECL \ + PyObject *dictkey_todecref; +#define DICTKEY_GET(err) \ + if (!(key = StringToChars(keyObject, &dictkey_todecref))) \ + return err; +#define DICTKEY_UNREF \ + Py_XDECREF(dictkey_todecref); + typedef void (*rangeinitializer)(void *); typedef void (*runner)(const char *, void * #ifdef PY_CAN_RECURSE @@ -64,6 +72,51 @@ Python_Release_Vim(void) { } +/* + * The "todecref" argument holds a pointer to PyObject * that must be + * DECREF'ed after returned char_u * is no longer needed or NULL if all what + * was needed to generate returned value is object. + * + * Use Py_XDECREF to decrement reference count. + */ + static char_u * +StringToChars(PyObject *object, PyObject **todecref) +{ + char_u *p; + PyObject *bytes = NULL; + + if (PyBytes_Check(object)) + { + + if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1) + return NULL; + if (p == NULL) + return NULL; + + *todecref = NULL; + } + else if (PyUnicode_Check(object)) + { + bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL); + if (bytes == NULL) + return NULL; + + if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1) + return NULL; + if (p == NULL) + return NULL; + + *todecref = bytes; + } + else + { + PyErr_SetString(PyExc_TypeError, _("object must be string")); + return NULL; + } + + return (char_u *) p; +} + /* Output buffer management */ @@ -1586,6 +1639,18 @@ set_option_value_for(key, numval, string return VimTryEnd(); } + static void * +py_memsave(void *p, size_t len) +{ + void *r; + if (!(r = PyMem_Malloc(len))) + return NULL; + mch_memmove(r, p, len); + return r; +} + +#define PY_STRSAVE(s) ((char_u *) py_memsave(s, STRLEN(s) + 1)) + static int OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject) { @@ -1670,57 +1735,16 @@ OptionsAssItem(OptionsObject *self, PyOb else { char_u *val; - if (PyBytes_Check(valObject)) - { - - if (PyString_AsStringAndSize(valObject, (char **) &val, NULL) == -1) - { - DICTKEY_UNREF - return -1; - } - if (val == NULL) - { - DICTKEY_UNREF - return -1; - } - - val = vim_strsave(val); - } - else if (PyUnicode_Check(valObject)) + PyObject *todecref; + + if ((val = StringToChars(valObject, &todecref))) { - PyObject *bytes; - - bytes = PyUnicode_AsEncodedString(valObject, (char *)ENC_OPT, NULL); - if (bytes == NULL) - { - DICTKEY_UNREF - return -1; - } - - if(PyString_AsStringAndSize(bytes, (char **) &val, NULL) == -1) - { - DICTKEY_UNREF - return -1; - } - if (val == NULL) - { - DICTKEY_UNREF - return -1; - } - - val = vim_strsave(val); - Py_XDECREF(bytes); + r = set_option_value_for(key, 0, val, opt_flags, + self->opt_type, self->from); + Py_XDECREF(todecref); } else - { - PyErr_SetString(PyExc_TypeError, _("object must be string")); - DICTKEY_UNREF - return -1; - } - - r = set_option_value_for(key, 0, val, opt_flags, - self->opt_type, self->from); - vim_free(val); + r = -1; } DICTKEY_UNREF @@ -2541,7 +2565,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, array = NULL; else { - array = (char **)alloc((unsigned)(new_len * sizeof(char *))); + array = PyMem_New(char *, new_len); if (array == NULL) { PyErr_NoMemory(); @@ -2558,7 +2582,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, { while (i) vim_free(array[--i]); - vim_free(array); + PyMem_Free(array); return FAIL; } } @@ -2635,7 +2659,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, * been dealt with (either freed, or the responsibility passed * to vim. */ - vim_free(array); + PyMem_Free(array); /* Adjust marks. Invalidate any which lie in the * changed range, and move any in the remainder of the buffer. @@ -2717,7 +2741,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P char **array; buf_T *savebuf; - array = (char **)alloc((unsigned)(size * sizeof(char *))); + array = PyMem_New(char *, size); if (array == NULL) { PyErr_NoMemory(); @@ -2733,7 +2757,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P { while (i) vim_free(array[--i]); - vim_free(array); + PyMem_Free(array); return FAIL; } } @@ -2768,7 +2792,7 @@ InsertBufferLines(buf_T *buf, PyInt n, P /* Free the array of lines. All of its contents have now * been freed. */ - vim_free(array); + PyMem_Free(array); restore_buffer(savebuf); update_screen(VALID); @@ -3179,6 +3203,45 @@ BufferAttr(BufferObject *self, char *nam return NULL; } + static int +BufferSetattr(BufferObject *self, char *name, PyObject *valObject) +{ + if (CheckBuffer(self)) + return -1; + + if (strcmp(name, "name") == 0) + { + char_u *val; + aco_save_T aco; + int r; + PyObject *todecref; + + if (!(val = StringToChars(valObject, &todecref))) + return -1; + + VimTryStart(); + /* Using aucmd_*: autocommands will be executed by rename_buffer */ + aucmd_prepbuf(&aco, self->buf); + r = rename_buffer(val); + aucmd_restbuf(&aco); + Py_XDECREF(todecref); + if (VimTryEnd()) + return -1; + + if (r == FAIL) + { + PyErr_SetVim(_("failed to rename buffer")); + return -1; + } + return 0; + } + else + { + PyErr_SetString(PyExc_AttributeError, name); + return -1; + } +} + static PyObject * BufferAppend(BufferObject *self, PyObject *args) { @@ -4040,7 +4103,7 @@ ConvertFromPyObject(PyObject *obj, typva if (result == NULL) return -1; - if (set_string_copy(result, tv) == -1) + if (set_string_copy(result, tv)) { Py_XDECREF(bytes); return -1; @@ -4169,11 +4232,13 @@ init_structs(void) BufferType.tp_methods = BufferMethods; #if PY_MAJOR_VERSION >= 3 BufferType.tp_getattro = (getattrofunc)BufferGetattro; + BufferType.tp_setattro = (setattrofunc)BufferSetattro; BufferType.tp_alloc = call_PyType_GenericAlloc; BufferType.tp_new = call_PyType_GenericNew; BufferType.tp_free = call_PyObject_Free; #else BufferType.tp_getattr = (getattrfunc)BufferGetattr; + BufferType.tp_setattr = (setattrfunc)BufferSetattr; #endif vim_memset(&WindowType, 0, sizeof(WindowType));