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