summaryrefslogtreecommitdiff
path: root/src/if_python.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/if_python.c')
-rw-r--r--src/if_python.c237
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.
*