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