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 57170bf1aeSBram Moolenaar static void init_structs(void); 58170bf1aeSBram 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* 105644d37b8SBram Moolenaar # if defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL) 106b61f95c3SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY) 107b61f95c3SBram Moolenaar # else 108fa5d1e63SBram Moolenaar # define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL) 109b61f95c3SBram Moolenaar # endif 110bd5e15fdSBram Moolenaar # define close_dll dlclose 111bd5e15fdSBram Moolenaar # define symbol_from_dll dlsym 112bd5e15fdSBram Moolenaar # else 113ebbcb824SBram Moolenaar # define load_dll vimLoadLib 114bd5e15fdSBram Moolenaar # define close_dll FreeLibrary 115bd5e15fdSBram Moolenaar # define symbol_from_dll GetProcAddress 116bd5e15fdSBram Moolenaar # endif 117bd5e15fdSBram Moolenaar 118e7cb9cf6SBram Moolenaar /* This makes if_python.c compile without warnings against Python 2.5 119e7cb9cf6SBram Moolenaar * on Win32 and Win64. */ 120e7cb9cf6SBram Moolenaar # undef PyRun_SimpleString 121e7cb9cf6SBram Moolenaar # undef PyArg_Parse 122e7cb9cf6SBram Moolenaar # undef PyArg_ParseTuple 123e7cb9cf6SBram Moolenaar # undef Py_BuildValue 124e7cb9cf6SBram Moolenaar # undef Py_InitModule4 125e7cb9cf6SBram Moolenaar # undef Py_InitModule4_64 126e7cb9cf6SBram Moolenaar 127071d4279SBram Moolenaar /* 128071d4279SBram Moolenaar * Wrapper defines 129071d4279SBram Moolenaar */ 130071d4279SBram Moolenaar # define PyArg_Parse dll_PyArg_Parse 131071d4279SBram Moolenaar # define PyArg_ParseTuple dll_PyArg_ParseTuple 132071d4279SBram Moolenaar # define PyDict_SetItemString dll_PyDict_SetItemString 133071d4279SBram Moolenaar # define PyErr_BadArgument dll_PyErr_BadArgument 134071d4279SBram Moolenaar # define PyErr_Clear dll_PyErr_Clear 135071d4279SBram Moolenaar # define PyErr_NoMemory dll_PyErr_NoMemory 136071d4279SBram Moolenaar # define PyErr_Occurred dll_PyErr_Occurred 137071d4279SBram Moolenaar # define PyErr_SetNone dll_PyErr_SetNone 138071d4279SBram Moolenaar # define PyErr_SetString dll_PyErr_SetString 139071d4279SBram Moolenaar # define PyEval_InitThreads dll_PyEval_InitThreads 140071d4279SBram Moolenaar # define PyEval_RestoreThread dll_PyEval_RestoreThread 141071d4279SBram Moolenaar # define PyEval_SaveThread dll_PyEval_SaveThread 142071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 143071d4279SBram Moolenaar # define PyGILState_Ensure dll_PyGILState_Ensure 144071d4279SBram Moolenaar # define PyGILState_Release dll_PyGILState_Release 145071d4279SBram Moolenaar # endif 146071d4279SBram Moolenaar # define PyInt_AsLong dll_PyInt_AsLong 147071d4279SBram Moolenaar # define PyInt_FromLong dll_PyInt_FromLong 148071d4279SBram Moolenaar # define PyInt_Type (*dll_PyInt_Type) 149071d4279SBram Moolenaar # define PyList_GetItem dll_PyList_GetItem 1500ac9379aSBram Moolenaar # define PyList_Append dll_PyList_Append 151071d4279SBram Moolenaar # define PyList_New dll_PyList_New 152071d4279SBram Moolenaar # define PyList_SetItem dll_PyList_SetItem 153071d4279SBram Moolenaar # define PyList_Size dll_PyList_Size 154071d4279SBram Moolenaar # define PyList_Type (*dll_PyList_Type) 155071d4279SBram Moolenaar # define PyImport_ImportModule dll_PyImport_ImportModule 1560ac9379aSBram Moolenaar # define PyDict_New dll_PyDict_New 157071d4279SBram Moolenaar # define PyDict_GetItemString dll_PyDict_GetItemString 158071d4279SBram Moolenaar # define PyModule_GetDict dll_PyModule_GetDict 159071d4279SBram Moolenaar # define PyRun_SimpleString dll_PyRun_SimpleString 160071d4279SBram Moolenaar # define PyString_AsString dll_PyString_AsString 161071d4279SBram Moolenaar # define PyString_FromString dll_PyString_FromString 162071d4279SBram Moolenaar # define PyString_FromStringAndSize dll_PyString_FromStringAndSize 163071d4279SBram Moolenaar # define PyString_Size dll_PyString_Size 164071d4279SBram Moolenaar # define PyString_Type (*dll_PyString_Type) 165071d4279SBram Moolenaar # define PySys_SetObject dll_PySys_SetObject 166071d4279SBram Moolenaar # define PySys_SetArgv dll_PySys_SetArgv 167071d4279SBram Moolenaar # define PyType_Type (*dll_PyType_Type) 168071d4279SBram Moolenaar # define Py_BuildValue dll_Py_BuildValue 169071d4279SBram Moolenaar # define Py_FindMethod dll_Py_FindMethod 170071d4279SBram Moolenaar # define Py_InitModule4 dll_Py_InitModule4 171644d37b8SBram Moolenaar # define Py_SetPythonHome dll_Py_SetPythonHome 172071d4279SBram Moolenaar # define Py_Initialize dll_Py_Initialize 1730e21a3f6SBram Moolenaar # define Py_Finalize dll_Py_Finalize 1740e21a3f6SBram Moolenaar # define Py_IsInitialized dll_Py_IsInitialized 175071d4279SBram Moolenaar # define _PyObject_New dll__PyObject_New 176071d4279SBram Moolenaar # define _Py_NoneStruct (*dll__Py_NoneStruct) 177071d4279SBram Moolenaar # define PyObject_Init dll__PyObject_Init 178071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 179071d4279SBram Moolenaar # define PyType_IsSubtype dll_PyType_IsSubtype 180071d4279SBram Moolenaar # endif 181071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 182071d4279SBram Moolenaar # define PyObject_Malloc dll_PyObject_Malloc 183071d4279SBram Moolenaar # define PyObject_Free dll_PyObject_Free 184071d4279SBram Moolenaar # endif 185071d4279SBram Moolenaar 186071d4279SBram Moolenaar /* 187071d4279SBram Moolenaar * Pointers for dynamic link 188071d4279SBram Moolenaar */ 189071d4279SBram Moolenaar static int(*dll_PyArg_Parse)(PyObject *, char *, ...); 190071d4279SBram Moolenaar static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...); 191071d4279SBram Moolenaar static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); 192071d4279SBram Moolenaar static int(*dll_PyErr_BadArgument)(void); 193071d4279SBram Moolenaar static void(*dll_PyErr_Clear)(void); 194071d4279SBram Moolenaar static PyObject*(*dll_PyErr_NoMemory)(void); 195071d4279SBram Moolenaar static PyObject*(*dll_PyErr_Occurred)(void); 196071d4279SBram Moolenaar static void(*dll_PyErr_SetNone)(PyObject *); 197071d4279SBram Moolenaar static void(*dll_PyErr_SetString)(PyObject *, const char *); 198071d4279SBram Moolenaar static void(*dll_PyEval_InitThreads)(void); 199071d4279SBram Moolenaar static void(*dll_PyEval_RestoreThread)(PyThreadState *); 200071d4279SBram Moolenaar static PyThreadState*(*dll_PyEval_SaveThread)(void); 201071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 202071d4279SBram Moolenaar static PyGILState_STATE (*dll_PyGILState_Ensure)(void); 203071d4279SBram Moolenaar static void (*dll_PyGILState_Release)(PyGILState_STATE); 204071d4279SBram Moolenaar #endif 205071d4279SBram Moolenaar static long(*dll_PyInt_AsLong)(PyObject *); 206071d4279SBram Moolenaar static PyObject*(*dll_PyInt_FromLong)(long); 207071d4279SBram Moolenaar static PyTypeObject* dll_PyInt_Type; 2082c45e945SBram Moolenaar static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt); 2090ac9379aSBram Moolenaar static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *); 2102c45e945SBram Moolenaar static PyObject*(*dll_PyList_New)(PyInt size); 2112c45e945SBram Moolenaar static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *); 2122c45e945SBram Moolenaar static PyInt(*dll_PyList_Size)(PyObject *); 213071d4279SBram Moolenaar static PyTypeObject* dll_PyList_Type; 214071d4279SBram Moolenaar static PyObject*(*dll_PyImport_ImportModule)(const char *); 2150ac9379aSBram Moolenaar static PyObject*(*dll_PyDict_New)(void); 216071d4279SBram Moolenaar static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *); 217071d4279SBram Moolenaar static PyObject*(*dll_PyModule_GetDict)(PyObject *); 218071d4279SBram Moolenaar static int(*dll_PyRun_SimpleString)(char *); 219071d4279SBram Moolenaar static char*(*dll_PyString_AsString)(PyObject *); 220071d4279SBram Moolenaar static PyObject*(*dll_PyString_FromString)(const char *); 2212c45e945SBram Moolenaar static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt); 2222c45e945SBram Moolenaar static PyInt(*dll_PyString_Size)(PyObject *); 223071d4279SBram Moolenaar static PyTypeObject* dll_PyString_Type; 224071d4279SBram Moolenaar static int(*dll_PySys_SetObject)(char *, PyObject *); 225071d4279SBram Moolenaar static int(*dll_PySys_SetArgv)(int, char **); 226071d4279SBram Moolenaar static PyTypeObject* dll_PyType_Type; 227071d4279SBram Moolenaar static PyObject*(*dll_Py_BuildValue)(char *, ...); 228071d4279SBram Moolenaar static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *); 229071d4279SBram Moolenaar static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int); 230644d37b8SBram Moolenaar static void(*dll_Py_SetPythonHome)(char *home); 231071d4279SBram Moolenaar static void(*dll_Py_Initialize)(void); 2320e21a3f6SBram Moolenaar static void(*dll_Py_Finalize)(void); 2330e21a3f6SBram Moolenaar static int(*dll_Py_IsInitialized)(void); 234071d4279SBram Moolenaar static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *); 235071d4279SBram Moolenaar static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *); 236071d4279SBram Moolenaar static PyObject* dll__Py_NoneStruct; 237071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 238071d4279SBram Moolenaar static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *); 239071d4279SBram Moolenaar # endif 240071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 241071d4279SBram Moolenaar static void* (*dll_PyObject_Malloc)(size_t); 242071d4279SBram Moolenaar static void (*dll_PyObject_Free)(void*); 243071d4279SBram Moolenaar # endif 244071d4279SBram Moolenaar 245071d4279SBram Moolenaar static HINSTANCE hinstPython = 0; /* Instance of python.dll */ 246071d4279SBram Moolenaar 247071d4279SBram Moolenaar /* Imported exception objects */ 248071d4279SBram Moolenaar static PyObject *imp_PyExc_AttributeError; 249071d4279SBram Moolenaar static PyObject *imp_PyExc_IndexError; 250071d4279SBram Moolenaar static PyObject *imp_PyExc_KeyboardInterrupt; 251071d4279SBram Moolenaar static PyObject *imp_PyExc_TypeError; 252071d4279SBram Moolenaar static PyObject *imp_PyExc_ValueError; 253071d4279SBram Moolenaar 254071d4279SBram Moolenaar # define PyExc_AttributeError imp_PyExc_AttributeError 255071d4279SBram Moolenaar # define PyExc_IndexError imp_PyExc_IndexError 256071d4279SBram Moolenaar # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt 257071d4279SBram Moolenaar # define PyExc_TypeError imp_PyExc_TypeError 258071d4279SBram Moolenaar # define PyExc_ValueError imp_PyExc_ValueError 259071d4279SBram Moolenaar 260071d4279SBram Moolenaar /* 261071d4279SBram Moolenaar * Table of name to function pointer of python. 262071d4279SBram Moolenaar */ 263071d4279SBram Moolenaar # define PYTHON_PROC FARPROC 264071d4279SBram Moolenaar static struct 265071d4279SBram Moolenaar { 266071d4279SBram Moolenaar char *name; 267071d4279SBram Moolenaar PYTHON_PROC *ptr; 268071d4279SBram Moolenaar } python_funcname_table[] = 269071d4279SBram Moolenaar { 270071d4279SBram Moolenaar {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse}, 271071d4279SBram Moolenaar {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple}, 272071d4279SBram Moolenaar {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString}, 273071d4279SBram Moolenaar {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument}, 274071d4279SBram Moolenaar {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear}, 275071d4279SBram Moolenaar {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory}, 276071d4279SBram Moolenaar {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred}, 277071d4279SBram Moolenaar {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone}, 278071d4279SBram Moolenaar {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString}, 279071d4279SBram Moolenaar {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads}, 280071d4279SBram Moolenaar {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread}, 281071d4279SBram Moolenaar {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread}, 282071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 283071d4279SBram Moolenaar {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure}, 284071d4279SBram Moolenaar {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release}, 285071d4279SBram Moolenaar # endif 286071d4279SBram Moolenaar {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong}, 287071d4279SBram Moolenaar {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong}, 288071d4279SBram Moolenaar {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type}, 289071d4279SBram Moolenaar {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem}, 2900ac9379aSBram Moolenaar {"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append}, 291071d4279SBram Moolenaar {"PyList_New", (PYTHON_PROC*)&dll_PyList_New}, 292071d4279SBram Moolenaar {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem}, 293071d4279SBram Moolenaar {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size}, 294071d4279SBram Moolenaar {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type}, 295071d4279SBram Moolenaar {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule}, 296071d4279SBram Moolenaar {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString}, 2970ac9379aSBram Moolenaar {"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New}, 298071d4279SBram Moolenaar {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict}, 299071d4279SBram Moolenaar {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString}, 300071d4279SBram Moolenaar {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString}, 301071d4279SBram Moolenaar {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString}, 302071d4279SBram Moolenaar {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize}, 303071d4279SBram Moolenaar {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size}, 304071d4279SBram Moolenaar {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type}, 305071d4279SBram Moolenaar {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject}, 306071d4279SBram Moolenaar {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv}, 307071d4279SBram Moolenaar {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type}, 308071d4279SBram Moolenaar {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue}, 309071d4279SBram Moolenaar {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod}, 310e7cb9cf6SBram Moolenaar # if (PY_VERSION_HEX >= 0x02050000) && SIZEOF_SIZE_T != SIZEOF_INT 311e7cb9cf6SBram Moolenaar {"Py_InitModule4_64", (PYTHON_PROC*)&dll_Py_InitModule4}, 312e7cb9cf6SBram Moolenaar # else 313071d4279SBram Moolenaar {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4}, 314e7cb9cf6SBram Moolenaar # endif 315644d37b8SBram Moolenaar {"Py_SetPythonHome", (PYTHON_PROC*)&dll_Py_SetPythonHome}, 316071d4279SBram Moolenaar {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize}, 3170e21a3f6SBram Moolenaar {"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize}, 3180e21a3f6SBram Moolenaar {"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized}, 319071d4279SBram Moolenaar {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New}, 320071d4279SBram Moolenaar {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init}, 321071d4279SBram Moolenaar {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct}, 322071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 323071d4279SBram Moolenaar {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype}, 324071d4279SBram Moolenaar # endif 325071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 326071d4279SBram Moolenaar {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc}, 327071d4279SBram Moolenaar {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free}, 328071d4279SBram Moolenaar # endif 329071d4279SBram Moolenaar {"", NULL}, 330071d4279SBram Moolenaar }; 331071d4279SBram Moolenaar 332071d4279SBram Moolenaar /* 333071d4279SBram Moolenaar * Free python.dll 334071d4279SBram Moolenaar */ 335071d4279SBram Moolenaar static void 336071d4279SBram Moolenaar end_dynamic_python(void) 337071d4279SBram Moolenaar { 338071d4279SBram Moolenaar if (hinstPython) 339071d4279SBram Moolenaar { 340bd5e15fdSBram Moolenaar close_dll(hinstPython); 341071d4279SBram Moolenaar hinstPython = 0; 342071d4279SBram Moolenaar } 343071d4279SBram Moolenaar } 344071d4279SBram Moolenaar 345071d4279SBram Moolenaar /* 346071d4279SBram Moolenaar * Load library and get all pointers. 347071d4279SBram Moolenaar * Parameter 'libname' provides name of DLL. 348071d4279SBram Moolenaar * Return OK or FAIL. 349071d4279SBram Moolenaar */ 350071d4279SBram Moolenaar static int 351071d4279SBram Moolenaar python_runtime_link_init(char *libname, int verbose) 352071d4279SBram Moolenaar { 353071d4279SBram Moolenaar int i; 354071d4279SBram Moolenaar 355644d37b8SBram Moolenaar #if !(defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL)) && defined(UNIX) && defined(FEAT_PYTHON3) 356b744b2faSBram Moolenaar /* Can't have Python and Python3 loaded at the same time. 357b744b2faSBram Moolenaar * It cause a crash, because RTLD_GLOBAL is needed for 358b744b2faSBram Moolenaar * standard C extension libraries of one or both python versions. */ 3594c3a326cSBram Moolenaar if (python3_loaded()) 3604c3a326cSBram Moolenaar { 361b744b2faSBram Moolenaar EMSG(_("E836: This Vim cannot execute :python after using :py3")); 3624c3a326cSBram Moolenaar return FAIL; 3634c3a326cSBram Moolenaar } 3644c3a326cSBram Moolenaar #endif 3654c3a326cSBram Moolenaar 366071d4279SBram Moolenaar if (hinstPython) 367071d4279SBram Moolenaar return OK; 368bd5e15fdSBram Moolenaar hinstPython = load_dll(libname); 369071d4279SBram Moolenaar if (!hinstPython) 370071d4279SBram Moolenaar { 371071d4279SBram Moolenaar if (verbose) 372071d4279SBram Moolenaar EMSG2(_(e_loadlib), libname); 373071d4279SBram Moolenaar return FAIL; 374071d4279SBram Moolenaar } 375071d4279SBram Moolenaar 376071d4279SBram Moolenaar for (i = 0; python_funcname_table[i].ptr; ++i) 377071d4279SBram Moolenaar { 378bd5e15fdSBram Moolenaar if ((*python_funcname_table[i].ptr = symbol_from_dll(hinstPython, 379071d4279SBram Moolenaar python_funcname_table[i].name)) == NULL) 380071d4279SBram Moolenaar { 381bd5e15fdSBram Moolenaar close_dll(hinstPython); 382071d4279SBram Moolenaar hinstPython = 0; 383071d4279SBram Moolenaar if (verbose) 384071d4279SBram Moolenaar EMSG2(_(e_loadfunc), python_funcname_table[i].name); 385071d4279SBram Moolenaar return FAIL; 386071d4279SBram Moolenaar } 387071d4279SBram Moolenaar } 388071d4279SBram Moolenaar return OK; 389071d4279SBram Moolenaar } 390071d4279SBram Moolenaar 391071d4279SBram Moolenaar /* 392071d4279SBram Moolenaar * If python is enabled (there is installed python on Windows system) return 393071d4279SBram Moolenaar * TRUE, else FALSE. 394071d4279SBram Moolenaar */ 395071d4279SBram Moolenaar int 396e7cb9cf6SBram Moolenaar python_enabled(int verbose) 397071d4279SBram Moolenaar { 398071d4279SBram Moolenaar return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK; 399071d4279SBram Moolenaar } 400071d4279SBram Moolenaar 401ca8a4dfeSBram Moolenaar /* 402ca8a4dfeSBram Moolenaar * Load the standard Python exceptions - don't import the symbols from the 403071d4279SBram Moolenaar * DLL, as this can cause errors (importing data symbols is not reliable). 404071d4279SBram Moolenaar */ 405071d4279SBram Moolenaar static void 406ca8a4dfeSBram Moolenaar get_exceptions(void) 407071d4279SBram Moolenaar { 408071d4279SBram Moolenaar PyObject *exmod = PyImport_ImportModule("exceptions"); 409071d4279SBram Moolenaar PyObject *exdict = PyModule_GetDict(exmod); 410071d4279SBram Moolenaar imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError"); 411071d4279SBram Moolenaar imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError"); 412071d4279SBram Moolenaar imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); 413071d4279SBram Moolenaar imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); 414071d4279SBram Moolenaar imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); 415071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_AttributeError); 416071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_IndexError); 417071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_KeyboardInterrupt); 418071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_TypeError); 419071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_ValueError); 420071d4279SBram Moolenaar Py_XDECREF(exmod); 421071d4279SBram Moolenaar } 422071d4279SBram Moolenaar #endif /* DYNAMIC_PYTHON */ 423071d4279SBram Moolenaar 424ca8a4dfeSBram Moolenaar static PyObject *BufferNew (buf_T *); 425ca8a4dfeSBram Moolenaar static PyObject *WindowNew(win_T *); 426ca8a4dfeSBram Moolenaar static PyObject *LineToString(const char *); 427ca8a4dfeSBram Moolenaar 428ca8a4dfeSBram Moolenaar static PyTypeObject RangeType; 429ca8a4dfeSBram Moolenaar 430170bf1aeSBram Moolenaar /* 431170bf1aeSBram Moolenaar * Include the code shared with if_python3.c 432170bf1aeSBram Moolenaar */ 433170bf1aeSBram Moolenaar #include "if_py_both.h" 434170bf1aeSBram Moolenaar 435170bf1aeSBram Moolenaar 436071d4279SBram Moolenaar /****************************************************** 437071d4279SBram Moolenaar * Internal function prototypes. 438071d4279SBram Moolenaar */ 439071d4279SBram Moolenaar 440e7cb9cf6SBram Moolenaar static PyInt RangeStart; 441e7cb9cf6SBram Moolenaar static PyInt RangeEnd; 442071d4279SBram Moolenaar 443071d4279SBram Moolenaar static void PythonIO_Flush(void); 444071d4279SBram Moolenaar static int PythonIO_Init(void); 445071d4279SBram Moolenaar static int PythonMod_Init(void); 446071d4279SBram Moolenaar 447071d4279SBram Moolenaar /* Utility functions for the vim/python interface 448071d4279SBram Moolenaar * ---------------------------------------------- 449071d4279SBram Moolenaar */ 450071d4279SBram Moolenaar 451e7cb9cf6SBram Moolenaar static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, PyInt *); 452071d4279SBram Moolenaar 453071d4279SBram Moolenaar 454071d4279SBram Moolenaar /****************************************************** 455071d4279SBram Moolenaar * 1. Python interpreter main program. 456071d4279SBram Moolenaar */ 457071d4279SBram Moolenaar 458071d4279SBram Moolenaar static int initialised = 0; 459071d4279SBram Moolenaar 460071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ 461071d4279SBram Moolenaar typedef PyObject PyThreadState; 4629ba0eb85SBram Moolenaar #endif 463071d4279SBram Moolenaar 4649ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4659ba0eb85SBram Moolenaar static PyGILState_STATE pygilstate = PyGILState_UNLOCKED; 4669ba0eb85SBram Moolenaar #else 467071d4279SBram Moolenaar static PyThreadState *saved_python_thread = NULL; 4689ba0eb85SBram Moolenaar #endif 469071d4279SBram Moolenaar 470071d4279SBram Moolenaar /* 471071d4279SBram Moolenaar * Suspend a thread of the Python interpreter, other threads are allowed to 472071d4279SBram Moolenaar * run. 473071d4279SBram Moolenaar */ 474293ee4d4SBram Moolenaar static void 475293ee4d4SBram Moolenaar Python_SaveThread(void) 476071d4279SBram Moolenaar { 4779ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4789ba0eb85SBram Moolenaar PyGILState_Release(pygilstate); 4799ba0eb85SBram Moolenaar #else 480071d4279SBram Moolenaar saved_python_thread = PyEval_SaveThread(); 4819ba0eb85SBram Moolenaar #endif 482071d4279SBram Moolenaar } 483071d4279SBram Moolenaar 484071d4279SBram Moolenaar /* 485071d4279SBram Moolenaar * Restore a thread of the Python interpreter, waits for other threads to 486071d4279SBram Moolenaar * block. 487071d4279SBram Moolenaar */ 488293ee4d4SBram Moolenaar static void 489293ee4d4SBram Moolenaar Python_RestoreThread(void) 490071d4279SBram Moolenaar { 4919ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE 4929ba0eb85SBram Moolenaar pygilstate = PyGILState_Ensure(); 4939ba0eb85SBram Moolenaar #else 494071d4279SBram Moolenaar PyEval_RestoreThread(saved_python_thread); 495071d4279SBram Moolenaar saved_python_thread = NULL; 496071d4279SBram Moolenaar #endif 4979ba0eb85SBram Moolenaar } 498071d4279SBram Moolenaar 499071d4279SBram Moolenaar void 500071d4279SBram Moolenaar python_end() 501071d4279SBram Moolenaar { 502a5792f58SBram Moolenaar static int recurse = 0; 503a5792f58SBram Moolenaar 504a5792f58SBram Moolenaar /* If a crash occurs while doing this, don't try again. */ 505a5792f58SBram Moolenaar if (recurse != 0) 506a5792f58SBram Moolenaar return; 507a5792f58SBram Moolenaar 508a5792f58SBram Moolenaar ++recurse; 509a5792f58SBram Moolenaar 510071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 5110e21a3f6SBram Moolenaar if (hinstPython && Py_IsInitialized()) 5129ba0eb85SBram Moolenaar { 5139ba0eb85SBram Moolenaar Python_RestoreThread(); /* enter python */ 5140e21a3f6SBram Moolenaar Py_Finalize(); 5159ba0eb85SBram Moolenaar } 516071d4279SBram Moolenaar end_dynamic_python(); 5170e21a3f6SBram Moolenaar #else 5180e21a3f6SBram Moolenaar if (Py_IsInitialized()) 5199ba0eb85SBram Moolenaar { 5209ba0eb85SBram Moolenaar Python_RestoreThread(); /* enter python */ 5210e21a3f6SBram Moolenaar Py_Finalize(); 5229ba0eb85SBram Moolenaar } 523071d4279SBram Moolenaar #endif 524a5792f58SBram Moolenaar 525a5792f58SBram Moolenaar --recurse; 526071d4279SBram Moolenaar } 527071d4279SBram Moolenaar 5284c3a326cSBram Moolenaar #if (defined(DYNAMIC_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO) 5294c3a326cSBram Moolenaar int 5304c3a326cSBram Moolenaar python_loaded() 5314c3a326cSBram Moolenaar { 5324c3a326cSBram Moolenaar return (hinstPython != 0); 5334c3a326cSBram Moolenaar } 5344c3a326cSBram Moolenaar #endif 5354c3a326cSBram Moolenaar 536071d4279SBram Moolenaar static int 537071d4279SBram Moolenaar Python_Init(void) 538071d4279SBram Moolenaar { 539071d4279SBram Moolenaar if (!initialised) 540071d4279SBram Moolenaar { 541071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 542071d4279SBram Moolenaar if (!python_enabled(TRUE)) 543071d4279SBram Moolenaar { 544071d4279SBram Moolenaar EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded.")); 545071d4279SBram Moolenaar goto fail; 546071d4279SBram Moolenaar } 547071d4279SBram Moolenaar #endif 548071d4279SBram Moolenaar 549644d37b8SBram Moolenaar #ifdef PYTHON_HOME 550644d37b8SBram Moolenaar Py_SetPythonHome(PYTHON_HOME); 551644d37b8SBram Moolenaar #endif 552644d37b8SBram Moolenaar 553170bf1aeSBram Moolenaar init_structs(); 554170bf1aeSBram Moolenaar 555071d4279SBram Moolenaar #if !defined(MACOS) || defined(MACOS_X_UNIX) 556071d4279SBram Moolenaar Py_Initialize(); 557071d4279SBram Moolenaar #else 558071d4279SBram Moolenaar PyMac_Initialize(); 559071d4279SBram Moolenaar #endif 560071d4279SBram Moolenaar /* initialise threads */ 561071d4279SBram Moolenaar PyEval_InitThreads(); 562071d4279SBram Moolenaar 563071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 564071d4279SBram Moolenaar get_exceptions(); 565071d4279SBram Moolenaar #endif 566071d4279SBram Moolenaar 567071d4279SBram Moolenaar if (PythonIO_Init()) 568071d4279SBram Moolenaar goto fail; 569071d4279SBram Moolenaar 570071d4279SBram Moolenaar if (PythonMod_Init()) 571071d4279SBram Moolenaar goto fail; 572071d4279SBram Moolenaar 5739774ecc8SBram Moolenaar /* Remove the element from sys.path that was added because of our 5749774ecc8SBram Moolenaar * argv[0] value in PythonMod_Init(). Previously we used an empty 5759774ecc8SBram Moolenaar * string, but dependinding on the OS we then get an empty entry or 5769774ecc8SBram Moolenaar * the current directory in sys.path. */ 5779774ecc8SBram Moolenaar PyRun_SimpleString("import sys; sys.path = filter(lambda x: x != '/must>not&exist', sys.path)"); 5789774ecc8SBram Moolenaar 579293ee4d4SBram Moolenaar /* the first python thread is vim's, release the lock */ 580071d4279SBram Moolenaar Python_SaveThread(); 581071d4279SBram Moolenaar 582071d4279SBram Moolenaar initialised = 1; 583071d4279SBram Moolenaar } 584071d4279SBram Moolenaar 585071d4279SBram Moolenaar return 0; 586071d4279SBram Moolenaar 587071d4279SBram Moolenaar fail: 588071d4279SBram Moolenaar /* We call PythonIO_Flush() here to print any Python errors. 589071d4279SBram Moolenaar * This is OK, as it is possible to call this function even 590071d4279SBram Moolenaar * if PythonIO_Init() has not completed successfully (it will 591071d4279SBram Moolenaar * not do anything in this case). 592071d4279SBram Moolenaar */ 593071d4279SBram Moolenaar PythonIO_Flush(); 594071d4279SBram Moolenaar return -1; 595071d4279SBram Moolenaar } 596071d4279SBram Moolenaar 597071d4279SBram Moolenaar /* 598071d4279SBram Moolenaar * External interface 599071d4279SBram Moolenaar */ 600071d4279SBram Moolenaar static void 601071d4279SBram Moolenaar DoPythonCommand(exarg_T *eap, const char *cmd) 602071d4279SBram Moolenaar { 6039ba0eb85SBram Moolenaar #ifndef PY_CAN_RECURSE 604071d4279SBram Moolenaar static int recursive = 0; 605071d4279SBram Moolenaar #endif 606071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 607071d4279SBram Moolenaar GrafPtr oldPort; 608071d4279SBram Moolenaar #endif 609071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 610071d4279SBram Moolenaar char *saved_locale; 611071d4279SBram Moolenaar #endif 612071d4279SBram Moolenaar 613071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 614071d4279SBram Moolenaar if (recursive) 615071d4279SBram Moolenaar { 616071d4279SBram Moolenaar EMSG(_("E659: Cannot invoke Python recursively")); 617071d4279SBram Moolenaar return; 618071d4279SBram Moolenaar } 619071d4279SBram Moolenaar ++recursive; 620071d4279SBram Moolenaar #endif 621071d4279SBram Moolenaar 622071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 623071d4279SBram Moolenaar GetPort(&oldPort); 624071d4279SBram Moolenaar /* Check if the Python library is available */ 625071d4279SBram Moolenaar if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress) 626071d4279SBram Moolenaar goto theend; 627071d4279SBram Moolenaar #endif 628071d4279SBram Moolenaar if (Python_Init()) 629071d4279SBram Moolenaar goto theend; 630071d4279SBram Moolenaar 631071d4279SBram Moolenaar RangeStart = eap->line1; 632071d4279SBram Moolenaar RangeEnd = eap->line2; 633071d4279SBram Moolenaar Python_Release_Vim(); /* leave vim */ 634071d4279SBram Moolenaar 635071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 636071d4279SBram Moolenaar /* Python only works properly when the LC_NUMERIC locale is "C". */ 637071d4279SBram Moolenaar saved_locale = setlocale(LC_NUMERIC, NULL); 638071d4279SBram Moolenaar if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0) 639071d4279SBram Moolenaar saved_locale = NULL; 640071d4279SBram Moolenaar else 641071d4279SBram Moolenaar { 642071d4279SBram Moolenaar /* Need to make a copy, value may change when setting new locale. */ 643071d4279SBram Moolenaar saved_locale = (char *)vim_strsave((char_u *)saved_locale); 644071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, "C"); 645071d4279SBram Moolenaar } 646071d4279SBram Moolenaar #endif 647071d4279SBram Moolenaar 648071d4279SBram Moolenaar Python_RestoreThread(); /* enter python */ 649071d4279SBram Moolenaar 650071d4279SBram Moolenaar PyRun_SimpleString((char *)(cmd)); 651071d4279SBram Moolenaar 652071d4279SBram Moolenaar Python_SaveThread(); /* leave python */ 653071d4279SBram Moolenaar 654071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 655071d4279SBram Moolenaar if (saved_locale != NULL) 656071d4279SBram Moolenaar { 657071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, saved_locale); 658071d4279SBram Moolenaar vim_free(saved_locale); 659071d4279SBram Moolenaar } 660071d4279SBram Moolenaar #endif 661071d4279SBram Moolenaar 662071d4279SBram Moolenaar Python_Lock_Vim(); /* enter vim */ 663071d4279SBram Moolenaar PythonIO_Flush(); 664071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 665071d4279SBram Moolenaar SetPort(oldPort); 666071d4279SBram Moolenaar #endif 667071d4279SBram Moolenaar 668071d4279SBram Moolenaar theend: 669071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 670071d4279SBram Moolenaar --recursive; 671071d4279SBram Moolenaar #endif 672071d4279SBram Moolenaar return; /* keeps lint happy */ 673071d4279SBram Moolenaar } 674071d4279SBram Moolenaar 675071d4279SBram Moolenaar /* 676071d4279SBram Moolenaar * ":python" 677071d4279SBram Moolenaar */ 678071d4279SBram Moolenaar void 679071d4279SBram Moolenaar ex_python(exarg_T *eap) 680071d4279SBram Moolenaar { 681071d4279SBram Moolenaar char_u *script; 682071d4279SBram Moolenaar 683071d4279SBram Moolenaar script = script_get(eap, eap->arg); 684071d4279SBram Moolenaar if (!eap->skip) 685071d4279SBram Moolenaar { 686071d4279SBram Moolenaar if (script == NULL) 687071d4279SBram Moolenaar DoPythonCommand(eap, (char *)eap->arg); 688071d4279SBram Moolenaar else 689071d4279SBram Moolenaar DoPythonCommand(eap, (char *)script); 690071d4279SBram Moolenaar } 691071d4279SBram Moolenaar vim_free(script); 692071d4279SBram Moolenaar } 693071d4279SBram Moolenaar 694071d4279SBram Moolenaar #define BUFFER_SIZE 1024 695071d4279SBram Moolenaar 696071d4279SBram Moolenaar /* 697071d4279SBram Moolenaar * ":pyfile" 698071d4279SBram Moolenaar */ 699071d4279SBram Moolenaar void 700071d4279SBram Moolenaar ex_pyfile(exarg_T *eap) 701071d4279SBram Moolenaar { 702071d4279SBram Moolenaar static char buffer[BUFFER_SIZE]; 703071d4279SBram Moolenaar const char *file = (char *)eap->arg; 704071d4279SBram Moolenaar char *p; 705071d4279SBram Moolenaar 706071d4279SBram Moolenaar /* Have to do it like this. PyRun_SimpleFile requires you to pass a 707071d4279SBram Moolenaar * stdio file pointer, but Vim and the Python DLL are compiled with 708071d4279SBram Moolenaar * different options under Windows, meaning that stdio pointers aren't 709071d4279SBram Moolenaar * compatible between the two. Yuk. 710071d4279SBram Moolenaar * 711071d4279SBram Moolenaar * Put the string "execfile('file')" into buffer. But, we need to 712071d4279SBram Moolenaar * escape any backslashes or single quotes in the file name, so that 713071d4279SBram Moolenaar * Python won't mangle the file name. 714071d4279SBram Moolenaar */ 715071d4279SBram Moolenaar strcpy(buffer, "execfile('"); 716071d4279SBram Moolenaar p = buffer + 10; /* size of "execfile('" */ 717071d4279SBram Moolenaar 718071d4279SBram Moolenaar while (*file && p < buffer + (BUFFER_SIZE - 3)) 719071d4279SBram Moolenaar { 720071d4279SBram Moolenaar if (*file == '\\' || *file == '\'') 721071d4279SBram Moolenaar *p++ = '\\'; 722071d4279SBram Moolenaar *p++ = *file++; 723071d4279SBram Moolenaar } 724071d4279SBram Moolenaar 725071d4279SBram Moolenaar /* If we didn't finish the file name, we hit a buffer overflow */ 726071d4279SBram Moolenaar if (*file != '\0') 727071d4279SBram Moolenaar return; 728071d4279SBram Moolenaar 729071d4279SBram Moolenaar /* Put in the terminating "')" and a null */ 730071d4279SBram Moolenaar *p++ = '\''; 731071d4279SBram Moolenaar *p++ = ')'; 732071d4279SBram Moolenaar *p++ = '\0'; 733071d4279SBram Moolenaar 734071d4279SBram Moolenaar /* Execute the file */ 735071d4279SBram Moolenaar DoPythonCommand(eap, buffer); 736071d4279SBram Moolenaar } 737071d4279SBram Moolenaar 738071d4279SBram Moolenaar /****************************************************** 739071d4279SBram Moolenaar * 2. Python output stream: writes output via [e]msg(). 740071d4279SBram Moolenaar */ 741071d4279SBram Moolenaar 742071d4279SBram Moolenaar /* Implementation functions 743071d4279SBram Moolenaar */ 744071d4279SBram Moolenaar 745071d4279SBram Moolenaar static PyObject * 746071d4279SBram Moolenaar OutputGetattr(PyObject *self, char *name) 747071d4279SBram Moolenaar { 748071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 749071d4279SBram Moolenaar return PyInt_FromLong(((OutputObject *)(self))->softspace); 750071d4279SBram Moolenaar 751071d4279SBram Moolenaar return Py_FindMethod(OutputMethods, self, name); 752071d4279SBram Moolenaar } 753071d4279SBram Moolenaar 754071d4279SBram Moolenaar static int 755071d4279SBram Moolenaar OutputSetattr(PyObject *self, char *name, PyObject *val) 756071d4279SBram Moolenaar { 757071d4279SBram Moolenaar if (val == NULL) { 758071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes")); 759071d4279SBram Moolenaar return -1; 760071d4279SBram Moolenaar } 761071d4279SBram Moolenaar 762071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 763071d4279SBram Moolenaar { 764071d4279SBram Moolenaar if (!PyInt_Check(val)) { 765071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("softspace must be an integer")); 766071d4279SBram Moolenaar return -1; 767071d4279SBram Moolenaar } 768071d4279SBram Moolenaar 769071d4279SBram Moolenaar ((OutputObject *)(self))->softspace = PyInt_AsLong(val); 770071d4279SBram Moolenaar return 0; 771071d4279SBram Moolenaar } 772071d4279SBram Moolenaar 773071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("invalid attribute")); 774071d4279SBram Moolenaar return -1; 775071d4279SBram Moolenaar } 776071d4279SBram Moolenaar 777071d4279SBram Moolenaar /***************/ 778071d4279SBram Moolenaar 779071d4279SBram Moolenaar static int 780071d4279SBram Moolenaar PythonIO_Init(void) 781071d4279SBram Moolenaar { 782071d4279SBram Moolenaar /* Fixups... */ 783*21377c8dSBram Moolenaar PyType_Ready(&OutputType); 784071d4279SBram Moolenaar 785170bf1aeSBram Moolenaar return PythonIO_Init_io(); 786071d4279SBram Moolenaar } 787071d4279SBram Moolenaar 788071d4279SBram Moolenaar /****************************************************** 789071d4279SBram Moolenaar * 3. Implementation of the Vim module for Python 790071d4279SBram Moolenaar */ 791071d4279SBram Moolenaar 792071d4279SBram Moolenaar /* Window type - Implementation functions 793071d4279SBram Moolenaar * -------------------------------------- 794071d4279SBram Moolenaar */ 795071d4279SBram Moolenaar 796071d4279SBram Moolenaar #define WindowType_Check(obj) ((obj)->ob_type == &WindowType) 797071d4279SBram Moolenaar 798071d4279SBram Moolenaar static void WindowDestructor(PyObject *); 799071d4279SBram Moolenaar static PyObject *WindowGetattr(PyObject *, char *); 800071d4279SBram Moolenaar 801071d4279SBram Moolenaar /* Buffer type - Implementation functions 802071d4279SBram Moolenaar * -------------------------------------- 803071d4279SBram Moolenaar */ 804071d4279SBram Moolenaar 805071d4279SBram Moolenaar #define BufferType_Check(obj) ((obj)->ob_type == &BufferType) 806071d4279SBram Moolenaar 807071d4279SBram Moolenaar static void BufferDestructor(PyObject *); 808071d4279SBram Moolenaar static PyObject *BufferGetattr(PyObject *, char *); 809071d4279SBram Moolenaar static PyObject *BufferRepr(PyObject *); 810071d4279SBram Moolenaar 8112c45e945SBram Moolenaar static PyInt BufferLength(PyObject *); 8122c45e945SBram Moolenaar static PyObject *BufferItem(PyObject *, PyInt); 8132c45e945SBram Moolenaar static PyObject *BufferSlice(PyObject *, PyInt, PyInt); 8142c45e945SBram Moolenaar static PyInt BufferAssItem(PyObject *, PyInt, PyObject *); 8152c45e945SBram Moolenaar static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *); 816071d4279SBram Moolenaar 817071d4279SBram Moolenaar /* Line range type - Implementation functions 818071d4279SBram Moolenaar * -------------------------------------- 819071d4279SBram Moolenaar */ 820071d4279SBram Moolenaar 821071d4279SBram Moolenaar #define RangeType_Check(obj) ((obj)->ob_type == &RangeType) 822071d4279SBram Moolenaar 8232c45e945SBram Moolenaar static PyInt RangeAssItem(PyObject *, PyInt, PyObject *); 8242c45e945SBram Moolenaar static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *); 825071d4279SBram Moolenaar 826071d4279SBram Moolenaar /* Current objects type - Implementation functions 827071d4279SBram Moolenaar * ----------------------------------------------- 828071d4279SBram Moolenaar */ 829071d4279SBram Moolenaar 830071d4279SBram Moolenaar static PyObject *CurrentGetattr(PyObject *, char *); 831071d4279SBram Moolenaar static int CurrentSetattr(PyObject *, char *, PyObject *); 832071d4279SBram Moolenaar 833071d4279SBram Moolenaar /* Common routines for buffers and line ranges 834071d4279SBram Moolenaar * ------------------------------------------- 835071d4279SBram Moolenaar */ 836170bf1aeSBram Moolenaar 8372c45e945SBram Moolenaar static PyInt 838e7cb9cf6SBram Moolenaar RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end) 839071d4279SBram Moolenaar { 840e7cb9cf6SBram Moolenaar PyInt size; 841e7cb9cf6SBram Moolenaar PyInt len_change; 842071d4279SBram Moolenaar 843071d4279SBram Moolenaar /* Self must be a valid buffer */ 844071d4279SBram Moolenaar if (CheckBuffer(self)) 845071d4279SBram Moolenaar return -1; 846071d4279SBram Moolenaar 847071d4279SBram Moolenaar /* Sort out the slice range */ 848071d4279SBram Moolenaar size = end - start + 1; 849071d4279SBram Moolenaar 850071d4279SBram Moolenaar if (lo < 0) 851071d4279SBram Moolenaar lo = 0; 852071d4279SBram Moolenaar else if (lo > size) 853071d4279SBram Moolenaar lo = size; 854071d4279SBram Moolenaar if (hi < 0) 855071d4279SBram Moolenaar hi = 0; 856071d4279SBram Moolenaar if (hi < lo) 857071d4279SBram Moolenaar hi = lo; 858071d4279SBram Moolenaar else if (hi > size) 859071d4279SBram Moolenaar hi = size; 860071d4279SBram Moolenaar 861ca8a4dfeSBram Moolenaar if (SetBufferLineList(self->buf, lo + start, hi + start, 862ca8a4dfeSBram Moolenaar val, &len_change) == FAIL) 863071d4279SBram Moolenaar return -1; 864071d4279SBram Moolenaar 865071d4279SBram Moolenaar if (new_end) 866071d4279SBram Moolenaar *new_end = end + len_change; 867071d4279SBram Moolenaar 868071d4279SBram Moolenaar return 0; 869071d4279SBram Moolenaar } 870071d4279SBram Moolenaar 871071d4279SBram Moolenaar static PySequenceMethods BufferAsSeq = { 8722c45e945SBram Moolenaar (PyInquiry) BufferLength, /* sq_length, len(x) */ 873071d4279SBram Moolenaar (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ 8742c45e945SBram Moolenaar (PyIntArgFunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */ 8752c45e945SBram Moolenaar (PyIntArgFunc) BufferItem, /* sq_item, x[i] */ 8762c45e945SBram Moolenaar (PyIntIntArgFunc) BufferSlice, /* sq_slice, x[i:j] */ 8772c45e945SBram Moolenaar (PyIntObjArgProc) BufferAssItem, /* sq_ass_item, x[i]=v */ 8782c45e945SBram Moolenaar (PyIntIntObjArgProc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */ 879071d4279SBram Moolenaar }; 880071d4279SBram Moolenaar 881071d4279SBram Moolenaar static PyTypeObject BufferType = { 882071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 883071d4279SBram Moolenaar 0, 884071d4279SBram Moolenaar "buffer", 885071d4279SBram Moolenaar sizeof(BufferObject), 886071d4279SBram Moolenaar 0, 887071d4279SBram Moolenaar 888071d4279SBram Moolenaar (destructor) BufferDestructor, /* tp_dealloc, refcount==0 */ 889071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 890071d4279SBram Moolenaar (getattrfunc) BufferGetattr, /* tp_getattr, x.attr */ 891071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 892071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 893071d4279SBram Moolenaar (reprfunc) BufferRepr, /* tp_repr, `x`, print x */ 894071d4279SBram Moolenaar 895071d4279SBram Moolenaar 0, /* as number */ 896071d4279SBram Moolenaar &BufferAsSeq, /* as sequence */ 897071d4279SBram Moolenaar 0, /* as mapping */ 898071d4279SBram Moolenaar 899071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 900071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 901071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 902071d4279SBram Moolenaar }; 903071d4279SBram Moolenaar 904071d4279SBram Moolenaar /* Buffer object - Implementation 905071d4279SBram Moolenaar */ 906071d4279SBram Moolenaar 907071d4279SBram Moolenaar static PyObject * 908071d4279SBram Moolenaar BufferNew(buf_T *buf) 909071d4279SBram Moolenaar { 910071d4279SBram Moolenaar /* We need to handle deletion of buffers underneath us. 911e344beadSBram Moolenaar * If we add a "b_python_ref" field to the buf_T structure, 912071d4279SBram Moolenaar * then we can get at it in buf_freeall() in vim. We then 913071d4279SBram Moolenaar * need to create only ONE Python object per buffer - if 914071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 915071d4279SBram Moolenaar * and return it. The (single) Python object referring to 916e344beadSBram Moolenaar * the buffer is stored in "b_python_ref". 917071d4279SBram Moolenaar * Question: what to do on a buf_freeall(). We'll probably 918071d4279SBram Moolenaar * have to either delete the Python object (DECREF it to 919071d4279SBram Moolenaar * zero - a bad idea, as it leaves dangling refs!) or 920071d4279SBram Moolenaar * set the buf_T * value to an invalid value (-1?), which 921071d4279SBram Moolenaar * means we need checks in all access functions... Bah. 922071d4279SBram Moolenaar */ 923071d4279SBram Moolenaar 924071d4279SBram Moolenaar BufferObject *self; 925071d4279SBram Moolenaar 926e344beadSBram Moolenaar if (buf->b_python_ref != NULL) 927071d4279SBram Moolenaar { 928e344beadSBram Moolenaar self = buf->b_python_ref; 929071d4279SBram Moolenaar Py_INCREF(self); 930071d4279SBram Moolenaar } 931071d4279SBram Moolenaar else 932071d4279SBram Moolenaar { 933071d4279SBram Moolenaar self = PyObject_NEW(BufferObject, &BufferType); 934071d4279SBram Moolenaar if (self == NULL) 935071d4279SBram Moolenaar return NULL; 936071d4279SBram Moolenaar self->buf = buf; 937e344beadSBram Moolenaar buf->b_python_ref = self; 938071d4279SBram Moolenaar } 939071d4279SBram Moolenaar 940071d4279SBram Moolenaar return (PyObject *)(self); 941071d4279SBram Moolenaar } 942071d4279SBram Moolenaar 943071d4279SBram Moolenaar static void 944071d4279SBram Moolenaar BufferDestructor(PyObject *self) 945071d4279SBram Moolenaar { 946071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 947071d4279SBram Moolenaar 948071d4279SBram Moolenaar if (this->buf && this->buf != INVALID_BUFFER_VALUE) 949e344beadSBram Moolenaar this->buf->b_python_ref = NULL; 950071d4279SBram Moolenaar 951658ada69SBram Moolenaar Py_DECREF(self); 952071d4279SBram Moolenaar } 953071d4279SBram Moolenaar 954071d4279SBram Moolenaar static PyObject * 955071d4279SBram Moolenaar BufferGetattr(PyObject *self, char *name) 956071d4279SBram Moolenaar { 957071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 958071d4279SBram Moolenaar 959071d4279SBram Moolenaar if (CheckBuffer(this)) 960071d4279SBram Moolenaar return NULL; 961071d4279SBram Moolenaar 962071d4279SBram Moolenaar if (strcmp(name, "name") == 0) 963071d4279SBram Moolenaar return Py_BuildValue("s", this->buf->b_ffname); 964071d4279SBram Moolenaar else if (strcmp(name, "number") == 0) 965e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum); 966071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 967071d4279SBram Moolenaar return Py_BuildValue("[ss]", "name", "number"); 968071d4279SBram Moolenaar else 969071d4279SBram Moolenaar return Py_FindMethod(BufferMethods, self, name); 970071d4279SBram Moolenaar } 971071d4279SBram Moolenaar 972071d4279SBram Moolenaar static PyObject * 973071d4279SBram Moolenaar BufferRepr(PyObject *self) 974071d4279SBram Moolenaar { 975555b280fSBram Moolenaar static char repr[100]; 976071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 977071d4279SBram Moolenaar 978071d4279SBram Moolenaar if (this->buf == INVALID_BUFFER_VALUE) 979071d4279SBram Moolenaar { 980e7cb9cf6SBram Moolenaar vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self)); 981071d4279SBram Moolenaar return PyString_FromString(repr); 982071d4279SBram Moolenaar } 983071d4279SBram Moolenaar else 984071d4279SBram Moolenaar { 985071d4279SBram Moolenaar char *name = (char *)this->buf->b_fname; 986e7cb9cf6SBram Moolenaar PyInt len; 987071d4279SBram Moolenaar 988071d4279SBram Moolenaar if (name == NULL) 989071d4279SBram Moolenaar name = ""; 990071d4279SBram Moolenaar len = strlen(name); 991071d4279SBram Moolenaar 992071d4279SBram Moolenaar if (len > 35) 993071d4279SBram Moolenaar name = name + (35 - len); 994071d4279SBram Moolenaar 995555b280fSBram Moolenaar vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name); 996071d4279SBram Moolenaar 997071d4279SBram Moolenaar return PyString_FromString(repr); 998071d4279SBram Moolenaar } 999071d4279SBram Moolenaar } 1000071d4279SBram Moolenaar 1001071d4279SBram Moolenaar /******************/ 1002071d4279SBram Moolenaar 10032c45e945SBram Moolenaar static PyInt 1004071d4279SBram Moolenaar BufferLength(PyObject *self) 1005071d4279SBram Moolenaar { 1006071d4279SBram Moolenaar /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ 1007071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1008071d4279SBram Moolenaar return -1; /* ??? */ 1009071d4279SBram Moolenaar 1010071d4279SBram Moolenaar return (((BufferObject *)(self))->buf->b_ml.ml_line_count); 1011071d4279SBram Moolenaar } 1012071d4279SBram Moolenaar 1013071d4279SBram Moolenaar static PyObject * 10142c45e945SBram Moolenaar BufferItem(PyObject *self, PyInt n) 1015071d4279SBram Moolenaar { 1016071d4279SBram Moolenaar return RBItem((BufferObject *)(self), n, 1, 1017071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1018071d4279SBram Moolenaar } 1019071d4279SBram Moolenaar 1020071d4279SBram Moolenaar static PyObject * 10212c45e945SBram Moolenaar BufferSlice(PyObject *self, PyInt lo, PyInt hi) 1022071d4279SBram Moolenaar { 1023071d4279SBram Moolenaar return RBSlice((BufferObject *)(self), lo, hi, 1, 1024071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1025071d4279SBram Moolenaar } 1026071d4279SBram Moolenaar 10272c45e945SBram Moolenaar static PyInt 10282c45e945SBram Moolenaar BufferAssItem(PyObject *self, PyInt n, PyObject *val) 1029071d4279SBram Moolenaar { 1030ca8a4dfeSBram Moolenaar return RBAsItem((BufferObject *)(self), n, val, 1, 1031e7cb9cf6SBram Moolenaar (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1032071d4279SBram Moolenaar NULL); 1033071d4279SBram Moolenaar } 1034071d4279SBram Moolenaar 10352c45e945SBram Moolenaar static PyInt 10362c45e945SBram Moolenaar BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) 1037071d4279SBram Moolenaar { 1038071d4279SBram Moolenaar return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, 1039e7cb9cf6SBram Moolenaar (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1040071d4279SBram Moolenaar NULL); 1041071d4279SBram Moolenaar } 1042071d4279SBram Moolenaar 1043071d4279SBram Moolenaar static PySequenceMethods RangeAsSeq = { 10442c45e945SBram Moolenaar (PyInquiry) RangeLength, /* sq_length, len(x) */ 1045071d4279SBram Moolenaar (binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */ 10462c45e945SBram Moolenaar (PyIntArgFunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */ 10472c45e945SBram Moolenaar (PyIntArgFunc) RangeItem, /* sq_item, x[i] */ 10482c45e945SBram Moolenaar (PyIntIntArgFunc) RangeSlice, /* sq_slice, x[i:j] */ 10492c45e945SBram Moolenaar (PyIntObjArgProc) RangeAssItem, /* sq_ass_item, x[i]=v */ 10502c45e945SBram Moolenaar (PyIntIntObjArgProc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */ 1051071d4279SBram Moolenaar }; 1052071d4279SBram Moolenaar 1053071d4279SBram Moolenaar /* Line range object - Implementation 1054071d4279SBram Moolenaar */ 1055071d4279SBram Moolenaar 1056071d4279SBram Moolenaar static void 1057071d4279SBram Moolenaar RangeDestructor(PyObject *self) 1058071d4279SBram Moolenaar { 1059071d4279SBram Moolenaar Py_DECREF(((RangeObject *)(self))->buf); 1060658ada69SBram Moolenaar Py_DECREF(self); 1061071d4279SBram Moolenaar } 1062071d4279SBram Moolenaar 1063071d4279SBram Moolenaar static PyObject * 1064071d4279SBram Moolenaar RangeGetattr(PyObject *self, char *name) 1065071d4279SBram Moolenaar { 1066071d4279SBram Moolenaar if (strcmp(name, "start") == 0) 1067e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start - 1); 1068071d4279SBram Moolenaar else if (strcmp(name, "end") == 0) 1069e7cb9cf6SBram Moolenaar return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1); 1070071d4279SBram Moolenaar else 1071071d4279SBram Moolenaar return Py_FindMethod(RangeMethods, self, name); 1072071d4279SBram Moolenaar } 1073071d4279SBram Moolenaar 1074071d4279SBram Moolenaar /****************/ 1075071d4279SBram Moolenaar 10762c45e945SBram Moolenaar static PyInt 10772c45e945SBram Moolenaar RangeAssItem(PyObject *self, PyInt n, PyObject *val) 1078071d4279SBram Moolenaar { 1079ca8a4dfeSBram Moolenaar return RBAsItem(((RangeObject *)(self))->buf, n, val, 1080071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1081071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1082071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1083071d4279SBram Moolenaar } 1084071d4279SBram Moolenaar 10852c45e945SBram Moolenaar static PyInt 10862c45e945SBram Moolenaar RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val) 1087071d4279SBram Moolenaar { 1088071d4279SBram Moolenaar return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, 1089071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1090071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1091071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1092071d4279SBram Moolenaar } 1093071d4279SBram Moolenaar 1094071d4279SBram Moolenaar /* Buffer list object - Definitions 1095071d4279SBram Moolenaar */ 1096071d4279SBram Moolenaar 1097071d4279SBram Moolenaar typedef struct 1098071d4279SBram Moolenaar { 1099071d4279SBram Moolenaar PyObject_HEAD 1100ca8a4dfeSBram Moolenaar } BufListObject; 1101071d4279SBram Moolenaar 1102071d4279SBram Moolenaar static PySequenceMethods BufListAsSeq = { 11032c45e945SBram Moolenaar (PyInquiry) BufListLength, /* sq_length, len(x) */ 1104071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 11052c45e945SBram Moolenaar (PyIntArgFunc) 0, /* sq_repeat, x*n */ 11062c45e945SBram Moolenaar (PyIntArgFunc) BufListItem, /* sq_item, x[i] */ 11072c45e945SBram Moolenaar (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ 11082c45e945SBram Moolenaar (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ 11092c45e945SBram Moolenaar (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ 1110071d4279SBram Moolenaar }; 1111071d4279SBram Moolenaar 1112071d4279SBram Moolenaar static PyTypeObject BufListType = { 1113071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1114071d4279SBram Moolenaar 0, 1115071d4279SBram Moolenaar "buffer list", 1116071d4279SBram Moolenaar sizeof(BufListObject), 1117071d4279SBram Moolenaar 0, 1118071d4279SBram Moolenaar 1119071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 1120071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1121071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 1122071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1123071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1124071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 1125071d4279SBram Moolenaar 1126071d4279SBram Moolenaar 0, /* as number */ 1127071d4279SBram Moolenaar &BufListAsSeq, /* as sequence */ 1128071d4279SBram Moolenaar 0, /* as mapping */ 1129071d4279SBram Moolenaar 1130071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1131071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1132071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1133071d4279SBram Moolenaar }; 1134071d4279SBram Moolenaar 1135071d4279SBram Moolenaar /* Window object - Definitions 1136071d4279SBram Moolenaar */ 1137071d4279SBram Moolenaar 1138071d4279SBram Moolenaar static struct PyMethodDef WindowMethods[] = { 1139071d4279SBram Moolenaar /* name, function, calling, documentation */ 1140071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1141071d4279SBram Moolenaar }; 1142071d4279SBram Moolenaar 1143071d4279SBram Moolenaar static PyTypeObject WindowType = { 1144071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1145071d4279SBram Moolenaar 0, 1146071d4279SBram Moolenaar "window", 1147071d4279SBram Moolenaar sizeof(WindowObject), 1148071d4279SBram Moolenaar 0, 1149071d4279SBram Moolenaar 1150071d4279SBram Moolenaar (destructor) WindowDestructor, /* tp_dealloc, refcount==0 */ 1151071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1152071d4279SBram Moolenaar (getattrfunc) WindowGetattr, /* tp_getattr, x.attr */ 1153071d4279SBram Moolenaar (setattrfunc) WindowSetattr, /* tp_setattr, x.attr=v */ 1154071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1155071d4279SBram Moolenaar (reprfunc) WindowRepr, /* tp_repr, `x`, print x */ 1156071d4279SBram Moolenaar 1157071d4279SBram Moolenaar 0, /* as number */ 1158071d4279SBram Moolenaar 0, /* as sequence */ 1159071d4279SBram Moolenaar 0, /* as mapping */ 1160071d4279SBram Moolenaar 1161071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1162071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1163071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1164071d4279SBram Moolenaar }; 1165071d4279SBram Moolenaar 1166071d4279SBram Moolenaar /* Window object - Implementation 1167071d4279SBram Moolenaar */ 1168071d4279SBram Moolenaar 1169071d4279SBram Moolenaar static PyObject * 1170071d4279SBram Moolenaar WindowNew(win_T *win) 1171071d4279SBram Moolenaar { 1172071d4279SBram Moolenaar /* We need to handle deletion of windows underneath us. 1173e344beadSBram Moolenaar * If we add a "w_python_ref" field to the win_T structure, 1174071d4279SBram Moolenaar * then we can get at it in win_free() in vim. We then 1175071d4279SBram Moolenaar * need to create only ONE Python object per window - if 1176071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 1177071d4279SBram Moolenaar * and return it. The (single) Python object referring to 1178e344beadSBram Moolenaar * the window is stored in "w_python_ref". 1179071d4279SBram Moolenaar * On a win_free() we set the Python object's win_T* field 1180071d4279SBram Moolenaar * to an invalid value. We trap all uses of a window 1181071d4279SBram Moolenaar * object, and reject them if the win_T* field is invalid. 1182071d4279SBram Moolenaar */ 1183071d4279SBram Moolenaar 1184071d4279SBram Moolenaar WindowObject *self; 1185071d4279SBram Moolenaar 1186e344beadSBram Moolenaar if (win->w_python_ref) 1187071d4279SBram Moolenaar { 1188e344beadSBram Moolenaar self = win->w_python_ref; 1189071d4279SBram Moolenaar Py_INCREF(self); 1190071d4279SBram Moolenaar } 1191071d4279SBram Moolenaar else 1192071d4279SBram Moolenaar { 1193071d4279SBram Moolenaar self = PyObject_NEW(WindowObject, &WindowType); 1194071d4279SBram Moolenaar if (self == NULL) 1195071d4279SBram Moolenaar return NULL; 1196071d4279SBram Moolenaar self->win = win; 1197e344beadSBram Moolenaar win->w_python_ref = self; 1198071d4279SBram Moolenaar } 1199071d4279SBram Moolenaar 1200071d4279SBram Moolenaar return (PyObject *)(self); 1201071d4279SBram Moolenaar } 1202071d4279SBram Moolenaar 1203071d4279SBram Moolenaar static void 1204071d4279SBram Moolenaar WindowDestructor(PyObject *self) 1205071d4279SBram Moolenaar { 1206071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1207071d4279SBram Moolenaar 1208071d4279SBram Moolenaar if (this->win && this->win != INVALID_WINDOW_VALUE) 1209e344beadSBram Moolenaar this->win->w_python_ref = NULL; 1210071d4279SBram Moolenaar 1211658ada69SBram Moolenaar Py_DECREF(self); 1212071d4279SBram Moolenaar } 1213071d4279SBram Moolenaar 1214071d4279SBram Moolenaar static PyObject * 1215071d4279SBram Moolenaar WindowGetattr(PyObject *self, char *name) 1216071d4279SBram Moolenaar { 1217071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1218071d4279SBram Moolenaar 1219071d4279SBram Moolenaar if (CheckWindow(this)) 1220071d4279SBram Moolenaar return NULL; 1221071d4279SBram Moolenaar 1222071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1223071d4279SBram Moolenaar return (PyObject *)BufferNew(this->win->w_buffer); 1224071d4279SBram Moolenaar else if (strcmp(name, "cursor") == 0) 1225071d4279SBram Moolenaar { 1226071d4279SBram Moolenaar pos_T *pos = &this->win->w_cursor; 1227071d4279SBram Moolenaar 1228071d4279SBram Moolenaar return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col)); 1229071d4279SBram Moolenaar } 1230071d4279SBram Moolenaar else if (strcmp(name, "height") == 0) 1231071d4279SBram Moolenaar return Py_BuildValue("l", (long)(this->win->w_height)); 1232071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT 1233071d4279SBram Moolenaar else if (strcmp(name, "width") == 0) 1234071d4279SBram Moolenaar return Py_BuildValue("l", (long)(W_WIDTH(this->win))); 1235071d4279SBram Moolenaar #endif 1236071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1237071d4279SBram Moolenaar return Py_BuildValue("[sss]", "buffer", "cursor", "height"); 1238071d4279SBram Moolenaar else 1239071d4279SBram Moolenaar return Py_FindMethod(WindowMethods, self, name); 1240071d4279SBram Moolenaar } 1241071d4279SBram Moolenaar 1242071d4279SBram Moolenaar /* Window list object - Definitions 1243071d4279SBram Moolenaar */ 1244071d4279SBram Moolenaar 1245071d4279SBram Moolenaar typedef struct 1246071d4279SBram Moolenaar { 1247071d4279SBram Moolenaar PyObject_HEAD 1248071d4279SBram Moolenaar } 1249071d4279SBram Moolenaar WinListObject; 1250071d4279SBram Moolenaar 1251071d4279SBram Moolenaar static PySequenceMethods WinListAsSeq = { 12522c45e945SBram Moolenaar (PyInquiry) WinListLength, /* sq_length, len(x) */ 1253071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 12542c45e945SBram Moolenaar (PyIntArgFunc) 0, /* sq_repeat, x*n */ 12552c45e945SBram Moolenaar (PyIntArgFunc) WinListItem, /* sq_item, x[i] */ 12562c45e945SBram Moolenaar (PyIntIntArgFunc) 0, /* sq_slice, x[i:j] */ 12572c45e945SBram Moolenaar (PyIntObjArgProc) 0, /* sq_ass_item, x[i]=v */ 12582c45e945SBram Moolenaar (PyIntIntObjArgProc) 0, /* sq_ass_slice, x[i:j]=v */ 1259071d4279SBram Moolenaar }; 1260071d4279SBram Moolenaar 1261071d4279SBram Moolenaar static PyTypeObject WinListType = { 1262071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1263071d4279SBram Moolenaar 0, 1264071d4279SBram Moolenaar "window list", 1265071d4279SBram Moolenaar sizeof(WinListObject), 1266071d4279SBram Moolenaar 0, 1267071d4279SBram Moolenaar 1268071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 1269071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1270071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 1271071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1272071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1273071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 1274071d4279SBram Moolenaar 1275071d4279SBram Moolenaar 0, /* as number */ 1276071d4279SBram Moolenaar &WinListAsSeq, /* as sequence */ 1277071d4279SBram Moolenaar 0, /* as mapping */ 1278071d4279SBram Moolenaar 1279071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1280071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1281071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1282071d4279SBram Moolenaar }; 1283071d4279SBram Moolenaar 1284071d4279SBram Moolenaar /* Current items object - Definitions 1285071d4279SBram Moolenaar */ 1286071d4279SBram Moolenaar 1287071d4279SBram Moolenaar typedef struct 1288071d4279SBram Moolenaar { 1289071d4279SBram Moolenaar PyObject_HEAD 1290ca8a4dfeSBram Moolenaar } CurrentObject; 1291071d4279SBram Moolenaar 1292071d4279SBram Moolenaar static PyTypeObject CurrentType = { 1293071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1294071d4279SBram Moolenaar 0, 1295071d4279SBram Moolenaar "current data", 1296071d4279SBram Moolenaar sizeof(CurrentObject), 1297071d4279SBram Moolenaar 0, 1298071d4279SBram Moolenaar 1299071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 1300071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1301071d4279SBram Moolenaar (getattrfunc) CurrentGetattr, /* tp_getattr, x.attr */ 1302071d4279SBram Moolenaar (setattrfunc) CurrentSetattr, /* tp_setattr, x.attr=v */ 1303071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1304071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 1305071d4279SBram Moolenaar 1306071d4279SBram Moolenaar 0, /* as number */ 1307071d4279SBram Moolenaar 0, /* as sequence */ 1308071d4279SBram Moolenaar 0, /* as mapping */ 1309071d4279SBram Moolenaar 1310071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1311071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1312071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1313071d4279SBram Moolenaar }; 1314071d4279SBram Moolenaar 1315071d4279SBram Moolenaar /* Current items object - Implementation 1316071d4279SBram Moolenaar */ 1317071d4279SBram Moolenaar static PyObject * 13184bdbbf70SBram Moolenaar CurrentGetattr(PyObject *self UNUSED, char *name) 1319071d4279SBram Moolenaar { 1320071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1321071d4279SBram Moolenaar return (PyObject *)BufferNew(curbuf); 1322071d4279SBram Moolenaar else if (strcmp(name, "window") == 0) 1323071d4279SBram Moolenaar return (PyObject *)WindowNew(curwin); 1324071d4279SBram Moolenaar else if (strcmp(name, "line") == 0) 1325e7cb9cf6SBram Moolenaar return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum); 1326071d4279SBram Moolenaar else if (strcmp(name, "range") == 0) 1327071d4279SBram Moolenaar return RangeNew(curbuf, RangeStart, RangeEnd); 1328071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1329071d4279SBram Moolenaar return Py_BuildValue("[ssss]", "buffer", "window", "line", "range"); 1330071d4279SBram Moolenaar else 1331071d4279SBram Moolenaar { 1332071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 1333071d4279SBram Moolenaar return NULL; 1334071d4279SBram Moolenaar } 1335071d4279SBram Moolenaar } 1336071d4279SBram Moolenaar 1337071d4279SBram Moolenaar static int 13384bdbbf70SBram Moolenaar CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value) 1339071d4279SBram Moolenaar { 1340071d4279SBram Moolenaar if (strcmp(name, "line") == 0) 1341071d4279SBram Moolenaar { 1342e7cb9cf6SBram Moolenaar if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL) 1343071d4279SBram Moolenaar return -1; 1344071d4279SBram Moolenaar 1345071d4279SBram Moolenaar return 0; 1346071d4279SBram Moolenaar } 1347071d4279SBram Moolenaar else 1348071d4279SBram Moolenaar { 1349071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 1350071d4279SBram Moolenaar return -1; 1351071d4279SBram Moolenaar } 1352071d4279SBram Moolenaar } 1353071d4279SBram Moolenaar 1354071d4279SBram Moolenaar /* External interface 1355071d4279SBram Moolenaar */ 1356071d4279SBram Moolenaar 1357071d4279SBram Moolenaar void 1358071d4279SBram Moolenaar python_buffer_free(buf_T *buf) 1359071d4279SBram Moolenaar { 1360e344beadSBram Moolenaar if (buf->b_python_ref != NULL) 1361071d4279SBram Moolenaar { 1362e344beadSBram Moolenaar BufferObject *bp = buf->b_python_ref; 1363071d4279SBram Moolenaar bp->buf = INVALID_BUFFER_VALUE; 1364e344beadSBram Moolenaar buf->b_python_ref = NULL; 1365071d4279SBram Moolenaar } 1366071d4279SBram Moolenaar } 1367071d4279SBram Moolenaar 1368071d4279SBram Moolenaar #if defined(FEAT_WINDOWS) || defined(PROTO) 1369071d4279SBram Moolenaar void 1370071d4279SBram Moolenaar python_window_free(win_T *win) 1371071d4279SBram Moolenaar { 1372e344beadSBram Moolenaar if (win->w_python_ref != NULL) 1373071d4279SBram Moolenaar { 1374e344beadSBram Moolenaar WindowObject *wp = win->w_python_ref; 1375071d4279SBram Moolenaar wp->win = INVALID_WINDOW_VALUE; 1376e344beadSBram Moolenaar win->w_python_ref = NULL; 1377071d4279SBram Moolenaar } 1378071d4279SBram Moolenaar } 1379071d4279SBram Moolenaar #endif 1380071d4279SBram Moolenaar 1381071d4279SBram Moolenaar static BufListObject TheBufferList = 1382071d4279SBram Moolenaar { 1383071d4279SBram Moolenaar PyObject_HEAD_INIT(&BufListType) 1384071d4279SBram Moolenaar }; 1385071d4279SBram Moolenaar 1386071d4279SBram Moolenaar static WinListObject TheWindowList = 1387071d4279SBram Moolenaar { 1388071d4279SBram Moolenaar PyObject_HEAD_INIT(&WinListType) 1389071d4279SBram Moolenaar }; 1390071d4279SBram Moolenaar 1391071d4279SBram Moolenaar static CurrentObject TheCurrent = 1392071d4279SBram Moolenaar { 1393071d4279SBram Moolenaar PyObject_HEAD_INIT(&CurrentType) 1394071d4279SBram Moolenaar }; 1395071d4279SBram Moolenaar 1396071d4279SBram Moolenaar static int 1397071d4279SBram Moolenaar PythonMod_Init(void) 1398071d4279SBram Moolenaar { 1399071d4279SBram Moolenaar PyObject *mod; 1400071d4279SBram Moolenaar PyObject *dict; 14019774ecc8SBram Moolenaar /* The special value is removed from sys.path in Python_Init(). */ 14029774ecc8SBram Moolenaar static char *(argv[2]) = {"/must>not&exist/foo", NULL}; 1403071d4279SBram Moolenaar 1404071d4279SBram Moolenaar /* Fixups... */ 1405*21377c8dSBram Moolenaar PyType_Ready(&BufferType); 1406*21377c8dSBram Moolenaar PyType_Ready(&RangeType); 1407*21377c8dSBram Moolenaar PyType_Ready(&WindowType); 1408*21377c8dSBram Moolenaar PyType_Ready(&BufListType); 1409*21377c8dSBram Moolenaar PyType_Ready(&WinListType); 1410*21377c8dSBram Moolenaar PyType_Ready(&CurrentType); 1411071d4279SBram Moolenaar 1412071d4279SBram Moolenaar /* Set sys.argv[] to avoid a crash in warn(). */ 1413071d4279SBram Moolenaar PySys_SetArgv(1, argv); 1414071d4279SBram Moolenaar 1415e7cb9cf6SBram Moolenaar mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION); 1416071d4279SBram Moolenaar dict = PyModule_GetDict(mod); 1417071d4279SBram Moolenaar 1418071d4279SBram Moolenaar VimError = Py_BuildValue("s", "vim.error"); 1419071d4279SBram Moolenaar 1420071d4279SBram Moolenaar PyDict_SetItemString(dict, "error", VimError); 14217df2d662SBram Moolenaar PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferList); 14227df2d662SBram Moolenaar PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent); 14237df2d662SBram Moolenaar PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList); 1424071d4279SBram Moolenaar 1425071d4279SBram Moolenaar if (PyErr_Occurred()) 1426071d4279SBram Moolenaar return -1; 1427071d4279SBram Moolenaar 1428071d4279SBram Moolenaar return 0; 1429071d4279SBram Moolenaar } 1430071d4279SBram Moolenaar 1431071d4279SBram Moolenaar /************************************************************************* 1432071d4279SBram Moolenaar * 4. Utility functions for handling the interface between Vim and Python. 1433071d4279SBram Moolenaar */ 1434071d4279SBram Moolenaar 1435071d4279SBram Moolenaar /* Replace a range of lines in the specified buffer. The line numbers are in 1436071d4279SBram Moolenaar * Vim format (1-based). The range is from lo up to, but not including, hi. 1437071d4279SBram Moolenaar * The replacement lines are given as a Python list of string objects. The 1438071d4279SBram Moolenaar * list is checked for validity and correct format. Errors are returned as a 1439071d4279SBram Moolenaar * value of FAIL. The return value is OK on success. 1440071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 1441071d4279SBram Moolenaar * is set to the change in the buffer length. 1442071d4279SBram Moolenaar */ 1443071d4279SBram Moolenaar static int 1444e7cb9cf6SBram Moolenaar SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change) 1445071d4279SBram Moolenaar { 1446071d4279SBram Moolenaar /* First of all, we check the thpe of the supplied Python object. 1447071d4279SBram Moolenaar * There are three cases: 1448071d4279SBram Moolenaar * 1. NULL, or None - this is a deletion. 1449071d4279SBram Moolenaar * 2. A list - this is a replacement. 1450071d4279SBram Moolenaar * 3. Anything else - this is an error. 1451071d4279SBram Moolenaar */ 1452071d4279SBram Moolenaar if (list == Py_None || list == NULL) 1453071d4279SBram Moolenaar { 14542c45e945SBram Moolenaar PyInt i; 1455e7cb9cf6SBram Moolenaar PyInt n = (int)(hi - lo); 1456071d4279SBram Moolenaar buf_T *savebuf = curbuf; 1457071d4279SBram Moolenaar 1458071d4279SBram Moolenaar PyErr_Clear(); 1459071d4279SBram Moolenaar curbuf = buf; 1460071d4279SBram Moolenaar 1461071d4279SBram Moolenaar if (u_savedel((linenr_T)lo, (long)n) == FAIL) 1462071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 1463071d4279SBram Moolenaar else 1464071d4279SBram Moolenaar { 1465071d4279SBram Moolenaar for (i = 0; i < n; ++i) 1466071d4279SBram Moolenaar { 1467071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 1468071d4279SBram Moolenaar { 1469071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 1470071d4279SBram Moolenaar break; 1471071d4279SBram Moolenaar } 1472071d4279SBram Moolenaar } 1473071d4279SBram Moolenaar if (buf == curwin->w_buffer) 1474e7cb9cf6SBram Moolenaar py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n); 1475cdcaa589SBram Moolenaar deleted_lines_mark((linenr_T)lo, (long)i); 1476071d4279SBram Moolenaar } 1477071d4279SBram Moolenaar 1478071d4279SBram Moolenaar curbuf = savebuf; 1479071d4279SBram Moolenaar 1480071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 1481071d4279SBram Moolenaar return FAIL; 1482071d4279SBram Moolenaar 1483071d4279SBram Moolenaar if (len_change) 1484071d4279SBram Moolenaar *len_change = -n; 1485071d4279SBram Moolenaar 1486071d4279SBram Moolenaar return OK; 1487071d4279SBram Moolenaar } 1488071d4279SBram Moolenaar else if (PyList_Check(list)) 1489071d4279SBram Moolenaar { 14902c45e945SBram Moolenaar PyInt i; 14912c45e945SBram Moolenaar PyInt new_len = PyList_Size(list); 14922c45e945SBram Moolenaar PyInt old_len = hi - lo; 1493e7cb9cf6SBram Moolenaar PyInt extra = 0; /* lines added to text, can be negative */ 1494071d4279SBram Moolenaar char **array; 1495071d4279SBram Moolenaar buf_T *savebuf; 1496071d4279SBram Moolenaar 1497071d4279SBram Moolenaar if (new_len == 0) /* avoid allocating zero bytes */ 1498071d4279SBram Moolenaar array = NULL; 1499071d4279SBram Moolenaar else 1500071d4279SBram Moolenaar { 1501071d4279SBram Moolenaar array = (char **)alloc((unsigned)(new_len * sizeof(char *))); 1502071d4279SBram Moolenaar if (array == NULL) 1503071d4279SBram Moolenaar { 1504071d4279SBram Moolenaar PyErr_NoMemory(); 1505071d4279SBram Moolenaar return FAIL; 1506071d4279SBram Moolenaar } 1507071d4279SBram Moolenaar } 1508071d4279SBram Moolenaar 1509071d4279SBram Moolenaar for (i = 0; i < new_len; ++i) 1510071d4279SBram Moolenaar { 1511071d4279SBram Moolenaar PyObject *line = PyList_GetItem(list, i); 1512071d4279SBram Moolenaar 1513071d4279SBram Moolenaar array[i] = StringToLine(line); 1514071d4279SBram Moolenaar if (array[i] == NULL) 1515071d4279SBram Moolenaar { 1516071d4279SBram Moolenaar while (i) 1517071d4279SBram Moolenaar vim_free(array[--i]); 1518071d4279SBram Moolenaar vim_free(array); 1519071d4279SBram Moolenaar return FAIL; 1520071d4279SBram Moolenaar } 1521071d4279SBram Moolenaar } 1522071d4279SBram Moolenaar 1523071d4279SBram Moolenaar savebuf = curbuf; 1524071d4279SBram Moolenaar 1525071d4279SBram Moolenaar PyErr_Clear(); 1526071d4279SBram Moolenaar curbuf = buf; 1527071d4279SBram Moolenaar 1528071d4279SBram Moolenaar if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) 1529071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 1530071d4279SBram Moolenaar 1531071d4279SBram Moolenaar /* If the size of the range is reducing (ie, new_len < old_len) we 1532071d4279SBram Moolenaar * need to delete some old_len. We do this at the start, by 1533071d4279SBram Moolenaar * repeatedly deleting line "lo". 1534071d4279SBram Moolenaar */ 1535071d4279SBram Moolenaar if (!PyErr_Occurred()) 1536071d4279SBram Moolenaar { 1537071d4279SBram Moolenaar for (i = 0; i < old_len - new_len; ++i) 1538071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 1539071d4279SBram Moolenaar { 1540071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 1541071d4279SBram Moolenaar break; 1542071d4279SBram Moolenaar } 1543071d4279SBram Moolenaar extra -= i; 1544071d4279SBram Moolenaar } 1545071d4279SBram Moolenaar 1546071d4279SBram Moolenaar /* For as long as possible, replace the existing old_len with the 1547071d4279SBram Moolenaar * new old_len. This is a more efficient operation, as it requires 1548071d4279SBram Moolenaar * less memory allocation and freeing. 1549071d4279SBram Moolenaar */ 1550071d4279SBram Moolenaar if (!PyErr_Occurred()) 1551071d4279SBram Moolenaar { 1552071d4279SBram Moolenaar for (i = 0; i < old_len && i < new_len; ++i) 1553071d4279SBram Moolenaar if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) 1554071d4279SBram Moolenaar == FAIL) 1555071d4279SBram Moolenaar { 1556071d4279SBram Moolenaar PyErr_SetVim(_("cannot replace line")); 1557071d4279SBram Moolenaar break; 1558071d4279SBram Moolenaar } 1559071d4279SBram Moolenaar } 1560071d4279SBram Moolenaar else 1561071d4279SBram Moolenaar i = 0; 1562071d4279SBram Moolenaar 1563071d4279SBram Moolenaar /* Now we may need to insert the remaining new old_len. If we do, we 1564071d4279SBram Moolenaar * must free the strings as we finish with them (we can't pass the 1565071d4279SBram Moolenaar * responsibility to vim in this case). 1566071d4279SBram Moolenaar */ 1567071d4279SBram Moolenaar if (!PyErr_Occurred()) 1568071d4279SBram Moolenaar { 1569071d4279SBram Moolenaar while (i < new_len) 1570071d4279SBram Moolenaar { 1571071d4279SBram Moolenaar if (ml_append((linenr_T)(lo + i - 1), 1572071d4279SBram Moolenaar (char_u *)array[i], 0, FALSE) == FAIL) 1573071d4279SBram Moolenaar { 1574071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 1575071d4279SBram Moolenaar break; 1576071d4279SBram Moolenaar } 1577071d4279SBram Moolenaar vim_free(array[i]); 1578071d4279SBram Moolenaar ++i; 1579071d4279SBram Moolenaar ++extra; 1580071d4279SBram Moolenaar } 1581071d4279SBram Moolenaar } 1582071d4279SBram Moolenaar 1583071d4279SBram Moolenaar /* Free any left-over old_len, as a result of an error */ 1584071d4279SBram Moolenaar while (i < new_len) 1585071d4279SBram Moolenaar { 1586071d4279SBram Moolenaar vim_free(array[i]); 1587071d4279SBram Moolenaar ++i; 1588071d4279SBram Moolenaar } 1589071d4279SBram Moolenaar 1590071d4279SBram Moolenaar /* Free the array of old_len. All of its contents have now 1591071d4279SBram Moolenaar * been dealt with (either freed, or the responsibility passed 1592071d4279SBram Moolenaar * to vim. 1593071d4279SBram Moolenaar */ 1594071d4279SBram Moolenaar vim_free(array); 1595071d4279SBram Moolenaar 1596071d4279SBram Moolenaar /* Adjust marks. Invalidate any which lie in the 1597071d4279SBram Moolenaar * changed range, and move any in the remainder of the buffer. 1598071d4279SBram Moolenaar */ 1599071d4279SBram Moolenaar mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), 1600071d4279SBram Moolenaar (long)MAXLNUM, (long)extra); 1601071d4279SBram Moolenaar changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); 1602071d4279SBram Moolenaar 1603071d4279SBram Moolenaar if (buf == curwin->w_buffer) 1604e7cb9cf6SBram Moolenaar py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra); 1605071d4279SBram Moolenaar 1606071d4279SBram Moolenaar curbuf = savebuf; 1607071d4279SBram Moolenaar 1608071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 1609071d4279SBram Moolenaar return FAIL; 1610071d4279SBram Moolenaar 1611071d4279SBram Moolenaar if (len_change) 1612071d4279SBram Moolenaar *len_change = new_len - old_len; 1613071d4279SBram Moolenaar 1614071d4279SBram Moolenaar return OK; 1615071d4279SBram Moolenaar } 1616071d4279SBram Moolenaar else 1617071d4279SBram Moolenaar { 1618071d4279SBram Moolenaar PyErr_BadArgument(); 1619071d4279SBram Moolenaar return FAIL; 1620071d4279SBram Moolenaar } 1621071d4279SBram Moolenaar } 1622071d4279SBram Moolenaar 1623071d4279SBram Moolenaar /* Convert a Vim line into a Python string. 1624071d4279SBram Moolenaar * All internal newlines are replaced by null characters. 1625071d4279SBram Moolenaar * 1626071d4279SBram Moolenaar * On errors, the Python exception data is set, and NULL is returned. 1627071d4279SBram Moolenaar */ 1628071d4279SBram Moolenaar static PyObject * 1629071d4279SBram Moolenaar LineToString(const char *str) 1630071d4279SBram Moolenaar { 1631071d4279SBram Moolenaar PyObject *result; 16322c45e945SBram Moolenaar PyInt len = strlen(str); 1633071d4279SBram Moolenaar char *p; 1634071d4279SBram Moolenaar 1635071d4279SBram Moolenaar /* Allocate an Python string object, with uninitialised contents. We 1636071d4279SBram Moolenaar * must do it this way, so that we can modify the string in place 1637071d4279SBram Moolenaar * later. See the Python source, Objects/stringobject.c for details. 1638071d4279SBram Moolenaar */ 1639071d4279SBram Moolenaar result = PyString_FromStringAndSize(NULL, len); 1640071d4279SBram Moolenaar if (result == NULL) 1641071d4279SBram Moolenaar return NULL; 1642071d4279SBram Moolenaar 1643071d4279SBram Moolenaar p = PyString_AsString(result); 1644071d4279SBram Moolenaar 1645071d4279SBram Moolenaar while (*str) 1646071d4279SBram Moolenaar { 1647071d4279SBram Moolenaar if (*str == '\n') 1648071d4279SBram Moolenaar *p = '\0'; 1649071d4279SBram Moolenaar else 1650071d4279SBram Moolenaar *p = *str; 1651071d4279SBram Moolenaar 1652071d4279SBram Moolenaar ++p; 1653071d4279SBram Moolenaar ++str; 1654071d4279SBram Moolenaar } 1655071d4279SBram Moolenaar 1656071d4279SBram Moolenaar return result; 1657071d4279SBram Moolenaar } 1658071d4279SBram Moolenaar 1659071d4279SBram Moolenaar 1660071d4279SBram Moolenaar /* Don't generate a prototype for the next function, it generates an error on 1661071d4279SBram Moolenaar * newer Python versions. */ 1662071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ && !defined(PROTO) 1663071d4279SBram Moolenaar 1664071d4279SBram Moolenaar char * 1665071d4279SBram Moolenaar Py_GetProgramName(void) 1666071d4279SBram Moolenaar { 1667071d4279SBram Moolenaar return "vim"; 1668071d4279SBram Moolenaar } 1669071d4279SBram Moolenaar #endif /* Python 1.4 */ 1670170bf1aeSBram Moolenaar 1671170bf1aeSBram Moolenaar static void 1672170bf1aeSBram Moolenaar init_structs(void) 1673170bf1aeSBram Moolenaar { 1674170bf1aeSBram Moolenaar vim_memset(&OutputType, 0, sizeof(OutputType)); 1675170bf1aeSBram Moolenaar OutputType.tp_name = "message"; 1676170bf1aeSBram Moolenaar OutputType.tp_basicsize = sizeof(OutputObject); 1677170bf1aeSBram Moolenaar OutputType.tp_getattr = OutputGetattr; 1678170bf1aeSBram Moolenaar OutputType.tp_setattr = OutputSetattr; 1679ca8a4dfeSBram Moolenaar 1680ca8a4dfeSBram Moolenaar vim_memset(&RangeType, 0, sizeof(RangeType)); 1681ca8a4dfeSBram Moolenaar RangeType.tp_name = "range"; 1682ca8a4dfeSBram Moolenaar RangeType.tp_basicsize = sizeof(RangeObject); 1683ca8a4dfeSBram Moolenaar RangeType.tp_dealloc = RangeDestructor; 1684ca8a4dfeSBram Moolenaar RangeType.tp_getattr = RangeGetattr; 1685ca8a4dfeSBram Moolenaar RangeType.tp_repr = RangeRepr; 1686ca8a4dfeSBram Moolenaar RangeType.tp_as_sequence = &RangeAsSeq; 1687170bf1aeSBram Moolenaar } 1688