xref: /vim-8.2.3635/src/if_python.c (revision 30fec7bc)
1071d4279SBram Moolenaar /* vi:set ts=8 sts=4 sw=4:
2071d4279SBram Moolenaar  *
3071d4279SBram Moolenaar  * VIM - Vi IMproved	by Bram Moolenaar
4071d4279SBram Moolenaar  *
5071d4279SBram Moolenaar  * Do ":help uganda"  in Vim to read copying and usage conditions.
6071d4279SBram Moolenaar  * Do ":help credits" in Vim to see a list of people who contributed.
7071d4279SBram Moolenaar  * See README.txt for an overview of the Vim source code.
8071d4279SBram Moolenaar  */
9071d4279SBram Moolenaar /*
10071d4279SBram Moolenaar  * Python extensions by Paul Moore.
11071d4279SBram Moolenaar  * Changes for Unix by David Leonard.
12071d4279SBram Moolenaar  *
13071d4279SBram Moolenaar  * This consists of four parts:
14071d4279SBram Moolenaar  * 1. Python interpreter main program
15071d4279SBram Moolenaar  * 2. Python output stream: writes output via [e]msg().
16071d4279SBram Moolenaar  * 3. Implementation of the Vim module for Python
17071d4279SBram Moolenaar  * 4. Utility functions for handling the interface between Vim and Python.
18071d4279SBram Moolenaar  */
19071d4279SBram Moolenaar 
20071d4279SBram Moolenaar #include "vim.h"
21071d4279SBram Moolenaar 
22071d4279SBram Moolenaar #include <limits.h>
23071d4279SBram Moolenaar 
24071d4279SBram Moolenaar /* Python.h defines _POSIX_THREADS itself (if needed) */
25071d4279SBram Moolenaar #ifdef _POSIX_THREADS
26071d4279SBram Moolenaar # undef _POSIX_THREADS
27071d4279SBram Moolenaar #endif
28071d4279SBram Moolenaar 
29071d4279SBram Moolenaar #if defined(_WIN32) && defined(HAVE_FCNTL_H)
30071d4279SBram Moolenaar # undef HAVE_FCNTL_H
31071d4279SBram Moolenaar #endif
32071d4279SBram Moolenaar 
33071d4279SBram Moolenaar #ifdef _DEBUG
34071d4279SBram Moolenaar # undef _DEBUG
35071d4279SBram Moolenaar #endif
36071d4279SBram Moolenaar 
37071d4279SBram Moolenaar #ifdef HAVE_STDARG_H
38071d4279SBram Moolenaar # undef HAVE_STDARG_H	/* Python's config.h defines it as well. */
39071d4279SBram Moolenaar #endif
40be2c9ae9SBram Moolenaar #ifdef _POSIX_C_SOURCE
41be2c9ae9SBram Moolenaar # undef _POSIX_C_SOURCE	/* pyconfig.h defines it as well. */
42be2c9ae9SBram Moolenaar #endif
43be2c9ae9SBram Moolenaar #ifdef _XOPEN_SOURCE
44be2c9ae9SBram Moolenaar # undef _XOPEN_SOURCE	/* pyconfig.h defines it as well. */
45be2c9ae9SBram Moolenaar #endif
46071d4279SBram Moolenaar 
472c45e945SBram Moolenaar #define PY_SSIZE_T_CLEAN
482c45e945SBram Moolenaar 
49071d4279SBram Moolenaar #include <Python.h>
50071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX)
51071d4279SBram Moolenaar # include "macglue.h"
52071d4279SBram Moolenaar # include <CodeFragments.h>
53071d4279SBram Moolenaar #endif
54071d4279SBram Moolenaar #undef main /* Defined in python.h - aargh */
55071d4279SBram Moolenaar #undef HAVE_FCNTL_H /* Clash with os_win32.h */
56071d4279SBram Moolenaar 
57170bf1aeSBram Moolenaar static void init_structs(void);
58170bf1aeSBram Moolenaar 
59071d4279SBram Moolenaar #if !defined(FEAT_PYTHON) && defined(PROTO)
60071d4279SBram Moolenaar /* Use this to be able to generate prototypes without python being used. */
61e7cb9cf6SBram Moolenaar # define PyObject Py_ssize_t
62e7cb9cf6SBram Moolenaar # define PyThreadState Py_ssize_t
63e7cb9cf6SBram Moolenaar # define PyTypeObject Py_ssize_t
64e7cb9cf6SBram Moolenaar struct PyMethodDef { Py_ssize_t a; };
65e7cb9cf6SBram Moolenaar # define PySequenceMethods Py_ssize_t
66071d4279SBram Moolenaar #endif
67071d4279SBram Moolenaar 
682c45e945SBram Moolenaar #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02050000
692c45e945SBram Moolenaar # define PyInt Py_ssize_t
702c45e945SBram Moolenaar # define PyInquiry lenfunc
712c45e945SBram Moolenaar # define PyIntArgFunc ssizeargfunc
722c45e945SBram Moolenaar # define PyIntIntArgFunc ssizessizeargfunc
732c45e945SBram Moolenaar # define PyIntObjArgProc ssizeobjargproc
742c45e945SBram Moolenaar # define PyIntIntObjArgProc ssizessizeobjargproc
75e7cb9cf6SBram Moolenaar # define Py_ssize_t_fmt "n"
762c45e945SBram Moolenaar #else
772c45e945SBram Moolenaar # define PyInt int
782c45e945SBram Moolenaar # define PyInquiry inquiry
792c45e945SBram Moolenaar # define PyIntArgFunc intargfunc
802c45e945SBram Moolenaar # define PyIntIntArgFunc intintargfunc
812c45e945SBram Moolenaar # define PyIntObjArgProc intobjargproc
822c45e945SBram Moolenaar # define PyIntIntObjArgProc intintobjargproc
83e7cb9cf6SBram Moolenaar # define Py_ssize_t_fmt "i"
842c45e945SBram Moolenaar #endif
852c45e945SBram Moolenaar 
86071d4279SBram Moolenaar /* Parser flags */
87071d4279SBram Moolenaar #define single_input	256
88071d4279SBram Moolenaar #define file_input	257
89071d4279SBram Moolenaar #define eval_input	258
90071d4279SBram Moolenaar 
91071d4279SBram Moolenaar #if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x020300F0
92071d4279SBram Moolenaar   /* Python 2.3: can invoke ":python" recursively. */
93071d4279SBram Moolenaar # define PY_CAN_RECURSE
94071d4279SBram Moolenaar #endif
95071d4279SBram Moolenaar 
96071d4279SBram Moolenaar # if defined(DYNAMIC_PYTHON) || defined(PROTO)
97071d4279SBram Moolenaar #  ifndef DYNAMIC_PYTHON
98e7cb9cf6SBram Moolenaar #   define HINSTANCE long_u		/* for generating prototypes */
99071d4279SBram Moolenaar #  endif
100071d4279SBram Moolenaar 
101fa5d1e63SBram Moolenaar # ifndef WIN3264
102bd5e15fdSBram Moolenaar #  include <dlfcn.h>
103bd5e15fdSBram Moolenaar #  define FARPROC void*
104bd5e15fdSBram Moolenaar #  define HINSTANCE void*
105644d37b8SBram Moolenaar #  if defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL)
106b61f95c3SBram Moolenaar #   define load_dll(n) dlopen((n), RTLD_LAZY)
107b61f95c3SBram Moolenaar #  else
108fa5d1e63SBram Moolenaar #   define load_dll(n) dlopen((n), RTLD_LAZY|RTLD_GLOBAL)
109b61f95c3SBram Moolenaar #  endif
110bd5e15fdSBram Moolenaar #  define close_dll dlclose
111bd5e15fdSBram Moolenaar #  define symbol_from_dll dlsym
112bd5e15fdSBram Moolenaar # else
113ebbcb824SBram Moolenaar #  define load_dll vimLoadLib
114bd5e15fdSBram Moolenaar #  define close_dll FreeLibrary
115bd5e15fdSBram Moolenaar #  define symbol_from_dll GetProcAddress
116bd5e15fdSBram Moolenaar # endif
117bd5e15fdSBram Moolenaar 
118e7cb9cf6SBram Moolenaar /* This makes if_python.c compile without warnings against Python 2.5
119e7cb9cf6SBram Moolenaar  * on Win32 and Win64. */
120e7cb9cf6SBram Moolenaar # undef PyRun_SimpleString
121e7cb9cf6SBram Moolenaar # undef PyArg_Parse
122e7cb9cf6SBram Moolenaar # undef PyArg_ParseTuple
123e7cb9cf6SBram Moolenaar # undef Py_BuildValue
124e7cb9cf6SBram Moolenaar # undef Py_InitModule4
125e7cb9cf6SBram Moolenaar # undef Py_InitModule4_64
126e7cb9cf6SBram Moolenaar 
127071d4279SBram Moolenaar /*
128071d4279SBram Moolenaar  * Wrapper defines
129071d4279SBram Moolenaar  */
130071d4279SBram Moolenaar # define PyArg_Parse dll_PyArg_Parse
131071d4279SBram Moolenaar # define PyArg_ParseTuple dll_PyArg_ParseTuple
132071d4279SBram Moolenaar # define PyDict_SetItemString dll_PyDict_SetItemString
133071d4279SBram Moolenaar # define PyErr_BadArgument dll_PyErr_BadArgument
134071d4279SBram Moolenaar # define PyErr_Clear dll_PyErr_Clear
135071d4279SBram Moolenaar # define PyErr_NoMemory dll_PyErr_NoMemory
136071d4279SBram Moolenaar # define PyErr_Occurred dll_PyErr_Occurred
137071d4279SBram Moolenaar # define PyErr_SetNone dll_PyErr_SetNone
138071d4279SBram Moolenaar # define PyErr_SetString dll_PyErr_SetString
139071d4279SBram Moolenaar # define PyEval_InitThreads dll_PyEval_InitThreads
140071d4279SBram Moolenaar # define PyEval_RestoreThread dll_PyEval_RestoreThread
141071d4279SBram Moolenaar # define PyEval_SaveThread dll_PyEval_SaveThread
142071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE
143071d4279SBram Moolenaar #  define PyGILState_Ensure dll_PyGILState_Ensure
144071d4279SBram Moolenaar #  define PyGILState_Release dll_PyGILState_Release
145071d4279SBram Moolenaar # endif
146071d4279SBram Moolenaar # define PyInt_AsLong dll_PyInt_AsLong
147071d4279SBram Moolenaar # define PyInt_FromLong dll_PyInt_FromLong
148071d4279SBram Moolenaar # define PyInt_Type (*dll_PyInt_Type)
149071d4279SBram Moolenaar # define PyList_GetItem dll_PyList_GetItem
1500ac9379aSBram Moolenaar # define PyList_Append dll_PyList_Append
151071d4279SBram Moolenaar # define PyList_New dll_PyList_New
152071d4279SBram Moolenaar # define PyList_SetItem dll_PyList_SetItem
153071d4279SBram Moolenaar # define PyList_Size dll_PyList_Size
154071d4279SBram Moolenaar # define PyList_Type (*dll_PyList_Type)
155071d4279SBram Moolenaar # define PyImport_ImportModule dll_PyImport_ImportModule
1560ac9379aSBram Moolenaar # define PyDict_New dll_PyDict_New
157071d4279SBram Moolenaar # define PyDict_GetItemString dll_PyDict_GetItemString
158071d4279SBram Moolenaar # define PyModule_GetDict dll_PyModule_GetDict
159071d4279SBram Moolenaar # define PyRun_SimpleString dll_PyRun_SimpleString
160071d4279SBram Moolenaar # define PyString_AsString dll_PyString_AsString
161071d4279SBram Moolenaar # define PyString_FromString dll_PyString_FromString
162071d4279SBram Moolenaar # define PyString_FromStringAndSize dll_PyString_FromStringAndSize
163071d4279SBram Moolenaar # define PyString_Size dll_PyString_Size
164071d4279SBram Moolenaar # define PyString_Type (*dll_PyString_Type)
165071d4279SBram Moolenaar # define PySys_SetObject dll_PySys_SetObject
166071d4279SBram Moolenaar # define PySys_SetArgv dll_PySys_SetArgv
167071d4279SBram Moolenaar # define PyType_Type (*dll_PyType_Type)
168*30fec7bcSBram Moolenaar # define PyType_Ready (*dll_PyType_Ready)
169071d4279SBram Moolenaar # define Py_BuildValue dll_Py_BuildValue
170071d4279SBram Moolenaar # define Py_FindMethod dll_Py_FindMethod
171071d4279SBram Moolenaar # define Py_InitModule4 dll_Py_InitModule4
172644d37b8SBram Moolenaar # define Py_SetPythonHome dll_Py_SetPythonHome
173071d4279SBram Moolenaar # define Py_Initialize dll_Py_Initialize
1740e21a3f6SBram Moolenaar # define Py_Finalize dll_Py_Finalize
1750e21a3f6SBram Moolenaar # define Py_IsInitialized dll_Py_IsInitialized
176071d4279SBram Moolenaar # define _PyObject_New dll__PyObject_New
177071d4279SBram Moolenaar # define _Py_NoneStruct (*dll__Py_NoneStruct)
178071d4279SBram Moolenaar # define PyObject_Init dll__PyObject_Init
179071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
180071d4279SBram Moolenaar #  define PyType_IsSubtype dll_PyType_IsSubtype
181071d4279SBram Moolenaar # endif
182071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
183071d4279SBram Moolenaar #  define PyObject_Malloc dll_PyObject_Malloc
184071d4279SBram Moolenaar #  define PyObject_Free dll_PyObject_Free
185071d4279SBram Moolenaar # endif
186071d4279SBram Moolenaar 
187071d4279SBram Moolenaar /*
188071d4279SBram Moolenaar  * Pointers for dynamic link
189071d4279SBram Moolenaar  */
190071d4279SBram Moolenaar static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
191071d4279SBram Moolenaar static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
192071d4279SBram Moolenaar static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
193071d4279SBram Moolenaar static int(*dll_PyErr_BadArgument)(void);
194071d4279SBram Moolenaar static void(*dll_PyErr_Clear)(void);
195071d4279SBram Moolenaar static PyObject*(*dll_PyErr_NoMemory)(void);
196071d4279SBram Moolenaar static PyObject*(*dll_PyErr_Occurred)(void);
197071d4279SBram Moolenaar static void(*dll_PyErr_SetNone)(PyObject *);
198071d4279SBram Moolenaar static void(*dll_PyErr_SetString)(PyObject *, const char *);
199071d4279SBram Moolenaar static void(*dll_PyEval_InitThreads)(void);
200071d4279SBram Moolenaar static void(*dll_PyEval_RestoreThread)(PyThreadState *);
201071d4279SBram Moolenaar static PyThreadState*(*dll_PyEval_SaveThread)(void);
202071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE
203071d4279SBram Moolenaar static PyGILState_STATE	(*dll_PyGILState_Ensure)(void);
204071d4279SBram Moolenaar static void (*dll_PyGILState_Release)(PyGILState_STATE);
205071d4279SBram Moolenaar #endif
206071d4279SBram Moolenaar static long(*dll_PyInt_AsLong)(PyObject *);
207071d4279SBram Moolenaar static PyObject*(*dll_PyInt_FromLong)(long);
208071d4279SBram Moolenaar static PyTypeObject* dll_PyInt_Type;
2092c45e945SBram Moolenaar static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt);
2100ac9379aSBram Moolenaar static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *);
2112c45e945SBram Moolenaar static PyObject*(*dll_PyList_New)(PyInt size);
2122c45e945SBram Moolenaar static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *);
2132c45e945SBram Moolenaar static PyInt(*dll_PyList_Size)(PyObject *);
214071d4279SBram Moolenaar static PyTypeObject* dll_PyList_Type;
215071d4279SBram Moolenaar static PyObject*(*dll_PyImport_ImportModule)(const char *);
2160ac9379aSBram Moolenaar static PyObject*(*dll_PyDict_New)(void);
217071d4279SBram Moolenaar static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
218071d4279SBram Moolenaar static PyObject*(*dll_PyModule_GetDict)(PyObject *);
219071d4279SBram Moolenaar static int(*dll_PyRun_SimpleString)(char *);
220071d4279SBram Moolenaar static char*(*dll_PyString_AsString)(PyObject *);
221071d4279SBram Moolenaar static PyObject*(*dll_PyString_FromString)(const char *);
2222c45e945SBram Moolenaar static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt);
2232c45e945SBram Moolenaar static PyInt(*dll_PyString_Size)(PyObject *);
224071d4279SBram Moolenaar static PyTypeObject* dll_PyString_Type;
225071d4279SBram Moolenaar static int(*dll_PySys_SetObject)(char *, PyObject *);
226071d4279SBram Moolenaar static int(*dll_PySys_SetArgv)(int, char **);
227071d4279SBram Moolenaar static PyTypeObject* dll_PyType_Type;
228*30fec7bcSBram Moolenaar static int (*dll_PyType_Ready)(PyTypeObject *type);
229071d4279SBram Moolenaar static PyObject*(*dll_Py_BuildValue)(char *, ...);
230071d4279SBram Moolenaar static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
231071d4279SBram Moolenaar static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
232644d37b8SBram Moolenaar static void(*dll_Py_SetPythonHome)(char *home);
233071d4279SBram Moolenaar static void(*dll_Py_Initialize)(void);
2340e21a3f6SBram Moolenaar static void(*dll_Py_Finalize)(void);
2350e21a3f6SBram Moolenaar static int(*dll_Py_IsInitialized)(void);
236071d4279SBram Moolenaar static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
237071d4279SBram Moolenaar static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
238071d4279SBram Moolenaar static PyObject* dll__Py_NoneStruct;
239071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
240071d4279SBram Moolenaar static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
241071d4279SBram Moolenaar # endif
242071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
243071d4279SBram Moolenaar static void* (*dll_PyObject_Malloc)(size_t);
244071d4279SBram Moolenaar static void (*dll_PyObject_Free)(void*);
245071d4279SBram Moolenaar # endif
246071d4279SBram Moolenaar 
247071d4279SBram Moolenaar static HINSTANCE hinstPython = 0; /* Instance of python.dll */
248071d4279SBram Moolenaar 
249071d4279SBram Moolenaar /* Imported exception objects */
250071d4279SBram Moolenaar static PyObject *imp_PyExc_AttributeError;
251071d4279SBram Moolenaar static PyObject *imp_PyExc_IndexError;
252071d4279SBram Moolenaar static PyObject *imp_PyExc_KeyboardInterrupt;
253071d4279SBram Moolenaar static PyObject *imp_PyExc_TypeError;
254071d4279SBram Moolenaar static PyObject *imp_PyExc_ValueError;
255071d4279SBram Moolenaar 
256071d4279SBram Moolenaar # define PyExc_AttributeError imp_PyExc_AttributeError
257071d4279SBram Moolenaar # define PyExc_IndexError imp_PyExc_IndexError
258071d4279SBram Moolenaar # define PyExc_KeyboardInterrupt imp_PyExc_KeyboardInterrupt
259071d4279SBram Moolenaar # define PyExc_TypeError imp_PyExc_TypeError
260071d4279SBram Moolenaar # define PyExc_ValueError imp_PyExc_ValueError
261071d4279SBram Moolenaar 
262071d4279SBram Moolenaar /*
263071d4279SBram Moolenaar  * Table of name to function pointer of python.
264071d4279SBram Moolenaar  */
265071d4279SBram Moolenaar # define PYTHON_PROC FARPROC
266071d4279SBram Moolenaar static struct
267071d4279SBram Moolenaar {
268071d4279SBram Moolenaar     char *name;
269071d4279SBram Moolenaar     PYTHON_PROC *ptr;
270071d4279SBram Moolenaar } python_funcname_table[] =
271071d4279SBram Moolenaar {
272071d4279SBram Moolenaar     {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
273071d4279SBram Moolenaar     {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
274071d4279SBram Moolenaar     {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
275071d4279SBram Moolenaar     {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
276071d4279SBram Moolenaar     {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
277071d4279SBram Moolenaar     {"PyErr_NoMemory", (PYTHON_PROC*)&dll_PyErr_NoMemory},
278071d4279SBram Moolenaar     {"PyErr_Occurred", (PYTHON_PROC*)&dll_PyErr_Occurred},
279071d4279SBram Moolenaar     {"PyErr_SetNone", (PYTHON_PROC*)&dll_PyErr_SetNone},
280071d4279SBram Moolenaar     {"PyErr_SetString", (PYTHON_PROC*)&dll_PyErr_SetString},
281071d4279SBram Moolenaar     {"PyEval_InitThreads", (PYTHON_PROC*)&dll_PyEval_InitThreads},
282071d4279SBram Moolenaar     {"PyEval_RestoreThread", (PYTHON_PROC*)&dll_PyEval_RestoreThread},
283071d4279SBram Moolenaar     {"PyEval_SaveThread", (PYTHON_PROC*)&dll_PyEval_SaveThread},
284071d4279SBram Moolenaar # ifdef PY_CAN_RECURSE
285071d4279SBram Moolenaar     {"PyGILState_Ensure", (PYTHON_PROC*)&dll_PyGILState_Ensure},
286071d4279SBram Moolenaar     {"PyGILState_Release", (PYTHON_PROC*)&dll_PyGILState_Release},
287071d4279SBram Moolenaar # endif
288071d4279SBram Moolenaar     {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong},
289071d4279SBram Moolenaar     {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong},
290071d4279SBram Moolenaar     {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type},
291071d4279SBram Moolenaar     {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem},
2920ac9379aSBram Moolenaar     {"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append},
293071d4279SBram Moolenaar     {"PyList_New", (PYTHON_PROC*)&dll_PyList_New},
294071d4279SBram Moolenaar     {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
295071d4279SBram Moolenaar     {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
296071d4279SBram Moolenaar     {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
297071d4279SBram Moolenaar     {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
298071d4279SBram Moolenaar     {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
2990ac9379aSBram Moolenaar     {"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New},
300071d4279SBram Moolenaar     {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
301071d4279SBram Moolenaar     {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
302071d4279SBram Moolenaar     {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
303071d4279SBram Moolenaar     {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
304071d4279SBram Moolenaar     {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize},
305071d4279SBram Moolenaar     {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size},
306071d4279SBram Moolenaar     {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type},
307071d4279SBram Moolenaar     {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
308071d4279SBram Moolenaar     {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
309071d4279SBram Moolenaar     {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
310*30fec7bcSBram Moolenaar     {"PyType_Ready", (PYTHON_PROC*)&dll_PyType_Ready},
311071d4279SBram Moolenaar     {"Py_BuildValue", (PYTHON_PROC*)&dll_Py_BuildValue},
312071d4279SBram Moolenaar     {"Py_FindMethod", (PYTHON_PROC*)&dll_Py_FindMethod},
313e7cb9cf6SBram Moolenaar # if (PY_VERSION_HEX >= 0x02050000) && SIZEOF_SIZE_T != SIZEOF_INT
314e7cb9cf6SBram Moolenaar     {"Py_InitModule4_64", (PYTHON_PROC*)&dll_Py_InitModule4},
315e7cb9cf6SBram Moolenaar # else
316071d4279SBram Moolenaar     {"Py_InitModule4", (PYTHON_PROC*)&dll_Py_InitModule4},
317e7cb9cf6SBram Moolenaar # endif
318644d37b8SBram Moolenaar     {"Py_SetPythonHome", (PYTHON_PROC*)&dll_Py_SetPythonHome},
319071d4279SBram Moolenaar     {"Py_Initialize", (PYTHON_PROC*)&dll_Py_Initialize},
3200e21a3f6SBram Moolenaar     {"Py_Finalize", (PYTHON_PROC*)&dll_Py_Finalize},
3210e21a3f6SBram Moolenaar     {"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized},
322071d4279SBram Moolenaar     {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
323071d4279SBram Moolenaar     {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
324071d4279SBram Moolenaar     {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct},
325071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
326071d4279SBram Moolenaar     {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype},
327071d4279SBram Moolenaar # endif
328071d4279SBram Moolenaar # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02030000
329071d4279SBram Moolenaar     {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc},
330071d4279SBram Moolenaar     {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free},
331071d4279SBram Moolenaar # endif
332071d4279SBram Moolenaar     {"", NULL},
333071d4279SBram Moolenaar };
334071d4279SBram Moolenaar 
335071d4279SBram Moolenaar /*
336071d4279SBram Moolenaar  * Free python.dll
337071d4279SBram Moolenaar  */
338071d4279SBram Moolenaar     static void
339071d4279SBram Moolenaar end_dynamic_python(void)
340071d4279SBram Moolenaar {
341071d4279SBram Moolenaar     if (hinstPython)
342071d4279SBram Moolenaar     {
343bd5e15fdSBram Moolenaar 	close_dll(hinstPython);
344071d4279SBram Moolenaar 	hinstPython = 0;
345071d4279SBram Moolenaar     }
346071d4279SBram Moolenaar }
347071d4279SBram Moolenaar 
348071d4279SBram Moolenaar /*
349071d4279SBram Moolenaar  * Load library and get all pointers.
350071d4279SBram Moolenaar  * Parameter 'libname' provides name of DLL.
351071d4279SBram Moolenaar  * Return OK or FAIL.
352071d4279SBram Moolenaar  */
353071d4279SBram Moolenaar     static int
354071d4279SBram Moolenaar python_runtime_link_init(char *libname, int verbose)
355071d4279SBram Moolenaar {
356071d4279SBram Moolenaar     int i;
357071d4279SBram Moolenaar 
358644d37b8SBram Moolenaar #if !(defined(PY_NO_RTLD_GLOBAL) && defined(PY3_NO_RTLD_GLOBAL)) && defined(UNIX) && defined(FEAT_PYTHON3)
359b744b2faSBram Moolenaar     /* Can't have Python and Python3 loaded at the same time.
360b744b2faSBram Moolenaar      * It cause a crash, because RTLD_GLOBAL is needed for
361b744b2faSBram Moolenaar      * standard C extension libraries of one or both python versions. */
3624c3a326cSBram Moolenaar     if (python3_loaded())
3634c3a326cSBram Moolenaar     {
364b744b2faSBram Moolenaar 	EMSG(_("E836: This Vim cannot execute :python after using :py3"));
3654c3a326cSBram Moolenaar 	return FAIL;
3664c3a326cSBram Moolenaar     }
3674c3a326cSBram Moolenaar #endif
3684c3a326cSBram Moolenaar 
369071d4279SBram Moolenaar     if (hinstPython)
370071d4279SBram Moolenaar 	return OK;
371bd5e15fdSBram Moolenaar     hinstPython = load_dll(libname);
372071d4279SBram Moolenaar     if (!hinstPython)
373071d4279SBram Moolenaar     {
374071d4279SBram Moolenaar 	if (verbose)
375071d4279SBram Moolenaar 	    EMSG2(_(e_loadlib), libname);
376071d4279SBram Moolenaar 	return FAIL;
377071d4279SBram Moolenaar     }
378071d4279SBram Moolenaar 
379071d4279SBram Moolenaar     for (i = 0; python_funcname_table[i].ptr; ++i)
380071d4279SBram Moolenaar     {
381bd5e15fdSBram Moolenaar 	if ((*python_funcname_table[i].ptr = symbol_from_dll(hinstPython,
382071d4279SBram Moolenaar 			python_funcname_table[i].name)) == NULL)
383071d4279SBram Moolenaar 	{
384bd5e15fdSBram Moolenaar 	    close_dll(hinstPython);
385071d4279SBram Moolenaar 	    hinstPython = 0;
386071d4279SBram Moolenaar 	    if (verbose)
387071d4279SBram Moolenaar 		EMSG2(_(e_loadfunc), python_funcname_table[i].name);
388071d4279SBram Moolenaar 	    return FAIL;
389071d4279SBram Moolenaar 	}
390071d4279SBram Moolenaar     }
391071d4279SBram Moolenaar     return OK;
392071d4279SBram Moolenaar }
393071d4279SBram Moolenaar 
394071d4279SBram Moolenaar /*
395071d4279SBram Moolenaar  * If python is enabled (there is installed python on Windows system) return
396071d4279SBram Moolenaar  * TRUE, else FALSE.
397071d4279SBram Moolenaar  */
398071d4279SBram Moolenaar     int
399e7cb9cf6SBram Moolenaar python_enabled(int verbose)
400071d4279SBram Moolenaar {
401071d4279SBram Moolenaar     return python_runtime_link_init(DYNAMIC_PYTHON_DLL, verbose) == OK;
402071d4279SBram Moolenaar }
403071d4279SBram Moolenaar 
404ca8a4dfeSBram Moolenaar /*
405ca8a4dfeSBram Moolenaar  * Load the standard Python exceptions - don't import the symbols from the
406071d4279SBram Moolenaar  * DLL, as this can cause errors (importing data symbols is not reliable).
407071d4279SBram Moolenaar  */
408071d4279SBram Moolenaar     static void
409ca8a4dfeSBram Moolenaar get_exceptions(void)
410071d4279SBram Moolenaar {
411071d4279SBram Moolenaar     PyObject *exmod = PyImport_ImportModule("exceptions");
412071d4279SBram Moolenaar     PyObject *exdict = PyModule_GetDict(exmod);
413071d4279SBram Moolenaar     imp_PyExc_AttributeError = PyDict_GetItemString(exdict, "AttributeError");
414071d4279SBram Moolenaar     imp_PyExc_IndexError = PyDict_GetItemString(exdict, "IndexError");
415071d4279SBram Moolenaar     imp_PyExc_KeyboardInterrupt = PyDict_GetItemString(exdict, "KeyboardInterrupt");
416071d4279SBram Moolenaar     imp_PyExc_TypeError = PyDict_GetItemString(exdict, "TypeError");
417071d4279SBram Moolenaar     imp_PyExc_ValueError = PyDict_GetItemString(exdict, "ValueError");
418071d4279SBram Moolenaar     Py_XINCREF(imp_PyExc_AttributeError);
419071d4279SBram Moolenaar     Py_XINCREF(imp_PyExc_IndexError);
420071d4279SBram Moolenaar     Py_XINCREF(imp_PyExc_KeyboardInterrupt);
421071d4279SBram Moolenaar     Py_XINCREF(imp_PyExc_TypeError);
422071d4279SBram Moolenaar     Py_XINCREF(imp_PyExc_ValueError);
423071d4279SBram Moolenaar     Py_XDECREF(exmod);
424071d4279SBram Moolenaar }
425071d4279SBram Moolenaar #endif /* DYNAMIC_PYTHON */
426071d4279SBram Moolenaar 
427ca8a4dfeSBram Moolenaar static PyObject *BufferNew (buf_T *);
428ca8a4dfeSBram Moolenaar static PyObject *WindowNew(win_T *);
429ca8a4dfeSBram Moolenaar static PyObject *LineToString(const char *);
430ca8a4dfeSBram Moolenaar 
431ca8a4dfeSBram Moolenaar static PyTypeObject RangeType;
432ca8a4dfeSBram Moolenaar 
433170bf1aeSBram Moolenaar /*
434170bf1aeSBram Moolenaar  * Include the code shared with if_python3.c
435170bf1aeSBram Moolenaar  */
436170bf1aeSBram Moolenaar #include "if_py_both.h"
437170bf1aeSBram Moolenaar 
438170bf1aeSBram Moolenaar 
439071d4279SBram Moolenaar /******************************************************
440071d4279SBram Moolenaar  * Internal function prototypes.
441071d4279SBram Moolenaar  */
442071d4279SBram Moolenaar 
443e7cb9cf6SBram Moolenaar static PyInt RangeStart;
444e7cb9cf6SBram Moolenaar static PyInt RangeEnd;
445071d4279SBram Moolenaar 
446071d4279SBram Moolenaar static void PythonIO_Flush(void);
447071d4279SBram Moolenaar static int PythonIO_Init(void);
448071d4279SBram Moolenaar static int PythonMod_Init(void);
449071d4279SBram Moolenaar 
450071d4279SBram Moolenaar /* Utility functions for the vim/python interface
451071d4279SBram Moolenaar  * ----------------------------------------------
452071d4279SBram Moolenaar  */
453071d4279SBram Moolenaar 
454e7cb9cf6SBram Moolenaar static int SetBufferLineList(buf_T *, PyInt, PyInt, PyObject *, PyInt *);
455071d4279SBram Moolenaar 
456071d4279SBram Moolenaar 
457071d4279SBram Moolenaar /******************************************************
458071d4279SBram Moolenaar  * 1. Python interpreter main program.
459071d4279SBram Moolenaar  */
460071d4279SBram Moolenaar 
461071d4279SBram Moolenaar static int initialised = 0;
462071d4279SBram Moolenaar 
463071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */
464071d4279SBram Moolenaar typedef PyObject PyThreadState;
4659ba0eb85SBram Moolenaar #endif
466071d4279SBram Moolenaar 
4679ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE
4689ba0eb85SBram Moolenaar static PyGILState_STATE pygilstate = PyGILState_UNLOCKED;
4699ba0eb85SBram Moolenaar #else
470071d4279SBram Moolenaar static PyThreadState *saved_python_thread = NULL;
4719ba0eb85SBram Moolenaar #endif
472071d4279SBram Moolenaar 
473071d4279SBram Moolenaar /*
474071d4279SBram Moolenaar  * Suspend a thread of the Python interpreter, other threads are allowed to
475071d4279SBram Moolenaar  * run.
476071d4279SBram Moolenaar  */
477293ee4d4SBram Moolenaar     static void
478293ee4d4SBram Moolenaar Python_SaveThread(void)
479071d4279SBram Moolenaar {
4809ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE
4819ba0eb85SBram Moolenaar     PyGILState_Release(pygilstate);
4829ba0eb85SBram Moolenaar #else
483071d4279SBram Moolenaar     saved_python_thread = PyEval_SaveThread();
4849ba0eb85SBram Moolenaar #endif
485071d4279SBram Moolenaar }
486071d4279SBram Moolenaar 
487071d4279SBram Moolenaar /*
488071d4279SBram Moolenaar  * Restore a thread of the Python interpreter, waits for other threads to
489071d4279SBram Moolenaar  * block.
490071d4279SBram Moolenaar  */
491293ee4d4SBram Moolenaar     static void
492293ee4d4SBram Moolenaar Python_RestoreThread(void)
493071d4279SBram Moolenaar {
4949ba0eb85SBram Moolenaar #ifdef PY_CAN_RECURSE
4959ba0eb85SBram Moolenaar     pygilstate = PyGILState_Ensure();
4969ba0eb85SBram Moolenaar #else
497071d4279SBram Moolenaar     PyEval_RestoreThread(saved_python_thread);
498071d4279SBram Moolenaar     saved_python_thread = NULL;
499071d4279SBram Moolenaar #endif
5009ba0eb85SBram Moolenaar }
501071d4279SBram Moolenaar 
502071d4279SBram Moolenaar     void
503071d4279SBram Moolenaar python_end()
504071d4279SBram Moolenaar {
505a5792f58SBram Moolenaar     static int recurse = 0;
506a5792f58SBram Moolenaar 
507a5792f58SBram Moolenaar     /* If a crash occurs while doing this, don't try again. */
508a5792f58SBram Moolenaar     if (recurse != 0)
509a5792f58SBram Moolenaar 	return;
510a5792f58SBram Moolenaar 
511a5792f58SBram Moolenaar     ++recurse;
512a5792f58SBram Moolenaar 
513071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON
5140e21a3f6SBram Moolenaar     if (hinstPython && Py_IsInitialized())
5159ba0eb85SBram Moolenaar     {
5169ba0eb85SBram Moolenaar 	Python_RestoreThread();	    /* enter python */
5170e21a3f6SBram Moolenaar 	Py_Finalize();
5189ba0eb85SBram Moolenaar     }
519071d4279SBram Moolenaar     end_dynamic_python();
5200e21a3f6SBram Moolenaar #else
5210e21a3f6SBram Moolenaar     if (Py_IsInitialized())
5229ba0eb85SBram Moolenaar     {
5239ba0eb85SBram Moolenaar 	Python_RestoreThread();	    /* enter python */
5240e21a3f6SBram Moolenaar 	Py_Finalize();
5259ba0eb85SBram Moolenaar     }
526071d4279SBram Moolenaar #endif
527a5792f58SBram Moolenaar 
528a5792f58SBram Moolenaar     --recurse;
529071d4279SBram Moolenaar }
530071d4279SBram Moolenaar 
5314c3a326cSBram Moolenaar #if (defined(DYNAMIC_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO)
5324c3a326cSBram Moolenaar     int
5334c3a326cSBram Moolenaar python_loaded()
5344c3a326cSBram Moolenaar {
5354c3a326cSBram Moolenaar     return (hinstPython != 0);
5364c3a326cSBram Moolenaar }
5374c3a326cSBram Moolenaar #endif
5384c3a326cSBram Moolenaar 
539071d4279SBram Moolenaar     static int
540071d4279SBram Moolenaar Python_Init(void)
541071d4279SBram Moolenaar {
542071d4279SBram Moolenaar     if (!initialised)
543071d4279SBram Moolenaar     {
544071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON
545071d4279SBram Moolenaar 	if (!python_enabled(TRUE))
546071d4279SBram Moolenaar 	{
547071d4279SBram Moolenaar 	    EMSG(_("E263: Sorry, this command is disabled, the Python library could not be loaded."));
548071d4279SBram Moolenaar 	    goto fail;
549071d4279SBram Moolenaar 	}
550071d4279SBram Moolenaar #endif
551071d4279SBram Moolenaar 
552644d37b8SBram Moolenaar #ifdef PYTHON_HOME
553644d37b8SBram Moolenaar 	Py_SetPythonHome(PYTHON_HOME);
554644d37b8SBram Moolenaar #endif
555644d37b8SBram Moolenaar 
556170bf1aeSBram Moolenaar 	init_structs();
557170bf1aeSBram Moolenaar 
558071d4279SBram Moolenaar #if !defined(MACOS) || defined(MACOS_X_UNIX)
559071d4279SBram Moolenaar 	Py_Initialize();
560071d4279SBram Moolenaar #else
561071d4279SBram Moolenaar 	PyMac_Initialize();
562071d4279SBram Moolenaar #endif
563071d4279SBram Moolenaar 	/* initialise threads */
564071d4279SBram Moolenaar 	PyEval_InitThreads();
565071d4279SBram Moolenaar 
566071d4279SBram Moolenaar #ifdef DYNAMIC_PYTHON
567071d4279SBram Moolenaar 	get_exceptions();
568071d4279SBram Moolenaar #endif
569071d4279SBram Moolenaar 
570071d4279SBram Moolenaar 	if (PythonIO_Init())
571071d4279SBram Moolenaar 	    goto fail;
572071d4279SBram Moolenaar 
573071d4279SBram Moolenaar 	if (PythonMod_Init())
574071d4279SBram Moolenaar 	    goto fail;
575071d4279SBram Moolenaar 
5769774ecc8SBram Moolenaar 	/* Remove the element from sys.path that was added because of our
5779774ecc8SBram Moolenaar 	 * argv[0] value in PythonMod_Init().  Previously we used an empty
5789774ecc8SBram Moolenaar 	 * string, but dependinding on the OS we then get an empty entry or
5799774ecc8SBram Moolenaar 	 * the current directory in sys.path. */
5809774ecc8SBram Moolenaar 	PyRun_SimpleString("import sys; sys.path = filter(lambda x: x != '/must>not&exist', sys.path)");
5819774ecc8SBram Moolenaar 
582293ee4d4SBram Moolenaar 	/* the first python thread is vim's, release the lock */
583071d4279SBram Moolenaar 	Python_SaveThread();
584071d4279SBram Moolenaar 
585071d4279SBram Moolenaar 	initialised = 1;
586071d4279SBram Moolenaar     }
587071d4279SBram Moolenaar 
588071d4279SBram Moolenaar     return 0;
589071d4279SBram Moolenaar 
590071d4279SBram Moolenaar fail:
591071d4279SBram Moolenaar     /* We call PythonIO_Flush() here to print any Python errors.
592071d4279SBram Moolenaar      * This is OK, as it is possible to call this function even
593071d4279SBram Moolenaar      * if PythonIO_Init() has not completed successfully (it will
594071d4279SBram Moolenaar      * not do anything in this case).
595071d4279SBram Moolenaar      */
596071d4279SBram Moolenaar     PythonIO_Flush();
597071d4279SBram Moolenaar     return -1;
598071d4279SBram Moolenaar }
599071d4279SBram Moolenaar 
600071d4279SBram Moolenaar /*
601071d4279SBram Moolenaar  * External interface
602071d4279SBram Moolenaar  */
603071d4279SBram Moolenaar     static void
604071d4279SBram Moolenaar DoPythonCommand(exarg_T *eap, const char *cmd)
605071d4279SBram Moolenaar {
6069ba0eb85SBram Moolenaar #ifndef PY_CAN_RECURSE
607071d4279SBram Moolenaar     static int		recursive = 0;
608071d4279SBram Moolenaar #endif
609071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX)
610071d4279SBram Moolenaar     GrafPtr		oldPort;
611071d4279SBram Moolenaar #endif
612071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
613071d4279SBram Moolenaar     char		*saved_locale;
614071d4279SBram Moolenaar #endif
615071d4279SBram Moolenaar 
616071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE
617071d4279SBram Moolenaar     if (recursive)
618071d4279SBram Moolenaar     {
619071d4279SBram Moolenaar 	EMSG(_("E659: Cannot invoke Python recursively"));
620071d4279SBram Moolenaar 	return;
621071d4279SBram Moolenaar     }
622071d4279SBram Moolenaar     ++recursive;
623071d4279SBram Moolenaar #endif
624071d4279SBram Moolenaar 
625071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX)
626071d4279SBram Moolenaar     GetPort(&oldPort);
627071d4279SBram Moolenaar     /* Check if the Python library is available */
628071d4279SBram Moolenaar     if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress)
629071d4279SBram Moolenaar 	goto theend;
630071d4279SBram Moolenaar #endif
631071d4279SBram Moolenaar     if (Python_Init())
632071d4279SBram Moolenaar 	goto theend;
633071d4279SBram Moolenaar 
634071d4279SBram Moolenaar     RangeStart = eap->line1;
635071d4279SBram Moolenaar     RangeEnd = eap->line2;
636071d4279SBram Moolenaar     Python_Release_Vim();	    /* leave vim */
637071d4279SBram Moolenaar 
638071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
639071d4279SBram Moolenaar     /* Python only works properly when the LC_NUMERIC locale is "C". */
640071d4279SBram Moolenaar     saved_locale = setlocale(LC_NUMERIC, NULL);
641071d4279SBram Moolenaar     if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0)
642071d4279SBram Moolenaar 	saved_locale = NULL;
643071d4279SBram Moolenaar     else
644071d4279SBram Moolenaar     {
645071d4279SBram Moolenaar 	/* Need to make a copy, value may change when setting new locale. */
646071d4279SBram Moolenaar 	saved_locale = (char *)vim_strsave((char_u *)saved_locale);
647071d4279SBram Moolenaar 	(void)setlocale(LC_NUMERIC, "C");
648071d4279SBram Moolenaar     }
649071d4279SBram Moolenaar #endif
650071d4279SBram Moolenaar 
651071d4279SBram Moolenaar     Python_RestoreThread();	    /* enter python */
652071d4279SBram Moolenaar 
653071d4279SBram Moolenaar     PyRun_SimpleString((char *)(cmd));
654071d4279SBram Moolenaar 
655071d4279SBram Moolenaar     Python_SaveThread();	    /* leave python */
656071d4279SBram Moolenaar 
657071d4279SBram Moolenaar #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
658071d4279SBram Moolenaar     if (saved_locale != NULL)
659071d4279SBram Moolenaar     {
660071d4279SBram Moolenaar 	(void)setlocale(LC_NUMERIC, saved_locale);
661071d4279SBram Moolenaar 	vim_free(saved_locale);
662071d4279SBram Moolenaar     }
663071d4279SBram Moolenaar #endif
664071d4279SBram Moolenaar 
665071d4279SBram Moolenaar     Python_Lock_Vim();		    /* enter vim */
666071d4279SBram Moolenaar     PythonIO_Flush();
667071d4279SBram Moolenaar #if defined(MACOS) && !defined(MACOS_X_UNIX)
668071d4279SBram Moolenaar     SetPort(oldPort);
669071d4279SBram Moolenaar #endif
670071d4279SBram Moolenaar 
671071d4279SBram Moolenaar theend:
672071d4279SBram Moolenaar #ifndef PY_CAN_RECURSE
673071d4279SBram Moolenaar     --recursive;
674071d4279SBram Moolenaar #endif
675071d4279SBram Moolenaar     return;	    /* keeps lint happy */
676071d4279SBram Moolenaar }
677071d4279SBram Moolenaar 
678071d4279SBram Moolenaar /*
679071d4279SBram Moolenaar  * ":python"
680071d4279SBram Moolenaar  */
681071d4279SBram Moolenaar     void
682071d4279SBram Moolenaar ex_python(exarg_T *eap)
683071d4279SBram Moolenaar {
684071d4279SBram Moolenaar     char_u *script;
685071d4279SBram Moolenaar 
686071d4279SBram Moolenaar     script = script_get(eap, eap->arg);
687071d4279SBram Moolenaar     if (!eap->skip)
688071d4279SBram Moolenaar     {
689071d4279SBram Moolenaar 	if (script == NULL)
690071d4279SBram Moolenaar 	    DoPythonCommand(eap, (char *)eap->arg);
691071d4279SBram Moolenaar 	else
692071d4279SBram Moolenaar 	    DoPythonCommand(eap, (char *)script);
693071d4279SBram Moolenaar     }
694071d4279SBram Moolenaar     vim_free(script);
695071d4279SBram Moolenaar }
696071d4279SBram Moolenaar 
697071d4279SBram Moolenaar #define BUFFER_SIZE 1024
698071d4279SBram Moolenaar 
699071d4279SBram Moolenaar /*
700071d4279SBram Moolenaar  * ":pyfile"
701071d4279SBram Moolenaar  */
702071d4279SBram Moolenaar     void
703071d4279SBram Moolenaar ex_pyfile(exarg_T *eap)
704071d4279SBram Moolenaar {
705071d4279SBram Moolenaar     static char buffer[BUFFER_SIZE];
706071d4279SBram Moolenaar     const char *file = (char *)eap->arg;
707071d4279SBram Moolenaar     char *p;
708071d4279SBram Moolenaar 
709071d4279SBram Moolenaar     /* Have to do it like this. PyRun_SimpleFile requires you to pass a
710071d4279SBram Moolenaar      * stdio file pointer, but Vim and the Python DLL are compiled with
711071d4279SBram Moolenaar      * different options under Windows, meaning that stdio pointers aren't
712071d4279SBram Moolenaar      * compatible between the two. Yuk.
713071d4279SBram Moolenaar      *
714071d4279SBram Moolenaar      * Put the string "execfile('file')" into buffer. But, we need to
715071d4279SBram Moolenaar      * escape any backslashes or single quotes in the file name, so that
716071d4279SBram Moolenaar      * Python won't mangle the file name.
717071d4279SBram Moolenaar      */
718071d4279SBram Moolenaar     strcpy(buffer, "execfile('");
719071d4279SBram Moolenaar     p = buffer + 10; /* size of "execfile('" */
720071d4279SBram Moolenaar 
721071d4279SBram Moolenaar     while (*file && p < buffer + (BUFFER_SIZE - 3))
722071d4279SBram Moolenaar     {
723071d4279SBram Moolenaar 	if (*file == '\\' || *file == '\'')
724071d4279SBram Moolenaar 	    *p++ = '\\';
725071d4279SBram Moolenaar 	*p++ = *file++;
726071d4279SBram Moolenaar     }
727071d4279SBram Moolenaar 
728071d4279SBram Moolenaar     /* If we didn't finish the file name, we hit a buffer overflow */
729071d4279SBram Moolenaar     if (*file != '\0')
730071d4279SBram Moolenaar 	return;
731071d4279SBram Moolenaar 
732071d4279SBram Moolenaar     /* Put in the terminating "')" and a null */
733071d4279SBram Moolenaar     *p++ = '\'';
734071d4279SBram Moolenaar     *p++ = ')';
735071d4279SBram Moolenaar     *p++ = '\0';
736071d4279SBram Moolenaar 
737071d4279SBram Moolenaar     /* Execute the file */
738071d4279SBram Moolenaar     DoPythonCommand(eap, buffer);
739071d4279SBram Moolenaar }
740071d4279SBram Moolenaar 
741071d4279SBram Moolenaar /******************************************************
742071d4279SBram Moolenaar  * 2. Python output stream: writes output via [e]msg().
743071d4279SBram Moolenaar  */
744071d4279SBram Moolenaar 
745071d4279SBram Moolenaar /* Implementation functions
746071d4279SBram Moolenaar  */
747071d4279SBram Moolenaar 
748071d4279SBram Moolenaar     static PyObject *
749071d4279SBram Moolenaar OutputGetattr(PyObject *self, char *name)
750071d4279SBram Moolenaar {
751071d4279SBram Moolenaar     if (strcmp(name, "softspace") == 0)
752071d4279SBram Moolenaar 	return PyInt_FromLong(((OutputObject *)(self))->softspace);
753071d4279SBram Moolenaar 
754071d4279SBram Moolenaar     return Py_FindMethod(OutputMethods, self, name);
755071d4279SBram Moolenaar }
756071d4279SBram Moolenaar 
757071d4279SBram Moolenaar     static int
758071d4279SBram Moolenaar OutputSetattr(PyObject *self, char *name, PyObject *val)
759071d4279SBram Moolenaar {
760071d4279SBram Moolenaar     if (val == NULL) {
761071d4279SBram Moolenaar 	PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
762071d4279SBram Moolenaar 	return -1;
763071d4279SBram Moolenaar     }
764071d4279SBram Moolenaar 
765071d4279SBram Moolenaar     if (strcmp(name, "softspace") == 0)
766071d4279SBram Moolenaar     {
767071d4279SBram Moolenaar 	if (!PyInt_Check(val)) {
768071d4279SBram Moolenaar 	    PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
769071d4279SBram Moolenaar 	    return -1;
770071d4279SBram Moolenaar 	}
771071d4279SBram Moolenaar 
772071d4279SBram Moolenaar 	((OutputObject *)(self))->softspace = PyInt_AsLong(val);
773071d4279SBram Moolenaar 	return 0;
774071d4279SBram Moolenaar     }
775071d4279SBram Moolenaar 
776071d4279SBram Moolenaar     PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
777071d4279SBram Moolenaar     return -1;
778071d4279SBram Moolenaar }
779071d4279SBram Moolenaar 
780071d4279SBram Moolenaar /***************/
781071d4279SBram Moolenaar 
782071d4279SBram Moolenaar     static int
783071d4279SBram Moolenaar PythonIO_Init(void)
784071d4279SBram Moolenaar {
785071d4279SBram Moolenaar     /* Fixups... */
78621377c8dSBram Moolenaar     PyType_Ready(&OutputType);
787071d4279SBram Moolenaar 
788170bf1aeSBram Moolenaar     return PythonIO_Init_io();
789071d4279SBram Moolenaar }
790071d4279SBram Moolenaar 
791071d4279SBram Moolenaar /******************************************************
792071d4279SBram Moolenaar  * 3. Implementation of the Vim module for Python
793071d4279SBram Moolenaar  */
794071d4279SBram Moolenaar 
795071d4279SBram Moolenaar /* Window type - Implementation functions
796071d4279SBram Moolenaar  * --------------------------------------
797071d4279SBram Moolenaar  */
798071d4279SBram Moolenaar 
799071d4279SBram Moolenaar #define WindowType_Check(obj) ((obj)->ob_type == &WindowType)
800071d4279SBram Moolenaar 
801071d4279SBram Moolenaar static void WindowDestructor(PyObject *);
802071d4279SBram Moolenaar static PyObject *WindowGetattr(PyObject *, char *);
803071d4279SBram Moolenaar 
804071d4279SBram Moolenaar /* Buffer type - Implementation functions
805071d4279SBram Moolenaar  * --------------------------------------
806071d4279SBram Moolenaar  */
807071d4279SBram Moolenaar 
808071d4279SBram Moolenaar #define BufferType_Check(obj) ((obj)->ob_type == &BufferType)
809071d4279SBram Moolenaar 
810071d4279SBram Moolenaar static void BufferDestructor(PyObject *);
811071d4279SBram Moolenaar static PyObject *BufferGetattr(PyObject *, char *);
812071d4279SBram Moolenaar static PyObject *BufferRepr(PyObject *);
813071d4279SBram Moolenaar 
8142c45e945SBram Moolenaar static PyInt BufferLength(PyObject *);
8152c45e945SBram Moolenaar static PyObject *BufferItem(PyObject *, PyInt);
8162c45e945SBram Moolenaar static PyObject *BufferSlice(PyObject *, PyInt, PyInt);
8172c45e945SBram Moolenaar static PyInt BufferAssItem(PyObject *, PyInt, PyObject *);
8182c45e945SBram Moolenaar static PyInt BufferAssSlice(PyObject *, PyInt, PyInt, PyObject *);
819071d4279SBram Moolenaar 
820071d4279SBram Moolenaar /* Line range type - Implementation functions
821071d4279SBram Moolenaar  * --------------------------------------
822071d4279SBram Moolenaar  */
823071d4279SBram Moolenaar 
824071d4279SBram Moolenaar #define RangeType_Check(obj) ((obj)->ob_type == &RangeType)
825071d4279SBram Moolenaar 
8262c45e945SBram Moolenaar static PyInt RangeAssItem(PyObject *, PyInt, PyObject *);
8272c45e945SBram Moolenaar static PyInt RangeAssSlice(PyObject *, PyInt, PyInt, PyObject *);
828071d4279SBram Moolenaar 
829071d4279SBram Moolenaar /* Current objects type - Implementation functions
830071d4279SBram Moolenaar  * -----------------------------------------------
831071d4279SBram Moolenaar  */
832071d4279SBram Moolenaar 
833071d4279SBram Moolenaar static PyObject *CurrentGetattr(PyObject *, char *);
834071d4279SBram Moolenaar static int CurrentSetattr(PyObject *, char *, PyObject *);
835071d4279SBram Moolenaar 
836071d4279SBram Moolenaar /* Common routines for buffers and line ranges
837071d4279SBram Moolenaar  * -------------------------------------------
838071d4279SBram Moolenaar  */
839170bf1aeSBram Moolenaar 
8402c45e945SBram Moolenaar     static PyInt
841e7cb9cf6SBram Moolenaar RBAssSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
842071d4279SBram Moolenaar {
843e7cb9cf6SBram Moolenaar     PyInt size;
844e7cb9cf6SBram Moolenaar     PyInt len_change;
845071d4279SBram Moolenaar 
846071d4279SBram Moolenaar     /* Self must be a valid buffer */
847071d4279SBram Moolenaar     if (CheckBuffer(self))
848071d4279SBram Moolenaar 	return -1;
849071d4279SBram Moolenaar 
850071d4279SBram Moolenaar     /* Sort out the slice range */
851071d4279SBram Moolenaar     size = end - start + 1;
852071d4279SBram Moolenaar 
853071d4279SBram Moolenaar     if (lo < 0)
854071d4279SBram Moolenaar 	lo = 0;
855071d4279SBram Moolenaar     else if (lo > size)
856071d4279SBram Moolenaar 	lo = size;
857071d4279SBram Moolenaar     if (hi < 0)
858071d4279SBram Moolenaar 	hi = 0;
859071d4279SBram Moolenaar     if (hi < lo)
860071d4279SBram Moolenaar 	hi = lo;
861071d4279SBram Moolenaar     else if (hi > size)
862071d4279SBram Moolenaar 	hi = size;
863071d4279SBram Moolenaar 
864ca8a4dfeSBram Moolenaar     if (SetBufferLineList(self->buf, lo + start, hi + start,
865ca8a4dfeSBram Moolenaar 						    val, &len_change) == FAIL)
866071d4279SBram Moolenaar 	return -1;
867071d4279SBram Moolenaar 
868071d4279SBram Moolenaar     if (new_end)
869071d4279SBram Moolenaar 	*new_end = end + len_change;
870071d4279SBram Moolenaar 
871071d4279SBram Moolenaar     return 0;
872071d4279SBram Moolenaar }
873071d4279SBram Moolenaar 
874071d4279SBram Moolenaar static PySequenceMethods BufferAsSeq = {
8752c45e945SBram Moolenaar     (PyInquiry)		BufferLength,	    /* sq_length,    len(x)   */
876071d4279SBram Moolenaar     (binaryfunc)	0, /* BufferConcat, */	     /* sq_concat,    x+y      */
8772c45e945SBram Moolenaar     (PyIntArgFunc)	0, /* BufferRepeat, */	     /* sq_repeat,    x*n      */
8782c45e945SBram Moolenaar     (PyIntArgFunc)	BufferItem,	    /* sq_item,      x[i]     */
8792c45e945SBram Moolenaar     (PyIntIntArgFunc)	BufferSlice,	    /* sq_slice,     x[i:j]   */
8802c45e945SBram Moolenaar     (PyIntObjArgProc)	BufferAssItem,	    /* sq_ass_item,  x[i]=v   */
8812c45e945SBram Moolenaar     (PyIntIntObjArgProc)	BufferAssSlice,     /* sq_ass_slice, x[i:j]=v */
882071d4279SBram Moolenaar };
883071d4279SBram Moolenaar 
884071d4279SBram Moolenaar static PyTypeObject BufferType = {
885071d4279SBram Moolenaar     PyObject_HEAD_INIT(0)
886071d4279SBram Moolenaar     0,
887071d4279SBram Moolenaar     "buffer",
888071d4279SBram Moolenaar     sizeof(BufferObject),
889071d4279SBram Moolenaar     0,
890071d4279SBram Moolenaar 
891071d4279SBram Moolenaar     (destructor)    BufferDestructor,	/* tp_dealloc,	refcount==0  */
892071d4279SBram Moolenaar     (printfunc)     0,			/* tp_print,	print x      */
893071d4279SBram Moolenaar     (getattrfunc)   BufferGetattr,	/* tp_getattr,	x.attr	     */
894071d4279SBram Moolenaar     (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
895071d4279SBram Moolenaar     (cmpfunc)	    0,			/* tp_compare,	x>y	     */
896071d4279SBram Moolenaar     (reprfunc)	    BufferRepr,		/* tp_repr,	`x`, print x */
897071d4279SBram Moolenaar 
898071d4279SBram Moolenaar     0,		    /* as number */
899071d4279SBram Moolenaar     &BufferAsSeq,   /* as sequence */
900071d4279SBram Moolenaar     0,		    /* as mapping */
901071d4279SBram Moolenaar 
902071d4279SBram Moolenaar     (hashfunc) 0,			/* tp_hash, dict(x) */
903071d4279SBram Moolenaar     (ternaryfunc) 0,			/* tp_call, x()     */
904071d4279SBram Moolenaar     (reprfunc) 0,			/* tp_str,  str(x)  */
905071d4279SBram Moolenaar };
906071d4279SBram Moolenaar 
907071d4279SBram Moolenaar /* Buffer object - Implementation
908071d4279SBram Moolenaar  */
909071d4279SBram Moolenaar 
910071d4279SBram Moolenaar     static PyObject *
911071d4279SBram Moolenaar BufferNew(buf_T *buf)
912071d4279SBram Moolenaar {
913071d4279SBram Moolenaar     /* We need to handle deletion of buffers underneath us.
914e344beadSBram Moolenaar      * If we add a "b_python_ref" field to the buf_T structure,
915071d4279SBram Moolenaar      * then we can get at it in buf_freeall() in vim. We then
916071d4279SBram Moolenaar      * need to create only ONE Python object per buffer - if
917071d4279SBram Moolenaar      * we try to create a second, just INCREF the existing one
918071d4279SBram Moolenaar      * and return it. The (single) Python object referring to
919e344beadSBram Moolenaar      * the buffer is stored in "b_python_ref".
920071d4279SBram Moolenaar      * Question: what to do on a buf_freeall(). We'll probably
921071d4279SBram Moolenaar      * have to either delete the Python object (DECREF it to
922071d4279SBram Moolenaar      * zero - a bad idea, as it leaves dangling refs!) or
923071d4279SBram Moolenaar      * set the buf_T * value to an invalid value (-1?), which
924071d4279SBram Moolenaar      * means we need checks in all access functions... Bah.
925071d4279SBram Moolenaar      */
926071d4279SBram Moolenaar 
927071d4279SBram Moolenaar     BufferObject *self;
928071d4279SBram Moolenaar 
929e344beadSBram Moolenaar     if (buf->b_python_ref != NULL)
930071d4279SBram Moolenaar     {
931e344beadSBram Moolenaar 	self = buf->b_python_ref;
932071d4279SBram Moolenaar 	Py_INCREF(self);
933071d4279SBram Moolenaar     }
934071d4279SBram Moolenaar     else
935071d4279SBram Moolenaar     {
936071d4279SBram Moolenaar 	self = PyObject_NEW(BufferObject, &BufferType);
937071d4279SBram Moolenaar 	if (self == NULL)
938071d4279SBram Moolenaar 	    return NULL;
939071d4279SBram Moolenaar 	self->buf = buf;
940e344beadSBram Moolenaar 	buf->b_python_ref = self;
941071d4279SBram Moolenaar     }
942071d4279SBram Moolenaar 
943071d4279SBram Moolenaar     return (PyObject *)(self);
944071d4279SBram Moolenaar }
945071d4279SBram Moolenaar 
946071d4279SBram Moolenaar     static void
947071d4279SBram Moolenaar BufferDestructor(PyObject *self)
948071d4279SBram Moolenaar {
949071d4279SBram Moolenaar     BufferObject *this = (BufferObject *)(self);
950071d4279SBram Moolenaar 
951071d4279SBram Moolenaar     if (this->buf && this->buf != INVALID_BUFFER_VALUE)
952e344beadSBram Moolenaar 	this->buf->b_python_ref = NULL;
953071d4279SBram Moolenaar 
954658ada69SBram Moolenaar     Py_DECREF(self);
955071d4279SBram Moolenaar }
956071d4279SBram Moolenaar 
957071d4279SBram Moolenaar     static PyObject *
958071d4279SBram Moolenaar BufferGetattr(PyObject *self, char *name)
959071d4279SBram Moolenaar {
960071d4279SBram Moolenaar     BufferObject *this = (BufferObject *)(self);
961071d4279SBram Moolenaar 
962071d4279SBram Moolenaar     if (CheckBuffer(this))
963071d4279SBram Moolenaar 	return NULL;
964071d4279SBram Moolenaar 
965071d4279SBram Moolenaar     if (strcmp(name, "name") == 0)
966071d4279SBram Moolenaar 	return Py_BuildValue("s", this->buf->b_ffname);
967071d4279SBram Moolenaar     else if (strcmp(name, "number") == 0)
968e7cb9cf6SBram Moolenaar 	return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum);
969071d4279SBram Moolenaar     else if (strcmp(name,"__members__") == 0)
970071d4279SBram Moolenaar 	return Py_BuildValue("[ss]", "name", "number");
971071d4279SBram Moolenaar     else
972071d4279SBram Moolenaar 	return Py_FindMethod(BufferMethods, self, name);
973071d4279SBram Moolenaar }
974071d4279SBram Moolenaar 
975071d4279SBram Moolenaar     static PyObject *
976071d4279SBram Moolenaar BufferRepr(PyObject *self)
977071d4279SBram Moolenaar {
978555b280fSBram Moolenaar     static char repr[100];
979071d4279SBram Moolenaar     BufferObject *this = (BufferObject *)(self);
980071d4279SBram Moolenaar 
981071d4279SBram Moolenaar     if (this->buf == INVALID_BUFFER_VALUE)
982071d4279SBram Moolenaar     {
983e7cb9cf6SBram Moolenaar 	vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self));
984071d4279SBram Moolenaar 	return PyString_FromString(repr);
985071d4279SBram Moolenaar     }
986071d4279SBram Moolenaar     else
987071d4279SBram Moolenaar     {
988071d4279SBram Moolenaar 	char *name = (char *)this->buf->b_fname;
989e7cb9cf6SBram Moolenaar 	PyInt len;
990071d4279SBram Moolenaar 
991071d4279SBram Moolenaar 	if (name == NULL)
992071d4279SBram Moolenaar 	    name = "";
993071d4279SBram Moolenaar 	len = strlen(name);
994071d4279SBram Moolenaar 
995071d4279SBram Moolenaar 	if (len > 35)
996071d4279SBram Moolenaar 	    name = name + (35 - len);
997071d4279SBram Moolenaar 
998555b280fSBram Moolenaar 	vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name);
999071d4279SBram Moolenaar 
1000071d4279SBram Moolenaar 	return PyString_FromString(repr);
1001071d4279SBram Moolenaar     }
1002071d4279SBram Moolenaar }
1003071d4279SBram Moolenaar 
1004071d4279SBram Moolenaar /******************/
1005071d4279SBram Moolenaar 
10062c45e945SBram Moolenaar     static PyInt
1007071d4279SBram Moolenaar BufferLength(PyObject *self)
1008071d4279SBram Moolenaar {
1009071d4279SBram Moolenaar     /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
1010071d4279SBram Moolenaar     if (CheckBuffer((BufferObject *)(self)))
1011071d4279SBram Moolenaar 	return -1; /* ??? */
1012071d4279SBram Moolenaar 
1013071d4279SBram Moolenaar     return (((BufferObject *)(self))->buf->b_ml.ml_line_count);
1014071d4279SBram Moolenaar }
1015071d4279SBram Moolenaar 
1016071d4279SBram Moolenaar     static PyObject *
10172c45e945SBram Moolenaar BufferItem(PyObject *self, PyInt n)
1018071d4279SBram Moolenaar {
1019071d4279SBram Moolenaar     return RBItem((BufferObject *)(self), n, 1,
1020071d4279SBram Moolenaar 		  (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
1021071d4279SBram Moolenaar }
1022071d4279SBram Moolenaar 
1023071d4279SBram Moolenaar     static PyObject *
10242c45e945SBram Moolenaar BufferSlice(PyObject *self, PyInt lo, PyInt hi)
1025071d4279SBram Moolenaar {
1026071d4279SBram Moolenaar     return RBSlice((BufferObject *)(self), lo, hi, 1,
1027071d4279SBram Moolenaar 		   (int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
1028071d4279SBram Moolenaar }
1029071d4279SBram Moolenaar 
10302c45e945SBram Moolenaar     static PyInt
10312c45e945SBram Moolenaar BufferAssItem(PyObject *self, PyInt n, PyObject *val)
1032071d4279SBram Moolenaar {
1033ca8a4dfeSBram Moolenaar     return RBAsItem((BufferObject *)(self), n, val, 1,
1034e7cb9cf6SBram Moolenaar 		     (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
1035071d4279SBram Moolenaar 		     NULL);
1036071d4279SBram Moolenaar }
1037071d4279SBram Moolenaar 
10382c45e945SBram Moolenaar     static PyInt
10392c45e945SBram Moolenaar BufferAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
1040071d4279SBram Moolenaar {
1041071d4279SBram Moolenaar     return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
1042e7cb9cf6SBram Moolenaar 		      (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
1043071d4279SBram Moolenaar 		      NULL);
1044071d4279SBram Moolenaar }
1045071d4279SBram Moolenaar 
1046071d4279SBram Moolenaar static PySequenceMethods RangeAsSeq = {
10472c45e945SBram Moolenaar     (PyInquiry)		RangeLength,	    /* sq_length,    len(x)   */
1048071d4279SBram Moolenaar     (binaryfunc)	0, /* RangeConcat, */	     /* sq_concat,    x+y      */
10492c45e945SBram Moolenaar     (PyIntArgFunc)	0, /* RangeRepeat, */	     /* sq_repeat,    x*n      */
10502c45e945SBram Moolenaar     (PyIntArgFunc)	RangeItem,	    /* sq_item,      x[i]     */
10512c45e945SBram Moolenaar     (PyIntIntArgFunc)	RangeSlice,	    /* sq_slice,     x[i:j]   */
10522c45e945SBram Moolenaar     (PyIntObjArgProc)	RangeAssItem,	    /* sq_ass_item,  x[i]=v   */
10532c45e945SBram Moolenaar     (PyIntIntObjArgProc)	RangeAssSlice,	    /* sq_ass_slice, x[i:j]=v */
1054071d4279SBram Moolenaar };
1055071d4279SBram Moolenaar 
1056071d4279SBram Moolenaar /* Line range object - Implementation
1057071d4279SBram Moolenaar  */
1058071d4279SBram Moolenaar 
1059071d4279SBram Moolenaar     static void
1060071d4279SBram Moolenaar RangeDestructor(PyObject *self)
1061071d4279SBram Moolenaar {
1062071d4279SBram Moolenaar     Py_DECREF(((RangeObject *)(self))->buf);
1063658ada69SBram Moolenaar     Py_DECREF(self);
1064071d4279SBram Moolenaar }
1065071d4279SBram Moolenaar 
1066071d4279SBram Moolenaar     static PyObject *
1067071d4279SBram Moolenaar RangeGetattr(PyObject *self, char *name)
1068071d4279SBram Moolenaar {
1069071d4279SBram Moolenaar     if (strcmp(name, "start") == 0)
1070e7cb9cf6SBram Moolenaar 	return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->start - 1);
1071071d4279SBram Moolenaar     else if (strcmp(name, "end") == 0)
1072e7cb9cf6SBram Moolenaar 	return Py_BuildValue(Py_ssize_t_fmt, ((RangeObject *)(self))->end - 1);
1073071d4279SBram Moolenaar     else
1074071d4279SBram Moolenaar 	return Py_FindMethod(RangeMethods, self, name);
1075071d4279SBram Moolenaar }
1076071d4279SBram Moolenaar 
1077071d4279SBram Moolenaar /****************/
1078071d4279SBram Moolenaar 
10792c45e945SBram Moolenaar     static PyInt
10802c45e945SBram Moolenaar RangeAssItem(PyObject *self, PyInt n, PyObject *val)
1081071d4279SBram Moolenaar {
1082ca8a4dfeSBram Moolenaar     return RBAsItem(((RangeObject *)(self))->buf, n, val,
1083071d4279SBram Moolenaar 		     ((RangeObject *)(self))->start,
1084071d4279SBram Moolenaar 		     ((RangeObject *)(self))->end,
1085071d4279SBram Moolenaar 		     &((RangeObject *)(self))->end);
1086071d4279SBram Moolenaar }
1087071d4279SBram Moolenaar 
10882c45e945SBram Moolenaar     static PyInt
10892c45e945SBram Moolenaar RangeAssSlice(PyObject *self, PyInt lo, PyInt hi, PyObject *val)
1090071d4279SBram Moolenaar {
1091071d4279SBram Moolenaar     return RBAssSlice(((RangeObject *)(self))->buf, lo, hi, val,
1092071d4279SBram Moolenaar 		      ((RangeObject *)(self))->start,
1093071d4279SBram Moolenaar 		      ((RangeObject *)(self))->end,
1094071d4279SBram Moolenaar 		      &((RangeObject *)(self))->end);
1095071d4279SBram Moolenaar }
1096071d4279SBram Moolenaar 
1097071d4279SBram Moolenaar /* Buffer list object - Definitions
1098071d4279SBram Moolenaar  */
1099071d4279SBram Moolenaar 
1100071d4279SBram Moolenaar typedef struct
1101071d4279SBram Moolenaar {
1102071d4279SBram Moolenaar     PyObject_HEAD
1103ca8a4dfeSBram Moolenaar } BufListObject;
1104071d4279SBram Moolenaar 
1105071d4279SBram Moolenaar static PySequenceMethods BufListAsSeq = {
11062c45e945SBram Moolenaar     (PyInquiry)		BufListLength,	    /* sq_length,    len(x)   */
1107071d4279SBram Moolenaar     (binaryfunc)	0,		    /* sq_concat,    x+y      */
11082c45e945SBram Moolenaar     (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
11092c45e945SBram Moolenaar     (PyIntArgFunc)	BufListItem,	    /* sq_item,      x[i]     */
11102c45e945SBram Moolenaar     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
11112c45e945SBram Moolenaar     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
11122c45e945SBram Moolenaar     (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
1113071d4279SBram Moolenaar };
1114071d4279SBram Moolenaar 
1115071d4279SBram Moolenaar static PyTypeObject BufListType = {
1116071d4279SBram Moolenaar     PyObject_HEAD_INIT(0)
1117071d4279SBram Moolenaar     0,
1118071d4279SBram Moolenaar     "buffer list",
1119071d4279SBram Moolenaar     sizeof(BufListObject),
1120071d4279SBram Moolenaar     0,
1121071d4279SBram Moolenaar 
1122071d4279SBram Moolenaar     (destructor)    0,			/* tp_dealloc,	refcount==0  */
1123071d4279SBram Moolenaar     (printfunc)     0,			/* tp_print,	print x      */
1124071d4279SBram Moolenaar     (getattrfunc)   0,			/* tp_getattr,	x.attr	     */
1125071d4279SBram Moolenaar     (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
1126071d4279SBram Moolenaar     (cmpfunc)	    0,			/* tp_compare,	x>y	     */
1127071d4279SBram Moolenaar     (reprfunc)	    0,			/* tp_repr,	`x`, print x */
1128071d4279SBram Moolenaar 
1129071d4279SBram Moolenaar     0,		    /* as number */
1130071d4279SBram Moolenaar     &BufListAsSeq,  /* as sequence */
1131071d4279SBram Moolenaar     0,		    /* as mapping */
1132071d4279SBram Moolenaar 
1133071d4279SBram Moolenaar     (hashfunc) 0,			/* tp_hash, dict(x) */
1134071d4279SBram Moolenaar     (ternaryfunc) 0,			/* tp_call, x()     */
1135071d4279SBram Moolenaar     (reprfunc) 0,			/* tp_str,  str(x)  */
1136071d4279SBram Moolenaar };
1137071d4279SBram Moolenaar 
1138071d4279SBram Moolenaar /* Window object - Definitions
1139071d4279SBram Moolenaar  */
1140071d4279SBram Moolenaar 
1141071d4279SBram Moolenaar static struct PyMethodDef WindowMethods[] = {
1142071d4279SBram Moolenaar     /* name,	    function,		calling,    documentation */
1143071d4279SBram Moolenaar     { NULL,	    NULL,		0,	    NULL }
1144071d4279SBram Moolenaar };
1145071d4279SBram Moolenaar 
1146071d4279SBram Moolenaar static PyTypeObject WindowType = {
1147071d4279SBram Moolenaar     PyObject_HEAD_INIT(0)
1148071d4279SBram Moolenaar     0,
1149071d4279SBram Moolenaar     "window",
1150071d4279SBram Moolenaar     sizeof(WindowObject),
1151071d4279SBram Moolenaar     0,
1152071d4279SBram Moolenaar 
1153071d4279SBram Moolenaar     (destructor)    WindowDestructor,	/* tp_dealloc,	refcount==0  */
1154071d4279SBram Moolenaar     (printfunc)     0,			/* tp_print,	print x      */
1155071d4279SBram Moolenaar     (getattrfunc)   WindowGetattr,	/* tp_getattr,	x.attr	     */
1156071d4279SBram Moolenaar     (setattrfunc)   WindowSetattr,	/* tp_setattr,	x.attr=v     */
1157071d4279SBram Moolenaar     (cmpfunc)	    0,			/* tp_compare,	x>y	     */
1158071d4279SBram Moolenaar     (reprfunc)	    WindowRepr,		/* tp_repr,	`x`, print x */
1159071d4279SBram Moolenaar 
1160071d4279SBram Moolenaar     0,		    /* as number */
1161071d4279SBram Moolenaar     0,		    /* as sequence */
1162071d4279SBram Moolenaar     0,		    /* as mapping */
1163071d4279SBram Moolenaar 
1164071d4279SBram Moolenaar     (hashfunc) 0,			/* tp_hash, dict(x) */
1165071d4279SBram Moolenaar     (ternaryfunc) 0,			/* tp_call, x()     */
1166071d4279SBram Moolenaar     (reprfunc) 0,			/* tp_str,  str(x)  */
1167071d4279SBram Moolenaar };
1168071d4279SBram Moolenaar 
1169071d4279SBram Moolenaar /* Window object - Implementation
1170071d4279SBram Moolenaar  */
1171071d4279SBram Moolenaar 
1172071d4279SBram Moolenaar     static PyObject *
1173071d4279SBram Moolenaar WindowNew(win_T *win)
1174071d4279SBram Moolenaar {
1175071d4279SBram Moolenaar     /* We need to handle deletion of windows underneath us.
1176e344beadSBram Moolenaar      * If we add a "w_python_ref" field to the win_T structure,
1177071d4279SBram Moolenaar      * then we can get at it in win_free() in vim. We then
1178071d4279SBram Moolenaar      * need to create only ONE Python object per window - if
1179071d4279SBram Moolenaar      * we try to create a second, just INCREF the existing one
1180071d4279SBram Moolenaar      * and return it. The (single) Python object referring to
1181e344beadSBram Moolenaar      * the window is stored in "w_python_ref".
1182071d4279SBram Moolenaar      * On a win_free() we set the Python object's win_T* field
1183071d4279SBram Moolenaar      * to an invalid value. We trap all uses of a window
1184071d4279SBram Moolenaar      * object, and reject them if the win_T* field is invalid.
1185071d4279SBram Moolenaar      */
1186071d4279SBram Moolenaar 
1187071d4279SBram Moolenaar     WindowObject *self;
1188071d4279SBram Moolenaar 
1189e344beadSBram Moolenaar     if (win->w_python_ref)
1190071d4279SBram Moolenaar     {
1191e344beadSBram Moolenaar 	self = win->w_python_ref;
1192071d4279SBram Moolenaar 	Py_INCREF(self);
1193071d4279SBram Moolenaar     }
1194071d4279SBram Moolenaar     else
1195071d4279SBram Moolenaar     {
1196071d4279SBram Moolenaar 	self = PyObject_NEW(WindowObject, &WindowType);
1197071d4279SBram Moolenaar 	if (self == NULL)
1198071d4279SBram Moolenaar 	    return NULL;
1199071d4279SBram Moolenaar 	self->win = win;
1200e344beadSBram Moolenaar 	win->w_python_ref = self;
1201071d4279SBram Moolenaar     }
1202071d4279SBram Moolenaar 
1203071d4279SBram Moolenaar     return (PyObject *)(self);
1204071d4279SBram Moolenaar }
1205071d4279SBram Moolenaar 
1206071d4279SBram Moolenaar     static void
1207071d4279SBram Moolenaar WindowDestructor(PyObject *self)
1208071d4279SBram Moolenaar {
1209071d4279SBram Moolenaar     WindowObject *this = (WindowObject *)(self);
1210071d4279SBram Moolenaar 
1211071d4279SBram Moolenaar     if (this->win && this->win != INVALID_WINDOW_VALUE)
1212e344beadSBram Moolenaar 	this->win->w_python_ref = NULL;
1213071d4279SBram Moolenaar 
1214658ada69SBram Moolenaar     Py_DECREF(self);
1215071d4279SBram Moolenaar }
1216071d4279SBram Moolenaar 
1217071d4279SBram Moolenaar     static PyObject *
1218071d4279SBram Moolenaar WindowGetattr(PyObject *self, char *name)
1219071d4279SBram Moolenaar {
1220071d4279SBram Moolenaar     WindowObject *this = (WindowObject *)(self);
1221071d4279SBram Moolenaar 
1222071d4279SBram Moolenaar     if (CheckWindow(this))
1223071d4279SBram Moolenaar 	return NULL;
1224071d4279SBram Moolenaar 
1225071d4279SBram Moolenaar     if (strcmp(name, "buffer") == 0)
1226071d4279SBram Moolenaar 	return (PyObject *)BufferNew(this->win->w_buffer);
1227071d4279SBram Moolenaar     else if (strcmp(name, "cursor") == 0)
1228071d4279SBram Moolenaar     {
1229071d4279SBram Moolenaar 	pos_T *pos = &this->win->w_cursor;
1230071d4279SBram Moolenaar 
1231071d4279SBram Moolenaar 	return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
1232071d4279SBram Moolenaar     }
1233071d4279SBram Moolenaar     else if (strcmp(name, "height") == 0)
1234071d4279SBram Moolenaar 	return Py_BuildValue("l", (long)(this->win->w_height));
1235071d4279SBram Moolenaar #ifdef FEAT_VERTSPLIT
1236071d4279SBram Moolenaar     else if (strcmp(name, "width") == 0)
1237071d4279SBram Moolenaar 	return Py_BuildValue("l", (long)(W_WIDTH(this->win)));
1238071d4279SBram Moolenaar #endif
1239071d4279SBram Moolenaar     else if (strcmp(name,"__members__") == 0)
1240071d4279SBram Moolenaar 	return Py_BuildValue("[sss]", "buffer", "cursor", "height");
1241071d4279SBram Moolenaar     else
1242071d4279SBram Moolenaar 	return Py_FindMethod(WindowMethods, self, name);
1243071d4279SBram Moolenaar }
1244071d4279SBram Moolenaar 
1245071d4279SBram Moolenaar /* Window list object - Definitions
1246071d4279SBram Moolenaar  */
1247071d4279SBram Moolenaar 
1248071d4279SBram Moolenaar typedef struct
1249071d4279SBram Moolenaar {
1250071d4279SBram Moolenaar     PyObject_HEAD
1251071d4279SBram Moolenaar }
1252071d4279SBram Moolenaar WinListObject;
1253071d4279SBram Moolenaar 
1254071d4279SBram Moolenaar static PySequenceMethods WinListAsSeq = {
12552c45e945SBram Moolenaar     (PyInquiry)		WinListLength,	    /* sq_length,    len(x)   */
1256071d4279SBram Moolenaar     (binaryfunc)	0,		    /* sq_concat,    x+y      */
12572c45e945SBram Moolenaar     (PyIntArgFunc)	0,		    /* sq_repeat,    x*n      */
12582c45e945SBram Moolenaar     (PyIntArgFunc)	WinListItem,	    /* sq_item,      x[i]     */
12592c45e945SBram Moolenaar     (PyIntIntArgFunc)	0,		    /* sq_slice,     x[i:j]   */
12602c45e945SBram Moolenaar     (PyIntObjArgProc)	0,		    /* sq_ass_item,  x[i]=v   */
12612c45e945SBram Moolenaar     (PyIntIntObjArgProc)	0,		    /* sq_ass_slice, x[i:j]=v */
1262071d4279SBram Moolenaar };
1263071d4279SBram Moolenaar 
1264071d4279SBram Moolenaar static PyTypeObject WinListType = {
1265071d4279SBram Moolenaar     PyObject_HEAD_INIT(0)
1266071d4279SBram Moolenaar     0,
1267071d4279SBram Moolenaar     "window list",
1268071d4279SBram Moolenaar     sizeof(WinListObject),
1269071d4279SBram Moolenaar     0,
1270071d4279SBram Moolenaar 
1271071d4279SBram Moolenaar     (destructor)    0,			/* tp_dealloc,	refcount==0  */
1272071d4279SBram Moolenaar     (printfunc)     0,			/* tp_print,	print x      */
1273071d4279SBram Moolenaar     (getattrfunc)   0,			/* tp_getattr,	x.attr	     */
1274071d4279SBram Moolenaar     (setattrfunc)   0,			/* tp_setattr,	x.attr=v     */
1275071d4279SBram Moolenaar     (cmpfunc)	    0,			/* tp_compare,	x>y	     */
1276071d4279SBram Moolenaar     (reprfunc)	    0,			/* tp_repr,	`x`, print x */
1277071d4279SBram Moolenaar 
1278071d4279SBram Moolenaar     0,		    /* as number */
1279071d4279SBram Moolenaar     &WinListAsSeq,  /* as sequence */
1280071d4279SBram Moolenaar     0,		    /* as mapping */
1281071d4279SBram Moolenaar 
1282071d4279SBram Moolenaar     (hashfunc) 0,			/* tp_hash, dict(x) */
1283071d4279SBram Moolenaar     (ternaryfunc) 0,			/* tp_call, x()     */
1284071d4279SBram Moolenaar     (reprfunc) 0,			/* tp_str,  str(x)  */
1285071d4279SBram Moolenaar };
1286071d4279SBram Moolenaar 
1287071d4279SBram Moolenaar /* Current items object - Definitions
1288071d4279SBram Moolenaar  */
1289071d4279SBram Moolenaar 
1290071d4279SBram Moolenaar typedef struct
1291071d4279SBram Moolenaar {
1292071d4279SBram Moolenaar     PyObject_HEAD
1293ca8a4dfeSBram Moolenaar } CurrentObject;
1294071d4279SBram Moolenaar 
1295071d4279SBram Moolenaar static PyTypeObject CurrentType = {
1296071d4279SBram Moolenaar     PyObject_HEAD_INIT(0)
1297071d4279SBram Moolenaar     0,
1298071d4279SBram Moolenaar     "current data",
1299071d4279SBram Moolenaar     sizeof(CurrentObject),
1300071d4279SBram Moolenaar     0,
1301071d4279SBram Moolenaar 
1302071d4279SBram Moolenaar     (destructor)    0,			/* tp_dealloc,	refcount==0  */
1303071d4279SBram Moolenaar     (printfunc)     0,			/* tp_print,	print x      */
1304071d4279SBram Moolenaar     (getattrfunc)   CurrentGetattr,	/* tp_getattr,	x.attr	     */
1305071d4279SBram Moolenaar     (setattrfunc)   CurrentSetattr,	/* tp_setattr,	x.attr=v     */
1306071d4279SBram Moolenaar     (cmpfunc)	    0,			/* tp_compare,	x>y	     */
1307071d4279SBram Moolenaar     (reprfunc)	    0,			/* tp_repr,	`x`, print x */
1308071d4279SBram Moolenaar 
1309071d4279SBram Moolenaar     0,		    /* as number */
1310071d4279SBram Moolenaar     0,		    /* as sequence */
1311071d4279SBram Moolenaar     0,		    /* as mapping */
1312071d4279SBram Moolenaar 
1313071d4279SBram Moolenaar     (hashfunc) 0,			/* tp_hash, dict(x) */
1314071d4279SBram Moolenaar     (ternaryfunc) 0,			/* tp_call, x()     */
1315071d4279SBram Moolenaar     (reprfunc) 0,			/* tp_str,  str(x)  */
1316071d4279SBram Moolenaar };
1317071d4279SBram Moolenaar 
1318071d4279SBram Moolenaar /* Current items object - Implementation
1319071d4279SBram Moolenaar  */
1320071d4279SBram Moolenaar     static PyObject *
13214bdbbf70SBram Moolenaar CurrentGetattr(PyObject *self UNUSED, char *name)
1322071d4279SBram Moolenaar {
1323071d4279SBram Moolenaar     if (strcmp(name, "buffer") == 0)
1324071d4279SBram Moolenaar 	return (PyObject *)BufferNew(curbuf);
1325071d4279SBram Moolenaar     else if (strcmp(name, "window") == 0)
1326071d4279SBram Moolenaar 	return (PyObject *)WindowNew(curwin);
1327071d4279SBram Moolenaar     else if (strcmp(name, "line") == 0)
1328e7cb9cf6SBram Moolenaar 	return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
1329071d4279SBram Moolenaar     else if (strcmp(name, "range") == 0)
1330071d4279SBram Moolenaar 	return RangeNew(curbuf, RangeStart, RangeEnd);
1331071d4279SBram Moolenaar     else if (strcmp(name,"__members__") == 0)
1332071d4279SBram Moolenaar 	return Py_BuildValue("[ssss]", "buffer", "window", "line", "range");
1333071d4279SBram Moolenaar     else
1334071d4279SBram Moolenaar     {
1335071d4279SBram Moolenaar 	PyErr_SetString(PyExc_AttributeError, name);
1336071d4279SBram Moolenaar 	return NULL;
1337071d4279SBram Moolenaar     }
1338071d4279SBram Moolenaar }
1339071d4279SBram Moolenaar 
1340071d4279SBram Moolenaar     static int
13414bdbbf70SBram Moolenaar CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
1342071d4279SBram Moolenaar {
1343071d4279SBram Moolenaar     if (strcmp(name, "line") == 0)
1344071d4279SBram Moolenaar     {
1345e7cb9cf6SBram Moolenaar 	if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
1346071d4279SBram Moolenaar 	    return -1;
1347071d4279SBram Moolenaar 
1348071d4279SBram Moolenaar 	return 0;
1349071d4279SBram Moolenaar     }
1350071d4279SBram Moolenaar     else
1351071d4279SBram Moolenaar     {
1352071d4279SBram Moolenaar 	PyErr_SetString(PyExc_AttributeError, name);
1353071d4279SBram Moolenaar 	return -1;
1354071d4279SBram Moolenaar     }
1355071d4279SBram Moolenaar }
1356071d4279SBram Moolenaar 
1357071d4279SBram Moolenaar /* External interface
1358071d4279SBram Moolenaar  */
1359071d4279SBram Moolenaar 
1360071d4279SBram Moolenaar     void
1361071d4279SBram Moolenaar python_buffer_free(buf_T *buf)
1362071d4279SBram Moolenaar {
1363e344beadSBram Moolenaar     if (buf->b_python_ref != NULL)
1364071d4279SBram Moolenaar     {
1365e344beadSBram Moolenaar 	BufferObject *bp = buf->b_python_ref;
1366071d4279SBram Moolenaar 	bp->buf = INVALID_BUFFER_VALUE;
1367e344beadSBram Moolenaar 	buf->b_python_ref = NULL;
1368071d4279SBram Moolenaar     }
1369071d4279SBram Moolenaar }
1370071d4279SBram Moolenaar 
1371071d4279SBram Moolenaar #if defined(FEAT_WINDOWS) || defined(PROTO)
1372071d4279SBram Moolenaar     void
1373071d4279SBram Moolenaar python_window_free(win_T *win)
1374071d4279SBram Moolenaar {
1375e344beadSBram Moolenaar     if (win->w_python_ref != NULL)
1376071d4279SBram Moolenaar     {
1377e344beadSBram Moolenaar 	WindowObject *wp = win->w_python_ref;
1378071d4279SBram Moolenaar 	wp->win = INVALID_WINDOW_VALUE;
1379e344beadSBram Moolenaar 	win->w_python_ref = NULL;
1380071d4279SBram Moolenaar     }
1381071d4279SBram Moolenaar }
1382071d4279SBram Moolenaar #endif
1383071d4279SBram Moolenaar 
1384071d4279SBram Moolenaar static BufListObject TheBufferList =
1385071d4279SBram Moolenaar {
1386071d4279SBram Moolenaar     PyObject_HEAD_INIT(&BufListType)
1387071d4279SBram Moolenaar };
1388071d4279SBram Moolenaar 
1389071d4279SBram Moolenaar static WinListObject TheWindowList =
1390071d4279SBram Moolenaar {
1391071d4279SBram Moolenaar     PyObject_HEAD_INIT(&WinListType)
1392071d4279SBram Moolenaar };
1393071d4279SBram Moolenaar 
1394071d4279SBram Moolenaar static CurrentObject TheCurrent =
1395071d4279SBram Moolenaar {
1396071d4279SBram Moolenaar     PyObject_HEAD_INIT(&CurrentType)
1397071d4279SBram Moolenaar };
1398071d4279SBram Moolenaar 
1399071d4279SBram Moolenaar     static int
1400071d4279SBram Moolenaar PythonMod_Init(void)
1401071d4279SBram Moolenaar {
1402071d4279SBram Moolenaar     PyObject *mod;
1403071d4279SBram Moolenaar     PyObject *dict;
14049774ecc8SBram Moolenaar     /* The special value is removed from sys.path in Python_Init(). */
14059774ecc8SBram Moolenaar     static char *(argv[2]) = {"/must>not&exist/foo", NULL};
1406071d4279SBram Moolenaar 
1407071d4279SBram Moolenaar     /* Fixups... */
140821377c8dSBram Moolenaar     PyType_Ready(&BufferType);
140921377c8dSBram Moolenaar     PyType_Ready(&RangeType);
141021377c8dSBram Moolenaar     PyType_Ready(&WindowType);
141121377c8dSBram Moolenaar     PyType_Ready(&BufListType);
141221377c8dSBram Moolenaar     PyType_Ready(&WinListType);
141321377c8dSBram Moolenaar     PyType_Ready(&CurrentType);
1414071d4279SBram Moolenaar 
1415071d4279SBram Moolenaar     /* Set sys.argv[] to avoid a crash in warn(). */
1416071d4279SBram Moolenaar     PySys_SetArgv(1, argv);
1417071d4279SBram Moolenaar 
1418e7cb9cf6SBram Moolenaar     mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION);
1419071d4279SBram Moolenaar     dict = PyModule_GetDict(mod);
1420071d4279SBram Moolenaar 
1421071d4279SBram Moolenaar     VimError = Py_BuildValue("s", "vim.error");
1422071d4279SBram Moolenaar 
1423071d4279SBram Moolenaar     PyDict_SetItemString(dict, "error", VimError);
14247df2d662SBram Moolenaar     PyDict_SetItemString(dict, "buffers", (PyObject *)(void *)&TheBufferList);
14257df2d662SBram Moolenaar     PyDict_SetItemString(dict, "current", (PyObject *)(void *)&TheCurrent);
14267df2d662SBram Moolenaar     PyDict_SetItemString(dict, "windows", (PyObject *)(void *)&TheWindowList);
1427071d4279SBram Moolenaar 
1428071d4279SBram Moolenaar     if (PyErr_Occurred())
1429071d4279SBram Moolenaar 	return -1;
1430071d4279SBram Moolenaar 
1431071d4279SBram Moolenaar     return 0;
1432071d4279SBram Moolenaar }
1433071d4279SBram Moolenaar 
1434071d4279SBram Moolenaar /*************************************************************************
1435071d4279SBram Moolenaar  * 4. Utility functions for handling the interface between Vim and Python.
1436071d4279SBram Moolenaar  */
1437071d4279SBram Moolenaar 
1438071d4279SBram Moolenaar /* Replace a range of lines in the specified buffer. The line numbers are in
1439071d4279SBram Moolenaar  * Vim format (1-based). The range is from lo up to, but not including, hi.
1440071d4279SBram Moolenaar  * The replacement lines are given as a Python list of string objects. The
1441071d4279SBram Moolenaar  * list is checked for validity and correct format. Errors are returned as a
1442071d4279SBram Moolenaar  * value of FAIL.  The return value is OK on success.
1443071d4279SBram Moolenaar  * If OK is returned and len_change is not NULL, *len_change
1444071d4279SBram Moolenaar  * is set to the change in the buffer length.
1445071d4279SBram Moolenaar  */
1446071d4279SBram Moolenaar     static int
1447e7cb9cf6SBram Moolenaar SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
1448071d4279SBram Moolenaar {
1449071d4279SBram Moolenaar     /* First of all, we check the thpe of the supplied Python object.
1450071d4279SBram Moolenaar      * There are three cases:
1451071d4279SBram Moolenaar      *	  1. NULL, or None - this is a deletion.
1452071d4279SBram Moolenaar      *	  2. A list	   - this is a replacement.
1453071d4279SBram Moolenaar      *	  3. Anything else - this is an error.
1454071d4279SBram Moolenaar      */
1455071d4279SBram Moolenaar     if (list == Py_None || list == NULL)
1456071d4279SBram Moolenaar     {
14572c45e945SBram Moolenaar 	PyInt	i;
1458e7cb9cf6SBram Moolenaar 	PyInt	n = (int)(hi - lo);
1459071d4279SBram Moolenaar 	buf_T	*savebuf = curbuf;
1460071d4279SBram Moolenaar 
1461071d4279SBram Moolenaar 	PyErr_Clear();
1462071d4279SBram Moolenaar 	curbuf = buf;
1463071d4279SBram Moolenaar 
1464071d4279SBram Moolenaar 	if (u_savedel((linenr_T)lo, (long)n) == FAIL)
1465071d4279SBram Moolenaar 	    PyErr_SetVim(_("cannot save undo information"));
1466071d4279SBram Moolenaar 	else
1467071d4279SBram Moolenaar 	{
1468071d4279SBram Moolenaar 	    for (i = 0; i < n; ++i)
1469071d4279SBram Moolenaar 	    {
1470071d4279SBram Moolenaar 		if (ml_delete((linenr_T)lo, FALSE) == FAIL)
1471071d4279SBram Moolenaar 		{
1472071d4279SBram Moolenaar 		    PyErr_SetVim(_("cannot delete line"));
1473071d4279SBram Moolenaar 		    break;
1474071d4279SBram Moolenaar 		}
1475071d4279SBram Moolenaar 	    }
1476071d4279SBram Moolenaar 	    if (buf == curwin->w_buffer)
1477e7cb9cf6SBram Moolenaar 		py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
1478cdcaa589SBram Moolenaar 	    deleted_lines_mark((linenr_T)lo, (long)i);
1479071d4279SBram Moolenaar 	}
1480071d4279SBram Moolenaar 
1481071d4279SBram Moolenaar 	curbuf = savebuf;
1482071d4279SBram Moolenaar 
1483071d4279SBram Moolenaar 	if (PyErr_Occurred() || VimErrorCheck())
1484071d4279SBram Moolenaar 	    return FAIL;
1485071d4279SBram Moolenaar 
1486071d4279SBram Moolenaar 	if (len_change)
1487071d4279SBram Moolenaar 	    *len_change = -n;
1488071d4279SBram Moolenaar 
1489071d4279SBram Moolenaar 	return OK;
1490071d4279SBram Moolenaar     }
1491071d4279SBram Moolenaar     else if (PyList_Check(list))
1492071d4279SBram Moolenaar     {
14932c45e945SBram Moolenaar 	PyInt	i;
14942c45e945SBram Moolenaar 	PyInt	new_len = PyList_Size(list);
14952c45e945SBram Moolenaar 	PyInt	old_len = hi - lo;
1496e7cb9cf6SBram Moolenaar 	PyInt	extra = 0;	/* lines added to text, can be negative */
1497071d4279SBram Moolenaar 	char	**array;
1498071d4279SBram Moolenaar 	buf_T	*savebuf;
1499071d4279SBram Moolenaar 
1500071d4279SBram Moolenaar 	if (new_len == 0)	/* avoid allocating zero bytes */
1501071d4279SBram Moolenaar 	    array = NULL;
1502071d4279SBram Moolenaar 	else
1503071d4279SBram Moolenaar 	{
1504071d4279SBram Moolenaar 	    array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
1505071d4279SBram Moolenaar 	    if (array == NULL)
1506071d4279SBram Moolenaar 	    {
1507071d4279SBram Moolenaar 		PyErr_NoMemory();
1508071d4279SBram Moolenaar 		return FAIL;
1509071d4279SBram Moolenaar 	    }
1510071d4279SBram Moolenaar 	}
1511071d4279SBram Moolenaar 
1512071d4279SBram Moolenaar 	for (i = 0; i < new_len; ++i)
1513071d4279SBram Moolenaar 	{
1514071d4279SBram Moolenaar 	    PyObject *line = PyList_GetItem(list, i);
1515071d4279SBram Moolenaar 
1516071d4279SBram Moolenaar 	    array[i] = StringToLine(line);
1517071d4279SBram Moolenaar 	    if (array[i] == NULL)
1518071d4279SBram Moolenaar 	    {
1519071d4279SBram Moolenaar 		while (i)
1520071d4279SBram Moolenaar 		    vim_free(array[--i]);
1521071d4279SBram Moolenaar 		vim_free(array);
1522071d4279SBram Moolenaar 		return FAIL;
1523071d4279SBram Moolenaar 	    }
1524071d4279SBram Moolenaar 	}
1525071d4279SBram Moolenaar 
1526071d4279SBram Moolenaar 	savebuf = curbuf;
1527071d4279SBram Moolenaar 
1528071d4279SBram Moolenaar 	PyErr_Clear();
1529071d4279SBram Moolenaar 	curbuf = buf;
1530071d4279SBram Moolenaar 
1531071d4279SBram Moolenaar 	if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
1532071d4279SBram Moolenaar 	    PyErr_SetVim(_("cannot save undo information"));
1533071d4279SBram Moolenaar 
1534071d4279SBram Moolenaar 	/* If the size of the range is reducing (ie, new_len < old_len) we
1535071d4279SBram Moolenaar 	 * need to delete some old_len. We do this at the start, by
1536071d4279SBram Moolenaar 	 * repeatedly deleting line "lo".
1537071d4279SBram Moolenaar 	 */
1538071d4279SBram Moolenaar 	if (!PyErr_Occurred())
1539071d4279SBram Moolenaar 	{
1540071d4279SBram Moolenaar 	    for (i = 0; i < old_len - new_len; ++i)
1541071d4279SBram Moolenaar 		if (ml_delete((linenr_T)lo, FALSE) == FAIL)
1542071d4279SBram Moolenaar 		{
1543071d4279SBram Moolenaar 		    PyErr_SetVim(_("cannot delete line"));
1544071d4279SBram Moolenaar 		    break;
1545071d4279SBram Moolenaar 		}
1546071d4279SBram Moolenaar 	    extra -= i;
1547071d4279SBram Moolenaar 	}
1548071d4279SBram Moolenaar 
1549071d4279SBram Moolenaar 	/* For as long as possible, replace the existing old_len with the
1550071d4279SBram Moolenaar 	 * new old_len. This is a more efficient operation, as it requires
1551071d4279SBram Moolenaar 	 * less memory allocation and freeing.
1552071d4279SBram Moolenaar 	 */
1553071d4279SBram Moolenaar 	if (!PyErr_Occurred())
1554071d4279SBram Moolenaar 	{
1555071d4279SBram Moolenaar 	    for (i = 0; i < old_len && i < new_len; ++i)
1556071d4279SBram Moolenaar 		if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
1557071d4279SBram Moolenaar 								      == FAIL)
1558071d4279SBram Moolenaar 		{
1559071d4279SBram Moolenaar 		    PyErr_SetVim(_("cannot replace line"));
1560071d4279SBram Moolenaar 		    break;
1561071d4279SBram Moolenaar 		}
1562071d4279SBram Moolenaar 	}
1563071d4279SBram Moolenaar 	else
1564071d4279SBram Moolenaar 	    i = 0;
1565071d4279SBram Moolenaar 
1566071d4279SBram Moolenaar 	/* Now we may need to insert the remaining new old_len. If we do, we
1567071d4279SBram Moolenaar 	 * must free the strings as we finish with them (we can't pass the
1568071d4279SBram Moolenaar 	 * responsibility to vim in this case).
1569071d4279SBram Moolenaar 	 */
1570071d4279SBram Moolenaar 	if (!PyErr_Occurred())
1571071d4279SBram Moolenaar 	{
1572071d4279SBram Moolenaar 	    while (i < new_len)
1573071d4279SBram Moolenaar 	    {
1574071d4279SBram Moolenaar 		if (ml_append((linenr_T)(lo + i - 1),
1575071d4279SBram Moolenaar 					(char_u *)array[i], 0, FALSE) == FAIL)
1576071d4279SBram Moolenaar 		{
1577071d4279SBram Moolenaar 		    PyErr_SetVim(_("cannot insert line"));
1578071d4279SBram Moolenaar 		    break;
1579071d4279SBram Moolenaar 		}
1580071d4279SBram Moolenaar 		vim_free(array[i]);
1581071d4279SBram Moolenaar 		++i;
1582071d4279SBram Moolenaar 		++extra;
1583071d4279SBram Moolenaar 	    }
1584071d4279SBram Moolenaar 	}
1585071d4279SBram Moolenaar 
1586071d4279SBram Moolenaar 	/* Free any left-over old_len, as a result of an error */
1587071d4279SBram Moolenaar 	while (i < new_len)
1588071d4279SBram Moolenaar 	{
1589071d4279SBram Moolenaar 	    vim_free(array[i]);
1590071d4279SBram Moolenaar 	    ++i;
1591071d4279SBram Moolenaar 	}
1592071d4279SBram Moolenaar 
1593071d4279SBram Moolenaar 	/* Free the array of old_len. All of its contents have now
1594071d4279SBram Moolenaar 	 * been dealt with (either freed, or the responsibility passed
1595071d4279SBram Moolenaar 	 * to vim.
1596071d4279SBram Moolenaar 	 */
1597071d4279SBram Moolenaar 	vim_free(array);
1598071d4279SBram Moolenaar 
1599071d4279SBram Moolenaar 	/* Adjust marks. Invalidate any which lie in the
1600071d4279SBram Moolenaar 	 * changed range, and move any in the remainder of the buffer.
1601071d4279SBram Moolenaar 	 */
1602071d4279SBram Moolenaar 	mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
1603071d4279SBram Moolenaar 						  (long)MAXLNUM, (long)extra);
1604071d4279SBram Moolenaar 	changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
1605071d4279SBram Moolenaar 
1606071d4279SBram Moolenaar 	if (buf == curwin->w_buffer)
1607e7cb9cf6SBram Moolenaar 	    py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
1608071d4279SBram Moolenaar 
1609071d4279SBram Moolenaar 	curbuf = savebuf;
1610071d4279SBram Moolenaar 
1611071d4279SBram Moolenaar 	if (PyErr_Occurred() || VimErrorCheck())
1612071d4279SBram Moolenaar 	    return FAIL;
1613071d4279SBram Moolenaar 
1614071d4279SBram Moolenaar 	if (len_change)
1615071d4279SBram Moolenaar 	    *len_change = new_len - old_len;
1616071d4279SBram Moolenaar 
1617071d4279SBram Moolenaar 	return OK;
1618071d4279SBram Moolenaar     }
1619071d4279SBram Moolenaar     else
1620071d4279SBram Moolenaar     {
1621071d4279SBram Moolenaar 	PyErr_BadArgument();
1622071d4279SBram Moolenaar 	return FAIL;
1623071d4279SBram Moolenaar     }
1624071d4279SBram Moolenaar }
1625071d4279SBram Moolenaar 
1626071d4279SBram Moolenaar /* Convert a Vim line into a Python string.
1627071d4279SBram Moolenaar  * All internal newlines are replaced by null characters.
1628071d4279SBram Moolenaar  *
1629071d4279SBram Moolenaar  * On errors, the Python exception data is set, and NULL is returned.
1630071d4279SBram Moolenaar  */
1631071d4279SBram Moolenaar     static PyObject *
1632071d4279SBram Moolenaar LineToString(const char *str)
1633071d4279SBram Moolenaar {
1634071d4279SBram Moolenaar     PyObject *result;
16352c45e945SBram Moolenaar     PyInt len = strlen(str);
1636071d4279SBram Moolenaar     char *p;
1637071d4279SBram Moolenaar 
1638071d4279SBram Moolenaar     /* Allocate an Python string object, with uninitialised contents. We
1639071d4279SBram Moolenaar      * must do it this way, so that we can modify the string in place
1640071d4279SBram Moolenaar      * later. See the Python source, Objects/stringobject.c for details.
1641071d4279SBram Moolenaar      */
1642071d4279SBram Moolenaar     result = PyString_FromStringAndSize(NULL, len);
1643071d4279SBram Moolenaar     if (result == NULL)
1644071d4279SBram Moolenaar 	return NULL;
1645071d4279SBram Moolenaar 
1646071d4279SBram Moolenaar     p = PyString_AsString(result);
1647071d4279SBram Moolenaar 
1648071d4279SBram Moolenaar     while (*str)
1649071d4279SBram Moolenaar     {
1650071d4279SBram Moolenaar 	if (*str == '\n')
1651071d4279SBram Moolenaar 	    *p = '\0';
1652071d4279SBram Moolenaar 	else
1653071d4279SBram Moolenaar 	    *p = *str;
1654071d4279SBram Moolenaar 
1655071d4279SBram Moolenaar 	++p;
1656071d4279SBram Moolenaar 	++str;
1657071d4279SBram Moolenaar     }
1658071d4279SBram Moolenaar 
1659071d4279SBram Moolenaar     return result;
1660071d4279SBram Moolenaar }
1661071d4279SBram Moolenaar 
1662071d4279SBram Moolenaar 
1663071d4279SBram Moolenaar /* Don't generate a prototype for the next function, it generates an error on
1664071d4279SBram Moolenaar  * newer Python versions. */
1665071d4279SBram Moolenaar #if PYTHON_API_VERSION < 1007 /* Python 1.4 */ && !defined(PROTO)
1666071d4279SBram Moolenaar 
1667071d4279SBram Moolenaar     char *
1668071d4279SBram Moolenaar Py_GetProgramName(void)
1669071d4279SBram Moolenaar {
1670071d4279SBram Moolenaar     return "vim";
1671071d4279SBram Moolenaar }
1672071d4279SBram Moolenaar #endif /* Python 1.4 */
1673170bf1aeSBram Moolenaar 
1674170bf1aeSBram Moolenaar     static void
1675170bf1aeSBram Moolenaar init_structs(void)
1676170bf1aeSBram Moolenaar {
1677170bf1aeSBram Moolenaar     vim_memset(&OutputType, 0, sizeof(OutputType));
1678170bf1aeSBram Moolenaar     OutputType.tp_name = "message";
1679170bf1aeSBram Moolenaar     OutputType.tp_basicsize = sizeof(OutputObject);
1680170bf1aeSBram Moolenaar     OutputType.tp_getattr = OutputGetattr;
1681170bf1aeSBram Moolenaar     OutputType.tp_setattr = OutputSetattr;
1682ca8a4dfeSBram Moolenaar 
1683ca8a4dfeSBram Moolenaar     vim_memset(&RangeType, 0, sizeof(RangeType));
1684ca8a4dfeSBram Moolenaar     RangeType.tp_name = "range";
1685ca8a4dfeSBram Moolenaar     RangeType.tp_basicsize = sizeof(RangeObject);
1686ca8a4dfeSBram Moolenaar     RangeType.tp_dealloc = RangeDestructor;
1687ca8a4dfeSBram Moolenaar     RangeType.tp_getattr = RangeGetattr;
1688ca8a4dfeSBram Moolenaar     RangeType.tp_repr = RangeRepr;
1689ca8a4dfeSBram Moolenaar     RangeType.tp_as_sequence = &RangeAsSeq;
1690170bf1aeSBram Moolenaar }
1691