forked from aniani/vim
257 lines
4.6 KiB
C
257 lines
4.6 KiB
C
|
/* vi:set ts=8 sts=4 sw=4:
|
||
|
*
|
||
|
* VIM - Vi IMproved by Bram Moolenaar
|
||
|
*
|
||
|
* Do ":help uganda" in Vim to read copying and usage conditions.
|
||
|
* Do ":help credits" in Vim to see a list of people who contributed.
|
||
|
* See README.txt for an overview of the Vim source code.
|
||
|
*/
|
||
|
/*
|
||
|
* Python extensions by Paul Moore, David Leonard, Roland Puntaier.
|
||
|
*
|
||
|
* Common code for if_python.c and if_python3.c.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* obtain a lock on the Vim data structures
|
||
|
*/
|
||
|
static void
|
||
|
Python_Lock_Vim(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* release a lock on the Vim data structures
|
||
|
*/
|
||
|
static void
|
||
|
Python_Release_Vim(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/* Output object definition
|
||
|
*/
|
||
|
|
||
|
static PyObject *OutputWrite(PyObject *, PyObject *);
|
||
|
static PyObject *OutputWritelines(PyObject *, PyObject *);
|
||
|
|
||
|
typedef void (*writefn)(char_u *);
|
||
|
static void writer(writefn fn, char_u *str, PyInt n);
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
PyObject_HEAD
|
||
|
long softspace;
|
||
|
long error;
|
||
|
} OutputObject;
|
||
|
|
||
|
static struct PyMethodDef OutputMethods[] = {
|
||
|
/* name, function, calling, documentation */
|
||
|
{"write", OutputWrite, 1, "" },
|
||
|
{"writelines", OutputWritelines, 1, "" },
|
||
|
{ NULL, NULL, 0, NULL }
|
||
|
};
|
||
|
|
||
|
/*************/
|
||
|
|
||
|
/* Output buffer management
|
||
|
*/
|
||
|
|
||
|
static PyObject *
|
||
|
OutputWrite(PyObject *self, PyObject *args)
|
||
|
{
|
||
|
int len;
|
||
|
char *str;
|
||
|
int error = ((OutputObject *)(self))->error;
|
||
|
|
||
|
if (!PyArg_ParseTuple(args, "s#", &str, &len))
|
||
|
return NULL;
|
||
|
|
||
|
Py_BEGIN_ALLOW_THREADS
|
||
|
Python_Lock_Vim();
|
||
|
writer((writefn)(error ? emsg : msg), (char_u *)str, len);
|
||
|
Python_Release_Vim();
|
||
|
Py_END_ALLOW_THREADS
|
||
|
|
||
|
Py_INCREF(Py_None);
|
||
|
return Py_None;
|
||
|
}
|
||
|
|
||
|
static PyObject *
|
||
|
OutputWritelines(PyObject *self, PyObject *args)
|
||
|
{
|
||
|
PyInt n;
|
||
|
PyInt i;
|
||
|
PyObject *list;
|
||
|
int error = ((OutputObject *)(self))->error;
|
||
|
|
||
|
if (!PyArg_ParseTuple(args, "O", &list))
|
||
|
return NULL;
|
||
|
Py_INCREF(list);
|
||
|
|
||
|
if (!PyList_Check(list)) {
|
||
|
PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
|
||
|
Py_DECREF(list);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
n = PyList_Size(list);
|
||
|
|
||
|
for (i = 0; i < n; ++i)
|
||
|
{
|
||
|
PyObject *line = PyList_GetItem(list, i);
|
||
|
char *str;
|
||
|
PyInt len;
|
||
|
|
||
|
if (!PyArg_Parse(line, "s#", &str, &len)) {
|
||
|
PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
|
||
|
Py_DECREF(list);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
Py_BEGIN_ALLOW_THREADS
|
||
|
Python_Lock_Vim();
|
||
|
writer((writefn)(error ? emsg : msg), (char_u *)str, len);
|
||
|
Python_Release_Vim();
|
||
|
Py_END_ALLOW_THREADS
|
||
|
}
|
||
|
|
||
|
Py_DECREF(list);
|
||
|
Py_INCREF(Py_None);
|
||
|
return Py_None;
|
||
|
}
|
||
|
|
||
|
static char_u *buffer = NULL;
|
||
|
static PyInt buffer_len = 0;
|
||
|
static PyInt buffer_size = 0;
|
||
|
|
||
|
static writefn old_fn = NULL;
|
||
|
|
||
|
static void
|
||
|
buffer_ensure(PyInt n)
|
||
|
{
|
||
|
PyInt new_size;
|
||
|
char_u *new_buffer;
|
||
|
|
||
|
if (n < buffer_size)
|
||
|
return;
|
||
|
|
||
|
new_size = buffer_size;
|
||
|
while (new_size < n)
|
||
|
new_size += 80;
|
||
|
|
||
|
if (new_size != buffer_size)
|
||
|
{
|
||
|
new_buffer = alloc((unsigned)new_size);
|
||
|
if (new_buffer == NULL)
|
||
|
return;
|
||
|
|
||
|
if (buffer)
|
||
|
{
|
||
|
memcpy(new_buffer, buffer, buffer_len);
|
||
|
vim_free(buffer);
|
||
|
}
|
||
|
|
||
|
buffer = new_buffer;
|
||
|
buffer_size = new_size;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
PythonIO_Flush(void)
|
||
|
{
|
||
|
if (old_fn && buffer_len)
|
||
|
{
|
||
|
buffer[buffer_len] = 0;
|
||
|
old_fn(buffer);
|
||
|
}
|
||
|
|
||
|
buffer_len = 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
writer(writefn fn, char_u *str, PyInt n)
|
||
|
{
|
||
|
char_u *ptr;
|
||
|
|
||
|
if (fn != old_fn && old_fn != NULL)
|
||
|
PythonIO_Flush();
|
||
|
|
||
|
old_fn = fn;
|
||
|
|
||
|
while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
|
||
|
{
|
||
|
PyInt len = ptr - str;
|
||
|
|
||
|
buffer_ensure(buffer_len + len + 1);
|
||
|
|
||
|
memcpy(buffer + buffer_len, str, len);
|
||
|
buffer_len += len;
|
||
|
buffer[buffer_len] = 0;
|
||
|
fn(buffer);
|
||
|
str = ptr + 1;
|
||
|
n -= len + 1;
|
||
|
buffer_len = 0;
|
||
|
}
|
||
|
|
||
|
/* Put the remaining text into the buffer for later printing */
|
||
|
buffer_ensure(buffer_len + n + 1);
|
||
|
memcpy(buffer + buffer_len, str, n);
|
||
|
buffer_len += n;
|
||
|
}
|
||
|
|
||
|
/***************/
|
||
|
|
||
|
static PyTypeObject OutputType;
|
||
|
|
||
|
static OutputObject Output =
|
||
|
{
|
||
|
PyObject_HEAD_INIT(&OutputType)
|
||
|
0,
|
||
|
0
|
||
|
};
|
||
|
|
||
|
static OutputObject Error =
|
||
|
{
|
||
|
PyObject_HEAD_INIT(&OutputType)
|
||
|
0,
|
||
|
1
|
||
|
};
|
||
|
|
||
|
static int
|
||
|
PythonIO_Init_io(void)
|
||
|
{
|
||
|
PySys_SetObject("stdout", (PyObject *)(void *)&Output);
|
||
|
PySys_SetObject("stderr", (PyObject *)(void *)&Error);
|
||
|
|
||
|
if (PyErr_Occurred())
|
||
|
{
|
||
|
EMSG(_("E264: Python: Error initialising I/O objects"));
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static PyObject *VimError;
|
||
|
|
||
|
/* Check to see whether a Vim error has been reported, or a keyboard
|
||
|
* interrupt has been detected.
|
||
|
*/
|
||
|
static int
|
||
|
VimErrorCheck(void)
|
||
|
{
|
||
|
if (got_int)
|
||
|
{
|
||
|
PyErr_SetNone(PyExc_KeyboardInterrupt);
|
||
|
return 1;
|
||
|
}
|
||
|
else if (did_emsg && !PyErr_Occurred())
|
||
|
{
|
||
|
PyErr_SetNone(VimError);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|