1071d4279SBram Moolenaar /* vi:set ts=8 sts=4 sw=4: 2071d4279SBram Moolenaar * 3071d4279SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar 4071d4279SBram Moolenaar * 5071d4279SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions. 6071d4279SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed. 7071d4279SBram Moolenaar * See README.txt for an overview of the Vim source code. 8071d4279SBram Moolenaar */ 9071d4279SBram Moolenaar /* 10071d4279SBram Moolenaar * Python extensions by Paul Moore. 11071d4279SBram Moolenaar * Changes for Unix by David Leonard. 12071d4279SBram Moolenaar * 13071d4279SBram Moolenaar * This consists of four parts: 14071d4279SBram Moolenaar * 1. Python interpreter main program 15071d4279SBram Moolenaar * 2. Python output stream: writes output via [e]msg(). 16071d4279SBram Moolenaar * 3. Implementation of the Vim module for Python 17071d4279SBram Moolenaar * 4. Utility functions for handling the interface between Vim and Python. 18071d4279SBram Moolenaar */ 19071d4279SBram Moolenaar 20071d4279SBram Moolenaar #include "vim.h" 21071d4279SBram Moolenaar 22071d4279SBram Moolenaar #include <limits.h> 23071d4279SBram Moolenaar 24071d4279SBram Moolenaar /* Python.h defines _POSIX_THREADS itself (if needed) */ 25071d4279SBram Moolenaar #ifdef _POSIX_THREADS 26071d4279SBram Moolenaar # undef _POSIX_THREADS 27071d4279SBram Moolenaar #endif 28071d4279SBram Moolenaar 29071d4279SBram Moolenaar #if defined(_WIN32) && defined(HAVE_FCNTL_H) 30071d4279SBram Moolenaar # undef HAVE_FCNTL_H 31071d4279SBram Moolenaar #endif 32071d4279SBram Moolenaar 33071d4279SBram Moolenaar #ifdef _DEBUG 34071d4279SBram Moolenaar # undef _DEBUG 35071d4279SBram Moolenaar #endif 36071d4279SBram Moolenaar 37071d4279SBram Moolenaar #ifdef HAVE_STDARG_H 38071d4279SBram Moolenaar # undef HAVE_STDARG_H /* Python's config.h defines it as well. */ 39071d4279SBram Moolenaar #endif 40be2c9ae9SBram Moolenaar #ifdef _POSIX_C_SOURCE 41be2c9ae9SBram Moolenaar # undef _POSIX_C_SOURCE /* pyconfig.h defines it as well. */ 42be2c9ae9SBram Moolenaar #endif 43be2c9ae9SBram Moolenaar #ifdef _XOPEN_SOURCE 44be2c9ae9SBram Moolenaar # undef _XOPEN_SOURCE /* pyconfig.h defines it as well. */ 45be2c9ae9SBram Moolenaar #endif 46071d4279SBram Moolenaar 472c45e945SBram Moolenaar #define PY_SSIZE_T_CLEAN 482c45e945SBram Moolenaar 49071d4279SBram Moolenaar #include <Python.h> 50071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 51071d4279SBram Moolenaar # include "macglue.h" 52071d4279SBram Moolenaar # include <CodeFragments.h> 53071d4279SBram Moolenaar #endif 54071d4279SBram Moolenaar #undef main /* Defined in python.h - aargh */ 55071d4279SBram Moolenaar #undef HAVE_FCNTL_H /* Clash with os_win32.h */ 56071d4279SBram Moolenaar 57*170bf1aeSBram Moolenaar static void init_structs(void); 58*170bf1aeSBram Moolenaar 59071d4279SBram Moolenaar #if !defined(FEAT_PYTHON) && defined(PROTO) 60071d4279SBram Moolenaar /* Use this to be able to generate prototypes without python being used. */ 61e7cb9cf6SBram Moolenaar # define PyObject Py_ssize_t 62e7cb9cf6SBram Moolenaar # define PyThreadState Py_ssize_t 63e7cb9cf6SBram Moolenaar # define PyTypeObject Py_ssize_t 64e7cb9cf6SBram Moolenaar struct PyMethodDef { Py_ssize_t a; }; 65e7cb9cf6SBram Moolenaar # define PySequenceMethods Py_ssize_t 66071d4279SBram Moolenaar #endif 67071d4279SBram Moolenaar 682c45e945SBram Moolenaar #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000 692c45e945SBram Moolenaar # define PyInt Py_ssize_t 702c45e945SBram Moolenaar # define PyInquiry lenfunc 712c45e945SBram Moolenaar # define PyIntArgFunc ssizeargfunc 722c45e945SBram Moolenaar # define PyIntIntArgFunc ssizessizeargfunc 732c45e945SBram Moolenaar # define PyIntObjArgProc ssizeobjargproc 742c45e945SBram Moolenaar # define PyIntIntObjArgProc ssizessizeobjargproc 75e7cb9cf6SBram Moolenaar # define Py_ssize_t_fmt "n" 762c45e945SBram Moolenaar #else 772c45e945SBram Moolenaar # define PyInt int 782c45e945SBram Moolenaar # define PyInquiry inquiry 792c45e945SBram Moolenaar # define PyIntArgFunc intargfunc 802c45e945SBram Moolenaar # define PyIntIntArgFunc intintargfunc 812c45e945SBram Moolenaar # define PyIntObjArgProc intobjargproc 822c45e945SBram Moolenaar # define PyIntIntObjArgProc intintobjargproc 83e7cb9cf6SBram Moolenaar # define Py_ssize_t_fmt "i" 842c45e945SBram Moolenaar #endif 852c45e945SBram Moolenaar 86071d4279SBram Moolenaar /* Parser flags */ 87071d4279SBram Moolenaar #define single_input 256 88071d4279SBram Moolenaar #define file_input 257 89071d4279SBram Moolenaar #define eval_input 258 90071d4279SBram Moolenaar 91071d4279SBram Moolenaar #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x020300F0 92071d4279SBram Moolenaar /* Python 2.3: can invoke ":python" recursively. */ 93071d4279SBram Moolenaar # define PY_CAN_RECURSE 94071d4279SBram Moolenaar #endif 95071d4279SBram Moolenaar 96071d4279SBram Moolenaar #if defined(DYNAMIC_PYTHON) || defined(PROTO) 97071d4279SBram Moolenaar # ifndef DYNAMIC_PYTHON 98e7cb9cf6SBram Moolenaar # define HINSTANCE long_u /* for generating prototypes */ 99071d4279SBram Moolenaar # endif 100071d4279SBram Moolenaar 101fa5d1e63SBram Moolenaar #ifndef WIN3264 102bd5e15fdSBram Moolenaar # include <dlfcn.h> 103bd5e15fdSBram Moolenaar # define FARPROC void* 104bd5e15fdSBram Moolenaar # define HINSTANCE void* 105fa5d1e63SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) 106bd5e15fdSBram Moolenaar # define close_dll dlclose 107bd5e15fdSBram Moolenaar # define symbol_from_dll dlsym 108bd5e15fdSBram Moolenaar #else 109bd5e15fdSBram Moolenaar # define load_dll LoadLibrary 110bd5e15fdSBram Moolenaar # define close_dll FreeLibrary 111bd5e15fdSBram Moolenaar # define symbol_from_dll GetProcAddress 112bd5e15fdSBram Moolenaar #endif 113bd5e15fdSBram Moolenaar 114e7cb9cf6SBram Moolenaar /* This makes if_python.c compile without warnings against Python 2.5 115e7cb9cf6SBram Moolenaar * on Win32 and Win64. */ 116e7cb9cf6SBram Moolenaar #undef PyRun_SimpleString 117e7cb9cf6SBram Moolenaar #undef PyArg_Parse 118e7cb9cf6SBram Moolenaar #undef PyArg_ParseTuple 119e7cb9cf6SBram Moolenaar #undef Py_BuildValue 120e7cb9cf6SBram Moolenaar #undef Py_InitModule4 121e7cb9cf6SBram Moolenaar #undef Py_InitModule4_64 122e7cb9cf6SBram Moolenaar 123071d4279SBram Moolenaar /* 124071d4279SBram Moolenaar * Wrapper defines 125071d4279SBram Moolenaar */ 126071d4279SBram Moolenaar # define PyArg_Parse dll_PyArg_Parse 127071d4279SBram Moolenaar # define PyArg_ParseTuple dll_PyArg_ParseTuple 128071d4279SBram Moolenaar # define PyDict_SetItemString dll_PyDict_SetItemString 129071d4279SBram Moolenaar # define PyErr_BadArgument dll_PyErr_BadArgument 130071d4279SBram Moolenaar # define PyErr_Clear dll_PyErr_Clear 131071d4279SBram Moolenaar # define PyErr_NoMemory dll_PyErr_NoMemory 132071d4279SBram Moolenaar # define PyErr_Occurred dll_PyErr_Occurred 133071d4279SBram Moolenaar # define PyErr_SetNone dll_PyErr_SetNone 134071d4279SBram Moolenaar # define PyErr_SetString dll_PyErr_SetString 135071d4279SBram Moolenaar # define PyEval_InitThreads dll_PyEval_InitThreads 136071d4279SBram Moolenaar # define PyEval_RestoreThread dll_PyEval_RestoreThread 137071d4279SBram Moolenaar # define PyEval_SaveThread dll_PyEval_SaveThread 138071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 139071d4279SBram Moolenaar # define PyGILState_Ensure dll_PyGILState_Ensure 140071d4279SBram Moolenaar # define PyGILState_Release dll_PyGILState_Release 141071d4279SBram Moolenaar # endif 142071d4279SBram Moolenaar # define PyInt_AsLong dll_PyInt_AsLong 143071d4279SBram Moolenaar # define PyInt_FromLong dll_PyInt_FromLong 144071d4279SBram Moolenaar # define PyInt_Type (*dll_PyInt_Type) 145071d4279SBram Moolenaar # define PyList_GetItem dll_PyList_GetItem 1460ac9379aSBram Moolenaar # define PyList_Append dll_PyList_Append 147071d4279SBram Moolenaar # define PyList_New dll_PyList_New 148071d4279SBram Moolenaar # define PyList_SetItem dll_PyList_SetItem 149071d4279SBram Moolenaar # define PyList_Size dll_PyList_Size 150071d4279SBram Moolenaar # define PyList_Type (*dll_PyList_Type) 151071d4279SBram Moolenaar # define PyImport_ImportModule dll_PyImport_ImportModule 1520ac9379aSBram Moolenaar # define PyDict_New dll_PyDict_New 153071d4279SBram Moolenaar # define PyDict_GetItemString dll_PyDict_GetItemString 154071d4279SBram Moolenaar # define PyModule_GetDict dll_PyModule_GetDict 155071d4279SBram Moolenaar # define PyRun_SimpleString dll_PyRun_SimpleString 156071d4279SBram Moolenaar # define PyString_AsString dll_PyString_AsString 157071d4279SBram Moolenaar # define PyString_FromString dll_PyString_FromString 158071d4279SBram Moolenaar # define PyString_FromStringAndSize dll_PyString_FromStringAndSize 159071d4279SBram Moolenaar # define PyString_Size dll_PyString_Size 160071d4279SBram Moolenaar # define PyString_Type (*dll_PyString_Type) 161071d4279SBram Moolenaar # define PySys_SetObject dll_PySys_SetObject 162071d4279SBram Moolenaar # define PySys_SetArgv dll_PySys_SetArgv 163071d4279SBram Moolenaar # define PyType_Type (*dll_PyType_Type) 164071d4279SBram Moolenaar # define Py_BuildValue dll_Py_BuildValue 165071d4279SBram Moolenaar # define Py_FindMethod dll_Py_FindMethod 166071d4279SBram Moolenaar # define Py_InitModule4 dll_Py_InitModule4 167071d4279SBram Moolenaar # define Py_Initialize dll_Py_Initialize 1680e21a3f6SBram Moolenaar # define Py_Finalize dll_Py_Finalize 1690e21a3f6SBram Moolenaar # define Py_IsInitialized dll_Py_IsInitialized 170071d4279SBram Moolenaar # define _PyObject_New dll__PyObject_New 171071d4279SBram Moolenaar # define _Py_NoneStruct (*dll__Py_NoneStruct) 172071d4279SBram Moolenaar # define PyObject_Init dll__PyObject_Init 173071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 174071d4279SBram Moolenaar # define PyType_IsSubtype dll_PyType_IsSubtype 175071d4279SBram Moolenaar # endif 176071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 177071d4279SBram Moolenaar # define PyObject_Malloc dll_PyObject_Malloc 178071d4279SBram Moolenaar # define PyObject_Free dll_PyObject_Free 179071d4279SBram Moolenaar # endif 180071d4279SBram Moolenaar 181071d4279SBram Moolenaar /* 182071d4279SBram Moolenaar * Pointers for dynamic link 183071d4279SBram Moolenaar */ 184071d4279SBram Moolenaar static int(*dll_PyArg_Parse)(PyObject *, char *, ...); 185071d4279SBram Moolenaar static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...); 186071d4279SBram Moolenaar static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); 187071d4279SBram Moolenaar static int(*dll_PyErr_BadArgument)(void); 188071d4279SBram Moolenaar static void(*dll_PyErr_Clear)(void); 189071d4279SBram Moolenaar static PyObject*(*dll_PyErr_NoMemory)(void); 190071d4279SBram Moolenaar static PyObject*(*dll_PyErr_Occurred)(void); 191071d4279SBram Moolenaar static void(*dll_PyErr_SetNone)(PyObject *); 192071d4279SBram Moolenaar static void(*dll_PyErr_SetString)(PyObject *, const char *); 193071d4279SBram Moolenaar static void(*dll_PyEval_InitThreads)(void); 194071d4279SBram Moolenaar static void(*dll_PyEval_RestoreThread)(PyThreadState *); 195071d4279SBram Moolenaar static PyThreadState*(*dll_PyEval_SaveThread)(void); 196071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 197071d4279SBram Moolenaar static PyGILState_STATE (*dll_PyGILState_Ensure)(void); 198071d4279SBram Moolenaar static void (*dll_PyGILState_Release)(PyGILState_STATE); 199071d4279SBram Moolenaar #endif 200071d4279SBram Moolenaar static long(*dll_PyInt_AsLong)(PyObject *); 201071d4279SBram Moolenaar static PyObject*(*dll_PyInt_FromLong)(long); 202071d4279SBram Moolenaar static PyTypeObject* dll_PyInt_Type; 2032c45e945SBram Moolenaar static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt); 2040ac9379aSBram Moolenaar static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *); 2052c45e945SBram Moolenaar static PyObject*(*dll_PyList_New)(PyInt size); 2062c45e945SBram Moolenaar static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *); 2072c45e945SBram Moolenaar static PyInt(*dll_PyList_Size)(PyObject *); 208071d4279SBram Moolenaar static PyTypeObject* dll_PyList_Type; 209071d4279SBram Moolenaar static PyObject*(*dll_PyImport_ImportModule)(const char *); 2100ac9379aSBram Moolenaar static PyObject*(*dll_PyDict_New)(void); 211071d4279SBram Moolenaar static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *); 212071d4279SBram Moolenaar static PyObject*(*dll_PyModule_GetDict)(PyObject *); 213071d4279SBram Moolenaar static int(*dll_PyRun_SimpleString)(char *); 214071d4279SBram Moolenaar static char*(*dll_PyString_AsString)(PyObject *); 215071d4279SBram Moolenaar static PyObject*(*dll_PyString_FromString)(const char *); 2162c45e945SBram Moolenaar static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt); 2172c45e945SBram Moolenaar static PyInt(*dll_PyString_Size)(PyObject *); 218071d4279SBram Moolenaar static PyTypeObject* dll_PyString_Type; 219071d4279SBram Moolenaar static int(*dll_PySys_SetObject)(char *, PyObject *); 220071d4279SBram Moolenaar static int(*dll_PySys_SetArgv)(int, char **); 221071d4279SBram Moolenaar static PyTypeObject* dll_PyType_Type; 222071d4279SBram Moolenaar static PyObject*(*dll_Py_BuildValue)(char *, ...); 223071d4279SBram Moolenaar static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *); 224071d4279SBram Moolenaar static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int); 225071d4279SBram Moolenaar static void(*dll_Py_Initialize)(void); 2260e21a3f6SBram Moolenaar static void(*dll_Py_Finalize)(void); 2270e21a3f6SBram Moolenaar static int(*dll_Py_IsInitialized)(void); 228071d4279SBram Moolenaar static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *); 229071d4279SBram Moolenaar static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *); 230071d4279SBram Moolenaar static PyObject* dll__Py_NoneStruct; 231071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 232071d4279SBram Moolenaar static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *); 233071d4279SBram Moolenaar # endif 234071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 235071d4279SBram Moolenaar static void* (*dll_PyObject_Malloc)(size_t); 236071d4279SBram Moolenaar static void (*dll_PyObject_Free)(void*); 237071d4279SBram Moolenaar # endif 238071d4279SBram Moolenaar 239071d4279SBram Moolenaar static HINSTANCE hinstPython = 0; /* Instance of python.dll */ 240071d4279SBram Moolenaar 241071d4279SBram Moolenaar /* Imported exception objects */ 242071d4279SBram Moolenaar static PyObject *imp_PyExc_AttributeError; 243071d4279SBram Moolenaar static PyObject *imp_PyExc_IndexError; 244071d4279SBram Moolenaar static PyObject *imp_PyExc_KeyboardInterrupt; 245071d4279SBram Moolenaar static PyObject *imp_PyExc_TypeError; 246071d4279SBram Moolenaar static PyObject *imp_PyExc_ValueError; 247071d4279SBram Moolenaar 248071d4279SBram Moolenaar # define PyExc_AttributeError imp_PyExc_AttributeError 249071d4279SBram Moolenaar # define PyExc_IndexError imp_PyExc_IndexError 250071d4279SBram Moolenaar # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt 251071d4279SBram Moolenaar # define PyExc_TypeError imp_PyExc_TypeError 252071d4279SBram Moolenaar # define PyExc_ValueError imp_PyExc_ValueError 253071d4279SBram Moolenaar 254071d4279SBram Moolenaar /* 255071d4279SBram Moolenaar * Table of name to function pointer of python. 256071d4279SBram Moolenaar */ 257071d4279SBram Moolenaar # define PYTHON_PROC FARPROC 258071d4279SBram Moolenaar static struct 259071d4279SBram Moolenaar { 260071d4279SBram Moolenaar char *name; 261071d4279SBram Moolenaar PYTHON_PROC *ptr; 262071d4279SBram Moolenaar } python_funcname_table[] = 263071d4279SBram Moolenaar { 264071d4279SBram Moolenaar {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse}, 265071d4279SBram Moolenaar {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple}, 266071d4279SBram Moolenaar {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString}, 267071d4279SBram Moolenaar {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument}, 268071d4279SBram Moolenaar {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear}, 269071d4279SBram Moolenaar {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory}, 270071d4279SBram Moolenaar {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred}, 271071d4279SBram Moolenaar {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone}, 272071d4279SBram Moolenaar {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString}, 273071d4279SBram Moolenaar {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads}, 274071d4279SBram Moolenaar {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread}, 275071d4279SBram Moolenaar {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread}, 276071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 277071d4279SBram Moolenaar {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure}, 278071d4279SBram Moolenaar {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release}, 279071d4279SBram Moolenaar # endif 280071d4279SBram Moolenaar {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong}, 281071d4279SBram Moolenaar {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong}, 282071d4279SBram Moolenaar {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type}, 283071d4279SBram Moolenaar {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem}, 2840ac9379aSBram Moolenaar {"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append}, 285071d4279SBram Moolenaar {"PyList_New", (PYTHON_PROC*)&dll_PyList_New}, 286071d4279SBram Moolenaar {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem}, 287071d4279SBram Moolenaar {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size}, 288071d4279SBram Moolenaar {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type}, 289071d4279SBram Moolenaar {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule}, 290071d4279SBram Moolenaar {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString}, 2910ac9379aSBram Moolenaar {"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New}, 292071d4279SBram Moolenaar {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict}, 293071d4279SBram Moolenaar {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString}, 294071d4279SBram Moolenaar {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString}, 295071d4279SBram Moolenaar {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString}, 296071d4279SBram Moolenaar {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize}, 297071d4279SBram Moolenaar {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size}, 298071d4279SBram Moolenaar {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type}, 299071d4279SBram Moolenaar {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject}, 300071d4279SBram Moolenaar {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv}, 301071d4279SBram Moolenaar {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type}, 302071d4279SBram Moolenaar {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue}, 303071d4279SBram Moolenaar {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod}, 304e7cb9cf6SBram Moolenaar # if (PY_VERSION_HEX >= 0x02050000) && SIZEOF_SIZE_T != SIZEOF_INT 305e7cb9cf6SBram Moolenaar {"Py_InitModule4_64", (PYTHON_PROC*)&dll_Py_InitModule4}, 306e7cb9cf6SBram Moolenaar # else 307071d4279SBram Moolenaar {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4}, 308e7cb9cf6SBram Moolenaar # endif 309071d4279SBram Moolenaar {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize}, 3100e21a3f6SBram Moolenaar {"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize}, 3110e21a3f6SBram Moolenaar {"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized}, 312071d4279SBram Moolenaar {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New}, 313071d4279SBram Moolenaar {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init}, 314071d4279SBram Moolenaar {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct}, 315071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 316071d4279SBram Moolenaar {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype}, 317071d4279SBram Moolenaar # endif 318071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 319071d4279SBram Moolenaar {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc}, 320071d4279SBram Moolenaar {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free}, 321071d4279SBram Moolenaar # endif 322071d4279SBram Moolenaar {"", NULL}, 323071d4279SBram Moolenaar }; 324071d4279SBram Moolenaar 325071d4279SBram Moolenaar /* 326071d4279SBram Moolenaar * Free python.dll 327071d4279SBram Moolenaar */ 328071d4279SBram Moolenaar static void 329071d4279SBram Moolenaar end_dynamic_python(void) 330071d4279SBram Moolenaar { 331071d4279SBram Moolenaar if (hinstPython) 332071d4279SBram Moolenaar { 333bd5e15fdSBram Moolenaar close_dll(hinstPython); 334071d4279SBram Moolenaar hinstPython = 0; 335071d4279SBram Moolenaar } 336071d4279SBram Moolenaar } 337071d4279SBram Moolenaar 338071d4279SBram Moolenaar /* 339071d4279SBram Moolenaar * Load library and get all pointers. 340071d4279SBram Moolenaar * Parameter 'libname' provides name of DLL. 341071d4279SBram Moolenaar * Return OK or FAIL. 342071d4279SBram Moolenaar */ 343071d4279SBram Moolenaar static int 344071d4279SBram Moolenaar python_runtime_link_init(char *libname, int verbose) 345071d4279SBram Moolenaar { 346071d4279SBram Moolenaar int i; 347071d4279SBram Moolenaar 3484c3a326cSBram Moolenaar #if defined(UNIX) && defined(FEAT_PYTHON3) 3494c3a326cSBram Moolenaar /* Can't have Python and Python3 loaded at the same time, it may cause a 3504c3a326cSBram Moolenaar * crash. */ 3514c3a326cSBram Moolenaar if (python3_loaded()) 3524c3a326cSBram Moolenaar { 3534c3a326cSBram Moolenaar EMSG(_("E999: Python: Cannot use :py and :py3 in one session")); 3544c3a326cSBram Moolenaar return FAIL; 3554c3a326cSBram Moolenaar } 3564c3a326cSBram Moolenaar #endif 3574c3a326cSBram Moolenaar 358071d4279SBram Moolenaar if (hinstPython) 359071d4279SBram Moolenaar return OK; 360bd5e15fdSBram Moolenaar hinstPython = load_dll(libname); 361071d4279SBram Moolenaar if (!hinstPython) 362071d4279SBram Moolenaar { 363071d4279SBram Moolenaar if (verbose) 364071d4279SBram Moolenaar EMSG2(_(e_loadlib), libname); 365071d4279SBram Moolenaar return FAIL; 366071d4279SBram Moolenaar } 367071d4279SBram Moolenaar 368071d4279SBram Moolenaar for (i = 0; python_funcname_table[i].ptr; ++i) 369071d4279SBram Moolenaar { 370bd5e15fdSBram Moolenaar if ((*python_funcname_table[i].ptr = symbol_from_dll(hinstPython, 371071d4279SBram Moolenaar python_funcname_table[i].name)) == NULL) 372071d4279SBram Moolenaar { 373bd5e15fdSBram Moolenaar close_dll(hinstPython); 374071d4279SBram Moolenaar hinstPython = 0; 375071d4279SBram Moolenaar if (verbose) 376071d4279SBram Moolenaar EMSG2(_(e_loadfunc), python_funcname_table[i].name); 377071d4279SBram Moolenaar return FAIL; 378071d4279SBram Moolenaar } 379071d4279SBram Moolenaar } 380071d4279SBram Moolenaar return OK; 381071d4279SBram Moolenaar } 382071d4279SBram Moolenaar 383071d4279SBram Moolenaar /* 384071d4279SBram Moolenaar * If python is enabled (there is installed python on Windows system) return 385071d4279SBram Moolenaar * TRUE, else FALSE. 386071d4279SBram Moolenaar */ 387071d4279SBram Moolenaar int 388e7cb9cf6SBram Moolenaar python_enabled(int verbose) 389071d4279SBram Moolenaar { 390071d4279SBram Moolenaar return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK; 391071d4279SBram Moolenaar } 392071d4279SBram Moolenaar 393071d4279SBram Moolenaar /* Load the standard Python exceptions - don't import the symbols from the 394071d4279SBram Moolenaar * DLL, as this can cause errors (importing data symbols is not reliable). 395071d4279SBram Moolenaar */ 396071d4279SBram Moolenaar static void get_exceptions __ARGS((void)); 397071d4279SBram Moolenaar 398071d4279SBram Moolenaar static void 399071d4279SBram Moolenaar get_exceptions() 400071d4279SBram Moolenaar { 401071d4279SBram Moolenaar PyObject *exmod = PyImport_ImportModule("exceptions"); 402071d4279SBram Moolenaar PyObject *exdict = PyModule_GetDict(exmod); 403071d4279SBram Moolenaar imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError"); 404071d4279SBram Moolenaar imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError"); 405071d4279SBram Moolenaar imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); 406071d4279SBram Moolenaar imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); 407071d4279SBram Moolenaar imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); 408071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_AttributeError); 409071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_IndexError); 410071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_KeyboardInterrupt); 411071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_TypeError); 412071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_ValueError); 413071d4279SBram Moolenaar Py_XDECREF(exmod); 414071d4279SBram Moolenaar } 415071d4279SBram Moolenaar #endif /* DYNAMIC_PYTHON */ 416071d4279SBram Moolenaar 417*170bf1aeSBram Moolenaar /* 418*170bf1aeSBram Moolenaar * Include the code shared with if_python3.c 419*170bf1aeSBram Moolenaar */ 420*170bf1aeSBram Moolenaar #include "if_py_both.h" 421*170bf1aeSBram Moolenaar 422*170bf1aeSBram Moolenaar 423071d4279SBram Moolenaar /****************************************************** 424071d4279SBram Moolenaar * Internal function prototypes. 425071d4279SBram Moolenaar */ 426071d4279SBram Moolenaar 427071d4279SBram Moolenaar static void DoPythonCommand(exarg_T *, const char *); 428e7cb9cf6SBram Moolenaar static PyInt RangeStart; 429e7cb9cf6SBram Moolenaar static PyInt RangeEnd; 430071d4279SBram Moolenaar 431071d4279SBram Moolenaar static void PythonIO_Flush(void); 432071d4279SBram Moolenaar static int PythonIO_Init(void); 433071d4279SBram Moolenaar static int PythonMod_Init(void); 434071d4279SBram Moolenaar 435071d4279SBram Moolenaar /* Utility functions for the vim/python interface 436071d4279SBram Moolenaar * ---------------------------------------------- 437071d4279SBram Moolenaar */ 438e7cb9cf6SBram Moolenaar static PyObject *GetBufferLine(buf_T *, PyInt); 4392c45e945SBram Moolenaar static PyObject *GetBufferLineList(buf_T *, PyInt, PyInt); 440071d4279SBram Moolenaar 441e7cb9cf6SBram Moolenaar static int SetBufferLine(buf_T *, PyInt, PyObject *, PyInt *); 442e7cb9cf6SBram Moolenaar static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, PyInt *); 443e7cb9cf6SBram Moolenaar static int InsertBufferLines(buf_T *, PyInt, PyObject *, PyInt *); 444071d4279SBram Moolenaar 445071d4279SBram Moolenaar static PyObject *LineToString(const char *); 446071d4279SBram Moolenaar static char *StringToLine(PyObject *); 447071d4279SBram Moolenaar 448071d4279SBram Moolenaar #define PyErr_SetVim(str) PyErr_SetString(VimError, str) 449071d4279SBram Moolenaar 450071d4279SBram Moolenaar /****************************************************** 451071d4279SBram Moolenaar * 1. Python interpreter main program. 452071d4279SBram Moolenaar */ 453071d4279SBram Moolenaar 454071d4279SBram Moolenaar static int initialised = 0; 455071d4279SBram Moolenaar 456071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ 457071d4279SBram Moolenaar typedef PyObject PyThreadState; 4589ba0eb85SBram Moolenaar #endif 459071d4279SBram Moolenaar 4609ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4619ba0eb85SBram Moolenaar static PyGILState_STATE pygilstate = PyGILState_UNLOCKED; 4629ba0eb85SBram Moolenaar #else 463071d4279SBram Moolenaar static PyThreadState *saved_python_thread = NULL; 4649ba0eb85SBram Moolenaar #endif 465071d4279SBram Moolenaar 466071d4279SBram Moolenaar /* 467071d4279SBram Moolenaar * Suspend a thread of the Python interpreter, other threads are allowed to 468071d4279SBram Moolenaar * run. 469071d4279SBram Moolenaar */ 470293ee4d4SBram Moolenaar static void 471293ee4d4SBram Moolenaar Python_SaveThread(void) 472071d4279SBram Moolenaar { 4739ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4749ba0eb85SBram Moolenaar PyGILState_Release(pygilstate); 4759ba0eb85SBram Moolenaar #else 476071d4279SBram Moolenaar saved_python_thread = PyEval_SaveThread(); 4779ba0eb85SBram Moolenaar #endif 478071d4279SBram Moolenaar } 479071d4279SBram Moolenaar 480071d4279SBram Moolenaar /* 481071d4279SBram Moolenaar * Restore a thread of the Python interpreter, waits for other threads to 482071d4279SBram Moolenaar * block. 483071d4279SBram Moolenaar */ 484293ee4d4SBram Moolenaar static void 485293ee4d4SBram Moolenaar Python_RestoreThread(void) 486071d4279SBram Moolenaar { 4879ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4889ba0eb85SBram Moolenaar pygilstate = PyGILState_Ensure(); 4899ba0eb85SBram Moolenaar #else 490071d4279SBram Moolenaar PyEval_RestoreThread(saved_python_thread); 491071d4279SBram Moolenaar saved_python_thread = NULL; 492071d4279SBram Moolenaar #endif 4939ba0eb85SBram Moolenaar } 494071d4279SBram Moolenaar 495071d4279SBram Moolenaar void 496071d4279SBram Moolenaar python_end() 497071d4279SBram Moolenaar { 498a5792f58SBram Moolenaar static int recurse = 0; 499a5792f58SBram Moolenaar 500a5792f58SBram Moolenaar /* If a crash occurs while doing this, don't try again. */ 501a5792f58SBram Moolenaar if (recurse != 0) 502a5792f58SBram Moolenaar return; 503a5792f58SBram Moolenaar 504a5792f58SBram Moolenaar ++recurse; 505a5792f58SBram Moolenaar 506071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 5070e21a3f6SBram Moolenaar if (hinstPython && Py_IsInitialized()) 5089ba0eb85SBram Moolenaar { 5099ba0eb85SBram Moolenaar Python_RestoreThread(); /* enter python */ 5100e21a3f6SBram Moolenaar Py_Finalize(); 5119ba0eb85SBram Moolenaar } 512071d4279SBram Moolenaar end_dynamic_python(); 5130e21a3f6SBram Moolenaar #else 5140e21a3f6SBram Moolenaar if (Py_IsInitialized()) 5159ba0eb85SBram Moolenaar { 5169ba0eb85SBram Moolenaar Python_RestoreThread(); /* enter python */ 5170e21a3f6SBram Moolenaar Py_Finalize(); 5189ba0eb85SBram Moolenaar } 519071d4279SBram Moolenaar #endif 520a5792f58SBram Moolenaar 521a5792f58SBram Moolenaar --recurse; 522071d4279SBram Moolenaar } 523071d4279SBram Moolenaar 5244c3a326cSBram Moolenaar #if (defined(DYNAMIC_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO) 5254c3a326cSBram Moolenaar int 5264c3a326cSBram Moolenaar python_loaded() 5274c3a326cSBram Moolenaar { 5284c3a326cSBram Moolenaar return (hinstPython != 0); 5294c3a326cSBram Moolenaar } 5304c3a326cSBram Moolenaar #endif 5314c3a326cSBram Moolenaar 532071d4279SBram Moolenaar static int 533071d4279SBram Moolenaar Python_Init(void) 534071d4279SBram Moolenaar { 535071d4279SBram Moolenaar if (!initialised) 536071d4279SBram Moolenaar { 537071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 538071d4279SBram Moolenaar if (!python_enabled(TRUE)) 539071d4279SBram Moolenaar { 540071d4279SBram Moolenaar EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded.")); 541071d4279SBram Moolenaar goto fail; 542071d4279SBram Moolenaar } 543071d4279SBram Moolenaar #endif 544071d4279SBram Moolenaar 545*170bf1aeSBram Moolenaar init_structs(); 546*170bf1aeSBram Moolenaar 547071d4279SBram Moolenaar #if !defined(MACOS) || defined(MACOS_X_UNIX) 548071d4279SBram Moolenaar Py_Initialize(); 549071d4279SBram Moolenaar #else 550071d4279SBram Moolenaar PyMac_Initialize(); 551071d4279SBram Moolenaar #endif 552071d4279SBram Moolenaar /* initialise threads */ 553071d4279SBram Moolenaar PyEval_InitThreads(); 554071d4279SBram Moolenaar 555071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 556071d4279SBram Moolenaar get_exceptions(); 557071d4279SBram Moolenaar #endif 558071d4279SBram Moolenaar 559071d4279SBram Moolenaar if (PythonIO_Init()) 560071d4279SBram Moolenaar goto fail; 561071d4279SBram Moolenaar 562071d4279SBram Moolenaar if (PythonMod_Init()) 563071d4279SBram Moolenaar goto fail; 564071d4279SBram Moolenaar 5659774ecc8SBram Moolenaar /* Remove the element from sys.path that was added because of our 5669774ecc8SBram Moolenaar * argv[0] value in PythonMod_Init(). Previously we used an empty 5679774ecc8SBram Moolenaar * string, but dependinding on the OS we then get an empty entry or 5689774ecc8SBram Moolenaar * the current directory in sys.path. */ 5699774ecc8SBram Moolenaar PyRun_SimpleString("import sys; sys.path = filter(lambda x: x != '/must>not&exist', sys.path)"); 5709774ecc8SBram Moolenaar 571293ee4d4SBram Moolenaar /* the first python thread is vim's, release the lock */ 572071d4279SBram Moolenaar Python_SaveThread(); 573071d4279SBram Moolenaar 574071d4279SBram Moolenaar initialised = 1; 575071d4279SBram Moolenaar } 576071d4279SBram Moolenaar 577071d4279SBram Moolenaar return 0; 578071d4279SBram Moolenaar 579071d4279SBram Moolenaar fail: 580071d4279SBram Moolenaar /* We call PythonIO_Flush() here to print any Python errors. 581071d4279SBram Moolenaar * This is OK, as it is possible to call this function even 582071d4279SBram Moolenaar * if PythonIO_Init() has not completed successfully (it will 583071d4279SBram Moolenaar * not do anything in this case). 584071d4279SBram Moolenaar */ 585071d4279SBram Moolenaar PythonIO_Flush(); 586071d4279SBram Moolenaar return -1; 587071d4279SBram Moolenaar } 588071d4279SBram Moolenaar 589071d4279SBram Moolenaar /* 590071d4279SBram Moolenaar * External interface 591071d4279SBram Moolenaar */ 592071d4279SBram Moolenaar static void 593071d4279SBram Moolenaar DoPythonCommand(exarg_T *eap, const char *cmd) 594071d4279SBram Moolenaar { 5959ba0eb85SBram Moolenaar #ifndef PY_CAN_RECURSE 596071d4279SBram Moolenaar static int recursive = 0; 597071d4279SBram Moolenaar #endif 598071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 599071d4279SBram Moolenaar GrafPtr oldPort; 600071d4279SBram Moolenaar #endif 601071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 602071d4279SBram Moolenaar char *saved_locale; 603071d4279SBram Moolenaar #endif 604071d4279SBram Moolenaar 605071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 606071d4279SBram Moolenaar if (recursive) 607071d4279SBram Moolenaar { 608071d4279SBram Moolenaar EMSG(_("E659: Cannot invoke Python recursively")); 609071d4279SBram Moolenaar return; 610071d4279SBram Moolenaar } 611071d4279SBram Moolenaar ++recursive; 612071d4279SBram Moolenaar #endif 613071d4279SBram Moolenaar 614071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 615071d4279SBram Moolenaar GetPort(&oldPort); 616071d4279SBram Moolenaar /* Check if the Python library is available */ 617071d4279SBram Moolenaar if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress) 618071d4279SBram Moolenaar goto theend; 619071d4279SBram Moolenaar #endif 620071d4279SBram Moolenaar if (Python_Init()) 621071d4279SBram Moolenaar goto theend; 622071d4279SBram Moolenaar 623071d4279SBram Moolenaar RangeStart = eap->line1; 624071d4279SBram Moolenaar RangeEnd = eap->line2; 625071d4279SBram Moolenaar Python_Release_Vim(); /* leave vim */ 626071d4279SBram Moolenaar 627071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 628071d4279SBram Moolenaar /* Python only works properly when the LC_NUMERIC locale is "C". */ 629071d4279SBram Moolenaar saved_locale = setlocale(LC_NUMERIC, NULL); 630071d4279SBram Moolenaar if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0) 631071d4279SBram Moolenaar saved_locale = NULL; 632071d4279SBram Moolenaar else 633071d4279SBram Moolenaar { 634071d4279SBram Moolenaar /* Need to make a copy, value may change when setting new locale. */ 635071d4279SBram Moolenaar saved_locale = (char *)vim_strsave((char_u *)saved_locale); 636071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, "C"); 637071d4279SBram Moolenaar } 638071d4279SBram Moolenaar #endif 639071d4279SBram Moolenaar 640071d4279SBram Moolenaar Python_RestoreThread(); /* enter python */ 641071d4279SBram Moolenaar 642071d4279SBram Moolenaar PyRun_SimpleString((char *)(cmd)); 643071d4279SBram Moolenaar 644071d4279SBram Moolenaar Python_SaveThread(); /* leave python */ 645071d4279SBram Moolenaar 646071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 647071d4279SBram Moolenaar if (saved_locale != NULL) 648071d4279SBram Moolenaar { 649071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, saved_locale); 650071d4279SBram Moolenaar vim_free(saved_locale); 651071d4279SBram Moolenaar } 652071d4279SBram Moolenaar #endif 653071d4279SBram Moolenaar 654071d4279SBram Moolenaar Python_Lock_Vim(); /* enter vim */ 655071d4279SBram Moolenaar PythonIO_Flush(); 656071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 657071d4279SBram Moolenaar SetPort(oldPort); 658071d4279SBram Moolenaar #endif 659071d4279SBram Moolenaar 660071d4279SBram Moolenaar theend: 661071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 662071d4279SBram Moolenaar --recursive; 663071d4279SBram Moolenaar #endif 664071d4279SBram Moolenaar return; /* keeps lint happy */ 665071d4279SBram Moolenaar } 666071d4279SBram Moolenaar 667071d4279SBram Moolenaar /* 668071d4279SBram Moolenaar * ":python" 669071d4279SBram Moolenaar */ 670071d4279SBram Moolenaar void 671071d4279SBram Moolenaar ex_python(exarg_T *eap) 672071d4279SBram Moolenaar { 673071d4279SBram Moolenaar char_u *script; 674071d4279SBram Moolenaar 675071d4279SBram Moolenaar script = script_get(eap, eap->arg); 676071d4279SBram Moolenaar if (!eap->skip) 677071d4279SBram Moolenaar { 678071d4279SBram Moolenaar if (script == NULL) 679071d4279SBram Moolenaar DoPythonCommand(eap, (char *)eap->arg); 680071d4279SBram Moolenaar else 681071d4279SBram Moolenaar DoPythonCommand(eap, (char *)script); 682071d4279SBram Moolenaar } 683071d4279SBram Moolenaar vim_free(script); 684071d4279SBram Moolenaar } 685071d4279SBram Moolenaar 686071d4279SBram Moolenaar #define BUFFER_SIZE 1024 687071d4279SBram Moolenaar 688071d4279SBram Moolenaar /* 689071d4279SBram Moolenaar * ":pyfile" 690071d4279SBram Moolenaar */ 691071d4279SBram Moolenaar void 692071d4279SBram Moolenaar ex_pyfile(exarg_T *eap) 693071d4279SBram Moolenaar { 694071d4279SBram Moolenaar static char buffer[BUFFER_SIZE]; 695071d4279SBram Moolenaar const char *file = (char *)eap->arg; 696071d4279SBram Moolenaar char *p; 697071d4279SBram Moolenaar 698071d4279SBram Moolenaar /* Have to do it like this. PyRun_SimpleFile requires you to pass a 699071d4279SBram Moolenaar * stdio file pointer, but Vim and the Python DLL are compiled with 700071d4279SBram Moolenaar * different options under Windows, meaning that stdio pointers aren't 701071d4279SBram Moolenaar * compatible between the two. Yuk. 702071d4279SBram Moolenaar * 703071d4279SBram Moolenaar * Put the string "execfile('file')" into buffer. But, we need to 704071d4279SBram Moolenaar * escape any backslashes or single quotes in the file name, so that 705071d4279SBram Moolenaar * Python won't mangle the file name. 706071d4279SBram Moolenaar */ 707071d4279SBram Moolenaar strcpy(buffer, "execfile('"); 708071d4279SBram Moolenaar p = buffer + 10; /* size of "execfile('" */ 709071d4279SBram Moolenaar 710071d4279SBram Moolenaar while (*file && p < buffer + (BUFFER_SIZE - 3)) 711071d4279SBram Moolenaar { 712071d4279SBram Moolenaar if (*file == '\\' || *file == '\'') 713071d4279SBram Moolenaar *p++ = '\\'; 714071d4279SBram Moolenaar *p++ = *file++; 715071d4279SBram Moolenaar } 716071d4279SBram Moolenaar 717071d4279SBram Moolenaar /* If we didn't finish the file name, we hit a buffer overflow */ 718071d4279SBram Moolenaar if (*file != '\0') 719071d4279SBram Moolenaar return; 720071d4279SBram Moolenaar 721071d4279SBram Moolenaar /* Put in the terminating "')" and a null */ 722071d4279SBram Moolenaar *p++ = '\''; 723071d4279SBram Moolenaar *p++ = ')'; 724071d4279SBram Moolenaar *p++ = '\0'; 725071d4279SBram Moolenaar 726071d4279SBram Moolenaar /* Execute the file */ 727071d4279SBram Moolenaar DoPythonCommand(eap, buffer); 728071d4279SBram Moolenaar } 729071d4279SBram Moolenaar 730071d4279SBram Moolenaar /****************************************************** 731071d4279SBram Moolenaar * 2. Python output stream: writes output via [e]msg(). 732071d4279SBram Moolenaar */ 733071d4279SBram Moolenaar 734071d4279SBram Moolenaar /* Implementation functions 735071d4279SBram Moolenaar */ 736071d4279SBram Moolenaar 737071d4279SBram Moolenaar static PyObject *OutputGetattr(PyObject *, char *); 738071d4279SBram Moolenaar static int OutputSetattr(PyObject *, char *, PyObject *); 739071d4279SBram Moolenaar 740071d4279SBram Moolenaar /*************/ 741071d4279SBram Moolenaar 742071d4279SBram Moolenaar static PyObject * 743071d4279SBram Moolenaar OutputGetattr(PyObject *self, char *name) 744071d4279SBram Moolenaar { 745071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 746071d4279SBram Moolenaar return PyInt_FromLong(((OutputObject *)(self))->softspace); 747071d4279SBram Moolenaar 748071d4279SBram Moolenaar return Py_FindMethod(OutputMethods, self, name); 749071d4279SBram Moolenaar } 750071d4279SBram Moolenaar 751071d4279SBram Moolenaar static int 752071d4279SBram Moolenaar OutputSetattr(PyObject *self, char *name, PyObject *val) 753071d4279SBram Moolenaar { 754071d4279SBram Moolenaar if (val == NULL) { 755071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes")); 756071d4279SBram Moolenaar return -1; 757071d4279SBram Moolenaar } 758071d4279SBram Moolenaar 759071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 760071d4279SBram Moolenaar { 761071d4279SBram Moolenaar if (!PyInt_Check(val)) { 762071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("softspace must be an integer")); 763071d4279SBram Moolenaar return -1; 764071d4279SBram Moolenaar } 765071d4279SBram Moolenaar 766071d4279SBram Moolenaar ((OutputObject *)(self))->softspace = PyInt_AsLong(val); 767071d4279SBram Moolenaar return 0; 768071d4279SBram Moolenaar } 769071d4279SBram Moolenaar 770071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("invalid attribute")); 771071d4279SBram Moolenaar return -1; 772071d4279SBram Moolenaar } 773071d4279SBram Moolenaar 774071d4279SBram Moolenaar /***************/ 775071d4279SBram Moolenaar 776071d4279SBram Moolenaar static int 777071d4279SBram Moolenaar PythonIO_Init(void) 778071d4279SBram Moolenaar { 779071d4279SBram Moolenaar /* Fixups... */ 780071d4279SBram Moolenaar OutputType.ob_type = &PyType_Type; 781071d4279SBram Moolenaar 782*170bf1aeSBram Moolenaar return PythonIO_Init_io(); 783071d4279SBram Moolenaar } 784071d4279SBram Moolenaar 785071d4279SBram Moolenaar /****************************************************** 786071d4279SBram Moolenaar * 3. Implementation of the Vim module for Python 787071d4279SBram Moolenaar */ 788071d4279SBram Moolenaar 789071d4279SBram Moolenaar /* Vim module - Implementation functions 790071d4279SBram Moolenaar * ------------------------------------- 791071d4279SBram Moolenaar */ 792071d4279SBram Moolenaar 793071d4279SBram Moolenaar static PyObject *VimCommand(PyObject *, PyObject *); 794071d4279SBram Moolenaar static PyObject *VimEval(PyObject *, PyObject *); 795071d4279SBram Moolenaar 796071d4279SBram Moolenaar /* Window type - Implementation functions 797071d4279SBram Moolenaar * -------------------------------------- 798071d4279SBram Moolenaar */ 799071d4279SBram Moolenaar 800071d4279SBram Moolenaar typedef struct 801071d4279SBram Moolenaar { 802071d4279SBram Moolenaar PyObject_HEAD 803071d4279SBram Moolenaar win_T *win; 804071d4279SBram Moolenaar } 805071d4279SBram Moolenaar WindowObject; 806071d4279SBram Moolenaar 807071d4279SBram Moolenaar #define INVALID_WINDOW_VALUE ((win_T *)(-1)) 808071d4279SBram Moolenaar 809071d4279SBram Moolenaar #define WindowType_Check(obj) ((obj)->ob_type == &WindowType) 810071d4279SBram Moolenaar 811071d4279SBram Moolenaar static PyObject *WindowNew(win_T *); 812071d4279SBram Moolenaar 813071d4279SBram Moolenaar static void WindowDestructor(PyObject *); 814071d4279SBram Moolenaar static PyObject *WindowGetattr(PyObject *, char *); 815071d4279SBram Moolenaar static int WindowSetattr(PyObject *, char *, PyObject *); 816071d4279SBram Moolenaar static PyObject *WindowRepr(PyObject *); 817071d4279SBram Moolenaar 818071d4279SBram Moolenaar /* Buffer type - Implementation functions 819071d4279SBram Moolenaar * -------------------------------------- 820071d4279SBram Moolenaar */ 821071d4279SBram Moolenaar 822071d4279SBram Moolenaar typedef struct 823071d4279SBram Moolenaar { 824071d4279SBram Moolenaar PyObject_HEAD 825071d4279SBram Moolenaar buf_T *buf; 826071d4279SBram Moolenaar } 827071d4279SBram Moolenaar BufferObject; 828071d4279SBram Moolenaar 829071d4279SBram Moolenaar #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) 830071d4279SBram Moolenaar 831071d4279SBram Moolenaar #define BufferType_Check(obj) ((obj)->ob_type == &BufferType) 832071d4279SBram Moolenaar 833071d4279SBram Moolenaar static PyObject *BufferNew (buf_T *); 834071d4279SBram Moolenaar 835071d4279SBram Moolenaar static void BufferDestructor(PyObject *); 836071d4279SBram Moolenaar static PyObject *BufferGetattr(PyObject *, char *); 837071d4279SBram Moolenaar static PyObject *BufferRepr(PyObject *); 838071d4279SBram Moolenaar 8392c45e945SBram Moolenaar static PyInt BufferLength(PyObject *); 8402c45e945SBram Moolenaar static PyObject *BufferItem(PyObject *, PyInt); 8412c45e945SBram Moolenaar static PyObject *BufferSlice(PyObject *, PyInt, PyInt); 8422c45e945SBram Moolenaar static PyInt BufferAssItem(PyObject *, PyInt, PyObject *); 8432c45e945SBram Moolenaar static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *); 844071d4279SBram Moolenaar 845071d4279SBram Moolenaar static PyObject *BufferAppend(PyObject *, PyObject *); 846071d4279SBram Moolenaar static PyObject *BufferMark(PyObject *, PyObject *); 847071d4279SBram Moolenaar static PyObject *BufferRange(PyObject *, PyObject *); 848071d4279SBram Moolenaar 849071d4279SBram Moolenaar /* Line range type - Implementation functions 850071d4279SBram Moolenaar * -------------------------------------- 851071d4279SBram Moolenaar */ 852071d4279SBram Moolenaar 853071d4279SBram Moolenaar typedef struct 854071d4279SBram Moolenaar { 855071d4279SBram Moolenaar PyObject_HEAD 856071d4279SBram Moolenaar BufferObject *buf; 857e7cb9cf6SBram Moolenaar PyInt start; 858e7cb9cf6SBram Moolenaar PyInt end; 859071d4279SBram Moolenaar } 860071d4279SBram Moolenaar RangeObject; 861071d4279SBram Moolenaar 862071d4279SBram Moolenaar #define RangeType_Check(obj) ((obj)->ob_type == &RangeType) 863071d4279SBram Moolenaar 864e7cb9cf6SBram Moolenaar static PyObject *RangeNew(buf_T *, PyInt, PyInt); 865071d4279SBram Moolenaar 866071d4279SBram Moolenaar static void RangeDestructor(PyObject *); 867071d4279SBram Moolenaar static PyObject *RangeGetattr(PyObject *, char *); 868071d4279SBram Moolenaar static PyObject *RangeRepr(PyObject *); 869071d4279SBram Moolenaar 8702c45e945SBram Moolenaar static PyInt RangeLength(PyObject *); 8712c45e945SBram Moolenaar static PyObject *RangeItem(PyObject *, PyInt); 8722c45e945SBram Moolenaar static PyObject *RangeSlice(PyObject *, PyInt, PyInt); 8732c45e945SBram Moolenaar static PyInt RangeAssItem(PyObject *, PyInt, PyObject *); 8742c45e945SBram Moolenaar static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *); 875071d4279SBram Moolenaar 876071d4279SBram Moolenaar static PyObject *RangeAppend(PyObject *, PyObject *); 877071d4279SBram Moolenaar 878071d4279SBram Moolenaar /* Window list type - Implementation functions 879071d4279SBram Moolenaar * ------------------------------------------- 880071d4279SBram Moolenaar */ 881071d4279SBram Moolenaar 8822c45e945SBram Moolenaar static PyInt WinListLength(PyObject *); 8832c45e945SBram Moolenaar static PyObject *WinListItem(PyObject *, PyInt); 884071d4279SBram Moolenaar 885071d4279SBram Moolenaar /* Buffer list type - Implementation functions 886071d4279SBram Moolenaar * ------------------------------------------- 887071d4279SBram Moolenaar */ 888071d4279SBram Moolenaar 8892c45e945SBram Moolenaar static PyInt BufListLength(PyObject *); 8902c45e945SBram Moolenaar static PyObject *BufListItem(PyObject *, PyInt); 891071d4279SBram Moolenaar 892071d4279SBram Moolenaar /* Current objects type - Implementation functions 893071d4279SBram Moolenaar * ----------------------------------------------- 894071d4279SBram Moolenaar */ 895071d4279SBram Moolenaar 896071d4279SBram Moolenaar static PyObject *CurrentGetattr(PyObject *, char *); 897071d4279SBram Moolenaar static int CurrentSetattr(PyObject *, char *, PyObject *); 898071d4279SBram Moolenaar 899071d4279SBram Moolenaar /* Vim module - Definitions 900071d4279SBram Moolenaar */ 901071d4279SBram Moolenaar 902071d4279SBram Moolenaar static struct PyMethodDef VimMethods[] = { 903071d4279SBram Moolenaar /* name, function, calling, documentation */ 904e7cb9cf6SBram Moolenaar {"command", VimCommand, 1, "Execute a Vim ex-mode command" }, 905e7cb9cf6SBram Moolenaar {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" }, 906071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 907071d4279SBram Moolenaar }; 908071d4279SBram Moolenaar 909071d4279SBram Moolenaar /* Vim module - Implementation 910071d4279SBram Moolenaar */ 911071d4279SBram Moolenaar static PyObject * 9124bdbbf70SBram Moolenaar VimCommand(PyObject *self UNUSED, PyObject *args) 913071d4279SBram Moolenaar { 914071d4279SBram Moolenaar char *cmd; 915071d4279SBram Moolenaar PyObject *result; 916071d4279SBram Moolenaar 917071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "s", &cmd)) 918071d4279SBram Moolenaar return NULL; 919071d4279SBram Moolenaar 920071d4279SBram Moolenaar PyErr_Clear(); 921071d4279SBram Moolenaar 922071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 923071d4279SBram Moolenaar Python_Lock_Vim(); 924071d4279SBram Moolenaar 925071d4279SBram Moolenaar do_cmdline_cmd((char_u *)cmd); 926071d4279SBram Moolenaar update_screen(VALID); 927071d4279SBram Moolenaar 928071d4279SBram Moolenaar Python_Release_Vim(); 929071d4279SBram Moolenaar Py_END_ALLOW_THREADS 930071d4279SBram Moolenaar 931071d4279SBram Moolenaar if (VimErrorCheck()) 932071d4279SBram Moolenaar result = NULL; 933071d4279SBram Moolenaar else 934071d4279SBram Moolenaar result = Py_None; 935071d4279SBram Moolenaar 936071d4279SBram Moolenaar Py_XINCREF(result); 937071d4279SBram Moolenaar return result; 938071d4279SBram Moolenaar } 939071d4279SBram Moolenaar 94001dd60cbSBram Moolenaar #ifdef FEAT_EVAL 941b71eaaeaSBram Moolenaar /* 942b71eaaeaSBram Moolenaar * Function to translate a typval_T into a PyObject; this will recursively 943b71eaaeaSBram Moolenaar * translate lists/dictionaries into their Python equivalents. 944b71eaaeaSBram Moolenaar * 945e7cb9cf6SBram Moolenaar * The depth parameter is to avoid infinite recursion, set it to 1 when 946b71eaaeaSBram Moolenaar * you call VimToPython. 947b71eaaeaSBram Moolenaar */ 948b71eaaeaSBram Moolenaar static PyObject * 949b71eaaeaSBram Moolenaar VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict) 950b71eaaeaSBram Moolenaar { 951b71eaaeaSBram Moolenaar PyObject *result; 952b71eaaeaSBram Moolenaar PyObject *newObj; 953b71eaaeaSBram Moolenaar char ptrBuf[NUMBUFLEN]; 954b71eaaeaSBram Moolenaar 955b71eaaeaSBram Moolenaar /* Avoid infinite recursion */ 956b71eaaeaSBram Moolenaar if (depth > 100) 957b71eaaeaSBram Moolenaar { 958b71eaaeaSBram Moolenaar Py_INCREF(Py_None); 959b71eaaeaSBram Moolenaar result = Py_None; 960b71eaaeaSBram Moolenaar return result; 961b71eaaeaSBram Moolenaar } 962b71eaaeaSBram Moolenaar 963b71eaaeaSBram Moolenaar /* Check if we run into a recursive loop. The item must be in lookupDict 964b71eaaeaSBram Moolenaar * then and we can use it again. */ 965d72b386aSBram Moolenaar if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL) 966d72b386aSBram Moolenaar || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL)) 967d72b386aSBram Moolenaar { 968d72b386aSBram Moolenaar sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U, 969d72b386aSBram Moolenaar our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list 970d72b386aSBram Moolenaar : (long_u)our_tv->vval.v_dict); 971b71eaaeaSBram Moolenaar result = PyDict_GetItemString(lookupDict, ptrBuf); 972b71eaaeaSBram Moolenaar if (result != NULL) 973d72b386aSBram Moolenaar { 974b71eaaeaSBram Moolenaar Py_INCREF(result); 975d72b386aSBram Moolenaar return result; 976d72b386aSBram Moolenaar } 977d72b386aSBram Moolenaar } 978d72b386aSBram Moolenaar 979d72b386aSBram Moolenaar if (our_tv->v_type == VAR_STRING) 980b71eaaeaSBram Moolenaar { 981b71eaaeaSBram Moolenaar result = Py_BuildValue("s", our_tv->vval.v_string); 982b71eaaeaSBram Moolenaar } 983b71eaaeaSBram Moolenaar else if (our_tv->v_type == VAR_NUMBER) 984b71eaaeaSBram Moolenaar { 985b71eaaeaSBram Moolenaar char buf[NUMBUFLEN]; 986b71eaaeaSBram Moolenaar 987b71eaaeaSBram Moolenaar /* For backwards compatibility numbers are stored as strings. */ 988b71eaaeaSBram Moolenaar sprintf(buf, "%ld", (long)our_tv->vval.v_number); 989b71eaaeaSBram Moolenaar result = Py_BuildValue("s", buf); 990b71eaaeaSBram Moolenaar } 9912c45e945SBram Moolenaar # ifdef FEAT_FLOAT 9922c45e945SBram Moolenaar else if (our_tv->v_type == VAR_FLOAT) 9932c45e945SBram Moolenaar { 9942c45e945SBram Moolenaar char buf[NUMBUFLEN]; 9952c45e945SBram Moolenaar 9962c45e945SBram Moolenaar sprintf(buf, "%f", our_tv->vval.v_float); 9972c45e945SBram Moolenaar result = Py_BuildValue("s", buf); 9982c45e945SBram Moolenaar } 9992c45e945SBram Moolenaar # endif 1000b71eaaeaSBram Moolenaar else if (our_tv->v_type == VAR_LIST) 1001b71eaaeaSBram Moolenaar { 1002b71eaaeaSBram Moolenaar list_T *list = our_tv->vval.v_list; 1003b71eaaeaSBram Moolenaar listitem_T *curr; 1004b71eaaeaSBram Moolenaar 1005b71eaaeaSBram Moolenaar result = PyList_New(0); 1006b71eaaeaSBram Moolenaar 1007b71eaaeaSBram Moolenaar if (list != NULL) 1008b71eaaeaSBram Moolenaar { 1009d72b386aSBram Moolenaar PyDict_SetItemString(lookupDict, ptrBuf, result); 1010d72b386aSBram Moolenaar 1011b71eaaeaSBram Moolenaar for (curr = list->lv_first; curr != NULL; curr = curr->li_next) 1012b71eaaeaSBram Moolenaar { 1013b71eaaeaSBram Moolenaar newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict); 1014b71eaaeaSBram Moolenaar PyList_Append(result, newObj); 1015b71eaaeaSBram Moolenaar Py_DECREF(newObj); 1016b71eaaeaSBram Moolenaar } 1017b71eaaeaSBram Moolenaar } 1018b71eaaeaSBram Moolenaar } 1019b71eaaeaSBram Moolenaar else if (our_tv->v_type == VAR_DICT) 1020b71eaaeaSBram Moolenaar { 1021b71eaaeaSBram Moolenaar result = PyDict_New(); 1022b71eaaeaSBram Moolenaar 1023b71eaaeaSBram Moolenaar if (our_tv->vval.v_dict != NULL) 1024b71eaaeaSBram Moolenaar { 1025b71eaaeaSBram Moolenaar hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab; 1026e7cb9cf6SBram Moolenaar long_u todo = ht->ht_used; 1027b71eaaeaSBram Moolenaar hashitem_T *hi; 1028b71eaaeaSBram Moolenaar dictitem_T *di; 1029b71eaaeaSBram Moolenaar 1030d72b386aSBram Moolenaar PyDict_SetItemString(lookupDict, ptrBuf, result); 1031d72b386aSBram Moolenaar 1032b71eaaeaSBram Moolenaar for (hi = ht->ht_array; todo > 0; ++hi) 1033b71eaaeaSBram Moolenaar { 1034b71eaaeaSBram Moolenaar if (!HASHITEM_EMPTY(hi)) 1035b71eaaeaSBram Moolenaar { 1036b71eaaeaSBram Moolenaar --todo; 1037b71eaaeaSBram Moolenaar 1038b71eaaeaSBram Moolenaar di = dict_lookup(hi); 1039b71eaaeaSBram Moolenaar newObj = VimToPython(&di->di_tv, depth + 1, lookupDict); 1040b71eaaeaSBram Moolenaar PyDict_SetItemString(result, (char *)hi->hi_key, newObj); 1041b71eaaeaSBram Moolenaar Py_DECREF(newObj); 1042b71eaaeaSBram Moolenaar } 1043b71eaaeaSBram Moolenaar } 1044b71eaaeaSBram Moolenaar } 1045b71eaaeaSBram Moolenaar } 1046b71eaaeaSBram Moolenaar else 1047b71eaaeaSBram Moolenaar { 1048b71eaaeaSBram Moolenaar Py_INCREF(Py_None); 1049b71eaaeaSBram Moolenaar result = Py_None; 1050b71eaaeaSBram Moolenaar } 1051b71eaaeaSBram Moolenaar 1052b71eaaeaSBram Moolenaar return result; 1053b71eaaeaSBram Moolenaar } 105401dd60cbSBram Moolenaar #endif 1055b71eaaeaSBram Moolenaar 1056071d4279SBram Moolenaar static PyObject * 10574bdbbf70SBram Moolenaar VimEval(PyObject *self UNUSED, PyObject *args) 1058071d4279SBram Moolenaar { 1059071d4279SBram Moolenaar #ifdef FEAT_EVAL 1060071d4279SBram Moolenaar char *expr; 1061b71eaaeaSBram Moolenaar typval_T *our_tv; 1062071d4279SBram Moolenaar PyObject *result; 1063b71eaaeaSBram Moolenaar PyObject *lookup_dict; 1064071d4279SBram Moolenaar 1065071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "s", &expr)) 1066071d4279SBram Moolenaar return NULL; 1067071d4279SBram Moolenaar 1068071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 1069071d4279SBram Moolenaar Python_Lock_Vim(); 1070b71eaaeaSBram Moolenaar our_tv = eval_expr((char_u *)expr, NULL); 1071b71eaaeaSBram Moolenaar 1072071d4279SBram Moolenaar Python_Release_Vim(); 1073071d4279SBram Moolenaar Py_END_ALLOW_THREADS 1074071d4279SBram Moolenaar 1075b71eaaeaSBram Moolenaar if (our_tv == NULL) 1076071d4279SBram Moolenaar { 1077071d4279SBram Moolenaar PyErr_SetVim(_("invalid expression")); 1078071d4279SBram Moolenaar return NULL; 1079071d4279SBram Moolenaar } 1080071d4279SBram Moolenaar 1081b71eaaeaSBram Moolenaar /* Convert the Vim type into a Python type. Create a dictionary that's 1082b71eaaeaSBram Moolenaar * used to check for recursive loops. */ 1083b71eaaeaSBram Moolenaar lookup_dict = PyDict_New(); 1084b71eaaeaSBram Moolenaar result = VimToPython(our_tv, 1, lookup_dict); 1085b71eaaeaSBram Moolenaar Py_DECREF(lookup_dict); 1086b71eaaeaSBram Moolenaar 1087071d4279SBram Moolenaar 1088071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 1089071d4279SBram Moolenaar Python_Lock_Vim(); 1090b71eaaeaSBram Moolenaar free_tv(our_tv); 1091071d4279SBram Moolenaar Python_Release_Vim(); 1092071d4279SBram Moolenaar Py_END_ALLOW_THREADS 1093071d4279SBram Moolenaar 1094071d4279SBram Moolenaar return result; 1095071d4279SBram Moolenaar #else 1096071d4279SBram Moolenaar PyErr_SetVim(_("expressions disabled at compile time")); 1097071d4279SBram Moolenaar return NULL; 1098071d4279SBram Moolenaar #endif 1099071d4279SBram Moolenaar } 1100071d4279SBram Moolenaar 1101071d4279SBram Moolenaar /* Common routines for buffers and line ranges 1102071d4279SBram Moolenaar * ------------------------------------------- 1103071d4279SBram Moolenaar */ 1104*170bf1aeSBram Moolenaar 1105071d4279SBram Moolenaar static int 1106071d4279SBram Moolenaar CheckBuffer(BufferObject *this) 1107071d4279SBram Moolenaar { 1108071d4279SBram Moolenaar if (this->buf == INVALID_BUFFER_VALUE) 1109071d4279SBram Moolenaar { 1110071d4279SBram Moolenaar PyErr_SetVim(_("attempt to refer to deleted buffer")); 1111071d4279SBram Moolenaar return -1; 1112071d4279SBram Moolenaar } 1113071d4279SBram Moolenaar 1114071d4279SBram Moolenaar return 0; 1115071d4279SBram Moolenaar } 1116071d4279SBram Moolenaar 1117071d4279SBram Moolenaar static PyObject * 1118e7cb9cf6SBram Moolenaar RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end) 1119071d4279SBram Moolenaar { 1120071d4279SBram Moolenaar if (CheckBuffer(self)) 1121071d4279SBram Moolenaar return NULL; 1122071d4279SBram Moolenaar 1123071d4279SBram Moolenaar if (n < 0 || n > end - start) 1124071d4279SBram Moolenaar { 1125071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("line number out of range")); 1126071d4279SBram Moolenaar return NULL; 1127071d4279SBram Moolenaar } 1128071d4279SBram Moolenaar 1129071d4279SBram Moolenaar return GetBufferLine(self->buf, n+start); 1130071d4279SBram Moolenaar } 1131071d4279SBram Moolenaar 1132071d4279SBram Moolenaar static PyObject * 1133e7cb9cf6SBram Moolenaar RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end) 1134071d4279SBram Moolenaar { 11352c45e945SBram Moolenaar PyInt size; 1136071d4279SBram Moolenaar 1137071d4279SBram Moolenaar if (CheckBuffer(self)) 1138071d4279SBram Moolenaar return NULL; 1139071d4279SBram Moolenaar 1140071d4279SBram Moolenaar size = end - start + 1; 1141071d4279SBram Moolenaar 1142071d4279SBram Moolenaar if (lo < 0) 1143071d4279SBram Moolenaar lo = 0; 1144071d4279SBram Moolenaar else if (lo > size) 1145071d4279SBram Moolenaar lo = size; 1146071d4279SBram Moolenaar if (hi < 0) 1147071d4279SBram Moolenaar hi = 0; 1148071d4279SBram Moolenaar if (hi < lo) 1149071d4279SBram Moolenaar hi = lo; 1150071d4279SBram Moolenaar else if (hi > size) 1151071d4279SBram Moolenaar hi = size; 1152071d4279SBram Moolenaar 1153071d4279SBram Moolenaar return GetBufferLineList(self->buf, lo+start, hi+start); 1154071d4279SBram Moolenaar } 1155071d4279SBram Moolenaar 11562c45e945SBram Moolenaar static PyInt 1157e7cb9cf6SBram Moolenaar RBAssItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end) 1158071d4279SBram Moolenaar { 1159e7cb9cf6SBram Moolenaar PyInt len_change; 1160071d4279SBram Moolenaar 1161071d4279SBram Moolenaar if (CheckBuffer(self)) 1162071d4279SBram Moolenaar return -1; 1163071d4279SBram Moolenaar 1164071d4279SBram Moolenaar if (n < 0 || n > end - start) 1165071d4279SBram Moolenaar { 1166071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("line number out of range")); 1167071d4279SBram Moolenaar return -1; 1168071d4279SBram Moolenaar } 1169071d4279SBram Moolenaar 1170071d4279SBram Moolenaar if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL) 1171071d4279SBram Moolenaar return -1; 1172071d4279SBram Moolenaar 1173071d4279SBram Moolenaar if (new_end) 1174071d4279SBram Moolenaar *new_end = end + len_change; 1175071d4279SBram Moolenaar 1176071d4279SBram Moolenaar return 0; 1177071d4279SBram Moolenaar } 1178071d4279SBram Moolenaar 11792c45e945SBram Moolenaar static PyInt 1180e7cb9cf6SBram Moolenaar RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end) 1181071d4279SBram Moolenaar { 1182e7cb9cf6SBram Moolenaar PyInt size; 1183e7cb9cf6SBram Moolenaar PyInt len_change; 1184071d4279SBram Moolenaar 1185071d4279SBram Moolenaar /* Self must be a valid buffer */ 1186071d4279SBram Moolenaar if (CheckBuffer(self)) 1187071d4279SBram Moolenaar return -1; 1188071d4279SBram Moolenaar 1189071d4279SBram Moolenaar /* Sort out the slice range */ 1190071d4279SBram Moolenaar size = end - start + 1; 1191071d4279SBram Moolenaar 1192071d4279SBram Moolenaar if (lo < 0) 1193071d4279SBram Moolenaar lo = 0; 1194071d4279SBram Moolenaar else if (lo > size) 1195071d4279SBram Moolenaar lo = size; 1196071d4279SBram Moolenaar if (hi < 0) 1197071d4279SBram Moolenaar hi = 0; 1198071d4279SBram Moolenaar if (hi < lo) 1199071d4279SBram Moolenaar hi = lo; 1200071d4279SBram Moolenaar else if (hi > size) 1201071d4279SBram Moolenaar hi = size; 1202071d4279SBram Moolenaar 1203071d4279SBram Moolenaar if (SetBufferLineList(self->buf, lo+start, hi+start, val, &len_change) == FAIL) 1204071d4279SBram Moolenaar return -1; 1205071d4279SBram Moolenaar 1206071d4279SBram Moolenaar if (new_end) 1207071d4279SBram Moolenaar *new_end = end + len_change; 1208071d4279SBram Moolenaar 1209071d4279SBram Moolenaar return 0; 1210071d4279SBram Moolenaar } 1211071d4279SBram Moolenaar 1212071d4279SBram Moolenaar static PyObject * 1213e7cb9cf6SBram Moolenaar RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end) 1214071d4279SBram Moolenaar { 1215071d4279SBram Moolenaar PyObject *lines; 1216e7cb9cf6SBram Moolenaar PyInt len_change; 1217e7cb9cf6SBram Moolenaar PyInt max; 1218e7cb9cf6SBram Moolenaar PyInt n; 1219071d4279SBram Moolenaar 1220071d4279SBram Moolenaar if (CheckBuffer(self)) 1221071d4279SBram Moolenaar return NULL; 1222071d4279SBram Moolenaar 1223071d4279SBram Moolenaar max = n = end - start + 1; 1224071d4279SBram Moolenaar 1225e7cb9cf6SBram Moolenaar if (!PyArg_ParseTuple(args, "O|" Py_ssize_t_fmt, &lines, &n)) 1226071d4279SBram Moolenaar return NULL; 1227071d4279SBram Moolenaar 1228071d4279SBram Moolenaar if (n < 0 || n > max) 1229071d4279SBram Moolenaar { 1230071d4279SBram Moolenaar PyErr_SetString(PyExc_ValueError, _("line number out of range")); 1231071d4279SBram Moolenaar return NULL; 1232071d4279SBram Moolenaar } 1233071d4279SBram Moolenaar 1234071d4279SBram Moolenaar if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL) 1235071d4279SBram Moolenaar return NULL; 1236071d4279SBram Moolenaar 1237071d4279SBram Moolenaar if (new_end) 1238071d4279SBram Moolenaar *new_end = end + len_change; 1239071d4279SBram Moolenaar 1240071d4279SBram Moolenaar Py_INCREF(Py_None); 1241071d4279SBram Moolenaar return Py_None; 1242071d4279SBram Moolenaar } 1243071d4279SBram Moolenaar 1244071d4279SBram Moolenaar 1245071d4279SBram Moolenaar /* Buffer object - Definitions 1246071d4279SBram Moolenaar */ 1247071d4279SBram Moolenaar 1248071d4279SBram Moolenaar static struct PyMethodDef BufferMethods[] = { 1249071d4279SBram Moolenaar /* name, function, calling, documentation */ 1250e7cb9cf6SBram Moolenaar {"append", BufferAppend, 1, "Append data to Vim buffer" }, 1251e7cb9cf6SBram Moolenaar {"mark", BufferMark, 1, "Return (row,col) representing position of named mark" }, 1252e7cb9cf6SBram Moolenaar {"range", BufferRange, 1, "Return a range object which represents the part of the given buffer between line numbers s and e" }, 1253071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1254071d4279SBram Moolenaar }; 1255071d4279SBram Moolenaar 1256071d4279SBram Moolenaar static PySequenceMethods BufferAsSeq = { 12572c45e945SBram Moolenaar (PyInquiry) BufferLength, /* sq_length, len(x) */ 1258071d4279SBram Moolenaar (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ 12592c45e945SBram Moolenaar (PyIntArgFunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */ 12602c45e945SBram Moolenaar (PyIntArgFunc) BufferItem, /* sq_item, x[i] */ 12612c45e945SBram Moolenaar (PyIntIntArgFunc) BufferSlice, /* sq_slice, x[i:j] */ 12622c45e945SBram Moolenaar (PyIntObjArgProc) BufferAssItem, /* sq_ass_item, x[i]=v */ 12632c45e945SBram Moolenaar (PyIntIntObjArgProc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */ 1264071d4279SBram Moolenaar }; 1265071d4279SBram Moolenaar 1266071d4279SBram Moolenaar static PyTypeObject BufferType = { 1267071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1268071d4279SBram Moolenaar 0, 1269071d4279SBram Moolenaar "buffer", 1270071d4279SBram Moolenaar sizeof(BufferObject), 1271071d4279SBram Moolenaar 0, 1272071d4279SBram Moolenaar 1273071d4279SBram Moolenaar (destructor) BufferDestructor, /* tp_dealloc, refcount==0 */ 1274071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1275071d4279SBram Moolenaar (getattrfunc) BufferGetattr, /* tp_getattr, x.attr */ 1276071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1277071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1278071d4279SBram Moolenaar (reprfunc) BufferRepr, /* tp_repr, `x`, print x */ 1279071d4279SBram Moolenaar 1280071d4279SBram Moolenaar 0, /* as number */ 1281071d4279SBram Moolenaar &BufferAsSeq, /* as sequence */ 1282071d4279SBram Moolenaar 0, /* as mapping */ 1283071d4279SBram Moolenaar 1284071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1285071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1286071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1287071d4279SBram Moolenaar }; 1288071d4279SBram Moolenaar 1289071d4279SBram Moolenaar /* Buffer object - Implementation 1290071d4279SBram Moolenaar */ 1291071d4279SBram Moolenaar 1292071d4279SBram Moolenaar static PyObject * 1293071d4279SBram Moolenaar BufferNew(buf_T *buf) 1294071d4279SBram Moolenaar { 1295071d4279SBram Moolenaar /* We need to handle deletion of buffers underneath us. 1296e344beadSBram Moolenaar * If we add a "b_python_ref" field to the buf_T structure, 1297071d4279SBram Moolenaar * then we can get at it in buf_freeall() in vim. We then 1298071d4279SBram Moolenaar * need to create only ONE Python object per buffer - if 1299071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 1300071d4279SBram Moolenaar * and return it. The (single) Python object referring to 1301e344beadSBram Moolenaar * the buffer is stored in "b_python_ref". 1302071d4279SBram Moolenaar * Question: what to do on a buf_freeall(). We'll probably 1303071d4279SBram Moolenaar * have to either delete the Python object (DECREF it to 1304071d4279SBram Moolenaar * zero - a bad idea, as it leaves dangling refs!) or 1305071d4279SBram Moolenaar * set the buf_T * value to an invalid value (-1?), which 1306071d4279SBram Moolenaar * means we need checks in all access functions... Bah. 1307071d4279SBram Moolenaar */ 1308071d4279SBram Moolenaar 1309071d4279SBram Moolenaar BufferObject *self; 1310071d4279SBram Moolenaar 1311e344beadSBram Moolenaar if (buf->b_python_ref != NULL) 1312071d4279SBram Moolenaar { 1313e344beadSBram Moolenaar self = buf->b_python_ref; 1314071d4279SBram Moolenaar Py_INCREF(self); 1315071d4279SBram Moolenaar } 1316071d4279SBram Moolenaar else 1317071d4279SBram Moolenaar { 1318071d4279SBram Moolenaar self = PyObject_NEW(BufferObject, &BufferType); 1319071d4279SBram Moolenaar if (self == NULL) 1320071d4279SBram Moolenaar return NULL; 1321071d4279SBram Moolenaar self->buf = buf; 1322e344beadSBram Moolenaar buf->b_python_ref = self; 1323071d4279SBram Moolenaar } 1324071d4279SBram Moolenaar 1325071d4279SBram Moolenaar return (PyObject *)(self); 1326071d4279SBram Moolenaar } 1327071d4279SBram Moolenaar 1328071d4279SBram Moolenaar static void 1329071d4279SBram Moolenaar BufferDestructor(PyObject *self) 1330071d4279SBram Moolenaar { 1331071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1332071d4279SBram Moolenaar 1333071d4279SBram Moolenaar if (this->buf && this->buf != INVALID_BUFFER_VALUE) 1334e344beadSBram Moolenaar this->buf->b_python_ref = NULL; 1335071d4279SBram Moolenaar 1336658ada69SBram Moolenaar Py_DECREF(self); 1337071d4279SBram Moolenaar } 1338071d4279SBram Moolenaar 1339071d4279SBram Moolenaar static PyObject * 1340071d4279SBram Moolenaar BufferGetattr(PyObject *self, char *name) 1341071d4279SBram Moolenaar { 1342071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1343071d4279SBram Moolenaar 1344071d4279SBram Moolenaar if (CheckBuffer(this)) 1345071d4279SBram Moolenaar return NULL; 1346071d4279SBram Moolenaar 1347071d4279SBram Moolenaar if (strcmp(name, "name") == 0) 1348071d4279SBram Moolenaar return Py_BuildValue("s", this->buf->b_ffname); 1349071d4279SBram Moolenaar else if (strcmp(name, "number") == 0) 1350e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum); 1351071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1352071d4279SBram Moolenaar return Py_BuildValue("[ss]", "name", "number"); 1353071d4279SBram Moolenaar else 1354071d4279SBram Moolenaar return Py_FindMethod(BufferMethods, self, name); 1355071d4279SBram Moolenaar } 1356071d4279SBram Moolenaar 1357071d4279SBram Moolenaar static PyObject * 1358071d4279SBram Moolenaar BufferRepr(PyObject *self) 1359071d4279SBram Moolenaar { 1360555b280fSBram Moolenaar static char repr[100]; 1361071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1362071d4279SBram Moolenaar 1363071d4279SBram Moolenaar if (this->buf == INVALID_BUFFER_VALUE) 1364071d4279SBram Moolenaar { 1365e7cb9cf6SBram Moolenaar vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self)); 1366071d4279SBram Moolenaar return PyString_FromString(repr); 1367071d4279SBram Moolenaar } 1368071d4279SBram Moolenaar else 1369071d4279SBram Moolenaar { 1370071d4279SBram Moolenaar char *name = (char *)this->buf->b_fname; 1371e7cb9cf6SBram Moolenaar PyInt len; 1372071d4279SBram Moolenaar 1373071d4279SBram Moolenaar if (name == NULL) 1374071d4279SBram Moolenaar name = ""; 1375071d4279SBram Moolenaar len = strlen(name); 1376071d4279SBram Moolenaar 1377071d4279SBram Moolenaar if (len > 35) 1378071d4279SBram Moolenaar name = name + (35 - len); 1379071d4279SBram Moolenaar 1380555b280fSBram Moolenaar vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name); 1381071d4279SBram Moolenaar 1382071d4279SBram Moolenaar return PyString_FromString(repr); 1383071d4279SBram Moolenaar } 1384071d4279SBram Moolenaar } 1385071d4279SBram Moolenaar 1386071d4279SBram Moolenaar /******************/ 1387071d4279SBram Moolenaar 13882c45e945SBram Moolenaar static PyInt 1389071d4279SBram Moolenaar BufferLength(PyObject *self) 1390071d4279SBram Moolenaar { 1391071d4279SBram Moolenaar /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ 1392071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1393071d4279SBram Moolenaar return -1; /* ??? */ 1394071d4279SBram Moolenaar 1395071d4279SBram Moolenaar return (((BufferObject *)(self))->buf->b_ml.ml_line_count); 1396071d4279SBram Moolenaar } 1397071d4279SBram Moolenaar 1398071d4279SBram Moolenaar static PyObject * 13992c45e945SBram Moolenaar BufferItem(PyObject *self, PyInt n) 1400071d4279SBram Moolenaar { 1401071d4279SBram Moolenaar return RBItem((BufferObject *)(self), n, 1, 1402071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1403071d4279SBram Moolenaar } 1404071d4279SBram Moolenaar 1405071d4279SBram Moolenaar static PyObject * 14062c45e945SBram Moolenaar BufferSlice(PyObject *self, PyInt lo, PyInt hi) 1407071d4279SBram Moolenaar { 1408071d4279SBram Moolenaar return RBSlice((BufferObject *)(self), lo, hi, 1, 1409071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1410071d4279SBram Moolenaar } 1411071d4279SBram Moolenaar 14122c45e945SBram Moolenaar static PyInt 14132c45e945SBram Moolenaar BufferAssItem(PyObject *self, PyInt n, PyObject *val) 1414071d4279SBram Moolenaar { 1415071d4279SBram Moolenaar return RBAssItem((BufferObject *)(self), n, val, 1, 1416e7cb9cf6SBram Moolenaar (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1417071d4279SBram Moolenaar NULL); 1418071d4279SBram Moolenaar } 1419071d4279SBram Moolenaar 14202c45e945SBram Moolenaar static PyInt 14212c45e945SBram Moolenaar BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) 1422071d4279SBram Moolenaar { 1423071d4279SBram Moolenaar return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, 1424e7cb9cf6SBram Moolenaar (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1425071d4279SBram Moolenaar NULL); 1426071d4279SBram Moolenaar } 1427071d4279SBram Moolenaar 1428071d4279SBram Moolenaar static PyObject * 1429071d4279SBram Moolenaar BufferAppend(PyObject *self, PyObject *args) 1430071d4279SBram Moolenaar { 1431071d4279SBram Moolenaar return RBAppend((BufferObject *)(self), args, 1, 1432e7cb9cf6SBram Moolenaar (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1433071d4279SBram Moolenaar NULL); 1434071d4279SBram Moolenaar } 1435071d4279SBram Moolenaar 1436071d4279SBram Moolenaar static PyObject * 1437071d4279SBram Moolenaar BufferMark(PyObject *self, PyObject *args) 1438071d4279SBram Moolenaar { 1439071d4279SBram Moolenaar pos_T *posp; 1440071d4279SBram Moolenaar char mark; 1441071d4279SBram Moolenaar buf_T *curbuf_save; 1442071d4279SBram Moolenaar 1443071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1444071d4279SBram Moolenaar return NULL; 1445071d4279SBram Moolenaar 1446071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "c", &mark)) 1447071d4279SBram Moolenaar return NULL; 1448071d4279SBram Moolenaar 1449071d4279SBram Moolenaar curbuf_save = curbuf; 1450071d4279SBram Moolenaar curbuf = ((BufferObject *)(self))->buf; 1451071d4279SBram Moolenaar posp = getmark(mark, FALSE); 1452071d4279SBram Moolenaar curbuf = curbuf_save; 1453071d4279SBram Moolenaar 1454071d4279SBram Moolenaar if (posp == NULL) 1455071d4279SBram Moolenaar { 1456071d4279SBram Moolenaar PyErr_SetVim(_("invalid mark name")); 1457071d4279SBram Moolenaar return NULL; 1458071d4279SBram Moolenaar } 1459071d4279SBram Moolenaar 1460071d4279SBram Moolenaar /* Ckeck for keyboard interrupt */ 1461071d4279SBram Moolenaar if (VimErrorCheck()) 1462071d4279SBram Moolenaar return NULL; 1463071d4279SBram Moolenaar 1464071d4279SBram Moolenaar if (posp->lnum <= 0) 1465071d4279SBram Moolenaar { 1466071d4279SBram Moolenaar /* Or raise an error? */ 1467071d4279SBram Moolenaar Py_INCREF(Py_None); 1468071d4279SBram Moolenaar return Py_None; 1469071d4279SBram Moolenaar } 1470071d4279SBram Moolenaar 1471071d4279SBram Moolenaar return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col)); 1472071d4279SBram Moolenaar } 1473071d4279SBram Moolenaar 1474071d4279SBram Moolenaar static PyObject * 1475071d4279SBram Moolenaar BufferRange(PyObject *self, PyObject *args) 1476071d4279SBram Moolenaar { 1477e7cb9cf6SBram Moolenaar PyInt start; 1478e7cb9cf6SBram Moolenaar PyInt end; 1479071d4279SBram Moolenaar 1480071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1481071d4279SBram Moolenaar return NULL; 1482071d4279SBram Moolenaar 1483e7cb9cf6SBram Moolenaar if (!PyArg_ParseTuple(args, Py_ssize_t_fmt Py_ssize_t_fmt, &start, &end)) 1484071d4279SBram Moolenaar return NULL; 1485071d4279SBram Moolenaar 1486071d4279SBram Moolenaar return RangeNew(((BufferObject *)(self))->buf, start, end); 1487071d4279SBram Moolenaar } 1488071d4279SBram Moolenaar 1489071d4279SBram Moolenaar /* Line range object - Definitions 1490071d4279SBram Moolenaar */ 1491071d4279SBram Moolenaar 1492071d4279SBram Moolenaar static struct PyMethodDef RangeMethods[] = { 1493071d4279SBram Moolenaar /* name, function, calling, documentation */ 1494e7cb9cf6SBram Moolenaar {"append", RangeAppend, 1, "Append data to the Vim range" }, 1495071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1496071d4279SBram Moolenaar }; 1497071d4279SBram Moolenaar 1498071d4279SBram Moolenaar static PySequenceMethods RangeAsSeq = { 14992c45e945SBram Moolenaar (PyInquiry) RangeLength, /* sq_length, len(x) */ 1500071d4279SBram Moolenaar (binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */ 15012c45e945SBram Moolenaar (PyIntArgFunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */ 15022c45e945SBram Moolenaar (PyIntArgFunc) RangeItem, /* sq_item, x[i] */ 15032c45e945SBram Moolenaar (PyIntIntArgFunc) RangeSlice, /* sq_slice, x[i:j] */ 15042c45e945SBram Moolenaar (PyIntObjArgProc) RangeAssItem, /* sq_ass_item, x[i]=v */ 15052c45e945SBram Moolenaar (PyIntIntObjArgProc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */ 1506071d4279SBram Moolenaar }; 1507071d4279SBram Moolenaar 1508071d4279SBram Moolenaar static PyTypeObject RangeType = { 1509071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1510071d4279SBram Moolenaar 0, 1511071d4279SBram Moolenaar "range", 1512071d4279SBram Moolenaar sizeof(RangeObject), 1513071d4279SBram Moolenaar 0, 1514071d4279SBram Moolenaar 1515071d4279SBram Moolenaar (destructor) RangeDestructor, /* tp_dealloc, refcount==0 */ 1516071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1517071d4279SBram Moolenaar (getattrfunc) RangeGetattr, /* tp_getattr, x.attr */ 1518071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1519071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1520071d4279SBram Moolenaar (reprfunc) RangeRepr, /* tp_repr, `x`, print x */ 1521071d4279SBram Moolenaar 1522071d4279SBram Moolenaar 0, /* as number */ 1523071d4279SBram Moolenaar &RangeAsSeq, /* as sequence */ 1524071d4279SBram Moolenaar 0, /* as mapping */ 1525071d4279SBram Moolenaar 1526071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1527071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1528071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1529071d4279SBram Moolenaar }; 1530071d4279SBram Moolenaar 1531071d4279SBram Moolenaar /* Line range object - Implementation 1532071d4279SBram Moolenaar */ 1533071d4279SBram Moolenaar 1534071d4279SBram Moolenaar static PyObject * 1535e7cb9cf6SBram Moolenaar RangeNew(buf_T *buf, PyInt start, PyInt end) 1536071d4279SBram Moolenaar { 1537071d4279SBram Moolenaar BufferObject *bufr; 1538071d4279SBram Moolenaar RangeObject *self; 1539071d4279SBram Moolenaar self = PyObject_NEW(RangeObject, &RangeType); 1540071d4279SBram Moolenaar if (self == NULL) 1541071d4279SBram Moolenaar return NULL; 1542071d4279SBram Moolenaar 1543071d4279SBram Moolenaar bufr = (BufferObject *)BufferNew(buf); 1544071d4279SBram Moolenaar if (bufr == NULL) 1545071d4279SBram Moolenaar { 1546658ada69SBram Moolenaar Py_DECREF(self); 1547071d4279SBram Moolenaar return NULL; 1548071d4279SBram Moolenaar } 1549071d4279SBram Moolenaar Py_INCREF(bufr); 1550071d4279SBram Moolenaar 1551071d4279SBram Moolenaar self->buf = bufr; 1552071d4279SBram Moolenaar self->start = start; 1553071d4279SBram Moolenaar self->end = end; 1554071d4279SBram Moolenaar 1555071d4279SBram Moolenaar return (PyObject *)(self); 1556071d4279SBram Moolenaar } 1557071d4279SBram Moolenaar 1558071d4279SBram Moolenaar static void 1559071d4279SBram Moolenaar RangeDestructor(PyObject *self) 1560071d4279SBram Moolenaar { 1561071d4279SBram Moolenaar Py_DECREF(((RangeObject *)(self))->buf); 1562658ada69SBram Moolenaar Py_DECREF(self); 1563071d4279SBram Moolenaar } 1564071d4279SBram Moolenaar 1565071d4279SBram Moolenaar static PyObject * 1566071d4279SBram Moolenaar RangeGetattr(PyObject *self, char *name) 1567071d4279SBram Moolenaar { 1568071d4279SBram Moolenaar if (strcmp(name, "start") == 0) 1569e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start - 1); 1570071d4279SBram Moolenaar else if (strcmp(name, "end") == 0) 1571e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1); 1572071d4279SBram Moolenaar else 1573071d4279SBram Moolenaar return Py_FindMethod(RangeMethods, self, name); 1574071d4279SBram Moolenaar } 1575071d4279SBram Moolenaar 1576071d4279SBram Moolenaar static PyObject * 1577071d4279SBram Moolenaar RangeRepr(PyObject *self) 1578071d4279SBram Moolenaar { 1579555b280fSBram Moolenaar static char repr[100]; 1580071d4279SBram Moolenaar RangeObject *this = (RangeObject *)(self); 1581071d4279SBram Moolenaar 1582071d4279SBram Moolenaar if (this->buf->buf == INVALID_BUFFER_VALUE) 1583071d4279SBram Moolenaar { 1584e7cb9cf6SBram Moolenaar vim_snprintf(repr, 100, "<range object (for deleted buffer) at %p>", 1585e7cb9cf6SBram Moolenaar (self)); 1586071d4279SBram Moolenaar return PyString_FromString(repr); 1587071d4279SBram Moolenaar } 1588071d4279SBram Moolenaar else 1589071d4279SBram Moolenaar { 1590071d4279SBram Moolenaar char *name = (char *)this->buf->buf->b_fname; 1591071d4279SBram Moolenaar int len; 1592071d4279SBram Moolenaar 1593071d4279SBram Moolenaar if (name == NULL) 1594071d4279SBram Moolenaar name = ""; 1595c236c16dSBram Moolenaar len = (int)strlen(name); 1596071d4279SBram Moolenaar 1597071d4279SBram Moolenaar if (len > 45) 1598071d4279SBram Moolenaar name = name + (45 - len); 1599071d4279SBram Moolenaar 1600555b280fSBram Moolenaar vim_snprintf(repr, 100, "<range %s%s (%d:%d)>", 1601071d4279SBram Moolenaar len > 45 ? "..." : "", name, 1602071d4279SBram Moolenaar this->start, this->end); 1603071d4279SBram Moolenaar 1604071d4279SBram Moolenaar return PyString_FromString(repr); 1605071d4279SBram Moolenaar } 1606071d4279SBram Moolenaar } 1607071d4279SBram Moolenaar 1608071d4279SBram Moolenaar /****************/ 1609071d4279SBram Moolenaar 16102c45e945SBram Moolenaar static PyInt 1611071d4279SBram Moolenaar RangeLength(PyObject *self) 1612071d4279SBram Moolenaar { 1613071d4279SBram Moolenaar /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ 1614071d4279SBram Moolenaar if (CheckBuffer(((RangeObject *)(self))->buf)) 1615071d4279SBram Moolenaar return -1; /* ??? */ 1616071d4279SBram Moolenaar 1617071d4279SBram Moolenaar return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1); 1618071d4279SBram Moolenaar } 1619071d4279SBram Moolenaar 1620071d4279SBram Moolenaar static PyObject * 16212c45e945SBram Moolenaar RangeItem(PyObject *self, PyInt n) 1622071d4279SBram Moolenaar { 1623071d4279SBram Moolenaar return RBItem(((RangeObject *)(self))->buf, n, 1624071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1625071d4279SBram Moolenaar ((RangeObject *)(self))->end); 1626071d4279SBram Moolenaar } 1627071d4279SBram Moolenaar 1628071d4279SBram Moolenaar static PyObject * 16292c45e945SBram Moolenaar RangeSlice(PyObject *self, PyInt lo, PyInt hi) 1630071d4279SBram Moolenaar { 1631071d4279SBram Moolenaar return RBSlice(((RangeObject *)(self))->buf, lo, hi, 1632071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1633071d4279SBram Moolenaar ((RangeObject *)(self))->end); 1634071d4279SBram Moolenaar } 1635071d4279SBram Moolenaar 16362c45e945SBram Moolenaar static PyInt 16372c45e945SBram Moolenaar RangeAssItem(PyObject *self, PyInt n, PyObject *val) 1638071d4279SBram Moolenaar { 1639071d4279SBram Moolenaar return RBAssItem(((RangeObject *)(self))->buf, n, val, 1640071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1641071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1642071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1643071d4279SBram Moolenaar } 1644071d4279SBram Moolenaar 16452c45e945SBram Moolenaar static PyInt 16462c45e945SBram Moolenaar RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) 1647071d4279SBram Moolenaar { 1648071d4279SBram Moolenaar return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, 1649071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1650071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1651071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1652071d4279SBram Moolenaar } 1653071d4279SBram Moolenaar 1654071d4279SBram Moolenaar static PyObject * 1655071d4279SBram Moolenaar RangeAppend(PyObject *self, PyObject *args) 1656071d4279SBram Moolenaar { 1657071d4279SBram Moolenaar return RBAppend(((RangeObject *)(self))->buf, args, 1658071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1659071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1660071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1661071d4279SBram Moolenaar } 1662071d4279SBram Moolenaar 1663071d4279SBram Moolenaar /* Buffer list object - Definitions 1664071d4279SBram Moolenaar */ 1665071d4279SBram Moolenaar 1666071d4279SBram Moolenaar typedef struct 1667071d4279SBram Moolenaar { 1668071d4279SBram Moolenaar PyObject_HEAD 1669071d4279SBram Moolenaar } 1670071d4279SBram Moolenaar BufListObject; 1671071d4279SBram Moolenaar 1672071d4279SBram Moolenaar static PySequenceMethods BufListAsSeq = { 16732c45e945SBram Moolenaar (PyInquiry) BufListLength, /* sq_length, len(x) */ 1674071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 16752c45e945SBram Moolenaar (PyIntArgFunc) 0, /* sq_repeat, x*n */ 16762c45e945SBram Moolenaar (PyIntArgFunc) BufListItem, /* sq_item, x[i] */ 16772c45e945SBram Moolenaar (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ 16782c45e945SBram Moolenaar (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ 16792c45e945SBram Moolenaar (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ 1680071d4279SBram Moolenaar }; 1681071d4279SBram Moolenaar 1682071d4279SBram Moolenaar static PyTypeObject BufListType = { 1683071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1684071d4279SBram Moolenaar 0, 1685071d4279SBram Moolenaar "buffer list", 1686071d4279SBram Moolenaar sizeof(BufListObject), 1687071d4279SBram Moolenaar 0, 1688071d4279SBram Moolenaar 1689071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 1690071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1691071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 1692071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1693071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1694071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 1695071d4279SBram Moolenaar 1696071d4279SBram Moolenaar 0, /* as number */ 1697071d4279SBram Moolenaar &BufListAsSeq, /* as sequence */ 1698071d4279SBram Moolenaar 0, /* as mapping */ 1699071d4279SBram Moolenaar 1700071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1701071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1702071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1703071d4279SBram Moolenaar }; 1704071d4279SBram Moolenaar 1705071d4279SBram Moolenaar /* Buffer list object - Implementation 1706071d4279SBram Moolenaar */ 1707071d4279SBram Moolenaar 17082c45e945SBram Moolenaar static PyInt 17094bdbbf70SBram Moolenaar BufListLength(PyObject *self UNUSED) 1710071d4279SBram Moolenaar { 1711071d4279SBram Moolenaar buf_T *b = firstbuf; 1712e7cb9cf6SBram Moolenaar PyInt n = 0; 1713071d4279SBram Moolenaar 1714071d4279SBram Moolenaar while (b) 1715071d4279SBram Moolenaar { 1716071d4279SBram Moolenaar ++n; 1717071d4279SBram Moolenaar b = b->b_next; 1718071d4279SBram Moolenaar } 1719071d4279SBram Moolenaar 1720071d4279SBram Moolenaar return n; 1721071d4279SBram Moolenaar } 1722071d4279SBram Moolenaar 1723071d4279SBram Moolenaar static PyObject * 17244bdbbf70SBram Moolenaar BufListItem(PyObject *self UNUSED, PyInt n) 1725071d4279SBram Moolenaar { 1726071d4279SBram Moolenaar buf_T *b; 1727071d4279SBram Moolenaar 1728071d4279SBram Moolenaar for (b = firstbuf; b; b = b->b_next, --n) 1729071d4279SBram Moolenaar { 1730071d4279SBram Moolenaar if (n == 0) 1731071d4279SBram Moolenaar return BufferNew(b); 1732071d4279SBram Moolenaar } 1733071d4279SBram Moolenaar 1734071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("no such buffer")); 1735071d4279SBram Moolenaar return NULL; 1736071d4279SBram Moolenaar } 1737071d4279SBram Moolenaar 1738071d4279SBram Moolenaar /* Window object - Definitions 1739071d4279SBram Moolenaar */ 1740071d4279SBram Moolenaar 1741071d4279SBram Moolenaar static struct PyMethodDef WindowMethods[] = { 1742071d4279SBram Moolenaar /* name, function, calling, documentation */ 1743071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1744071d4279SBram Moolenaar }; 1745071d4279SBram Moolenaar 1746071d4279SBram Moolenaar static PyTypeObject WindowType = { 1747071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1748071d4279SBram Moolenaar 0, 1749071d4279SBram Moolenaar "window", 1750071d4279SBram Moolenaar sizeof(WindowObject), 1751071d4279SBram Moolenaar 0, 1752071d4279SBram Moolenaar 1753071d4279SBram Moolenaar (destructor) WindowDestructor, /* tp_dealloc, refcount==0 */ 1754071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1755071d4279SBram Moolenaar (getattrfunc) WindowGetattr, /* tp_getattr, x.attr */ 1756071d4279SBram Moolenaar (setattrfunc) WindowSetattr, /* tp_setattr, x.attr=v */ 1757071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1758071d4279SBram Moolenaar (reprfunc) WindowRepr, /* tp_repr, `x`, print x */ 1759071d4279SBram Moolenaar 1760071d4279SBram Moolenaar 0, /* as number */ 1761071d4279SBram Moolenaar 0, /* as sequence */ 1762071d4279SBram Moolenaar 0, /* as mapping */ 1763071d4279SBram Moolenaar 1764071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1765071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1766071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1767071d4279SBram Moolenaar }; 1768071d4279SBram Moolenaar 1769071d4279SBram Moolenaar /* Window object - Implementation 1770071d4279SBram Moolenaar */ 1771071d4279SBram Moolenaar 1772071d4279SBram Moolenaar static PyObject * 1773071d4279SBram Moolenaar WindowNew(win_T *win) 1774071d4279SBram Moolenaar { 1775071d4279SBram Moolenaar /* We need to handle deletion of windows underneath us. 1776e344beadSBram Moolenaar * If we add a "w_python_ref" field to the win_T structure, 1777071d4279SBram Moolenaar * then we can get at it in win_free() in vim. We then 1778071d4279SBram Moolenaar * need to create only ONE Python object per window - if 1779071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 1780071d4279SBram Moolenaar * and return it. The (single) Python object referring to 1781e344beadSBram Moolenaar * the window is stored in "w_python_ref". 1782071d4279SBram Moolenaar * On a win_free() we set the Python object's win_T* field 1783071d4279SBram Moolenaar * to an invalid value. We trap all uses of a window 1784071d4279SBram Moolenaar * object, and reject them if the win_T* field is invalid. 1785071d4279SBram Moolenaar */ 1786071d4279SBram Moolenaar 1787071d4279SBram Moolenaar WindowObject *self; 1788071d4279SBram Moolenaar 1789e344beadSBram Moolenaar if (win->w_python_ref) 1790071d4279SBram Moolenaar { 1791e344beadSBram Moolenaar self = win->w_python_ref; 1792071d4279SBram Moolenaar Py_INCREF(self); 1793071d4279SBram Moolenaar } 1794071d4279SBram Moolenaar else 1795071d4279SBram Moolenaar { 1796071d4279SBram Moolenaar self = PyObject_NEW(WindowObject, &WindowType); 1797071d4279SBram Moolenaar if (self == NULL) 1798071d4279SBram Moolenaar return NULL; 1799071d4279SBram Moolenaar self->win = win; 1800e344beadSBram Moolenaar win->w_python_ref = self; 1801071d4279SBram Moolenaar } 1802071d4279SBram Moolenaar 1803071d4279SBram Moolenaar return (PyObject *)(self); 1804071d4279SBram Moolenaar } 1805071d4279SBram Moolenaar 1806071d4279SBram Moolenaar static void 1807071d4279SBram Moolenaar WindowDestructor(PyObject *self) 1808071d4279SBram Moolenaar { 1809071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1810071d4279SBram Moolenaar 1811071d4279SBram Moolenaar if (this->win && this->win != INVALID_WINDOW_VALUE) 1812e344beadSBram Moolenaar this->win->w_python_ref = NULL; 1813071d4279SBram Moolenaar 1814658ada69SBram Moolenaar Py_DECREF(self); 1815071d4279SBram Moolenaar } 1816071d4279SBram Moolenaar 1817071d4279SBram Moolenaar static int 1818071d4279SBram Moolenaar CheckWindow(WindowObject *this) 1819071d4279SBram Moolenaar { 1820071d4279SBram Moolenaar if (this->win == INVALID_WINDOW_VALUE) 1821071d4279SBram Moolenaar { 1822071d4279SBram Moolenaar PyErr_SetVim(_("attempt to refer to deleted window")); 1823071d4279SBram Moolenaar return -1; 1824071d4279SBram Moolenaar } 1825071d4279SBram Moolenaar 1826071d4279SBram Moolenaar return 0; 1827071d4279SBram Moolenaar } 1828071d4279SBram Moolenaar 1829071d4279SBram Moolenaar static PyObject * 1830071d4279SBram Moolenaar WindowGetattr(PyObject *self, char *name) 1831071d4279SBram Moolenaar { 1832071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1833071d4279SBram Moolenaar 1834071d4279SBram Moolenaar if (CheckWindow(this)) 1835071d4279SBram Moolenaar return NULL; 1836071d4279SBram Moolenaar 1837071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1838071d4279SBram Moolenaar return (PyObject *)BufferNew(this->win->w_buffer); 1839071d4279SBram Moolenaar else if (strcmp(name, "cursor") == 0) 1840071d4279SBram Moolenaar { 1841071d4279SBram Moolenaar pos_T *pos = &this->win->w_cursor; 1842071d4279SBram Moolenaar 1843071d4279SBram Moolenaar return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col)); 1844071d4279SBram Moolenaar } 1845071d4279SBram Moolenaar else if (strcmp(name, "height") == 0) 1846071d4279SBram Moolenaar return Py_BuildValue("l", (long)(this->win->w_height)); 1847071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT 1848071d4279SBram Moolenaar else if (strcmp(name, "width") == 0) 1849071d4279SBram Moolenaar return Py_BuildValue("l", (long)(W_WIDTH(this->win))); 1850071d4279SBram Moolenaar #endif 1851071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1852071d4279SBram Moolenaar return Py_BuildValue("[sss]", "buffer", "cursor", "height"); 1853071d4279SBram Moolenaar else 1854071d4279SBram Moolenaar return Py_FindMethod(WindowMethods, self, name); 1855071d4279SBram Moolenaar } 1856071d4279SBram Moolenaar 1857071d4279SBram Moolenaar static int 1858071d4279SBram Moolenaar WindowSetattr(PyObject *self, char *name, PyObject *val) 1859071d4279SBram Moolenaar { 1860071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1861071d4279SBram Moolenaar 1862071d4279SBram Moolenaar if (CheckWindow(this)) 1863071d4279SBram Moolenaar return -1; 1864071d4279SBram Moolenaar 1865071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1866071d4279SBram Moolenaar { 1867071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("readonly attribute")); 1868071d4279SBram Moolenaar return -1; 1869071d4279SBram Moolenaar } 1870071d4279SBram Moolenaar else if (strcmp(name, "cursor") == 0) 1871071d4279SBram Moolenaar { 1872071d4279SBram Moolenaar long lnum; 1873071d4279SBram Moolenaar long col; 1874badfde1bSBram Moolenaar long len; 1875071d4279SBram Moolenaar 1876071d4279SBram Moolenaar if (!PyArg_Parse(val, "(ll)", &lnum, &col)) 1877071d4279SBram Moolenaar return -1; 1878071d4279SBram Moolenaar 1879071d4279SBram Moolenaar if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count) 1880071d4279SBram Moolenaar { 1881071d4279SBram Moolenaar PyErr_SetVim(_("cursor position outside buffer")); 1882071d4279SBram Moolenaar return -1; 1883071d4279SBram Moolenaar } 1884071d4279SBram Moolenaar 1885071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1886071d4279SBram Moolenaar if (VimErrorCheck()) 1887071d4279SBram Moolenaar return -1; 1888071d4279SBram Moolenaar 1889badfde1bSBram Moolenaar /* When column is out of range silently correct it. */ 18908b9c05faSBram Moolenaar len = (long)STRLEN(ml_get_buf(this->win->w_buffer, lnum, FALSE)); 1891badfde1bSBram Moolenaar if (col > len) 1892badfde1bSBram Moolenaar col = len; 1893071d4279SBram Moolenaar 1894071d4279SBram Moolenaar this->win->w_cursor.lnum = lnum; 1895071d4279SBram Moolenaar this->win->w_cursor.col = col; 1896badfde1bSBram Moolenaar #ifdef FEAT_VIRTUALEDIT 1897badfde1bSBram Moolenaar this->win->w_cursor.coladd = 0; 1898badfde1bSBram Moolenaar #endif 1899071d4279SBram Moolenaar update_screen(VALID); 1900071d4279SBram Moolenaar 1901071d4279SBram Moolenaar return 0; 1902071d4279SBram Moolenaar } 1903071d4279SBram Moolenaar else if (strcmp(name, "height") == 0) 1904071d4279SBram Moolenaar { 1905071d4279SBram Moolenaar int height; 1906071d4279SBram Moolenaar win_T *savewin; 1907071d4279SBram Moolenaar 1908071d4279SBram Moolenaar if (!PyArg_Parse(val, "i", &height)) 1909071d4279SBram Moolenaar return -1; 1910071d4279SBram Moolenaar 1911071d4279SBram Moolenaar #ifdef FEAT_GUI 1912071d4279SBram Moolenaar need_mouse_correct = TRUE; 1913071d4279SBram Moolenaar #endif 1914071d4279SBram Moolenaar savewin = curwin; 1915071d4279SBram Moolenaar curwin = this->win; 1916071d4279SBram Moolenaar win_setheight(height); 1917071d4279SBram Moolenaar curwin = savewin; 1918071d4279SBram Moolenaar 1919071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1920071d4279SBram Moolenaar if (VimErrorCheck()) 1921071d4279SBram Moolenaar return -1; 1922071d4279SBram Moolenaar 1923071d4279SBram Moolenaar return 0; 1924071d4279SBram Moolenaar } 1925071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT 1926071d4279SBram Moolenaar else if (strcmp(name, "width") == 0) 1927071d4279SBram Moolenaar { 1928071d4279SBram Moolenaar int width; 1929071d4279SBram Moolenaar win_T *savewin; 1930071d4279SBram Moolenaar 1931071d4279SBram Moolenaar if (!PyArg_Parse(val, "i", &width)) 1932071d4279SBram Moolenaar return -1; 1933071d4279SBram Moolenaar 1934071d4279SBram Moolenaar #ifdef FEAT_GUI 1935071d4279SBram Moolenaar need_mouse_correct = TRUE; 1936071d4279SBram Moolenaar #endif 1937071d4279SBram Moolenaar savewin = curwin; 1938071d4279SBram Moolenaar curwin = this->win; 1939071d4279SBram Moolenaar win_setwidth(width); 1940071d4279SBram Moolenaar curwin = savewin; 1941071d4279SBram Moolenaar 1942071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1943071d4279SBram Moolenaar if (VimErrorCheck()) 1944071d4279SBram Moolenaar return -1; 1945071d4279SBram Moolenaar 1946071d4279SBram Moolenaar return 0; 1947071d4279SBram Moolenaar } 1948071d4279SBram Moolenaar #endif 1949071d4279SBram Moolenaar else 1950071d4279SBram Moolenaar { 1951071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 1952071d4279SBram Moolenaar return -1; 1953071d4279SBram Moolenaar } 1954071d4279SBram Moolenaar } 1955071d4279SBram Moolenaar 1956071d4279SBram Moolenaar static PyObject * 1957071d4279SBram Moolenaar WindowRepr(PyObject *self) 1958071d4279SBram Moolenaar { 1959555b280fSBram Moolenaar static char repr[100]; 1960071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1961071d4279SBram Moolenaar 1962071d4279SBram Moolenaar if (this->win == INVALID_WINDOW_VALUE) 1963071d4279SBram Moolenaar { 1964e7cb9cf6SBram Moolenaar vim_snprintf(repr, 100, _("<window object (deleted) at %p>"), (self)); 1965071d4279SBram Moolenaar return PyString_FromString(repr); 1966071d4279SBram Moolenaar } 1967071d4279SBram Moolenaar else 1968071d4279SBram Moolenaar { 1969071d4279SBram Moolenaar int i = 0; 1970071d4279SBram Moolenaar win_T *w; 1971071d4279SBram Moolenaar 1972071d4279SBram Moolenaar for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w)) 1973071d4279SBram Moolenaar ++i; 1974071d4279SBram Moolenaar 1975071d4279SBram Moolenaar if (w == NULL) 1976e7cb9cf6SBram Moolenaar vim_snprintf(repr, 100, _("<window object (unknown) at %p>"), 1977e7cb9cf6SBram Moolenaar (self)); 1978071d4279SBram Moolenaar else 1979555b280fSBram Moolenaar vim_snprintf(repr, 100, _("<window %d>"), i); 1980071d4279SBram Moolenaar 1981071d4279SBram Moolenaar return PyString_FromString(repr); 1982071d4279SBram Moolenaar } 1983071d4279SBram Moolenaar } 1984071d4279SBram Moolenaar 1985071d4279SBram Moolenaar /* Window list object - Definitions 1986071d4279SBram Moolenaar */ 1987071d4279SBram Moolenaar 1988071d4279SBram Moolenaar typedef struct 1989071d4279SBram Moolenaar { 1990071d4279SBram Moolenaar PyObject_HEAD 1991071d4279SBram Moolenaar } 1992071d4279SBram Moolenaar WinListObject; 1993071d4279SBram Moolenaar 1994071d4279SBram Moolenaar static PySequenceMethods WinListAsSeq = { 19952c45e945SBram Moolenaar (PyInquiry) WinListLength, /* sq_length, len(x) */ 1996071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 19972c45e945SBram Moolenaar (PyIntArgFunc) 0, /* sq_repeat, x*n */ 19982c45e945SBram Moolenaar (PyIntArgFunc) WinListItem, /* sq_item, x[i] */ 19992c45e945SBram Moolenaar (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ 20002c45e945SBram Moolenaar (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ 20012c45e945SBram Moolenaar (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ 2002071d4279SBram Moolenaar }; 2003071d4279SBram Moolenaar 2004071d4279SBram Moolenaar static PyTypeObject WinListType = { 2005071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 2006071d4279SBram Moolenaar 0, 2007071d4279SBram Moolenaar "window list", 2008071d4279SBram Moolenaar sizeof(WinListObject), 2009071d4279SBram Moolenaar 0, 2010071d4279SBram Moolenaar 2011071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 2012071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 2013071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 2014071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 2015071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 2016071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 2017071d4279SBram Moolenaar 2018071d4279SBram Moolenaar 0, /* as number */ 2019071d4279SBram Moolenaar &WinListAsSeq, /* as sequence */ 2020071d4279SBram Moolenaar 0, /* as mapping */ 2021071d4279SBram Moolenaar 2022071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 2023071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 2024071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 2025071d4279SBram Moolenaar }; 2026071d4279SBram Moolenaar 2027071d4279SBram Moolenaar /* Window list object - Implementation 2028071d4279SBram Moolenaar */ 20292c45e945SBram Moolenaar static PyInt 20304bdbbf70SBram Moolenaar WinListLength(PyObject *self UNUSED) 2031071d4279SBram Moolenaar { 2032071d4279SBram Moolenaar win_T *w = firstwin; 2033e7cb9cf6SBram Moolenaar PyInt n = 0; 2034071d4279SBram Moolenaar 2035f740b29aSBram Moolenaar while (w != NULL) 2036071d4279SBram Moolenaar { 2037071d4279SBram Moolenaar ++n; 2038071d4279SBram Moolenaar w = W_NEXT(w); 2039071d4279SBram Moolenaar } 2040071d4279SBram Moolenaar 2041071d4279SBram Moolenaar return n; 2042071d4279SBram Moolenaar } 2043071d4279SBram Moolenaar 2044071d4279SBram Moolenaar static PyObject * 20454bdbbf70SBram Moolenaar WinListItem(PyObject *self UNUSED, PyInt n) 2046071d4279SBram Moolenaar { 2047071d4279SBram Moolenaar win_T *w; 2048071d4279SBram Moolenaar 2049f740b29aSBram Moolenaar for (w = firstwin; w != NULL; w = W_NEXT(w), --n) 2050071d4279SBram Moolenaar if (n == 0) 2051071d4279SBram Moolenaar return WindowNew(w); 2052071d4279SBram Moolenaar 2053071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("no such window")); 2054071d4279SBram Moolenaar return NULL; 2055071d4279SBram Moolenaar } 2056071d4279SBram Moolenaar 2057071d4279SBram Moolenaar /* Current items object - Definitions 2058071d4279SBram Moolenaar */ 2059071d4279SBram Moolenaar 2060071d4279SBram Moolenaar typedef struct 2061071d4279SBram Moolenaar { 2062071d4279SBram Moolenaar PyObject_HEAD 2063071d4279SBram Moolenaar } 2064071d4279SBram Moolenaar CurrentObject; 2065071d4279SBram Moolenaar 2066071d4279SBram Moolenaar static PyTypeObject CurrentType = { 2067071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 2068071d4279SBram Moolenaar 0, 2069071d4279SBram Moolenaar "current data", 2070071d4279SBram Moolenaar sizeof(CurrentObject), 2071071d4279SBram Moolenaar 0, 2072071d4279SBram Moolenaar 2073071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 2074071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 2075071d4279SBram Moolenaar (getattrfunc) CurrentGetattr, /* tp_getattr, x.attr */ 2076071d4279SBram Moolenaar (setattrfunc) CurrentSetattr, /* tp_setattr, x.attr=v */ 2077071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 2078071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 2079071d4279SBram Moolenaar 2080071d4279SBram Moolenaar 0, /* as number */ 2081071d4279SBram Moolenaar 0, /* as sequence */ 2082071d4279SBram Moolenaar 0, /* as mapping */ 2083071d4279SBram Moolenaar 2084071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 2085071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 2086071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 2087071d4279SBram Moolenaar }; 2088071d4279SBram Moolenaar 2089071d4279SBram Moolenaar /* Current items object - Implementation 2090071d4279SBram Moolenaar */ 2091071d4279SBram Moolenaar static PyObject * 20924bdbbf70SBram Moolenaar CurrentGetattr(PyObject *self UNUSED, char *name) 2093071d4279SBram Moolenaar { 2094071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 2095071d4279SBram Moolenaar return (PyObject *)BufferNew(curbuf); 2096071d4279SBram Moolenaar else if (strcmp(name, "window") == 0) 2097071d4279SBram Moolenaar return (PyObject *)WindowNew(curwin); 2098071d4279SBram Moolenaar else if (strcmp(name, "line") == 0) 2099e7cb9cf6SBram Moolenaar return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum); 2100071d4279SBram Moolenaar else if (strcmp(name, "range") == 0) 2101071d4279SBram Moolenaar return RangeNew(curbuf, RangeStart, RangeEnd); 2102071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 2103071d4279SBram Moolenaar return Py_BuildValue("[ssss]", "buffer", "window", "line", "range"); 2104071d4279SBram Moolenaar else 2105071d4279SBram Moolenaar { 2106071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 2107071d4279SBram Moolenaar return NULL; 2108071d4279SBram Moolenaar } 2109071d4279SBram Moolenaar } 2110071d4279SBram Moolenaar 2111071d4279SBram Moolenaar static int 21124bdbbf70SBram Moolenaar CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value) 2113071d4279SBram Moolenaar { 2114071d4279SBram Moolenaar if (strcmp(name, "line") == 0) 2115071d4279SBram Moolenaar { 2116e7cb9cf6SBram Moolenaar if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL) 2117071d4279SBram Moolenaar return -1; 2118071d4279SBram Moolenaar 2119071d4279SBram Moolenaar return 0; 2120071d4279SBram Moolenaar } 2121071d4279SBram Moolenaar else 2122071d4279SBram Moolenaar { 2123071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 2124071d4279SBram Moolenaar return -1; 2125071d4279SBram Moolenaar } 2126071d4279SBram Moolenaar } 2127071d4279SBram Moolenaar 2128071d4279SBram Moolenaar /* External interface 2129071d4279SBram Moolenaar */ 2130071d4279SBram Moolenaar 2131071d4279SBram Moolenaar void 2132071d4279SBram Moolenaar python_buffer_free(buf_T *buf) 2133071d4279SBram Moolenaar { 2134e344beadSBram Moolenaar if (buf->b_python_ref != NULL) 2135071d4279SBram Moolenaar { 2136e344beadSBram Moolenaar BufferObject *bp = buf->b_python_ref; 2137071d4279SBram Moolenaar bp->buf = INVALID_BUFFER_VALUE; 2138e344beadSBram Moolenaar buf->b_python_ref = NULL; 2139071d4279SBram Moolenaar } 2140071d4279SBram Moolenaar } 2141071d4279SBram Moolenaar 2142071d4279SBram Moolenaar #if defined(FEAT_WINDOWS) || defined(PROTO) 2143071d4279SBram Moolenaar void 2144071d4279SBram Moolenaar python_window_free(win_T *win) 2145071d4279SBram Moolenaar { 2146e344beadSBram Moolenaar if (win->w_python_ref != NULL) 2147071d4279SBram Moolenaar { 2148e344beadSBram Moolenaar WindowObject *wp = win->w_python_ref; 2149071d4279SBram Moolenaar wp->win = INVALID_WINDOW_VALUE; 2150e344beadSBram Moolenaar win->w_python_ref = NULL; 2151071d4279SBram Moolenaar } 2152071d4279SBram Moolenaar } 2153071d4279SBram Moolenaar #endif 2154071d4279SBram Moolenaar 2155071d4279SBram Moolenaar static BufListObject TheBufferList = 2156071d4279SBram Moolenaar { 2157071d4279SBram Moolenaar PyObject_HEAD_INIT(&BufListType) 2158071d4279SBram Moolenaar }; 2159071d4279SBram Moolenaar 2160071d4279SBram Moolenaar static WinListObject TheWindowList = 2161071d4279SBram Moolenaar { 2162071d4279SBram Moolenaar PyObject_HEAD_INIT(&WinListType) 2163071d4279SBram Moolenaar }; 2164071d4279SBram Moolenaar 2165071d4279SBram Moolenaar static CurrentObject TheCurrent = 2166071d4279SBram Moolenaar { 2167071d4279SBram Moolenaar PyObject_HEAD_INIT(&CurrentType) 2168071d4279SBram Moolenaar }; 2169071d4279SBram Moolenaar 2170071d4279SBram Moolenaar static int 2171071d4279SBram Moolenaar PythonMod_Init(void) 2172071d4279SBram Moolenaar { 2173071d4279SBram Moolenaar PyObject *mod; 2174071d4279SBram Moolenaar PyObject *dict; 21759774ecc8SBram Moolenaar /* The special value is removed from sys.path in Python_Init(). */ 21769774ecc8SBram Moolenaar static char *(argv[2]) = {"/must>not&exist/foo", NULL}; 2177071d4279SBram Moolenaar 2178071d4279SBram Moolenaar /* Fixups... */ 2179071d4279SBram Moolenaar BufferType.ob_type = &PyType_Type; 2180071d4279SBram Moolenaar RangeType.ob_type = &PyType_Type; 2181071d4279SBram Moolenaar WindowType.ob_type = &PyType_Type; 2182071d4279SBram Moolenaar BufListType.ob_type = &PyType_Type; 2183071d4279SBram Moolenaar WinListType.ob_type = &PyType_Type; 2184071d4279SBram Moolenaar CurrentType.ob_type = &PyType_Type; 2185071d4279SBram Moolenaar 2186071d4279SBram Moolenaar /* Set sys.argv[] to avoid a crash in warn(). */ 2187071d4279SBram Moolenaar PySys_SetArgv(1, argv); 2188071d4279SBram Moolenaar 2189e7cb9cf6SBram Moolenaar mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION); 2190071d4279SBram Moolenaar dict = PyModule_GetDict(mod); 2191071d4279SBram Moolenaar 2192071d4279SBram Moolenaar VimError = Py_BuildValue("s", "vim.error"); 2193071d4279SBram Moolenaar 2194071d4279SBram Moolenaar PyDict_SetItemString(dict, "error", VimError); 21957df2d662SBram Moolenaar PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferList); 21967df2d662SBram Moolenaar PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent); 21977df2d662SBram Moolenaar PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList); 2198071d4279SBram Moolenaar 2199071d4279SBram Moolenaar if (PyErr_Occurred()) 2200071d4279SBram Moolenaar return -1; 2201071d4279SBram Moolenaar 2202071d4279SBram Moolenaar return 0; 2203071d4279SBram Moolenaar } 2204071d4279SBram Moolenaar 2205071d4279SBram Moolenaar /************************************************************************* 2206071d4279SBram Moolenaar * 4. Utility functions for handling the interface between Vim and Python. 2207071d4279SBram Moolenaar */ 2208071d4279SBram Moolenaar 2209071d4279SBram Moolenaar /* Get a line from the specified buffer. The line number is 2210071d4279SBram Moolenaar * in Vim format (1-based). The line is returned as a Python 2211071d4279SBram Moolenaar * string object. 2212071d4279SBram Moolenaar */ 2213071d4279SBram Moolenaar static PyObject * 2214e7cb9cf6SBram Moolenaar GetBufferLine(buf_T *buf, PyInt n) 2215071d4279SBram Moolenaar { 2216071d4279SBram Moolenaar return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE)); 2217071d4279SBram Moolenaar } 2218071d4279SBram Moolenaar 2219071d4279SBram Moolenaar /* Get a list of lines from the specified buffer. The line numbers 2220071d4279SBram Moolenaar * are in Vim format (1-based). The range is from lo up to, but not 2221071d4279SBram Moolenaar * including, hi. The list is returned as a Python list of string objects. 2222071d4279SBram Moolenaar */ 2223071d4279SBram Moolenaar static PyObject * 22242c45e945SBram Moolenaar GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi) 2225071d4279SBram Moolenaar { 22262c45e945SBram Moolenaar PyInt i; 22272c45e945SBram Moolenaar PyInt n = hi - lo; 2228071d4279SBram Moolenaar PyObject *list = PyList_New(n); 2229071d4279SBram Moolenaar 2230071d4279SBram Moolenaar if (list == NULL) 2231071d4279SBram Moolenaar return NULL; 2232071d4279SBram Moolenaar 2233071d4279SBram Moolenaar for (i = 0; i < n; ++i) 2234071d4279SBram Moolenaar { 2235071d4279SBram Moolenaar PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE)); 2236071d4279SBram Moolenaar 2237071d4279SBram Moolenaar /* Error check - was the Python string creation OK? */ 2238071d4279SBram Moolenaar if (str == NULL) 2239071d4279SBram Moolenaar { 2240071d4279SBram Moolenaar Py_DECREF(list); 2241071d4279SBram Moolenaar return NULL; 2242071d4279SBram Moolenaar } 2243071d4279SBram Moolenaar 2244071d4279SBram Moolenaar /* Set the list item */ 2245071d4279SBram Moolenaar if (PyList_SetItem(list, i, str)) 2246071d4279SBram Moolenaar { 2247071d4279SBram Moolenaar Py_DECREF(str); 2248071d4279SBram Moolenaar Py_DECREF(list); 2249071d4279SBram Moolenaar return NULL; 2250071d4279SBram Moolenaar } 2251071d4279SBram Moolenaar } 2252071d4279SBram Moolenaar 2253071d4279SBram Moolenaar /* The ownership of the Python list is passed to the caller (ie, 2254071d4279SBram Moolenaar * the caller should Py_DECREF() the object when it is finished 2255071d4279SBram Moolenaar * with it). 2256071d4279SBram Moolenaar */ 2257071d4279SBram Moolenaar 2258071d4279SBram Moolenaar return list; 2259071d4279SBram Moolenaar } 2260071d4279SBram Moolenaar 2261071d4279SBram Moolenaar /* 2262071d4279SBram Moolenaar * Check if deleting lines made the cursor position invalid. 2263071d4279SBram Moolenaar * Changed the lines from "lo" to "hi" and added "extra" lines (negative if 2264071d4279SBram Moolenaar * deleted). 2265071d4279SBram Moolenaar */ 2266071d4279SBram Moolenaar static void 2267e7cb9cf6SBram Moolenaar py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) 2268071d4279SBram Moolenaar { 2269071d4279SBram Moolenaar if (curwin->w_cursor.lnum >= lo) 2270071d4279SBram Moolenaar { 2271071d4279SBram Moolenaar /* Adjust the cursor position if it's in/after the changed 2272071d4279SBram Moolenaar * lines. */ 2273071d4279SBram Moolenaar if (curwin->w_cursor.lnum >= hi) 2274071d4279SBram Moolenaar { 2275071d4279SBram Moolenaar curwin->w_cursor.lnum += extra; 2276071d4279SBram Moolenaar check_cursor_col(); 2277071d4279SBram Moolenaar } 2278071d4279SBram Moolenaar else if (extra < 0) 2279071d4279SBram Moolenaar { 2280071d4279SBram Moolenaar curwin->w_cursor.lnum = lo; 2281071d4279SBram Moolenaar check_cursor(); 2282071d4279SBram Moolenaar } 2283454ec05aSBram Moolenaar else 2284454ec05aSBram Moolenaar check_cursor_col(); 2285071d4279SBram Moolenaar changed_cline_bef_curs(); 2286071d4279SBram Moolenaar } 2287071d4279SBram Moolenaar invalidate_botline(); 2288071d4279SBram Moolenaar } 2289071d4279SBram Moolenaar 2290071d4279SBram Moolenaar /* Replace a line in the specified buffer. The line number is 2291071d4279SBram Moolenaar * in Vim format (1-based). The replacement line is given as 2292071d4279SBram Moolenaar * a Python string object. The object is checked for validity 2293071d4279SBram Moolenaar * and correct format. Errors are returned as a value of FAIL. 2294071d4279SBram Moolenaar * The return value is OK on success. 2295071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2296071d4279SBram Moolenaar * is set to the change in the buffer length. 2297071d4279SBram Moolenaar */ 2298071d4279SBram Moolenaar static int 2299e7cb9cf6SBram Moolenaar SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change) 2300071d4279SBram Moolenaar { 2301071d4279SBram Moolenaar /* First of all, we check the thpe of the supplied Python object. 2302071d4279SBram Moolenaar * There are three cases: 2303071d4279SBram Moolenaar * 1. NULL, or None - this is a deletion. 2304071d4279SBram Moolenaar * 2. A string - this is a replacement. 2305071d4279SBram Moolenaar * 3. Anything else - this is an error. 2306071d4279SBram Moolenaar */ 2307071d4279SBram Moolenaar if (line == Py_None || line == NULL) 2308071d4279SBram Moolenaar { 2309071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2310071d4279SBram Moolenaar 2311071d4279SBram Moolenaar PyErr_Clear(); 2312071d4279SBram Moolenaar curbuf = buf; 2313071d4279SBram Moolenaar 2314071d4279SBram Moolenaar if (u_savedel((linenr_T)n, 1L) == FAIL) 2315071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2316071d4279SBram Moolenaar else if (ml_delete((linenr_T)n, FALSE) == FAIL) 2317071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2318071d4279SBram Moolenaar else 2319071d4279SBram Moolenaar { 2320071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2321e7cb9cf6SBram Moolenaar py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1); 2322cdcaa589SBram Moolenaar deleted_lines_mark((linenr_T)n, 1L); 2323071d4279SBram Moolenaar } 2324071d4279SBram Moolenaar 2325071d4279SBram Moolenaar curbuf = savebuf; 2326071d4279SBram Moolenaar 2327071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2328071d4279SBram Moolenaar return FAIL; 2329071d4279SBram Moolenaar 2330071d4279SBram Moolenaar if (len_change) 2331071d4279SBram Moolenaar *len_change = -1; 2332071d4279SBram Moolenaar 2333071d4279SBram Moolenaar return OK; 2334071d4279SBram Moolenaar } 2335071d4279SBram Moolenaar else if (PyString_Check(line)) 2336071d4279SBram Moolenaar { 2337071d4279SBram Moolenaar char *save = StringToLine(line); 2338071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2339071d4279SBram Moolenaar 2340071d4279SBram Moolenaar if (save == NULL) 2341071d4279SBram Moolenaar return FAIL; 2342071d4279SBram Moolenaar 2343071d4279SBram Moolenaar /* We do not need to free "save" if ml_replace() consumes it. */ 2344071d4279SBram Moolenaar PyErr_Clear(); 2345071d4279SBram Moolenaar curbuf = buf; 2346071d4279SBram Moolenaar 2347071d4279SBram Moolenaar if (u_savesub((linenr_T)n) == FAIL) 2348071d4279SBram Moolenaar { 2349071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2350071d4279SBram Moolenaar vim_free(save); 2351071d4279SBram Moolenaar } 2352071d4279SBram Moolenaar else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL) 2353071d4279SBram Moolenaar { 2354071d4279SBram Moolenaar PyErr_SetVim(_("cannot replace line")); 2355071d4279SBram Moolenaar vim_free(save); 2356071d4279SBram Moolenaar } 2357071d4279SBram Moolenaar else 2358071d4279SBram Moolenaar changed_bytes((linenr_T)n, 0); 2359071d4279SBram Moolenaar 2360071d4279SBram Moolenaar curbuf = savebuf; 2361071d4279SBram Moolenaar 2362454ec05aSBram Moolenaar /* Check that the cursor is not beyond the end of the line now. */ 2363454ec05aSBram Moolenaar if (buf == curwin->w_buffer) 2364454ec05aSBram Moolenaar check_cursor_col(); 2365454ec05aSBram Moolenaar 2366071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2367071d4279SBram Moolenaar return FAIL; 2368071d4279SBram Moolenaar 2369071d4279SBram Moolenaar if (len_change) 2370071d4279SBram Moolenaar *len_change = 0; 2371071d4279SBram Moolenaar 2372071d4279SBram Moolenaar return OK; 2373071d4279SBram Moolenaar } 2374071d4279SBram Moolenaar else 2375071d4279SBram Moolenaar { 2376071d4279SBram Moolenaar PyErr_BadArgument(); 2377071d4279SBram Moolenaar return FAIL; 2378071d4279SBram Moolenaar } 2379071d4279SBram Moolenaar } 2380071d4279SBram Moolenaar 2381071d4279SBram Moolenaar /* Replace a range of lines in the specified buffer. The line numbers are in 2382071d4279SBram Moolenaar * Vim format (1-based). The range is from lo up to, but not including, hi. 2383071d4279SBram Moolenaar * The replacement lines are given as a Python list of string objects. The 2384071d4279SBram Moolenaar * list is checked for validity and correct format. Errors are returned as a 2385071d4279SBram Moolenaar * value of FAIL. The return value is OK on success. 2386071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2387071d4279SBram Moolenaar * is set to the change in the buffer length. 2388071d4279SBram Moolenaar */ 2389071d4279SBram Moolenaar static int 2390e7cb9cf6SBram Moolenaar SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change) 2391071d4279SBram Moolenaar { 2392071d4279SBram Moolenaar /* First of all, we check the thpe of the supplied Python object. 2393071d4279SBram Moolenaar * There are three cases: 2394071d4279SBram Moolenaar * 1. NULL, or None - this is a deletion. 2395071d4279SBram Moolenaar * 2. A list - this is a replacement. 2396071d4279SBram Moolenaar * 3. Anything else - this is an error. 2397071d4279SBram Moolenaar */ 2398071d4279SBram Moolenaar if (list == Py_None || list == NULL) 2399071d4279SBram Moolenaar { 24002c45e945SBram Moolenaar PyInt i; 2401e7cb9cf6SBram Moolenaar PyInt n = (int)(hi - lo); 2402071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2403071d4279SBram Moolenaar 2404071d4279SBram Moolenaar PyErr_Clear(); 2405071d4279SBram Moolenaar curbuf = buf; 2406071d4279SBram Moolenaar 2407071d4279SBram Moolenaar if (u_savedel((linenr_T)lo, (long)n) == FAIL) 2408071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2409071d4279SBram Moolenaar else 2410071d4279SBram Moolenaar { 2411071d4279SBram Moolenaar for (i = 0; i < n; ++i) 2412071d4279SBram Moolenaar { 2413071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2414071d4279SBram Moolenaar { 2415071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2416071d4279SBram Moolenaar break; 2417071d4279SBram Moolenaar } 2418071d4279SBram Moolenaar } 2419071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2420e7cb9cf6SBram Moolenaar py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); 2421cdcaa589SBram Moolenaar deleted_lines_mark((linenr_T)lo, (long)i); 2422071d4279SBram Moolenaar } 2423071d4279SBram Moolenaar 2424071d4279SBram Moolenaar curbuf = savebuf; 2425071d4279SBram Moolenaar 2426071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2427071d4279SBram Moolenaar return FAIL; 2428071d4279SBram Moolenaar 2429071d4279SBram Moolenaar if (len_change) 2430071d4279SBram Moolenaar *len_change = -n; 2431071d4279SBram Moolenaar 2432071d4279SBram Moolenaar return OK; 2433071d4279SBram Moolenaar } 2434071d4279SBram Moolenaar else if (PyList_Check(list)) 2435071d4279SBram Moolenaar { 24362c45e945SBram Moolenaar PyInt i; 24372c45e945SBram Moolenaar PyInt new_len = PyList_Size(list); 24382c45e945SBram Moolenaar PyInt old_len = hi - lo; 2439e7cb9cf6SBram Moolenaar PyInt extra = 0; /* lines added to text, can be negative */ 2440071d4279SBram Moolenaar char **array; 2441071d4279SBram Moolenaar buf_T *savebuf; 2442071d4279SBram Moolenaar 2443071d4279SBram Moolenaar if (new_len == 0) /* avoid allocating zero bytes */ 2444071d4279SBram Moolenaar array = NULL; 2445071d4279SBram Moolenaar else 2446071d4279SBram Moolenaar { 2447071d4279SBram Moolenaar array = (char **)alloc((unsigned)(new_len * sizeof(char *))); 2448071d4279SBram Moolenaar if (array == NULL) 2449071d4279SBram Moolenaar { 2450071d4279SBram Moolenaar PyErr_NoMemory(); 2451071d4279SBram Moolenaar return FAIL; 2452071d4279SBram Moolenaar } 2453071d4279SBram Moolenaar } 2454071d4279SBram Moolenaar 2455071d4279SBram Moolenaar for (i = 0; i < new_len; ++i) 2456071d4279SBram Moolenaar { 2457071d4279SBram Moolenaar PyObject *line = PyList_GetItem(list, i); 2458071d4279SBram Moolenaar 2459071d4279SBram Moolenaar array[i] = StringToLine(line); 2460071d4279SBram Moolenaar if (array[i] == NULL) 2461071d4279SBram Moolenaar { 2462071d4279SBram Moolenaar while (i) 2463071d4279SBram Moolenaar vim_free(array[--i]); 2464071d4279SBram Moolenaar vim_free(array); 2465071d4279SBram Moolenaar return FAIL; 2466071d4279SBram Moolenaar } 2467071d4279SBram Moolenaar } 2468071d4279SBram Moolenaar 2469071d4279SBram Moolenaar savebuf = curbuf; 2470071d4279SBram Moolenaar 2471071d4279SBram Moolenaar PyErr_Clear(); 2472071d4279SBram Moolenaar curbuf = buf; 2473071d4279SBram Moolenaar 2474071d4279SBram Moolenaar if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) 2475071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2476071d4279SBram Moolenaar 2477071d4279SBram Moolenaar /* If the size of the range is reducing (ie, new_len < old_len) we 2478071d4279SBram Moolenaar * need to delete some old_len. We do this at the start, by 2479071d4279SBram Moolenaar * repeatedly deleting line "lo". 2480071d4279SBram Moolenaar */ 2481071d4279SBram Moolenaar if (!PyErr_Occurred()) 2482071d4279SBram Moolenaar { 2483071d4279SBram Moolenaar for (i = 0; i < old_len - new_len; ++i) 2484071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2485071d4279SBram Moolenaar { 2486071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2487071d4279SBram Moolenaar break; 2488071d4279SBram Moolenaar } 2489071d4279SBram Moolenaar extra -= i; 2490071d4279SBram Moolenaar } 2491071d4279SBram Moolenaar 2492071d4279SBram Moolenaar /* For as long as possible, replace the existing old_len with the 2493071d4279SBram Moolenaar * new old_len. This is a more efficient operation, as it requires 2494071d4279SBram Moolenaar * less memory allocation and freeing. 2495071d4279SBram Moolenaar */ 2496071d4279SBram Moolenaar if (!PyErr_Occurred()) 2497071d4279SBram Moolenaar { 2498071d4279SBram Moolenaar for (i = 0; i < old_len && i < new_len; ++i) 2499071d4279SBram Moolenaar if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) 2500071d4279SBram Moolenaar == FAIL) 2501071d4279SBram Moolenaar { 2502071d4279SBram Moolenaar PyErr_SetVim(_("cannot replace line")); 2503071d4279SBram Moolenaar break; 2504071d4279SBram Moolenaar } 2505071d4279SBram Moolenaar } 2506071d4279SBram Moolenaar else 2507071d4279SBram Moolenaar i = 0; 2508071d4279SBram Moolenaar 2509071d4279SBram Moolenaar /* Now we may need to insert the remaining new old_len. If we do, we 2510071d4279SBram Moolenaar * must free the strings as we finish with them (we can't pass the 2511071d4279SBram Moolenaar * responsibility to vim in this case). 2512071d4279SBram Moolenaar */ 2513071d4279SBram Moolenaar if (!PyErr_Occurred()) 2514071d4279SBram Moolenaar { 2515071d4279SBram Moolenaar while (i < new_len) 2516071d4279SBram Moolenaar { 2517071d4279SBram Moolenaar if (ml_append((linenr_T)(lo + i - 1), 2518071d4279SBram Moolenaar (char_u *)array[i], 0, FALSE) == FAIL) 2519071d4279SBram Moolenaar { 2520071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2521071d4279SBram Moolenaar break; 2522071d4279SBram Moolenaar } 2523071d4279SBram Moolenaar vim_free(array[i]); 2524071d4279SBram Moolenaar ++i; 2525071d4279SBram Moolenaar ++extra; 2526071d4279SBram Moolenaar } 2527071d4279SBram Moolenaar } 2528071d4279SBram Moolenaar 2529071d4279SBram Moolenaar /* Free any left-over old_len, as a result of an error */ 2530071d4279SBram Moolenaar while (i < new_len) 2531071d4279SBram Moolenaar { 2532071d4279SBram Moolenaar vim_free(array[i]); 2533071d4279SBram Moolenaar ++i; 2534071d4279SBram Moolenaar } 2535071d4279SBram Moolenaar 2536071d4279SBram Moolenaar /* Free the array of old_len. All of its contents have now 2537071d4279SBram Moolenaar * been dealt with (either freed, or the responsibility passed 2538071d4279SBram Moolenaar * to vim. 2539071d4279SBram Moolenaar */ 2540071d4279SBram Moolenaar vim_free(array); 2541071d4279SBram Moolenaar 2542071d4279SBram Moolenaar /* Adjust marks. Invalidate any which lie in the 2543071d4279SBram Moolenaar * changed range, and move any in the remainder of the buffer. 2544071d4279SBram Moolenaar */ 2545071d4279SBram Moolenaar mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), 2546071d4279SBram Moolenaar (long)MAXLNUM, (long)extra); 2547071d4279SBram Moolenaar changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); 2548071d4279SBram Moolenaar 2549071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2550e7cb9cf6SBram Moolenaar py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); 2551071d4279SBram Moolenaar 2552071d4279SBram Moolenaar curbuf = savebuf; 2553071d4279SBram Moolenaar 2554071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2555071d4279SBram Moolenaar return FAIL; 2556071d4279SBram Moolenaar 2557071d4279SBram Moolenaar if (len_change) 2558071d4279SBram Moolenaar *len_change = new_len - old_len; 2559071d4279SBram Moolenaar 2560071d4279SBram Moolenaar return OK; 2561071d4279SBram Moolenaar } 2562071d4279SBram Moolenaar else 2563071d4279SBram Moolenaar { 2564071d4279SBram Moolenaar PyErr_BadArgument(); 2565071d4279SBram Moolenaar return FAIL; 2566071d4279SBram Moolenaar } 2567071d4279SBram Moolenaar } 2568071d4279SBram Moolenaar 2569071d4279SBram Moolenaar /* Insert a number of lines into the specified buffer after the specifed line. 2570071d4279SBram Moolenaar * The line number is in Vim format (1-based). The lines to be inserted are 2571071d4279SBram Moolenaar * given as a Python list of string objects or as a single string. The lines 2572071d4279SBram Moolenaar * to be added are checked for validity and correct format. Errors are 2573071d4279SBram Moolenaar * returned as a value of FAIL. The return value is OK on success. 2574071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2575071d4279SBram Moolenaar * is set to the change in the buffer length. 2576071d4279SBram Moolenaar */ 2577071d4279SBram Moolenaar static int 2578e7cb9cf6SBram Moolenaar InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change) 2579071d4279SBram Moolenaar { 2580071d4279SBram Moolenaar /* First of all, we check the type of the supplied Python object. 2581071d4279SBram Moolenaar * It must be a string or a list, or the call is in error. 2582071d4279SBram Moolenaar */ 2583071d4279SBram Moolenaar if (PyString_Check(lines)) 2584071d4279SBram Moolenaar { 2585071d4279SBram Moolenaar char *str = StringToLine(lines); 2586071d4279SBram Moolenaar buf_T *savebuf; 2587071d4279SBram Moolenaar 2588071d4279SBram Moolenaar if (str == NULL) 2589071d4279SBram Moolenaar return FAIL; 2590071d4279SBram Moolenaar 2591071d4279SBram Moolenaar savebuf = curbuf; 2592071d4279SBram Moolenaar 2593071d4279SBram Moolenaar PyErr_Clear(); 2594071d4279SBram Moolenaar curbuf = buf; 2595071d4279SBram Moolenaar 2596071d4279SBram Moolenaar if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL) 2597071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2598071d4279SBram Moolenaar else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL) 2599071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2600071d4279SBram Moolenaar else 2601071d4279SBram Moolenaar appended_lines_mark((linenr_T)n, 1L); 2602071d4279SBram Moolenaar 2603071d4279SBram Moolenaar vim_free(str); 2604071d4279SBram Moolenaar curbuf = savebuf; 2605071d4279SBram Moolenaar update_screen(VALID); 2606071d4279SBram Moolenaar 2607071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2608071d4279SBram Moolenaar return FAIL; 2609071d4279SBram Moolenaar 2610071d4279SBram Moolenaar if (len_change) 2611071d4279SBram Moolenaar *len_change = 1; 2612071d4279SBram Moolenaar 2613071d4279SBram Moolenaar return OK; 2614071d4279SBram Moolenaar } 2615071d4279SBram Moolenaar else if (PyList_Check(lines)) 2616071d4279SBram Moolenaar { 26172c45e945SBram Moolenaar PyInt i; 26182c45e945SBram Moolenaar PyInt size = PyList_Size(lines); 2619071d4279SBram Moolenaar char **array; 2620071d4279SBram Moolenaar buf_T *savebuf; 2621071d4279SBram Moolenaar 2622071d4279SBram Moolenaar array = (char **)alloc((unsigned)(size * sizeof(char *))); 2623071d4279SBram Moolenaar if (array == NULL) 2624071d4279SBram Moolenaar { 2625071d4279SBram Moolenaar PyErr_NoMemory(); 2626071d4279SBram Moolenaar return FAIL; 2627071d4279SBram Moolenaar } 2628071d4279SBram Moolenaar 2629071d4279SBram Moolenaar for (i = 0; i < size; ++i) 2630071d4279SBram Moolenaar { 2631071d4279SBram Moolenaar PyObject *line = PyList_GetItem(lines, i); 2632071d4279SBram Moolenaar array[i] = StringToLine(line); 2633071d4279SBram Moolenaar 2634071d4279SBram Moolenaar if (array[i] == NULL) 2635071d4279SBram Moolenaar { 2636071d4279SBram Moolenaar while (i) 2637071d4279SBram Moolenaar vim_free(array[--i]); 2638071d4279SBram Moolenaar vim_free(array); 2639071d4279SBram Moolenaar return FAIL; 2640071d4279SBram Moolenaar } 2641071d4279SBram Moolenaar } 2642071d4279SBram Moolenaar 2643071d4279SBram Moolenaar savebuf = curbuf; 2644071d4279SBram Moolenaar 2645071d4279SBram Moolenaar PyErr_Clear(); 2646071d4279SBram Moolenaar curbuf = buf; 2647071d4279SBram Moolenaar 2648071d4279SBram Moolenaar if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) 2649071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2650071d4279SBram Moolenaar else 2651071d4279SBram Moolenaar { 2652071d4279SBram Moolenaar for (i = 0; i < size; ++i) 2653071d4279SBram Moolenaar { 2654071d4279SBram Moolenaar if (ml_append((linenr_T)(n + i), 2655071d4279SBram Moolenaar (char_u *)array[i], 0, FALSE) == FAIL) 2656071d4279SBram Moolenaar { 2657071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2658071d4279SBram Moolenaar 2659071d4279SBram Moolenaar /* Free the rest of the lines */ 2660071d4279SBram Moolenaar while (i < size) 2661071d4279SBram Moolenaar vim_free(array[i++]); 2662071d4279SBram Moolenaar 2663071d4279SBram Moolenaar break; 2664071d4279SBram Moolenaar } 2665071d4279SBram Moolenaar vim_free(array[i]); 2666071d4279SBram Moolenaar } 2667071d4279SBram Moolenaar if (i > 0) 2668071d4279SBram Moolenaar appended_lines_mark((linenr_T)n, (long)i); 2669071d4279SBram Moolenaar } 2670071d4279SBram Moolenaar 2671071d4279SBram Moolenaar /* Free the array of lines. All of its contents have now 2672071d4279SBram Moolenaar * been freed. 2673071d4279SBram Moolenaar */ 2674071d4279SBram Moolenaar vim_free(array); 2675071d4279SBram Moolenaar 2676071d4279SBram Moolenaar curbuf = savebuf; 2677071d4279SBram Moolenaar update_screen(VALID); 2678071d4279SBram Moolenaar 2679071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2680071d4279SBram Moolenaar return FAIL; 2681071d4279SBram Moolenaar 2682071d4279SBram Moolenaar if (len_change) 2683071d4279SBram Moolenaar *len_change = size; 2684071d4279SBram Moolenaar 2685071d4279SBram Moolenaar return OK; 2686071d4279SBram Moolenaar } 2687071d4279SBram Moolenaar else 2688071d4279SBram Moolenaar { 2689071d4279SBram Moolenaar PyErr_BadArgument(); 2690071d4279SBram Moolenaar return FAIL; 2691071d4279SBram Moolenaar } 2692071d4279SBram Moolenaar } 2693071d4279SBram Moolenaar 2694071d4279SBram Moolenaar /* Convert a Vim line into a Python string. 2695071d4279SBram Moolenaar * All internal newlines are replaced by null characters. 2696071d4279SBram Moolenaar * 2697071d4279SBram Moolenaar * On errors, the Python exception data is set, and NULL is returned. 2698071d4279SBram Moolenaar */ 2699071d4279SBram Moolenaar static PyObject * 2700071d4279SBram Moolenaar LineToString(const char *str) 2701071d4279SBram Moolenaar { 2702071d4279SBram Moolenaar PyObject *result; 27032c45e945SBram Moolenaar PyInt len = strlen(str); 2704071d4279SBram Moolenaar char *p; 2705071d4279SBram Moolenaar 2706071d4279SBram Moolenaar /* Allocate an Python string object, with uninitialised contents. We 2707071d4279SBram Moolenaar * must do it this way, so that we can modify the string in place 2708071d4279SBram Moolenaar * later. See the Python source, Objects/stringobject.c for details. 2709071d4279SBram Moolenaar */ 2710071d4279SBram Moolenaar result = PyString_FromStringAndSize(NULL, len); 2711071d4279SBram Moolenaar if (result == NULL) 2712071d4279SBram Moolenaar return NULL; 2713071d4279SBram Moolenaar 2714071d4279SBram Moolenaar p = PyString_AsString(result); 2715071d4279SBram Moolenaar 2716071d4279SBram Moolenaar while (*str) 2717071d4279SBram Moolenaar { 2718071d4279SBram Moolenaar if (*str == '\n') 2719071d4279SBram Moolenaar *p = '\0'; 2720071d4279SBram Moolenaar else 2721071d4279SBram Moolenaar *p = *str; 2722071d4279SBram Moolenaar 2723071d4279SBram Moolenaar ++p; 2724071d4279SBram Moolenaar ++str; 2725071d4279SBram Moolenaar } 2726071d4279SBram Moolenaar 2727071d4279SBram Moolenaar return result; 2728071d4279SBram Moolenaar } 2729071d4279SBram Moolenaar 2730071d4279SBram Moolenaar /* Convert a Python string into a Vim line. 2731071d4279SBram Moolenaar * 2732071d4279SBram Moolenaar * The result is in allocated memory. All internal nulls are replaced by 2733071d4279SBram Moolenaar * newline characters. It is an error for the string to contain newline 2734071d4279SBram Moolenaar * characters. 2735071d4279SBram Moolenaar * 2736071d4279SBram Moolenaar * On errors, the Python exception data is set, and NULL is returned. 2737071d4279SBram Moolenaar */ 2738071d4279SBram Moolenaar static char * 2739071d4279SBram Moolenaar StringToLine(PyObject *obj) 2740071d4279SBram Moolenaar { 2741071d4279SBram Moolenaar const char *str; 2742071d4279SBram Moolenaar char *save; 27432c45e945SBram Moolenaar PyInt len; 27442c45e945SBram Moolenaar PyInt i; 27455eb86f91SBram Moolenaar char *p; 2746071d4279SBram Moolenaar 2747071d4279SBram Moolenaar if (obj == NULL || !PyString_Check(obj)) 2748071d4279SBram Moolenaar { 2749071d4279SBram Moolenaar PyErr_BadArgument(); 2750071d4279SBram Moolenaar return NULL; 2751071d4279SBram Moolenaar } 2752071d4279SBram Moolenaar 2753071d4279SBram Moolenaar str = PyString_AsString(obj); 2754071d4279SBram Moolenaar len = PyString_Size(obj); 2755071d4279SBram Moolenaar 27565eb86f91SBram Moolenaar /* 27575eb86f91SBram Moolenaar * Error checking: String must not contain newlines, as we 2758071d4279SBram Moolenaar * are replacing a single line, and we must replace it with 2759071d4279SBram Moolenaar * a single line. 27605eb86f91SBram Moolenaar * A trailing newline is removed, so that append(f.readlines()) works. 2761071d4279SBram Moolenaar */ 27625eb86f91SBram Moolenaar p = memchr(str, '\n', len); 27635eb86f91SBram Moolenaar if (p != NULL) 27645eb86f91SBram Moolenaar { 27655eb86f91SBram Moolenaar if (p == str + len - 1) 27665eb86f91SBram Moolenaar --len; 27675eb86f91SBram Moolenaar else 2768071d4279SBram Moolenaar { 2769071d4279SBram Moolenaar PyErr_SetVim(_("string cannot contain newlines")); 2770071d4279SBram Moolenaar return NULL; 2771071d4279SBram Moolenaar } 27725eb86f91SBram Moolenaar } 2773071d4279SBram Moolenaar 2774071d4279SBram Moolenaar /* Create a copy of the string, with internal nulls replaced by 2775071d4279SBram Moolenaar * newline characters, as is the vim convention. 2776071d4279SBram Moolenaar */ 2777071d4279SBram Moolenaar save = (char *)alloc((unsigned)(len+1)); 2778071d4279SBram Moolenaar if (save == NULL) 2779071d4279SBram Moolenaar { 2780071d4279SBram Moolenaar PyErr_NoMemory(); 2781071d4279SBram Moolenaar return NULL; 2782071d4279SBram Moolenaar } 2783071d4279SBram Moolenaar 2784071d4279SBram Moolenaar for (i = 0; i < len; ++i) 2785071d4279SBram Moolenaar { 2786071d4279SBram Moolenaar if (str[i] == '\0') 2787071d4279SBram Moolenaar save[i] = '\n'; 2788071d4279SBram Moolenaar else 2789071d4279SBram Moolenaar save[i] = str[i]; 2790071d4279SBram Moolenaar } 2791071d4279SBram Moolenaar 2792071d4279SBram Moolenaar save[i] = '\0'; 2793071d4279SBram Moolenaar 2794071d4279SBram Moolenaar return save; 2795071d4279SBram Moolenaar } 2796071d4279SBram Moolenaar 2797071d4279SBram Moolenaar 2798071d4279SBram Moolenaar /* Don't generate a prototype for the next function, it generates an error on 2799071d4279SBram Moolenaar * newer Python versions. */ 2800071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ && !defined(PROTO) 2801071d4279SBram Moolenaar 2802071d4279SBram Moolenaar char * 2803071d4279SBram Moolenaar Py_GetProgramName(void) 2804071d4279SBram Moolenaar { 2805071d4279SBram Moolenaar return "vim"; 2806071d4279SBram Moolenaar } 2807071d4279SBram Moolenaar #endif /* Python 1.4 */ 2808*170bf1aeSBram Moolenaar 2809*170bf1aeSBram Moolenaar static void 2810*170bf1aeSBram Moolenaar init_structs(void) 2811*170bf1aeSBram Moolenaar { 2812*170bf1aeSBram Moolenaar vim_memset(&OutputType, 0, sizeof(OutputType)); 2813*170bf1aeSBram Moolenaar OutputType.tp_name = "message"; 2814*170bf1aeSBram Moolenaar OutputType.tp_basicsize = sizeof(OutputObject); 2815*170bf1aeSBram Moolenaar OutputType.tp_getattr = OutputGetattr; 2816*170bf1aeSBram Moolenaar OutputType.tp_setattr = OutputSetattr; 2817*170bf1aeSBram Moolenaar } 2818