diff options
Diffstat (limited to 'src/if_python.c')
-rw-r--r-- | src/if_python.c | 237 |
1 files changed, 9 insertions, 228 deletions
diff --git a/src/if_python.c b/src/if_python.c index d35e9abe..f3b7e5b6 100644 --- a/src/if_python.c +++ b/src/if_python.c @@ -56,6 +56,10 @@ static void init_structs(void); +/* No-op conversion functions, use with care! */ +#define PyString_AsBytes(obj) (obj) +#define PyString_FreeBytes(obj) + #if !defined(FEAT_PYTHON) && defined(PROTO) /* Use this to be able to generate prototypes without python being used. */ # define PyObject Py_ssize_t @@ -129,6 +133,7 @@ struct PyMethodDef { Py_ssize_t a; }; */ # define PyArg_Parse dll_PyArg_Parse # define PyArg_ParseTuple dll_PyArg_ParseTuple +# define PyMem_Free dll_PyMem_Free # define PyDict_SetItemString dll_PyDict_SetItemString # define PyErr_BadArgument dll_PyErr_BadArgument # define PyErr_Clear dll_PyErr_Clear @@ -189,6 +194,7 @@ struct PyMethodDef { Py_ssize_t a; }; */ static int(*dll_PyArg_Parse)(PyObject *, char *, ...); static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...); +static int(*dll_PyMem_Free)(void *); static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); static int(*dll_PyErr_BadArgument)(void); static void(*dll_PyErr_Clear)(void); @@ -271,6 +277,7 @@ static struct { {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse}, {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple}, + {"PyMem_Free", (PYTHON_PROC*)&dll_PyMem_Free}, {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString}, {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument}, {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear}, @@ -833,44 +840,6 @@ static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *); static PyObject *CurrentGetattr(PyObject *, char *); static int CurrentSetattr(PyObject *, char *, PyObject *); -/* Common routines for buffers and line ranges - * ------------------------------------------- - */ - - static PyInt -RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end) -{ - PyInt size; - PyInt len_change; - - /* Self must be a valid buffer */ - if (CheckBuffer(self)) - return -1; - - /* Sort out the slice range */ - size = end - start + 1; - - if (lo < 0) - lo = 0; - else if (lo > size) - lo = size; - if (hi < 0) - hi = 0; - if (hi < lo) - hi = lo; - else if (hi > size) - hi = size; - - if (SetBufferLineList(self->buf, lo + start, hi + start, - val, &len_change) == FAIL) - return -1; - - if (new_end) - *new_end = end + len_change; - - return 0; -} - static PySequenceMethods BufferAsSeq = { (PyInquiry) BufferLength, /* sq_length, len(x) */ (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ @@ -1038,7 +1007,7 @@ BufferAssItem(PyObject *self, PyInt n, PyObject *val) static PyInt BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { - return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, + return RBAsSlice((BufferObject *)(self), lo, hi, val, 1, (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, NULL); } @@ -1088,7 +1057,7 @@ RangeAssItem(PyObject *self, PyInt n, PyObject *val) static PyInt RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) { - return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, + return RBAsSlice(((RangeObject *)(self))->buf, lo, hi, val, ((RangeObject *)(self))->start, ((RangeObject *)(self))->end, &((RangeObject *)(self))->end); @@ -1435,194 +1404,6 @@ PythonMod_Init(void) * 4. Utility functions for handling the interface between Vim and Python. */ -/* Replace a range of lines in the specified buffer. The line numbers are in - * Vim format (1-based). The range is from lo up to, but not including, hi. - * The replacement lines are given as a Python list of string objects. The - * list is checked for validity and correct format. Errors are returned as a - * value of FAIL. The return value is OK on success. - * If OK is returned and len_change is not NULL, *len_change - * is set to the change in the buffer length. - */ - static int -SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change) -{ - /* First of all, we check the thpe of the supplied Python object. - * There are three cases: - * 1. NULL, or None - this is a deletion. - * 2. A list - this is a replacement. - * 3. Anything else - this is an error. - */ - if (list == Py_None || list == NULL) - { - PyInt i; - PyInt n = (int)(hi - lo); - buf_T *savebuf = curbuf; - - PyErr_Clear(); - curbuf = buf; - - if (u_savedel((linenr_T)lo, (long)n) == FAIL) - PyErr_SetVim(_("cannot save undo information")); - else - { - for (i = 0; i < n; ++i) - { - if (ml_delete((linenr_T)lo, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot delete line")); - break; - } - } - if (buf == curwin->w_buffer) - py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); - deleted_lines_mark((linenr_T)lo, (long)i); - } - - curbuf = savebuf; - - if (PyErr_Occurred() || VimErrorCheck()) - return FAIL; - - if (len_change) - *len_change = -n; - - return OK; - } - else if (PyList_Check(list)) - { - PyInt i; - PyInt new_len = PyList_Size(list); - PyInt old_len = hi - lo; - PyInt extra = 0; /* lines added to text, can be negative */ - char **array; - buf_T *savebuf; - - if (new_len == 0) /* avoid allocating zero bytes */ - array = NULL; - else - { - array = (char **)alloc((unsigned)(new_len * sizeof(char *))); - if (array == NULL) - { - PyErr_NoMemory(); - return FAIL; - } - } - - for (i = 0; i < new_len; ++i) - { - PyObject *line = PyList_GetItem(list, i); - - array[i] = StringToLine(line); - if (array[i] == NULL) - { - while (i) - vim_free(array[--i]); - vim_free(array); - return FAIL; - } - } - - savebuf = curbuf; - - PyErr_Clear(); - curbuf = buf; - - if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) - PyErr_SetVim(_("cannot save undo information")); - - /* If the size of the range is reducing (ie, new_len < old_len) we - * need to delete some old_len. We do this at the start, by - * repeatedly deleting line "lo". - */ - if (!PyErr_Occurred()) - { - for (i = 0; i < old_len - new_len; ++i) - if (ml_delete((linenr_T)lo, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot delete line")); - break; - } - extra -= i; - } - - /* For as long as possible, replace the existing old_len with the - * new old_len. This is a more efficient operation, as it requires - * less memory allocation and freeing. - */ - if (!PyErr_Occurred()) - { - for (i = 0; i < old_len && i < new_len; ++i) - if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) - == FAIL) - { - PyErr_SetVim(_("cannot replace line")); - break; - } - } - else - i = 0; - - /* Now we may need to insert the remaining new old_len. If we do, we - * must free the strings as we finish with them (we can't pass the - * responsibility to vim in this case). - */ - if (!PyErr_Occurred()) - { - while (i < new_len) - { - if (ml_append((linenr_T)(lo + i - 1), - (char_u *)array[i], 0, FALSE) == FAIL) - { - PyErr_SetVim(_("cannot insert line")); - break; - } - vim_free(array[i]); - ++i; - ++extra; - } - } - - /* Free any left-over old_len, as a result of an error */ - while (i < new_len) - { - vim_free(array[i]); - ++i; - } - - /* Free the array of old_len. All of its contents have now - * been dealt with (either freed, or the responsibility passed - * to vim. - */ - vim_free(array); - - /* Adjust marks. Invalidate any which lie in the - * changed range, and move any in the remainder of the buffer. - */ - mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), - (long)MAXLNUM, (long)extra); - changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); - - if (buf == curwin->w_buffer) - py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); - - curbuf = savebuf; - - if (PyErr_Occurred() || VimErrorCheck()) - return FAIL; - - if (len_change) - *len_change = new_len - old_len; - - return OK; - } - else - { - PyErr_BadArgument(); - return FAIL; - } -} - /* Convert a Vim line into a Python string. * All internal newlines are replaced by null characters. * |