blob: e48740c275a99d0c2ac6e81f45a197f0c48bb1bb [file] [log] [blame]
Bram Moolenaardb913952012-06-29 12:54:53 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020010 * Python extensions by Paul Moore, David Leonard, Roland Puntaier, Nikolay
11 * Pavlov.
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020012 *
13 * Common code for if_python.c and if_python3.c.
14 */
15
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020016#if PY_VERSION_HEX < 0x02050000
17typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
18#endif
19
Bram Moolenaar91805fc2011-06-26 04:01:44 +020020#ifdef FEAT_MBYTE
Bram Moolenaar808c2bc2013-06-23 13:11:18 +020021# define ENC_OPT ((char *)p_enc)
Bram Moolenaar91805fc2011-06-26 04:01:44 +020022#else
23# define ENC_OPT "latin1"
24#endif
Bram Moolenaard620aa92013-05-17 16:40:06 +020025#define DOPY_FUNC "_vim_pydo"
Bram Moolenaar91805fc2011-06-26 04:01:44 +020026
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020027static const char *vim_special_path = "_vim_path_";
28
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020029#define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020030#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020031#define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
Bram Moolenaarc476e522013-06-23 13:46:40 +020032#define PyErr_FORMAT(exc, str, tail) PyErr_Format(exc, _(str), tail)
33#define PyErr_VIM_FORMAT(str, tail) PyErr_FORMAT(VimError, str, tail)
34
35#define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \
36 ? "(NULL)" \
37 : obj->ob_type->tp_name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020038
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020039#define RAISE_NO_EMPTY_KEYS PyErr_SET_STRING(PyExc_ValueError, \
40 "empty keys are not allowed")
Bram Moolenaarc476e522013-06-23 13:46:40 +020041#define RAISE_LOCKED(type) PyErr_SET_VIM(_(type " is locked"))
42#define RAISE_LOCKED_DICTIONARY RAISE_LOCKED("dictionary")
43#define RAISE_LOCKED_LIST RAISE_LOCKED("list")
44#define RAISE_UNDO_FAIL PyErr_SET_VIM("cannot save undo information")
45#define RAISE_LINE_FAIL(act) PyErr_SET_VIM("cannot " act " line")
46#define RAISE_KEY_ADD_FAIL(key) \
47 PyErr_VIM_FORMAT("failed to add key '%s' to dictionary", key)
48#define RAISE_INVALID_INDEX_TYPE(idx) \
49 PyErr_FORMAT(PyExc_TypeError, "index must be int or slice, not %s", \
50 Py_TYPE_NAME(idx));
Bram Moolenaar35eacd72013-05-30 22:06:33 +020051
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020052#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
53#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020054#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020055
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020056typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020057typedef void (*runner)(const char *, void *
58#ifdef PY_CAN_RECURSE
59 , PyGILState_STATE *
60#endif
61 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020062
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020063static int ConvertFromPyObject(PyObject *, typval_T *);
64static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +020065static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020066static PyObject *WindowNew(win_T *, tabpage_T *);
67static PyObject *BufferNew (buf_T *);
68static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020069
70static PyInt RangeStart;
71static PyInt RangeEnd;
72
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020073static PyObject *globals;
74
Bram Moolenaarf4258302013-06-02 18:20:17 +020075static PyObject *py_chdir;
76static PyObject *py_fchdir;
77static PyObject *py_getcwd;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020078static PyObject *vim_module;
79static PyObject *vim_special_path_object;
Bram Moolenaarf4258302013-06-02 18:20:17 +020080
Bram Moolenaar81c40c52013-06-12 14:41:04 +020081static PyObject *py_find_module;
82static PyObject *py_load_module;
83
84static PyObject *VimError;
85
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020086/*
87 * obtain a lock on the Vim data structures
88 */
89 static void
90Python_Lock_Vim(void)
91{
92}
93
94/*
95 * release a lock on the Vim data structures
96 */
97 static void
98Python_Release_Vim(void)
99{
100}
101
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200102/*
103 * The "todecref" argument holds a pointer to PyObject * that must be
104 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
105 * was needed to generate returned value is object.
106 *
107 * Use Py_XDECREF to decrement reference count.
108 */
109 static char_u *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200110StringToChars(PyObject *obj, PyObject **todecref)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200111{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200112 char_u *str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200113
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200114 if (PyBytes_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200115 {
116
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200117 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1
118 || str == NULL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200119 return NULL;
120
121 *todecref = NULL;
122 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200123 else if (PyUnicode_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200124 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200125 PyObject *bytes;
126
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200127 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200128 return NULL;
129
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200130 if(PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1
131 || str == NULL)
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200132 {
133 Py_DECREF(bytes);
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200134 return NULL;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200135 }
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200136
137 *todecref = bytes;
138 }
139 else
140 {
Bram Moolenaarc476e522013-06-23 13:46:40 +0200141 PyErr_FORMAT(PyExc_TypeError,
142#if PY_MAJOR_VERSION < 3
143 "expected str() or unicode() instance, but got %s"
144#else
145 "expected bytes() or str() instance, but got %s"
146#endif
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200147 , Py_TYPE_NAME(obj));
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200148 return NULL;
149 }
150
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200151 return (char_u *) str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200152}
153
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200154#define NUMBER_LONG 1
155#define NUMBER_INT 2
156#define NUMBER_NATURAL 4
157#define NUMBER_UNSIGNED 8
158
159 static int
160NumberToLong(PyObject *obj, long *result, int flags)
161{
162#if PY_MAJOR_VERSION < 3
163 if (PyInt_Check(obj))
164 {
165 *result = PyInt_AsLong(obj);
166 if (PyErr_Occurred())
167 return -1;
168 }
169 else
170#endif
171 if (PyLong_Check(obj))
172 {
173 *result = PyLong_AsLong(obj);
174 if (PyErr_Occurred())
175 return -1;
176 }
177 else if (PyNumber_Check(obj))
178 {
179 PyObject *num;
180
181 if (!(num = PyNumber_Long(obj)))
182 return -1;
183
184 *result = PyLong_AsLong(num);
185
186 Py_DECREF(num);
187
188 if (PyErr_Occurred())
189 return -1;
190 }
191 else
192 {
193 PyErr_FORMAT(PyExc_TypeError,
194#if PY_MAJOR_VERSION < 3
195 "expected int(), long() or something supporting "
196 "coercing to long(), but got %s"
197#else
198 "expected int() or something supporting coercing to int(), "
199 "but got %s"
200#endif
201 , Py_TYPE_NAME(obj));
202 return -1;
203 }
204
205 if (flags & NUMBER_INT)
206 {
207 if (*result > INT_MAX)
208 {
209 PyErr_SET_STRING(PyExc_OverflowError,
210 "value is too large to fit into C int type");
211 return -1;
212 }
213 else if (*result < INT_MIN)
214 {
215 PyErr_SET_STRING(PyExc_OverflowError,
216 "value is too small to fit into C int type");
217 return -1;
218 }
219 }
220
221 if (flags & NUMBER_NATURAL)
222 {
223 if (*result <= 0)
224 {
225 PyErr_SET_STRING(PyExc_ValueError,
226 "number must be greater then zero");
227 return -1;
228 }
229 }
230 else if (flags & NUMBER_UNSIGNED)
231 {
232 if (*result < 0)
233 {
234 PyErr_SET_STRING(PyExc_ValueError,
235 "number must be greater or equal to zero");
236 return -1;
237 }
238 }
239
240 return 0;
241}
242
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200243 static int
244add_string(PyObject *list, char *s)
245{
246 PyObject *string;
247
248 if (!(string = PyString_FromString(s)))
249 return -1;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200250
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200251 if (PyList_Append(list, string))
252 {
253 Py_DECREF(string);
254 return -1;
255 }
256
257 Py_DECREF(string);
258 return 0;
259}
260
261 static PyObject *
262ObjectDir(PyObject *self, char **attributes)
263{
264 PyMethodDef *method;
265 char **attr;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200266 PyObject *ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200267
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200268 if (!(ret = PyList_New(0)))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200269 return NULL;
270
271 if (self)
272 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200273 if (add_string(ret, (char *) method->ml_name))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200274 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200275 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200276 return NULL;
277 }
278
279 for (attr = attributes ; *attr ; ++attr)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200280 if (add_string(ret, *attr))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200281 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200282 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200283 return NULL;
284 }
285
286#if PY_MAJOR_VERSION < 3
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200287 if (add_string(ret, "__members__"))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200288 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200289 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200290 return NULL;
291 }
292#endif
293
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200294 return ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200295}
296
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200297/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200298 */
299
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200300/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200301typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200302
303static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200304
305typedef struct
306{
307 PyObject_HEAD
308 long softspace;
309 long error;
310} OutputObject;
311
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200312static char *OutputAttrs[] = {
313 "softspace",
314 NULL
315};
316
317 static PyObject *
318OutputDir(PyObject *self)
319{
320 return ObjectDir(self, OutputAttrs);
321}
322
Bram Moolenaar77045652012-09-21 13:46:06 +0200323 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200324OutputSetattr(OutputObject *self, char *name, PyObject *valObject)
Bram Moolenaar77045652012-09-21 13:46:06 +0200325{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200326 if (valObject == NULL)
Bram Moolenaar77045652012-09-21 13:46:06 +0200327 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200328 PyErr_SET_STRING(PyExc_AttributeError,
329 "can't delete OutputObject attributes");
Bram Moolenaar77045652012-09-21 13:46:06 +0200330 return -1;
331 }
332
333 if (strcmp(name, "softspace") == 0)
334 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200335 if (NumberToLong(valObject, &(self->softspace), NUMBER_UNSIGNED))
Bram Moolenaar77045652012-09-21 13:46:06 +0200336 return -1;
Bram Moolenaar77045652012-09-21 13:46:06 +0200337 return 0;
338 }
339
Bram Moolenaarc476e522013-06-23 13:46:40 +0200340 PyErr_FORMAT(PyExc_AttributeError, "invalid attribute: %s", name);
Bram Moolenaar77045652012-09-21 13:46:06 +0200341 return -1;
342}
343
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200344/* Buffer IO, we write one whole line at a time. */
345static garray_T io_ga = {0, 0, 1, 80, NULL};
346static writefn old_fn = NULL;
347
348 static void
349PythonIO_Flush(void)
350{
351 if (old_fn != NULL && io_ga.ga_len > 0)
352 {
353 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
354 old_fn((char_u *)io_ga.ga_data);
355 }
356 io_ga.ga_len = 0;
357}
358
359 static void
360writer(writefn fn, char_u *str, PyInt n)
361{
362 char_u *ptr;
363
364 /* Flush when switching output function. */
365 if (fn != old_fn)
366 PythonIO_Flush();
367 old_fn = fn;
368
369 /* Write each NL separated line. Text after the last NL is kept for
370 * writing later. */
371 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
372 {
373 PyInt len = ptr - str;
374
375 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
376 break;
377
378 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
379 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
380 fn((char_u *)io_ga.ga_data);
381 str = ptr + 1;
382 n -= len + 1;
383 io_ga.ga_len = 0;
384 }
385
386 /* Put the remaining text into io_ga for later printing. */
387 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
388 {
389 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
390 io_ga.ga_len += (int)n;
391 }
392}
393
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200394 static int
395write_output(OutputObject *self, PyObject *string)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200396{
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200397 Py_ssize_t len = 0;
398 char *str = NULL;
399 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200400
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200401 if (!PyArg_Parse(string, "et#", ENC_OPT, &str, &len))
402 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200403
404 Py_BEGIN_ALLOW_THREADS
405 Python_Lock_Vim();
406 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
407 Python_Release_Vim();
408 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200409 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200410
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200411 return 0;
412}
413
414 static PyObject *
415OutputWrite(OutputObject *self, PyObject *string)
416{
417 if (write_output(self, string))
418 return NULL;
419
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200420 Py_INCREF(Py_None);
421 return Py_None;
422}
423
424 static PyObject *
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200425OutputWritelines(OutputObject *self, PyObject *seq)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200426{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200427 PyObject *iterator;
428 PyObject *item;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200429
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200430 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200431 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200432
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200433 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200434 {
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200435 if (write_output(self, item))
Bram Moolenaardb913952012-06-29 12:54:53 +0200436 {
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200437 Py_DECREF(iterator);
438 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200439 return NULL;
440 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200441 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200442 }
443
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200444 Py_DECREF(iterator);
445
446 /* Iterator may have finished due to an exception */
447 if (PyErr_Occurred())
448 return NULL;
449
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200450 Py_INCREF(Py_None);
451 return Py_None;
452}
453
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100454 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200455OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100456{
457 /* do nothing */
458 Py_INCREF(Py_None);
459 return Py_None;
460}
461
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200462/***************/
463
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200464static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200465 /* name, function, calling, doc */
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200466 {"write", (PyCFunction)OutputWrite, METH_O, ""},
467 {"writelines", (PyCFunction)OutputWritelines, METH_O, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200468 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200469 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200470 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200471};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200472
473static OutputObject Output =
474{
475 PyObject_HEAD_INIT(&OutputType)
476 0,
477 0
478};
479
480static OutputObject Error =
481{
482 PyObject_HEAD_INIT(&OutputType)
483 0,
484 1
485};
486
487 static int
488PythonIO_Init_io(void)
489{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200490 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
491 return -1;
492 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
493 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200494
495 if (PyErr_Occurred())
496 {
497 EMSG(_("E264: Python: Error initialising I/O objects"));
498 return -1;
499 }
500
501 return 0;
502}
503
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200504typedef struct
505{
506 PyObject_HEAD
507 PyObject *module;
508} LoaderObject;
509static PyTypeObject LoaderType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200510
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200511 static void
512LoaderDestructor(LoaderObject *self)
513{
514 Py_DECREF(self->module);
515 DESTRUCTOR_FINISH(self);
516}
517
518 static PyObject *
519LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
520{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200521 PyObject *ret = self->module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200522
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200523 Py_INCREF(ret);
524 return ret;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200525}
526
527static struct PyMethodDef LoaderMethods[] = {
528 /* name, function, calling, doc */
529 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
530 { NULL, NULL, 0, NULL}
531};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200532
533/* Check to see whether a Vim error has been reported, or a keyboard
534 * interrupt has been detected.
535 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200536
537 static void
538VimTryStart(void)
539{
540 ++trylevel;
541}
542
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200543 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200544VimTryEnd(void)
545{
546 --trylevel;
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200547 /* Without this it stops processing all subsequent VimL commands and
548 * generates strange error messages if I e.g. try calling Test() in a cycle */
549 did_emsg = FALSE;
550 /* Keyboard interrupt should be preferred over anything else */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200551 if (got_int)
552 {
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200553 did_throw = got_int = FALSE;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200554 PyErr_SetNone(PyExc_KeyboardInterrupt);
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200555 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200556 }
557 else if (!did_throw)
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200558 return (PyErr_Occurred() ? -1 : 0);
559 /* Python exception is preferred over vim one; unlikely to occur though */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200560 else if (PyErr_Occurred())
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200561 {
562 did_throw = FALSE;
563 return -1;
564 }
565 /* Finally transform VimL exception to python one */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200566 else
567 {
568 PyErr_SetVim((char *) current_exception->value);
569 discard_current_exception();
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200570 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200571 }
572}
573
574 static int
575VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200576{
577 if (got_int)
578 {
579 PyErr_SetNone(PyExc_KeyboardInterrupt);
580 return 1;
581 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200582 return 0;
583}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200584
585/* Vim module - Implementation
586 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200587
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200588 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200589VimCommand(PyObject *self UNUSED, PyObject *string)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200590{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200591 char_u *cmd;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200592 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200593 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200594
Bram Moolenaar389a1792013-06-23 13:00:44 +0200595 if (!(cmd = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200596 return NULL;
597
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200598 Py_BEGIN_ALLOW_THREADS
599 Python_Lock_Vim();
600
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200601 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200602 do_cmdline_cmd(cmd);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200603 update_screen(VALID);
604
605 Python_Release_Vim();
606 Py_END_ALLOW_THREADS
607
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200608 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200609 ret = NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200610 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200611 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200612
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200613 Py_XINCREF(ret);
Bram Moolenaar389a1792013-06-23 13:00:44 +0200614 Py_XDECREF(todecref);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200615 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200616}
617
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200618/*
619 * Function to translate a typval_T into a PyObject; this will recursively
620 * translate lists/dictionaries into their Python equivalents.
621 *
622 * The depth parameter is to avoid infinite recursion, set it to 1 when
623 * you call VimToPython.
624 */
625 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200626VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200627{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200628 PyObject *ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200629 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200630 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200631
632 /* Avoid infinite recursion */
633 if (depth > 100)
634 {
635 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200636 ret = Py_None;
637 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200638 }
639
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200640 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200641 * then and we can use it again. */
642 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
643 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
644 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200645 sprintf(ptrBuf, "%p",
646 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
647 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200648
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200649 if ((ret = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200650 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200651 Py_INCREF(ret);
652 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200653 }
654 }
655
656 if (our_tv->v_type == VAR_STRING)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200657 ret = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200658 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200659 else if (our_tv->v_type == VAR_NUMBER)
660 {
661 char buf[NUMBUFLEN];
662
663 /* For backwards compatibility numbers are stored as strings. */
664 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200665 ret = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200666 }
667# ifdef FEAT_FLOAT
668 else if (our_tv->v_type == VAR_FLOAT)
669 {
670 char buf[NUMBUFLEN];
671
672 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200673 ret = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200674 }
675# endif
676 else if (our_tv->v_type == VAR_LIST)
677 {
678 list_T *list = our_tv->vval.v_list;
679 listitem_T *curr;
680
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200681 if (list == NULL)
682 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200683
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200684 if (!(ret = PyList_New(0)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200685 return NULL;
686
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200687 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200688 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200689 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200690 return NULL;
691 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200692
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200693 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
694 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200695 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200696 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200697 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200698 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200699 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200700 if (PyList_Append(ret, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200701 {
702 Py_DECREF(newObj);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200703 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200704 return NULL;
705 }
706 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200707 }
708 }
709 else if (our_tv->v_type == VAR_DICT)
710 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200711
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200712 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
713 long_u todo = ht->ht_used;
714 hashitem_T *hi;
715 dictitem_T *di;
716 if (our_tv->vval.v_dict == NULL)
717 return NULL;
718
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200719 if (!(ret = PyDict_New()))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200720 return NULL;
721
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200722 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200723 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200724 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200725 return NULL;
726 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200727
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200728 for (hi = ht->ht_array; todo > 0; ++hi)
729 {
730 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200731 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200732 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200733
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200734 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200735 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200736 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200737 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200738 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200739 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200740 if (PyDict_SetItemString(ret, (char *)hi->hi_key, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200741 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200742 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200743 Py_DECREF(newObj);
744 return NULL;
745 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200746 }
747 }
748 }
749 else
750 {
751 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200752 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200753 }
754
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200755 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200756}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200757
758 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200759VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200760{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200761 char_u *expr;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200762 typval_T *our_tv;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200763 PyObject *string;
764 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200765 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200766 PyObject *lookup_dict;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200767
Bram Moolenaar389a1792013-06-23 13:00:44 +0200768 if (!PyArg_ParseTuple(args, "O", &string))
769 return NULL;
770
771 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200772 return NULL;
773
774 Py_BEGIN_ALLOW_THREADS
775 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200776 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200777 our_tv = eval_expr(expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200778 Python_Release_Vim();
779 Py_END_ALLOW_THREADS
780
Bram Moolenaar389a1792013-06-23 13:00:44 +0200781 Py_XDECREF(todecref);
782
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200783 if (VimTryEnd())
784 return NULL;
785
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200786 if (our_tv == NULL)
787 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200788 PyErr_SET_VIM("invalid expression");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200789 return NULL;
790 }
791
792 /* Convert the Vim type into a Python type. Create a dictionary that's
793 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200794 if (!(lookup_dict = PyDict_New()))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200795 ret = NULL;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200796 else
797 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200798 ret = VimToPython(our_tv, 1, lookup_dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200799 Py_DECREF(lookup_dict);
800 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200801
802
803 Py_BEGIN_ALLOW_THREADS
804 Python_Lock_Vim();
805 free_tv(our_tv);
806 Python_Release_Vim();
807 Py_END_ALLOW_THREADS
808
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200809 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200810}
811
Bram Moolenaardb913952012-06-29 12:54:53 +0200812static PyObject *ConvertToPyObject(typval_T *);
813
814 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200815VimEvalPy(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200816{
Bram Moolenaardb913952012-06-29 12:54:53 +0200817 typval_T *our_tv;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200818 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200819 char_u *expr;
820 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +0200821
Bram Moolenaar389a1792013-06-23 13:00:44 +0200822 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200823 return NULL;
824
825 Py_BEGIN_ALLOW_THREADS
826 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200827 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200828 our_tv = eval_expr(expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200829 Python_Release_Vim();
830 Py_END_ALLOW_THREADS
831
Bram Moolenaar389a1792013-06-23 13:00:44 +0200832 Py_XDECREF(todecref);
833
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200834 if (VimTryEnd())
835 return NULL;
836
Bram Moolenaardb913952012-06-29 12:54:53 +0200837 if (our_tv == NULL)
838 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200839 PyErr_SET_VIM("invalid expression");
Bram Moolenaardb913952012-06-29 12:54:53 +0200840 return NULL;
841 }
842
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200843 ret = ConvertToPyObject(our_tv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200844 Py_BEGIN_ALLOW_THREADS
845 Python_Lock_Vim();
846 free_tv(our_tv);
847 Python_Release_Vim();
848 Py_END_ALLOW_THREADS
849
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200850 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +0200851}
852
853 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200854VimStrwidth(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200855{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200856 char_u *str;
857 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200858 int len;
Bram Moolenaardb913952012-06-29 12:54:53 +0200859
Bram Moolenaar389a1792013-06-23 13:00:44 +0200860 if (!(str = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200861 return NULL;
862
Bram Moolenaara54bf402012-12-05 16:30:07 +0100863#ifdef FEAT_MBYTE
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200864 len = mb_string2cells(str, (int)STRLEN(str));
Bram Moolenaara54bf402012-12-05 16:30:07 +0100865#else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200866 len = STRLEN(str);
Bram Moolenaara54bf402012-12-05 16:30:07 +0100867#endif
Bram Moolenaar389a1792013-06-23 13:00:44 +0200868
869 Py_XDECREF(todecref);
870
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200871 return PyLong_FromLong(len);
Bram Moolenaardb913952012-06-29 12:54:53 +0200872}
873
Bram Moolenaarf4258302013-06-02 18:20:17 +0200874 static PyObject *
875_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
876{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200877 PyObject *ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200878 PyObject *newwd;
879 PyObject *todecref;
880 char_u *new_dir;
881
Bram Moolenaard4209d22013-06-05 20:34:15 +0200882 if (_chdir == NULL)
883 return NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200884 if (!(ret = PyObject_Call(_chdir, args, kwargs)))
Bram Moolenaarf4258302013-06-02 18:20:17 +0200885 return NULL;
886
887 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
888 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200889 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +0200890 return NULL;
891 }
892
893 if (!(new_dir = StringToChars(newwd, &todecref)))
894 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200895 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +0200896 Py_DECREF(newwd);
897 return NULL;
898 }
899
900 VimTryStart();
901
902 if (vim_chdir(new_dir))
903 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200904 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +0200905 Py_DECREF(newwd);
906 Py_XDECREF(todecref);
907
908 if (VimTryEnd())
909 return NULL;
910
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200911 PyErr_SET_VIM("failed to change directory");
Bram Moolenaarf4258302013-06-02 18:20:17 +0200912 return NULL;
913 }
914
915 Py_DECREF(newwd);
916 Py_XDECREF(todecref);
917
918 post_chdir(FALSE);
919
920 if (VimTryEnd())
921 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200922 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +0200923 return NULL;
924 }
925
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200926 return ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200927}
928
929 static PyObject *
930VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
931{
932 return _VimChdir(py_chdir, args, kwargs);
933}
934
935 static PyObject *
936VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
937{
938 return _VimChdir(py_fchdir, args, kwargs);
939}
940
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200941typedef struct {
942 PyObject *callable;
943 PyObject *result;
944} map_rtp_data;
945
946 static void
947map_rtp_callback(char_u *path, void *_data)
948{
949 void **data = (void **) _data;
950 PyObject *pathObject;
951 map_rtp_data *mr_data = *((map_rtp_data **) data);
952
953 if (!(pathObject = PyString_FromString((char *) path)))
954 {
955 *data = NULL;
956 return;
957 }
958
959 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
960 pathObject, NULL);
961
962 Py_DECREF(pathObject);
963
964 if (!mr_data->result || mr_data->result != Py_None)
965 *data = NULL;
966 else
967 {
968 Py_DECREF(mr_data->result);
969 mr_data->result = NULL;
970 }
971}
972
973 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200974VimForeachRTP(PyObject *self UNUSED, PyObject *callable)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200975{
976 map_rtp_data data;
977
Bram Moolenaar389a1792013-06-23 13:00:44 +0200978 data.callable = callable;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200979 data.result = NULL;
980
981 do_in_runtimepath(NULL, FALSE, &map_rtp_callback, &data);
982
983 if (data.result == NULL)
984 {
985 if (PyErr_Occurred())
986 return NULL;
987 else
988 {
989 Py_INCREF(Py_None);
990 return Py_None;
991 }
992 }
993 return data.result;
994}
995
996/*
997 * _vim_runtimepath_ special path implementation.
998 */
999
1000 static void
1001map_finder_callback(char_u *path, void *_data)
1002{
1003 void **data = (void **) _data;
1004 PyObject *list = *((PyObject **) data);
1005 PyObject *pathObject1, *pathObject2;
1006 char *pathbuf;
1007 size_t pathlen;
1008
1009 pathlen = STRLEN(path);
1010
1011#if PY_MAJOR_VERSION < 3
1012# define PY_MAIN_DIR_STRING "python2"
1013#else
1014# define PY_MAIN_DIR_STRING "python3"
1015#endif
1016#define PY_ALTERNATE_DIR_STRING "pythonx"
1017
1018#define PYTHONX_STRING_LENGTH 7 /* STRLEN("pythonx") */
1019 if (!(pathbuf = PyMem_New(char,
1020 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
1021 {
1022 PyErr_NoMemory();
1023 *data = NULL;
1024 return;
1025 }
1026
1027 mch_memmove(pathbuf, path, pathlen + 1);
1028 add_pathsep((char_u *) pathbuf);
1029
1030 pathlen = STRLEN(pathbuf);
1031 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
1032 PYTHONX_STRING_LENGTH + 1);
1033
1034 if (!(pathObject1 = PyString_FromString(pathbuf)))
1035 {
1036 *data = NULL;
1037 PyMem_Free(pathbuf);
1038 return;
1039 }
1040
1041 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
1042 PYTHONX_STRING_LENGTH + 1);
1043
1044 if (!(pathObject2 = PyString_FromString(pathbuf)))
1045 {
1046 Py_DECREF(pathObject1);
1047 PyMem_Free(pathbuf);
1048 *data = NULL;
1049 return;
1050 }
1051
1052 PyMem_Free(pathbuf);
1053
1054 if (PyList_Append(list, pathObject1)
1055 || PyList_Append(list, pathObject2))
1056 *data = NULL;
1057
1058 Py_DECREF(pathObject1);
1059 Py_DECREF(pathObject2);
1060}
1061
1062 static PyObject *
1063Vim_GetPaths(PyObject *self UNUSED)
1064{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001065 PyObject *ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001066
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001067 if (!(ret = PyList_New(0)))
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001068 return NULL;
1069
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001070 do_in_runtimepath(NULL, FALSE, &map_finder_callback, ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001071
1072 if (PyErr_Occurred())
1073 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001074 Py_DECREF(ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001075 return NULL;
1076 }
1077
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001078 return ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001079}
1080
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001081 static PyObject *
1082call_load_module(char *name, int len, PyObject *find_module_result)
1083{
1084 PyObject *fd, *pathname, *description;
1085
Bram Moolenaarc476e522013-06-23 13:46:40 +02001086 if (!PyTuple_Check(find_module_result))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001087 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001088 PyErr_FORMAT(PyExc_TypeError,
1089 "expected 3-tuple as imp.find_module() result, but got %s",
1090 Py_TYPE_NAME(find_module_result));
1091 return NULL;
1092 }
1093 if (PyTuple_GET_SIZE(find_module_result) != 3)
1094 {
1095 PyErr_FORMAT(PyExc_TypeError,
1096 "expected 3-tuple as imp.find_module() result, but got "
1097 "tuple of size %d",
1098 (int) PyTuple_GET_SIZE(find_module_result));
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001099 return NULL;
1100 }
1101
1102 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
1103 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
1104 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
1105 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001106 PyErr_SET_STRING(PyExc_RuntimeError,
1107 "internal error: imp.find_module returned tuple with NULL");
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001108 return NULL;
1109 }
1110
1111 return PyObject_CallFunction(py_load_module,
1112 "s#OOO", name, len, fd, pathname, description);
1113}
1114
1115 static PyObject *
1116find_module(char *fullname, char *tail, PyObject *new_path)
1117{
1118 PyObject *find_module_result;
1119 PyObject *module;
1120 char *dot;
1121
1122 if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
1123 {
1124 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001125 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001126 * first component
1127 */
1128 PyObject *newest_path;
1129 int partlen = (int) (dot - 1 - tail);
1130
1131 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1132 "s#O", tail, partlen, new_path)))
1133 return NULL;
1134
1135 if (!(module = call_load_module(
1136 fullname,
1137 ((int) (tail - fullname)) + partlen,
1138 find_module_result)))
1139 {
1140 Py_DECREF(find_module_result);
1141 return NULL;
1142 }
1143
1144 Py_DECREF(find_module_result);
1145
1146 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1147 {
1148 Py_DECREF(module);
1149 return NULL;
1150 }
1151
1152 Py_DECREF(module);
1153
1154 module = find_module(fullname, dot + 1, newest_path);
1155
1156 Py_DECREF(newest_path);
1157
1158 return module;
1159 }
1160 else
1161 {
1162 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1163 "sO", tail, new_path)))
1164 return NULL;
1165
1166 if (!(module = call_load_module(
1167 fullname,
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001168 (int)STRLEN(fullname),
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001169 find_module_result)))
1170 {
1171 Py_DECREF(find_module_result);
1172 return NULL;
1173 }
1174
1175 Py_DECREF(find_module_result);
1176
1177 return module;
1178 }
1179}
1180
1181 static PyObject *
1182FinderFindModule(PyObject *self, PyObject *args)
1183{
1184 char *fullname;
1185 PyObject *module;
1186 PyObject *new_path;
1187 LoaderObject *loader;
1188
1189 if (!PyArg_ParseTuple(args, "s", &fullname))
1190 return NULL;
1191
1192 if (!(new_path = Vim_GetPaths(self)))
1193 return NULL;
1194
1195 module = find_module(fullname, fullname, new_path);
1196
1197 Py_DECREF(new_path);
1198
1199 if (!module)
1200 {
1201 Py_INCREF(Py_None);
1202 return Py_None;
1203 }
1204
1205 if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
1206 {
1207 Py_DECREF(module);
1208 return NULL;
1209 }
1210
1211 loader->module = module;
1212
1213 return (PyObject *) loader;
1214}
1215
1216 static PyObject *
1217VimPathHook(PyObject *self UNUSED, PyObject *args)
1218{
1219 char *path;
1220
1221 if (PyArg_ParseTuple(args, "s", &path)
1222 && STRCMP(path, vim_special_path) == 0)
1223 {
1224 Py_INCREF(vim_module);
1225 return vim_module;
1226 }
1227
1228 PyErr_Clear();
1229 PyErr_SetNone(PyExc_ImportError);
1230 return NULL;
1231}
1232
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001233/*
1234 * Vim module - Definitions
1235 */
1236
1237static struct PyMethodDef VimMethods[] = {
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001238 /* name, function, calling, documentation */
Bram Moolenaar389a1792013-06-23 13:00:44 +02001239 {"command", VimCommand, METH_O, "Execute a Vim ex-mode command" },
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001240 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02001241 {"bindeval", VimEvalPy, METH_O, "Like eval(), but returns objects attached to vim ones"},
1242 {"strwidth", VimStrwidth, METH_O, "Screen string width, counts <Tab> as having width 1"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001243 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1244 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001245 {"foreach_rtp", VimForeachRTP, METH_O, "Call given callable for each path in &rtp"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001246 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001247 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1248 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1249 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001250};
1251
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001252/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001253 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001254 */
1255
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001256static PyTypeObject IterType;
1257
1258typedef PyObject *(*nextfun)(void **);
1259typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001260typedef int (*traversefun)(void *, visitproc, void *);
1261typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001262
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001263/* Main purpose of this object is removing the need for do python
1264 * initialization (i.e. PyType_Ready and setting type attributes) for a big
1265 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001266
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001267typedef struct
1268{
1269 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001270 void *cur;
1271 nextfun next;
1272 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001273 traversefun traverse;
1274 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001275} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001276
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001277 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001278IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
1279 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001280{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001281 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001282
Bram Moolenaar774267b2013-05-21 20:51:59 +02001283 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001284 self->cur = start;
1285 self->next = next;
1286 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001287 self->traverse = traverse;
1288 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001289
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001290 return (PyObject *)(self);
1291}
1292
1293 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001294IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001295{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001296 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001297 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001298 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001299}
1300
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001301 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001302IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001303{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001304 if (self->traverse != NULL)
1305 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001306 else
1307 return 0;
1308}
1309
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001310/* Mac OSX defines clear() somewhere. */
1311#ifdef clear
1312# undef clear
1313#endif
1314
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001315 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001316IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001317{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001318 if (self->clear != NULL)
1319 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001320 else
1321 return 0;
1322}
1323
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001324 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001325IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001326{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001327 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001328}
1329
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001330 static PyObject *
1331IterIter(PyObject *self)
1332{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001333 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001334 return self;
1335}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001336
Bram Moolenaardb913952012-06-29 12:54:53 +02001337typedef struct pylinkedlist_S {
1338 struct pylinkedlist_S *pll_next;
1339 struct pylinkedlist_S *pll_prev;
1340 PyObject *pll_obj;
1341} pylinkedlist_T;
1342
1343static pylinkedlist_T *lastdict = NULL;
1344static pylinkedlist_T *lastlist = NULL;
1345
1346 static void
1347pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1348{
1349 if (ref->pll_prev == NULL)
1350 {
1351 if (ref->pll_next == NULL)
1352 {
1353 *last = NULL;
1354 return;
1355 }
1356 }
1357 else
1358 ref->pll_prev->pll_next = ref->pll_next;
1359
1360 if (ref->pll_next == NULL)
1361 *last = ref->pll_prev;
1362 else
1363 ref->pll_next->pll_prev = ref->pll_prev;
1364}
1365
1366 static void
1367pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1368{
1369 if (*last == NULL)
1370 ref->pll_prev = NULL;
1371 else
1372 {
1373 (*last)->pll_next = ref;
1374 ref->pll_prev = *last;
1375 }
1376 ref->pll_next = NULL;
1377 ref->pll_obj = self;
1378 *last = ref;
1379}
1380
1381static PyTypeObject DictionaryType;
1382
1383typedef struct
1384{
1385 PyObject_HEAD
1386 dict_T *dict;
1387 pylinkedlist_T ref;
1388} DictionaryObject;
1389
Bram Moolenaara9922d62013-05-30 13:01:18 +02001390static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1391
1392#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
1393
Bram Moolenaardb913952012-06-29 12:54:53 +02001394 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001395DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001396{
1397 DictionaryObject *self;
1398
Bram Moolenaara9922d62013-05-30 13:01:18 +02001399 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001400 if (self == NULL)
1401 return NULL;
1402 self->dict = dict;
1403 ++dict->dv_refcount;
1404
1405 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1406
1407 return (PyObject *)(self);
1408}
1409
Bram Moolenaara9922d62013-05-30 13:01:18 +02001410 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001411py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001412{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001413 dict_T *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001414
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001415 if (!(ret = dict_alloc()))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001416 {
1417 PyErr_NoMemory();
1418 return NULL;
1419 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001420 ++ret->dv_refcount;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001421
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001422 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001423}
1424
1425 static PyObject *
1426DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1427{
1428 DictionaryObject *self;
1429 dict_T *dict;
1430
1431 if (!(dict = py_dict_alloc()))
1432 return NULL;
1433
1434 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1435
1436 --dict->dv_refcount;
1437
1438 if (kwargs || PyTuple_Size(args))
1439 {
1440 PyObject *tmp;
1441 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1442 {
1443 Py_DECREF(self);
1444 return NULL;
1445 }
1446
1447 Py_DECREF(tmp);
1448 }
1449
1450 return (PyObject *)(self);
1451}
1452
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001453 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001454DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001455{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001456 pyll_remove(&self->ref, &lastdict);
1457 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001458
1459 DESTRUCTOR_FINISH(self);
1460}
1461
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001462static char *DictionaryAttrs[] = {
1463 "locked", "scope",
1464 NULL
1465};
1466
1467 static PyObject *
1468DictionaryDir(PyObject *self)
1469{
1470 return ObjectDir(self, DictionaryAttrs);
1471}
1472
Bram Moolenaardb913952012-06-29 12:54:53 +02001473 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001474DictionarySetattr(DictionaryObject *self, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001475{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001476 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001477 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001478 PyErr_SET_STRING(PyExc_AttributeError,
1479 "cannot delete vim.Dictionary attributes");
Bram Moolenaar66b79852012-09-21 14:00:35 +02001480 return -1;
1481 }
1482
1483 if (strcmp(name, "locked") == 0)
1484 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001485 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001486 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001487 PyErr_SET_STRING(PyExc_TypeError, "cannot modify fixed dictionary");
Bram Moolenaar66b79852012-09-21 14:00:35 +02001488 return -1;
1489 }
1490 else
1491 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001492 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02001493 if (istrue == -1)
1494 return -1;
1495 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001496 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001497 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001498 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001499 }
1500 return 0;
1501 }
1502 else
1503 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001504 PyErr_FORMAT(PyExc_AttributeError, "cannot set attribute %s", name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02001505 return -1;
1506 }
1507}
1508
1509 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001510DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001511{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001512 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001513}
1514
Bram Moolenaara9922d62013-05-30 13:01:18 +02001515#define DICT_FLAG_HAS_DEFAULT 0x01
1516#define DICT_FLAG_POP 0x02
1517#define DICT_FLAG_NONE_DEFAULT 0x04
1518#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
1519#define DICT_FLAG_RETURN_PAIR 0x10
1520
Bram Moolenaardb913952012-06-29 12:54:53 +02001521 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001522_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001523{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001524 PyObject *keyObject;
1525 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001526 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001527 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001528 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001529 dict_T *dict = self->dict;
1530 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001531 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001532
Bram Moolenaara9922d62013-05-30 13:01:18 +02001533 if (flags & DICT_FLAG_HAS_DEFAULT)
1534 {
1535 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1536 return NULL;
1537 }
1538 else
1539 keyObject = args;
1540
1541 if (flags & DICT_FLAG_RETURN_BOOL)
1542 defObject = Py_False;
1543
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001544 if (!(key = StringToChars(keyObject, &todecref)))
1545 return NULL;
1546
1547 if (*key == NUL)
1548 {
1549 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001550 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001551 return NULL;
1552 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001553
Bram Moolenaara9922d62013-05-30 13:01:18 +02001554 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001555
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001556 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001557
Bram Moolenaara9922d62013-05-30 13:01:18 +02001558 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001559 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001560 if (defObject)
1561 {
1562 Py_INCREF(defObject);
1563 return defObject;
1564 }
1565 else
1566 {
1567 PyErr_SetObject(PyExc_KeyError, keyObject);
1568 return NULL;
1569 }
1570 }
1571 else if (flags & DICT_FLAG_RETURN_BOOL)
1572 {
1573 Py_INCREF(Py_True);
1574 return Py_True;
1575 }
1576
1577 di = dict_lookup(hi);
1578
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001579 if (!(ret = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001580 return NULL;
1581
1582 if (flags & DICT_FLAG_POP)
1583 {
1584 if (dict->dv_lock)
1585 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001586 RAISE_LOCKED_DICTIONARY;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001587 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001588 return NULL;
1589 }
1590
1591 hash_remove(&dict->dv_hashtab, hi);
1592 dictitem_free(di);
1593 }
1594
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001595 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001596}
1597
1598 static PyObject *
1599DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1600{
1601 return _DictionaryItem(self, keyObject, 0);
1602}
1603
1604 static int
1605DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1606{
1607 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001608 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001609
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001610 ret = (rObj == Py_True);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001611
1612 Py_DECREF(Py_True);
1613
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001614 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001615}
1616
1617typedef struct
1618{
1619 hashitem_T *ht_array;
1620 long_u ht_used;
1621 hashtab_T *ht;
1622 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001623 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001624} dictiterinfo_T;
1625
1626 static PyObject *
1627DictionaryIterNext(dictiterinfo_T **dii)
1628{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001629 PyObject *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001630
1631 if (!(*dii)->todo)
1632 return NULL;
1633
1634 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1635 (*dii)->ht->ht_used != (*dii)->ht_used)
1636 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001637 PyErr_SET_STRING(PyExc_RuntimeError,
1638 "hashtab changed during iteration");
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001639 return NULL;
1640 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001641
Bram Moolenaara9922d62013-05-30 13:01:18 +02001642 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1643 ++((*dii)->hi);
1644
1645 --((*dii)->todo);
1646
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001647 if (!(ret = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001648 return NULL;
1649
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001650 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001651}
1652
1653 static PyObject *
1654DictionaryIter(DictionaryObject *self)
1655{
1656 dictiterinfo_T *dii;
1657 hashtab_T *ht;
1658
1659 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1660 {
1661 PyErr_NoMemory();
1662 return NULL;
1663 }
1664
1665 ht = &self->dict->dv_hashtab;
1666 dii->ht_array = ht->ht_array;
1667 dii->ht_used = ht->ht_used;
1668 dii->ht = ht;
1669 dii->hi = dii->ht_array;
1670 dii->todo = dii->ht_used;
1671
1672 return IterNew(dii,
1673 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1674 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001675}
1676
1677 static PyInt
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001678DictionaryAssItem(
1679 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001680{
1681 char_u *key;
1682 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001683 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001684 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001685 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001686
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001687 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001688 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001689 RAISE_LOCKED_DICTIONARY;
Bram Moolenaardb913952012-06-29 12:54:53 +02001690 return -1;
1691 }
1692
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001693 if (!(key = StringToChars(keyObject, &todecref)))
1694 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001695
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001696 if (*key == NUL)
1697 {
1698 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001699 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001700 return -1;
1701 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001702
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001703 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001704
1705 if (valObject == NULL)
1706 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001707 hashitem_T *hi;
1708
Bram Moolenaardb913952012-06-29 12:54:53 +02001709 if (di == NULL)
1710 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001711 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001712 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001713 return -1;
1714 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001715 hi = hash_find(&dict->dv_hashtab, di->di_key);
1716 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001717 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001718 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001719 return 0;
1720 }
1721
1722 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001723 {
1724 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001725 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001726 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001727
1728 if (di == NULL)
1729 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001730 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001731 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001732 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001733 PyErr_NoMemory();
1734 return -1;
1735 }
1736 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001737 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001738
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001739 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001740 {
1741 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001742 dictitem_free(di);
Bram Moolenaarc476e522013-06-23 13:46:40 +02001743 RAISE_KEY_ADD_FAIL(key);
1744 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001745 return -1;
1746 }
1747 }
1748 else
1749 clear_tv(&di->di_tv);
1750
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001751 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001752
1753 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001754 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001755 return 0;
1756}
1757
Bram Moolenaara9922d62013-05-30 13:01:18 +02001758typedef PyObject *(*hi_to_py)(hashitem_T *);
1759
Bram Moolenaardb913952012-06-29 12:54:53 +02001760 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001761DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001762{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001763 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001764 long_u todo = dict->dv_hashtab.ht_used;
1765 Py_ssize_t i = 0;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001766 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001767 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001768 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001769
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001770 ret = PyList_New(todo);
Bram Moolenaardb913952012-06-29 12:54:53 +02001771 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1772 {
1773 if (!HASHITEM_EMPTY(hi))
1774 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001775 if (!(newObj = hiconvert(hi)))
1776 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001777 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001778 return NULL;
1779 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001780 PyList_SET_ITEM(ret, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001781 --todo;
1782 ++i;
1783 }
1784 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001785 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001786}
1787
Bram Moolenaara9922d62013-05-30 13:01:18 +02001788 static PyObject *
1789dict_key(hashitem_T *hi)
1790{
1791 return PyBytes_FromString((char *)(hi->hi_key));
1792}
1793
1794 static PyObject *
1795DictionaryListKeys(DictionaryObject *self)
1796{
1797 return DictionaryListObjects(self, dict_key);
1798}
1799
1800 static PyObject *
1801dict_val(hashitem_T *hi)
1802{
1803 dictitem_T *di;
1804
1805 di = dict_lookup(hi);
1806 return ConvertToPyObject(&di->di_tv);
1807}
1808
1809 static PyObject *
1810DictionaryListValues(DictionaryObject *self)
1811{
1812 return DictionaryListObjects(self, dict_val);
1813}
1814
1815 static PyObject *
1816dict_item(hashitem_T *hi)
1817{
1818 PyObject *keyObject;
1819 PyObject *valObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001820 PyObject *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001821
1822 if (!(keyObject = dict_key(hi)))
1823 return NULL;
1824
1825 if (!(valObject = dict_val(hi)))
1826 {
1827 Py_DECREF(keyObject);
1828 return NULL;
1829 }
1830
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001831 ret = Py_BuildValue("(OO)", keyObject, valObject);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001832
1833 Py_DECREF(keyObject);
1834 Py_DECREF(valObject);
1835
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001836 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001837}
1838
1839 static PyObject *
1840DictionaryListItems(DictionaryObject *self)
1841{
1842 return DictionaryListObjects(self, dict_item);
1843}
1844
1845 static PyObject *
1846DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1847{
1848 dict_T *dict = self->dict;
1849
1850 if (dict->dv_lock)
1851 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001852 RAISE_LOCKED_DICTIONARY;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001853 return NULL;
1854 }
1855
1856 if (kwargs)
1857 {
1858 typval_T tv;
1859
1860 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1861 return NULL;
1862
1863 VimTryStart();
1864 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1865 clear_tv(&tv);
1866 if (VimTryEnd())
1867 return NULL;
1868 }
1869 else
1870 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001871 PyObject *obj;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001872
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001873 if (!PyArg_ParseTuple(args, "O", &obj))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001874 return NULL;
1875
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001876 if (PyObject_HasAttrString(obj, "keys"))
1877 return DictionaryUpdate(self, NULL, obj);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001878 else
1879 {
1880 PyObject *iterator;
1881 PyObject *item;
1882
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001883 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001884 return NULL;
1885
1886 while ((item = PyIter_Next(iterator)))
1887 {
1888 PyObject *fast;
1889 PyObject *keyObject;
1890 PyObject *valObject;
1891 PyObject *todecref;
1892 char_u *key;
1893 dictitem_T *di;
1894
1895 if (!(fast = PySequence_Fast(item, "")))
1896 {
1897 Py_DECREF(iterator);
1898 Py_DECREF(item);
1899 return NULL;
1900 }
1901
1902 Py_DECREF(item);
1903
1904 if (PySequence_Fast_GET_SIZE(fast) != 2)
1905 {
1906 Py_DECREF(iterator);
1907 Py_DECREF(fast);
Bram Moolenaarc476e522013-06-23 13:46:40 +02001908 PyErr_FORMAT(PyExc_ValueError,
1909 "expected sequence element of size 2, "
1910 "but got sequence of size %d",
1911 PySequence_Fast_GET_SIZE(fast));
Bram Moolenaara9922d62013-05-30 13:01:18 +02001912 return NULL;
1913 }
1914
1915 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1916
1917 if (!(key = StringToChars(keyObject, &todecref)))
1918 {
1919 Py_DECREF(iterator);
1920 Py_DECREF(fast);
1921 return NULL;
1922 }
1923
1924 di = dictitem_alloc(key);
1925
1926 Py_XDECREF(todecref);
1927
1928 if (di == NULL)
1929 {
1930 Py_DECREF(fast);
1931 Py_DECREF(iterator);
1932 PyErr_NoMemory();
1933 return NULL;
1934 }
1935 di->di_tv.v_lock = 0;
1936 di->di_tv.v_type = VAR_UNKNOWN;
1937
1938 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1939
1940 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1941 {
1942 Py_DECREF(iterator);
1943 Py_DECREF(fast);
1944 dictitem_free(di);
1945 return NULL;
1946 }
1947
1948 Py_DECREF(fast);
1949
1950 if (dict_add(dict, di) == FAIL)
1951 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001952 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001953 Py_DECREF(iterator);
1954 dictitem_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001955 return NULL;
1956 }
1957 }
1958
1959 Py_DECREF(iterator);
1960
1961 /* Iterator may have finished due to an exception */
1962 if (PyErr_Occurred())
1963 return NULL;
1964 }
1965 }
1966 Py_INCREF(Py_None);
1967 return Py_None;
1968}
1969
1970 static PyObject *
1971DictionaryGet(DictionaryObject *self, PyObject *args)
1972{
1973 return _DictionaryItem(self, args,
1974 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1975}
1976
1977 static PyObject *
1978DictionaryPop(DictionaryObject *self, PyObject *args)
1979{
1980 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1981}
1982
1983 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001984DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001985{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001986 hashitem_T *hi;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001987 PyObject *ret;
Bram Moolenaarde71b562013-06-02 17:41:54 +02001988 PyObject *valObject;
1989 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001990
Bram Moolenaarde71b562013-06-02 17:41:54 +02001991 if (self->dict->dv_hashtab.ht_used == 0)
1992 {
1993 PyErr_SetNone(PyExc_KeyError);
1994 return NULL;
1995 }
1996
1997 hi = self->dict->dv_hashtab.ht_array;
1998 while (HASHITEM_EMPTY(hi))
1999 ++hi;
2000
2001 di = dict_lookup(hi);
2002
2003 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002004 return NULL;
2005
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002006 if (!(ret = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
Bram Moolenaarde71b562013-06-02 17:41:54 +02002007 {
2008 Py_DECREF(valObject);
2009 return NULL;
2010 }
2011
2012 hash_remove(&self->dict->dv_hashtab, hi);
2013 dictitem_free(di);
2014
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002015 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002016}
2017
2018 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02002019DictionaryHasKey(DictionaryObject *self, PyObject *keyObject)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002020{
Bram Moolenaara9922d62013-05-30 13:01:18 +02002021 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
2022}
2023
2024static PySequenceMethods DictionaryAsSeq = {
2025 0, /* sq_length */
2026 0, /* sq_concat */
2027 0, /* sq_repeat */
2028 0, /* sq_item */
2029 0, /* sq_slice */
2030 0, /* sq_ass_item */
2031 0, /* sq_ass_slice */
2032 (objobjproc) DictionaryContains, /* sq_contains */
2033 0, /* sq_inplace_concat */
2034 0, /* sq_inplace_repeat */
2035};
2036
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002037static PyMappingMethods DictionaryAsMapping = {
2038 (lenfunc) DictionaryLength,
2039 (binaryfunc) DictionaryItem,
2040 (objobjargproc) DictionaryAssItem,
2041};
2042
Bram Moolenaardb913952012-06-29 12:54:53 +02002043static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02002044 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02002045 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
2046 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
2047 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
2048 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
2049 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02002050 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaar389a1792013-06-23 13:00:44 +02002051 {"has_key", (PyCFunction)DictionaryHasKey, METH_O, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002052 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
2053 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002054};
2055
2056static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002057static PySequenceMethods ListAsSeq;
2058static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02002059
2060typedef struct
2061{
2062 PyObject_HEAD
2063 list_T *list;
2064 pylinkedlist_T ref;
2065} ListObject;
2066
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002067#define NEW_LIST(list) ListNew(&ListType, list)
2068
Bram Moolenaardb913952012-06-29 12:54:53 +02002069 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002070ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02002071{
2072 ListObject *self;
2073
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002074 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02002075 if (self == NULL)
2076 return NULL;
2077 self->list = list;
2078 ++list->lv_refcount;
2079
2080 pyll_add((PyObject *)(self), &self->ref, &lastlist);
2081
2082 return (PyObject *)(self);
2083}
2084
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002085 static list_T *
2086py_list_alloc()
2087{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002088 list_T *ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002089
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002090 if (!(ret = list_alloc()))
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002091 {
2092 PyErr_NoMemory();
2093 return NULL;
2094 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002095 ++ret->lv_refcount;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002096
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002097 return ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002098}
2099
2100 static int
2101list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
2102{
2103 PyObject *iterator;
2104 PyObject *item;
2105 listitem_T *li;
2106
2107 if (!(iterator = PyObject_GetIter(obj)))
2108 return -1;
2109
2110 while ((item = PyIter_Next(iterator)))
2111 {
2112 if (!(li = listitem_alloc()))
2113 {
2114 PyErr_NoMemory();
2115 Py_DECREF(item);
2116 Py_DECREF(iterator);
2117 return -1;
2118 }
2119 li->li_tv.v_lock = 0;
2120 li->li_tv.v_type = VAR_UNKNOWN;
2121
2122 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
2123 {
2124 Py_DECREF(item);
2125 Py_DECREF(iterator);
2126 listitem_free(li);
2127 return -1;
2128 }
2129
2130 Py_DECREF(item);
2131
2132 list_append(l, li);
2133 }
2134
2135 Py_DECREF(iterator);
2136
2137 /* Iterator may have finished due to an exception */
2138 if (PyErr_Occurred())
2139 return -1;
2140
2141 return 0;
2142}
2143
2144 static PyObject *
2145ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2146{
2147 list_T *list;
2148 PyObject *obj = NULL;
2149
2150 if (kwargs)
2151 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002152 PyErr_SET_STRING(PyExc_TypeError,
2153 "list constructor does not accept keyword arguments");
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002154 return NULL;
2155 }
2156
2157 if (!PyArg_ParseTuple(args, "|O", &obj))
2158 return NULL;
2159
2160 if (!(list = py_list_alloc()))
2161 return NULL;
2162
2163 if (obj)
2164 {
2165 PyObject *lookup_dict;
2166
2167 if (!(lookup_dict = PyDict_New()))
2168 {
2169 list_unref(list);
2170 return NULL;
2171 }
2172
2173 if (list_py_concat(list, obj, lookup_dict) == -1)
2174 {
2175 Py_DECREF(lookup_dict);
2176 list_unref(list);
2177 return NULL;
2178 }
2179
2180 Py_DECREF(lookup_dict);
2181 }
2182
2183 return ListNew(subtype, list);
2184}
2185
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002186 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002187ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002188{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002189 pyll_remove(&self->ref, &lastlist);
2190 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002191
2192 DESTRUCTOR_FINISH(self);
2193}
2194
Bram Moolenaardb913952012-06-29 12:54:53 +02002195 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002196ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002197{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002198 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002199}
2200
2201 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002202ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002203{
2204 listitem_T *li;
2205
Bram Moolenaard6e39182013-05-21 18:30:34 +02002206 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002207 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002208 PyErr_SET_STRING(PyExc_IndexError, "list index out of range");
Bram Moolenaardb913952012-06-29 12:54:53 +02002209 return NULL;
2210 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002211 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002212 if (li == NULL)
2213 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002214 /* No more suitable format specifications in python-2.3 */
2215 PyErr_VIM_FORMAT("internal error: failed to get vim list item %d",
2216 (int) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002217 return NULL;
2218 }
2219 return ConvertToPyObject(&li->li_tv);
2220}
2221
2222#define PROC_RANGE \
2223 if (last < 0) {\
2224 if (last < -size) \
2225 last = 0; \
2226 else \
2227 last += size; \
2228 } \
2229 if (first < 0) \
2230 first = 0; \
2231 if (first > size) \
2232 first = size; \
2233 if (last > size) \
2234 last = size;
2235
2236 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002237ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02002238{
2239 PyInt i;
2240 PyInt size = ListLength(self);
2241 PyInt n;
2242 PyObject *list;
2243 int reversed = 0;
2244
2245 PROC_RANGE
2246 if (first >= last)
2247 first = last;
2248
2249 n = last-first;
2250 list = PyList_New(n);
2251 if (list == NULL)
2252 return NULL;
2253
2254 for (i = 0; i < n; ++i)
2255 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02002256 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02002257 if (item == NULL)
2258 {
2259 Py_DECREF(list);
2260 return NULL;
2261 }
2262
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02002263 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002264 }
2265
2266 return list;
2267}
2268
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002269typedef struct
2270{
2271 listwatch_T lw;
2272 list_T *list;
2273} listiterinfo_T;
2274
2275 static void
2276ListIterDestruct(listiterinfo_T *lii)
2277{
2278 list_rem_watch(lii->list, &lii->lw);
2279 PyMem_Free(lii);
2280}
2281
2282 static PyObject *
2283ListIterNext(listiterinfo_T **lii)
2284{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002285 PyObject *ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002286
2287 if (!((*lii)->lw.lw_item))
2288 return NULL;
2289
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002290 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002291 return NULL;
2292
2293 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2294
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002295 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002296}
2297
2298 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002299ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002300{
2301 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002302 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002303
2304 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2305 {
2306 PyErr_NoMemory();
2307 return NULL;
2308 }
2309
2310 list_add_watch(l, &lii->lw);
2311 lii->lw.lw_item = l->lv_first;
2312 lii->list = l;
2313
2314 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002315 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2316 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002317}
2318
Bram Moolenaardb913952012-06-29 12:54:53 +02002319 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002320ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002321{
2322 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002323 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002324 listitem_T *li;
2325 Py_ssize_t length = ListLength(self);
2326
2327 if (l->lv_lock)
2328 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002329 RAISE_LOCKED_LIST;
Bram Moolenaardb913952012-06-29 12:54:53 +02002330 return -1;
2331 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002332 if (index > length || (index == length && obj == NULL))
Bram Moolenaardb913952012-06-29 12:54:53 +02002333 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002334 PyErr_SET_STRING(PyExc_IndexError, "list index out of range");
Bram Moolenaardb913952012-06-29 12:54:53 +02002335 return -1;
2336 }
2337
2338 if (obj == NULL)
2339 {
2340 li = list_find(l, (long) index);
2341 list_remove(l, li, li);
2342 clear_tv(&li->li_tv);
2343 vim_free(li);
2344 return 0;
2345 }
2346
2347 if (ConvertFromPyObject(obj, &tv) == -1)
2348 return -1;
2349
2350 if (index == length)
2351 {
2352 if (list_append_tv(l, &tv) == FAIL)
2353 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002354 clear_tv(&tv);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002355 PyErr_SET_VIM("failed to add item to list");
Bram Moolenaardb913952012-06-29 12:54:53 +02002356 return -1;
2357 }
2358 }
2359 else
2360 {
2361 li = list_find(l, (long) index);
2362 clear_tv(&li->li_tv);
2363 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002364 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002365 }
2366 return 0;
2367}
2368
2369 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002370ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002371{
2372 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002373 PyObject *iterator;
2374 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02002375 listitem_T *li;
2376 listitem_T *next;
2377 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002378 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002379 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002380
2381 if (l->lv_lock)
2382 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002383 RAISE_LOCKED_LIST;
Bram Moolenaardb913952012-06-29 12:54:53 +02002384 return -1;
2385 }
2386
2387 PROC_RANGE
2388
2389 if (first == size)
2390 li = NULL;
2391 else
2392 {
2393 li = list_find(l, (long) first);
2394 if (li == NULL)
2395 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002396 PyErr_VIM_FORMAT("internal error: no vim list item %d", (int)first);
Bram Moolenaardb913952012-06-29 12:54:53 +02002397 return -1;
2398 }
2399 if (last > first)
2400 {
2401 i = last - first;
2402 while (i-- && li != NULL)
2403 {
2404 next = li->li_next;
2405 listitem_remove(l, li);
2406 li = next;
2407 }
2408 }
2409 }
2410
2411 if (obj == NULL)
2412 return 0;
2413
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002414 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002415 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02002416
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002417 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002418 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002419 if (ConvertFromPyObject(item, &v) == -1)
2420 {
2421 Py_DECREF(iterator);
2422 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002423 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002424 }
2425 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002426 if (list_insert_tv(l, &v, li) == FAIL)
2427 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002428 clear_tv(&v);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002429 PyErr_SET_VIM("internal error: failed to add item to list");
Bram Moolenaardb913952012-06-29 12:54:53 +02002430 return -1;
2431 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002432 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002433 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002434 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02002435 return 0;
2436}
2437
2438 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002439ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002440{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002441 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002442 PyObject *lookup_dict;
2443
2444 if (l->lv_lock)
2445 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002446 RAISE_LOCKED_LIST;
Bram Moolenaardb913952012-06-29 12:54:53 +02002447 return NULL;
2448 }
2449
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02002450 if (!(lookup_dict = PyDict_New()))
2451 return NULL;
2452
Bram Moolenaardb913952012-06-29 12:54:53 +02002453 if (list_py_concat(l, obj, lookup_dict) == -1)
2454 {
2455 Py_DECREF(lookup_dict);
2456 return NULL;
2457 }
2458 Py_DECREF(lookup_dict);
2459
2460 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02002461 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002462}
2463
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002464static char *ListAttrs[] = {
2465 "locked",
2466 NULL
2467};
2468
2469 static PyObject *
2470ListDir(PyObject *self)
2471{
2472 return ObjectDir(self, ListAttrs);
2473}
2474
Bram Moolenaar66b79852012-09-21 14:00:35 +02002475 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002476ListSetattr(ListObject *self, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002477{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002478 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002479 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002480 PyErr_SET_STRING(PyExc_AttributeError,
2481 "cannot delete vim.List attributes");
Bram Moolenaar66b79852012-09-21 14:00:35 +02002482 return -1;
2483 }
2484
2485 if (strcmp(name, "locked") == 0)
2486 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002487 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002488 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002489 PyErr_SET_STRING(PyExc_TypeError, "cannot modify fixed list");
Bram Moolenaar66b79852012-09-21 14:00:35 +02002490 return -1;
2491 }
2492 else
2493 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002494 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02002495 if (istrue == -1)
2496 return -1;
2497 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002498 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002499 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002500 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002501 }
2502 return 0;
2503 }
2504 else
2505 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002506 PyErr_FORMAT(PyExc_AttributeError, "cannot set attribute %s", name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02002507 return -1;
2508 }
2509}
2510
Bram Moolenaardb913952012-06-29 12:54:53 +02002511static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002512 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2513 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2514 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002515};
2516
2517typedef struct
2518{
2519 PyObject_HEAD
2520 char_u *name;
2521} FunctionObject;
2522
2523static PyTypeObject FunctionType;
2524
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002525#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
2526
Bram Moolenaardb913952012-06-29 12:54:53 +02002527 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002528FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002529{
2530 FunctionObject *self;
2531
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002532 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2533
Bram Moolenaardb913952012-06-29 12:54:53 +02002534 if (self == NULL)
2535 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002536
2537 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002538 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002539 if (!translated_function_exists(name))
2540 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002541 PyErr_FORMAT(PyExc_ValueError,
2542 "unnamed function %s does not exist", name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002543 return NULL;
2544 }
2545 self->name = vim_strsave(name);
2546 func_ref(self->name);
2547 }
2548 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002549 if ((self->name = get_expanded_name(name,
2550 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2551 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002552 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002553 PyErr_FORMAT(PyExc_ValueError, "function %s does not exist", name);
Bram Moolenaar018acca2013-05-30 13:37:28 +02002554 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002555 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002556
2557 return (PyObject *)(self);
2558}
2559
2560 static PyObject *
2561FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2562{
2563 PyObject *self;
2564 char_u *name;
2565
2566 if (kwargs)
2567 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002568 PyErr_SET_STRING(PyExc_TypeError,
2569 "function constructor does not accept keyword arguments");
Bram Moolenaardb913952012-06-29 12:54:53 +02002570 return NULL;
2571 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002572
Bram Moolenaar389a1792013-06-23 13:00:44 +02002573 if (!PyArg_ParseTuple(args, "et", "ascii", &name))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002574 return NULL;
2575
2576 self = FunctionNew(subtype, name);
2577
Bram Moolenaar389a1792013-06-23 13:00:44 +02002578 PyMem_Free(name);
2579
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002580 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002581}
2582
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002583 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002584FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002585{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002586 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002587 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002588
2589 DESTRUCTOR_FINISH(self);
2590}
2591
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002592static char *FunctionAttrs[] = {
2593 "softspace",
2594 NULL
2595};
2596
2597 static PyObject *
2598FunctionDir(PyObject *self)
2599{
2600 return ObjectDir(self, FunctionAttrs);
2601}
2602
Bram Moolenaardb913952012-06-29 12:54:53 +02002603 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002604FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002605{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002606 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002607 typval_T args;
2608 typval_T selfdicttv;
2609 typval_T rettv;
2610 dict_T *selfdict = NULL;
2611 PyObject *selfdictObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002612 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02002613 int error;
2614
2615 if (ConvertFromPyObject(argsObject, &args) == -1)
2616 return NULL;
2617
2618 if (kwargs != NULL)
2619 {
2620 selfdictObject = PyDict_GetItemString(kwargs, "self");
2621 if (selfdictObject != NULL)
2622 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002623 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002624 {
2625 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002626 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002627 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002628 selfdict = selfdicttv.vval.v_dict;
2629 }
2630 }
2631
Bram Moolenaar71700b82013-05-15 17:49:05 +02002632 Py_BEGIN_ALLOW_THREADS
2633 Python_Lock_Vim();
2634
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002635 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002636 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002637
2638 Python_Release_Vim();
2639 Py_END_ALLOW_THREADS
2640
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002641 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002642 ret = NULL;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002643 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002644 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002645 ret = NULL;
Bram Moolenaarc476e522013-06-23 13:46:40 +02002646 PyErr_VIM_FORMAT("failed to run function %s", (char *)name);
Bram Moolenaardb913952012-06-29 12:54:53 +02002647 }
2648 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002649 ret = ConvertToPyObject(&rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002650
Bram Moolenaardb913952012-06-29 12:54:53 +02002651 clear_tv(&args);
2652 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002653 if (selfdict != NULL)
2654 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002655
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002656 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02002657}
2658
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002659 static PyObject *
2660FunctionRepr(FunctionObject *self)
2661{
Bram Moolenaar841fbd22013-06-23 14:37:07 +02002662#ifdef Py_TRACE_REFS
2663 /* For unknown reason self->name may be NULL after calling
2664 * Finalize */
2665 return PyString_FromFormat("<vim.Function '%s'>",
2666 (self->name == NULL ? "<NULL>" : (char *) self->name));
2667#else
2668 return PyString_FromFormat("<vim.Function '%s'>", (char *) self->name);
2669#endif
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002670}
2671
Bram Moolenaardb913952012-06-29 12:54:53 +02002672static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002673 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2674 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002675};
2676
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002677/*
2678 * Options object
2679 */
2680
2681static PyTypeObject OptionsType;
2682
2683typedef int (*checkfun)(void *);
2684
2685typedef struct
2686{
2687 PyObject_HEAD
2688 int opt_type;
2689 void *from;
2690 checkfun Check;
2691 PyObject *fromObj;
2692} OptionsObject;
2693
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002694 static int
2695dummy_check(void *arg UNUSED)
2696{
2697 return 0;
2698}
2699
2700 static PyObject *
2701OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2702{
2703 OptionsObject *self;
2704
Bram Moolenaar774267b2013-05-21 20:51:59 +02002705 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002706 if (self == NULL)
2707 return NULL;
2708
2709 self->opt_type = opt_type;
2710 self->from = from;
2711 self->Check = Check;
2712 self->fromObj = fromObj;
2713 if (fromObj)
2714 Py_INCREF(fromObj);
2715
2716 return (PyObject *)(self);
2717}
2718
2719 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002720OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002721{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002722 PyObject_GC_UnTrack((void *)(self));
2723 Py_XDECREF(self->fromObj);
2724 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002725}
2726
2727 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002728OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002729{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002730 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002731 return 0;
2732}
2733
2734 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002735OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002736{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002737 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002738 return 0;
2739}
2740
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002741 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002742OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002743{
2744 char_u *key;
2745 int flags;
2746 long numval;
2747 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002748 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002749
Bram Moolenaard6e39182013-05-21 18:30:34 +02002750 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002751 return NULL;
2752
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002753 if (!(key = StringToChars(keyObject, &todecref)))
2754 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002755
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002756 if (*key == NUL)
2757 {
2758 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002759 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002760 return NULL;
2761 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002762
2763 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002764 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002765
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002766 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002767
2768 if (flags == 0)
2769 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002770 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002771 return NULL;
2772 }
2773
2774 if (flags & SOPT_UNSET)
2775 {
2776 Py_INCREF(Py_None);
2777 return Py_None;
2778 }
2779 else if (flags & SOPT_BOOL)
2780 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002781 PyObject *ret;
2782 ret = numval ? Py_True : Py_False;
2783 Py_INCREF(ret);
2784 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002785 }
2786 else if (flags & SOPT_NUM)
2787 return PyInt_FromLong(numval);
2788 else if (flags & SOPT_STRING)
2789 {
2790 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002791 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002792 PyObject *ret = PyBytes_FromString((char *) stringval);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002793 vim_free(stringval);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002794 return ret;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002795 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002796 else
2797 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002798 PyErr_SET_STRING(PyExc_RuntimeError,
2799 "unable to get option value");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002800 return NULL;
2801 }
2802 }
2803 else
2804 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002805 PyErr_SET_VIM("internal error: unknown option type");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002806 return NULL;
2807 }
2808}
2809
2810 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002811set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002812{
2813 char_u *errmsg;
2814
2815 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2816 {
2817 if (VimTryEnd())
2818 return FAIL;
2819 PyErr_SetVim((char *)errmsg);
2820 return FAIL;
2821 }
2822 return OK;
2823}
2824
2825 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002826set_option_value_for(
2827 char_u *key,
2828 int numval,
2829 char_u *stringval,
2830 int opt_flags,
2831 int opt_type,
2832 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002833{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002834 win_T *save_curwin = NULL;
2835 tabpage_T *save_curtab = NULL;
2836 buf_T *save_curbuf = NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002837 int set_ret = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002838
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002839 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002840 switch (opt_type)
2841 {
2842 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002843 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02002844 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002845 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002846 if (VimTryEnd())
2847 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002848 PyErr_SET_VIM("problem while switching windows");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002849 return -1;
2850 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002851 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
2852 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002853 break;
2854 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002855 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002856 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002857 restore_buffer(save_curbuf);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002858 break;
2859 case SREQ_GLOBAL:
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002860 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002861 break;
2862 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002863 if (set_ret == FAIL)
2864 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002865 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002866}
2867
2868 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002869OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002870{
2871 char_u *key;
2872 int flags;
2873 int opt_flags;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002874 int ret = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002875 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002876
Bram Moolenaard6e39182013-05-21 18:30:34 +02002877 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002878 return -1;
2879
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002880 if (!(key = StringToChars(keyObject, &todecref)))
2881 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002882
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002883 if (*key == NUL)
2884 {
2885 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002886 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002887 return -1;
2888 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002889
2890 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002891 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002892
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002893 if (flags == 0)
2894 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002895 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002896 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002897 return -1;
2898 }
2899
2900 if (valObject == NULL)
2901 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002902 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002903 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002904 PyErr_FORMAT(PyExc_ValueError,
2905 "unable to unset global option %s", key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002906 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002907 return -1;
2908 }
2909 else if (!(flags & SOPT_GLOBAL))
2910 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002911 PyErr_FORMAT(PyExc_ValueError,
2912 "unable to unset option %s "
2913 "which does not have global value", key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002914 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002915 return -1;
2916 }
2917 else
2918 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002919 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002920 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002921 return 0;
2922 }
2923 }
2924
Bram Moolenaard6e39182013-05-21 18:30:34 +02002925 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002926
2927 if (flags & SOPT_BOOL)
2928 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002929 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002930
Bram Moolenaarb983f752013-05-15 16:11:50 +02002931 if (istrue == -1)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002932 ret = -1;
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002933 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002934 ret = set_option_value_for(key, istrue, NULL,
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002935 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002936 }
2937 else if (flags & SOPT_NUM)
2938 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02002939 long val;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002940
Bram Moolenaar141be8a2013-06-23 14:16:57 +02002941 if (NumberToLong(valObject, &val, NUMBER_INT))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002942 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002943 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002944 return -1;
2945 }
2946
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002947 ret = set_option_value_for(key, (int) val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002948 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002949 }
2950 else
2951 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002952 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002953 PyObject *todecref;
2954
2955 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002956 ret = set_option_value_for(key, 0, val, opt_flags,
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002957 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002958 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002959 ret = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002960 }
2961
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002962 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002963
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002964 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002965}
2966
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002967static PyMappingMethods OptionsAsMapping = {
2968 (lenfunc) NULL,
2969 (binaryfunc) OptionsItem,
2970 (objobjargproc) OptionsAssItem,
2971};
2972
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002973/* Tabpage object
2974 */
2975
2976typedef struct
2977{
2978 PyObject_HEAD
2979 tabpage_T *tab;
2980} TabPageObject;
2981
2982static PyObject *WinListNew(TabPageObject *tabObject);
2983
2984static PyTypeObject TabPageType;
2985
2986 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002987CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002988{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002989 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002990 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002991 PyErr_SET_VIM("attempt to refer to deleted tab page");
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002992 return -1;
2993 }
2994
2995 return 0;
2996}
2997
2998 static PyObject *
2999TabPageNew(tabpage_T *tab)
3000{
3001 TabPageObject *self;
3002
3003 if (TAB_PYTHON_REF(tab))
3004 {
3005 self = TAB_PYTHON_REF(tab);
3006 Py_INCREF(self);
3007 }
3008 else
3009 {
3010 self = PyObject_NEW(TabPageObject, &TabPageType);
3011 if (self == NULL)
3012 return NULL;
3013 self->tab = tab;
3014 TAB_PYTHON_REF(tab) = self;
3015 }
3016
3017 return (PyObject *)(self);
3018}
3019
3020 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003021TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003022{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003023 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
3024 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003025
3026 DESTRUCTOR_FINISH(self);
3027}
3028
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003029static char *TabPageAttrs[] = {
3030 "windows", "number", "vars", "window", "valid",
3031 NULL
3032};
3033
3034 static PyObject *
3035TabPageDir(PyObject *self)
3036{
3037 return ObjectDir(self, TabPageAttrs);
3038}
3039
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003040 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003041TabPageAttrValid(TabPageObject *self, char *name)
3042{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003043 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003044
3045 if (strcmp(name, "valid") != 0)
3046 return NULL;
3047
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003048 ret = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
3049 Py_INCREF(ret);
3050 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003051}
3052
3053 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003054TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003055{
3056 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003057 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003058 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003059 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003060 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003061 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003062 else if (strcmp(name, "window") == 0)
3063 {
3064 /* For current tab window.c does not bother to set or update tp_curwin
3065 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003066 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003067 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003068 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02003069 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003070 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003071 else if (strcmp(name, "__members__") == 0)
3072 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003073 return NULL;
3074}
3075
3076 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003077TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003078{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003079 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003080 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003081 else
3082 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003083 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003084
3085 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003086 return PyString_FromFormat("<tabpage object (unknown) at %p>",
3087 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003088 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003089 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003090 }
3091}
3092
3093static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003094 /* name, function, calling, documentation */
3095 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
3096 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003097};
3098
3099/*
3100 * Window list object
3101 */
3102
3103static PyTypeObject TabListType;
3104static PySequenceMethods TabListAsSeq;
3105
3106typedef struct
3107{
3108 PyObject_HEAD
3109} TabListObject;
3110
3111 static PyInt
3112TabListLength(PyObject *self UNUSED)
3113{
3114 tabpage_T *tp = first_tabpage;
3115 PyInt n = 0;
3116
3117 while (tp != NULL)
3118 {
3119 ++n;
3120 tp = tp->tp_next;
3121 }
3122
3123 return n;
3124}
3125
3126 static PyObject *
3127TabListItem(PyObject *self UNUSED, PyInt n)
3128{
3129 tabpage_T *tp;
3130
3131 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
3132 if (n == 0)
3133 return TabPageNew(tp);
3134
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003135 PyErr_SET_STRING(PyExc_IndexError, "no such tab page");
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003136 return NULL;
3137}
3138
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +02003139/*
3140 * Window object
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003141 */
3142
3143typedef struct
3144{
3145 PyObject_HEAD
3146 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003147 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003148} WindowObject;
3149
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003150static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003151
3152 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003153CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003154{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003155 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003156 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003157 PyErr_SET_VIM("attempt to refer to deleted window");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003158 return -1;
3159 }
3160
3161 return 0;
3162}
3163
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003164 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003165WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02003166{
3167 /* We need to handle deletion of windows underneath us.
3168 * If we add a "w_python*_ref" field to the win_T structure,
3169 * then we can get at it in win_free() in vim. We then
3170 * need to create only ONE Python object per window - if
3171 * we try to create a second, just INCREF the existing one
3172 * and return it. The (single) Python object referring to
3173 * the window is stored in "w_python*_ref".
3174 * On a win_free() we set the Python object's win_T* field
3175 * to an invalid value. We trap all uses of a window
3176 * object, and reject them if the win_T* field is invalid.
3177 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003178 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003179 * w_python_ref and w_python3_ref fields respectively.
3180 */
3181
3182 WindowObject *self;
3183
3184 if (WIN_PYTHON_REF(win))
3185 {
3186 self = WIN_PYTHON_REF(win);
3187 Py_INCREF(self);
3188 }
3189 else
3190 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02003191 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02003192 if (self == NULL)
3193 return NULL;
3194 self->win = win;
3195 WIN_PYTHON_REF(win) = self;
3196 }
3197
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003198 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
3199
Bram Moolenaar971db462013-05-12 18:44:48 +02003200 return (PyObject *)(self);
3201}
3202
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003203 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003204WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003205{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003206 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02003207 if (self->win && self->win != INVALID_WINDOW_VALUE)
3208 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003209 Py_XDECREF(((PyObject *)(self->tabObject)));
3210 PyObject_GC_Del((void *)(self));
3211}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003212
Bram Moolenaar774267b2013-05-21 20:51:59 +02003213 static int
3214WindowTraverse(WindowObject *self, visitproc visit, void *arg)
3215{
3216 Py_VISIT(((PyObject *)(self->tabObject)));
3217 return 0;
3218}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003219
Bram Moolenaar774267b2013-05-21 20:51:59 +02003220 static int
3221WindowClear(WindowObject *self)
3222{
3223 Py_CLEAR(self->tabObject);
3224 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003225}
3226
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003227 static win_T *
3228get_firstwin(TabPageObject *tabObject)
3229{
3230 if (tabObject)
3231 {
3232 if (CheckTabPage(tabObject))
3233 return NULL;
3234 /* For current tab window.c does not bother to set or update tp_firstwin
3235 */
3236 else if (tabObject->tab == curtab)
3237 return firstwin;
3238 else
3239 return tabObject->tab->tp_firstwin;
3240 }
3241 else
3242 return firstwin;
3243}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003244static char *WindowAttrs[] = {
3245 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
3246 "tabpage", "valid",
3247 NULL
3248};
3249
3250 static PyObject *
3251WindowDir(PyObject *self)
3252{
3253 return ObjectDir(self, WindowAttrs);
3254}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003255
Bram Moolenaar971db462013-05-12 18:44:48 +02003256 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003257WindowAttrValid(WindowObject *self, char *name)
3258{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003259 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003260
3261 if (strcmp(name, "valid") != 0)
3262 return NULL;
3263
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003264 ret = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
3265 Py_INCREF(ret);
3266 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003267}
3268
3269 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003270WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003271{
3272 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003273 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003274 else if (strcmp(name, "cursor") == 0)
3275 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003276 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003277
3278 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
3279 }
3280 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003281 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003282#ifdef FEAT_WINDOWS
3283 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003284 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003285#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003286#ifdef FEAT_VERTSPLIT
3287 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003288 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003289 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003290 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003291#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02003292 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003293 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003294 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003295 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
3296 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02003297 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003298 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003299 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003300 return NULL;
3301 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003302 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003303 }
3304 else if (strcmp(name, "tabpage") == 0)
3305 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003306 Py_INCREF(self->tabObject);
3307 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003308 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003309 else if (strcmp(name, "__members__") == 0)
3310 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003311 else
3312 return NULL;
3313}
3314
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003315 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003316WindowSetattr(WindowObject *self, char *name, PyObject *valObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003317{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003318 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003319 return -1;
3320
3321 if (strcmp(name, "buffer") == 0)
3322 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003323 PyErr_SET_STRING(PyExc_TypeError, "readonly attribute: buffer");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003324 return -1;
3325 }
3326 else if (strcmp(name, "cursor") == 0)
3327 {
3328 long lnum;
3329 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003330
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003331 if (!PyArg_Parse(valObject, "(ll)", &lnum, &col))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003332 return -1;
3333
Bram Moolenaard6e39182013-05-21 18:30:34 +02003334 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003335 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003336 PyErr_SET_VIM("cursor position outside buffer");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003337 return -1;
3338 }
3339
3340 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003341 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003342 return -1;
3343
Bram Moolenaard6e39182013-05-21 18:30:34 +02003344 self->win->w_cursor.lnum = lnum;
3345 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003346#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02003347 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003348#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003349 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003350 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003351
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003352 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003353 return 0;
3354 }
3355 else if (strcmp(name, "height") == 0)
3356 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003357 long height;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003358 win_T *savewin;
3359
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003360 if (NumberToLong(valObject, &height, NUMBER_INT))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003361 return -1;
3362
3363#ifdef FEAT_GUI
3364 need_mouse_correct = TRUE;
3365#endif
3366 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003367 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003368
3369 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003370 win_setheight((int) height);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003371 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003372 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003373 return -1;
3374
3375 return 0;
3376 }
3377#ifdef FEAT_VERTSPLIT
3378 else if (strcmp(name, "width") == 0)
3379 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003380 long width;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003381 win_T *savewin;
3382
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003383 if (NumberToLong(valObject, &width, NUMBER_INT))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003384 return -1;
3385
3386#ifdef FEAT_GUI
3387 need_mouse_correct = TRUE;
3388#endif
3389 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003390 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003391
3392 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003393 win_setwidth((int) width);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003394 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003395 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003396 return -1;
3397
3398 return 0;
3399 }
3400#endif
3401 else
3402 {
3403 PyErr_SetString(PyExc_AttributeError, name);
3404 return -1;
3405 }
3406}
3407
3408 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003409WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003410{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003411 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003412 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003413 else
3414 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003415 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003416
Bram Moolenaar6d216452013-05-12 19:00:41 +02003417 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003418 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003419 (self));
3420 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003421 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003422 }
3423}
3424
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003425static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003426 /* name, function, calling, documentation */
3427 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
3428 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003429};
3430
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003431/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003432 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003433 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003434
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003435static PyTypeObject WinListType;
3436static PySequenceMethods WinListAsSeq;
3437
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003438typedef struct
3439{
3440 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003441 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003442} WinListObject;
3443
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003444 static PyObject *
3445WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003446{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003447 WinListObject *self;
3448
3449 self = PyObject_NEW(WinListObject, &WinListType);
3450 self->tabObject = tabObject;
3451 Py_INCREF(tabObject);
3452
3453 return (PyObject *)(self);
3454}
3455
3456 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003457WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003458{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003459 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003460
3461 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02003462 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003463 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02003464 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003465
3466 DESTRUCTOR_FINISH(self);
3467}
3468
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003469 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003470WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003471{
3472 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003473 PyInt n = 0;
3474
Bram Moolenaard6e39182013-05-21 18:30:34 +02003475 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003476 return -1;
3477
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003478 while (w != NULL)
3479 {
3480 ++n;
3481 w = W_NEXT(w);
3482 }
3483
3484 return n;
3485}
3486
3487 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003488WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003489{
3490 win_T *w;
3491
Bram Moolenaard6e39182013-05-21 18:30:34 +02003492 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003493 return NULL;
3494
3495 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003496 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003497 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003498
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003499 PyErr_SET_STRING(PyExc_IndexError, "no such window");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003500 return NULL;
3501}
3502
3503/* Convert a Python string into a Vim line.
3504 *
3505 * The result is in allocated memory. All internal nulls are replaced by
3506 * newline characters. It is an error for the string to contain newline
3507 * characters.
3508 *
3509 * On errors, the Python exception data is set, and NULL is returned.
3510 */
3511 static char *
3512StringToLine(PyObject *obj)
3513{
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003514 char *str;
3515 char *save;
3516 PyObject *bytes = NULL;
3517 Py_ssize_t len;
3518 PyInt i;
3519 char *p;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003520
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003521 if (PyBytes_Check(obj))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003522 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003523 if (PyBytes_AsStringAndSize(obj, &str, &len) == -1
3524 || str == NULL)
3525 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003526 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003527 else if (PyUnicode_Check(obj))
3528 {
3529 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL)))
3530 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003531
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003532 if(PyBytes_AsStringAndSize(bytes, &str, &len) == -1
3533 || str == NULL)
3534 {
3535 Py_DECREF(bytes);
3536 return NULL;
3537 }
3538 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003539
3540 /*
3541 * Error checking: String must not contain newlines, as we
3542 * are replacing a single line, and we must replace it with
3543 * a single line.
3544 * A trailing newline is removed, so that append(f.readlines()) works.
3545 */
3546 p = memchr(str, '\n', len);
3547 if (p != NULL)
3548 {
3549 if (p == str + len - 1)
3550 --len;
3551 else
3552 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003553 PyErr_SET_VIM("string cannot contain newlines");
Bram Moolenaar841fbd22013-06-23 14:37:07 +02003554 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003555 return NULL;
3556 }
3557 }
3558
3559 /* Create a copy of the string, with internal nulls replaced by
3560 * newline characters, as is the vim convention.
3561 */
3562 save = (char *)alloc((unsigned)(len+1));
3563 if (save == NULL)
3564 {
3565 PyErr_NoMemory();
Bram Moolenaar841fbd22013-06-23 14:37:07 +02003566 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003567 return NULL;
3568 }
3569
3570 for (i = 0; i < len; ++i)
3571 {
3572 if (str[i] == '\0')
3573 save[i] = '\n';
3574 else
3575 save[i] = str[i];
3576 }
3577
3578 save[i] = '\0';
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003579 Py_XDECREF(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003580
3581 return save;
3582}
3583
3584/* Get a line from the specified buffer. The line number is
3585 * in Vim format (1-based). The line is returned as a Python
3586 * string object.
3587 */
3588 static PyObject *
3589GetBufferLine(buf_T *buf, PyInt n)
3590{
3591 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3592}
3593
3594
3595/* Get a list of lines from the specified buffer. The line numbers
3596 * are in Vim format (1-based). The range is from lo up to, but not
3597 * including, hi. The list is returned as a Python list of string objects.
3598 */
3599 static PyObject *
3600GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3601{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003602 PyInt i;
3603 PyInt n = hi - lo;
3604 PyObject *list = PyList_New(n);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003605
3606 if (list == NULL)
3607 return NULL;
3608
3609 for (i = 0; i < n; ++i)
3610 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003611 PyObject *string = LineToString(
3612 (char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003613
3614 /* Error check - was the Python string creation OK? */
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003615 if (string == NULL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003616 {
3617 Py_DECREF(list);
3618 return NULL;
3619 }
3620
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003621 PyList_SET_ITEM(list, i, string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003622 }
3623
3624 /* The ownership of the Python list is passed to the caller (ie,
3625 * the caller should Py_DECREF() the object when it is finished
3626 * with it).
3627 */
3628
3629 return list;
3630}
3631
3632/*
3633 * Check if deleting lines made the cursor position invalid.
3634 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3635 * deleted).
3636 */
3637 static void
3638py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3639{
3640 if (curwin->w_cursor.lnum >= lo)
3641 {
3642 /* Adjust the cursor position if it's in/after the changed
3643 * lines. */
3644 if (curwin->w_cursor.lnum >= hi)
3645 {
3646 curwin->w_cursor.lnum += extra;
3647 check_cursor_col();
3648 }
3649 else if (extra < 0)
3650 {
3651 curwin->w_cursor.lnum = lo;
3652 check_cursor();
3653 }
3654 else
3655 check_cursor_col();
3656 changed_cline_bef_curs();
3657 }
3658 invalidate_botline();
3659}
3660
Bram Moolenaar19e60942011-06-19 00:27:51 +02003661/*
3662 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003663 * in Vim format (1-based). The replacement line is given as
3664 * a Python string object. The object is checked for validity
3665 * and correct format. Errors are returned as a value of FAIL.
3666 * The return value is OK on success.
3667 * If OK is returned and len_change is not NULL, *len_change
3668 * is set to the change in the buffer length.
3669 */
3670 static int
3671SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3672{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003673 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003674 * There are three cases:
3675 * 1. NULL, or None - this is a deletion.
3676 * 2. A string - this is a replacement.
3677 * 3. Anything else - this is an error.
3678 */
3679 if (line == Py_None || line == NULL)
3680 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003681 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003682
3683 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003684 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003685
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003686 VimTryStart();
3687
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003688 if (u_savedel((linenr_T)n, 1L) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003689 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003690 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003691 RAISE_LINE_FAIL("delete");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003692 else
3693 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003694 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003695 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3696 deleted_lines_mark((linenr_T)n, 1L);
3697 }
3698
Bram Moolenaar105bc352013-05-17 16:03:57 +02003699 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003700
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003701 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003702 return FAIL;
3703
3704 if (len_change)
3705 *len_change = -1;
3706
3707 return OK;
3708 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003709 else if (PyBytes_Check(line) || PyUnicode_Check(line))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003710 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003711 char *save = StringToLine(line);
3712 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003713
3714 if (save == NULL)
3715 return FAIL;
3716
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003717 VimTryStart();
3718
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003719 /* We do not need to free "save" if ml_replace() consumes it. */
3720 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003721 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003722
3723 if (u_savesub((linenr_T)n) == FAIL)
3724 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003725 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003726 vim_free(save);
3727 }
3728 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3729 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003730 RAISE_LINE_FAIL("replace");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003731 vim_free(save);
3732 }
3733 else
3734 changed_bytes((linenr_T)n, 0);
3735
Bram Moolenaar105bc352013-05-17 16:03:57 +02003736 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003737
3738 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003739 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003740 check_cursor_col();
3741
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003742 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003743 return FAIL;
3744
3745 if (len_change)
3746 *len_change = 0;
3747
3748 return OK;
3749 }
3750 else
3751 {
3752 PyErr_BadArgument();
3753 return FAIL;
3754 }
3755}
3756
Bram Moolenaar19e60942011-06-19 00:27:51 +02003757/* Replace a range of lines in the specified buffer. The line numbers are in
3758 * Vim format (1-based). The range is from lo up to, but not including, hi.
3759 * The replacement lines are given as a Python list of string objects. The
3760 * list is checked for validity and correct format. Errors are returned as a
3761 * value of FAIL. The return value is OK on success.
3762 * If OK is returned and len_change is not NULL, *len_change
3763 * is set to the change in the buffer length.
3764 */
3765 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003766SetBufferLineList(
3767 buf_T *buf,
3768 PyInt lo,
3769 PyInt hi,
3770 PyObject *list,
3771 PyInt *len_change)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003772{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003773 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003774 * There are three cases:
3775 * 1. NULL, or None - this is a deletion.
3776 * 2. A list - this is a replacement.
3777 * 3. Anything else - this is an error.
3778 */
3779 if (list == Py_None || list == NULL)
3780 {
3781 PyInt i;
3782 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003783 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003784
3785 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003786 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003787 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003788
3789 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003790 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003791 else
3792 {
3793 for (i = 0; i < n; ++i)
3794 {
3795 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3796 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003797 RAISE_LINE_FAIL("delete");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003798 break;
3799 }
3800 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003801 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003802 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3803 deleted_lines_mark((linenr_T)lo, (long)i);
3804 }
3805
Bram Moolenaar105bc352013-05-17 16:03:57 +02003806 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003807
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003808 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003809 return FAIL;
3810
3811 if (len_change)
3812 *len_change = -n;
3813
3814 return OK;
3815 }
3816 else if (PyList_Check(list))
3817 {
3818 PyInt i;
3819 PyInt new_len = PyList_Size(list);
3820 PyInt old_len = hi - lo;
3821 PyInt extra = 0; /* lines added to text, can be negative */
3822 char **array;
3823 buf_T *savebuf;
3824
3825 if (new_len == 0) /* avoid allocating zero bytes */
3826 array = NULL;
3827 else
3828 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003829 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003830 if (array == NULL)
3831 {
3832 PyErr_NoMemory();
3833 return FAIL;
3834 }
3835 }
3836
3837 for (i = 0; i < new_len; ++i)
3838 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003839 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003840
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003841 if (!(line = PyList_GetItem(list, i)) ||
3842 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003843 {
3844 while (i)
3845 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003846 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003847 return FAIL;
3848 }
3849 }
3850
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003851 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003852 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003853
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003854 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003855 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003856
3857 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003858 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003859
3860 /* If the size of the range is reducing (ie, new_len < old_len) we
3861 * need to delete some old_len. We do this at the start, by
3862 * repeatedly deleting line "lo".
3863 */
3864 if (!PyErr_Occurred())
3865 {
3866 for (i = 0; i < old_len - new_len; ++i)
3867 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3868 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003869 RAISE_LINE_FAIL("delete");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003870 break;
3871 }
3872 extra -= i;
3873 }
3874
3875 /* For as long as possible, replace the existing old_len with the
3876 * new old_len. This is a more efficient operation, as it requires
3877 * less memory allocation and freeing.
3878 */
3879 if (!PyErr_Occurred())
3880 {
3881 for (i = 0; i < old_len && i < new_len; ++i)
3882 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3883 == FAIL)
3884 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003885 RAISE_LINE_FAIL("replace");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003886 break;
3887 }
3888 }
3889 else
3890 i = 0;
3891
3892 /* Now we may need to insert the remaining new old_len. If we do, we
3893 * must free the strings as we finish with them (we can't pass the
3894 * responsibility to vim in this case).
3895 */
3896 if (!PyErr_Occurred())
3897 {
3898 while (i < new_len)
3899 {
3900 if (ml_append((linenr_T)(lo + i - 1),
3901 (char_u *)array[i], 0, FALSE) == FAIL)
3902 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003903 RAISE_LINE_FAIL("insert");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003904 break;
3905 }
3906 vim_free(array[i]);
3907 ++i;
3908 ++extra;
3909 }
3910 }
3911
3912 /* Free any left-over old_len, as a result of an error */
3913 while (i < new_len)
3914 {
3915 vim_free(array[i]);
3916 ++i;
3917 }
3918
3919 /* Free the array of old_len. All of its contents have now
3920 * been dealt with (either freed, or the responsibility passed
3921 * to vim.
3922 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003923 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003924
3925 /* Adjust marks. Invalidate any which lie in the
3926 * changed range, and move any in the remainder of the buffer.
3927 */
3928 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3929 (long)MAXLNUM, (long)extra);
3930 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3931
Bram Moolenaar105bc352013-05-17 16:03:57 +02003932 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003933 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3934
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003935 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003936 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003937
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003938 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003939 return FAIL;
3940
3941 if (len_change)
3942 *len_change = new_len - old_len;
3943
3944 return OK;
3945 }
3946 else
3947 {
3948 PyErr_BadArgument();
3949 return FAIL;
3950 }
3951}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003952
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003953/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003954 * The line number is in Vim format (1-based). The lines to be inserted are
3955 * given as a Python list of string objects or as a single string. The lines
3956 * to be added are checked for validity and correct format. Errors are
3957 * returned as a value of FAIL. The return value is OK on success.
3958 * If OK is returned and len_change is not NULL, *len_change
3959 * is set to the change in the buffer length.
3960 */
3961 static int
3962InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3963{
3964 /* First of all, we check the type of the supplied Python object.
3965 * It must be a string or a list, or the call is in error.
3966 */
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003967 if (PyBytes_Check(lines) || PyUnicode_Check(lines))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003968 {
3969 char *str = StringToLine(lines);
3970 buf_T *savebuf;
3971
3972 if (str == NULL)
3973 return FAIL;
3974
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003975 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003976 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003977 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003978
3979 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003980 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003981 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02003982 RAISE_LINE_FAIL("insert");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003983 else
3984 appended_lines_mark((linenr_T)n, 1L);
3985
3986 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003987 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003988 update_screen(VALID);
3989
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003990 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003991 return FAIL;
3992
3993 if (len_change)
3994 *len_change = 1;
3995
3996 return OK;
3997 }
3998 else if (PyList_Check(lines))
3999 {
4000 PyInt i;
4001 PyInt size = PyList_Size(lines);
4002 char **array;
4003 buf_T *savebuf;
4004
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004005 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004006 if (array == NULL)
4007 {
4008 PyErr_NoMemory();
4009 return FAIL;
4010 }
4011
4012 for (i = 0; i < size; ++i)
4013 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004014 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004015
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004016 if (!(line = PyList_GetItem(lines, i)) ||
4017 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004018 {
4019 while (i)
4020 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004021 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004022 return FAIL;
4023 }
4024 }
4025
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004026 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004027 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02004028 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004029
4030 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004031 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004032 else
4033 {
4034 for (i = 0; i < size; ++i)
4035 {
4036 if (ml_append((linenr_T)(n + i),
4037 (char_u *)array[i], 0, FALSE) == FAIL)
4038 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004039 RAISE_LINE_FAIL("insert");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004040
4041 /* Free the rest of the lines */
4042 while (i < size)
4043 vim_free(array[i++]);
4044
4045 break;
4046 }
4047 vim_free(array[i]);
4048 }
4049 if (i > 0)
4050 appended_lines_mark((linenr_T)n, (long)i);
4051 }
4052
4053 /* Free the array of lines. All of its contents have now
4054 * been freed.
4055 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004056 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004057
Bram Moolenaar105bc352013-05-17 16:03:57 +02004058 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004059 update_screen(VALID);
4060
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004061 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004062 return FAIL;
4063
4064 if (len_change)
4065 *len_change = size;
4066
4067 return OK;
4068 }
4069 else
4070 {
4071 PyErr_BadArgument();
4072 return FAIL;
4073 }
4074}
4075
4076/*
4077 * Common routines for buffers and line ranges
4078 * -------------------------------------------
4079 */
4080
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004081typedef struct
4082{
4083 PyObject_HEAD
4084 buf_T *buf;
4085} BufferObject;
4086
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004087 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02004088CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004089{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004090 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004091 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004092 PyErr_SET_VIM("attempt to refer to deleted buffer");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004093 return -1;
4094 }
4095
4096 return 0;
4097}
4098
4099 static PyObject *
4100RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
4101{
4102 if (CheckBuffer(self))
4103 return NULL;
4104
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004105 if (end == -1)
4106 end = self->buf->b_ml.ml_line_count;
4107
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004108 if (n < 0)
4109 n += end - start + 1;
4110
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004111 if (n < 0 || n > end - start)
4112 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004113 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004114 return NULL;
4115 }
4116
4117 return GetBufferLine(self->buf, n+start);
4118}
4119
4120 static PyObject *
4121RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
4122{
4123 PyInt size;
4124
4125 if (CheckBuffer(self))
4126 return NULL;
4127
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004128 if (end == -1)
4129 end = self->buf->b_ml.ml_line_count;
4130
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004131 size = end - start + 1;
4132
4133 if (lo < 0)
4134 lo = 0;
4135 else if (lo > size)
4136 lo = size;
4137 if (hi < 0)
4138 hi = 0;
4139 if (hi < lo)
4140 hi = lo;
4141 else if (hi > size)
4142 hi = size;
4143
4144 return GetBufferLineList(self->buf, lo+start, hi+start);
4145}
4146
4147 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004148RBAsItem(
4149 BufferObject *self,
4150 PyInt n,
4151 PyObject *valObject,
4152 PyInt start,
4153 PyInt end,
4154 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004155{
4156 PyInt len_change;
4157
4158 if (CheckBuffer(self))
4159 return -1;
4160
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004161 if (end == -1)
4162 end = self->buf->b_ml.ml_line_count;
4163
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004164 if (n < 0)
4165 n += end - start + 1;
4166
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004167 if (n < 0 || n > end - start)
4168 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004169 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004170 return -1;
4171 }
4172
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004173 if (SetBufferLine(self->buf, n+start, valObject, &len_change) == FAIL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004174 return -1;
4175
4176 if (new_end)
4177 *new_end = end + len_change;
4178
4179 return 0;
4180}
4181
Bram Moolenaar19e60942011-06-19 00:27:51 +02004182 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004183RBAsSlice(
4184 BufferObject *self,
4185 PyInt lo,
4186 PyInt hi,
4187 PyObject *valObject,
4188 PyInt start,
4189 PyInt end,
4190 PyInt *new_end)
Bram Moolenaar19e60942011-06-19 00:27:51 +02004191{
4192 PyInt size;
4193 PyInt len_change;
4194
4195 /* Self must be a valid buffer */
4196 if (CheckBuffer(self))
4197 return -1;
4198
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004199 if (end == -1)
4200 end = self->buf->b_ml.ml_line_count;
4201
Bram Moolenaar19e60942011-06-19 00:27:51 +02004202 /* Sort out the slice range */
4203 size = end - start + 1;
4204
4205 if (lo < 0)
4206 lo = 0;
4207 else if (lo > size)
4208 lo = size;
4209 if (hi < 0)
4210 hi = 0;
4211 if (hi < lo)
4212 hi = lo;
4213 else if (hi > size)
4214 hi = size;
4215
4216 if (SetBufferLineList(self->buf, lo + start, hi + start,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004217 valObject, &len_change) == FAIL)
Bram Moolenaar19e60942011-06-19 00:27:51 +02004218 return -1;
4219
4220 if (new_end)
4221 *new_end = end + len_change;
4222
4223 return 0;
4224}
4225
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004226
4227 static PyObject *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004228RBAppend(
4229 BufferObject *self,
4230 PyObject *args,
4231 PyInt start,
4232 PyInt end,
4233 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004234{
4235 PyObject *lines;
4236 PyInt len_change;
4237 PyInt max;
4238 PyInt n;
4239
4240 if (CheckBuffer(self))
4241 return NULL;
4242
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004243 if (end == -1)
4244 end = self->buf->b_ml.ml_line_count;
4245
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004246 max = n = end - start + 1;
4247
4248 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
4249 return NULL;
4250
4251 if (n < 0 || n > max)
4252 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004253 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004254 return NULL;
4255 }
4256
4257 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
4258 return NULL;
4259
4260 if (new_end)
4261 *new_end = end + len_change;
4262
4263 Py_INCREF(Py_None);
4264 return Py_None;
4265}
4266
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004267/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004268 */
4269
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004270static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004271static PySequenceMethods RangeAsSeq;
4272static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004273
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004274typedef struct
4275{
4276 PyObject_HEAD
4277 BufferObject *buf;
4278 PyInt start;
4279 PyInt end;
4280} RangeObject;
4281
4282 static PyObject *
4283RangeNew(buf_T *buf, PyInt start, PyInt end)
4284{
4285 BufferObject *bufr;
4286 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004287 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004288 if (self == NULL)
4289 return NULL;
4290
4291 bufr = (BufferObject *)BufferNew(buf);
4292 if (bufr == NULL)
4293 {
4294 Py_DECREF(self);
4295 return NULL;
4296 }
4297 Py_INCREF(bufr);
4298
4299 self->buf = bufr;
4300 self->start = start;
4301 self->end = end;
4302
4303 return (PyObject *)(self);
4304}
4305
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004306 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004307RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004308{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004309 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004310 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02004311 PyObject_GC_Del((void *)(self));
4312}
4313
4314 static int
4315RangeTraverse(RangeObject *self, visitproc visit, void *arg)
4316{
4317 Py_VISIT(((PyObject *)(self->buf)));
4318 return 0;
4319}
4320
4321 static int
4322RangeClear(RangeObject *self)
4323{
4324 Py_CLEAR(self->buf);
4325 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004326}
4327
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004328 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004329RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004330{
4331 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004332 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004333 return -1; /* ??? */
4334
Bram Moolenaard6e39182013-05-21 18:30:34 +02004335 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004336}
4337
4338 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004339RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004340{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004341 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004342}
4343
4344 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004345RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004346{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004347 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004348}
4349
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004350static char *RangeAttrs[] = {
4351 "start", "end",
4352 NULL
4353};
4354
4355 static PyObject *
4356RangeDir(PyObject *self)
4357{
4358 return ObjectDir(self, RangeAttrs);
4359}
4360
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004361 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004362RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004363{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004364 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004365}
4366
4367 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004368RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004369{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004370 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004371 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
4372 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004373 else
4374 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004375 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004376
4377 if (name == NULL)
4378 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004379
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004380 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02004381 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004382 }
4383}
4384
4385static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004386 /* name, function, calling, documentation */
4387 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004388 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
4389 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004390};
4391
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004392static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004393static PySequenceMethods BufferAsSeq;
4394static PyMappingMethods BufferAsMapping;
4395
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004396 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02004397BufferNew(buf_T *buf)
4398{
4399 /* We need to handle deletion of buffers underneath us.
4400 * If we add a "b_python*_ref" field to the buf_T structure,
4401 * then we can get at it in buf_freeall() in vim. We then
4402 * need to create only ONE Python object per buffer - if
4403 * we try to create a second, just INCREF the existing one
4404 * and return it. The (single) Python object referring to
4405 * the buffer is stored in "b_python*_ref".
4406 * Question: what to do on a buf_freeall(). We'll probably
4407 * have to either delete the Python object (DECREF it to
4408 * zero - a bad idea, as it leaves dangling refs!) or
4409 * set the buf_T * value to an invalid value (-1?), which
4410 * means we need checks in all access functions... Bah.
4411 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004412 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02004413 * b_python_ref and b_python3_ref fields respectively.
4414 */
4415
4416 BufferObject *self;
4417
4418 if (BUF_PYTHON_REF(buf) != NULL)
4419 {
4420 self = BUF_PYTHON_REF(buf);
4421 Py_INCREF(self);
4422 }
4423 else
4424 {
4425 self = PyObject_NEW(BufferObject, &BufferType);
4426 if (self == NULL)
4427 return NULL;
4428 self->buf = buf;
4429 BUF_PYTHON_REF(buf) = self;
4430 }
4431
4432 return (PyObject *)(self);
4433}
4434
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004435 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004436BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004437{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004438 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
4439 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004440
4441 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004442}
4443
Bram Moolenaar971db462013-05-12 18:44:48 +02004444 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004445BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02004446{
4447 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004448 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02004449 return -1; /* ??? */
4450
Bram Moolenaard6e39182013-05-21 18:30:34 +02004451 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02004452}
4453
4454 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004455BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02004456{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004457 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004458}
4459
4460 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004461BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02004462{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004463 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004464}
4465
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004466static char *BufferAttrs[] = {
4467 "name", "number", "vars", "options", "valid",
4468 NULL
4469};
4470
4471 static PyObject *
4472BufferDir(PyObject *self)
4473{
4474 return ObjectDir(self, BufferAttrs);
4475}
4476
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004477 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004478BufferAttrValid(BufferObject *self, char *name)
4479{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004480 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004481
4482 if (strcmp(name, "valid") != 0)
4483 return NULL;
4484
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004485 ret = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
4486 Py_INCREF(ret);
4487 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004488}
4489
4490 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004491BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004492{
4493 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02004494 return PyString_FromString((self->buf->b_ffname == NULL
4495 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004496 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004497 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004498 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004499 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004500 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004501 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
4502 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004503 else if (strcmp(name, "__members__") == 0)
4504 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004505 else
4506 return NULL;
4507}
4508
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004509 static int
4510BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
4511{
4512 if (CheckBuffer(self))
4513 return -1;
4514
4515 if (strcmp(name, "name") == 0)
4516 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004517 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004518 aco_save_T aco;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004519 int ren_ret;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004520 PyObject *todecref;
4521
4522 if (!(val = StringToChars(valObject, &todecref)))
4523 return -1;
4524
4525 VimTryStart();
4526 /* Using aucmd_*: autocommands will be executed by rename_buffer */
4527 aucmd_prepbuf(&aco, self->buf);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004528 ren_ret = rename_buffer(val);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004529 aucmd_restbuf(&aco);
4530 Py_XDECREF(todecref);
4531 if (VimTryEnd())
4532 return -1;
4533
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004534 if (ren_ret == FAIL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004535 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004536 PyErr_SET_VIM("failed to rename buffer");
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004537 return -1;
4538 }
4539 return 0;
4540 }
4541 else
4542 {
4543 PyErr_SetString(PyExc_AttributeError, name);
4544 return -1;
4545 }
4546}
4547
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004548 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004549BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004550{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004551 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004552}
4553
4554 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02004555BufferMark(BufferObject *self, PyObject *pmarkObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004556{
4557 pos_T *posp;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004558 char_u *pmark;
4559 char_u mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004560 buf_T *savebuf;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004561 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004562
Bram Moolenaard6e39182013-05-21 18:30:34 +02004563 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004564 return NULL;
4565
Bram Moolenaar389a1792013-06-23 13:00:44 +02004566 if (!(pmark = StringToChars(pmarkObject, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004567 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004568
Bram Moolenaar389a1792013-06-23 13:00:44 +02004569 if (pmark[0] == '\0' || pmark[1] != '\0')
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004570 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004571 PyErr_SET_STRING(PyExc_ValueError,
4572 "mark name must be a single character");
Bram Moolenaar841fbd22013-06-23 14:37:07 +02004573 Py_XDECREF(todecref);
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004574 return NULL;
4575 }
4576
4577 mark = *pmark;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004578
4579 Py_XDECREF(todecref);
4580
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004581 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004582 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004583 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004584 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004585 if (VimTryEnd())
4586 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004587
4588 if (posp == NULL)
4589 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004590 PyErr_SET_VIM("invalid mark name");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004591 return NULL;
4592 }
4593
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004594 if (posp->lnum <= 0)
4595 {
4596 /* Or raise an error? */
4597 Py_INCREF(Py_None);
4598 return Py_None;
4599 }
4600
4601 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4602}
4603
4604 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004605BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004606{
4607 PyInt start;
4608 PyInt end;
4609
Bram Moolenaard6e39182013-05-21 18:30:34 +02004610 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004611 return NULL;
4612
4613 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4614 return NULL;
4615
Bram Moolenaard6e39182013-05-21 18:30:34 +02004616 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004617}
4618
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004619 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004620BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004621{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004622 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004623 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004624 else
4625 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004626 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004627
4628 if (name == NULL)
4629 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004630
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004631 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004632 }
4633}
4634
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004635static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004636 /* name, function, calling, documentation */
4637 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02004638 {"mark", (PyCFunction)BufferMark, METH_O, "Return (row,col) representing position of named mark" },
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004639 {"range", (PyCFunction)BufferRange, METH_VARARGS, "Return a range object which represents the part of the given buffer between line numbers s and e" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004640 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4641 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004642};
4643
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004644/*
4645 * Buffer list object - Implementation
4646 */
4647
4648static PyTypeObject BufMapType;
4649
4650typedef struct
4651{
4652 PyObject_HEAD
4653} BufMapObject;
4654
4655 static PyInt
4656BufMapLength(PyObject *self UNUSED)
4657{
4658 buf_T *b = firstbuf;
4659 PyInt n = 0;
4660
4661 while (b)
4662 {
4663 ++n;
4664 b = b->b_next;
4665 }
4666
4667 return n;
4668}
4669
4670 static PyObject *
4671BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4672{
4673 buf_T *b;
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004674 long bnr;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004675
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004676 if (NumberToLong(keyObject, &bnr, NUMBER_INT|NUMBER_NATURAL))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004677 return NULL;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004678
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004679 b = buflist_findnr((int) bnr);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004680
4681 if (b)
4682 return BufferNew(b);
4683 else
4684 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004685 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004686 return NULL;
4687 }
4688}
4689
4690 static void
4691BufMapIterDestruct(PyObject *buffer)
4692{
4693 /* Iteration was stopped before all buffers were processed */
4694 if (buffer)
4695 {
4696 Py_DECREF(buffer);
4697 }
4698}
4699
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004700 static int
4701BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4702{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004703 if (buffer)
4704 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004705 return 0;
4706}
4707
4708 static int
4709BufMapIterClear(PyObject **buffer)
4710{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004711 if (*buffer)
4712 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004713 return 0;
4714}
4715
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004716 static PyObject *
4717BufMapIterNext(PyObject **buffer)
4718{
4719 PyObject *next;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004720 PyObject *ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004721
4722 if (!*buffer)
4723 return NULL;
4724
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004725 ret = *buffer;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004726
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004727 if (CheckBuffer((BufferObject *)(ret)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004728 {
4729 *buffer = NULL;
4730 return NULL;
4731 }
4732
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004733 if (!((BufferObject *)(ret))->buf->b_next)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004734 next = NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004735 else if (!(next = BufferNew(((BufferObject *)(ret))->buf->b_next)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004736 return NULL;
4737 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004738 /* Do not increment reference: we no longer hold it (decref), but whoever
4739 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004740 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004741}
4742
4743 static PyObject *
4744BufMapIter(PyObject *self UNUSED)
4745{
4746 PyObject *buffer;
4747
4748 buffer = BufferNew(firstbuf);
4749 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004750 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4751 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004752}
4753
4754static PyMappingMethods BufMapAsMapping = {
4755 (lenfunc) BufMapLength,
4756 (binaryfunc) BufMapItem,
4757 (objobjargproc) 0,
4758};
4759
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004760/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004761 */
4762
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004763static char *CurrentAttrs[] = {
4764 "buffer", "window", "line", "range", "tabpage",
4765 NULL
4766};
4767
4768 static PyObject *
4769CurrentDir(PyObject *self)
4770{
4771 return ObjectDir(self, CurrentAttrs);
4772}
4773
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004774 static PyObject *
4775CurrentGetattr(PyObject *self UNUSED, char *name)
4776{
4777 if (strcmp(name, "buffer") == 0)
4778 return (PyObject *)BufferNew(curbuf);
4779 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004780 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004781 else if (strcmp(name, "tabpage") == 0)
4782 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004783 else if (strcmp(name, "line") == 0)
4784 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4785 else if (strcmp(name, "range") == 0)
4786 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004787 else if (strcmp(name, "__members__") == 0)
4788 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004789 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004790#if PY_MAJOR_VERSION < 3
4791 return Py_FindMethod(WindowMethods, self, name);
4792#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004793 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004794#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004795}
4796
4797 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004798CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *valObject)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004799{
4800 if (strcmp(name, "line") == 0)
4801 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004802 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, valObject,
4803 NULL) == FAIL)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004804 return -1;
4805
4806 return 0;
4807 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004808 else if (strcmp(name, "buffer") == 0)
4809 {
4810 int count;
4811
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004812 if (valObject->ob_type != &BufferType)
Bram Moolenaare7614592013-05-15 15:51:08 +02004813 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004814 PyErr_FORMAT(PyExc_TypeError,
4815 "expected vim.Buffer object, but got %s",
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004816 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02004817 return -1;
4818 }
4819
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004820 if (CheckBuffer((BufferObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02004821 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004822 count = ((BufferObject *)(valObject))->buf->b_fnum;
Bram Moolenaare7614592013-05-15 15:51:08 +02004823
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004824 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004825 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4826 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004827 if (VimTryEnd())
4828 return -1;
Bram Moolenaarc476e522013-06-23 13:46:40 +02004829 PyErr_VIM_FORMAT("failed to switch to buffer %d", count);
Bram Moolenaare7614592013-05-15 15:51:08 +02004830 return -1;
4831 }
4832
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004833 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004834 }
4835 else if (strcmp(name, "window") == 0)
4836 {
4837 int count;
4838
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004839 if (valObject->ob_type != &WindowType)
Bram Moolenaare7614592013-05-15 15:51:08 +02004840 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004841 PyErr_FORMAT(PyExc_TypeError,
4842 "expected vim.Window object, but got %s",
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004843 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02004844 return -1;
4845 }
4846
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004847 if (CheckWindow((WindowObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02004848 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004849 count = get_win_number(((WindowObject *)(valObject))->win, firstwin);
Bram Moolenaare7614592013-05-15 15:51:08 +02004850
4851 if (!count)
4852 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004853 PyErr_SET_STRING(PyExc_ValueError,
4854 "failed to find window in the current tab page");
Bram Moolenaare7614592013-05-15 15:51:08 +02004855 return -1;
4856 }
4857
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004858 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004859 win_goto(((WindowObject *)(valObject))->win);
4860 if (((WindowObject *)(valObject))->win != curwin)
Bram Moolenaare7614592013-05-15 15:51:08 +02004861 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004862 if (VimTryEnd())
4863 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004864 PyErr_SET_STRING(PyExc_RuntimeError,
4865 "did not switch to the specified window");
Bram Moolenaare7614592013-05-15 15:51:08 +02004866 return -1;
4867 }
4868
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004869 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004870 }
4871 else if (strcmp(name, "tabpage") == 0)
4872 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004873 if (valObject->ob_type != &TabPageType)
Bram Moolenaare7614592013-05-15 15:51:08 +02004874 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004875 PyErr_FORMAT(PyExc_TypeError,
4876 "expected vim.TabPage object, but got %s",
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004877 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02004878 return -1;
4879 }
4880
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004881 if (CheckTabPage((TabPageObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02004882 return -1;
4883
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004884 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004885 goto_tabpage_tp(((TabPageObject *)(valObject))->tab, TRUE, TRUE);
4886 if (((TabPageObject *)(valObject))->tab != curtab)
Bram Moolenaare7614592013-05-15 15:51:08 +02004887 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004888 if (VimTryEnd())
4889 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004890 PyErr_SET_STRING(PyExc_RuntimeError,
4891 "did not switch to the specified tab page");
Bram Moolenaare7614592013-05-15 15:51:08 +02004892 return -1;
4893 }
4894
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004895 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004896 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004897 else
4898 {
4899 PyErr_SetString(PyExc_AttributeError, name);
4900 return -1;
4901 }
4902}
4903
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004904static struct PyMethodDef CurrentMethods[] = {
4905 /* name, function, calling, documentation */
4906 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4907 { NULL, NULL, 0, NULL}
4908};
4909
Bram Moolenaardb913952012-06-29 12:54:53 +02004910 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004911init_range_cmd(exarg_T *eap)
4912{
4913 RangeStart = eap->line1;
4914 RangeEnd = eap->line2;
4915}
4916
4917 static void
4918init_range_eval(typval_T *rettv UNUSED)
4919{
4920 RangeStart = (PyInt) curwin->w_cursor.lnum;
4921 RangeEnd = RangeStart;
4922}
4923
4924 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004925run_cmd(const char *cmd, void *arg UNUSED
4926#ifdef PY_CAN_RECURSE
4927 , PyGILState_STATE *pygilstate UNUSED
4928#endif
4929 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004930{
4931 PyRun_SimpleString((char *) cmd);
4932}
4933
4934static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4935static int code_hdr_len = 30;
4936
4937 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004938run_do(const char *cmd, void *arg UNUSED
4939#ifdef PY_CAN_RECURSE
4940 , PyGILState_STATE *pygilstate
4941#endif
4942 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004943{
4944 PyInt lnum;
4945 size_t len;
4946 char *code;
4947 int status;
4948 PyObject *pyfunc, *pymain;
4949
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004950 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004951 {
4952 EMSG(_("cannot save undo information"));
4953 return;
4954 }
4955
4956 len = code_hdr_len + STRLEN(cmd);
4957 code = PyMem_New(char, len + 1);
4958 memcpy(code, code_hdr, code_hdr_len);
4959 STRCPY(code + code_hdr_len, cmd);
4960 status = PyRun_SimpleString(code);
4961 PyMem_Free(code);
4962
4963 if (status)
4964 {
4965 EMSG(_("failed to run the code"));
4966 return;
4967 }
4968
4969 status = 0;
4970 pymain = PyImport_AddModule("__main__");
4971 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004972#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004973 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004974#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004975
4976 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4977 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004978 PyObject *line;
4979 PyObject *linenr;
4980 PyObject *ret;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004981
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004982#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004983 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004984#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004985 if (!(line = GetBufferLine(curbuf, lnum)))
4986 goto err;
4987 if (!(linenr = PyInt_FromLong((long) lnum)))
4988 {
4989 Py_DECREF(line);
4990 goto err;
4991 }
4992 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4993 Py_DECREF(line);
4994 Py_DECREF(linenr);
4995 if (!ret)
4996 goto err;
4997
4998 if (ret != Py_None)
4999 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
5000 goto err;
5001
5002 Py_XDECREF(ret);
5003 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005004#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005005 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005006#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005007 }
5008 goto out;
5009err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005010#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005011 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005012#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005013 PyErr_PrintEx(0);
5014 PythonIO_Flush();
5015 status = 1;
5016out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005017#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005018 if (!status)
5019 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005020#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005021 Py_DECREF(pyfunc);
5022 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
5023 if (status)
5024 return;
5025 check_cursor();
5026 update_curbuf(NOT_VALID);
5027}
5028
5029 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005030run_eval(const char *cmd, typval_T *rettv
5031#ifdef PY_CAN_RECURSE
5032 , PyGILState_STATE *pygilstate UNUSED
5033#endif
5034 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005035{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005036 PyObject *run_ret;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005037
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005038 run_ret = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
5039 if (run_ret == NULL)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005040 {
5041 if (PyErr_Occurred() && !msg_silent)
5042 PyErr_PrintEx(0);
5043 EMSG(_("E858: Eval did not return a valid python object"));
5044 }
5045 else
5046 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005047 if (ConvertFromPyObject(run_ret, rettv) == -1)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005048 EMSG(_("E859: Failed to convert returned python object to vim value"));
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005049 Py_DECREF(run_ret);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005050 }
5051 PyErr_Clear();
5052}
5053
5054 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02005055set_ref_in_py(const int copyID)
5056{
5057 pylinkedlist_T *cur;
5058 dict_T *dd;
5059 list_T *ll;
5060
5061 if (lastdict != NULL)
5062 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
5063 {
5064 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
5065 if (dd->dv_copyID != copyID)
5066 {
5067 dd->dv_copyID = copyID;
5068 set_ref_in_ht(&dd->dv_hashtab, copyID);
5069 }
5070 }
5071
5072 if (lastlist != NULL)
5073 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
5074 {
5075 ll = ((ListObject *) (cur->pll_obj))->list;
5076 if (ll->lv_copyID != copyID)
5077 {
5078 ll->lv_copyID = copyID;
5079 set_ref_in_list(ll, copyID);
5080 }
5081 }
5082}
5083
5084 static int
5085set_string_copy(char_u *str, typval_T *tv)
5086{
5087 tv->vval.v_string = vim_strsave(str);
5088 if (tv->vval.v_string == NULL)
5089 {
5090 PyErr_NoMemory();
5091 return -1;
5092 }
5093 return 0;
5094}
5095
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005096 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005097pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005098{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005099 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005100 char_u *key;
5101 dictitem_T *di;
5102 PyObject *keyObject;
5103 PyObject *valObject;
5104 Py_ssize_t iter = 0;
5105
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005106 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005107 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005108
5109 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005110 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005111
5112 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
5113 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005114 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005115
Bram Moolenaara03e6312013-05-29 22:49:26 +02005116 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005117 {
5118 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005119 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005120 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005121
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005122 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005123 {
5124 dict_unref(dict);
5125 return -1;
5126 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005127
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005128 if (*key == NUL)
5129 {
5130 dict_unref(dict);
5131 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005132 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005133 return -1;
5134 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005135
5136 di = dictitem_alloc(key);
5137
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005138 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005139
5140 if (di == NULL)
5141 {
5142 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005143 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005144 return -1;
5145 }
5146 di->di_tv.v_lock = 0;
5147
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005148 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005149 {
5150 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005151 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005152 return -1;
5153 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005154
5155 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005156 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005157 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara03e6312013-05-29 22:49:26 +02005158 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005159 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005160 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005161 return -1;
5162 }
5163 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005164
5165 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005166 return 0;
5167}
5168
5169 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005170pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005171{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005172 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005173 char_u *key;
5174 dictitem_T *di;
5175 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005176 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005177 PyObject *keyObject;
5178 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005179
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005180 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005181 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005182
5183 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005184 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005185
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005186 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005187 {
5188 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005189 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005190 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005191
5192 if (!(iterator = PyObject_GetIter(list)))
5193 {
5194 dict_unref(dict);
5195 Py_DECREF(list);
5196 return -1;
5197 }
5198 Py_DECREF(list);
5199
5200 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005201 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005202 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005203
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005204 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005205 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005206 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005207 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005208 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005209 return -1;
5210 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005211
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005212 if (*key == NUL)
5213 {
5214 Py_DECREF(keyObject);
5215 Py_DECREF(iterator);
5216 Py_XDECREF(todecref);
5217 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005218 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005219 return -1;
5220 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005221
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005222 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005223 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005224 Py_DECREF(keyObject);
5225 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005226 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005227 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005228 return -1;
5229 }
5230
5231 di = dictitem_alloc(key);
5232
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005233 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005234 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005235
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005236 if (di == NULL)
5237 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005238 Py_DECREF(iterator);
5239 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005240 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005241 PyErr_NoMemory();
5242 return -1;
5243 }
5244 di->di_tv.v_lock = 0;
5245
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005246 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005247 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005248 Py_DECREF(iterator);
5249 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005250 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005251 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005252 return -1;
5253 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02005254
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005255 Py_DECREF(valObject);
5256
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005257 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005258 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005259 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005260 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005261 dictitem_free(di);
5262 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005263 return -1;
5264 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005265 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005266 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005267 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005268 return 0;
5269}
5270
5271 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005272pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005273{
5274 list_T *l;
5275
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005276 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005277 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005278
5279 tv->v_type = VAR_LIST;
5280 tv->vval.v_list = l;
5281
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005282 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005283 {
5284 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005285 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005286 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005287
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005288 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005289 return 0;
5290}
5291
Bram Moolenaardb913952012-06-29 12:54:53 +02005292typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
5293
5294 static int
5295convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005296 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005297{
5298 PyObject *capsule;
5299 char hexBuf[sizeof(void *) * 2 + 3];
5300
5301 sprintf(hexBuf, "%p", obj);
5302
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005303# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005304 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005305# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005306 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005307# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02005308 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005309 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005310# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02005311 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02005312# else
5313 capsule = PyCObject_FromVoidPtr(tv, NULL);
5314# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02005315 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
5316 {
5317 Py_DECREF(capsule);
5318 tv->v_type = VAR_UNKNOWN;
5319 return -1;
5320 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02005321
5322 Py_DECREF(capsule);
5323
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005324 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02005325 {
5326 tv->v_type = VAR_UNKNOWN;
5327 return -1;
5328 }
5329 /* As we are not using copy_tv which increments reference count we must
5330 * do it ourself. */
5331 switch(tv->v_type)
5332 {
5333 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
5334 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
5335 }
5336 }
5337 else
5338 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005339 typval_T *v;
5340
5341# ifdef PY_USE_CAPSULE
5342 v = PyCapsule_GetPointer(capsule, NULL);
5343# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02005344 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005345# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02005346 copy_tv(v, tv);
5347 }
5348 return 0;
5349}
5350
5351 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02005352ConvertFromPyMapping(PyObject *obj, typval_T *tv)
5353{
5354 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005355 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005356
5357 if (!(lookup_dict = PyDict_New()))
5358 return -1;
5359
5360 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
5361 {
5362 tv->v_type = VAR_DICT;
5363 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5364 ++tv->vval.v_dict->dv_refcount;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005365 ret = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005366 }
5367 else if (PyDict_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005368 ret = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02005369 else if (PyMapping_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005370 ret = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02005371 else
5372 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005373 PyErr_FORMAT(PyExc_TypeError,
5374 "unable to convert %s to vim dictionary",
5375 Py_TYPE_NAME(obj));
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005376 ret = -1;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005377 }
5378 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005379 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005380}
5381
5382 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02005383ConvertFromPyObject(PyObject *obj, typval_T *tv)
5384{
5385 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005386 int ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02005387
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005388 if (!(lookup_dict = PyDict_New()))
5389 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005390 ret = _ConvertFromPyObject(obj, tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005391 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005392 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02005393}
5394
5395 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005396_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005397{
Bram Moolenaara9922d62013-05-30 13:01:18 +02005398 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005399 {
5400 tv->v_type = VAR_DICT;
5401 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5402 ++tv->vval.v_dict->dv_refcount;
5403 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02005404 else if (PyType_IsSubtype(obj->ob_type, &ListType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005405 {
5406 tv->v_type = VAR_LIST;
5407 tv->vval.v_list = (((ListObject *)(obj))->list);
5408 ++tv->vval.v_list->lv_refcount;
5409 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02005410 else if (PyType_IsSubtype(obj->ob_type, &FunctionType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005411 {
5412 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
5413 return -1;
5414
5415 tv->v_type = VAR_FUNC;
5416 func_ref(tv->vval.v_string);
5417 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005418 else if (PyBytes_Check(obj))
5419 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005420 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02005421
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005422 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005423 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005424 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005425 return -1;
5426
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005427 if (set_string_copy(str, tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02005428 return -1;
5429
5430 tv->v_type = VAR_STRING;
5431 }
5432 else if (PyUnicode_Check(obj))
5433 {
5434 PyObject *bytes;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005435 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02005436
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005437 bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02005438 if (bytes == NULL)
5439 return -1;
5440
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005441 if(PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005442 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005443 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005444 return -1;
5445
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005446 if (set_string_copy(str, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02005447 {
5448 Py_XDECREF(bytes);
5449 return -1;
5450 }
5451 Py_XDECREF(bytes);
5452
5453 tv->v_type = VAR_STRING;
5454 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02005455#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02005456 else if (PyInt_Check(obj))
5457 {
5458 tv->v_type = VAR_NUMBER;
5459 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005460 if (PyErr_Occurred())
5461 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005462 }
5463#endif
5464 else if (PyLong_Check(obj))
5465 {
5466 tv->v_type = VAR_NUMBER;
5467 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005468 if (PyErr_Occurred())
5469 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005470 }
5471 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005472 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005473#ifdef FEAT_FLOAT
5474 else if (PyFloat_Check(obj))
5475 {
5476 tv->v_type = VAR_FLOAT;
5477 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
5478 }
5479#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005480 else if (PyObject_HasAttrString(obj, "keys"))
5481 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005482 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005483 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005484 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005485 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005486 else if (PyNumber_Check(obj))
5487 {
5488 PyObject *num;
5489
5490 if (!(num = PyNumber_Long(obj)))
5491 return -1;
5492
5493 tv->v_type = VAR_NUMBER;
5494 tv->vval.v_number = (varnumber_T) PyLong_AsLong(num);
5495
5496 Py_DECREF(num);
5497 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005498 else
5499 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005500 PyErr_FORMAT(PyExc_TypeError,
5501 "unable to convert %s to vim structure",
5502 Py_TYPE_NAME(obj));
Bram Moolenaardb913952012-06-29 12:54:53 +02005503 return -1;
5504 }
5505 return 0;
5506}
5507
5508 static PyObject *
5509ConvertToPyObject(typval_T *tv)
5510{
5511 if (tv == NULL)
5512 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005513 PyErr_SET_VIM("internal error: NULL reference passed");
Bram Moolenaardb913952012-06-29 12:54:53 +02005514 return NULL;
5515 }
5516 switch (tv->v_type)
5517 {
5518 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005519 return PyBytes_FromString(tv->vval.v_string == NULL
5520 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005521 case VAR_NUMBER:
5522 return PyLong_FromLong((long) tv->vval.v_number);
5523#ifdef FEAT_FLOAT
5524 case VAR_FLOAT:
5525 return PyFloat_FromDouble((double) tv->vval.v_float);
5526#endif
5527 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005528 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02005529 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02005530 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005531 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005532 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005533 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005534 case VAR_UNKNOWN:
5535 Py_INCREF(Py_None);
5536 return Py_None;
5537 default:
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005538 PyErr_SET_VIM("internal error: invalid value type");
Bram Moolenaardb913952012-06-29 12:54:53 +02005539 return NULL;
5540 }
5541}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005542
5543typedef struct
5544{
5545 PyObject_HEAD
5546} CurrentObject;
5547static PyTypeObject CurrentType;
5548
5549 static void
5550init_structs(void)
5551{
5552 vim_memset(&OutputType, 0, sizeof(OutputType));
5553 OutputType.tp_name = "vim.message";
5554 OutputType.tp_basicsize = sizeof(OutputObject);
5555 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
5556 OutputType.tp_doc = "vim message object";
5557 OutputType.tp_methods = OutputMethods;
5558#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005559 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
5560 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005561 OutputType.tp_alloc = call_PyType_GenericAlloc;
5562 OutputType.tp_new = call_PyType_GenericNew;
5563 OutputType.tp_free = call_PyObject_Free;
5564#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005565 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
5566 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005567#endif
5568
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005569 vim_memset(&IterType, 0, sizeof(IterType));
5570 IterType.tp_name = "vim.iter";
5571 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005572 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005573 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005574 IterType.tp_iter = (getiterfunc)IterIter;
5575 IterType.tp_iternext = (iternextfunc)IterNext;
5576 IterType.tp_dealloc = (destructor)IterDestructor;
5577 IterType.tp_traverse = (traverseproc)IterTraverse;
5578 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005579
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005580 vim_memset(&BufferType, 0, sizeof(BufferType));
5581 BufferType.tp_name = "vim.buffer";
5582 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005583 BufferType.tp_dealloc = (destructor)BufferDestructor;
5584 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005585 BufferType.tp_as_sequence = &BufferAsSeq;
5586 BufferType.tp_as_mapping = &BufferAsMapping;
5587 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5588 BufferType.tp_doc = "vim buffer object";
5589 BufferType.tp_methods = BufferMethods;
5590#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005591 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005592 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005593 BufferType.tp_alloc = call_PyType_GenericAlloc;
5594 BufferType.tp_new = call_PyType_GenericNew;
5595 BufferType.tp_free = call_PyObject_Free;
5596#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005597 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005598 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005599#endif
5600
5601 vim_memset(&WindowType, 0, sizeof(WindowType));
5602 WindowType.tp_name = "vim.window";
5603 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005604 WindowType.tp_dealloc = (destructor)WindowDestructor;
5605 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005606 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005607 WindowType.tp_doc = "vim Window object";
5608 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005609 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5610 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005611#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005612 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5613 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005614 WindowType.tp_alloc = call_PyType_GenericAlloc;
5615 WindowType.tp_new = call_PyType_GenericNew;
5616 WindowType.tp_free = call_PyObject_Free;
5617#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005618 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5619 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005620#endif
5621
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005622 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5623 TabPageType.tp_name = "vim.tabpage";
5624 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005625 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5626 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005627 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5628 TabPageType.tp_doc = "vim tab page object";
5629 TabPageType.tp_methods = TabPageMethods;
5630#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005631 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005632 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5633 TabPageType.tp_new = call_PyType_GenericNew;
5634 TabPageType.tp_free = call_PyObject_Free;
5635#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005636 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005637#endif
5638
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005639 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5640 BufMapType.tp_name = "vim.bufferlist";
5641 BufMapType.tp_basicsize = sizeof(BufMapObject);
5642 BufMapType.tp_as_mapping = &BufMapAsMapping;
5643 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005644 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005645 BufferType.tp_doc = "vim buffer list";
5646
5647 vim_memset(&WinListType, 0, sizeof(WinListType));
5648 WinListType.tp_name = "vim.windowlist";
5649 WinListType.tp_basicsize = sizeof(WinListType);
5650 WinListType.tp_as_sequence = &WinListAsSeq;
5651 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5652 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005653 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005654
5655 vim_memset(&TabListType, 0, sizeof(TabListType));
5656 TabListType.tp_name = "vim.tabpagelist";
5657 TabListType.tp_basicsize = sizeof(TabListType);
5658 TabListType.tp_as_sequence = &TabListAsSeq;
5659 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5660 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005661
5662 vim_memset(&RangeType, 0, sizeof(RangeType));
5663 RangeType.tp_name = "vim.range";
5664 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005665 RangeType.tp_dealloc = (destructor)RangeDestructor;
5666 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005667 RangeType.tp_as_sequence = &RangeAsSeq;
5668 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005669 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005670 RangeType.tp_doc = "vim Range object";
5671 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005672 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5673 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005674#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005675 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005676 RangeType.tp_alloc = call_PyType_GenericAlloc;
5677 RangeType.tp_new = call_PyType_GenericNew;
5678 RangeType.tp_free = call_PyObject_Free;
5679#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005680 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005681#endif
5682
5683 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5684 CurrentType.tp_name = "vim.currentdata";
5685 CurrentType.tp_basicsize = sizeof(CurrentObject);
5686 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5687 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005688 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005689#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005690 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5691 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005692#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005693 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5694 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005695#endif
5696
5697 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5698 DictionaryType.tp_name = "vim.dictionary";
5699 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005700 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005701 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005702 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005703 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005704 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5705 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005706 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5707 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5708 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005709#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005710 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5711 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005712#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005713 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5714 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005715#endif
5716
5717 vim_memset(&ListType, 0, sizeof(ListType));
5718 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005719 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005720 ListType.tp_basicsize = sizeof(ListObject);
5721 ListType.tp_as_sequence = &ListAsSeq;
5722 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005723 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005724 ListType.tp_doc = "list pushing modifications to vim structure";
5725 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005726 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005727 ListType.tp_new = (newfunc)ListConstructor;
5728 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005729#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005730 ListType.tp_getattro = (getattrofunc)ListGetattro;
5731 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005732#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005733 ListType.tp_getattr = (getattrfunc)ListGetattr;
5734 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005735#endif
5736
5737 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005738 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005739 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005740 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5741 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005742 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005743 FunctionType.tp_doc = "object that calls vim function";
5744 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005745 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005746 FunctionType.tp_new = (newfunc)FunctionConstructor;
5747 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005748#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005749 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005750#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005751 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005752#endif
5753
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005754 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5755 OptionsType.tp_name = "vim.options";
5756 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005757 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005758 OptionsType.tp_doc = "object for manipulating options";
5759 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005760 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5761 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5762 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005763
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005764 vim_memset(&LoaderType, 0, sizeof(LoaderType));
5765 LoaderType.tp_name = "vim.Loader";
5766 LoaderType.tp_basicsize = sizeof(LoaderObject);
5767 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
5768 LoaderType.tp_doc = "vim message object";
5769 LoaderType.tp_methods = LoaderMethods;
5770 LoaderType.tp_dealloc = (destructor)LoaderDestructor;
5771
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005772#if PY_MAJOR_VERSION >= 3
5773 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5774 vimmodule.m_name = "vim";
5775 vimmodule.m_doc = "Vim Python interface\n";
5776 vimmodule.m_size = -1;
5777 vimmodule.m_methods = VimMethods;
5778#endif
5779}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005780
5781#define PYTYPE_READY(type) \
5782 if (PyType_Ready(&type)) \
5783 return -1;
5784
5785 static int
5786init_types()
5787{
5788 PYTYPE_READY(IterType);
5789 PYTYPE_READY(BufferType);
5790 PYTYPE_READY(RangeType);
5791 PYTYPE_READY(WindowType);
5792 PYTYPE_READY(TabPageType);
5793 PYTYPE_READY(BufMapType);
5794 PYTYPE_READY(WinListType);
5795 PYTYPE_READY(TabListType);
5796 PYTYPE_READY(CurrentType);
5797 PYTYPE_READY(DictionaryType);
5798 PYTYPE_READY(ListType);
5799 PYTYPE_READY(FunctionType);
5800 PYTYPE_READY(OptionsType);
5801 PYTYPE_READY(OutputType);
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005802 PYTYPE_READY(LoaderType);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005803 return 0;
5804}
5805
5806 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02005807init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005808{
5809 PyObject *path;
5810 PyObject *path_hook;
5811 PyObject *path_hooks;
5812
5813 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
5814 return -1;
5815
5816 if (!(path_hooks = PySys_GetObject("path_hooks")))
5817 {
5818 PyErr_Clear();
5819 path_hooks = PyList_New(1);
5820 PyList_SET_ITEM(path_hooks, 0, path_hook);
5821 if (PySys_SetObject("path_hooks", path_hooks))
5822 {
5823 Py_DECREF(path_hooks);
5824 return -1;
5825 }
5826 Py_DECREF(path_hooks);
5827 }
5828 else if (PyList_Check(path_hooks))
5829 {
5830 if (PyList_Append(path_hooks, path_hook))
5831 {
5832 Py_DECREF(path_hook);
5833 return -1;
5834 }
5835 Py_DECREF(path_hook);
5836 }
5837 else
5838 {
5839 VimTryStart();
5840 EMSG(_("Failed to set path hook: sys.path_hooks is not a list\n"
5841 "You should now do the following:\n"
5842 "- append vim.path_hook to sys.path_hooks\n"
5843 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
5844 VimTryEnd(); /* Discard the error */
5845 Py_DECREF(path_hook);
5846 return 0;
5847 }
5848
5849 if (!(path = PySys_GetObject("path")))
5850 {
5851 PyErr_Clear();
5852 path = PyList_New(1);
5853 Py_INCREF(vim_special_path_object);
5854 PyList_SET_ITEM(path, 0, vim_special_path_object);
5855 if (PySys_SetObject("path", path))
5856 {
5857 Py_DECREF(path);
5858 return -1;
5859 }
5860 Py_DECREF(path);
5861 }
5862 else if (PyList_Check(path))
5863 {
5864 if (PyList_Append(path, vim_special_path_object))
5865 return -1;
5866 }
5867 else
5868 {
5869 VimTryStart();
5870 EMSG(_("Failed to set path: sys.path is not a list\n"
5871 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
5872 VimTryEnd(); /* Discard the error */
5873 }
5874
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005875 return 0;
5876}
5877
5878static BufMapObject TheBufferMap =
5879{
5880 PyObject_HEAD_INIT(&BufMapType)
5881};
5882
5883static WinListObject TheWindowList =
5884{
5885 PyObject_HEAD_INIT(&WinListType)
5886 NULL
5887};
5888
5889static CurrentObject TheCurrent =
5890{
5891 PyObject_HEAD_INIT(&CurrentType)
5892};
5893
5894static TabListObject TheTabPageList =
5895{
5896 PyObject_HEAD_INIT(&TabListType)
5897};
5898
5899static struct numeric_constant {
5900 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005901 int val;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005902} numeric_constants[] = {
5903 {"VAR_LOCKED", VAR_LOCKED},
5904 {"VAR_FIXED", VAR_FIXED},
5905 {"VAR_SCOPE", VAR_SCOPE},
5906 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5907};
5908
5909static struct object_constant {
5910 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005911 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005912} object_constants[] = {
5913 {"buffers", (PyObject *)(void *)&TheBufferMap},
5914 {"windows", (PyObject *)(void *)&TheWindowList},
5915 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5916 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005917
5918 {"Buffer", (PyObject *)&BufferType},
5919 {"Range", (PyObject *)&RangeType},
5920 {"Window", (PyObject *)&WindowType},
5921 {"TabPage", (PyObject *)&TabPageType},
5922 {"Dictionary", (PyObject *)&DictionaryType},
5923 {"List", (PyObject *)&ListType},
5924 {"Function", (PyObject *)&FunctionType},
5925 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005926 {"_Loader", (PyObject *)&LoaderType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005927};
5928
5929typedef int (*object_adder)(PyObject *, const char *, PyObject *);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005930typedef PyObject *(*attr_getter)(PyObject *, const char *);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005931
5932#define ADD_OBJECT(m, name, obj) \
5933 if (add_object(m, name, obj)) \
5934 return -1;
5935
5936#define ADD_CHECKED_OBJECT(m, name, obj) \
5937 { \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005938 PyObject *valObject = obj; \
5939 if (!valObject) \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005940 return -1; \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005941 ADD_OBJECT(m, name, valObject); \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005942 }
5943
5944 static int
Bram Moolenaarf4258302013-06-02 18:20:17 +02005945populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005946{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005947 int i;
5948 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005949 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005950 PyObject *imp;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005951
5952 for (i = 0; i < (int)(sizeof(numeric_constants)
5953 / sizeof(struct numeric_constant));
5954 ++i)
5955 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005956 PyInt_FromLong(numeric_constants[i].val));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005957
5958 for (i = 0; i < (int)(sizeof(object_constants)
5959 / sizeof(struct object_constant));
5960 ++i)
5961 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005962 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005963
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005964 valObject = object_constants[i].valObject;
5965 Py_INCREF(valObject);
5966 ADD_OBJECT(m, object_constants[i].name, valObject);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005967 }
5968
5969 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5970 return -1;
5971 ADD_OBJECT(m, "error", VimError);
5972
Bram Moolenaara9922d62013-05-30 13:01:18 +02005973 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5974 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005975 ADD_CHECKED_OBJECT(m, "options",
5976 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02005977
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005978 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005979 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005980 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005981
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005982 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005983 return -1;
5984 ADD_OBJECT(m, "_getcwd", py_getcwd)
5985
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005986 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005987 return -1;
5988 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005989 if (!(attr = get_attr(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005990 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005991 if (PyObject_SetAttrString(other_module, "chdir", attr))
5992 {
5993 Py_DECREF(attr);
5994 return -1;
5995 }
5996 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005997
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005998 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005999 {
6000 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02006001 if (!(attr = get_attr(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006002 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02006003 if (PyObject_SetAttrString(other_module, "fchdir", attr))
6004 {
6005 Py_DECREF(attr);
6006 return -1;
6007 }
6008 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02006009 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02006010 else
6011 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02006012
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006013 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
6014 return -1;
6015
6016 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
6017
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006018 if (!(imp = PyImport_ImportModule("imp")))
6019 return -1;
6020
6021 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
6022 {
6023 Py_DECREF(imp);
6024 return -1;
6025 }
6026
6027 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
6028 {
6029 Py_DECREF(py_find_module);
6030 Py_DECREF(imp);
6031 return -1;
6032 }
6033
6034 Py_DECREF(imp);
6035
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02006036 ADD_OBJECT(m, "_find_module", py_find_module);
6037 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006038
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006039 return 0;
6040}