1*071d4279SBram Moolenaar /* vi:set ts=8 sts=4 sw=4: 2*071d4279SBram Moolenaar * 3*071d4279SBram Moolenaar * VIM - Vi IMproved by Bram Moolenaar 4*071d4279SBram Moolenaar * 5*071d4279SBram Moolenaar * Do ":help uganda" in Vim to read copying and usage conditions. 6*071d4279SBram Moolenaar * Do ":help credits" in Vim to see a list of people who contributed. 7*071d4279SBram Moolenaar * See README.txt for an overview of the Vim source code. 8*071d4279SBram Moolenaar */ 9*071d4279SBram Moolenaar /* 10*071d4279SBram Moolenaar * Python extensions by Paul Moore. 11*071d4279SBram Moolenaar * Changes for Unix by David Leonard. 12*071d4279SBram Moolenaar * 13*071d4279SBram Moolenaar * This consists of four parts: 14*071d4279SBram Moolenaar * 1. Python interpreter main program 15*071d4279SBram Moolenaar * 2. Python output stream: writes output via [e]msg(). 16*071d4279SBram Moolenaar * 3. Implementation of the Vim module for Python 17*071d4279SBram Moolenaar * 4. Utility functions for handling the interface between Vim and Python. 18*071d4279SBram Moolenaar */ 19*071d4279SBram Moolenaar 20*071d4279SBram Moolenaar #include "vim.h" 21*071d4279SBram Moolenaar 22*071d4279SBram Moolenaar #include <stdio.h> 23*071d4279SBram Moolenaar #include <stdarg.h> 24*071d4279SBram Moolenaar #include <limits.h> 25*071d4279SBram Moolenaar 26*071d4279SBram Moolenaar /* Python.h defines _POSIX_THREADS itself (if needed) */ 27*071d4279SBram Moolenaar #ifdef _POSIX_THREADS 28*071d4279SBram Moolenaar # undef _POSIX_THREADS 29*071d4279SBram Moolenaar #endif 30*071d4279SBram Moolenaar 31*071d4279SBram Moolenaar #if defined(_WIN32) && defined (HAVE_FCNTL_H) 32*071d4279SBram Moolenaar # undef HAVE_FCNTL_H 33*071d4279SBram Moolenaar #endif 34*071d4279SBram Moolenaar 35*071d4279SBram Moolenaar #ifdef _DEBUG 36*071d4279SBram Moolenaar # undef _DEBUG 37*071d4279SBram Moolenaar #endif 38*071d4279SBram Moolenaar 39*071d4279SBram Moolenaar #ifdef HAVE_STDARG_H 40*071d4279SBram Moolenaar # undef HAVE_STDARG_H /* Python's config.h defines it as well. */ 41*071d4279SBram Moolenaar #endif 42*071d4279SBram Moolenaar 43*071d4279SBram Moolenaar #include <Python.h> 44*071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 45*071d4279SBram Moolenaar # include "macglue.h" 46*071d4279SBram Moolenaar # include <CodeFragments.h> 47*071d4279SBram Moolenaar #endif 48*071d4279SBram Moolenaar #undef main /* Defined in python.h - aargh */ 49*071d4279SBram Moolenaar #undef HAVE_FCNTL_H /* Clash with os_win32.h */ 50*071d4279SBram Moolenaar 51*071d4279SBram Moolenaar #if !defined(FEAT_PYTHON) && defined(PROTO) 52*071d4279SBram Moolenaar /* Use this to be able to generate prototypes without python being used. */ 53*071d4279SBram Moolenaar # define PyObject int 54*071d4279SBram Moolenaar # define PyThreadState int 55*071d4279SBram Moolenaar # define PyTypeObject int 56*071d4279SBram Moolenaar struct PyMethodDef { int a; }; 57*071d4279SBram Moolenaar # define PySequenceMethods int 58*071d4279SBram Moolenaar #endif 59*071d4279SBram Moolenaar 60*071d4279SBram Moolenaar /* Parser flags */ 61*071d4279SBram Moolenaar #define single_input 256 62*071d4279SBram Moolenaar #define file_input 257 63*071d4279SBram Moolenaar #define eval_input 258 64*071d4279SBram Moolenaar 65*071d4279SBram Moolenaar #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x020300F0 66*071d4279SBram Moolenaar /* Python 2.3: can invoke ":python" recursively. */ 67*071d4279SBram Moolenaar # define PY_CAN_RECURSE 68*071d4279SBram Moolenaar #endif 69*071d4279SBram Moolenaar 70*071d4279SBram Moolenaar #if defined(DYNAMIC_PYTHON) || defined(PROTO) 71*071d4279SBram Moolenaar # ifndef DYNAMIC_PYTHON 72*071d4279SBram Moolenaar # define HINSTANCE int /* for generating prototypes */ 73*071d4279SBram Moolenaar # endif 74*071d4279SBram Moolenaar 75*071d4279SBram Moolenaar /* 76*071d4279SBram Moolenaar * Wrapper defines 77*071d4279SBram Moolenaar */ 78*071d4279SBram Moolenaar # define PyArg_Parse dll_PyArg_Parse 79*071d4279SBram Moolenaar # define PyArg_ParseTuple dll_PyArg_ParseTuple 80*071d4279SBram Moolenaar # define PyDict_SetItemString dll_PyDict_SetItemString 81*071d4279SBram Moolenaar # define PyErr_BadArgument dll_PyErr_BadArgument 82*071d4279SBram Moolenaar # define PyErr_Clear dll_PyErr_Clear 83*071d4279SBram Moolenaar # define PyErr_NoMemory dll_PyErr_NoMemory 84*071d4279SBram Moolenaar # define PyErr_Occurred dll_PyErr_Occurred 85*071d4279SBram Moolenaar # define PyErr_SetNone dll_PyErr_SetNone 86*071d4279SBram Moolenaar # define PyErr_SetString dll_PyErr_SetString 87*071d4279SBram Moolenaar # define PyEval_InitThreads dll_PyEval_InitThreads 88*071d4279SBram Moolenaar # define PyEval_RestoreThread dll_PyEval_RestoreThread 89*071d4279SBram Moolenaar # define PyEval_SaveThread dll_PyEval_SaveThread 90*071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 91*071d4279SBram Moolenaar # define PyGILState_Ensure dll_PyGILState_Ensure 92*071d4279SBram Moolenaar # define PyGILState_Release dll_PyGILState_Release 93*071d4279SBram Moolenaar # endif 94*071d4279SBram Moolenaar # define PyInt_AsLong dll_PyInt_AsLong 95*071d4279SBram Moolenaar # define PyInt_FromLong dll_PyInt_FromLong 96*071d4279SBram Moolenaar # define PyInt_Type (*dll_PyInt_Type) 97*071d4279SBram Moolenaar # define PyList_GetItem dll_PyList_GetItem 98*071d4279SBram Moolenaar # define PyList_New dll_PyList_New 99*071d4279SBram Moolenaar # define PyList_SetItem dll_PyList_SetItem 100*071d4279SBram Moolenaar # define PyList_Size dll_PyList_Size 101*071d4279SBram Moolenaar # define PyList_Type (*dll_PyList_Type) 102*071d4279SBram Moolenaar # define PyImport_ImportModule dll_PyImport_ImportModule 103*071d4279SBram Moolenaar # define PyDict_GetItemString dll_PyDict_GetItemString 104*071d4279SBram Moolenaar # define PyModule_GetDict dll_PyModule_GetDict 105*071d4279SBram Moolenaar # define PyRun_SimpleString dll_PyRun_SimpleString 106*071d4279SBram Moolenaar # define PyString_AsString dll_PyString_AsString 107*071d4279SBram Moolenaar # define PyString_FromString dll_PyString_FromString 108*071d4279SBram Moolenaar # define PyString_FromStringAndSize dll_PyString_FromStringAndSize 109*071d4279SBram Moolenaar # define PyString_Size dll_PyString_Size 110*071d4279SBram Moolenaar # define PyString_Type (*dll_PyString_Type) 111*071d4279SBram Moolenaar # define PySys_SetObject dll_PySys_SetObject 112*071d4279SBram Moolenaar # define PySys_SetArgv dll_PySys_SetArgv 113*071d4279SBram Moolenaar # define PyType_Type (*dll_PyType_Type) 114*071d4279SBram Moolenaar # define Py_BuildValue dll_Py_BuildValue 115*071d4279SBram Moolenaar # define Py_FindMethod dll_Py_FindMethod 116*071d4279SBram Moolenaar # define Py_InitModule4 dll_Py_InitModule4 117*071d4279SBram Moolenaar # define Py_Initialize dll_Py_Initialize 118*071d4279SBram Moolenaar # define _PyObject_New dll__PyObject_New 119*071d4279SBram Moolenaar # define _Py_NoneStruct (*dll__Py_NoneStruct) 120*071d4279SBram Moolenaar # define PyObject_Init dll__PyObject_Init 121*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 122*071d4279SBram Moolenaar # define PyType_IsSubtype dll_PyType_IsSubtype 123*071d4279SBram Moolenaar # endif 124*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 125*071d4279SBram Moolenaar # define PyObject_Malloc dll_PyObject_Malloc 126*071d4279SBram Moolenaar # define PyObject_Free dll_PyObject_Free 127*071d4279SBram Moolenaar # endif 128*071d4279SBram Moolenaar 129*071d4279SBram Moolenaar /* 130*071d4279SBram Moolenaar * Pointers for dynamic link 131*071d4279SBram Moolenaar */ 132*071d4279SBram Moolenaar static int(*dll_PyArg_Parse)(PyObject *, char *, ...); 133*071d4279SBram Moolenaar static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...); 134*071d4279SBram Moolenaar static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item); 135*071d4279SBram Moolenaar static int(*dll_PyErr_BadArgument)(void); 136*071d4279SBram Moolenaar static void(*dll_PyErr_Clear)(void); 137*071d4279SBram Moolenaar static PyObject*(*dll_PyErr_NoMemory)(void); 138*071d4279SBram Moolenaar static PyObject*(*dll_PyErr_Occurred)(void); 139*071d4279SBram Moolenaar static void(*dll_PyErr_SetNone)(PyObject *); 140*071d4279SBram Moolenaar static void(*dll_PyErr_SetString)(PyObject *, const char *); 141*071d4279SBram Moolenaar static void(*dll_PyEval_InitThreads)(void); 142*071d4279SBram Moolenaar static void(*dll_PyEval_RestoreThread)(PyThreadState *); 143*071d4279SBram Moolenaar static PyThreadState*(*dll_PyEval_SaveThread)(void); 144*071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 145*071d4279SBram Moolenaar static PyGILState_STATE (*dll_PyGILState_Ensure)(void); 146*071d4279SBram Moolenaar static void (*dll_PyGILState_Release)(PyGILState_STATE); 147*071d4279SBram Moolenaar #endif 148*071d4279SBram Moolenaar static long(*dll_PyInt_AsLong)(PyObject *); 149*071d4279SBram Moolenaar static PyObject*(*dll_PyInt_FromLong)(long); 150*071d4279SBram Moolenaar static PyTypeObject* dll_PyInt_Type; 151*071d4279SBram Moolenaar static PyObject*(*dll_PyList_GetItem)(PyObject *, int); 152*071d4279SBram Moolenaar static PyObject*(*dll_PyList_New)(int size); 153*071d4279SBram Moolenaar static int(*dll_PyList_SetItem)(PyObject *, int, PyObject *); 154*071d4279SBram Moolenaar static int(*dll_PyList_Size)(PyObject *); 155*071d4279SBram Moolenaar static PyTypeObject* dll_PyList_Type; 156*071d4279SBram Moolenaar static PyObject*(*dll_PyImport_ImportModule)(const char *); 157*071d4279SBram Moolenaar static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *); 158*071d4279SBram Moolenaar static PyObject*(*dll_PyModule_GetDict)(PyObject *); 159*071d4279SBram Moolenaar static int(*dll_PyRun_SimpleString)(char *); 160*071d4279SBram Moolenaar static char*(*dll_PyString_AsString)(PyObject *); 161*071d4279SBram Moolenaar static PyObject*(*dll_PyString_FromString)(const char *); 162*071d4279SBram Moolenaar static PyObject*(*dll_PyString_FromStringAndSize)(const char *, int); 163*071d4279SBram Moolenaar static int(*dll_PyString_Size)(PyObject *); 164*071d4279SBram Moolenaar static PyTypeObject* dll_PyString_Type; 165*071d4279SBram Moolenaar static int(*dll_PySys_SetObject)(char *, PyObject *); 166*071d4279SBram Moolenaar static int(*dll_PySys_SetArgv)(int, char **); 167*071d4279SBram Moolenaar static PyTypeObject* dll_PyType_Type; 168*071d4279SBram Moolenaar static PyObject*(*dll_Py_BuildValue)(char *, ...); 169*071d4279SBram Moolenaar static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *); 170*071d4279SBram Moolenaar static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int); 171*071d4279SBram Moolenaar static void(*dll_Py_Initialize)(void); 172*071d4279SBram Moolenaar static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *); 173*071d4279SBram Moolenaar static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *); 174*071d4279SBram Moolenaar static PyObject* dll__Py_NoneStruct; 175*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 176*071d4279SBram Moolenaar static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *); 177*071d4279SBram Moolenaar # endif 178*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 179*071d4279SBram Moolenaar static void* (*dll_PyObject_Malloc)(size_t); 180*071d4279SBram Moolenaar static void (*dll_PyObject_Free)(void*); 181*071d4279SBram Moolenaar # endif 182*071d4279SBram Moolenaar 183*071d4279SBram Moolenaar static HINSTANCE hinstPython = 0; /* Instance of python.dll */ 184*071d4279SBram Moolenaar 185*071d4279SBram Moolenaar /* Imported exception objects */ 186*071d4279SBram Moolenaar static PyObject *imp_PyExc_AttributeError; 187*071d4279SBram Moolenaar static PyObject *imp_PyExc_IndexError; 188*071d4279SBram Moolenaar static PyObject *imp_PyExc_KeyboardInterrupt; 189*071d4279SBram Moolenaar static PyObject *imp_PyExc_TypeError; 190*071d4279SBram Moolenaar static PyObject *imp_PyExc_ValueError; 191*071d4279SBram Moolenaar 192*071d4279SBram Moolenaar # define PyExc_AttributeError imp_PyExc_AttributeError 193*071d4279SBram Moolenaar # define PyExc_IndexError imp_PyExc_IndexError 194*071d4279SBram Moolenaar # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt 195*071d4279SBram Moolenaar # define PyExc_TypeError imp_PyExc_TypeError 196*071d4279SBram Moolenaar # define PyExc_ValueError imp_PyExc_ValueError 197*071d4279SBram Moolenaar 198*071d4279SBram Moolenaar /* 199*071d4279SBram Moolenaar * Table of name to function pointer of python. 200*071d4279SBram Moolenaar */ 201*071d4279SBram Moolenaar # define PYTHON_PROC FARPROC 202*071d4279SBram Moolenaar static struct 203*071d4279SBram Moolenaar { 204*071d4279SBram Moolenaar char *name; 205*071d4279SBram Moolenaar PYTHON_PROC *ptr; 206*071d4279SBram Moolenaar } python_funcname_table[] = 207*071d4279SBram Moolenaar { 208*071d4279SBram Moolenaar {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse}, 209*071d4279SBram Moolenaar {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple}, 210*071d4279SBram Moolenaar {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString}, 211*071d4279SBram Moolenaar {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument}, 212*071d4279SBram Moolenaar {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear}, 213*071d4279SBram Moolenaar {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory}, 214*071d4279SBram Moolenaar {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred}, 215*071d4279SBram Moolenaar {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone}, 216*071d4279SBram Moolenaar {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString}, 217*071d4279SBram Moolenaar {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads}, 218*071d4279SBram Moolenaar {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread}, 219*071d4279SBram Moolenaar {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread}, 220*071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE 221*071d4279SBram Moolenaar {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure}, 222*071d4279SBram Moolenaar {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release}, 223*071d4279SBram Moolenaar # endif 224*071d4279SBram Moolenaar {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong}, 225*071d4279SBram Moolenaar {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong}, 226*071d4279SBram Moolenaar {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type}, 227*071d4279SBram Moolenaar {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem}, 228*071d4279SBram Moolenaar {"PyList_New", (PYTHON_PROC*)&dll_PyList_New}, 229*071d4279SBram Moolenaar {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem}, 230*071d4279SBram Moolenaar {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size}, 231*071d4279SBram Moolenaar {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type}, 232*071d4279SBram Moolenaar {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule}, 233*071d4279SBram Moolenaar {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString}, 234*071d4279SBram Moolenaar {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict}, 235*071d4279SBram Moolenaar {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString}, 236*071d4279SBram Moolenaar {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString}, 237*071d4279SBram Moolenaar {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString}, 238*071d4279SBram Moolenaar {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize}, 239*071d4279SBram Moolenaar {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size}, 240*071d4279SBram Moolenaar {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type}, 241*071d4279SBram Moolenaar {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject}, 242*071d4279SBram Moolenaar {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv}, 243*071d4279SBram Moolenaar {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type}, 244*071d4279SBram Moolenaar {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue}, 245*071d4279SBram Moolenaar {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod}, 246*071d4279SBram Moolenaar {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4}, 247*071d4279SBram Moolenaar {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize}, 248*071d4279SBram Moolenaar {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New}, 249*071d4279SBram Moolenaar {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init}, 250*071d4279SBram Moolenaar {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct}, 251*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000 252*071d4279SBram Moolenaar {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype}, 253*071d4279SBram Moolenaar # endif 254*071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000 255*071d4279SBram Moolenaar {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc}, 256*071d4279SBram Moolenaar {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free}, 257*071d4279SBram Moolenaar # endif 258*071d4279SBram Moolenaar {"", NULL}, 259*071d4279SBram Moolenaar }; 260*071d4279SBram Moolenaar 261*071d4279SBram Moolenaar /* 262*071d4279SBram Moolenaar * Free python.dll 263*071d4279SBram Moolenaar */ 264*071d4279SBram Moolenaar static void 265*071d4279SBram Moolenaar end_dynamic_python(void) 266*071d4279SBram Moolenaar { 267*071d4279SBram Moolenaar if (hinstPython) 268*071d4279SBram Moolenaar { 269*071d4279SBram Moolenaar FreeLibrary(hinstPython); 270*071d4279SBram Moolenaar hinstPython = 0; 271*071d4279SBram Moolenaar } 272*071d4279SBram Moolenaar } 273*071d4279SBram Moolenaar 274*071d4279SBram Moolenaar /* 275*071d4279SBram Moolenaar * Load library and get all pointers. 276*071d4279SBram Moolenaar * Parameter 'libname' provides name of DLL. 277*071d4279SBram Moolenaar * Return OK or FAIL. 278*071d4279SBram Moolenaar */ 279*071d4279SBram Moolenaar static int 280*071d4279SBram Moolenaar python_runtime_link_init(char *libname, int verbose) 281*071d4279SBram Moolenaar { 282*071d4279SBram Moolenaar int i; 283*071d4279SBram Moolenaar 284*071d4279SBram Moolenaar if (hinstPython) 285*071d4279SBram Moolenaar return OK; 286*071d4279SBram Moolenaar hinstPython = LoadLibrary(libname); 287*071d4279SBram Moolenaar if (!hinstPython) 288*071d4279SBram Moolenaar { 289*071d4279SBram Moolenaar if (verbose) 290*071d4279SBram Moolenaar EMSG2(_(e_loadlib), libname); 291*071d4279SBram Moolenaar return FAIL; 292*071d4279SBram Moolenaar } 293*071d4279SBram Moolenaar 294*071d4279SBram Moolenaar for (i = 0; python_funcname_table[i].ptr; ++i) 295*071d4279SBram Moolenaar { 296*071d4279SBram Moolenaar if ((*python_funcname_table[i].ptr = GetProcAddress(hinstPython, 297*071d4279SBram Moolenaar python_funcname_table[i].name)) == NULL) 298*071d4279SBram Moolenaar { 299*071d4279SBram Moolenaar FreeLibrary(hinstPython); 300*071d4279SBram Moolenaar hinstPython = 0; 301*071d4279SBram Moolenaar if (verbose) 302*071d4279SBram Moolenaar EMSG2(_(e_loadfunc), python_funcname_table[i].name); 303*071d4279SBram Moolenaar return FAIL; 304*071d4279SBram Moolenaar } 305*071d4279SBram Moolenaar } 306*071d4279SBram Moolenaar return OK; 307*071d4279SBram Moolenaar } 308*071d4279SBram Moolenaar 309*071d4279SBram Moolenaar /* 310*071d4279SBram Moolenaar * If python is enabled (there is installed python on Windows system) return 311*071d4279SBram Moolenaar * TRUE, else FALSE. 312*071d4279SBram Moolenaar */ 313*071d4279SBram Moolenaar int 314*071d4279SBram Moolenaar python_enabled(verbose) 315*071d4279SBram Moolenaar int verbose; 316*071d4279SBram Moolenaar { 317*071d4279SBram Moolenaar return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK; 318*071d4279SBram Moolenaar } 319*071d4279SBram Moolenaar 320*071d4279SBram Moolenaar /* Load the standard Python exceptions - don't import the symbols from the 321*071d4279SBram Moolenaar * DLL, as this can cause errors (importing data symbols is not reliable). 322*071d4279SBram Moolenaar */ 323*071d4279SBram Moolenaar static void get_exceptions __ARGS((void)); 324*071d4279SBram Moolenaar 325*071d4279SBram Moolenaar static void 326*071d4279SBram Moolenaar get_exceptions() 327*071d4279SBram Moolenaar { 328*071d4279SBram Moolenaar PyObject *exmod = PyImport_ImportModule("exceptions"); 329*071d4279SBram Moolenaar PyObject *exdict = PyModule_GetDict(exmod); 330*071d4279SBram Moolenaar imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError"); 331*071d4279SBram Moolenaar imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError"); 332*071d4279SBram Moolenaar imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt"); 333*071d4279SBram Moolenaar imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError"); 334*071d4279SBram Moolenaar imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError"); 335*071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_AttributeError); 336*071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_IndexError); 337*071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_KeyboardInterrupt); 338*071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_TypeError); 339*071d4279SBram Moolenaar Py_XINCREF(imp_PyExc_ValueError); 340*071d4279SBram Moolenaar Py_XDECREF(exmod); 341*071d4279SBram Moolenaar } 342*071d4279SBram Moolenaar #endif /* DYNAMIC_PYTHON */ 343*071d4279SBram Moolenaar 344*071d4279SBram Moolenaar /****************************************************** 345*071d4279SBram Moolenaar * Internal function prototypes. 346*071d4279SBram Moolenaar */ 347*071d4279SBram Moolenaar 348*071d4279SBram Moolenaar static void DoPythonCommand(exarg_T *, const char *); 349*071d4279SBram Moolenaar static int RangeStart; 350*071d4279SBram Moolenaar static int RangeEnd; 351*071d4279SBram Moolenaar 352*071d4279SBram Moolenaar static void PythonIO_Flush(void); 353*071d4279SBram Moolenaar static int PythonIO_Init(void); 354*071d4279SBram Moolenaar static int PythonMod_Init(void); 355*071d4279SBram Moolenaar 356*071d4279SBram Moolenaar /* Utility functions for the vim/python interface 357*071d4279SBram Moolenaar * ---------------------------------------------- 358*071d4279SBram Moolenaar */ 359*071d4279SBram Moolenaar static PyObject *GetBufferLine(buf_T *, int); 360*071d4279SBram Moolenaar static PyObject *GetBufferLineList(buf_T *, int, int); 361*071d4279SBram Moolenaar 362*071d4279SBram Moolenaar static int SetBufferLine(buf_T *, int, PyObject *, int *); 363*071d4279SBram Moolenaar static int SetBufferLineList(buf_T *, int, int, PyObject *, int *); 364*071d4279SBram Moolenaar static int InsertBufferLines(buf_T *, int, PyObject *, int *); 365*071d4279SBram Moolenaar 366*071d4279SBram Moolenaar static PyObject *LineToString(const char *); 367*071d4279SBram Moolenaar static char *StringToLine(PyObject *); 368*071d4279SBram Moolenaar 369*071d4279SBram Moolenaar static int VimErrorCheck(void); 370*071d4279SBram Moolenaar 371*071d4279SBram Moolenaar #define PyErr_SetVim(str) PyErr_SetString(VimError, str) 372*071d4279SBram Moolenaar 373*071d4279SBram Moolenaar /****************************************************** 374*071d4279SBram Moolenaar * 1. Python interpreter main program. 375*071d4279SBram Moolenaar */ 376*071d4279SBram Moolenaar 377*071d4279SBram Moolenaar static int initialised = 0; 378*071d4279SBram Moolenaar 379*071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ 380*071d4279SBram Moolenaar typedef PyObject PyThreadState; 381*071d4279SBram Moolenaar #endif /* Python 1.4 */ 382*071d4279SBram Moolenaar 383*071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 384*071d4279SBram Moolenaar static PyThreadState* saved_python_thread = NULL; 385*071d4279SBram Moolenaar 386*071d4279SBram Moolenaar /* 387*071d4279SBram Moolenaar * Suspend a thread of the Python interpreter, other threads are allowed to 388*071d4279SBram Moolenaar * run. 389*071d4279SBram Moolenaar */ 390*071d4279SBram Moolenaar static void Python_SaveThread(void) 391*071d4279SBram Moolenaar { 392*071d4279SBram Moolenaar saved_python_thread = PyEval_SaveThread(); 393*071d4279SBram Moolenaar } 394*071d4279SBram Moolenaar 395*071d4279SBram Moolenaar /* 396*071d4279SBram Moolenaar * Restore a thread of the Python interpreter, waits for other threads to 397*071d4279SBram Moolenaar * block. 398*071d4279SBram Moolenaar */ 399*071d4279SBram Moolenaar static void Python_RestoreThread(void) 400*071d4279SBram Moolenaar { 401*071d4279SBram Moolenaar PyEval_RestoreThread(saved_python_thread); 402*071d4279SBram Moolenaar saved_python_thread = NULL; 403*071d4279SBram Moolenaar } 404*071d4279SBram Moolenaar #endif 405*071d4279SBram Moolenaar 406*071d4279SBram Moolenaar /* 407*071d4279SBram Moolenaar * obtain a lock on the Vim data structures 408*071d4279SBram Moolenaar */ 409*071d4279SBram Moolenaar static void Python_Lock_Vim(void) 410*071d4279SBram Moolenaar { 411*071d4279SBram Moolenaar } 412*071d4279SBram Moolenaar 413*071d4279SBram Moolenaar /* 414*071d4279SBram Moolenaar * release a lock on the Vim data structures 415*071d4279SBram Moolenaar */ 416*071d4279SBram Moolenaar static void Python_Release_Vim(void) 417*071d4279SBram Moolenaar { 418*071d4279SBram Moolenaar } 419*071d4279SBram Moolenaar 420*071d4279SBram Moolenaar void 421*071d4279SBram Moolenaar python_end() 422*071d4279SBram Moolenaar { 423*071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 424*071d4279SBram Moolenaar end_dynamic_python(); 425*071d4279SBram Moolenaar #endif 426*071d4279SBram Moolenaar } 427*071d4279SBram Moolenaar 428*071d4279SBram Moolenaar static int 429*071d4279SBram Moolenaar Python_Init(void) 430*071d4279SBram Moolenaar { 431*071d4279SBram Moolenaar if (!initialised) 432*071d4279SBram Moolenaar { 433*071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 434*071d4279SBram Moolenaar if (!python_enabled(TRUE)) 435*071d4279SBram Moolenaar { 436*071d4279SBram Moolenaar EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded.")); 437*071d4279SBram Moolenaar goto fail; 438*071d4279SBram Moolenaar } 439*071d4279SBram Moolenaar #endif 440*071d4279SBram Moolenaar 441*071d4279SBram Moolenaar #if !defined(MACOS) || defined(MACOS_X_UNIX) 442*071d4279SBram Moolenaar Py_Initialize(); 443*071d4279SBram Moolenaar #else 444*071d4279SBram Moolenaar PyMac_Initialize(); 445*071d4279SBram Moolenaar #endif 446*071d4279SBram Moolenaar /* initialise threads */ 447*071d4279SBram Moolenaar PyEval_InitThreads(); 448*071d4279SBram Moolenaar 449*071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON 450*071d4279SBram Moolenaar get_exceptions(); 451*071d4279SBram Moolenaar #endif 452*071d4279SBram Moolenaar 453*071d4279SBram Moolenaar if (PythonIO_Init()) 454*071d4279SBram Moolenaar goto fail; 455*071d4279SBram Moolenaar 456*071d4279SBram Moolenaar if (PythonMod_Init()) 457*071d4279SBram Moolenaar goto fail; 458*071d4279SBram Moolenaar 459*071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 460*071d4279SBram Moolenaar /* the first python thread is vim's */ 461*071d4279SBram Moolenaar Python_SaveThread(); 462*071d4279SBram Moolenaar #endif 463*071d4279SBram Moolenaar 464*071d4279SBram Moolenaar initialised = 1; 465*071d4279SBram Moolenaar } 466*071d4279SBram Moolenaar 467*071d4279SBram Moolenaar return 0; 468*071d4279SBram Moolenaar 469*071d4279SBram Moolenaar fail: 470*071d4279SBram Moolenaar /* We call PythonIO_Flush() here to print any Python errors. 471*071d4279SBram Moolenaar * This is OK, as it is possible to call this function even 472*071d4279SBram Moolenaar * if PythonIO_Init() has not completed successfully (it will 473*071d4279SBram Moolenaar * not do anything in this case). 474*071d4279SBram Moolenaar */ 475*071d4279SBram Moolenaar PythonIO_Flush(); 476*071d4279SBram Moolenaar return -1; 477*071d4279SBram Moolenaar } 478*071d4279SBram Moolenaar 479*071d4279SBram Moolenaar /* 480*071d4279SBram Moolenaar * External interface 481*071d4279SBram Moolenaar */ 482*071d4279SBram Moolenaar static void 483*071d4279SBram Moolenaar DoPythonCommand(exarg_T *eap, const char *cmd) 484*071d4279SBram Moolenaar { 485*071d4279SBram Moolenaar #ifdef PY_CAN_RECURSE 486*071d4279SBram Moolenaar PyGILState_STATE pygilstate; 487*071d4279SBram Moolenaar #else 488*071d4279SBram Moolenaar static int recursive = 0; 489*071d4279SBram Moolenaar #endif 490*071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 491*071d4279SBram Moolenaar GrafPtr oldPort; 492*071d4279SBram Moolenaar #endif 493*071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 494*071d4279SBram Moolenaar char *saved_locale; 495*071d4279SBram Moolenaar #endif 496*071d4279SBram Moolenaar 497*071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 498*071d4279SBram Moolenaar if (recursive) 499*071d4279SBram Moolenaar { 500*071d4279SBram Moolenaar EMSG(_("E659: Cannot invoke Python recursively")); 501*071d4279SBram Moolenaar return; 502*071d4279SBram Moolenaar } 503*071d4279SBram Moolenaar ++recursive; 504*071d4279SBram Moolenaar #endif 505*071d4279SBram Moolenaar 506*071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 507*071d4279SBram Moolenaar GetPort(&oldPort); 508*071d4279SBram Moolenaar /* Check if the Python library is available */ 509*071d4279SBram Moolenaar if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress) 510*071d4279SBram Moolenaar goto theend; 511*071d4279SBram Moolenaar #endif 512*071d4279SBram Moolenaar if (Python_Init()) 513*071d4279SBram Moolenaar goto theend; 514*071d4279SBram Moolenaar 515*071d4279SBram Moolenaar RangeStart = eap->line1; 516*071d4279SBram Moolenaar RangeEnd = eap->line2; 517*071d4279SBram Moolenaar Python_Release_Vim(); /* leave vim */ 518*071d4279SBram Moolenaar 519*071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 520*071d4279SBram Moolenaar /* Python only works properly when the LC_NUMERIC locale is "C". */ 521*071d4279SBram Moolenaar saved_locale = setlocale(LC_NUMERIC, NULL); 522*071d4279SBram Moolenaar if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0) 523*071d4279SBram Moolenaar saved_locale = NULL; 524*071d4279SBram Moolenaar else 525*071d4279SBram Moolenaar { 526*071d4279SBram Moolenaar /* Need to make a copy, value may change when setting new locale. */ 527*071d4279SBram Moolenaar saved_locale = (char *)vim_strsave((char_u *)saved_locale); 528*071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, "C"); 529*071d4279SBram Moolenaar } 530*071d4279SBram Moolenaar #endif 531*071d4279SBram Moolenaar 532*071d4279SBram Moolenaar #ifdef PY_CAN_RECURSE 533*071d4279SBram Moolenaar pygilstate = PyGILState_Ensure(); 534*071d4279SBram Moolenaar #else 535*071d4279SBram Moolenaar Python_RestoreThread(); /* enter python */ 536*071d4279SBram Moolenaar #endif 537*071d4279SBram Moolenaar 538*071d4279SBram Moolenaar PyRun_SimpleString((char *)(cmd)); 539*071d4279SBram Moolenaar 540*071d4279SBram Moolenaar #ifdef PY_CAN_RECURSE 541*071d4279SBram Moolenaar PyGILState_Release(pygilstate); 542*071d4279SBram Moolenaar #else 543*071d4279SBram Moolenaar Python_SaveThread(); /* leave python */ 544*071d4279SBram Moolenaar #endif 545*071d4279SBram Moolenaar 546*071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) 547*071d4279SBram Moolenaar if (saved_locale != NULL) 548*071d4279SBram Moolenaar { 549*071d4279SBram Moolenaar (void)setlocale(LC_NUMERIC, saved_locale); 550*071d4279SBram Moolenaar vim_free(saved_locale); 551*071d4279SBram Moolenaar } 552*071d4279SBram Moolenaar #endif 553*071d4279SBram Moolenaar 554*071d4279SBram Moolenaar Python_Lock_Vim(); /* enter vim */ 555*071d4279SBram Moolenaar PythonIO_Flush(); 556*071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX) 557*071d4279SBram Moolenaar SetPort(oldPort); 558*071d4279SBram Moolenaar #endif 559*071d4279SBram Moolenaar 560*071d4279SBram Moolenaar theend: 561*071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE 562*071d4279SBram Moolenaar --recursive; 563*071d4279SBram Moolenaar #endif 564*071d4279SBram Moolenaar return; /* keeps lint happy */ 565*071d4279SBram Moolenaar } 566*071d4279SBram Moolenaar 567*071d4279SBram Moolenaar /* 568*071d4279SBram Moolenaar * ":python" 569*071d4279SBram Moolenaar */ 570*071d4279SBram Moolenaar void 571*071d4279SBram Moolenaar ex_python(exarg_T *eap) 572*071d4279SBram Moolenaar { 573*071d4279SBram Moolenaar char_u *script; 574*071d4279SBram Moolenaar 575*071d4279SBram Moolenaar script = script_get(eap, eap->arg); 576*071d4279SBram Moolenaar if (!eap->skip) 577*071d4279SBram Moolenaar { 578*071d4279SBram Moolenaar if (script == NULL) 579*071d4279SBram Moolenaar DoPythonCommand(eap, (char *)eap->arg); 580*071d4279SBram Moolenaar else 581*071d4279SBram Moolenaar DoPythonCommand(eap, (char *)script); 582*071d4279SBram Moolenaar } 583*071d4279SBram Moolenaar vim_free(script); 584*071d4279SBram Moolenaar } 585*071d4279SBram Moolenaar 586*071d4279SBram Moolenaar #define BUFFER_SIZE 1024 587*071d4279SBram Moolenaar 588*071d4279SBram Moolenaar /* 589*071d4279SBram Moolenaar * ":pyfile" 590*071d4279SBram Moolenaar */ 591*071d4279SBram Moolenaar void 592*071d4279SBram Moolenaar ex_pyfile(exarg_T *eap) 593*071d4279SBram Moolenaar { 594*071d4279SBram Moolenaar static char buffer[BUFFER_SIZE]; 595*071d4279SBram Moolenaar const char *file = (char *)eap->arg; 596*071d4279SBram Moolenaar char *p; 597*071d4279SBram Moolenaar 598*071d4279SBram Moolenaar /* Have to do it like this. PyRun_SimpleFile requires you to pass a 599*071d4279SBram Moolenaar * stdio file pointer, but Vim and the Python DLL are compiled with 600*071d4279SBram Moolenaar * different options under Windows, meaning that stdio pointers aren't 601*071d4279SBram Moolenaar * compatible between the two. Yuk. 602*071d4279SBram Moolenaar * 603*071d4279SBram Moolenaar * Put the string "execfile('file')" into buffer. But, we need to 604*071d4279SBram Moolenaar * escape any backslashes or single quotes in the file name, so that 605*071d4279SBram Moolenaar * Python won't mangle the file name. 606*071d4279SBram Moolenaar */ 607*071d4279SBram Moolenaar strcpy(buffer, "execfile('"); 608*071d4279SBram Moolenaar p = buffer + 10; /* size of "execfile('" */ 609*071d4279SBram Moolenaar 610*071d4279SBram Moolenaar while (*file && p < buffer + (BUFFER_SIZE - 3)) 611*071d4279SBram Moolenaar { 612*071d4279SBram Moolenaar if (*file == '\\' || *file == '\'') 613*071d4279SBram Moolenaar *p++ = '\\'; 614*071d4279SBram Moolenaar *p++ = *file++; 615*071d4279SBram Moolenaar } 616*071d4279SBram Moolenaar 617*071d4279SBram Moolenaar /* If we didn't finish the file name, we hit a buffer overflow */ 618*071d4279SBram Moolenaar if (*file != '\0') 619*071d4279SBram Moolenaar return; 620*071d4279SBram Moolenaar 621*071d4279SBram Moolenaar /* Put in the terminating "')" and a null */ 622*071d4279SBram Moolenaar *p++ = '\''; 623*071d4279SBram Moolenaar *p++ = ')'; 624*071d4279SBram Moolenaar *p++ = '\0'; 625*071d4279SBram Moolenaar 626*071d4279SBram Moolenaar /* Execute the file */ 627*071d4279SBram Moolenaar DoPythonCommand(eap, buffer); 628*071d4279SBram Moolenaar } 629*071d4279SBram Moolenaar 630*071d4279SBram Moolenaar /****************************************************** 631*071d4279SBram Moolenaar * 2. Python output stream: writes output via [e]msg(). 632*071d4279SBram Moolenaar */ 633*071d4279SBram Moolenaar 634*071d4279SBram Moolenaar /* Implementation functions 635*071d4279SBram Moolenaar */ 636*071d4279SBram Moolenaar 637*071d4279SBram Moolenaar static PyObject *OutputGetattr(PyObject *, char *); 638*071d4279SBram Moolenaar static int OutputSetattr(PyObject *, char *, PyObject *); 639*071d4279SBram Moolenaar 640*071d4279SBram Moolenaar static PyObject *OutputWrite(PyObject *, PyObject *); 641*071d4279SBram Moolenaar static PyObject *OutputWritelines(PyObject *, PyObject *); 642*071d4279SBram Moolenaar 643*071d4279SBram Moolenaar typedef void (*writefn)(char_u *); 644*071d4279SBram Moolenaar static void writer(writefn fn, char_u *str, int n); 645*071d4279SBram Moolenaar 646*071d4279SBram Moolenaar /* Output object definition 647*071d4279SBram Moolenaar */ 648*071d4279SBram Moolenaar 649*071d4279SBram Moolenaar typedef struct 650*071d4279SBram Moolenaar { 651*071d4279SBram Moolenaar PyObject_HEAD 652*071d4279SBram Moolenaar long softspace; 653*071d4279SBram Moolenaar long error; 654*071d4279SBram Moolenaar } OutputObject; 655*071d4279SBram Moolenaar 656*071d4279SBram Moolenaar static struct PyMethodDef OutputMethods[] = { 657*071d4279SBram Moolenaar /* name, function, calling, documentation */ 658*071d4279SBram Moolenaar {"write", OutputWrite, 1, "" }, 659*071d4279SBram Moolenaar {"writelines", OutputWritelines, 1, "" }, 660*071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 661*071d4279SBram Moolenaar }; 662*071d4279SBram Moolenaar 663*071d4279SBram Moolenaar static PyTypeObject OutputType = { 664*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 665*071d4279SBram Moolenaar 0, 666*071d4279SBram Moolenaar "message", 667*071d4279SBram Moolenaar sizeof(OutputObject), 668*071d4279SBram Moolenaar 0, 669*071d4279SBram Moolenaar 670*071d4279SBram Moolenaar (destructor) 0, 671*071d4279SBram Moolenaar (printfunc) 0, 672*071d4279SBram Moolenaar (getattrfunc) OutputGetattr, 673*071d4279SBram Moolenaar (setattrfunc) OutputSetattr, 674*071d4279SBram Moolenaar (cmpfunc) 0, 675*071d4279SBram Moolenaar (reprfunc) 0, 676*071d4279SBram Moolenaar 677*071d4279SBram Moolenaar 0, /* as number */ 678*071d4279SBram Moolenaar 0, /* as sequence */ 679*071d4279SBram Moolenaar 0, /* as mapping */ 680*071d4279SBram Moolenaar 681*071d4279SBram Moolenaar (hashfunc) 0, 682*071d4279SBram Moolenaar (ternaryfunc) 0, 683*071d4279SBram Moolenaar (reprfunc) 0 684*071d4279SBram Moolenaar }; 685*071d4279SBram Moolenaar 686*071d4279SBram Moolenaar /*************/ 687*071d4279SBram Moolenaar 688*071d4279SBram Moolenaar static PyObject * 689*071d4279SBram Moolenaar OutputGetattr(PyObject *self, char *name) 690*071d4279SBram Moolenaar { 691*071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 692*071d4279SBram Moolenaar return PyInt_FromLong(((OutputObject *)(self))->softspace); 693*071d4279SBram Moolenaar 694*071d4279SBram Moolenaar return Py_FindMethod(OutputMethods, self, name); 695*071d4279SBram Moolenaar } 696*071d4279SBram Moolenaar 697*071d4279SBram Moolenaar static int 698*071d4279SBram Moolenaar OutputSetattr(PyObject *self, char *name, PyObject *val) 699*071d4279SBram Moolenaar { 700*071d4279SBram Moolenaar if (val == NULL) { 701*071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes")); 702*071d4279SBram Moolenaar return -1; 703*071d4279SBram Moolenaar } 704*071d4279SBram Moolenaar 705*071d4279SBram Moolenaar if (strcmp(name, "softspace") == 0) 706*071d4279SBram Moolenaar { 707*071d4279SBram Moolenaar if (!PyInt_Check(val)) { 708*071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("softspace must be an integer")); 709*071d4279SBram Moolenaar return -1; 710*071d4279SBram Moolenaar } 711*071d4279SBram Moolenaar 712*071d4279SBram Moolenaar ((OutputObject *)(self))->softspace = PyInt_AsLong(val); 713*071d4279SBram Moolenaar return 0; 714*071d4279SBram Moolenaar } 715*071d4279SBram Moolenaar 716*071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, _("invalid attribute")); 717*071d4279SBram Moolenaar return -1; 718*071d4279SBram Moolenaar } 719*071d4279SBram Moolenaar 720*071d4279SBram Moolenaar /*************/ 721*071d4279SBram Moolenaar 722*071d4279SBram Moolenaar static PyObject * 723*071d4279SBram Moolenaar OutputWrite(PyObject *self, PyObject *args) 724*071d4279SBram Moolenaar { 725*071d4279SBram Moolenaar int len; 726*071d4279SBram Moolenaar char *str; 727*071d4279SBram Moolenaar int error = ((OutputObject *)(self))->error; 728*071d4279SBram Moolenaar 729*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "s#", &str, &len)) 730*071d4279SBram Moolenaar return NULL; 731*071d4279SBram Moolenaar 732*071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 733*071d4279SBram Moolenaar Python_Lock_Vim(); 734*071d4279SBram Moolenaar writer((writefn)(error ? emsg : msg), (char_u *)str, len); 735*071d4279SBram Moolenaar Python_Release_Vim(); 736*071d4279SBram Moolenaar Py_END_ALLOW_THREADS 737*071d4279SBram Moolenaar 738*071d4279SBram Moolenaar Py_INCREF(Py_None); 739*071d4279SBram Moolenaar return Py_None; 740*071d4279SBram Moolenaar } 741*071d4279SBram Moolenaar 742*071d4279SBram Moolenaar static PyObject * 743*071d4279SBram Moolenaar OutputWritelines(PyObject *self, PyObject *args) 744*071d4279SBram Moolenaar { 745*071d4279SBram Moolenaar int n; 746*071d4279SBram Moolenaar int i; 747*071d4279SBram Moolenaar PyObject *list; 748*071d4279SBram Moolenaar int error = ((OutputObject *)(self))->error; 749*071d4279SBram Moolenaar 750*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "O", &list)) 751*071d4279SBram Moolenaar return NULL; 752*071d4279SBram Moolenaar Py_INCREF(list); 753*071d4279SBram Moolenaar 754*071d4279SBram Moolenaar if (!PyList_Check(list)) { 755*071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); 756*071d4279SBram Moolenaar Py_DECREF(list); 757*071d4279SBram Moolenaar return NULL; 758*071d4279SBram Moolenaar } 759*071d4279SBram Moolenaar 760*071d4279SBram Moolenaar n = PyList_Size(list); 761*071d4279SBram Moolenaar 762*071d4279SBram Moolenaar for (i = 0; i < n; ++i) 763*071d4279SBram Moolenaar { 764*071d4279SBram Moolenaar PyObject *line = PyList_GetItem(list, i); 765*071d4279SBram Moolenaar char *str; 766*071d4279SBram Moolenaar int len; 767*071d4279SBram Moolenaar 768*071d4279SBram Moolenaar if (!PyArg_Parse(line, "s#", &str, &len)) { 769*071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings")); 770*071d4279SBram Moolenaar Py_DECREF(list); 771*071d4279SBram Moolenaar return NULL; 772*071d4279SBram Moolenaar } 773*071d4279SBram Moolenaar 774*071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 775*071d4279SBram Moolenaar Python_Lock_Vim(); 776*071d4279SBram Moolenaar writer((writefn)(error ? emsg : msg), (char_u *)str, len); 777*071d4279SBram Moolenaar Python_Release_Vim(); 778*071d4279SBram Moolenaar Py_END_ALLOW_THREADS 779*071d4279SBram Moolenaar } 780*071d4279SBram Moolenaar 781*071d4279SBram Moolenaar Py_DECREF(list); 782*071d4279SBram Moolenaar Py_INCREF(Py_None); 783*071d4279SBram Moolenaar return Py_None; 784*071d4279SBram Moolenaar } 785*071d4279SBram Moolenaar 786*071d4279SBram Moolenaar /* Output buffer management 787*071d4279SBram Moolenaar */ 788*071d4279SBram Moolenaar 789*071d4279SBram Moolenaar static char_u *buffer = NULL; 790*071d4279SBram Moolenaar static int buffer_len = 0; 791*071d4279SBram Moolenaar static int buffer_size = 0; 792*071d4279SBram Moolenaar 793*071d4279SBram Moolenaar static writefn old_fn = NULL; 794*071d4279SBram Moolenaar 795*071d4279SBram Moolenaar static void 796*071d4279SBram Moolenaar buffer_ensure(int n) 797*071d4279SBram Moolenaar { 798*071d4279SBram Moolenaar int new_size; 799*071d4279SBram Moolenaar char_u *new_buffer; 800*071d4279SBram Moolenaar 801*071d4279SBram Moolenaar if (n < buffer_size) 802*071d4279SBram Moolenaar return; 803*071d4279SBram Moolenaar 804*071d4279SBram Moolenaar new_size = buffer_size; 805*071d4279SBram Moolenaar while (new_size < n) 806*071d4279SBram Moolenaar new_size += 80; 807*071d4279SBram Moolenaar 808*071d4279SBram Moolenaar if (new_size != buffer_size) 809*071d4279SBram Moolenaar { 810*071d4279SBram Moolenaar new_buffer = alloc((unsigned)new_size); 811*071d4279SBram Moolenaar if (new_buffer == NULL) 812*071d4279SBram Moolenaar return; 813*071d4279SBram Moolenaar 814*071d4279SBram Moolenaar if (buffer) 815*071d4279SBram Moolenaar { 816*071d4279SBram Moolenaar memcpy(new_buffer, buffer, buffer_len); 817*071d4279SBram Moolenaar vim_free(buffer); 818*071d4279SBram Moolenaar } 819*071d4279SBram Moolenaar 820*071d4279SBram Moolenaar buffer = new_buffer; 821*071d4279SBram Moolenaar buffer_size = new_size; 822*071d4279SBram Moolenaar } 823*071d4279SBram Moolenaar } 824*071d4279SBram Moolenaar 825*071d4279SBram Moolenaar static void 826*071d4279SBram Moolenaar PythonIO_Flush(void) 827*071d4279SBram Moolenaar { 828*071d4279SBram Moolenaar if (old_fn && buffer_len) 829*071d4279SBram Moolenaar { 830*071d4279SBram Moolenaar buffer[buffer_len] = 0; 831*071d4279SBram Moolenaar old_fn(buffer); 832*071d4279SBram Moolenaar } 833*071d4279SBram Moolenaar 834*071d4279SBram Moolenaar buffer_len = 0; 835*071d4279SBram Moolenaar } 836*071d4279SBram Moolenaar 837*071d4279SBram Moolenaar static void 838*071d4279SBram Moolenaar writer(writefn fn, char_u *str, int n) 839*071d4279SBram Moolenaar { 840*071d4279SBram Moolenaar char_u *ptr; 841*071d4279SBram Moolenaar 842*071d4279SBram Moolenaar if (fn != old_fn && old_fn != NULL) 843*071d4279SBram Moolenaar PythonIO_Flush(); 844*071d4279SBram Moolenaar 845*071d4279SBram Moolenaar old_fn = fn; 846*071d4279SBram Moolenaar 847*071d4279SBram Moolenaar while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL) 848*071d4279SBram Moolenaar { 849*071d4279SBram Moolenaar int len = ptr - str; 850*071d4279SBram Moolenaar 851*071d4279SBram Moolenaar buffer_ensure(buffer_len + len + 1); 852*071d4279SBram Moolenaar 853*071d4279SBram Moolenaar memcpy(buffer + buffer_len, str, len); 854*071d4279SBram Moolenaar buffer_len += len; 855*071d4279SBram Moolenaar buffer[buffer_len] = 0; 856*071d4279SBram Moolenaar fn(buffer); 857*071d4279SBram Moolenaar str = ptr + 1; 858*071d4279SBram Moolenaar n -= len + 1; 859*071d4279SBram Moolenaar buffer_len = 0; 860*071d4279SBram Moolenaar } 861*071d4279SBram Moolenaar 862*071d4279SBram Moolenaar /* Put the remaining text into the buffer for later printing */ 863*071d4279SBram Moolenaar buffer_ensure(buffer_len + n + 1); 864*071d4279SBram Moolenaar memcpy(buffer + buffer_len, str, n); 865*071d4279SBram Moolenaar buffer_len += n; 866*071d4279SBram Moolenaar } 867*071d4279SBram Moolenaar 868*071d4279SBram Moolenaar /***************/ 869*071d4279SBram Moolenaar 870*071d4279SBram Moolenaar static OutputObject Output = 871*071d4279SBram Moolenaar { 872*071d4279SBram Moolenaar PyObject_HEAD_INIT(&OutputType) 873*071d4279SBram Moolenaar 0, 874*071d4279SBram Moolenaar 0 875*071d4279SBram Moolenaar }; 876*071d4279SBram Moolenaar 877*071d4279SBram Moolenaar static OutputObject Error = 878*071d4279SBram Moolenaar { 879*071d4279SBram Moolenaar PyObject_HEAD_INIT(&OutputType) 880*071d4279SBram Moolenaar 0, 881*071d4279SBram Moolenaar 1 882*071d4279SBram Moolenaar }; 883*071d4279SBram Moolenaar 884*071d4279SBram Moolenaar static int 885*071d4279SBram Moolenaar PythonIO_Init(void) 886*071d4279SBram Moolenaar { 887*071d4279SBram Moolenaar /* Fixups... */ 888*071d4279SBram Moolenaar OutputType.ob_type = &PyType_Type; 889*071d4279SBram Moolenaar 890*071d4279SBram Moolenaar PySys_SetObject("stdout", (PyObject *)(&Output)); 891*071d4279SBram Moolenaar PySys_SetObject("stderr", (PyObject *)(&Error)); 892*071d4279SBram Moolenaar 893*071d4279SBram Moolenaar if (PyErr_Occurred()) 894*071d4279SBram Moolenaar { 895*071d4279SBram Moolenaar EMSG(_("E264: Python: Error initialising I/O objects")); 896*071d4279SBram Moolenaar return -1; 897*071d4279SBram Moolenaar } 898*071d4279SBram Moolenaar 899*071d4279SBram Moolenaar return 0; 900*071d4279SBram Moolenaar } 901*071d4279SBram Moolenaar 902*071d4279SBram Moolenaar /****************************************************** 903*071d4279SBram Moolenaar * 3. Implementation of the Vim module for Python 904*071d4279SBram Moolenaar */ 905*071d4279SBram Moolenaar 906*071d4279SBram Moolenaar /* Vim module - Implementation functions 907*071d4279SBram Moolenaar * ------------------------------------- 908*071d4279SBram Moolenaar */ 909*071d4279SBram Moolenaar 910*071d4279SBram Moolenaar static PyObject *VimError; 911*071d4279SBram Moolenaar 912*071d4279SBram Moolenaar static PyObject *VimCommand(PyObject *, PyObject *); 913*071d4279SBram Moolenaar static PyObject *VimEval(PyObject *, PyObject *); 914*071d4279SBram Moolenaar 915*071d4279SBram Moolenaar /* Window type - Implementation functions 916*071d4279SBram Moolenaar * -------------------------------------- 917*071d4279SBram Moolenaar */ 918*071d4279SBram Moolenaar 919*071d4279SBram Moolenaar typedef struct 920*071d4279SBram Moolenaar { 921*071d4279SBram Moolenaar PyObject_HEAD 922*071d4279SBram Moolenaar win_T *win; 923*071d4279SBram Moolenaar } 924*071d4279SBram Moolenaar WindowObject; 925*071d4279SBram Moolenaar 926*071d4279SBram Moolenaar #define INVALID_WINDOW_VALUE ((win_T *)(-1)) 927*071d4279SBram Moolenaar 928*071d4279SBram Moolenaar #define WindowType_Check(obj) ((obj)->ob_type == &WindowType) 929*071d4279SBram Moolenaar 930*071d4279SBram Moolenaar static PyObject *WindowNew(win_T *); 931*071d4279SBram Moolenaar 932*071d4279SBram Moolenaar static void WindowDestructor(PyObject *); 933*071d4279SBram Moolenaar static PyObject *WindowGetattr(PyObject *, char *); 934*071d4279SBram Moolenaar static int WindowSetattr(PyObject *, char *, PyObject *); 935*071d4279SBram Moolenaar static PyObject *WindowRepr(PyObject *); 936*071d4279SBram Moolenaar 937*071d4279SBram Moolenaar /* Buffer type - Implementation functions 938*071d4279SBram Moolenaar * -------------------------------------- 939*071d4279SBram Moolenaar */ 940*071d4279SBram Moolenaar 941*071d4279SBram Moolenaar typedef struct 942*071d4279SBram Moolenaar { 943*071d4279SBram Moolenaar PyObject_HEAD 944*071d4279SBram Moolenaar buf_T *buf; 945*071d4279SBram Moolenaar } 946*071d4279SBram Moolenaar BufferObject; 947*071d4279SBram Moolenaar 948*071d4279SBram Moolenaar #define INVALID_BUFFER_VALUE ((buf_T *)(-1)) 949*071d4279SBram Moolenaar 950*071d4279SBram Moolenaar #define BufferType_Check(obj) ((obj)->ob_type == &BufferType) 951*071d4279SBram Moolenaar 952*071d4279SBram Moolenaar static PyObject *BufferNew (buf_T *); 953*071d4279SBram Moolenaar 954*071d4279SBram Moolenaar static void BufferDestructor(PyObject *); 955*071d4279SBram Moolenaar static PyObject *BufferGetattr(PyObject *, char *); 956*071d4279SBram Moolenaar static PyObject *BufferRepr(PyObject *); 957*071d4279SBram Moolenaar 958*071d4279SBram Moolenaar static int BufferLength(PyObject *); 959*071d4279SBram Moolenaar static PyObject *BufferItem(PyObject *, int); 960*071d4279SBram Moolenaar static PyObject *BufferSlice(PyObject *, int, int); 961*071d4279SBram Moolenaar static int BufferAssItem(PyObject *, int, PyObject *); 962*071d4279SBram Moolenaar static int BufferAssSlice(PyObject *, int, int, PyObject *); 963*071d4279SBram Moolenaar 964*071d4279SBram Moolenaar static PyObject *BufferAppend(PyObject *, PyObject *); 965*071d4279SBram Moolenaar static PyObject *BufferMark(PyObject *, PyObject *); 966*071d4279SBram Moolenaar static PyObject *BufferRange(PyObject *, PyObject *); 967*071d4279SBram Moolenaar 968*071d4279SBram Moolenaar /* Line range type - Implementation functions 969*071d4279SBram Moolenaar * -------------------------------------- 970*071d4279SBram Moolenaar */ 971*071d4279SBram Moolenaar 972*071d4279SBram Moolenaar typedef struct 973*071d4279SBram Moolenaar { 974*071d4279SBram Moolenaar PyObject_HEAD 975*071d4279SBram Moolenaar BufferObject *buf; 976*071d4279SBram Moolenaar int start; 977*071d4279SBram Moolenaar int end; 978*071d4279SBram Moolenaar } 979*071d4279SBram Moolenaar RangeObject; 980*071d4279SBram Moolenaar 981*071d4279SBram Moolenaar #define RangeType_Check(obj) ((obj)->ob_type == &RangeType) 982*071d4279SBram Moolenaar 983*071d4279SBram Moolenaar static PyObject *RangeNew(buf_T *, int, int); 984*071d4279SBram Moolenaar 985*071d4279SBram Moolenaar static void RangeDestructor(PyObject *); 986*071d4279SBram Moolenaar static PyObject *RangeGetattr(PyObject *, char *); 987*071d4279SBram Moolenaar static PyObject *RangeRepr(PyObject *); 988*071d4279SBram Moolenaar 989*071d4279SBram Moolenaar static int RangeLength(PyObject *); 990*071d4279SBram Moolenaar static PyObject *RangeItem(PyObject *, int); 991*071d4279SBram Moolenaar static PyObject *RangeSlice(PyObject *, int, int); 992*071d4279SBram Moolenaar static int RangeAssItem(PyObject *, int, PyObject *); 993*071d4279SBram Moolenaar static int RangeAssSlice(PyObject *, int, int, PyObject *); 994*071d4279SBram Moolenaar 995*071d4279SBram Moolenaar static PyObject *RangeAppend(PyObject *, PyObject *); 996*071d4279SBram Moolenaar 997*071d4279SBram Moolenaar /* Window list type - Implementation functions 998*071d4279SBram Moolenaar * ------------------------------------------- 999*071d4279SBram Moolenaar */ 1000*071d4279SBram Moolenaar 1001*071d4279SBram Moolenaar static int WinListLength(PyObject *); 1002*071d4279SBram Moolenaar static PyObject *WinListItem(PyObject *, int); 1003*071d4279SBram Moolenaar 1004*071d4279SBram Moolenaar /* Buffer list type - Implementation functions 1005*071d4279SBram Moolenaar * ------------------------------------------- 1006*071d4279SBram Moolenaar */ 1007*071d4279SBram Moolenaar 1008*071d4279SBram Moolenaar static int BufListLength(PyObject *); 1009*071d4279SBram Moolenaar static PyObject *BufListItem(PyObject *, int); 1010*071d4279SBram Moolenaar 1011*071d4279SBram Moolenaar /* Current objects type - Implementation functions 1012*071d4279SBram Moolenaar * ----------------------------------------------- 1013*071d4279SBram Moolenaar */ 1014*071d4279SBram Moolenaar 1015*071d4279SBram Moolenaar static PyObject *CurrentGetattr(PyObject *, char *); 1016*071d4279SBram Moolenaar static int CurrentSetattr(PyObject *, char *, PyObject *); 1017*071d4279SBram Moolenaar 1018*071d4279SBram Moolenaar /* Vim module - Definitions 1019*071d4279SBram Moolenaar */ 1020*071d4279SBram Moolenaar 1021*071d4279SBram Moolenaar static struct PyMethodDef VimMethods[] = { 1022*071d4279SBram Moolenaar /* name, function, calling, documentation */ 1023*071d4279SBram Moolenaar {"command", VimCommand, 1, "" }, 1024*071d4279SBram Moolenaar {"eval", VimEval, 1, "" }, 1025*071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1026*071d4279SBram Moolenaar }; 1027*071d4279SBram Moolenaar 1028*071d4279SBram Moolenaar /* Vim module - Implementation 1029*071d4279SBram Moolenaar */ 1030*071d4279SBram Moolenaar /*ARGSUSED*/ 1031*071d4279SBram Moolenaar static PyObject * 1032*071d4279SBram Moolenaar VimCommand(PyObject *self, PyObject *args) 1033*071d4279SBram Moolenaar { 1034*071d4279SBram Moolenaar char *cmd; 1035*071d4279SBram Moolenaar PyObject *result; 1036*071d4279SBram Moolenaar 1037*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "s", &cmd)) 1038*071d4279SBram Moolenaar return NULL; 1039*071d4279SBram Moolenaar 1040*071d4279SBram Moolenaar PyErr_Clear(); 1041*071d4279SBram Moolenaar 1042*071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 1043*071d4279SBram Moolenaar Python_Lock_Vim(); 1044*071d4279SBram Moolenaar 1045*071d4279SBram Moolenaar do_cmdline_cmd((char_u *)cmd); 1046*071d4279SBram Moolenaar update_screen(VALID); 1047*071d4279SBram Moolenaar 1048*071d4279SBram Moolenaar Python_Release_Vim(); 1049*071d4279SBram Moolenaar Py_END_ALLOW_THREADS 1050*071d4279SBram Moolenaar 1051*071d4279SBram Moolenaar if (VimErrorCheck()) 1052*071d4279SBram Moolenaar result = NULL; 1053*071d4279SBram Moolenaar else 1054*071d4279SBram Moolenaar result = Py_None; 1055*071d4279SBram Moolenaar 1056*071d4279SBram Moolenaar Py_XINCREF(result); 1057*071d4279SBram Moolenaar return result; 1058*071d4279SBram Moolenaar } 1059*071d4279SBram Moolenaar 1060*071d4279SBram Moolenaar /*ARGSUSED*/ 1061*071d4279SBram Moolenaar static PyObject * 1062*071d4279SBram Moolenaar VimEval(PyObject *self, PyObject *args) 1063*071d4279SBram Moolenaar { 1064*071d4279SBram Moolenaar #ifdef FEAT_EVAL 1065*071d4279SBram Moolenaar char *expr; 1066*071d4279SBram Moolenaar char *str; 1067*071d4279SBram Moolenaar PyObject *result; 1068*071d4279SBram Moolenaar 1069*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "s", &expr)) 1070*071d4279SBram Moolenaar return NULL; 1071*071d4279SBram Moolenaar 1072*071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 1073*071d4279SBram Moolenaar Python_Lock_Vim(); 1074*071d4279SBram Moolenaar str = (char *)eval_to_string((char_u *)expr, NULL); 1075*071d4279SBram Moolenaar Python_Release_Vim(); 1076*071d4279SBram Moolenaar Py_END_ALLOW_THREADS 1077*071d4279SBram Moolenaar 1078*071d4279SBram Moolenaar if (str == NULL) 1079*071d4279SBram Moolenaar { 1080*071d4279SBram Moolenaar PyErr_SetVim(_("invalid expression")); 1081*071d4279SBram Moolenaar return NULL; 1082*071d4279SBram Moolenaar } 1083*071d4279SBram Moolenaar 1084*071d4279SBram Moolenaar result = Py_BuildValue("s", str); 1085*071d4279SBram Moolenaar 1086*071d4279SBram Moolenaar Py_BEGIN_ALLOW_THREADS 1087*071d4279SBram Moolenaar Python_Lock_Vim(); 1088*071d4279SBram Moolenaar vim_free(str); 1089*071d4279SBram Moolenaar Python_Release_Vim(); 1090*071d4279SBram Moolenaar Py_END_ALLOW_THREADS 1091*071d4279SBram Moolenaar 1092*071d4279SBram Moolenaar return result; 1093*071d4279SBram Moolenaar #else 1094*071d4279SBram Moolenaar PyErr_SetVim(_("expressions disabled at compile time")); 1095*071d4279SBram Moolenaar return NULL; 1096*071d4279SBram Moolenaar #endif 1097*071d4279SBram Moolenaar } 1098*071d4279SBram Moolenaar 1099*071d4279SBram Moolenaar /* Common routines for buffers and line ranges 1100*071d4279SBram Moolenaar * ------------------------------------------- 1101*071d4279SBram Moolenaar */ 1102*071d4279SBram Moolenaar static int 1103*071d4279SBram Moolenaar CheckBuffer(BufferObject *this) 1104*071d4279SBram Moolenaar { 1105*071d4279SBram Moolenaar if (this->buf == INVALID_BUFFER_VALUE) 1106*071d4279SBram Moolenaar { 1107*071d4279SBram Moolenaar PyErr_SetVim(_("attempt to refer to deleted buffer")); 1108*071d4279SBram Moolenaar return -1; 1109*071d4279SBram Moolenaar } 1110*071d4279SBram Moolenaar 1111*071d4279SBram Moolenaar return 0; 1112*071d4279SBram Moolenaar } 1113*071d4279SBram Moolenaar 1114*071d4279SBram Moolenaar static PyObject * 1115*071d4279SBram Moolenaar RBItem(BufferObject *self, int n, int start, int end) 1116*071d4279SBram Moolenaar { 1117*071d4279SBram Moolenaar if (CheckBuffer(self)) 1118*071d4279SBram Moolenaar return NULL; 1119*071d4279SBram Moolenaar 1120*071d4279SBram Moolenaar if (n < 0 || n > end - start) 1121*071d4279SBram Moolenaar { 1122*071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("line number out of range")); 1123*071d4279SBram Moolenaar return NULL; 1124*071d4279SBram Moolenaar } 1125*071d4279SBram Moolenaar 1126*071d4279SBram Moolenaar return GetBufferLine(self->buf, n+start); 1127*071d4279SBram Moolenaar } 1128*071d4279SBram Moolenaar 1129*071d4279SBram Moolenaar static PyObject * 1130*071d4279SBram Moolenaar RBSlice(BufferObject *self, int lo, int hi, int start, int end) 1131*071d4279SBram Moolenaar { 1132*071d4279SBram Moolenaar int size; 1133*071d4279SBram Moolenaar 1134*071d4279SBram Moolenaar if (CheckBuffer(self)) 1135*071d4279SBram Moolenaar return NULL; 1136*071d4279SBram Moolenaar 1137*071d4279SBram Moolenaar size = end - start + 1; 1138*071d4279SBram Moolenaar 1139*071d4279SBram Moolenaar if (lo < 0) 1140*071d4279SBram Moolenaar lo = 0; 1141*071d4279SBram Moolenaar else if (lo > size) 1142*071d4279SBram Moolenaar lo = size; 1143*071d4279SBram Moolenaar if (hi < 0) 1144*071d4279SBram Moolenaar hi = 0; 1145*071d4279SBram Moolenaar if (hi < lo) 1146*071d4279SBram Moolenaar hi = lo; 1147*071d4279SBram Moolenaar else if (hi > size) 1148*071d4279SBram Moolenaar hi = size; 1149*071d4279SBram Moolenaar 1150*071d4279SBram Moolenaar return GetBufferLineList(self->buf, lo+start, hi+start); 1151*071d4279SBram Moolenaar } 1152*071d4279SBram Moolenaar 1153*071d4279SBram Moolenaar static int 1154*071d4279SBram Moolenaar RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end) 1155*071d4279SBram Moolenaar { 1156*071d4279SBram Moolenaar int len_change; 1157*071d4279SBram Moolenaar 1158*071d4279SBram Moolenaar if (CheckBuffer(self)) 1159*071d4279SBram Moolenaar return -1; 1160*071d4279SBram Moolenaar 1161*071d4279SBram Moolenaar if (n < 0 || n > end - start) 1162*071d4279SBram Moolenaar { 1163*071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("line number out of range")); 1164*071d4279SBram Moolenaar return -1; 1165*071d4279SBram Moolenaar } 1166*071d4279SBram Moolenaar 1167*071d4279SBram Moolenaar if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL) 1168*071d4279SBram Moolenaar return -1; 1169*071d4279SBram Moolenaar 1170*071d4279SBram Moolenaar if (new_end) 1171*071d4279SBram Moolenaar *new_end = end + len_change; 1172*071d4279SBram Moolenaar 1173*071d4279SBram Moolenaar return 0; 1174*071d4279SBram Moolenaar } 1175*071d4279SBram Moolenaar 1176*071d4279SBram Moolenaar static int 1177*071d4279SBram Moolenaar RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end) 1178*071d4279SBram Moolenaar { 1179*071d4279SBram Moolenaar int size; 1180*071d4279SBram Moolenaar int len_change; 1181*071d4279SBram Moolenaar 1182*071d4279SBram Moolenaar /* Self must be a valid buffer */ 1183*071d4279SBram Moolenaar if (CheckBuffer(self)) 1184*071d4279SBram Moolenaar return -1; 1185*071d4279SBram Moolenaar 1186*071d4279SBram Moolenaar /* Sort out the slice range */ 1187*071d4279SBram Moolenaar size = end - start + 1; 1188*071d4279SBram Moolenaar 1189*071d4279SBram Moolenaar if (lo < 0) 1190*071d4279SBram Moolenaar lo = 0; 1191*071d4279SBram Moolenaar else if (lo > size) 1192*071d4279SBram Moolenaar lo = size; 1193*071d4279SBram Moolenaar if (hi < 0) 1194*071d4279SBram Moolenaar hi = 0; 1195*071d4279SBram Moolenaar if (hi < lo) 1196*071d4279SBram Moolenaar hi = lo; 1197*071d4279SBram Moolenaar else if (hi > size) 1198*071d4279SBram Moolenaar hi = size; 1199*071d4279SBram Moolenaar 1200*071d4279SBram Moolenaar if (SetBufferLineList(self->buf, lo+start, hi+start, val, &len_change) == FAIL) 1201*071d4279SBram Moolenaar return -1; 1202*071d4279SBram Moolenaar 1203*071d4279SBram Moolenaar if (new_end) 1204*071d4279SBram Moolenaar *new_end = end + len_change; 1205*071d4279SBram Moolenaar 1206*071d4279SBram Moolenaar return 0; 1207*071d4279SBram Moolenaar } 1208*071d4279SBram Moolenaar 1209*071d4279SBram Moolenaar static PyObject * 1210*071d4279SBram Moolenaar RBAppend(BufferObject *self, PyObject *args, int start, int end, int *new_end) 1211*071d4279SBram Moolenaar { 1212*071d4279SBram Moolenaar PyObject *lines; 1213*071d4279SBram Moolenaar int len_change; 1214*071d4279SBram Moolenaar int max; 1215*071d4279SBram Moolenaar int n; 1216*071d4279SBram Moolenaar 1217*071d4279SBram Moolenaar if (CheckBuffer(self)) 1218*071d4279SBram Moolenaar return NULL; 1219*071d4279SBram Moolenaar 1220*071d4279SBram Moolenaar max = n = end - start + 1; 1221*071d4279SBram Moolenaar 1222*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "O|i", &lines, &n)) 1223*071d4279SBram Moolenaar return NULL; 1224*071d4279SBram Moolenaar 1225*071d4279SBram Moolenaar if (n < 0 || n > max) 1226*071d4279SBram Moolenaar { 1227*071d4279SBram Moolenaar PyErr_SetString(PyExc_ValueError, _("line number out of range")); 1228*071d4279SBram Moolenaar return NULL; 1229*071d4279SBram Moolenaar } 1230*071d4279SBram Moolenaar 1231*071d4279SBram Moolenaar if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL) 1232*071d4279SBram Moolenaar return NULL; 1233*071d4279SBram Moolenaar 1234*071d4279SBram Moolenaar if (new_end) 1235*071d4279SBram Moolenaar *new_end = end + len_change; 1236*071d4279SBram Moolenaar 1237*071d4279SBram Moolenaar Py_INCREF(Py_None); 1238*071d4279SBram Moolenaar return Py_None; 1239*071d4279SBram Moolenaar } 1240*071d4279SBram Moolenaar 1241*071d4279SBram Moolenaar 1242*071d4279SBram Moolenaar /* Buffer object - Definitions 1243*071d4279SBram Moolenaar */ 1244*071d4279SBram Moolenaar 1245*071d4279SBram Moolenaar static struct PyMethodDef BufferMethods[] = { 1246*071d4279SBram Moolenaar /* name, function, calling, documentation */ 1247*071d4279SBram Moolenaar {"append", BufferAppend, 1, "" }, 1248*071d4279SBram Moolenaar {"mark", BufferMark, 1, "" }, 1249*071d4279SBram Moolenaar {"range", BufferRange, 1, "" }, 1250*071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1251*071d4279SBram Moolenaar }; 1252*071d4279SBram Moolenaar 1253*071d4279SBram Moolenaar static PySequenceMethods BufferAsSeq = { 1254*071d4279SBram Moolenaar (inquiry) BufferLength, /* sq_length, len(x) */ 1255*071d4279SBram Moolenaar (binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */ 1256*071d4279SBram Moolenaar (intargfunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */ 1257*071d4279SBram Moolenaar (intargfunc) BufferItem, /* sq_item, x[i] */ 1258*071d4279SBram Moolenaar (intintargfunc) BufferSlice, /* sq_slice, x[i:j] */ 1259*071d4279SBram Moolenaar (intobjargproc) BufferAssItem, /* sq_ass_item, x[i]=v */ 1260*071d4279SBram Moolenaar (intintobjargproc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */ 1261*071d4279SBram Moolenaar }; 1262*071d4279SBram Moolenaar 1263*071d4279SBram Moolenaar static PyTypeObject BufferType = { 1264*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1265*071d4279SBram Moolenaar 0, 1266*071d4279SBram Moolenaar "buffer", 1267*071d4279SBram Moolenaar sizeof(BufferObject), 1268*071d4279SBram Moolenaar 0, 1269*071d4279SBram Moolenaar 1270*071d4279SBram Moolenaar (destructor) BufferDestructor, /* tp_dealloc, refcount==0 */ 1271*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1272*071d4279SBram Moolenaar (getattrfunc) BufferGetattr, /* tp_getattr, x.attr */ 1273*071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1274*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1275*071d4279SBram Moolenaar (reprfunc) BufferRepr, /* tp_repr, `x`, print x */ 1276*071d4279SBram Moolenaar 1277*071d4279SBram Moolenaar 0, /* as number */ 1278*071d4279SBram Moolenaar &BufferAsSeq, /* as sequence */ 1279*071d4279SBram Moolenaar 0, /* as mapping */ 1280*071d4279SBram Moolenaar 1281*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1282*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1283*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1284*071d4279SBram Moolenaar }; 1285*071d4279SBram Moolenaar 1286*071d4279SBram Moolenaar /* Buffer object - Implementation 1287*071d4279SBram Moolenaar */ 1288*071d4279SBram Moolenaar 1289*071d4279SBram Moolenaar static PyObject * 1290*071d4279SBram Moolenaar BufferNew(buf_T *buf) 1291*071d4279SBram Moolenaar { 1292*071d4279SBram Moolenaar /* We need to handle deletion of buffers underneath us. 1293*071d4279SBram Moolenaar * If we add a "python_ref" field to the buf_T structure, 1294*071d4279SBram Moolenaar * then we can get at it in buf_freeall() in vim. We then 1295*071d4279SBram Moolenaar * need to create only ONE Python object per buffer - if 1296*071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 1297*071d4279SBram Moolenaar * and return it. The (single) Python object referring to 1298*071d4279SBram Moolenaar * the buffer is stored in "python_ref". 1299*071d4279SBram Moolenaar * Question: what to do on a buf_freeall(). We'll probably 1300*071d4279SBram Moolenaar * have to either delete the Python object (DECREF it to 1301*071d4279SBram Moolenaar * zero - a bad idea, as it leaves dangling refs!) or 1302*071d4279SBram Moolenaar * set the buf_T * value to an invalid value (-1?), which 1303*071d4279SBram Moolenaar * means we need checks in all access functions... Bah. 1304*071d4279SBram Moolenaar */ 1305*071d4279SBram Moolenaar 1306*071d4279SBram Moolenaar BufferObject *self; 1307*071d4279SBram Moolenaar 1308*071d4279SBram Moolenaar if (buf->python_ref) 1309*071d4279SBram Moolenaar { 1310*071d4279SBram Moolenaar self = buf->python_ref; 1311*071d4279SBram Moolenaar Py_INCREF(self); 1312*071d4279SBram Moolenaar } 1313*071d4279SBram Moolenaar else 1314*071d4279SBram Moolenaar { 1315*071d4279SBram Moolenaar self = PyObject_NEW(BufferObject, &BufferType); 1316*071d4279SBram Moolenaar if (self == NULL) 1317*071d4279SBram Moolenaar return NULL; 1318*071d4279SBram Moolenaar self->buf = buf; 1319*071d4279SBram Moolenaar buf->python_ref = self; 1320*071d4279SBram Moolenaar } 1321*071d4279SBram Moolenaar 1322*071d4279SBram Moolenaar return (PyObject *)(self); 1323*071d4279SBram Moolenaar } 1324*071d4279SBram Moolenaar 1325*071d4279SBram Moolenaar static void 1326*071d4279SBram Moolenaar BufferDestructor(PyObject *self) 1327*071d4279SBram Moolenaar { 1328*071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1329*071d4279SBram Moolenaar 1330*071d4279SBram Moolenaar if (this->buf && this->buf != INVALID_BUFFER_VALUE) 1331*071d4279SBram Moolenaar this->buf->python_ref = NULL; 1332*071d4279SBram Moolenaar 1333*071d4279SBram Moolenaar PyMem_DEL(self); 1334*071d4279SBram Moolenaar } 1335*071d4279SBram Moolenaar 1336*071d4279SBram Moolenaar static PyObject * 1337*071d4279SBram Moolenaar BufferGetattr(PyObject *self, char *name) 1338*071d4279SBram Moolenaar { 1339*071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1340*071d4279SBram Moolenaar 1341*071d4279SBram Moolenaar if (CheckBuffer(this)) 1342*071d4279SBram Moolenaar return NULL; 1343*071d4279SBram Moolenaar 1344*071d4279SBram Moolenaar if (strcmp(name, "name") == 0) 1345*071d4279SBram Moolenaar return Py_BuildValue("s",this->buf->b_ffname); 1346*071d4279SBram Moolenaar else if (strcmp(name, "number") == 0) 1347*071d4279SBram Moolenaar return Py_BuildValue("i",this->buf->b_fnum); 1348*071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1349*071d4279SBram Moolenaar return Py_BuildValue("[ss]", "name", "number"); 1350*071d4279SBram Moolenaar else 1351*071d4279SBram Moolenaar return Py_FindMethod(BufferMethods, self, name); 1352*071d4279SBram Moolenaar } 1353*071d4279SBram Moolenaar 1354*071d4279SBram Moolenaar static PyObject * 1355*071d4279SBram Moolenaar BufferRepr(PyObject *self) 1356*071d4279SBram Moolenaar { 1357*071d4279SBram Moolenaar static char repr[50]; 1358*071d4279SBram Moolenaar BufferObject *this = (BufferObject *)(self); 1359*071d4279SBram Moolenaar 1360*071d4279SBram Moolenaar if (this->buf == INVALID_BUFFER_VALUE) 1361*071d4279SBram Moolenaar { 1362*071d4279SBram Moolenaar sprintf(repr, _("<buffer object (deleted) at %8lX>"), (long)(self)); 1363*071d4279SBram Moolenaar return PyString_FromString(repr); 1364*071d4279SBram Moolenaar } 1365*071d4279SBram Moolenaar else 1366*071d4279SBram Moolenaar { 1367*071d4279SBram Moolenaar char *name = (char *)this->buf->b_fname; 1368*071d4279SBram Moolenaar int len; 1369*071d4279SBram Moolenaar 1370*071d4279SBram Moolenaar if (name == NULL) 1371*071d4279SBram Moolenaar name = ""; 1372*071d4279SBram Moolenaar len = strlen(name); 1373*071d4279SBram Moolenaar 1374*071d4279SBram Moolenaar if (len > 35) 1375*071d4279SBram Moolenaar name = name + (35 - len); 1376*071d4279SBram Moolenaar 1377*071d4279SBram Moolenaar sprintf(repr, "<buffer %s%s>", len > 35 ? "..." : "", name); 1378*071d4279SBram Moolenaar 1379*071d4279SBram Moolenaar return PyString_FromString(repr); 1380*071d4279SBram Moolenaar } 1381*071d4279SBram Moolenaar } 1382*071d4279SBram Moolenaar 1383*071d4279SBram Moolenaar /******************/ 1384*071d4279SBram Moolenaar 1385*071d4279SBram Moolenaar static int 1386*071d4279SBram Moolenaar BufferLength(PyObject *self) 1387*071d4279SBram Moolenaar { 1388*071d4279SBram Moolenaar /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ 1389*071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1390*071d4279SBram Moolenaar return -1; /* ??? */ 1391*071d4279SBram Moolenaar 1392*071d4279SBram Moolenaar return (((BufferObject *)(self))->buf->b_ml.ml_line_count); 1393*071d4279SBram Moolenaar } 1394*071d4279SBram Moolenaar 1395*071d4279SBram Moolenaar static PyObject * 1396*071d4279SBram Moolenaar BufferItem(PyObject *self, int n) 1397*071d4279SBram Moolenaar { 1398*071d4279SBram Moolenaar return RBItem((BufferObject *)(self), n, 1, 1399*071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1400*071d4279SBram Moolenaar } 1401*071d4279SBram Moolenaar 1402*071d4279SBram Moolenaar static PyObject * 1403*071d4279SBram Moolenaar BufferSlice(PyObject *self, int lo, int hi) 1404*071d4279SBram Moolenaar { 1405*071d4279SBram Moolenaar return RBSlice((BufferObject *)(self), lo, hi, 1, 1406*071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count); 1407*071d4279SBram Moolenaar } 1408*071d4279SBram Moolenaar 1409*071d4279SBram Moolenaar static int 1410*071d4279SBram Moolenaar BufferAssItem(PyObject *self, int n, PyObject *val) 1411*071d4279SBram Moolenaar { 1412*071d4279SBram Moolenaar return RBAssItem((BufferObject *)(self), n, val, 1, 1413*071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1414*071d4279SBram Moolenaar NULL); 1415*071d4279SBram Moolenaar } 1416*071d4279SBram Moolenaar 1417*071d4279SBram Moolenaar static int 1418*071d4279SBram Moolenaar BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val) 1419*071d4279SBram Moolenaar { 1420*071d4279SBram Moolenaar return RBAssSlice((BufferObject *)(self), lo, hi, val, 1, 1421*071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1422*071d4279SBram Moolenaar NULL); 1423*071d4279SBram Moolenaar } 1424*071d4279SBram Moolenaar 1425*071d4279SBram Moolenaar static PyObject * 1426*071d4279SBram Moolenaar BufferAppend(PyObject *self, PyObject *args) 1427*071d4279SBram Moolenaar { 1428*071d4279SBram Moolenaar return RBAppend((BufferObject *)(self), args, 1, 1429*071d4279SBram Moolenaar (int)((BufferObject *)(self))->buf->b_ml.ml_line_count, 1430*071d4279SBram Moolenaar NULL); 1431*071d4279SBram Moolenaar } 1432*071d4279SBram Moolenaar 1433*071d4279SBram Moolenaar static PyObject * 1434*071d4279SBram Moolenaar BufferMark(PyObject *self, PyObject *args) 1435*071d4279SBram Moolenaar { 1436*071d4279SBram Moolenaar pos_T *posp; 1437*071d4279SBram Moolenaar char mark; 1438*071d4279SBram Moolenaar buf_T *curbuf_save; 1439*071d4279SBram Moolenaar 1440*071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1441*071d4279SBram Moolenaar return NULL; 1442*071d4279SBram Moolenaar 1443*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "c", &mark)) 1444*071d4279SBram Moolenaar return NULL; 1445*071d4279SBram Moolenaar 1446*071d4279SBram Moolenaar curbuf_save = curbuf; 1447*071d4279SBram Moolenaar curbuf = ((BufferObject *)(self))->buf; 1448*071d4279SBram Moolenaar posp = getmark(mark, FALSE); 1449*071d4279SBram Moolenaar curbuf = curbuf_save; 1450*071d4279SBram Moolenaar 1451*071d4279SBram Moolenaar if (posp == NULL) 1452*071d4279SBram Moolenaar { 1453*071d4279SBram Moolenaar PyErr_SetVim(_("invalid mark name")); 1454*071d4279SBram Moolenaar return NULL; 1455*071d4279SBram Moolenaar } 1456*071d4279SBram Moolenaar 1457*071d4279SBram Moolenaar /* Ckeck for keyboard interrupt */ 1458*071d4279SBram Moolenaar if (VimErrorCheck()) 1459*071d4279SBram Moolenaar return NULL; 1460*071d4279SBram Moolenaar 1461*071d4279SBram Moolenaar if (posp->lnum <= 0) 1462*071d4279SBram Moolenaar { 1463*071d4279SBram Moolenaar /* Or raise an error? */ 1464*071d4279SBram Moolenaar Py_INCREF(Py_None); 1465*071d4279SBram Moolenaar return Py_None; 1466*071d4279SBram Moolenaar } 1467*071d4279SBram Moolenaar 1468*071d4279SBram Moolenaar return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col)); 1469*071d4279SBram Moolenaar } 1470*071d4279SBram Moolenaar 1471*071d4279SBram Moolenaar static PyObject * 1472*071d4279SBram Moolenaar BufferRange(PyObject *self, PyObject *args) 1473*071d4279SBram Moolenaar { 1474*071d4279SBram Moolenaar int start; 1475*071d4279SBram Moolenaar int end; 1476*071d4279SBram Moolenaar 1477*071d4279SBram Moolenaar if (CheckBuffer((BufferObject *)(self))) 1478*071d4279SBram Moolenaar return NULL; 1479*071d4279SBram Moolenaar 1480*071d4279SBram Moolenaar if (!PyArg_ParseTuple(args, "ii", &start, &end)) 1481*071d4279SBram Moolenaar return NULL; 1482*071d4279SBram Moolenaar 1483*071d4279SBram Moolenaar return RangeNew(((BufferObject *)(self))->buf, start, end); 1484*071d4279SBram Moolenaar } 1485*071d4279SBram Moolenaar 1486*071d4279SBram Moolenaar /* Line range object - Definitions 1487*071d4279SBram Moolenaar */ 1488*071d4279SBram Moolenaar 1489*071d4279SBram Moolenaar static struct PyMethodDef RangeMethods[] = { 1490*071d4279SBram Moolenaar /* name, function, calling, documentation */ 1491*071d4279SBram Moolenaar {"append", RangeAppend, 1, "" }, 1492*071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1493*071d4279SBram Moolenaar }; 1494*071d4279SBram Moolenaar 1495*071d4279SBram Moolenaar static PySequenceMethods RangeAsSeq = { 1496*071d4279SBram Moolenaar (inquiry) RangeLength, /* sq_length, len(x) */ 1497*071d4279SBram Moolenaar (binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */ 1498*071d4279SBram Moolenaar (intargfunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */ 1499*071d4279SBram Moolenaar (intargfunc) RangeItem, /* sq_item, x[i] */ 1500*071d4279SBram Moolenaar (intintargfunc) RangeSlice, /* sq_slice, x[i:j] */ 1501*071d4279SBram Moolenaar (intobjargproc) RangeAssItem, /* sq_ass_item, x[i]=v */ 1502*071d4279SBram Moolenaar (intintobjargproc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */ 1503*071d4279SBram Moolenaar }; 1504*071d4279SBram Moolenaar 1505*071d4279SBram Moolenaar static PyTypeObject RangeType = { 1506*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1507*071d4279SBram Moolenaar 0, 1508*071d4279SBram Moolenaar "range", 1509*071d4279SBram Moolenaar sizeof(RangeObject), 1510*071d4279SBram Moolenaar 0, 1511*071d4279SBram Moolenaar 1512*071d4279SBram Moolenaar (destructor) RangeDestructor, /* tp_dealloc, refcount==0 */ 1513*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1514*071d4279SBram Moolenaar (getattrfunc) RangeGetattr, /* tp_getattr, x.attr */ 1515*071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1516*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1517*071d4279SBram Moolenaar (reprfunc) RangeRepr, /* tp_repr, `x`, print x */ 1518*071d4279SBram Moolenaar 1519*071d4279SBram Moolenaar 0, /* as number */ 1520*071d4279SBram Moolenaar &RangeAsSeq, /* as sequence */ 1521*071d4279SBram Moolenaar 0, /* as mapping */ 1522*071d4279SBram Moolenaar 1523*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1524*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1525*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1526*071d4279SBram Moolenaar }; 1527*071d4279SBram Moolenaar 1528*071d4279SBram Moolenaar /* Line range object - Implementation 1529*071d4279SBram Moolenaar */ 1530*071d4279SBram Moolenaar 1531*071d4279SBram Moolenaar static PyObject * 1532*071d4279SBram Moolenaar RangeNew(buf_T *buf, int start, int end) 1533*071d4279SBram Moolenaar { 1534*071d4279SBram Moolenaar BufferObject *bufr; 1535*071d4279SBram Moolenaar RangeObject *self; 1536*071d4279SBram Moolenaar self = PyObject_NEW(RangeObject, &RangeType); 1537*071d4279SBram Moolenaar if (self == NULL) 1538*071d4279SBram Moolenaar return NULL; 1539*071d4279SBram Moolenaar 1540*071d4279SBram Moolenaar bufr = (BufferObject *)BufferNew(buf); 1541*071d4279SBram Moolenaar if (bufr == NULL) 1542*071d4279SBram Moolenaar { 1543*071d4279SBram Moolenaar PyMem_DEL(self); 1544*071d4279SBram Moolenaar return NULL; 1545*071d4279SBram Moolenaar } 1546*071d4279SBram Moolenaar Py_INCREF(bufr); 1547*071d4279SBram Moolenaar 1548*071d4279SBram Moolenaar self->buf = bufr; 1549*071d4279SBram Moolenaar self->start = start; 1550*071d4279SBram Moolenaar self->end = end; 1551*071d4279SBram Moolenaar 1552*071d4279SBram Moolenaar return (PyObject *)(self); 1553*071d4279SBram Moolenaar } 1554*071d4279SBram Moolenaar 1555*071d4279SBram Moolenaar static void 1556*071d4279SBram Moolenaar RangeDestructor(PyObject *self) 1557*071d4279SBram Moolenaar { 1558*071d4279SBram Moolenaar Py_DECREF(((RangeObject *)(self))->buf); 1559*071d4279SBram Moolenaar PyMem_DEL(self); 1560*071d4279SBram Moolenaar } 1561*071d4279SBram Moolenaar 1562*071d4279SBram Moolenaar static PyObject * 1563*071d4279SBram Moolenaar RangeGetattr(PyObject *self, char *name) 1564*071d4279SBram Moolenaar { 1565*071d4279SBram Moolenaar if (strcmp(name, "start") == 0) 1566*071d4279SBram Moolenaar return Py_BuildValue("i",((RangeObject *)(self))->start - 1); 1567*071d4279SBram Moolenaar else if (strcmp(name, "end") == 0) 1568*071d4279SBram Moolenaar return Py_BuildValue("i",((RangeObject *)(self))->end - 1); 1569*071d4279SBram Moolenaar else 1570*071d4279SBram Moolenaar return Py_FindMethod(RangeMethods, self, name); 1571*071d4279SBram Moolenaar } 1572*071d4279SBram Moolenaar 1573*071d4279SBram Moolenaar static PyObject * 1574*071d4279SBram Moolenaar RangeRepr(PyObject *self) 1575*071d4279SBram Moolenaar { 1576*071d4279SBram Moolenaar static char repr[75]; 1577*071d4279SBram Moolenaar RangeObject *this = (RangeObject *)(self); 1578*071d4279SBram Moolenaar 1579*071d4279SBram Moolenaar if (this->buf->buf == INVALID_BUFFER_VALUE) 1580*071d4279SBram Moolenaar { 1581*071d4279SBram Moolenaar sprintf(repr, "<range object (for deleted buffer) at %8lX>", 1582*071d4279SBram Moolenaar (long)(self)); 1583*071d4279SBram Moolenaar return PyString_FromString(repr); 1584*071d4279SBram Moolenaar } 1585*071d4279SBram Moolenaar else 1586*071d4279SBram Moolenaar { 1587*071d4279SBram Moolenaar char *name = (char *)this->buf->buf->b_fname; 1588*071d4279SBram Moolenaar int len; 1589*071d4279SBram Moolenaar 1590*071d4279SBram Moolenaar if (name == NULL) 1591*071d4279SBram Moolenaar name = ""; 1592*071d4279SBram Moolenaar len = strlen(name); 1593*071d4279SBram Moolenaar 1594*071d4279SBram Moolenaar if (len > 45) 1595*071d4279SBram Moolenaar name = name + (45 - len); 1596*071d4279SBram Moolenaar 1597*071d4279SBram Moolenaar sprintf(repr, "<range %s%s (%d:%d)>", 1598*071d4279SBram Moolenaar len > 45 ? "..." : "", name, 1599*071d4279SBram Moolenaar this->start, this->end); 1600*071d4279SBram Moolenaar 1601*071d4279SBram Moolenaar return PyString_FromString(repr); 1602*071d4279SBram Moolenaar } 1603*071d4279SBram Moolenaar } 1604*071d4279SBram Moolenaar 1605*071d4279SBram Moolenaar /****************/ 1606*071d4279SBram Moolenaar 1607*071d4279SBram Moolenaar static int 1608*071d4279SBram Moolenaar RangeLength(PyObject *self) 1609*071d4279SBram Moolenaar { 1610*071d4279SBram Moolenaar /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */ 1611*071d4279SBram Moolenaar if (CheckBuffer(((RangeObject *)(self))->buf)) 1612*071d4279SBram Moolenaar return -1; /* ??? */ 1613*071d4279SBram Moolenaar 1614*071d4279SBram Moolenaar return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1); 1615*071d4279SBram Moolenaar } 1616*071d4279SBram Moolenaar 1617*071d4279SBram Moolenaar static PyObject * 1618*071d4279SBram Moolenaar RangeItem(PyObject *self, int n) 1619*071d4279SBram Moolenaar { 1620*071d4279SBram Moolenaar return RBItem(((RangeObject *)(self))->buf, n, 1621*071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1622*071d4279SBram Moolenaar ((RangeObject *)(self))->end); 1623*071d4279SBram Moolenaar } 1624*071d4279SBram Moolenaar 1625*071d4279SBram Moolenaar static PyObject * 1626*071d4279SBram Moolenaar RangeSlice(PyObject *self, int lo, int hi) 1627*071d4279SBram Moolenaar { 1628*071d4279SBram Moolenaar return RBSlice(((RangeObject *)(self))->buf, lo, hi, 1629*071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1630*071d4279SBram Moolenaar ((RangeObject *)(self))->end); 1631*071d4279SBram Moolenaar } 1632*071d4279SBram Moolenaar 1633*071d4279SBram Moolenaar static int 1634*071d4279SBram Moolenaar RangeAssItem(PyObject *self, int n, PyObject *val) 1635*071d4279SBram Moolenaar { 1636*071d4279SBram Moolenaar return RBAssItem(((RangeObject *)(self))->buf, n, val, 1637*071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1638*071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1639*071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1640*071d4279SBram Moolenaar } 1641*071d4279SBram Moolenaar 1642*071d4279SBram Moolenaar static int 1643*071d4279SBram Moolenaar RangeAssSlice(PyObject *self, int lo, int hi, PyObject *val) 1644*071d4279SBram Moolenaar { 1645*071d4279SBram Moolenaar return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val, 1646*071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1647*071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1648*071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1649*071d4279SBram Moolenaar } 1650*071d4279SBram Moolenaar 1651*071d4279SBram Moolenaar static PyObject * 1652*071d4279SBram Moolenaar RangeAppend(PyObject *self, PyObject *args) 1653*071d4279SBram Moolenaar { 1654*071d4279SBram Moolenaar return RBAppend(((RangeObject *)(self))->buf, args, 1655*071d4279SBram Moolenaar ((RangeObject *)(self))->start, 1656*071d4279SBram Moolenaar ((RangeObject *)(self))->end, 1657*071d4279SBram Moolenaar &((RangeObject *)(self))->end); 1658*071d4279SBram Moolenaar } 1659*071d4279SBram Moolenaar 1660*071d4279SBram Moolenaar /* Buffer list object - Definitions 1661*071d4279SBram Moolenaar */ 1662*071d4279SBram Moolenaar 1663*071d4279SBram Moolenaar typedef struct 1664*071d4279SBram Moolenaar { 1665*071d4279SBram Moolenaar PyObject_HEAD 1666*071d4279SBram Moolenaar } 1667*071d4279SBram Moolenaar BufListObject; 1668*071d4279SBram Moolenaar 1669*071d4279SBram Moolenaar static PySequenceMethods BufListAsSeq = { 1670*071d4279SBram Moolenaar (inquiry) BufListLength, /* sq_length, len(x) */ 1671*071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 1672*071d4279SBram Moolenaar (intargfunc) 0, /* sq_repeat, x*n */ 1673*071d4279SBram Moolenaar (intargfunc) BufListItem, /* sq_item, x[i] */ 1674*071d4279SBram Moolenaar (intintargfunc) 0, /* sq_slice, x[i:j] */ 1675*071d4279SBram Moolenaar (intobjargproc) 0, /* sq_ass_item, x[i]=v */ 1676*071d4279SBram Moolenaar (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */ 1677*071d4279SBram Moolenaar }; 1678*071d4279SBram Moolenaar 1679*071d4279SBram Moolenaar static PyTypeObject BufListType = { 1680*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1681*071d4279SBram Moolenaar 0, 1682*071d4279SBram Moolenaar "buffer list", 1683*071d4279SBram Moolenaar sizeof(BufListObject), 1684*071d4279SBram Moolenaar 0, 1685*071d4279SBram Moolenaar 1686*071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 1687*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1688*071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 1689*071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 1690*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1691*071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 1692*071d4279SBram Moolenaar 1693*071d4279SBram Moolenaar 0, /* as number */ 1694*071d4279SBram Moolenaar &BufListAsSeq, /* as sequence */ 1695*071d4279SBram Moolenaar 0, /* as mapping */ 1696*071d4279SBram Moolenaar 1697*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1698*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1699*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1700*071d4279SBram Moolenaar }; 1701*071d4279SBram Moolenaar 1702*071d4279SBram Moolenaar /* Buffer list object - Implementation 1703*071d4279SBram Moolenaar */ 1704*071d4279SBram Moolenaar 1705*071d4279SBram Moolenaar /*ARGSUSED*/ 1706*071d4279SBram Moolenaar static int 1707*071d4279SBram Moolenaar BufListLength(PyObject *self) 1708*071d4279SBram Moolenaar { 1709*071d4279SBram Moolenaar buf_T *b = firstbuf; 1710*071d4279SBram Moolenaar int n = 0; 1711*071d4279SBram Moolenaar 1712*071d4279SBram Moolenaar while (b) 1713*071d4279SBram Moolenaar { 1714*071d4279SBram Moolenaar ++n; 1715*071d4279SBram Moolenaar b = b->b_next; 1716*071d4279SBram Moolenaar } 1717*071d4279SBram Moolenaar 1718*071d4279SBram Moolenaar return n; 1719*071d4279SBram Moolenaar } 1720*071d4279SBram Moolenaar 1721*071d4279SBram Moolenaar /*ARGSUSED*/ 1722*071d4279SBram Moolenaar static PyObject * 1723*071d4279SBram Moolenaar BufListItem(PyObject *self, int n) 1724*071d4279SBram Moolenaar { 1725*071d4279SBram Moolenaar buf_T *b; 1726*071d4279SBram Moolenaar 1727*071d4279SBram Moolenaar for (b = firstbuf; b; b = b->b_next, --n) 1728*071d4279SBram Moolenaar { 1729*071d4279SBram Moolenaar if (n == 0) 1730*071d4279SBram Moolenaar return BufferNew(b); 1731*071d4279SBram Moolenaar } 1732*071d4279SBram Moolenaar 1733*071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("no such buffer")); 1734*071d4279SBram Moolenaar return NULL; 1735*071d4279SBram Moolenaar } 1736*071d4279SBram Moolenaar 1737*071d4279SBram Moolenaar /* Window object - Definitions 1738*071d4279SBram Moolenaar */ 1739*071d4279SBram Moolenaar 1740*071d4279SBram Moolenaar static struct PyMethodDef WindowMethods[] = { 1741*071d4279SBram Moolenaar /* name, function, calling, documentation */ 1742*071d4279SBram Moolenaar { NULL, NULL, 0, NULL } 1743*071d4279SBram Moolenaar }; 1744*071d4279SBram Moolenaar 1745*071d4279SBram Moolenaar static PyTypeObject WindowType = { 1746*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1747*071d4279SBram Moolenaar 0, 1748*071d4279SBram Moolenaar "window", 1749*071d4279SBram Moolenaar sizeof(WindowObject), 1750*071d4279SBram Moolenaar 0, 1751*071d4279SBram Moolenaar 1752*071d4279SBram Moolenaar (destructor) WindowDestructor, /* tp_dealloc, refcount==0 */ 1753*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 1754*071d4279SBram Moolenaar (getattrfunc) WindowGetattr, /* tp_getattr, x.attr */ 1755*071d4279SBram Moolenaar (setattrfunc) WindowSetattr, /* tp_setattr, x.attr=v */ 1756*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 1757*071d4279SBram Moolenaar (reprfunc) WindowRepr, /* tp_repr, `x`, print x */ 1758*071d4279SBram Moolenaar 1759*071d4279SBram Moolenaar 0, /* as number */ 1760*071d4279SBram Moolenaar 0, /* as sequence */ 1761*071d4279SBram Moolenaar 0, /* as mapping */ 1762*071d4279SBram Moolenaar 1763*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 1764*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 1765*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 1766*071d4279SBram Moolenaar }; 1767*071d4279SBram Moolenaar 1768*071d4279SBram Moolenaar /* Window object - Implementation 1769*071d4279SBram Moolenaar */ 1770*071d4279SBram Moolenaar 1771*071d4279SBram Moolenaar static PyObject * 1772*071d4279SBram Moolenaar WindowNew(win_T *win) 1773*071d4279SBram Moolenaar { 1774*071d4279SBram Moolenaar /* We need to handle deletion of windows underneath us. 1775*071d4279SBram Moolenaar * If we add a "python_ref" field to the win_T structure, 1776*071d4279SBram Moolenaar * then we can get at it in win_free() in vim. We then 1777*071d4279SBram Moolenaar * need to create only ONE Python object per window - if 1778*071d4279SBram Moolenaar * we try to create a second, just INCREF the existing one 1779*071d4279SBram Moolenaar * and return it. The (single) Python object referring to 1780*071d4279SBram Moolenaar * the window is stored in "python_ref". 1781*071d4279SBram Moolenaar * On a win_free() we set the Python object's win_T* field 1782*071d4279SBram Moolenaar * to an invalid value. We trap all uses of a window 1783*071d4279SBram Moolenaar * object, and reject them if the win_T* field is invalid. 1784*071d4279SBram Moolenaar */ 1785*071d4279SBram Moolenaar 1786*071d4279SBram Moolenaar WindowObject *self; 1787*071d4279SBram Moolenaar 1788*071d4279SBram Moolenaar if (win->python_ref) 1789*071d4279SBram Moolenaar { 1790*071d4279SBram Moolenaar self = win->python_ref; 1791*071d4279SBram Moolenaar Py_INCREF(self); 1792*071d4279SBram Moolenaar } 1793*071d4279SBram Moolenaar else 1794*071d4279SBram Moolenaar { 1795*071d4279SBram Moolenaar self = PyObject_NEW(WindowObject, &WindowType); 1796*071d4279SBram Moolenaar if (self == NULL) 1797*071d4279SBram Moolenaar return NULL; 1798*071d4279SBram Moolenaar self->win = win; 1799*071d4279SBram Moolenaar win->python_ref = self; 1800*071d4279SBram Moolenaar } 1801*071d4279SBram Moolenaar 1802*071d4279SBram Moolenaar return (PyObject *)(self); 1803*071d4279SBram Moolenaar } 1804*071d4279SBram Moolenaar 1805*071d4279SBram Moolenaar static void 1806*071d4279SBram Moolenaar WindowDestructor(PyObject *self) 1807*071d4279SBram Moolenaar { 1808*071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1809*071d4279SBram Moolenaar 1810*071d4279SBram Moolenaar if (this->win && this->win != INVALID_WINDOW_VALUE) 1811*071d4279SBram Moolenaar this->win->python_ref = NULL; 1812*071d4279SBram Moolenaar 1813*071d4279SBram Moolenaar PyMem_DEL(self); 1814*071d4279SBram Moolenaar } 1815*071d4279SBram Moolenaar 1816*071d4279SBram Moolenaar static int 1817*071d4279SBram Moolenaar CheckWindow(WindowObject *this) 1818*071d4279SBram Moolenaar { 1819*071d4279SBram Moolenaar if (this->win == INVALID_WINDOW_VALUE) 1820*071d4279SBram Moolenaar { 1821*071d4279SBram Moolenaar PyErr_SetVim(_("attempt to refer to deleted window")); 1822*071d4279SBram Moolenaar return -1; 1823*071d4279SBram Moolenaar } 1824*071d4279SBram Moolenaar 1825*071d4279SBram Moolenaar return 0; 1826*071d4279SBram Moolenaar } 1827*071d4279SBram Moolenaar 1828*071d4279SBram Moolenaar static PyObject * 1829*071d4279SBram Moolenaar WindowGetattr(PyObject *self, char *name) 1830*071d4279SBram Moolenaar { 1831*071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1832*071d4279SBram Moolenaar 1833*071d4279SBram Moolenaar if (CheckWindow(this)) 1834*071d4279SBram Moolenaar return NULL; 1835*071d4279SBram Moolenaar 1836*071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1837*071d4279SBram Moolenaar return (PyObject *)BufferNew(this->win->w_buffer); 1838*071d4279SBram Moolenaar else if (strcmp(name, "cursor") == 0) 1839*071d4279SBram Moolenaar { 1840*071d4279SBram Moolenaar pos_T *pos = &this->win->w_cursor; 1841*071d4279SBram Moolenaar 1842*071d4279SBram Moolenaar return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col)); 1843*071d4279SBram Moolenaar } 1844*071d4279SBram Moolenaar else if (strcmp(name, "height") == 0) 1845*071d4279SBram Moolenaar return Py_BuildValue("l", (long)(this->win->w_height)); 1846*071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT 1847*071d4279SBram Moolenaar else if (strcmp(name, "width") == 0) 1848*071d4279SBram Moolenaar return Py_BuildValue("l", (long)(W_WIDTH(this->win))); 1849*071d4279SBram Moolenaar #endif 1850*071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 1851*071d4279SBram Moolenaar return Py_BuildValue("[sss]", "buffer", "cursor", "height"); 1852*071d4279SBram Moolenaar else 1853*071d4279SBram Moolenaar return Py_FindMethod(WindowMethods, self, name); 1854*071d4279SBram Moolenaar } 1855*071d4279SBram Moolenaar 1856*071d4279SBram Moolenaar static int 1857*071d4279SBram Moolenaar WindowSetattr(PyObject *self, char *name, PyObject *val) 1858*071d4279SBram Moolenaar { 1859*071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1860*071d4279SBram Moolenaar 1861*071d4279SBram Moolenaar if (CheckWindow(this)) 1862*071d4279SBram Moolenaar return -1; 1863*071d4279SBram Moolenaar 1864*071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 1865*071d4279SBram Moolenaar { 1866*071d4279SBram Moolenaar PyErr_SetString(PyExc_TypeError, _("readonly attribute")); 1867*071d4279SBram Moolenaar return -1; 1868*071d4279SBram Moolenaar } 1869*071d4279SBram Moolenaar else if (strcmp(name, "cursor") == 0) 1870*071d4279SBram Moolenaar { 1871*071d4279SBram Moolenaar long lnum; 1872*071d4279SBram Moolenaar long col; 1873*071d4279SBram Moolenaar 1874*071d4279SBram Moolenaar if (!PyArg_Parse(val, "(ll)", &lnum, &col)) 1875*071d4279SBram Moolenaar return -1; 1876*071d4279SBram Moolenaar 1877*071d4279SBram Moolenaar if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count) 1878*071d4279SBram Moolenaar { 1879*071d4279SBram Moolenaar PyErr_SetVim(_("cursor position outside buffer")); 1880*071d4279SBram Moolenaar return -1; 1881*071d4279SBram Moolenaar } 1882*071d4279SBram Moolenaar 1883*071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1884*071d4279SBram Moolenaar if (VimErrorCheck()) 1885*071d4279SBram Moolenaar return -1; 1886*071d4279SBram Moolenaar 1887*071d4279SBram Moolenaar /* NO CHECK ON COLUMN - SEEMS NOT TO MATTER */ 1888*071d4279SBram Moolenaar 1889*071d4279SBram Moolenaar this->win->w_cursor.lnum = lnum; 1890*071d4279SBram Moolenaar this->win->w_cursor.col = col; 1891*071d4279SBram Moolenaar update_screen(VALID); 1892*071d4279SBram Moolenaar 1893*071d4279SBram Moolenaar return 0; 1894*071d4279SBram Moolenaar } 1895*071d4279SBram Moolenaar else if (strcmp(name, "height") == 0) 1896*071d4279SBram Moolenaar { 1897*071d4279SBram Moolenaar int height; 1898*071d4279SBram Moolenaar win_T *savewin; 1899*071d4279SBram Moolenaar 1900*071d4279SBram Moolenaar if (!PyArg_Parse(val, "i", &height)) 1901*071d4279SBram Moolenaar return -1; 1902*071d4279SBram Moolenaar 1903*071d4279SBram Moolenaar #ifdef FEAT_GUI 1904*071d4279SBram Moolenaar need_mouse_correct = TRUE; 1905*071d4279SBram Moolenaar #endif 1906*071d4279SBram Moolenaar savewin = curwin; 1907*071d4279SBram Moolenaar curwin = this->win; 1908*071d4279SBram Moolenaar win_setheight(height); 1909*071d4279SBram Moolenaar curwin = savewin; 1910*071d4279SBram Moolenaar 1911*071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1912*071d4279SBram Moolenaar if (VimErrorCheck()) 1913*071d4279SBram Moolenaar return -1; 1914*071d4279SBram Moolenaar 1915*071d4279SBram Moolenaar return 0; 1916*071d4279SBram Moolenaar } 1917*071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT 1918*071d4279SBram Moolenaar else if (strcmp(name, "width") == 0) 1919*071d4279SBram Moolenaar { 1920*071d4279SBram Moolenaar int width; 1921*071d4279SBram Moolenaar win_T *savewin; 1922*071d4279SBram Moolenaar 1923*071d4279SBram Moolenaar if (!PyArg_Parse(val, "i", &width)) 1924*071d4279SBram Moolenaar return -1; 1925*071d4279SBram Moolenaar 1926*071d4279SBram Moolenaar #ifdef FEAT_GUI 1927*071d4279SBram Moolenaar need_mouse_correct = TRUE; 1928*071d4279SBram Moolenaar #endif 1929*071d4279SBram Moolenaar savewin = curwin; 1930*071d4279SBram Moolenaar curwin = this->win; 1931*071d4279SBram Moolenaar win_setwidth(width); 1932*071d4279SBram Moolenaar curwin = savewin; 1933*071d4279SBram Moolenaar 1934*071d4279SBram Moolenaar /* Check for keyboard interrupts */ 1935*071d4279SBram Moolenaar if (VimErrorCheck()) 1936*071d4279SBram Moolenaar return -1; 1937*071d4279SBram Moolenaar 1938*071d4279SBram Moolenaar return 0; 1939*071d4279SBram Moolenaar } 1940*071d4279SBram Moolenaar #endif 1941*071d4279SBram Moolenaar else 1942*071d4279SBram Moolenaar { 1943*071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 1944*071d4279SBram Moolenaar return -1; 1945*071d4279SBram Moolenaar } 1946*071d4279SBram Moolenaar } 1947*071d4279SBram Moolenaar 1948*071d4279SBram Moolenaar static PyObject * 1949*071d4279SBram Moolenaar WindowRepr(PyObject *self) 1950*071d4279SBram Moolenaar { 1951*071d4279SBram Moolenaar static char repr[50]; 1952*071d4279SBram Moolenaar WindowObject *this = (WindowObject *)(self); 1953*071d4279SBram Moolenaar 1954*071d4279SBram Moolenaar if (this->win == INVALID_WINDOW_VALUE) 1955*071d4279SBram Moolenaar { 1956*071d4279SBram Moolenaar sprintf(repr, _("<window object (deleted) at %.8lX>"), (long)(self)); 1957*071d4279SBram Moolenaar return PyString_FromString(repr); 1958*071d4279SBram Moolenaar } 1959*071d4279SBram Moolenaar else 1960*071d4279SBram Moolenaar { 1961*071d4279SBram Moolenaar int i = 0; 1962*071d4279SBram Moolenaar win_T *w; 1963*071d4279SBram Moolenaar 1964*071d4279SBram Moolenaar for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w)) 1965*071d4279SBram Moolenaar ++i; 1966*071d4279SBram Moolenaar 1967*071d4279SBram Moolenaar if (w == NULL) 1968*071d4279SBram Moolenaar sprintf(repr, _("<window object (unknown) at %.8lX>"), (long)(self)); 1969*071d4279SBram Moolenaar else 1970*071d4279SBram Moolenaar sprintf(repr, _("<window %d>"), i); 1971*071d4279SBram Moolenaar 1972*071d4279SBram Moolenaar return PyString_FromString(repr); 1973*071d4279SBram Moolenaar } 1974*071d4279SBram Moolenaar } 1975*071d4279SBram Moolenaar 1976*071d4279SBram Moolenaar /* Window list object - Definitions 1977*071d4279SBram Moolenaar */ 1978*071d4279SBram Moolenaar 1979*071d4279SBram Moolenaar typedef struct 1980*071d4279SBram Moolenaar { 1981*071d4279SBram Moolenaar PyObject_HEAD 1982*071d4279SBram Moolenaar } 1983*071d4279SBram Moolenaar WinListObject; 1984*071d4279SBram Moolenaar 1985*071d4279SBram Moolenaar static PySequenceMethods WinListAsSeq = { 1986*071d4279SBram Moolenaar (inquiry) WinListLength, /* sq_length, len(x) */ 1987*071d4279SBram Moolenaar (binaryfunc) 0, /* sq_concat, x+y */ 1988*071d4279SBram Moolenaar (intargfunc) 0, /* sq_repeat, x*n */ 1989*071d4279SBram Moolenaar (intargfunc) WinListItem, /* sq_item, x[i] */ 1990*071d4279SBram Moolenaar (intintargfunc) 0, /* sq_slice, x[i:j] */ 1991*071d4279SBram Moolenaar (intobjargproc) 0, /* sq_ass_item, x[i]=v */ 1992*071d4279SBram Moolenaar (intintobjargproc) 0, /* sq_ass_slice, x[i:j]=v */ 1993*071d4279SBram Moolenaar }; 1994*071d4279SBram Moolenaar 1995*071d4279SBram Moolenaar static PyTypeObject WinListType = { 1996*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 1997*071d4279SBram Moolenaar 0, 1998*071d4279SBram Moolenaar "window list", 1999*071d4279SBram Moolenaar sizeof(WinListObject), 2000*071d4279SBram Moolenaar 0, 2001*071d4279SBram Moolenaar 2002*071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 2003*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 2004*071d4279SBram Moolenaar (getattrfunc) 0, /* tp_getattr, x.attr */ 2005*071d4279SBram Moolenaar (setattrfunc) 0, /* tp_setattr, x.attr=v */ 2006*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 2007*071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 2008*071d4279SBram Moolenaar 2009*071d4279SBram Moolenaar 0, /* as number */ 2010*071d4279SBram Moolenaar &WinListAsSeq, /* as sequence */ 2011*071d4279SBram Moolenaar 0, /* as mapping */ 2012*071d4279SBram Moolenaar 2013*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 2014*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 2015*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 2016*071d4279SBram Moolenaar }; 2017*071d4279SBram Moolenaar 2018*071d4279SBram Moolenaar /* Window list object - Implementation 2019*071d4279SBram Moolenaar */ 2020*071d4279SBram Moolenaar /*ARGSUSED*/ 2021*071d4279SBram Moolenaar static int 2022*071d4279SBram Moolenaar WinListLength(PyObject *self) 2023*071d4279SBram Moolenaar { 2024*071d4279SBram Moolenaar win_T *w = firstwin; 2025*071d4279SBram Moolenaar int n = 0; 2026*071d4279SBram Moolenaar 2027*071d4279SBram Moolenaar while (w) 2028*071d4279SBram Moolenaar { 2029*071d4279SBram Moolenaar ++n; 2030*071d4279SBram Moolenaar w = W_NEXT(w); 2031*071d4279SBram Moolenaar } 2032*071d4279SBram Moolenaar 2033*071d4279SBram Moolenaar return n; 2034*071d4279SBram Moolenaar } 2035*071d4279SBram Moolenaar 2036*071d4279SBram Moolenaar /*ARGSUSED*/ 2037*071d4279SBram Moolenaar static PyObject * 2038*071d4279SBram Moolenaar WinListItem(PyObject *self, int n) 2039*071d4279SBram Moolenaar { 2040*071d4279SBram Moolenaar win_T *w; 2041*071d4279SBram Moolenaar 2042*071d4279SBram Moolenaar for (w = firstwin; w; w = W_NEXT(w), --n) 2043*071d4279SBram Moolenaar if (n == 0) 2044*071d4279SBram Moolenaar return WindowNew(w); 2045*071d4279SBram Moolenaar 2046*071d4279SBram Moolenaar PyErr_SetString(PyExc_IndexError, _("no such window")); 2047*071d4279SBram Moolenaar return NULL; 2048*071d4279SBram Moolenaar } 2049*071d4279SBram Moolenaar 2050*071d4279SBram Moolenaar /* Current items object - Definitions 2051*071d4279SBram Moolenaar */ 2052*071d4279SBram Moolenaar 2053*071d4279SBram Moolenaar typedef struct 2054*071d4279SBram Moolenaar { 2055*071d4279SBram Moolenaar PyObject_HEAD 2056*071d4279SBram Moolenaar } 2057*071d4279SBram Moolenaar CurrentObject; 2058*071d4279SBram Moolenaar 2059*071d4279SBram Moolenaar static PyTypeObject CurrentType = { 2060*071d4279SBram Moolenaar PyObject_HEAD_INIT(0) 2061*071d4279SBram Moolenaar 0, 2062*071d4279SBram Moolenaar "current data", 2063*071d4279SBram Moolenaar sizeof(CurrentObject), 2064*071d4279SBram Moolenaar 0, 2065*071d4279SBram Moolenaar 2066*071d4279SBram Moolenaar (destructor) 0, /* tp_dealloc, refcount==0 */ 2067*071d4279SBram Moolenaar (printfunc) 0, /* tp_print, print x */ 2068*071d4279SBram Moolenaar (getattrfunc) CurrentGetattr, /* tp_getattr, x.attr */ 2069*071d4279SBram Moolenaar (setattrfunc) CurrentSetattr, /* tp_setattr, x.attr=v */ 2070*071d4279SBram Moolenaar (cmpfunc) 0, /* tp_compare, x>y */ 2071*071d4279SBram Moolenaar (reprfunc) 0, /* tp_repr, `x`, print x */ 2072*071d4279SBram Moolenaar 2073*071d4279SBram Moolenaar 0, /* as number */ 2074*071d4279SBram Moolenaar 0, /* as sequence */ 2075*071d4279SBram Moolenaar 0, /* as mapping */ 2076*071d4279SBram Moolenaar 2077*071d4279SBram Moolenaar (hashfunc) 0, /* tp_hash, dict(x) */ 2078*071d4279SBram Moolenaar (ternaryfunc) 0, /* tp_call, x() */ 2079*071d4279SBram Moolenaar (reprfunc) 0, /* tp_str, str(x) */ 2080*071d4279SBram Moolenaar }; 2081*071d4279SBram Moolenaar 2082*071d4279SBram Moolenaar /* Current items object - Implementation 2083*071d4279SBram Moolenaar */ 2084*071d4279SBram Moolenaar /*ARGSUSED*/ 2085*071d4279SBram Moolenaar static PyObject * 2086*071d4279SBram Moolenaar CurrentGetattr(PyObject *self, char *name) 2087*071d4279SBram Moolenaar { 2088*071d4279SBram Moolenaar if (strcmp(name, "buffer") == 0) 2089*071d4279SBram Moolenaar return (PyObject *)BufferNew(curbuf); 2090*071d4279SBram Moolenaar else if (strcmp(name, "window") == 0) 2091*071d4279SBram Moolenaar return (PyObject *)WindowNew(curwin); 2092*071d4279SBram Moolenaar else if (strcmp(name, "line") == 0) 2093*071d4279SBram Moolenaar return GetBufferLine(curbuf, (int)curwin->w_cursor.lnum); 2094*071d4279SBram Moolenaar else if (strcmp(name, "range") == 0) 2095*071d4279SBram Moolenaar return RangeNew(curbuf, RangeStart, RangeEnd); 2096*071d4279SBram Moolenaar else if (strcmp(name,"__members__") == 0) 2097*071d4279SBram Moolenaar return Py_BuildValue("[ssss]", "buffer", "window", "line", "range"); 2098*071d4279SBram Moolenaar else 2099*071d4279SBram Moolenaar { 2100*071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 2101*071d4279SBram Moolenaar return NULL; 2102*071d4279SBram Moolenaar } 2103*071d4279SBram Moolenaar } 2104*071d4279SBram Moolenaar 2105*071d4279SBram Moolenaar /*ARGSUSED*/ 2106*071d4279SBram Moolenaar static int 2107*071d4279SBram Moolenaar CurrentSetattr(PyObject *self, char *name, PyObject *value) 2108*071d4279SBram Moolenaar { 2109*071d4279SBram Moolenaar if (strcmp(name, "line") == 0) 2110*071d4279SBram Moolenaar { 2111*071d4279SBram Moolenaar if (SetBufferLine(curbuf, (int)curwin->w_cursor.lnum, value, NULL) == FAIL) 2112*071d4279SBram Moolenaar return -1; 2113*071d4279SBram Moolenaar 2114*071d4279SBram Moolenaar return 0; 2115*071d4279SBram Moolenaar } 2116*071d4279SBram Moolenaar else 2117*071d4279SBram Moolenaar { 2118*071d4279SBram Moolenaar PyErr_SetString(PyExc_AttributeError, name); 2119*071d4279SBram Moolenaar return -1; 2120*071d4279SBram Moolenaar } 2121*071d4279SBram Moolenaar } 2122*071d4279SBram Moolenaar 2123*071d4279SBram Moolenaar /* External interface 2124*071d4279SBram Moolenaar */ 2125*071d4279SBram Moolenaar 2126*071d4279SBram Moolenaar void 2127*071d4279SBram Moolenaar python_buffer_free(buf_T *buf) 2128*071d4279SBram Moolenaar { 2129*071d4279SBram Moolenaar if (buf->python_ref) 2130*071d4279SBram Moolenaar { 2131*071d4279SBram Moolenaar BufferObject *bp = buf->python_ref; 2132*071d4279SBram Moolenaar bp->buf = INVALID_BUFFER_VALUE; 2133*071d4279SBram Moolenaar buf->python_ref = NULL; 2134*071d4279SBram Moolenaar } 2135*071d4279SBram Moolenaar } 2136*071d4279SBram Moolenaar 2137*071d4279SBram Moolenaar #if defined(FEAT_WINDOWS) || defined(PROTO) 2138*071d4279SBram Moolenaar void 2139*071d4279SBram Moolenaar python_window_free(win_T *win) 2140*071d4279SBram Moolenaar { 2141*071d4279SBram Moolenaar if (win->python_ref) 2142*071d4279SBram Moolenaar { 2143*071d4279SBram Moolenaar WindowObject *wp = win->python_ref; 2144*071d4279SBram Moolenaar wp->win = INVALID_WINDOW_VALUE; 2145*071d4279SBram Moolenaar win->python_ref = NULL; 2146*071d4279SBram Moolenaar } 2147*071d4279SBram Moolenaar } 2148*071d4279SBram Moolenaar #endif 2149*071d4279SBram Moolenaar 2150*071d4279SBram Moolenaar static BufListObject TheBufferList = 2151*071d4279SBram Moolenaar { 2152*071d4279SBram Moolenaar PyObject_HEAD_INIT(&BufListType) 2153*071d4279SBram Moolenaar }; 2154*071d4279SBram Moolenaar 2155*071d4279SBram Moolenaar static WinListObject TheWindowList = 2156*071d4279SBram Moolenaar { 2157*071d4279SBram Moolenaar PyObject_HEAD_INIT(&WinListType) 2158*071d4279SBram Moolenaar }; 2159*071d4279SBram Moolenaar 2160*071d4279SBram Moolenaar static CurrentObject TheCurrent = 2161*071d4279SBram Moolenaar { 2162*071d4279SBram Moolenaar PyObject_HEAD_INIT(&CurrentType) 2163*071d4279SBram Moolenaar }; 2164*071d4279SBram Moolenaar 2165*071d4279SBram Moolenaar static int 2166*071d4279SBram Moolenaar PythonMod_Init(void) 2167*071d4279SBram Moolenaar { 2168*071d4279SBram Moolenaar PyObject *mod; 2169*071d4279SBram Moolenaar PyObject *dict; 2170*071d4279SBram Moolenaar static char *(argv[2]) = {"", NULL}; 2171*071d4279SBram Moolenaar 2172*071d4279SBram Moolenaar /* Fixups... */ 2173*071d4279SBram Moolenaar BufferType.ob_type = &PyType_Type; 2174*071d4279SBram Moolenaar RangeType.ob_type = &PyType_Type; 2175*071d4279SBram Moolenaar WindowType.ob_type = &PyType_Type; 2176*071d4279SBram Moolenaar BufListType.ob_type = &PyType_Type; 2177*071d4279SBram Moolenaar WinListType.ob_type = &PyType_Type; 2178*071d4279SBram Moolenaar CurrentType.ob_type = &PyType_Type; 2179*071d4279SBram Moolenaar 2180*071d4279SBram Moolenaar /* Set sys.argv[] to avoid a crash in warn(). */ 2181*071d4279SBram Moolenaar PySys_SetArgv(1, argv); 2182*071d4279SBram Moolenaar 2183*071d4279SBram Moolenaar mod = Py_InitModule("vim", VimMethods); 2184*071d4279SBram Moolenaar dict = PyModule_GetDict(mod); 2185*071d4279SBram Moolenaar 2186*071d4279SBram Moolenaar VimError = Py_BuildValue("s", "vim.error"); 2187*071d4279SBram Moolenaar 2188*071d4279SBram Moolenaar PyDict_SetItemString(dict, "error", VimError); 2189*071d4279SBram Moolenaar PyDict_SetItemString(dict, "buffers", (PyObject *)(&TheBufferList)); 2190*071d4279SBram Moolenaar PyDict_SetItemString(dict, "current", (PyObject *)(&TheCurrent)); 2191*071d4279SBram Moolenaar PyDict_SetItemString(dict, "windows", (PyObject *)(&TheWindowList)); 2192*071d4279SBram Moolenaar 2193*071d4279SBram Moolenaar if (PyErr_Occurred()) 2194*071d4279SBram Moolenaar return -1; 2195*071d4279SBram Moolenaar 2196*071d4279SBram Moolenaar return 0; 2197*071d4279SBram Moolenaar } 2198*071d4279SBram Moolenaar 2199*071d4279SBram Moolenaar /************************************************************************* 2200*071d4279SBram Moolenaar * 4. Utility functions for handling the interface between Vim and Python. 2201*071d4279SBram Moolenaar */ 2202*071d4279SBram Moolenaar 2203*071d4279SBram Moolenaar /* Get a line from the specified buffer. The line number is 2204*071d4279SBram Moolenaar * in Vim format (1-based). The line is returned as a Python 2205*071d4279SBram Moolenaar * string object. 2206*071d4279SBram Moolenaar */ 2207*071d4279SBram Moolenaar static PyObject * 2208*071d4279SBram Moolenaar GetBufferLine(buf_T *buf, int n) 2209*071d4279SBram Moolenaar { 2210*071d4279SBram Moolenaar return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE)); 2211*071d4279SBram Moolenaar } 2212*071d4279SBram Moolenaar 2213*071d4279SBram Moolenaar /* Get a list of lines from the specified buffer. The line numbers 2214*071d4279SBram Moolenaar * are in Vim format (1-based). The range is from lo up to, but not 2215*071d4279SBram Moolenaar * including, hi. The list is returned as a Python list of string objects. 2216*071d4279SBram Moolenaar */ 2217*071d4279SBram Moolenaar static PyObject * 2218*071d4279SBram Moolenaar GetBufferLineList(buf_T *buf, int lo, int hi) 2219*071d4279SBram Moolenaar { 2220*071d4279SBram Moolenaar int i; 2221*071d4279SBram Moolenaar int n = hi - lo; 2222*071d4279SBram Moolenaar PyObject *list = PyList_New(n); 2223*071d4279SBram Moolenaar 2224*071d4279SBram Moolenaar if (list == NULL) 2225*071d4279SBram Moolenaar return NULL; 2226*071d4279SBram Moolenaar 2227*071d4279SBram Moolenaar for (i = 0; i < n; ++i) 2228*071d4279SBram Moolenaar { 2229*071d4279SBram Moolenaar PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE)); 2230*071d4279SBram Moolenaar 2231*071d4279SBram Moolenaar /* Error check - was the Python string creation OK? */ 2232*071d4279SBram Moolenaar if (str == NULL) 2233*071d4279SBram Moolenaar { 2234*071d4279SBram Moolenaar Py_DECREF(list); 2235*071d4279SBram Moolenaar return NULL; 2236*071d4279SBram Moolenaar } 2237*071d4279SBram Moolenaar 2238*071d4279SBram Moolenaar /* Set the list item */ 2239*071d4279SBram Moolenaar if (PyList_SetItem(list, i, str)) 2240*071d4279SBram Moolenaar { 2241*071d4279SBram Moolenaar Py_DECREF(str); 2242*071d4279SBram Moolenaar Py_DECREF(list); 2243*071d4279SBram Moolenaar return NULL; 2244*071d4279SBram Moolenaar } 2245*071d4279SBram Moolenaar } 2246*071d4279SBram Moolenaar 2247*071d4279SBram Moolenaar /* The ownership of the Python list is passed to the caller (ie, 2248*071d4279SBram Moolenaar * the caller should Py_DECREF() the object when it is finished 2249*071d4279SBram Moolenaar * with it). 2250*071d4279SBram Moolenaar */ 2251*071d4279SBram Moolenaar 2252*071d4279SBram Moolenaar return list; 2253*071d4279SBram Moolenaar } 2254*071d4279SBram Moolenaar 2255*071d4279SBram Moolenaar /* 2256*071d4279SBram Moolenaar * Check if deleting lines made the cursor position invalid. 2257*071d4279SBram Moolenaar * Changed the lines from "lo" to "hi" and added "extra" lines (negative if 2258*071d4279SBram Moolenaar * deleted). 2259*071d4279SBram Moolenaar */ 2260*071d4279SBram Moolenaar static void 2261*071d4279SBram Moolenaar py_fix_cursor(int lo, int hi, int extra) 2262*071d4279SBram Moolenaar { 2263*071d4279SBram Moolenaar if (curwin->w_cursor.lnum >= lo) 2264*071d4279SBram Moolenaar { 2265*071d4279SBram Moolenaar /* Adjust the cursor position if it's in/after the changed 2266*071d4279SBram Moolenaar * lines. */ 2267*071d4279SBram Moolenaar if (curwin->w_cursor.lnum >= hi) 2268*071d4279SBram Moolenaar { 2269*071d4279SBram Moolenaar curwin->w_cursor.lnum += extra; 2270*071d4279SBram Moolenaar check_cursor_col(); 2271*071d4279SBram Moolenaar } 2272*071d4279SBram Moolenaar else if (extra < 0) 2273*071d4279SBram Moolenaar { 2274*071d4279SBram Moolenaar curwin->w_cursor.lnum = lo; 2275*071d4279SBram Moolenaar check_cursor(); 2276*071d4279SBram Moolenaar } 2277*071d4279SBram Moolenaar changed_cline_bef_curs(); 2278*071d4279SBram Moolenaar } 2279*071d4279SBram Moolenaar invalidate_botline(); 2280*071d4279SBram Moolenaar } 2281*071d4279SBram Moolenaar 2282*071d4279SBram Moolenaar /* Replace a line in the specified buffer. The line number is 2283*071d4279SBram Moolenaar * in Vim format (1-based). The replacement line is given as 2284*071d4279SBram Moolenaar * a Python string object. The object is checked for validity 2285*071d4279SBram Moolenaar * and correct format. Errors are returned as a value of FAIL. 2286*071d4279SBram Moolenaar * The return value is OK on success. 2287*071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2288*071d4279SBram Moolenaar * is set to the change in the buffer length. 2289*071d4279SBram Moolenaar */ 2290*071d4279SBram Moolenaar static int 2291*071d4279SBram Moolenaar SetBufferLine(buf_T *buf, int n, PyObject *line, int *len_change) 2292*071d4279SBram Moolenaar { 2293*071d4279SBram Moolenaar /* First of all, we check the thpe of the supplied Python object. 2294*071d4279SBram Moolenaar * There are three cases: 2295*071d4279SBram Moolenaar * 1. NULL, or None - this is a deletion. 2296*071d4279SBram Moolenaar * 2. A string - this is a replacement. 2297*071d4279SBram Moolenaar * 3. Anything else - this is an error. 2298*071d4279SBram Moolenaar */ 2299*071d4279SBram Moolenaar if (line == Py_None || line == NULL) 2300*071d4279SBram Moolenaar { 2301*071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2302*071d4279SBram Moolenaar 2303*071d4279SBram Moolenaar PyErr_Clear(); 2304*071d4279SBram Moolenaar curbuf = buf; 2305*071d4279SBram Moolenaar 2306*071d4279SBram Moolenaar if (u_savedel((linenr_T)n, 1L) == FAIL) 2307*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2308*071d4279SBram Moolenaar else if (ml_delete((linenr_T)n, FALSE) == FAIL) 2309*071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2310*071d4279SBram Moolenaar else 2311*071d4279SBram Moolenaar { 2312*071d4279SBram Moolenaar deleted_lines_mark((linenr_T)n, 1L); 2313*071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2314*071d4279SBram Moolenaar py_fix_cursor(n, n + 1, -1); 2315*071d4279SBram Moolenaar } 2316*071d4279SBram Moolenaar 2317*071d4279SBram Moolenaar curbuf = savebuf; 2318*071d4279SBram Moolenaar 2319*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2320*071d4279SBram Moolenaar return FAIL; 2321*071d4279SBram Moolenaar 2322*071d4279SBram Moolenaar if (len_change) 2323*071d4279SBram Moolenaar *len_change = -1; 2324*071d4279SBram Moolenaar 2325*071d4279SBram Moolenaar return OK; 2326*071d4279SBram Moolenaar } 2327*071d4279SBram Moolenaar else if (PyString_Check(line)) 2328*071d4279SBram Moolenaar { 2329*071d4279SBram Moolenaar char *save = StringToLine(line); 2330*071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2331*071d4279SBram Moolenaar 2332*071d4279SBram Moolenaar if (save == NULL) 2333*071d4279SBram Moolenaar return FAIL; 2334*071d4279SBram Moolenaar 2335*071d4279SBram Moolenaar /* We do not need to free "save" if ml_replace() consumes it. */ 2336*071d4279SBram Moolenaar PyErr_Clear(); 2337*071d4279SBram Moolenaar curbuf = buf; 2338*071d4279SBram Moolenaar 2339*071d4279SBram Moolenaar if (u_savesub((linenr_T)n) == FAIL) 2340*071d4279SBram Moolenaar { 2341*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2342*071d4279SBram Moolenaar vim_free(save); 2343*071d4279SBram Moolenaar } 2344*071d4279SBram Moolenaar else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL) 2345*071d4279SBram Moolenaar { 2346*071d4279SBram Moolenaar PyErr_SetVim(_("cannot replace line")); 2347*071d4279SBram Moolenaar vim_free(save); 2348*071d4279SBram Moolenaar } 2349*071d4279SBram Moolenaar else 2350*071d4279SBram Moolenaar changed_bytes((linenr_T)n, 0); 2351*071d4279SBram Moolenaar 2352*071d4279SBram Moolenaar curbuf = savebuf; 2353*071d4279SBram Moolenaar 2354*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2355*071d4279SBram Moolenaar return FAIL; 2356*071d4279SBram Moolenaar 2357*071d4279SBram Moolenaar if (len_change) 2358*071d4279SBram Moolenaar *len_change = 0; 2359*071d4279SBram Moolenaar 2360*071d4279SBram Moolenaar return OK; 2361*071d4279SBram Moolenaar } 2362*071d4279SBram Moolenaar else 2363*071d4279SBram Moolenaar { 2364*071d4279SBram Moolenaar PyErr_BadArgument(); 2365*071d4279SBram Moolenaar return FAIL; 2366*071d4279SBram Moolenaar } 2367*071d4279SBram Moolenaar } 2368*071d4279SBram Moolenaar 2369*071d4279SBram Moolenaar /* Replace a range of lines in the specified buffer. The line numbers are in 2370*071d4279SBram Moolenaar * Vim format (1-based). The range is from lo up to, but not including, hi. 2371*071d4279SBram Moolenaar * The replacement lines are given as a Python list of string objects. The 2372*071d4279SBram Moolenaar * list is checked for validity and correct format. Errors are returned as a 2373*071d4279SBram Moolenaar * value of FAIL. The return value is OK on success. 2374*071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2375*071d4279SBram Moolenaar * is set to the change in the buffer length. 2376*071d4279SBram Moolenaar */ 2377*071d4279SBram Moolenaar static int 2378*071d4279SBram Moolenaar SetBufferLineList(buf_T *buf, int lo, int hi, PyObject *list, int *len_change) 2379*071d4279SBram Moolenaar { 2380*071d4279SBram Moolenaar /* First of all, we check the thpe of the supplied Python object. 2381*071d4279SBram Moolenaar * There are three cases: 2382*071d4279SBram Moolenaar * 1. NULL, or None - this is a deletion. 2383*071d4279SBram Moolenaar * 2. A list - this is a replacement. 2384*071d4279SBram Moolenaar * 3. Anything else - this is an error. 2385*071d4279SBram Moolenaar */ 2386*071d4279SBram Moolenaar if (list == Py_None || list == NULL) 2387*071d4279SBram Moolenaar { 2388*071d4279SBram Moolenaar int i; 2389*071d4279SBram Moolenaar int n = hi - lo; 2390*071d4279SBram Moolenaar buf_T *savebuf = curbuf; 2391*071d4279SBram Moolenaar 2392*071d4279SBram Moolenaar PyErr_Clear(); 2393*071d4279SBram Moolenaar curbuf = buf; 2394*071d4279SBram Moolenaar 2395*071d4279SBram Moolenaar if (u_savedel((linenr_T)lo, (long)n) == FAIL) 2396*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2397*071d4279SBram Moolenaar else 2398*071d4279SBram Moolenaar { 2399*071d4279SBram Moolenaar for (i = 0; i < n; ++i) 2400*071d4279SBram Moolenaar { 2401*071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2402*071d4279SBram Moolenaar { 2403*071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2404*071d4279SBram Moolenaar break; 2405*071d4279SBram Moolenaar } 2406*071d4279SBram Moolenaar } 2407*071d4279SBram Moolenaar deleted_lines_mark((linenr_T)lo, (long)i); 2408*071d4279SBram Moolenaar 2409*071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2410*071d4279SBram Moolenaar py_fix_cursor(lo, hi, -n); 2411*071d4279SBram Moolenaar } 2412*071d4279SBram Moolenaar 2413*071d4279SBram Moolenaar curbuf = savebuf; 2414*071d4279SBram Moolenaar 2415*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2416*071d4279SBram Moolenaar return FAIL; 2417*071d4279SBram Moolenaar 2418*071d4279SBram Moolenaar if (len_change) 2419*071d4279SBram Moolenaar *len_change = -n; 2420*071d4279SBram Moolenaar 2421*071d4279SBram Moolenaar return OK; 2422*071d4279SBram Moolenaar } 2423*071d4279SBram Moolenaar else if (PyList_Check(list)) 2424*071d4279SBram Moolenaar { 2425*071d4279SBram Moolenaar int i; 2426*071d4279SBram Moolenaar int new_len = PyList_Size(list); 2427*071d4279SBram Moolenaar int old_len = hi - lo; 2428*071d4279SBram Moolenaar int extra = 0; /* lines added to text, can be negative */ 2429*071d4279SBram Moolenaar char **array; 2430*071d4279SBram Moolenaar buf_T *savebuf; 2431*071d4279SBram Moolenaar 2432*071d4279SBram Moolenaar if (new_len == 0) /* avoid allocating zero bytes */ 2433*071d4279SBram Moolenaar array = NULL; 2434*071d4279SBram Moolenaar else 2435*071d4279SBram Moolenaar { 2436*071d4279SBram Moolenaar array = (char **)alloc((unsigned)(new_len * sizeof(char *))); 2437*071d4279SBram Moolenaar if (array == NULL) 2438*071d4279SBram Moolenaar { 2439*071d4279SBram Moolenaar PyErr_NoMemory(); 2440*071d4279SBram Moolenaar return FAIL; 2441*071d4279SBram Moolenaar } 2442*071d4279SBram Moolenaar } 2443*071d4279SBram Moolenaar 2444*071d4279SBram Moolenaar for (i = 0; i < new_len; ++i) 2445*071d4279SBram Moolenaar { 2446*071d4279SBram Moolenaar PyObject *line = PyList_GetItem(list, i); 2447*071d4279SBram Moolenaar 2448*071d4279SBram Moolenaar array[i] = StringToLine(line); 2449*071d4279SBram Moolenaar if (array[i] == NULL) 2450*071d4279SBram Moolenaar { 2451*071d4279SBram Moolenaar while (i) 2452*071d4279SBram Moolenaar vim_free(array[--i]); 2453*071d4279SBram Moolenaar vim_free(array); 2454*071d4279SBram Moolenaar return FAIL; 2455*071d4279SBram Moolenaar } 2456*071d4279SBram Moolenaar } 2457*071d4279SBram Moolenaar 2458*071d4279SBram Moolenaar savebuf = curbuf; 2459*071d4279SBram Moolenaar 2460*071d4279SBram Moolenaar PyErr_Clear(); 2461*071d4279SBram Moolenaar curbuf = buf; 2462*071d4279SBram Moolenaar 2463*071d4279SBram Moolenaar if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL) 2464*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2465*071d4279SBram Moolenaar 2466*071d4279SBram Moolenaar /* If the size of the range is reducing (ie, new_len < old_len) we 2467*071d4279SBram Moolenaar * need to delete some old_len. We do this at the start, by 2468*071d4279SBram Moolenaar * repeatedly deleting line "lo". 2469*071d4279SBram Moolenaar */ 2470*071d4279SBram Moolenaar if (!PyErr_Occurred()) 2471*071d4279SBram Moolenaar { 2472*071d4279SBram Moolenaar for (i = 0; i < old_len - new_len; ++i) 2473*071d4279SBram Moolenaar if (ml_delete((linenr_T)lo, FALSE) == FAIL) 2474*071d4279SBram Moolenaar { 2475*071d4279SBram Moolenaar PyErr_SetVim(_("cannot delete line")); 2476*071d4279SBram Moolenaar break; 2477*071d4279SBram Moolenaar } 2478*071d4279SBram Moolenaar extra -= i; 2479*071d4279SBram Moolenaar } 2480*071d4279SBram Moolenaar 2481*071d4279SBram Moolenaar /* For as long as possible, replace the existing old_len with the 2482*071d4279SBram Moolenaar * new old_len. This is a more efficient operation, as it requires 2483*071d4279SBram Moolenaar * less memory allocation and freeing. 2484*071d4279SBram Moolenaar */ 2485*071d4279SBram Moolenaar if (!PyErr_Occurred()) 2486*071d4279SBram Moolenaar { 2487*071d4279SBram Moolenaar for (i = 0; i < old_len && i < new_len; ++i) 2488*071d4279SBram Moolenaar if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE) 2489*071d4279SBram Moolenaar == FAIL) 2490*071d4279SBram Moolenaar { 2491*071d4279SBram Moolenaar PyErr_SetVim(_("cannot replace line")); 2492*071d4279SBram Moolenaar break; 2493*071d4279SBram Moolenaar } 2494*071d4279SBram Moolenaar } 2495*071d4279SBram Moolenaar else 2496*071d4279SBram Moolenaar i = 0; 2497*071d4279SBram Moolenaar 2498*071d4279SBram Moolenaar /* Now we may need to insert the remaining new old_len. If we do, we 2499*071d4279SBram Moolenaar * must free the strings as we finish with them (we can't pass the 2500*071d4279SBram Moolenaar * responsibility to vim in this case). 2501*071d4279SBram Moolenaar */ 2502*071d4279SBram Moolenaar if (!PyErr_Occurred()) 2503*071d4279SBram Moolenaar { 2504*071d4279SBram Moolenaar while (i < new_len) 2505*071d4279SBram Moolenaar { 2506*071d4279SBram Moolenaar if (ml_append((linenr_T)(lo + i - 1), 2507*071d4279SBram Moolenaar (char_u *)array[i], 0, FALSE) == FAIL) 2508*071d4279SBram Moolenaar { 2509*071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2510*071d4279SBram Moolenaar break; 2511*071d4279SBram Moolenaar } 2512*071d4279SBram Moolenaar vim_free(array[i]); 2513*071d4279SBram Moolenaar ++i; 2514*071d4279SBram Moolenaar ++extra; 2515*071d4279SBram Moolenaar } 2516*071d4279SBram Moolenaar } 2517*071d4279SBram Moolenaar 2518*071d4279SBram Moolenaar /* Free any left-over old_len, as a result of an error */ 2519*071d4279SBram Moolenaar while (i < new_len) 2520*071d4279SBram Moolenaar { 2521*071d4279SBram Moolenaar vim_free(array[i]); 2522*071d4279SBram Moolenaar ++i; 2523*071d4279SBram Moolenaar } 2524*071d4279SBram Moolenaar 2525*071d4279SBram Moolenaar /* Free the array of old_len. All of its contents have now 2526*071d4279SBram Moolenaar * been dealt with (either freed, or the responsibility passed 2527*071d4279SBram Moolenaar * to vim. 2528*071d4279SBram Moolenaar */ 2529*071d4279SBram Moolenaar vim_free(array); 2530*071d4279SBram Moolenaar 2531*071d4279SBram Moolenaar /* Adjust marks. Invalidate any which lie in the 2532*071d4279SBram Moolenaar * changed range, and move any in the remainder of the buffer. 2533*071d4279SBram Moolenaar */ 2534*071d4279SBram Moolenaar mark_adjust((linenr_T)lo, (linenr_T)(hi - 1), 2535*071d4279SBram Moolenaar (long)MAXLNUM, (long)extra); 2536*071d4279SBram Moolenaar changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra); 2537*071d4279SBram Moolenaar 2538*071d4279SBram Moolenaar if (buf == curwin->w_buffer) 2539*071d4279SBram Moolenaar py_fix_cursor(lo, hi, extra); 2540*071d4279SBram Moolenaar 2541*071d4279SBram Moolenaar curbuf = savebuf; 2542*071d4279SBram Moolenaar 2543*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2544*071d4279SBram Moolenaar return FAIL; 2545*071d4279SBram Moolenaar 2546*071d4279SBram Moolenaar if (len_change) 2547*071d4279SBram Moolenaar *len_change = new_len - old_len; 2548*071d4279SBram Moolenaar 2549*071d4279SBram Moolenaar return OK; 2550*071d4279SBram Moolenaar } 2551*071d4279SBram Moolenaar else 2552*071d4279SBram Moolenaar { 2553*071d4279SBram Moolenaar PyErr_BadArgument(); 2554*071d4279SBram Moolenaar return FAIL; 2555*071d4279SBram Moolenaar } 2556*071d4279SBram Moolenaar } 2557*071d4279SBram Moolenaar 2558*071d4279SBram Moolenaar /* Insert a number of lines into the specified buffer after the specifed line. 2559*071d4279SBram Moolenaar * The line number is in Vim format (1-based). The lines to be inserted are 2560*071d4279SBram Moolenaar * given as a Python list of string objects or as a single string. The lines 2561*071d4279SBram Moolenaar * to be added are checked for validity and correct format. Errors are 2562*071d4279SBram Moolenaar * returned as a value of FAIL. The return value is OK on success. 2563*071d4279SBram Moolenaar * If OK is returned and len_change is not NULL, *len_change 2564*071d4279SBram Moolenaar * is set to the change in the buffer length. 2565*071d4279SBram Moolenaar */ 2566*071d4279SBram Moolenaar static int 2567*071d4279SBram Moolenaar InsertBufferLines(buf_T *buf, int n, PyObject *lines, int *len_change) 2568*071d4279SBram Moolenaar { 2569*071d4279SBram Moolenaar /* First of all, we check the type of the supplied Python object. 2570*071d4279SBram Moolenaar * It must be a string or a list, or the call is in error. 2571*071d4279SBram Moolenaar */ 2572*071d4279SBram Moolenaar if (PyString_Check(lines)) 2573*071d4279SBram Moolenaar { 2574*071d4279SBram Moolenaar char *str = StringToLine(lines); 2575*071d4279SBram Moolenaar buf_T *savebuf; 2576*071d4279SBram Moolenaar 2577*071d4279SBram Moolenaar if (str == NULL) 2578*071d4279SBram Moolenaar return FAIL; 2579*071d4279SBram Moolenaar 2580*071d4279SBram Moolenaar savebuf = curbuf; 2581*071d4279SBram Moolenaar 2582*071d4279SBram Moolenaar PyErr_Clear(); 2583*071d4279SBram Moolenaar curbuf = buf; 2584*071d4279SBram Moolenaar 2585*071d4279SBram Moolenaar if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL) 2586*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2587*071d4279SBram Moolenaar else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL) 2588*071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2589*071d4279SBram Moolenaar else 2590*071d4279SBram Moolenaar appended_lines_mark((linenr_T)n, 1L); 2591*071d4279SBram Moolenaar 2592*071d4279SBram Moolenaar vim_free(str); 2593*071d4279SBram Moolenaar curbuf = savebuf; 2594*071d4279SBram Moolenaar update_screen(VALID); 2595*071d4279SBram Moolenaar 2596*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2597*071d4279SBram Moolenaar return FAIL; 2598*071d4279SBram Moolenaar 2599*071d4279SBram Moolenaar if (len_change) 2600*071d4279SBram Moolenaar *len_change = 1; 2601*071d4279SBram Moolenaar 2602*071d4279SBram Moolenaar return OK; 2603*071d4279SBram Moolenaar } 2604*071d4279SBram Moolenaar else if (PyList_Check(lines)) 2605*071d4279SBram Moolenaar { 2606*071d4279SBram Moolenaar int i; 2607*071d4279SBram Moolenaar int size = PyList_Size(lines); 2608*071d4279SBram Moolenaar char **array; 2609*071d4279SBram Moolenaar buf_T *savebuf; 2610*071d4279SBram Moolenaar 2611*071d4279SBram Moolenaar array = (char **)alloc((unsigned)(size * sizeof(char *))); 2612*071d4279SBram Moolenaar if (array == NULL) 2613*071d4279SBram Moolenaar { 2614*071d4279SBram Moolenaar PyErr_NoMemory(); 2615*071d4279SBram Moolenaar return FAIL; 2616*071d4279SBram Moolenaar } 2617*071d4279SBram Moolenaar 2618*071d4279SBram Moolenaar for (i = 0; i < size; ++i) 2619*071d4279SBram Moolenaar { 2620*071d4279SBram Moolenaar PyObject *line = PyList_GetItem(lines, i); 2621*071d4279SBram Moolenaar array[i] = StringToLine(line); 2622*071d4279SBram Moolenaar 2623*071d4279SBram Moolenaar if (array[i] == NULL) 2624*071d4279SBram Moolenaar { 2625*071d4279SBram Moolenaar while (i) 2626*071d4279SBram Moolenaar vim_free(array[--i]); 2627*071d4279SBram Moolenaar vim_free(array); 2628*071d4279SBram Moolenaar return FAIL; 2629*071d4279SBram Moolenaar } 2630*071d4279SBram Moolenaar } 2631*071d4279SBram Moolenaar 2632*071d4279SBram Moolenaar savebuf = curbuf; 2633*071d4279SBram Moolenaar 2634*071d4279SBram Moolenaar PyErr_Clear(); 2635*071d4279SBram Moolenaar curbuf = buf; 2636*071d4279SBram Moolenaar 2637*071d4279SBram Moolenaar if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL) 2638*071d4279SBram Moolenaar PyErr_SetVim(_("cannot save undo information")); 2639*071d4279SBram Moolenaar else 2640*071d4279SBram Moolenaar { 2641*071d4279SBram Moolenaar for (i = 0; i < size; ++i) 2642*071d4279SBram Moolenaar { 2643*071d4279SBram Moolenaar if (ml_append((linenr_T)(n + i), 2644*071d4279SBram Moolenaar (char_u *)array[i], 0, FALSE) == FAIL) 2645*071d4279SBram Moolenaar { 2646*071d4279SBram Moolenaar PyErr_SetVim(_("cannot insert line")); 2647*071d4279SBram Moolenaar 2648*071d4279SBram Moolenaar /* Free the rest of the lines */ 2649*071d4279SBram Moolenaar while (i < size) 2650*071d4279SBram Moolenaar vim_free(array[i++]); 2651*071d4279SBram Moolenaar 2652*071d4279SBram Moolenaar break; 2653*071d4279SBram Moolenaar } 2654*071d4279SBram Moolenaar vim_free(array[i]); 2655*071d4279SBram Moolenaar } 2656*071d4279SBram Moolenaar if (i > 0) 2657*071d4279SBram Moolenaar appended_lines_mark((linenr_T)n, (long)i); 2658*071d4279SBram Moolenaar } 2659*071d4279SBram Moolenaar 2660*071d4279SBram Moolenaar /* Free the array of lines. All of its contents have now 2661*071d4279SBram Moolenaar * been freed. 2662*071d4279SBram Moolenaar */ 2663*071d4279SBram Moolenaar vim_free(array); 2664*071d4279SBram Moolenaar 2665*071d4279SBram Moolenaar curbuf = savebuf; 2666*071d4279SBram Moolenaar update_screen(VALID); 2667*071d4279SBram Moolenaar 2668*071d4279SBram Moolenaar if (PyErr_Occurred() || VimErrorCheck()) 2669*071d4279SBram Moolenaar return FAIL; 2670*071d4279SBram Moolenaar 2671*071d4279SBram Moolenaar if (len_change) 2672*071d4279SBram Moolenaar *len_change = size; 2673*071d4279SBram Moolenaar 2674*071d4279SBram Moolenaar return OK; 2675*071d4279SBram Moolenaar } 2676*071d4279SBram Moolenaar else 2677*071d4279SBram Moolenaar { 2678*071d4279SBram Moolenaar PyErr_BadArgument(); 2679*071d4279SBram Moolenaar return FAIL; 2680*071d4279SBram Moolenaar } 2681*071d4279SBram Moolenaar } 2682*071d4279SBram Moolenaar 2683*071d4279SBram Moolenaar /* Convert a Vim line into a Python string. 2684*071d4279SBram Moolenaar * All internal newlines are replaced by null characters. 2685*071d4279SBram Moolenaar * 2686*071d4279SBram Moolenaar * On errors, the Python exception data is set, and NULL is returned. 2687*071d4279SBram Moolenaar */ 2688*071d4279SBram Moolenaar static PyObject * 2689*071d4279SBram Moolenaar LineToString(const char *str) 2690*071d4279SBram Moolenaar { 2691*071d4279SBram Moolenaar PyObject *result; 2692*071d4279SBram Moolenaar int len = strlen(str); 2693*071d4279SBram Moolenaar char *p; 2694*071d4279SBram Moolenaar 2695*071d4279SBram Moolenaar /* Allocate an Python string object, with uninitialised contents. We 2696*071d4279SBram Moolenaar * must do it this way, so that we can modify the string in place 2697*071d4279SBram Moolenaar * later. See the Python source, Objects/stringobject.c for details. 2698*071d4279SBram Moolenaar */ 2699*071d4279SBram Moolenaar result = PyString_FromStringAndSize(NULL, len); 2700*071d4279SBram Moolenaar if (result == NULL) 2701*071d4279SBram Moolenaar return NULL; 2702*071d4279SBram Moolenaar 2703*071d4279SBram Moolenaar p = PyString_AsString(result); 2704*071d4279SBram Moolenaar 2705*071d4279SBram Moolenaar while (*str) 2706*071d4279SBram Moolenaar { 2707*071d4279SBram Moolenaar if (*str == '\n') 2708*071d4279SBram Moolenaar *p = '\0'; 2709*071d4279SBram Moolenaar else 2710*071d4279SBram Moolenaar *p = *str; 2711*071d4279SBram Moolenaar 2712*071d4279SBram Moolenaar ++p; 2713*071d4279SBram Moolenaar ++str; 2714*071d4279SBram Moolenaar } 2715*071d4279SBram Moolenaar 2716*071d4279SBram Moolenaar return result; 2717*071d4279SBram Moolenaar } 2718*071d4279SBram Moolenaar 2719*071d4279SBram Moolenaar /* Convert a Python string into a Vim line. 2720*071d4279SBram Moolenaar * 2721*071d4279SBram Moolenaar * The result is in allocated memory. All internal nulls are replaced by 2722*071d4279SBram Moolenaar * newline characters. It is an error for the string to contain newline 2723*071d4279SBram Moolenaar * characters. 2724*071d4279SBram Moolenaar * 2725*071d4279SBram Moolenaar * On errors, the Python exception data is set, and NULL is returned. 2726*071d4279SBram Moolenaar */ 2727*071d4279SBram Moolenaar static char * 2728*071d4279SBram Moolenaar StringToLine(PyObject *obj) 2729*071d4279SBram Moolenaar { 2730*071d4279SBram Moolenaar const char *str; 2731*071d4279SBram Moolenaar char *save; 2732*071d4279SBram Moolenaar int len; 2733*071d4279SBram Moolenaar int i; 2734*071d4279SBram Moolenaar 2735*071d4279SBram Moolenaar if (obj == NULL || !PyString_Check(obj)) 2736*071d4279SBram Moolenaar { 2737*071d4279SBram Moolenaar PyErr_BadArgument(); 2738*071d4279SBram Moolenaar return NULL; 2739*071d4279SBram Moolenaar } 2740*071d4279SBram Moolenaar 2741*071d4279SBram Moolenaar str = PyString_AsString(obj); 2742*071d4279SBram Moolenaar len = PyString_Size(obj); 2743*071d4279SBram Moolenaar 2744*071d4279SBram Moolenaar /* Error checking: String must not contain newlines, as we 2745*071d4279SBram Moolenaar * are replacing a single line, and we must replace it with 2746*071d4279SBram Moolenaar * a single line. 2747*071d4279SBram Moolenaar */ 2748*071d4279SBram Moolenaar if (memchr(str, '\n', len)) 2749*071d4279SBram Moolenaar { 2750*071d4279SBram Moolenaar PyErr_SetVim(_("string cannot contain newlines")); 2751*071d4279SBram Moolenaar return NULL; 2752*071d4279SBram Moolenaar } 2753*071d4279SBram Moolenaar 2754*071d4279SBram Moolenaar /* Create a copy of the string, with internal nulls replaced by 2755*071d4279SBram Moolenaar * newline characters, as is the vim convention. 2756*071d4279SBram Moolenaar */ 2757*071d4279SBram Moolenaar save = (char *)alloc((unsigned)(len+1)); 2758*071d4279SBram Moolenaar if (save == NULL) 2759*071d4279SBram Moolenaar { 2760*071d4279SBram Moolenaar PyErr_NoMemory(); 2761*071d4279SBram Moolenaar return NULL; 2762*071d4279SBram Moolenaar } 2763*071d4279SBram Moolenaar 2764*071d4279SBram Moolenaar for (i = 0; i < len; ++i) 2765*071d4279SBram Moolenaar { 2766*071d4279SBram Moolenaar if (str[i] == '\0') 2767*071d4279SBram Moolenaar save[i] = '\n'; 2768*071d4279SBram Moolenaar else 2769*071d4279SBram Moolenaar save[i] = str[i]; 2770*071d4279SBram Moolenaar } 2771*071d4279SBram Moolenaar 2772*071d4279SBram Moolenaar save[i] = '\0'; 2773*071d4279SBram Moolenaar 2774*071d4279SBram Moolenaar return save; 2775*071d4279SBram Moolenaar } 2776*071d4279SBram Moolenaar 2777*071d4279SBram Moolenaar /* Check to see whether a Vim error has been reported, or a keyboard 2778*071d4279SBram Moolenaar * interrupt has been detected. 2779*071d4279SBram Moolenaar */ 2780*071d4279SBram Moolenaar static int 2781*071d4279SBram Moolenaar VimErrorCheck(void) 2782*071d4279SBram Moolenaar { 2783*071d4279SBram Moolenaar if (got_int) 2784*071d4279SBram Moolenaar { 2785*071d4279SBram Moolenaar PyErr_SetNone(PyExc_KeyboardInterrupt); 2786*071d4279SBram Moolenaar return 1; 2787*071d4279SBram Moolenaar } 2788*071d4279SBram Moolenaar else if (did_emsg && !PyErr_Occurred()) 2789*071d4279SBram Moolenaar { 2790*071d4279SBram Moolenaar PyErr_SetNone(VimError); 2791*071d4279SBram Moolenaar return 1; 2792*071d4279SBram Moolenaar } 2793*071d4279SBram Moolenaar 2794*071d4279SBram Moolenaar return 0; 2795*071d4279SBram Moolenaar } 2796*071d4279SBram Moolenaar 2797*071d4279SBram Moolenaar 2798*071d4279SBram Moolenaar /* Don't generate a prototype for the next function, it generates an error on 2799*071d4279SBram Moolenaar * newer Python versions. */ 2800*071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ && !defined(PROTO) 2801*071d4279SBram Moolenaar 2802*071d4279SBram Moolenaar char * 2803*071d4279SBram Moolenaar Py_GetProgramName(void) 2804*071d4279SBram Moolenaar { 2805*071d4279SBram Moolenaar return "vim"; 2806*071d4279SBram Moolenaar } 2807*071d4279SBram Moolenaar #endif /* Python 1.4 */ 2808