blob: 164e2a42aa293ec80e7bb0293d4e9e4076e70787 [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
21# define ENC_OPT p_enc
22#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 Moolenaar3d0c52d2013-05-12 19:45:35 +020029#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
30
Bram Moolenaar35eacd72013-05-30 22:06:33 +020031#define RAISE_NO_EMPTY_KEYS PyErr_SetString(PyExc_ValueError, \
32 _("empty keys are not allowed"))
33
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020034#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
35#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020036#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020037
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020038typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020039typedef void (*runner)(const char *, void *
40#ifdef PY_CAN_RECURSE
41 , PyGILState_STATE *
42#endif
43 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020044
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020045static int ConvertFromPyObject(PyObject *, typval_T *);
46static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +020047static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020048static PyObject *WindowNew(win_T *, tabpage_T *);
49static PyObject *BufferNew (buf_T *);
50static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020051
52static PyInt RangeStart;
53static PyInt RangeEnd;
54
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020055static PyObject *globals;
56
Bram Moolenaarf4258302013-06-02 18:20:17 +020057static PyObject *py_chdir;
58static PyObject *py_fchdir;
59static PyObject *py_getcwd;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020060static PyObject *vim_module;
61static PyObject *vim_special_path_object;
Bram Moolenaarf4258302013-06-02 18:20:17 +020062
Bram Moolenaar81c40c52013-06-12 14:41:04 +020063static PyObject *py_find_module;
64static PyObject *py_load_module;
65
66static PyObject *VimError;
67
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020068/*
69 * obtain a lock on the Vim data structures
70 */
71 static void
72Python_Lock_Vim(void)
73{
74}
75
76/*
77 * release a lock on the Vim data structures
78 */
79 static void
80Python_Release_Vim(void)
81{
82}
83
Bram Moolenaare9ba5162013-05-29 22:02:22 +020084/*
85 * The "todecref" argument holds a pointer to PyObject * that must be
86 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
87 * was needed to generate returned value is object.
88 *
89 * Use Py_XDECREF to decrement reference count.
90 */
91 static char_u *
92StringToChars(PyObject *object, PyObject **todecref)
93{
94 char_u *p;
95 PyObject *bytes = NULL;
96
97 if (PyBytes_Check(object))
98 {
99
100 if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1)
101 return NULL;
102 if (p == NULL)
103 return NULL;
104
105 *todecref = NULL;
106 }
107 else if (PyUnicode_Check(object))
108 {
109 bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL);
110 if (bytes == NULL)
111 return NULL;
112
113 if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1)
114 return NULL;
115 if (p == NULL)
116 return NULL;
117
118 *todecref = bytes;
119 }
120 else
121 {
122 PyErr_SetString(PyExc_TypeError, _("object must be string"));
123 return NULL;
124 }
125
126 return (char_u *) p;
127}
128
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200129 static int
130add_string(PyObject *list, char *s)
131{
132 PyObject *string;
133
134 if (!(string = PyString_FromString(s)))
135 return -1;
136 if (PyList_Append(list, string))
137 {
138 Py_DECREF(string);
139 return -1;
140 }
141
142 Py_DECREF(string);
143 return 0;
144}
145
146 static PyObject *
147ObjectDir(PyObject *self, char **attributes)
148{
149 PyMethodDef *method;
150 char **attr;
151 PyObject *r;
152
153 if (!(r = PyList_New(0)))
154 return NULL;
155
156 if (self)
157 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
158 if (add_string(r, (char *) method->ml_name))
159 {
160 Py_DECREF(r);
161 return NULL;
162 }
163
164 for (attr = attributes ; *attr ; ++attr)
165 if (add_string(r, *attr))
166 {
167 Py_DECREF(r);
168 return NULL;
169 }
170
171#if PY_MAJOR_VERSION < 3
172 if (add_string(r, "__members__"))
173 {
174 Py_DECREF(r);
175 return NULL;
176 }
177#endif
178
179 return r;
180}
181
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200182/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200183 */
184
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200185/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200186typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200187
188static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200189
190typedef struct
191{
192 PyObject_HEAD
193 long softspace;
194 long error;
195} OutputObject;
196
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200197static char *OutputAttrs[] = {
198 "softspace",
199 NULL
200};
201
202 static PyObject *
203OutputDir(PyObject *self)
204{
205 return ObjectDir(self, OutputAttrs);
206}
207
Bram Moolenaar77045652012-09-21 13:46:06 +0200208 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200209OutputSetattr(OutputObject *self, char *name, PyObject *val)
Bram Moolenaar77045652012-09-21 13:46:06 +0200210{
211 if (val == NULL)
212 {
Bram Moolenaar8661b172013-05-15 15:44:28 +0200213 PyErr_SetString(PyExc_AttributeError,
214 _("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200215 return -1;
216 }
217
218 if (strcmp(name, "softspace") == 0)
219 {
220 if (!PyInt_Check(val))
221 {
222 PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
223 return -1;
224 }
225
Bram Moolenaard6e39182013-05-21 18:30:34 +0200226 self->softspace = PyInt_AsLong(val);
Bram Moolenaar77045652012-09-21 13:46:06 +0200227 return 0;
228 }
229
230 PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
231 return -1;
232}
233
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200234/* Buffer IO, we write one whole line at a time. */
235static garray_T io_ga = {0, 0, 1, 80, NULL};
236static writefn old_fn = NULL;
237
238 static void
239PythonIO_Flush(void)
240{
241 if (old_fn != NULL && io_ga.ga_len > 0)
242 {
243 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
244 old_fn((char_u *)io_ga.ga_data);
245 }
246 io_ga.ga_len = 0;
247}
248
249 static void
250writer(writefn fn, char_u *str, PyInt n)
251{
252 char_u *ptr;
253
254 /* Flush when switching output function. */
255 if (fn != old_fn)
256 PythonIO_Flush();
257 old_fn = fn;
258
259 /* Write each NL separated line. Text after the last NL is kept for
260 * writing later. */
261 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
262 {
263 PyInt len = ptr - str;
264
265 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
266 break;
267
268 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
269 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
270 fn((char_u *)io_ga.ga_data);
271 str = ptr + 1;
272 n -= len + 1;
273 io_ga.ga_len = 0;
274 }
275
276 /* Put the remaining text into io_ga for later printing. */
277 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
278 {
279 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
280 io_ga.ga_len += (int)n;
281 }
282}
283
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200284 static int
285write_output(OutputObject *self, PyObject *string)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200286{
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200287 Py_ssize_t len = 0;
288 char *str = NULL;
289 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200290
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200291 if (!PyArg_Parse(string, "et#", ENC_OPT, &str, &len))
292 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200293
294 Py_BEGIN_ALLOW_THREADS
295 Python_Lock_Vim();
296 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
297 Python_Release_Vim();
298 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200299 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200300
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200301 return 0;
302}
303
304 static PyObject *
305OutputWrite(OutputObject *self, PyObject *string)
306{
307 if (write_output(self, string))
308 return NULL;
309
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200310 Py_INCREF(Py_None);
311 return Py_None;
312}
313
314 static PyObject *
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200315OutputWritelines(OutputObject *self, PyObject *seq)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200316{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200317 PyObject *iterator;
318 PyObject *item;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200319
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200320 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200321 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200322
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200323 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200324 {
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200325 if (write_output(self, item))
Bram Moolenaardb913952012-06-29 12:54:53 +0200326 {
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200327 Py_DECREF(iterator);
328 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200329 return NULL;
330 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200331 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200332 }
333
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200334 Py_DECREF(iterator);
335
336 /* Iterator may have finished due to an exception */
337 if (PyErr_Occurred())
338 return NULL;
339
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200340 Py_INCREF(Py_None);
341 return Py_None;
342}
343
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100344 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200345OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100346{
347 /* do nothing */
348 Py_INCREF(Py_None);
349 return Py_None;
350}
351
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200352/***************/
353
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200354static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200355 /* name, function, calling, doc */
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200356 {"write", (PyCFunction)OutputWrite, METH_O, ""},
357 {"writelines", (PyCFunction)OutputWritelines, METH_O, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200358 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200359 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200360 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200361};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200362
363static OutputObject Output =
364{
365 PyObject_HEAD_INIT(&OutputType)
366 0,
367 0
368};
369
370static OutputObject Error =
371{
372 PyObject_HEAD_INIT(&OutputType)
373 0,
374 1
375};
376
377 static int
378PythonIO_Init_io(void)
379{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200380 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
381 return -1;
382 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
383 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200384
385 if (PyErr_Occurred())
386 {
387 EMSG(_("E264: Python: Error initialising I/O objects"));
388 return -1;
389 }
390
391 return 0;
392}
393
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200394typedef struct
395{
396 PyObject_HEAD
397 PyObject *module;
398} LoaderObject;
399static PyTypeObject LoaderType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200400
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200401 static void
402LoaderDestructor(LoaderObject *self)
403{
404 Py_DECREF(self->module);
405 DESTRUCTOR_FINISH(self);
406}
407
408 static PyObject *
409LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
410{
411 PyObject *r = self->module;
412
413 Py_INCREF(r);
414 return r;
415}
416
417static struct PyMethodDef LoaderMethods[] = {
418 /* name, function, calling, doc */
419 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
420 { NULL, NULL, 0, NULL}
421};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200422
423/* Check to see whether a Vim error has been reported, or a keyboard
424 * interrupt has been detected.
425 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200426
427 static void
428VimTryStart(void)
429{
430 ++trylevel;
431}
432
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200433 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200434VimTryEnd(void)
435{
436 --trylevel;
437 if (got_int)
438 {
439 PyErr_SetNone(PyExc_KeyboardInterrupt);
440 return 1;
441 }
442 else if (!did_throw)
443 return 0;
444 else if (PyErr_Occurred())
445 return 1;
446 else
447 {
448 PyErr_SetVim((char *) current_exception->value);
449 discard_current_exception();
450 return 1;
451 }
452}
453
454 static int
455VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200456{
457 if (got_int)
458 {
459 PyErr_SetNone(PyExc_KeyboardInterrupt);
460 return 1;
461 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200462 return 0;
463}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200464
465/* Vim module - Implementation
466 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200467
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200468 static PyObject *
469VimCommand(PyObject *self UNUSED, PyObject *args)
470{
471 char *cmd;
472 PyObject *result;
473
474 if (!PyArg_ParseTuple(args, "s", &cmd))
475 return NULL;
476
477 PyErr_Clear();
478
479 Py_BEGIN_ALLOW_THREADS
480 Python_Lock_Vim();
481
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200482 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200483 do_cmdline_cmd((char_u *)cmd);
484 update_screen(VALID);
485
486 Python_Release_Vim();
487 Py_END_ALLOW_THREADS
488
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200489 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200490 result = NULL;
491 else
492 result = Py_None;
493
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200494
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200495 Py_XINCREF(result);
496 return result;
497}
498
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200499/*
500 * Function to translate a typval_T into a PyObject; this will recursively
501 * translate lists/dictionaries into their Python equivalents.
502 *
503 * The depth parameter is to avoid infinite recursion, set it to 1 when
504 * you call VimToPython.
505 */
506 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200507VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200508{
509 PyObject *result;
510 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200511 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200512
513 /* Avoid infinite recursion */
514 if (depth > 100)
515 {
516 Py_INCREF(Py_None);
517 result = Py_None;
518 return result;
519 }
520
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200521 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200522 * then and we can use it again. */
523 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
524 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
525 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200526 sprintf(ptrBuf, "%p",
527 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
528 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200529
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200530 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200531 {
532 Py_INCREF(result);
533 return result;
534 }
535 }
536
537 if (our_tv->v_type == VAR_STRING)
538 {
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200539 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200540 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200541 }
542 else if (our_tv->v_type == VAR_NUMBER)
543 {
544 char buf[NUMBUFLEN];
545
546 /* For backwards compatibility numbers are stored as strings. */
547 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200548 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200549 }
550# ifdef FEAT_FLOAT
551 else if (our_tv->v_type == VAR_FLOAT)
552 {
553 char buf[NUMBUFLEN];
554
555 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200556 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200557 }
558# endif
559 else if (our_tv->v_type == VAR_LIST)
560 {
561 list_T *list = our_tv->vval.v_list;
562 listitem_T *curr;
563
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200564 if (list == NULL)
565 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200566
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200567 if (!(result = PyList_New(0)))
568 return NULL;
569
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200570 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200571 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200572 Py_DECREF(result);
573 return NULL;
574 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200575
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200576 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
577 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200578 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200579 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200580 Py_DECREF(result);
581 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200582 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200583 if (PyList_Append(result, newObj))
584 {
585 Py_DECREF(newObj);
586 Py_DECREF(result);
587 return NULL;
588 }
589 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200590 }
591 }
592 else if (our_tv->v_type == VAR_DICT)
593 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200594
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200595 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
596 long_u todo = ht->ht_used;
597 hashitem_T *hi;
598 dictitem_T *di;
599 if (our_tv->vval.v_dict == NULL)
600 return NULL;
601
602 if (!(result = PyDict_New()))
603 return NULL;
604
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200605 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200606 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200607 Py_DECREF(result);
608 return NULL;
609 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200610
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200611 for (hi = ht->ht_array; todo > 0; ++hi)
612 {
613 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200614 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200615 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200616
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200617 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200618 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200619 {
620 Py_DECREF(result);
621 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200622 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200623 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
624 {
625 Py_DECREF(result);
626 Py_DECREF(newObj);
627 return NULL;
628 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200629 }
630 }
631 }
632 else
633 {
634 Py_INCREF(Py_None);
635 result = Py_None;
636 }
637
638 return result;
639}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200640
641 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200642VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200643{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200644 char *expr;
645 typval_T *our_tv;
646 PyObject *result;
647 PyObject *lookup_dict;
648
649 if (!PyArg_ParseTuple(args, "s", &expr))
650 return NULL;
651
652 Py_BEGIN_ALLOW_THREADS
653 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200654 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200655 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200656 Python_Release_Vim();
657 Py_END_ALLOW_THREADS
658
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200659 if (VimTryEnd())
660 return NULL;
661
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200662 if (our_tv == NULL)
663 {
664 PyErr_SetVim(_("invalid expression"));
665 return NULL;
666 }
667
668 /* Convert the Vim type into a Python type. Create a dictionary that's
669 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200670 if (!(lookup_dict = PyDict_New()))
671 result = NULL;
672 else
673 {
674 result = VimToPython(our_tv, 1, lookup_dict);
675 Py_DECREF(lookup_dict);
676 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200677
678
679 Py_BEGIN_ALLOW_THREADS
680 Python_Lock_Vim();
681 free_tv(our_tv);
682 Python_Release_Vim();
683 Py_END_ALLOW_THREADS
684
685 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200686}
687
Bram Moolenaardb913952012-06-29 12:54:53 +0200688static PyObject *ConvertToPyObject(typval_T *);
689
690 static PyObject *
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200691VimEvalPy(PyObject *self UNUSED, PyObject *args)
Bram Moolenaardb913952012-06-29 12:54:53 +0200692{
Bram Moolenaardb913952012-06-29 12:54:53 +0200693 char *expr;
694 typval_T *our_tv;
695 PyObject *result;
696
697 if (!PyArg_ParseTuple(args, "s", &expr))
698 return NULL;
699
700 Py_BEGIN_ALLOW_THREADS
701 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200702 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +0200703 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200704 Python_Release_Vim();
705 Py_END_ALLOW_THREADS
706
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200707 if (VimTryEnd())
708 return NULL;
709
Bram Moolenaardb913952012-06-29 12:54:53 +0200710 if (our_tv == NULL)
711 {
712 PyErr_SetVim(_("invalid expression"));
713 return NULL;
714 }
715
716 result = ConvertToPyObject(our_tv);
717 Py_BEGIN_ALLOW_THREADS
718 Python_Lock_Vim();
719 free_tv(our_tv);
720 Python_Release_Vim();
721 Py_END_ALLOW_THREADS
722
723 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200724}
725
726 static PyObject *
727VimStrwidth(PyObject *self UNUSED, PyObject *args)
728{
729 char *expr;
730
731 if (!PyArg_ParseTuple(args, "s", &expr))
732 return NULL;
733
Bram Moolenaara54bf402012-12-05 16:30:07 +0100734 return PyLong_FromLong(
735#ifdef FEAT_MBYTE
736 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
737#else
738 STRLEN(expr)
739#endif
740 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200741}
742
Bram Moolenaarf4258302013-06-02 18:20:17 +0200743 static PyObject *
744_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
745{
746 PyObject *r;
747 PyObject *newwd;
748 PyObject *todecref;
749 char_u *new_dir;
750
Bram Moolenaard4209d22013-06-05 20:34:15 +0200751 if (_chdir == NULL)
752 return NULL;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200753 if (!(r = PyObject_Call(_chdir, args, kwargs)))
754 return NULL;
755
756 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
757 {
758 Py_DECREF(r);
759 return NULL;
760 }
761
762 if (!(new_dir = StringToChars(newwd, &todecref)))
763 {
764 Py_DECREF(r);
765 Py_DECREF(newwd);
766 return NULL;
767 }
768
769 VimTryStart();
770
771 if (vim_chdir(new_dir))
772 {
773 Py_DECREF(r);
774 Py_DECREF(newwd);
775 Py_XDECREF(todecref);
776
777 if (VimTryEnd())
778 return NULL;
779
780 PyErr_SetVim(_("failed to change directory"));
781 return NULL;
782 }
783
784 Py_DECREF(newwd);
785 Py_XDECREF(todecref);
786
787 post_chdir(FALSE);
788
789 if (VimTryEnd())
790 {
791 Py_DECREF(r);
792 return NULL;
793 }
794
795 return r;
796}
797
798 static PyObject *
799VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
800{
801 return _VimChdir(py_chdir, args, kwargs);
802}
803
804 static PyObject *
805VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
806{
807 return _VimChdir(py_fchdir, args, kwargs);
808}
809
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200810typedef struct {
811 PyObject *callable;
812 PyObject *result;
813} map_rtp_data;
814
815 static void
816map_rtp_callback(char_u *path, void *_data)
817{
818 void **data = (void **) _data;
819 PyObject *pathObject;
820 map_rtp_data *mr_data = *((map_rtp_data **) data);
821
822 if (!(pathObject = PyString_FromString((char *) path)))
823 {
824 *data = NULL;
825 return;
826 }
827
828 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
829 pathObject, NULL);
830
831 Py_DECREF(pathObject);
832
833 if (!mr_data->result || mr_data->result != Py_None)
834 *data = NULL;
835 else
836 {
837 Py_DECREF(mr_data->result);
838 mr_data->result = NULL;
839 }
840}
841
842 static PyObject *
843VimForeachRTP(PyObject *self UNUSED, PyObject *args)
844{
845 map_rtp_data data;
846
847 if (!PyArg_ParseTuple(args, "O", &data.callable))
848 return NULL;
849
850 data.result = NULL;
851
852 do_in_runtimepath(NULL, FALSE, &map_rtp_callback, &data);
853
854 if (data.result == NULL)
855 {
856 if (PyErr_Occurred())
857 return NULL;
858 else
859 {
860 Py_INCREF(Py_None);
861 return Py_None;
862 }
863 }
864 return data.result;
865}
866
867/*
868 * _vim_runtimepath_ special path implementation.
869 */
870
871 static void
872map_finder_callback(char_u *path, void *_data)
873{
874 void **data = (void **) _data;
875 PyObject *list = *((PyObject **) data);
876 PyObject *pathObject1, *pathObject2;
877 char *pathbuf;
878 size_t pathlen;
879
880 pathlen = STRLEN(path);
881
882#if PY_MAJOR_VERSION < 3
883# define PY_MAIN_DIR_STRING "python2"
884#else
885# define PY_MAIN_DIR_STRING "python3"
886#endif
887#define PY_ALTERNATE_DIR_STRING "pythonx"
888
889#define PYTHONX_STRING_LENGTH 7 /* STRLEN("pythonx") */
890 if (!(pathbuf = PyMem_New(char,
891 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
892 {
893 PyErr_NoMemory();
894 *data = NULL;
895 return;
896 }
897
898 mch_memmove(pathbuf, path, pathlen + 1);
899 add_pathsep((char_u *) pathbuf);
900
901 pathlen = STRLEN(pathbuf);
902 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
903 PYTHONX_STRING_LENGTH + 1);
904
905 if (!(pathObject1 = PyString_FromString(pathbuf)))
906 {
907 *data = NULL;
908 PyMem_Free(pathbuf);
909 return;
910 }
911
912 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
913 PYTHONX_STRING_LENGTH + 1);
914
915 if (!(pathObject2 = PyString_FromString(pathbuf)))
916 {
917 Py_DECREF(pathObject1);
918 PyMem_Free(pathbuf);
919 *data = NULL;
920 return;
921 }
922
923 PyMem_Free(pathbuf);
924
925 if (PyList_Append(list, pathObject1)
926 || PyList_Append(list, pathObject2))
927 *data = NULL;
928
929 Py_DECREF(pathObject1);
930 Py_DECREF(pathObject2);
931}
932
933 static PyObject *
934Vim_GetPaths(PyObject *self UNUSED)
935{
936 PyObject *r;
937
938 if (!(r = PyList_New(0)))
939 return NULL;
940
941 do_in_runtimepath(NULL, FALSE, &map_finder_callback, r);
942
943 if (PyErr_Occurred())
944 {
945 Py_DECREF(r);
946 return NULL;
947 }
948
949 return r;
950}
951
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200952 static PyObject *
953call_load_module(char *name, int len, PyObject *find_module_result)
954{
955 PyObject *fd, *pathname, *description;
956
957 if (!PyTuple_Check(find_module_result)
958 || PyTuple_GET_SIZE(find_module_result) != 3)
959 {
960 PyErr_SetString(PyExc_TypeError,
961 _("expected 3-tuple as imp.find_module() result"));
962 return NULL;
963 }
964
965 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
966 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
967 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
968 {
969 PyErr_SetString(PyExc_RuntimeError,
970 _("internal error: imp.find_module returned tuple with NULL"));
971 return NULL;
972 }
973
974 return PyObject_CallFunction(py_load_module,
975 "s#OOO", name, len, fd, pathname, description);
976}
977
978 static PyObject *
979find_module(char *fullname, char *tail, PyObject *new_path)
980{
981 PyObject *find_module_result;
982 PyObject *module;
983 char *dot;
984
985 if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
986 {
987 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +0200988 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200989 * first component
990 */
991 PyObject *newest_path;
992 int partlen = (int) (dot - 1 - tail);
993
994 if (!(find_module_result = PyObject_CallFunction(py_find_module,
995 "s#O", tail, partlen, new_path)))
996 return NULL;
997
998 if (!(module = call_load_module(
999 fullname,
1000 ((int) (tail - fullname)) + partlen,
1001 find_module_result)))
1002 {
1003 Py_DECREF(find_module_result);
1004 return NULL;
1005 }
1006
1007 Py_DECREF(find_module_result);
1008
1009 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1010 {
1011 Py_DECREF(module);
1012 return NULL;
1013 }
1014
1015 Py_DECREF(module);
1016
1017 module = find_module(fullname, dot + 1, newest_path);
1018
1019 Py_DECREF(newest_path);
1020
1021 return module;
1022 }
1023 else
1024 {
1025 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1026 "sO", tail, new_path)))
1027 return NULL;
1028
1029 if (!(module = call_load_module(
1030 fullname,
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001031 (int)STRLEN(fullname),
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001032 find_module_result)))
1033 {
1034 Py_DECREF(find_module_result);
1035 return NULL;
1036 }
1037
1038 Py_DECREF(find_module_result);
1039
1040 return module;
1041 }
1042}
1043
1044 static PyObject *
1045FinderFindModule(PyObject *self, PyObject *args)
1046{
1047 char *fullname;
1048 PyObject *module;
1049 PyObject *new_path;
1050 LoaderObject *loader;
1051
1052 if (!PyArg_ParseTuple(args, "s", &fullname))
1053 return NULL;
1054
1055 if (!(new_path = Vim_GetPaths(self)))
1056 return NULL;
1057
1058 module = find_module(fullname, fullname, new_path);
1059
1060 Py_DECREF(new_path);
1061
1062 if (!module)
1063 {
1064 Py_INCREF(Py_None);
1065 return Py_None;
1066 }
1067
1068 if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
1069 {
1070 Py_DECREF(module);
1071 return NULL;
1072 }
1073
1074 loader->module = module;
1075
1076 return (PyObject *) loader;
1077}
1078
1079 static PyObject *
1080VimPathHook(PyObject *self UNUSED, PyObject *args)
1081{
1082 char *path;
1083
1084 if (PyArg_ParseTuple(args, "s", &path)
1085 && STRCMP(path, vim_special_path) == 0)
1086 {
1087 Py_INCREF(vim_module);
1088 return vim_module;
1089 }
1090
1091 PyErr_Clear();
1092 PyErr_SetNone(PyExc_ImportError);
1093 return NULL;
1094}
1095
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001096/*
1097 * Vim module - Definitions
1098 */
1099
1100static struct PyMethodDef VimMethods[] = {
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001101 /* name, function, calling, documentation */
1102 {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" },
1103 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
1104 {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"},
1105 {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"},
1106 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1107 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1108 {"foreach_rtp", VimForeachRTP, METH_VARARGS, "Call given callable for each path in &rtp"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001109 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001110 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1111 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1112 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001113};
1114
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001115/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001116 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001117 */
1118
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001119static PyTypeObject IterType;
1120
1121typedef PyObject *(*nextfun)(void **);
1122typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001123typedef int (*traversefun)(void *, visitproc, void *);
1124typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001125
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001126/* Main purpose of this object is removing the need for do python
1127 * initialization (i.e. PyType_Ready and setting type attributes) for a big
1128 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001129
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001130typedef struct
1131{
1132 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001133 void *cur;
1134 nextfun next;
1135 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001136 traversefun traverse;
1137 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001138} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001139
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001140 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001141IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
1142 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001143{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001144 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001145
Bram Moolenaar774267b2013-05-21 20:51:59 +02001146 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001147 self->cur = start;
1148 self->next = next;
1149 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001150 self->traverse = traverse;
1151 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001152
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001153 return (PyObject *)(self);
1154}
1155
1156 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001157IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001158{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001159 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001160 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001161 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001162}
1163
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001164 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001165IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001166{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001167 if (self->traverse != NULL)
1168 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001169 else
1170 return 0;
1171}
1172
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001173/* Mac OSX defines clear() somewhere. */
1174#ifdef clear
1175# undef clear
1176#endif
1177
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001178 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001179IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001180{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001181 if (self->clear != NULL)
1182 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001183 else
1184 return 0;
1185}
1186
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001187 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001188IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001189{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001190 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001191}
1192
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001193 static PyObject *
1194IterIter(PyObject *self)
1195{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001196 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001197 return self;
1198}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001199
Bram Moolenaardb913952012-06-29 12:54:53 +02001200typedef struct pylinkedlist_S {
1201 struct pylinkedlist_S *pll_next;
1202 struct pylinkedlist_S *pll_prev;
1203 PyObject *pll_obj;
1204} pylinkedlist_T;
1205
1206static pylinkedlist_T *lastdict = NULL;
1207static pylinkedlist_T *lastlist = NULL;
1208
1209 static void
1210pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1211{
1212 if (ref->pll_prev == NULL)
1213 {
1214 if (ref->pll_next == NULL)
1215 {
1216 *last = NULL;
1217 return;
1218 }
1219 }
1220 else
1221 ref->pll_prev->pll_next = ref->pll_next;
1222
1223 if (ref->pll_next == NULL)
1224 *last = ref->pll_prev;
1225 else
1226 ref->pll_next->pll_prev = ref->pll_prev;
1227}
1228
1229 static void
1230pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1231{
1232 if (*last == NULL)
1233 ref->pll_prev = NULL;
1234 else
1235 {
1236 (*last)->pll_next = ref;
1237 ref->pll_prev = *last;
1238 }
1239 ref->pll_next = NULL;
1240 ref->pll_obj = self;
1241 *last = ref;
1242}
1243
1244static PyTypeObject DictionaryType;
1245
1246typedef struct
1247{
1248 PyObject_HEAD
1249 dict_T *dict;
1250 pylinkedlist_T ref;
1251} DictionaryObject;
1252
Bram Moolenaara9922d62013-05-30 13:01:18 +02001253static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1254
1255#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
1256
Bram Moolenaardb913952012-06-29 12:54:53 +02001257 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001258DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001259{
1260 DictionaryObject *self;
1261
Bram Moolenaara9922d62013-05-30 13:01:18 +02001262 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001263 if (self == NULL)
1264 return NULL;
1265 self->dict = dict;
1266 ++dict->dv_refcount;
1267
1268 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1269
1270 return (PyObject *)(self);
1271}
1272
Bram Moolenaara9922d62013-05-30 13:01:18 +02001273 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001274py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001275{
1276 dict_T *r;
1277
1278 if (!(r = dict_alloc()))
1279 {
1280 PyErr_NoMemory();
1281 return NULL;
1282 }
1283 ++r->dv_refcount;
1284
1285 return r;
1286}
1287
1288 static PyObject *
1289DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1290{
1291 DictionaryObject *self;
1292 dict_T *dict;
1293
1294 if (!(dict = py_dict_alloc()))
1295 return NULL;
1296
1297 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1298
1299 --dict->dv_refcount;
1300
1301 if (kwargs || PyTuple_Size(args))
1302 {
1303 PyObject *tmp;
1304 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1305 {
1306 Py_DECREF(self);
1307 return NULL;
1308 }
1309
1310 Py_DECREF(tmp);
1311 }
1312
1313 return (PyObject *)(self);
1314}
1315
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001316 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001317DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001318{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001319 pyll_remove(&self->ref, &lastdict);
1320 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001321
1322 DESTRUCTOR_FINISH(self);
1323}
1324
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001325static char *DictionaryAttrs[] = {
1326 "locked", "scope",
1327 NULL
1328};
1329
1330 static PyObject *
1331DictionaryDir(PyObject *self)
1332{
1333 return ObjectDir(self, DictionaryAttrs);
1334}
1335
Bram Moolenaardb913952012-06-29 12:54:53 +02001336 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001337DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001338{
1339 if (val == NULL)
1340 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001341 PyErr_SetString(PyExc_AttributeError,
1342 _("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001343 return -1;
1344 }
1345
1346 if (strcmp(name, "locked") == 0)
1347 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001348 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001349 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001350 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001351 return -1;
1352 }
1353 else
1354 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001355 int istrue = PyObject_IsTrue(val);
1356 if (istrue == -1)
1357 return -1;
1358 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001359 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001360 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001361 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001362 }
1363 return 0;
1364 }
1365 else
1366 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001367 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001368 return -1;
1369 }
1370}
1371
1372 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001373DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001374{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001375 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001376}
1377
Bram Moolenaara9922d62013-05-30 13:01:18 +02001378#define DICT_FLAG_HAS_DEFAULT 0x01
1379#define DICT_FLAG_POP 0x02
1380#define DICT_FLAG_NONE_DEFAULT 0x04
1381#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
1382#define DICT_FLAG_RETURN_PAIR 0x10
1383
Bram Moolenaardb913952012-06-29 12:54:53 +02001384 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001385_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001386{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001387 PyObject *keyObject;
1388 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
1389 PyObject *r;
Bram Moolenaardb913952012-06-29 12:54:53 +02001390 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001391 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001392 dict_T *dict = self->dict;
1393 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001394 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001395
Bram Moolenaara9922d62013-05-30 13:01:18 +02001396 if (flags & DICT_FLAG_HAS_DEFAULT)
1397 {
1398 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1399 return NULL;
1400 }
1401 else
1402 keyObject = args;
1403
1404 if (flags & DICT_FLAG_RETURN_BOOL)
1405 defObject = Py_False;
1406
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001407 if (!(key = StringToChars(keyObject, &todecref)))
1408 return NULL;
1409
1410 if (*key == NUL)
1411 {
1412 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001413 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001414 return NULL;
1415 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001416
Bram Moolenaara9922d62013-05-30 13:01:18 +02001417 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001418
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001419 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001420
Bram Moolenaara9922d62013-05-30 13:01:18 +02001421 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001422 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001423 if (defObject)
1424 {
1425 Py_INCREF(defObject);
1426 return defObject;
1427 }
1428 else
1429 {
1430 PyErr_SetObject(PyExc_KeyError, keyObject);
1431 return NULL;
1432 }
1433 }
1434 else if (flags & DICT_FLAG_RETURN_BOOL)
1435 {
1436 Py_INCREF(Py_True);
1437 return Py_True;
1438 }
1439
1440 di = dict_lookup(hi);
1441
1442 if (!(r = ConvertToPyObject(&di->di_tv)))
1443 return NULL;
1444
1445 if (flags & DICT_FLAG_POP)
1446 {
1447 if (dict->dv_lock)
1448 {
1449 PyErr_SetVim(_("dict is locked"));
1450 Py_DECREF(r);
1451 return NULL;
1452 }
1453
1454 hash_remove(&dict->dv_hashtab, hi);
1455 dictitem_free(di);
1456 }
1457
Bram Moolenaara9922d62013-05-30 13:01:18 +02001458 return r;
1459}
1460
1461 static PyObject *
1462DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1463{
1464 return _DictionaryItem(self, keyObject, 0);
1465}
1466
1467 static int
1468DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1469{
1470 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1471 int r;
1472
1473 r = (rObj == Py_True);
1474
1475 Py_DECREF(Py_True);
1476
1477 return r;
1478}
1479
1480typedef struct
1481{
1482 hashitem_T *ht_array;
1483 long_u ht_used;
1484 hashtab_T *ht;
1485 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001486 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001487} dictiterinfo_T;
1488
1489 static PyObject *
1490DictionaryIterNext(dictiterinfo_T **dii)
1491{
1492 PyObject *r;
1493
1494 if (!(*dii)->todo)
1495 return NULL;
1496
1497 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1498 (*dii)->ht->ht_used != (*dii)->ht_used)
1499 {
1500 PyErr_SetString(PyExc_RuntimeError,
1501 _("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001502 return NULL;
1503 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001504
Bram Moolenaara9922d62013-05-30 13:01:18 +02001505 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1506 ++((*dii)->hi);
1507
1508 --((*dii)->todo);
1509
1510 if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1511 return NULL;
1512
1513 return r;
1514}
1515
1516 static PyObject *
1517DictionaryIter(DictionaryObject *self)
1518{
1519 dictiterinfo_T *dii;
1520 hashtab_T *ht;
1521
1522 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1523 {
1524 PyErr_NoMemory();
1525 return NULL;
1526 }
1527
1528 ht = &self->dict->dv_hashtab;
1529 dii->ht_array = ht->ht_array;
1530 dii->ht_used = ht->ht_used;
1531 dii->ht = ht;
1532 dii->hi = dii->ht_array;
1533 dii->todo = dii->ht_used;
1534
1535 return IterNew(dii,
1536 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1537 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001538}
1539
1540 static PyInt
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001541DictionaryAssItem(
1542 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001543{
1544 char_u *key;
1545 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001546 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001547 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001548 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001549
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001550 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001551 {
1552 PyErr_SetVim(_("dict is locked"));
1553 return -1;
1554 }
1555
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001556 if (!(key = StringToChars(keyObject, &todecref)))
1557 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001558
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001559 if (*key == NUL)
1560 {
1561 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001562 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001563 return -1;
1564 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001565
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001566 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001567
1568 if (valObject == NULL)
1569 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001570 hashitem_T *hi;
1571
Bram Moolenaardb913952012-06-29 12:54:53 +02001572 if (di == NULL)
1573 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001574 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001575 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001576 return -1;
1577 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001578 hi = hash_find(&dict->dv_hashtab, di->di_key);
1579 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001580 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001581 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001582 return 0;
1583 }
1584
1585 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001586 {
1587 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001588 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001589 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001590
1591 if (di == NULL)
1592 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001593 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001594 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001595 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001596 PyErr_NoMemory();
1597 return -1;
1598 }
1599 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001600 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001601
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001602 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001603 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001604 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001605 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001606 dictitem_free(di);
Bram Moolenaardb913952012-06-29 12:54:53 +02001607 PyErr_SetVim(_("failed to add key to dictionary"));
1608 return -1;
1609 }
1610 }
1611 else
1612 clear_tv(&di->di_tv);
1613
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001614 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001615
1616 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001617 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001618 return 0;
1619}
1620
Bram Moolenaara9922d62013-05-30 13:01:18 +02001621typedef PyObject *(*hi_to_py)(hashitem_T *);
1622
Bram Moolenaardb913952012-06-29 12:54:53 +02001623 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001624DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001625{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001626 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001627 long_u todo = dict->dv_hashtab.ht_used;
1628 Py_ssize_t i = 0;
1629 PyObject *r;
1630 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001631 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001632
1633 r = PyList_New(todo);
1634 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1635 {
1636 if (!HASHITEM_EMPTY(hi))
1637 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001638 if (!(newObj = hiconvert(hi)))
1639 {
1640 Py_DECREF(r);
1641 return NULL;
1642 }
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02001643 PyList_SET_ITEM(r, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001644 --todo;
1645 ++i;
1646 }
1647 }
1648 return r;
1649}
1650
Bram Moolenaara9922d62013-05-30 13:01:18 +02001651 static PyObject *
1652dict_key(hashitem_T *hi)
1653{
1654 return PyBytes_FromString((char *)(hi->hi_key));
1655}
1656
1657 static PyObject *
1658DictionaryListKeys(DictionaryObject *self)
1659{
1660 return DictionaryListObjects(self, dict_key);
1661}
1662
1663 static PyObject *
1664dict_val(hashitem_T *hi)
1665{
1666 dictitem_T *di;
1667
1668 di = dict_lookup(hi);
1669 return ConvertToPyObject(&di->di_tv);
1670}
1671
1672 static PyObject *
1673DictionaryListValues(DictionaryObject *self)
1674{
1675 return DictionaryListObjects(self, dict_val);
1676}
1677
1678 static PyObject *
1679dict_item(hashitem_T *hi)
1680{
1681 PyObject *keyObject;
1682 PyObject *valObject;
1683 PyObject *r;
1684
1685 if (!(keyObject = dict_key(hi)))
1686 return NULL;
1687
1688 if (!(valObject = dict_val(hi)))
1689 {
1690 Py_DECREF(keyObject);
1691 return NULL;
1692 }
1693
1694 r = Py_BuildValue("(OO)", keyObject, valObject);
1695
1696 Py_DECREF(keyObject);
1697 Py_DECREF(valObject);
1698
1699 return r;
1700}
1701
1702 static PyObject *
1703DictionaryListItems(DictionaryObject *self)
1704{
1705 return DictionaryListObjects(self, dict_item);
1706}
1707
1708 static PyObject *
1709DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1710{
1711 dict_T *dict = self->dict;
1712
1713 if (dict->dv_lock)
1714 {
1715 PyErr_SetVim(_("dict is locked"));
1716 return NULL;
1717 }
1718
1719 if (kwargs)
1720 {
1721 typval_T tv;
1722
1723 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1724 return NULL;
1725
1726 VimTryStart();
1727 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1728 clear_tv(&tv);
1729 if (VimTryEnd())
1730 return NULL;
1731 }
1732 else
1733 {
1734 PyObject *object;
1735
1736 if (!PyArg_Parse(args, "(O)", &object))
1737 return NULL;
1738
1739 if (PyObject_HasAttrString(object, "keys"))
1740 return DictionaryUpdate(self, NULL, object);
1741 else
1742 {
1743 PyObject *iterator;
1744 PyObject *item;
1745
1746 if (!(iterator = PyObject_GetIter(object)))
1747 return NULL;
1748
1749 while ((item = PyIter_Next(iterator)))
1750 {
1751 PyObject *fast;
1752 PyObject *keyObject;
1753 PyObject *valObject;
1754 PyObject *todecref;
1755 char_u *key;
1756 dictitem_T *di;
1757
1758 if (!(fast = PySequence_Fast(item, "")))
1759 {
1760 Py_DECREF(iterator);
1761 Py_DECREF(item);
1762 return NULL;
1763 }
1764
1765 Py_DECREF(item);
1766
1767 if (PySequence_Fast_GET_SIZE(fast) != 2)
1768 {
1769 Py_DECREF(iterator);
1770 Py_DECREF(fast);
1771 PyErr_SetString(PyExc_ValueError,
1772 _("expected sequence element of size 2"));
1773 return NULL;
1774 }
1775
1776 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1777
1778 if (!(key = StringToChars(keyObject, &todecref)))
1779 {
1780 Py_DECREF(iterator);
1781 Py_DECREF(fast);
1782 return NULL;
1783 }
1784
1785 di = dictitem_alloc(key);
1786
1787 Py_XDECREF(todecref);
1788
1789 if (di == NULL)
1790 {
1791 Py_DECREF(fast);
1792 Py_DECREF(iterator);
1793 PyErr_NoMemory();
1794 return NULL;
1795 }
1796 di->di_tv.v_lock = 0;
1797 di->di_tv.v_type = VAR_UNKNOWN;
1798
1799 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1800
1801 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1802 {
1803 Py_DECREF(iterator);
1804 Py_DECREF(fast);
1805 dictitem_free(di);
1806 return NULL;
1807 }
1808
1809 Py_DECREF(fast);
1810
1811 if (dict_add(dict, di) == FAIL)
1812 {
1813 Py_DECREF(iterator);
1814 dictitem_free(di);
1815 PyErr_SetVim(_("failed to add key to dictionary"));
1816 return NULL;
1817 }
1818 }
1819
1820 Py_DECREF(iterator);
1821
1822 /* Iterator may have finished due to an exception */
1823 if (PyErr_Occurred())
1824 return NULL;
1825 }
1826 }
1827 Py_INCREF(Py_None);
1828 return Py_None;
1829}
1830
1831 static PyObject *
1832DictionaryGet(DictionaryObject *self, PyObject *args)
1833{
1834 return _DictionaryItem(self, args,
1835 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1836}
1837
1838 static PyObject *
1839DictionaryPop(DictionaryObject *self, PyObject *args)
1840{
1841 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1842}
1843
1844 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001845DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001846{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001847 hashitem_T *hi;
1848 PyObject *r;
1849 PyObject *valObject;
1850 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001851
Bram Moolenaarde71b562013-06-02 17:41:54 +02001852 if (self->dict->dv_hashtab.ht_used == 0)
1853 {
1854 PyErr_SetNone(PyExc_KeyError);
1855 return NULL;
1856 }
1857
1858 hi = self->dict->dv_hashtab.ht_array;
1859 while (HASHITEM_EMPTY(hi))
1860 ++hi;
1861
1862 di = dict_lookup(hi);
1863
1864 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001865 return NULL;
1866
Bram Moolenaarde71b562013-06-02 17:41:54 +02001867 if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
1868 {
1869 Py_DECREF(valObject);
1870 return NULL;
1871 }
1872
1873 hash_remove(&self->dict->dv_hashtab, hi);
1874 dictitem_free(di);
1875
1876 return r;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001877}
1878
1879 static PyObject *
1880DictionaryHasKey(DictionaryObject *self, PyObject *args)
1881{
1882 PyObject *keyObject;
1883
1884 if (!PyArg_ParseTuple(args, "O", &keyObject))
1885 return NULL;
1886
1887 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1888}
1889
1890static PySequenceMethods DictionaryAsSeq = {
1891 0, /* sq_length */
1892 0, /* sq_concat */
1893 0, /* sq_repeat */
1894 0, /* sq_item */
1895 0, /* sq_slice */
1896 0, /* sq_ass_item */
1897 0, /* sq_ass_slice */
1898 (objobjproc) DictionaryContains, /* sq_contains */
1899 0, /* sq_inplace_concat */
1900 0, /* sq_inplace_repeat */
1901};
1902
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001903static PyMappingMethods DictionaryAsMapping = {
1904 (lenfunc) DictionaryLength,
1905 (binaryfunc) DictionaryItem,
1906 (objobjargproc) DictionaryAssItem,
1907};
1908
Bram Moolenaardb913952012-06-29 12:54:53 +02001909static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001910 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001911 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
1912 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
1913 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
1914 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
1915 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02001916 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001917 {"has_key", (PyCFunction)DictionaryHasKey, METH_VARARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001918 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1919 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001920};
1921
1922static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001923static PySequenceMethods ListAsSeq;
1924static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001925
1926typedef struct
1927{
1928 PyObject_HEAD
1929 list_T *list;
1930 pylinkedlist_T ref;
1931} ListObject;
1932
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001933#define NEW_LIST(list) ListNew(&ListType, list)
1934
Bram Moolenaardb913952012-06-29 12:54:53 +02001935 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001936ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02001937{
1938 ListObject *self;
1939
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001940 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001941 if (self == NULL)
1942 return NULL;
1943 self->list = list;
1944 ++list->lv_refcount;
1945
1946 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1947
1948 return (PyObject *)(self);
1949}
1950
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001951 static list_T *
1952py_list_alloc()
1953{
1954 list_T *r;
1955
1956 if (!(r = list_alloc()))
1957 {
1958 PyErr_NoMemory();
1959 return NULL;
1960 }
1961 ++r->lv_refcount;
1962
1963 return r;
1964}
1965
1966 static int
1967list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
1968{
1969 PyObject *iterator;
1970 PyObject *item;
1971 listitem_T *li;
1972
1973 if (!(iterator = PyObject_GetIter(obj)))
1974 return -1;
1975
1976 while ((item = PyIter_Next(iterator)))
1977 {
1978 if (!(li = listitem_alloc()))
1979 {
1980 PyErr_NoMemory();
1981 Py_DECREF(item);
1982 Py_DECREF(iterator);
1983 return -1;
1984 }
1985 li->li_tv.v_lock = 0;
1986 li->li_tv.v_type = VAR_UNKNOWN;
1987
1988 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
1989 {
1990 Py_DECREF(item);
1991 Py_DECREF(iterator);
1992 listitem_free(li);
1993 return -1;
1994 }
1995
1996 Py_DECREF(item);
1997
1998 list_append(l, li);
1999 }
2000
2001 Py_DECREF(iterator);
2002
2003 /* Iterator may have finished due to an exception */
2004 if (PyErr_Occurred())
2005 return -1;
2006
2007 return 0;
2008}
2009
2010 static PyObject *
2011ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2012{
2013 list_T *list;
2014 PyObject *obj = NULL;
2015
2016 if (kwargs)
2017 {
2018 PyErr_SetString(PyExc_TypeError,
2019 _("list constructor does not accept keyword arguments"));
2020 return NULL;
2021 }
2022
2023 if (!PyArg_ParseTuple(args, "|O", &obj))
2024 return NULL;
2025
2026 if (!(list = py_list_alloc()))
2027 return NULL;
2028
2029 if (obj)
2030 {
2031 PyObject *lookup_dict;
2032
2033 if (!(lookup_dict = PyDict_New()))
2034 {
2035 list_unref(list);
2036 return NULL;
2037 }
2038
2039 if (list_py_concat(list, obj, lookup_dict) == -1)
2040 {
2041 Py_DECREF(lookup_dict);
2042 list_unref(list);
2043 return NULL;
2044 }
2045
2046 Py_DECREF(lookup_dict);
2047 }
2048
2049 return ListNew(subtype, list);
2050}
2051
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002052 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002053ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002054{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002055 pyll_remove(&self->ref, &lastlist);
2056 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002057
2058 DESTRUCTOR_FINISH(self);
2059}
2060
Bram Moolenaardb913952012-06-29 12:54:53 +02002061 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002062ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002063{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002064 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002065}
2066
2067 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002068ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002069{
2070 listitem_T *li;
2071
Bram Moolenaard6e39182013-05-21 18:30:34 +02002072 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002073 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002074 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002075 return NULL;
2076 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002077 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002078 if (li == NULL)
2079 {
2080 PyErr_SetVim(_("internal error: failed to get vim list item"));
2081 return NULL;
2082 }
2083 return ConvertToPyObject(&li->li_tv);
2084}
2085
2086#define PROC_RANGE \
2087 if (last < 0) {\
2088 if (last < -size) \
2089 last = 0; \
2090 else \
2091 last += size; \
2092 } \
2093 if (first < 0) \
2094 first = 0; \
2095 if (first > size) \
2096 first = size; \
2097 if (last > size) \
2098 last = size;
2099
2100 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002101ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02002102{
2103 PyInt i;
2104 PyInt size = ListLength(self);
2105 PyInt n;
2106 PyObject *list;
2107 int reversed = 0;
2108
2109 PROC_RANGE
2110 if (first >= last)
2111 first = last;
2112
2113 n = last-first;
2114 list = PyList_New(n);
2115 if (list == NULL)
2116 return NULL;
2117
2118 for (i = 0; i < n; ++i)
2119 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02002120 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02002121 if (item == NULL)
2122 {
2123 Py_DECREF(list);
2124 return NULL;
2125 }
2126
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02002127 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002128 }
2129
2130 return list;
2131}
2132
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002133typedef struct
2134{
2135 listwatch_T lw;
2136 list_T *list;
2137} listiterinfo_T;
2138
2139 static void
2140ListIterDestruct(listiterinfo_T *lii)
2141{
2142 list_rem_watch(lii->list, &lii->lw);
2143 PyMem_Free(lii);
2144}
2145
2146 static PyObject *
2147ListIterNext(listiterinfo_T **lii)
2148{
2149 PyObject *r;
2150
2151 if (!((*lii)->lw.lw_item))
2152 return NULL;
2153
2154 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
2155 return NULL;
2156
2157 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2158
2159 return r;
2160}
2161
2162 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002163ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002164{
2165 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002166 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002167
2168 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2169 {
2170 PyErr_NoMemory();
2171 return NULL;
2172 }
2173
2174 list_add_watch(l, &lii->lw);
2175 lii->lw.lw_item = l->lv_first;
2176 lii->list = l;
2177
2178 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002179 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2180 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002181}
2182
Bram Moolenaardb913952012-06-29 12:54:53 +02002183 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002184ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002185{
2186 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002187 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002188 listitem_T *li;
2189 Py_ssize_t length = ListLength(self);
2190
2191 if (l->lv_lock)
2192 {
2193 PyErr_SetVim(_("list is locked"));
2194 return -1;
2195 }
2196 if (index>length || (index==length && obj==NULL))
2197 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002198 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002199 return -1;
2200 }
2201
2202 if (obj == NULL)
2203 {
2204 li = list_find(l, (long) index);
2205 list_remove(l, li, li);
2206 clear_tv(&li->li_tv);
2207 vim_free(li);
2208 return 0;
2209 }
2210
2211 if (ConvertFromPyObject(obj, &tv) == -1)
2212 return -1;
2213
2214 if (index == length)
2215 {
2216 if (list_append_tv(l, &tv) == FAIL)
2217 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002218 clear_tv(&tv);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002219 PyErr_SetVim(_("failed to add item to list"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002220 return -1;
2221 }
2222 }
2223 else
2224 {
2225 li = list_find(l, (long) index);
2226 clear_tv(&li->li_tv);
2227 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002228 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002229 }
2230 return 0;
2231}
2232
2233 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002234ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002235{
2236 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002237 PyObject *iterator;
2238 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02002239 listitem_T *li;
2240 listitem_T *next;
2241 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002242 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002243 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002244
2245 if (l->lv_lock)
2246 {
2247 PyErr_SetVim(_("list is locked"));
2248 return -1;
2249 }
2250
2251 PROC_RANGE
2252
2253 if (first == size)
2254 li = NULL;
2255 else
2256 {
2257 li = list_find(l, (long) first);
2258 if (li == NULL)
2259 {
2260 PyErr_SetVim(_("internal error: no vim list item"));
2261 return -1;
2262 }
2263 if (last > first)
2264 {
2265 i = last - first;
2266 while (i-- && li != NULL)
2267 {
2268 next = li->li_next;
2269 listitem_remove(l, li);
2270 li = next;
2271 }
2272 }
2273 }
2274
2275 if (obj == NULL)
2276 return 0;
2277
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002278 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002279 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02002280
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002281 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002282 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002283 if (ConvertFromPyObject(item, &v) == -1)
2284 {
2285 Py_DECREF(iterator);
2286 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002287 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002288 }
2289 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002290 if (list_insert_tv(l, &v, li) == FAIL)
2291 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002292 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002293 PyErr_SetVim(_("internal error: failed to add item to list"));
2294 return -1;
2295 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002296 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002297 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002298 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02002299 return 0;
2300}
2301
2302 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002303ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002304{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002305 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002306 PyObject *lookup_dict;
2307
2308 if (l->lv_lock)
2309 {
2310 PyErr_SetVim(_("list is locked"));
2311 return NULL;
2312 }
2313
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02002314 if (!(lookup_dict = PyDict_New()))
2315 return NULL;
2316
Bram Moolenaardb913952012-06-29 12:54:53 +02002317 if (list_py_concat(l, obj, lookup_dict) == -1)
2318 {
2319 Py_DECREF(lookup_dict);
2320 return NULL;
2321 }
2322 Py_DECREF(lookup_dict);
2323
2324 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02002325 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002326}
2327
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002328static char *ListAttrs[] = {
2329 "locked",
2330 NULL
2331};
2332
2333 static PyObject *
2334ListDir(PyObject *self)
2335{
2336 return ObjectDir(self, ListAttrs);
2337}
2338
Bram Moolenaar66b79852012-09-21 14:00:35 +02002339 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002340ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002341{
2342 if (val == NULL)
2343 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002344 PyErr_SetString(PyExc_AttributeError,
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002345 _("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002346 return -1;
2347 }
2348
2349 if (strcmp(name, "locked") == 0)
2350 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002351 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002352 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002353 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002354 return -1;
2355 }
2356 else
2357 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002358 int istrue = PyObject_IsTrue(val);
2359 if (istrue == -1)
2360 return -1;
2361 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002362 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002363 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002364 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002365 }
2366 return 0;
2367 }
2368 else
2369 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002370 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002371 return -1;
2372 }
2373}
2374
Bram Moolenaardb913952012-06-29 12:54:53 +02002375static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002376 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2377 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2378 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002379};
2380
2381typedef struct
2382{
2383 PyObject_HEAD
2384 char_u *name;
2385} FunctionObject;
2386
2387static PyTypeObject FunctionType;
2388
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002389#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
2390
Bram Moolenaardb913952012-06-29 12:54:53 +02002391 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002392FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002393{
2394 FunctionObject *self;
2395
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002396 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2397
Bram Moolenaardb913952012-06-29 12:54:53 +02002398 if (self == NULL)
2399 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002400
2401 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002402 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002403 if (!translated_function_exists(name))
2404 {
2405 PyErr_SetString(PyExc_ValueError,
2406 _("unnamed function does not exist"));
2407 return NULL;
2408 }
2409 self->name = vim_strsave(name);
2410 func_ref(self->name);
2411 }
2412 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002413 if ((self->name = get_expanded_name(name,
2414 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2415 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002416 {
Bram Moolenaar018acca2013-05-30 13:37:28 +02002417 PyErr_SetString(PyExc_ValueError, _("function does not exist"));
2418 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002419 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002420
2421 return (PyObject *)(self);
2422}
2423
2424 static PyObject *
2425FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2426{
2427 PyObject *self;
2428 char_u *name;
2429
2430 if (kwargs)
2431 {
2432 PyErr_SetString(PyExc_TypeError,
2433 _("function constructor does not accept keyword arguments"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002434 return NULL;
2435 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002436
2437 if (!PyArg_ParseTuple(args, "s", &name))
2438 return NULL;
2439
2440 self = FunctionNew(subtype, name);
2441
2442 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002443}
2444
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002445 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002446FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002447{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002448 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002449 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002450
2451 DESTRUCTOR_FINISH(self);
2452}
2453
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002454static char *FunctionAttrs[] = {
2455 "softspace",
2456 NULL
2457};
2458
2459 static PyObject *
2460FunctionDir(PyObject *self)
2461{
2462 return ObjectDir(self, FunctionAttrs);
2463}
2464
Bram Moolenaardb913952012-06-29 12:54:53 +02002465 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002466FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002467{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002468 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002469 typval_T args;
2470 typval_T selfdicttv;
2471 typval_T rettv;
2472 dict_T *selfdict = NULL;
2473 PyObject *selfdictObject;
2474 PyObject *result;
2475 int error;
2476
2477 if (ConvertFromPyObject(argsObject, &args) == -1)
2478 return NULL;
2479
2480 if (kwargs != NULL)
2481 {
2482 selfdictObject = PyDict_GetItemString(kwargs, "self");
2483 if (selfdictObject != NULL)
2484 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002485 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002486 {
2487 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002488 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002489 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002490 selfdict = selfdicttv.vval.v_dict;
2491 }
2492 }
2493
Bram Moolenaar71700b82013-05-15 17:49:05 +02002494 Py_BEGIN_ALLOW_THREADS
2495 Python_Lock_Vim();
2496
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002497 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002498 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002499
2500 Python_Release_Vim();
2501 Py_END_ALLOW_THREADS
2502
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002503 if (VimTryEnd())
2504 result = NULL;
2505 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002506 {
2507 result = NULL;
2508 PyErr_SetVim(_("failed to run function"));
2509 }
2510 else
2511 result = ConvertToPyObject(&rettv);
2512
Bram Moolenaardb913952012-06-29 12:54:53 +02002513 clear_tv(&args);
2514 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002515 if (selfdict != NULL)
2516 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002517
2518 return result;
2519}
2520
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002521 static PyObject *
2522FunctionRepr(FunctionObject *self)
2523{
2524 return PyString_FromFormat("<vim.Function '%s'>", self->name);
2525}
2526
Bram Moolenaardb913952012-06-29 12:54:53 +02002527static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002528 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2529 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002530};
2531
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002532/*
2533 * Options object
2534 */
2535
2536static PyTypeObject OptionsType;
2537
2538typedef int (*checkfun)(void *);
2539
2540typedef struct
2541{
2542 PyObject_HEAD
2543 int opt_type;
2544 void *from;
2545 checkfun Check;
2546 PyObject *fromObj;
2547} OptionsObject;
2548
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002549 static int
2550dummy_check(void *arg UNUSED)
2551{
2552 return 0;
2553}
2554
2555 static PyObject *
2556OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2557{
2558 OptionsObject *self;
2559
Bram Moolenaar774267b2013-05-21 20:51:59 +02002560 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002561 if (self == NULL)
2562 return NULL;
2563
2564 self->opt_type = opt_type;
2565 self->from = from;
2566 self->Check = Check;
2567 self->fromObj = fromObj;
2568 if (fromObj)
2569 Py_INCREF(fromObj);
2570
2571 return (PyObject *)(self);
2572}
2573
2574 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002575OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002576{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002577 PyObject_GC_UnTrack((void *)(self));
2578 Py_XDECREF(self->fromObj);
2579 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002580}
2581
2582 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002583OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002584{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002585 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002586 return 0;
2587}
2588
2589 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002590OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002591{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002592 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002593 return 0;
2594}
2595
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002596 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002597OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002598{
2599 char_u *key;
2600 int flags;
2601 long numval;
2602 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002603 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002604
Bram Moolenaard6e39182013-05-21 18:30:34 +02002605 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002606 return NULL;
2607
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002608 if (!(key = StringToChars(keyObject, &todecref)))
2609 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002610
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002611 if (*key == NUL)
2612 {
2613 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002614 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002615 return NULL;
2616 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002617
2618 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002619 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002620
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002621 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002622
2623 if (flags == 0)
2624 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002625 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002626 return NULL;
2627 }
2628
2629 if (flags & SOPT_UNSET)
2630 {
2631 Py_INCREF(Py_None);
2632 return Py_None;
2633 }
2634 else if (flags & SOPT_BOOL)
2635 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002636 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002637 r = numval ? Py_True : Py_False;
2638 Py_INCREF(r);
2639 return r;
2640 }
2641 else if (flags & SOPT_NUM)
2642 return PyInt_FromLong(numval);
2643 else if (flags & SOPT_STRING)
2644 {
2645 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002646 {
2647 PyObject *r = PyBytes_FromString((char *) stringval);
2648 vim_free(stringval);
2649 return r;
2650 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002651 else
2652 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002653 PyErr_SetString(PyExc_RuntimeError,
2654 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002655 return NULL;
2656 }
2657 }
2658 else
2659 {
2660 PyErr_SetVim("Internal error: unknown option type. Should not happen");
2661 return NULL;
2662 }
2663}
2664
2665 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002666set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002667{
2668 char_u *errmsg;
2669
2670 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2671 {
2672 if (VimTryEnd())
2673 return FAIL;
2674 PyErr_SetVim((char *)errmsg);
2675 return FAIL;
2676 }
2677 return OK;
2678}
2679
2680 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002681set_option_value_for(
2682 char_u *key,
2683 int numval,
2684 char_u *stringval,
2685 int opt_flags,
2686 int opt_type,
2687 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002688{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002689 win_T *save_curwin = NULL;
2690 tabpage_T *save_curtab = NULL;
2691 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002692 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002693
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002694 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002695 switch (opt_type)
2696 {
2697 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002698 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02002699 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002700 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002701 if (VimTryEnd())
2702 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002703 PyErr_SetVim("Problem while switching windows.");
2704 return -1;
2705 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002706 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaard6949742013-06-16 14:18:28 +02002707 restore_win(save_curwin, save_curtab, FALSE);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002708 if (r == FAIL)
2709 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002710 break;
2711 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002712 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002713 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002714 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002715 if (r == FAIL)
2716 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002717 break;
2718 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002719 r = set_option_value_err(key, numval, stringval, opt_flags);
2720 if (r == FAIL)
2721 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002722 break;
2723 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002724 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002725}
2726
2727 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002728OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002729{
2730 char_u *key;
2731 int flags;
2732 int opt_flags;
2733 int r = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002734 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002735
Bram Moolenaard6e39182013-05-21 18:30:34 +02002736 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002737 return -1;
2738
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002739 if (!(key = StringToChars(keyObject, &todecref)))
2740 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002741
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002742 if (*key == NUL)
2743 {
2744 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002745 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002746 return -1;
2747 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002748
2749 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002750 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002751
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002752 if (flags == 0)
2753 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002754 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002755 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002756 return -1;
2757 }
2758
2759 if (valObject == NULL)
2760 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002761 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002762 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002763 PyErr_SetString(PyExc_ValueError,
2764 _("unable to unset global option"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002765 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002766 return -1;
2767 }
2768 else if (!(flags & SOPT_GLOBAL))
2769 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002770 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
2771 "without global value"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002772 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002773 return -1;
2774 }
2775 else
2776 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002777 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002778 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002779 return 0;
2780 }
2781 }
2782
Bram Moolenaard6e39182013-05-21 18:30:34 +02002783 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002784
2785 if (flags & SOPT_BOOL)
2786 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002787 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002788
Bram Moolenaarb983f752013-05-15 16:11:50 +02002789 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002790 r = -1;
2791 else
2792 r = set_option_value_for(key, istrue, NULL,
2793 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002794 }
2795 else if (flags & SOPT_NUM)
2796 {
2797 int val;
2798
2799#if PY_MAJOR_VERSION < 3
2800 if (PyInt_Check(valObject))
2801 val = PyInt_AsLong(valObject);
2802 else
2803#endif
2804 if (PyLong_Check(valObject))
2805 val = PyLong_AsLong(valObject);
2806 else
2807 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002808 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002809 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002810 return -1;
2811 }
2812
2813 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002814 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002815 }
2816 else
2817 {
2818 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002819 PyObject *todecref;
2820
2821 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002822 r = set_option_value_for(key, 0, val, opt_flags,
2823 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002824 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002825 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002826 }
2827
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002828 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002829
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002830 return r;
2831}
2832
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002833static PyMappingMethods OptionsAsMapping = {
2834 (lenfunc) NULL,
2835 (binaryfunc) OptionsItem,
2836 (objobjargproc) OptionsAssItem,
2837};
2838
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002839/* Tabpage object
2840 */
2841
2842typedef struct
2843{
2844 PyObject_HEAD
2845 tabpage_T *tab;
2846} TabPageObject;
2847
2848static PyObject *WinListNew(TabPageObject *tabObject);
2849
2850static PyTypeObject TabPageType;
2851
2852 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002853CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002854{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002855 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002856 {
2857 PyErr_SetVim(_("attempt to refer to deleted tab page"));
2858 return -1;
2859 }
2860
2861 return 0;
2862}
2863
2864 static PyObject *
2865TabPageNew(tabpage_T *tab)
2866{
2867 TabPageObject *self;
2868
2869 if (TAB_PYTHON_REF(tab))
2870 {
2871 self = TAB_PYTHON_REF(tab);
2872 Py_INCREF(self);
2873 }
2874 else
2875 {
2876 self = PyObject_NEW(TabPageObject, &TabPageType);
2877 if (self == NULL)
2878 return NULL;
2879 self->tab = tab;
2880 TAB_PYTHON_REF(tab) = self;
2881 }
2882
2883 return (PyObject *)(self);
2884}
2885
2886 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002887TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002888{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002889 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
2890 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002891
2892 DESTRUCTOR_FINISH(self);
2893}
2894
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002895static char *TabPageAttrs[] = {
2896 "windows", "number", "vars", "window", "valid",
2897 NULL
2898};
2899
2900 static PyObject *
2901TabPageDir(PyObject *self)
2902{
2903 return ObjectDir(self, TabPageAttrs);
2904}
2905
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002906 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002907TabPageAttrValid(TabPageObject *self, char *name)
2908{
2909 PyObject *r;
2910
2911 if (strcmp(name, "valid") != 0)
2912 return NULL;
2913
2914 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
2915 Py_INCREF(r);
2916 return r;
2917}
2918
2919 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002920TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002921{
2922 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002923 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002924 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002925 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002926 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002927 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002928 else if (strcmp(name, "window") == 0)
2929 {
2930 /* For current tab window.c does not bother to set or update tp_curwin
2931 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002932 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002933 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002934 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002935 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002936 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002937 else if (strcmp(name, "__members__") == 0)
2938 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002939 return NULL;
2940}
2941
2942 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002943TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002944{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002945 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002946 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002947 else
2948 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002949 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002950
2951 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002952 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2953 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002954 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002955 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002956 }
2957}
2958
2959static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002960 /* name, function, calling, documentation */
2961 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2962 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002963};
2964
2965/*
2966 * Window list object
2967 */
2968
2969static PyTypeObject TabListType;
2970static PySequenceMethods TabListAsSeq;
2971
2972typedef struct
2973{
2974 PyObject_HEAD
2975} TabListObject;
2976
2977 static PyInt
2978TabListLength(PyObject *self UNUSED)
2979{
2980 tabpage_T *tp = first_tabpage;
2981 PyInt n = 0;
2982
2983 while (tp != NULL)
2984 {
2985 ++n;
2986 tp = tp->tp_next;
2987 }
2988
2989 return n;
2990}
2991
2992 static PyObject *
2993TabListItem(PyObject *self UNUSED, PyInt n)
2994{
2995 tabpage_T *tp;
2996
2997 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
2998 if (n == 0)
2999 return TabPageNew(tp);
3000
3001 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
3002 return NULL;
3003}
3004
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +02003005/*
3006 * Window object
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003007 */
3008
3009typedef struct
3010{
3011 PyObject_HEAD
3012 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003013 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003014} WindowObject;
3015
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003016static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003017
3018 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003019CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003020{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003021 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003022 {
3023 PyErr_SetVim(_("attempt to refer to deleted window"));
3024 return -1;
3025 }
3026
3027 return 0;
3028}
3029
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003030 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003031WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02003032{
3033 /* We need to handle deletion of windows underneath us.
3034 * If we add a "w_python*_ref" field to the win_T structure,
3035 * then we can get at it in win_free() in vim. We then
3036 * need to create only ONE Python object per window - if
3037 * we try to create a second, just INCREF the existing one
3038 * and return it. The (single) Python object referring to
3039 * the window is stored in "w_python*_ref".
3040 * On a win_free() we set the Python object's win_T* field
3041 * to an invalid value. We trap all uses of a window
3042 * object, and reject them if the win_T* field is invalid.
3043 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003044 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003045 * w_python_ref and w_python3_ref fields respectively.
3046 */
3047
3048 WindowObject *self;
3049
3050 if (WIN_PYTHON_REF(win))
3051 {
3052 self = WIN_PYTHON_REF(win);
3053 Py_INCREF(self);
3054 }
3055 else
3056 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02003057 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02003058 if (self == NULL)
3059 return NULL;
3060 self->win = win;
3061 WIN_PYTHON_REF(win) = self;
3062 }
3063
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003064 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
3065
Bram Moolenaar971db462013-05-12 18:44:48 +02003066 return (PyObject *)(self);
3067}
3068
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003069 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003070WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003071{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003072 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02003073 if (self->win && self->win != INVALID_WINDOW_VALUE)
3074 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003075 Py_XDECREF(((PyObject *)(self->tabObject)));
3076 PyObject_GC_Del((void *)(self));
3077}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003078
Bram Moolenaar774267b2013-05-21 20:51:59 +02003079 static int
3080WindowTraverse(WindowObject *self, visitproc visit, void *arg)
3081{
3082 Py_VISIT(((PyObject *)(self->tabObject)));
3083 return 0;
3084}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003085
Bram Moolenaar774267b2013-05-21 20:51:59 +02003086 static int
3087WindowClear(WindowObject *self)
3088{
3089 Py_CLEAR(self->tabObject);
3090 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003091}
3092
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003093 static win_T *
3094get_firstwin(TabPageObject *tabObject)
3095{
3096 if (tabObject)
3097 {
3098 if (CheckTabPage(tabObject))
3099 return NULL;
3100 /* For current tab window.c does not bother to set or update tp_firstwin
3101 */
3102 else if (tabObject->tab == curtab)
3103 return firstwin;
3104 else
3105 return tabObject->tab->tp_firstwin;
3106 }
3107 else
3108 return firstwin;
3109}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003110static char *WindowAttrs[] = {
3111 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
3112 "tabpage", "valid",
3113 NULL
3114};
3115
3116 static PyObject *
3117WindowDir(PyObject *self)
3118{
3119 return ObjectDir(self, WindowAttrs);
3120}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003121
Bram Moolenaar971db462013-05-12 18:44:48 +02003122 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003123WindowAttrValid(WindowObject *self, char *name)
3124{
3125 PyObject *r;
3126
3127 if (strcmp(name, "valid") != 0)
3128 return NULL;
3129
3130 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
3131 Py_INCREF(r);
3132 return r;
3133}
3134
3135 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003136WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003137{
3138 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003139 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003140 else if (strcmp(name, "cursor") == 0)
3141 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003142 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003143
3144 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
3145 }
3146 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003147 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003148#ifdef FEAT_WINDOWS
3149 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003150 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003151#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003152#ifdef FEAT_VERTSPLIT
3153 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003154 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003155 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003156 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003157#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02003158 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003159 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003160 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003161 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
3162 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02003163 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003164 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003165 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003166 return NULL;
3167 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003168 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003169 }
3170 else if (strcmp(name, "tabpage") == 0)
3171 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003172 Py_INCREF(self->tabObject);
3173 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003174 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003175 else if (strcmp(name, "__members__") == 0)
3176 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003177 else
3178 return NULL;
3179}
3180
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003181 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003182WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003183{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003184 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003185 return -1;
3186
3187 if (strcmp(name, "buffer") == 0)
3188 {
3189 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
3190 return -1;
3191 }
3192 else if (strcmp(name, "cursor") == 0)
3193 {
3194 long lnum;
3195 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003196
3197 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
3198 return -1;
3199
Bram Moolenaard6e39182013-05-21 18:30:34 +02003200 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003201 {
3202 PyErr_SetVim(_("cursor position outside buffer"));
3203 return -1;
3204 }
3205
3206 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003207 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003208 return -1;
3209
Bram Moolenaard6e39182013-05-21 18:30:34 +02003210 self->win->w_cursor.lnum = lnum;
3211 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003212#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02003213 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003214#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003215 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003216 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003217
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003218 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003219 return 0;
3220 }
3221 else if (strcmp(name, "height") == 0)
3222 {
3223 int height;
3224 win_T *savewin;
3225
3226 if (!PyArg_Parse(val, "i", &height))
3227 return -1;
3228
3229#ifdef FEAT_GUI
3230 need_mouse_correct = TRUE;
3231#endif
3232 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003233 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003234
3235 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003236 win_setheight(height);
3237 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003238 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003239 return -1;
3240
3241 return 0;
3242 }
3243#ifdef FEAT_VERTSPLIT
3244 else if (strcmp(name, "width") == 0)
3245 {
3246 int width;
3247 win_T *savewin;
3248
3249 if (!PyArg_Parse(val, "i", &width))
3250 return -1;
3251
3252#ifdef FEAT_GUI
3253 need_mouse_correct = TRUE;
3254#endif
3255 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003256 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003257
3258 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003259 win_setwidth(width);
3260 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003261 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003262 return -1;
3263
3264 return 0;
3265 }
3266#endif
3267 else
3268 {
3269 PyErr_SetString(PyExc_AttributeError, name);
3270 return -1;
3271 }
3272}
3273
3274 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003275WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003276{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003277 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003278 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003279 else
3280 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003281 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003282
Bram Moolenaar6d216452013-05-12 19:00:41 +02003283 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003284 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003285 (self));
3286 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003287 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003288 }
3289}
3290
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003291static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003292 /* name, function, calling, documentation */
3293 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
3294 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003295};
3296
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003297/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003298 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003299 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003300
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003301static PyTypeObject WinListType;
3302static PySequenceMethods WinListAsSeq;
3303
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003304typedef struct
3305{
3306 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003307 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003308} WinListObject;
3309
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003310 static PyObject *
3311WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003312{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003313 WinListObject *self;
3314
3315 self = PyObject_NEW(WinListObject, &WinListType);
3316 self->tabObject = tabObject;
3317 Py_INCREF(tabObject);
3318
3319 return (PyObject *)(self);
3320}
3321
3322 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003323WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003324{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003325 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003326
3327 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02003328 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003329 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02003330 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003331
3332 DESTRUCTOR_FINISH(self);
3333}
3334
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003335 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003336WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003337{
3338 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003339 PyInt n = 0;
3340
Bram Moolenaard6e39182013-05-21 18:30:34 +02003341 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003342 return -1;
3343
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003344 while (w != NULL)
3345 {
3346 ++n;
3347 w = W_NEXT(w);
3348 }
3349
3350 return n;
3351}
3352
3353 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003354WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003355{
3356 win_T *w;
3357
Bram Moolenaard6e39182013-05-21 18:30:34 +02003358 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003359 return NULL;
3360
3361 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003362 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003363 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003364
3365 PyErr_SetString(PyExc_IndexError, _("no such window"));
3366 return NULL;
3367}
3368
3369/* Convert a Python string into a Vim line.
3370 *
3371 * The result is in allocated memory. All internal nulls are replaced by
3372 * newline characters. It is an error for the string to contain newline
3373 * characters.
3374 *
3375 * On errors, the Python exception data is set, and NULL is returned.
3376 */
3377 static char *
3378StringToLine(PyObject *obj)
3379{
3380 const char *str;
3381 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003382 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003383 PyInt len;
3384 PyInt i;
3385 char *p;
3386
3387 if (obj == NULL || !PyString_Check(obj))
3388 {
3389 PyErr_BadArgument();
3390 return NULL;
3391 }
3392
Bram Moolenaar19e60942011-06-19 00:27:51 +02003393 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
3394 str = PyString_AsString(bytes);
3395 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003396
3397 /*
3398 * Error checking: String must not contain newlines, as we
3399 * are replacing a single line, and we must replace it with
3400 * a single line.
3401 * A trailing newline is removed, so that append(f.readlines()) works.
3402 */
3403 p = memchr(str, '\n', len);
3404 if (p != NULL)
3405 {
3406 if (p == str + len - 1)
3407 --len;
3408 else
3409 {
3410 PyErr_SetVim(_("string cannot contain newlines"));
3411 return NULL;
3412 }
3413 }
3414
3415 /* Create a copy of the string, with internal nulls replaced by
3416 * newline characters, as is the vim convention.
3417 */
3418 save = (char *)alloc((unsigned)(len+1));
3419 if (save == NULL)
3420 {
3421 PyErr_NoMemory();
3422 return NULL;
3423 }
3424
3425 for (i = 0; i < len; ++i)
3426 {
3427 if (str[i] == '\0')
3428 save[i] = '\n';
3429 else
3430 save[i] = str[i];
3431 }
3432
3433 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02003434 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003435
3436 return save;
3437}
3438
3439/* Get a line from the specified buffer. The line number is
3440 * in Vim format (1-based). The line is returned as a Python
3441 * string object.
3442 */
3443 static PyObject *
3444GetBufferLine(buf_T *buf, PyInt n)
3445{
3446 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3447}
3448
3449
3450/* Get a list of lines from the specified buffer. The line numbers
3451 * are in Vim format (1-based). The range is from lo up to, but not
3452 * including, hi. The list is returned as a Python list of string objects.
3453 */
3454 static PyObject *
3455GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3456{
3457 PyInt i;
3458 PyInt n = hi - lo;
3459 PyObject *list = PyList_New(n);
3460
3461 if (list == NULL)
3462 return NULL;
3463
3464 for (i = 0; i < n; ++i)
3465 {
3466 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
3467
3468 /* Error check - was the Python string creation OK? */
3469 if (str == NULL)
3470 {
3471 Py_DECREF(list);
3472 return NULL;
3473 }
3474
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02003475 PyList_SET_ITEM(list, i, str);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003476 }
3477
3478 /* The ownership of the Python list is passed to the caller (ie,
3479 * the caller should Py_DECREF() the object when it is finished
3480 * with it).
3481 */
3482
3483 return list;
3484}
3485
3486/*
3487 * Check if deleting lines made the cursor position invalid.
3488 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3489 * deleted).
3490 */
3491 static void
3492py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3493{
3494 if (curwin->w_cursor.lnum >= lo)
3495 {
3496 /* Adjust the cursor position if it's in/after the changed
3497 * lines. */
3498 if (curwin->w_cursor.lnum >= hi)
3499 {
3500 curwin->w_cursor.lnum += extra;
3501 check_cursor_col();
3502 }
3503 else if (extra < 0)
3504 {
3505 curwin->w_cursor.lnum = lo;
3506 check_cursor();
3507 }
3508 else
3509 check_cursor_col();
3510 changed_cline_bef_curs();
3511 }
3512 invalidate_botline();
3513}
3514
Bram Moolenaar19e60942011-06-19 00:27:51 +02003515/*
3516 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003517 * in Vim format (1-based). The replacement line is given as
3518 * a Python string object. The object is checked for validity
3519 * and correct format. Errors are returned as a value of FAIL.
3520 * The return value is OK on success.
3521 * If OK is returned and len_change is not NULL, *len_change
3522 * is set to the change in the buffer length.
3523 */
3524 static int
3525SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3526{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003527 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003528 * There are three cases:
3529 * 1. NULL, or None - this is a deletion.
3530 * 2. A string - this is a replacement.
3531 * 3. Anything else - this is an error.
3532 */
3533 if (line == Py_None || line == NULL)
3534 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003535 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003536
3537 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003538 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003539
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003540 VimTryStart();
3541
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003542 if (u_savedel((linenr_T)n, 1L) == FAIL)
3543 PyErr_SetVim(_("cannot save undo information"));
3544 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
3545 PyErr_SetVim(_("cannot delete line"));
3546 else
3547 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003548 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003549 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3550 deleted_lines_mark((linenr_T)n, 1L);
3551 }
3552
Bram Moolenaar105bc352013-05-17 16:03:57 +02003553 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003554
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003555 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003556 return FAIL;
3557
3558 if (len_change)
3559 *len_change = -1;
3560
3561 return OK;
3562 }
3563 else if (PyString_Check(line))
3564 {
3565 char *save = StringToLine(line);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003566 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003567
3568 if (save == NULL)
3569 return FAIL;
3570
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003571 VimTryStart();
3572
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003573 /* We do not need to free "save" if ml_replace() consumes it. */
3574 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003575 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003576
3577 if (u_savesub((linenr_T)n) == FAIL)
3578 {
3579 PyErr_SetVim(_("cannot save undo information"));
3580 vim_free(save);
3581 }
3582 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3583 {
3584 PyErr_SetVim(_("cannot replace line"));
3585 vim_free(save);
3586 }
3587 else
3588 changed_bytes((linenr_T)n, 0);
3589
Bram Moolenaar105bc352013-05-17 16:03:57 +02003590 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003591
3592 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003593 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003594 check_cursor_col();
3595
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003596 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003597 return FAIL;
3598
3599 if (len_change)
3600 *len_change = 0;
3601
3602 return OK;
3603 }
3604 else
3605 {
3606 PyErr_BadArgument();
3607 return FAIL;
3608 }
3609}
3610
Bram Moolenaar19e60942011-06-19 00:27:51 +02003611/* Replace a range of lines in the specified buffer. The line numbers are in
3612 * Vim format (1-based). The range is from lo up to, but not including, hi.
3613 * The replacement lines are given as a Python list of string objects. The
3614 * list is checked for validity and correct format. Errors are returned as a
3615 * value of FAIL. The return value is OK on success.
3616 * If OK is returned and len_change is not NULL, *len_change
3617 * is set to the change in the buffer length.
3618 */
3619 static int
3620SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
3621{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003622 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003623 * There are three cases:
3624 * 1. NULL, or None - this is a deletion.
3625 * 2. A list - this is a replacement.
3626 * 3. Anything else - this is an error.
3627 */
3628 if (list == Py_None || list == NULL)
3629 {
3630 PyInt i;
3631 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003632 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003633
3634 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003635 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003636 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003637
3638 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
3639 PyErr_SetVim(_("cannot save undo information"));
3640 else
3641 {
3642 for (i = 0; i < n; ++i)
3643 {
3644 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3645 {
3646 PyErr_SetVim(_("cannot delete line"));
3647 break;
3648 }
3649 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003650 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003651 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3652 deleted_lines_mark((linenr_T)lo, (long)i);
3653 }
3654
Bram Moolenaar105bc352013-05-17 16:03:57 +02003655 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003656
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003657 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003658 return FAIL;
3659
3660 if (len_change)
3661 *len_change = -n;
3662
3663 return OK;
3664 }
3665 else if (PyList_Check(list))
3666 {
3667 PyInt i;
3668 PyInt new_len = PyList_Size(list);
3669 PyInt old_len = hi - lo;
3670 PyInt extra = 0; /* lines added to text, can be negative */
3671 char **array;
3672 buf_T *savebuf;
3673
3674 if (new_len == 0) /* avoid allocating zero bytes */
3675 array = NULL;
3676 else
3677 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003678 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003679 if (array == NULL)
3680 {
3681 PyErr_NoMemory();
3682 return FAIL;
3683 }
3684 }
3685
3686 for (i = 0; i < new_len; ++i)
3687 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003688 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003689
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003690 if (!(line = PyList_GetItem(list, i)) ||
3691 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003692 {
3693 while (i)
3694 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003695 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003696 return FAIL;
3697 }
3698 }
3699
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003700 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003701 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003702
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003703 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003704 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003705
3706 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
3707 PyErr_SetVim(_("cannot save undo information"));
3708
3709 /* If the size of the range is reducing (ie, new_len < old_len) we
3710 * need to delete some old_len. We do this at the start, by
3711 * repeatedly deleting line "lo".
3712 */
3713 if (!PyErr_Occurred())
3714 {
3715 for (i = 0; i < old_len - new_len; ++i)
3716 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3717 {
3718 PyErr_SetVim(_("cannot delete line"));
3719 break;
3720 }
3721 extra -= i;
3722 }
3723
3724 /* For as long as possible, replace the existing old_len with the
3725 * new old_len. This is a more efficient operation, as it requires
3726 * less memory allocation and freeing.
3727 */
3728 if (!PyErr_Occurred())
3729 {
3730 for (i = 0; i < old_len && i < new_len; ++i)
3731 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3732 == FAIL)
3733 {
3734 PyErr_SetVim(_("cannot replace line"));
3735 break;
3736 }
3737 }
3738 else
3739 i = 0;
3740
3741 /* Now we may need to insert the remaining new old_len. If we do, we
3742 * must free the strings as we finish with them (we can't pass the
3743 * responsibility to vim in this case).
3744 */
3745 if (!PyErr_Occurred())
3746 {
3747 while (i < new_len)
3748 {
3749 if (ml_append((linenr_T)(lo + i - 1),
3750 (char_u *)array[i], 0, FALSE) == FAIL)
3751 {
3752 PyErr_SetVim(_("cannot insert line"));
3753 break;
3754 }
3755 vim_free(array[i]);
3756 ++i;
3757 ++extra;
3758 }
3759 }
3760
3761 /* Free any left-over old_len, as a result of an error */
3762 while (i < new_len)
3763 {
3764 vim_free(array[i]);
3765 ++i;
3766 }
3767
3768 /* Free the array of old_len. All of its contents have now
3769 * been dealt with (either freed, or the responsibility passed
3770 * to vim.
3771 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003772 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003773
3774 /* Adjust marks. Invalidate any which lie in the
3775 * changed range, and move any in the remainder of the buffer.
3776 */
3777 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3778 (long)MAXLNUM, (long)extra);
3779 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3780
Bram Moolenaar105bc352013-05-17 16:03:57 +02003781 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003782 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3783
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003784 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003785 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003786
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003787 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003788 return FAIL;
3789
3790 if (len_change)
3791 *len_change = new_len - old_len;
3792
3793 return OK;
3794 }
3795 else
3796 {
3797 PyErr_BadArgument();
3798 return FAIL;
3799 }
3800}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003801
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003802/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003803 * The line number is in Vim format (1-based). The lines to be inserted are
3804 * given as a Python list of string objects or as a single string. The lines
3805 * to be added are checked for validity and correct format. Errors are
3806 * returned as a value of FAIL. The return value is OK on success.
3807 * If OK is returned and len_change is not NULL, *len_change
3808 * is set to the change in the buffer length.
3809 */
3810 static int
3811InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3812{
3813 /* First of all, we check the type of the supplied Python object.
3814 * It must be a string or a list, or the call is in error.
3815 */
3816 if (PyString_Check(lines))
3817 {
3818 char *str = StringToLine(lines);
3819 buf_T *savebuf;
3820
3821 if (str == NULL)
3822 return FAIL;
3823
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003824 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003825 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003826 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003827
3828 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
3829 PyErr_SetVim(_("cannot save undo information"));
3830 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
3831 PyErr_SetVim(_("cannot insert line"));
3832 else
3833 appended_lines_mark((linenr_T)n, 1L);
3834
3835 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003836 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003837 update_screen(VALID);
3838
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003839 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003840 return FAIL;
3841
3842 if (len_change)
3843 *len_change = 1;
3844
3845 return OK;
3846 }
3847 else if (PyList_Check(lines))
3848 {
3849 PyInt i;
3850 PyInt size = PyList_Size(lines);
3851 char **array;
3852 buf_T *savebuf;
3853
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003854 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003855 if (array == NULL)
3856 {
3857 PyErr_NoMemory();
3858 return FAIL;
3859 }
3860
3861 for (i = 0; i < size; ++i)
3862 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003863 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003864
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003865 if (!(line = PyList_GetItem(lines, i)) ||
3866 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003867 {
3868 while (i)
3869 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003870 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003871 return FAIL;
3872 }
3873 }
3874
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003875 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003876 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003877 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003878
3879 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
3880 PyErr_SetVim(_("cannot save undo information"));
3881 else
3882 {
3883 for (i = 0; i < size; ++i)
3884 {
3885 if (ml_append((linenr_T)(n + i),
3886 (char_u *)array[i], 0, FALSE) == FAIL)
3887 {
3888 PyErr_SetVim(_("cannot insert line"));
3889
3890 /* Free the rest of the lines */
3891 while (i < size)
3892 vim_free(array[i++]);
3893
3894 break;
3895 }
3896 vim_free(array[i]);
3897 }
3898 if (i > 0)
3899 appended_lines_mark((linenr_T)n, (long)i);
3900 }
3901
3902 /* Free the array of lines. All of its contents have now
3903 * been freed.
3904 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003905 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003906
Bram Moolenaar105bc352013-05-17 16:03:57 +02003907 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003908 update_screen(VALID);
3909
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003910 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003911 return FAIL;
3912
3913 if (len_change)
3914 *len_change = size;
3915
3916 return OK;
3917 }
3918 else
3919 {
3920 PyErr_BadArgument();
3921 return FAIL;
3922 }
3923}
3924
3925/*
3926 * Common routines for buffers and line ranges
3927 * -------------------------------------------
3928 */
3929
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003930typedef struct
3931{
3932 PyObject_HEAD
3933 buf_T *buf;
3934} BufferObject;
3935
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003936 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003937CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003938{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003939 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003940 {
3941 PyErr_SetVim(_("attempt to refer to deleted buffer"));
3942 return -1;
3943 }
3944
3945 return 0;
3946}
3947
3948 static PyObject *
3949RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3950{
3951 if (CheckBuffer(self))
3952 return NULL;
3953
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003954 if (end == -1)
3955 end = self->buf->b_ml.ml_line_count;
3956
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003957 if (n < 0)
3958 n += end - start + 1;
3959
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003960 if (n < 0 || n > end - start)
3961 {
3962 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3963 return NULL;
3964 }
3965
3966 return GetBufferLine(self->buf, n+start);
3967}
3968
3969 static PyObject *
3970RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3971{
3972 PyInt size;
3973
3974 if (CheckBuffer(self))
3975 return NULL;
3976
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003977 if (end == -1)
3978 end = self->buf->b_ml.ml_line_count;
3979
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003980 size = end - start + 1;
3981
3982 if (lo < 0)
3983 lo = 0;
3984 else if (lo > size)
3985 lo = size;
3986 if (hi < 0)
3987 hi = 0;
3988 if (hi < lo)
3989 hi = lo;
3990 else if (hi > size)
3991 hi = size;
3992
3993 return GetBufferLineList(self->buf, lo+start, hi+start);
3994}
3995
3996 static PyInt
3997RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3998{
3999 PyInt len_change;
4000
4001 if (CheckBuffer(self))
4002 return -1;
4003
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004004 if (end == -1)
4005 end = self->buf->b_ml.ml_line_count;
4006
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004007 if (n < 0)
4008 n += end - start + 1;
4009
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004010 if (n < 0 || n > end - start)
4011 {
4012 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
4013 return -1;
4014 }
4015
4016 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
4017 return -1;
4018
4019 if (new_end)
4020 *new_end = end + len_change;
4021
4022 return 0;
4023}
4024
Bram Moolenaar19e60942011-06-19 00:27:51 +02004025 static PyInt
4026RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
4027{
4028 PyInt size;
4029 PyInt len_change;
4030
4031 /* Self must be a valid buffer */
4032 if (CheckBuffer(self))
4033 return -1;
4034
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004035 if (end == -1)
4036 end = self->buf->b_ml.ml_line_count;
4037
Bram Moolenaar19e60942011-06-19 00:27:51 +02004038 /* Sort out the slice range */
4039 size = end - start + 1;
4040
4041 if (lo < 0)
4042 lo = 0;
4043 else if (lo > size)
4044 lo = size;
4045 if (hi < 0)
4046 hi = 0;
4047 if (hi < lo)
4048 hi = lo;
4049 else if (hi > size)
4050 hi = size;
4051
4052 if (SetBufferLineList(self->buf, lo + start, hi + start,
4053 val, &len_change) == FAIL)
4054 return -1;
4055
4056 if (new_end)
4057 *new_end = end + len_change;
4058
4059 return 0;
4060}
4061
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004062
4063 static PyObject *
4064RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
4065{
4066 PyObject *lines;
4067 PyInt len_change;
4068 PyInt max;
4069 PyInt n;
4070
4071 if (CheckBuffer(self))
4072 return NULL;
4073
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004074 if (end == -1)
4075 end = self->buf->b_ml.ml_line_count;
4076
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004077 max = n = end - start + 1;
4078
4079 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
4080 return NULL;
4081
4082 if (n < 0 || n > max)
4083 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004084 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004085 return NULL;
4086 }
4087
4088 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
4089 return NULL;
4090
4091 if (new_end)
4092 *new_end = end + len_change;
4093
4094 Py_INCREF(Py_None);
4095 return Py_None;
4096}
4097
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004098/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004099 */
4100
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004101static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004102static PySequenceMethods RangeAsSeq;
4103static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004104
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004105typedef struct
4106{
4107 PyObject_HEAD
4108 BufferObject *buf;
4109 PyInt start;
4110 PyInt end;
4111} RangeObject;
4112
4113 static PyObject *
4114RangeNew(buf_T *buf, PyInt start, PyInt end)
4115{
4116 BufferObject *bufr;
4117 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004118 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004119 if (self == NULL)
4120 return NULL;
4121
4122 bufr = (BufferObject *)BufferNew(buf);
4123 if (bufr == NULL)
4124 {
4125 Py_DECREF(self);
4126 return NULL;
4127 }
4128 Py_INCREF(bufr);
4129
4130 self->buf = bufr;
4131 self->start = start;
4132 self->end = end;
4133
4134 return (PyObject *)(self);
4135}
4136
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004137 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004138RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004139{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004140 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004141 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02004142 PyObject_GC_Del((void *)(self));
4143}
4144
4145 static int
4146RangeTraverse(RangeObject *self, visitproc visit, void *arg)
4147{
4148 Py_VISIT(((PyObject *)(self->buf)));
4149 return 0;
4150}
4151
4152 static int
4153RangeClear(RangeObject *self)
4154{
4155 Py_CLEAR(self->buf);
4156 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004157}
4158
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004159 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004160RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004161{
4162 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004163 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004164 return -1; /* ??? */
4165
Bram Moolenaard6e39182013-05-21 18:30:34 +02004166 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004167}
4168
4169 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004170RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004171{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004172 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004173}
4174
4175 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004176RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004177{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004178 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004179}
4180
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004181static char *RangeAttrs[] = {
4182 "start", "end",
4183 NULL
4184};
4185
4186 static PyObject *
4187RangeDir(PyObject *self)
4188{
4189 return ObjectDir(self, RangeAttrs);
4190}
4191
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004192 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004193RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004194{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004195 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004196}
4197
4198 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004199RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004200{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004201 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004202 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
4203 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004204 else
4205 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004206 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004207
4208 if (name == NULL)
4209 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004210
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004211 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02004212 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004213 }
4214}
4215
4216static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004217 /* name, function, calling, documentation */
4218 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004219 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
4220 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004221};
4222
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004223static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004224static PySequenceMethods BufferAsSeq;
4225static PyMappingMethods BufferAsMapping;
4226
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004227 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02004228BufferNew(buf_T *buf)
4229{
4230 /* We need to handle deletion of buffers underneath us.
4231 * If we add a "b_python*_ref" field to the buf_T structure,
4232 * then we can get at it in buf_freeall() in vim. We then
4233 * need to create only ONE Python object per buffer - if
4234 * we try to create a second, just INCREF the existing one
4235 * and return it. The (single) Python object referring to
4236 * the buffer is stored in "b_python*_ref".
4237 * Question: what to do on a buf_freeall(). We'll probably
4238 * have to either delete the Python object (DECREF it to
4239 * zero - a bad idea, as it leaves dangling refs!) or
4240 * set the buf_T * value to an invalid value (-1?), which
4241 * means we need checks in all access functions... Bah.
4242 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004243 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02004244 * b_python_ref and b_python3_ref fields respectively.
4245 */
4246
4247 BufferObject *self;
4248
4249 if (BUF_PYTHON_REF(buf) != NULL)
4250 {
4251 self = BUF_PYTHON_REF(buf);
4252 Py_INCREF(self);
4253 }
4254 else
4255 {
4256 self = PyObject_NEW(BufferObject, &BufferType);
4257 if (self == NULL)
4258 return NULL;
4259 self->buf = buf;
4260 BUF_PYTHON_REF(buf) = self;
4261 }
4262
4263 return (PyObject *)(self);
4264}
4265
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004266 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004267BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004268{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004269 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
4270 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004271
4272 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004273}
4274
Bram Moolenaar971db462013-05-12 18:44:48 +02004275 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004276BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02004277{
4278 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004279 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02004280 return -1; /* ??? */
4281
Bram Moolenaard6e39182013-05-21 18:30:34 +02004282 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02004283}
4284
4285 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004286BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02004287{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004288 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004289}
4290
4291 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004292BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02004293{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004294 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004295}
4296
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004297static char *BufferAttrs[] = {
4298 "name", "number", "vars", "options", "valid",
4299 NULL
4300};
4301
4302 static PyObject *
4303BufferDir(PyObject *self)
4304{
4305 return ObjectDir(self, BufferAttrs);
4306}
4307
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004308 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004309BufferAttrValid(BufferObject *self, char *name)
4310{
4311 PyObject *r;
4312
4313 if (strcmp(name, "valid") != 0)
4314 return NULL;
4315
4316 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
4317 Py_INCREF(r);
4318 return r;
4319}
4320
4321 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004322BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004323{
4324 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02004325 return PyString_FromString((self->buf->b_ffname == NULL
4326 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004327 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004328 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004329 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004330 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004331 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004332 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
4333 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004334 else if (strcmp(name, "__members__") == 0)
4335 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004336 else
4337 return NULL;
4338}
4339
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004340 static int
4341BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
4342{
4343 if (CheckBuffer(self))
4344 return -1;
4345
4346 if (strcmp(name, "name") == 0)
4347 {
4348 char_u *val;
4349 aco_save_T aco;
4350 int r;
4351 PyObject *todecref;
4352
4353 if (!(val = StringToChars(valObject, &todecref)))
4354 return -1;
4355
4356 VimTryStart();
4357 /* Using aucmd_*: autocommands will be executed by rename_buffer */
4358 aucmd_prepbuf(&aco, self->buf);
4359 r = rename_buffer(val);
4360 aucmd_restbuf(&aco);
4361 Py_XDECREF(todecref);
4362 if (VimTryEnd())
4363 return -1;
4364
4365 if (r == FAIL)
4366 {
4367 PyErr_SetVim(_("failed to rename buffer"));
4368 return -1;
4369 }
4370 return 0;
4371 }
4372 else
4373 {
4374 PyErr_SetString(PyExc_AttributeError, name);
4375 return -1;
4376 }
4377}
4378
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004379 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004380BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004381{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004382 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004383}
4384
4385 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004386BufferMark(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004387{
4388 pos_T *posp;
4389 char *pmark;
4390 char mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004391 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004392
Bram Moolenaard6e39182013-05-21 18:30:34 +02004393 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004394 return NULL;
4395
4396 if (!PyArg_ParseTuple(args, "s", &pmark))
4397 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004398
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004399 if (STRLEN(pmark) != 1)
4400 {
4401 PyErr_SetString(PyExc_ValueError,
4402 _("mark name must be a single character"));
4403 return NULL;
4404 }
4405
4406 mark = *pmark;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004407 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004408 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004409 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004410 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004411 if (VimTryEnd())
4412 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004413
4414 if (posp == NULL)
4415 {
4416 PyErr_SetVim(_("invalid mark name"));
4417 return NULL;
4418 }
4419
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004420 if (posp->lnum <= 0)
4421 {
4422 /* Or raise an error? */
4423 Py_INCREF(Py_None);
4424 return Py_None;
4425 }
4426
4427 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4428}
4429
4430 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004431BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004432{
4433 PyInt start;
4434 PyInt end;
4435
Bram Moolenaard6e39182013-05-21 18:30:34 +02004436 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004437 return NULL;
4438
4439 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4440 return NULL;
4441
Bram Moolenaard6e39182013-05-21 18:30:34 +02004442 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004443}
4444
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004445 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004446BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004447{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004448 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004449 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004450 else
4451 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004452 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004453
4454 if (name == NULL)
4455 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004456
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004457 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004458 }
4459}
4460
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004461static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004462 /* name, function, calling, documentation */
4463 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
4464 {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" },
4465 {"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 +02004466 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4467 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004468};
4469
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004470/*
4471 * Buffer list object - Implementation
4472 */
4473
4474static PyTypeObject BufMapType;
4475
4476typedef struct
4477{
4478 PyObject_HEAD
4479} BufMapObject;
4480
4481 static PyInt
4482BufMapLength(PyObject *self UNUSED)
4483{
4484 buf_T *b = firstbuf;
4485 PyInt n = 0;
4486
4487 while (b)
4488 {
4489 ++n;
4490 b = b->b_next;
4491 }
4492
4493 return n;
4494}
4495
4496 static PyObject *
4497BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4498{
4499 buf_T *b;
4500 int bnr;
4501
4502#if PY_MAJOR_VERSION < 3
4503 if (PyInt_Check(keyObject))
4504 bnr = PyInt_AsLong(keyObject);
4505 else
4506#endif
4507 if (PyLong_Check(keyObject))
4508 bnr = PyLong_AsLong(keyObject);
4509 else
4510 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004511 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004512 return NULL;
4513 }
4514
4515 b = buflist_findnr(bnr);
4516
4517 if (b)
4518 return BufferNew(b);
4519 else
4520 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004521 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004522 return NULL;
4523 }
4524}
4525
4526 static void
4527BufMapIterDestruct(PyObject *buffer)
4528{
4529 /* Iteration was stopped before all buffers were processed */
4530 if (buffer)
4531 {
4532 Py_DECREF(buffer);
4533 }
4534}
4535
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004536 static int
4537BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4538{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004539 if (buffer)
4540 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004541 return 0;
4542}
4543
4544 static int
4545BufMapIterClear(PyObject **buffer)
4546{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004547 if (*buffer)
4548 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004549 return 0;
4550}
4551
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004552 static PyObject *
4553BufMapIterNext(PyObject **buffer)
4554{
4555 PyObject *next;
4556 PyObject *r;
4557
4558 if (!*buffer)
4559 return NULL;
4560
4561 r = *buffer;
4562
4563 if (CheckBuffer((BufferObject *)(r)))
4564 {
4565 *buffer = NULL;
4566 return NULL;
4567 }
4568
4569 if (!((BufferObject *)(r))->buf->b_next)
4570 next = NULL;
4571 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
4572 return NULL;
4573 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004574 /* Do not increment reference: we no longer hold it (decref), but whoever
4575 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004576 return r;
4577}
4578
4579 static PyObject *
4580BufMapIter(PyObject *self UNUSED)
4581{
4582 PyObject *buffer;
4583
4584 buffer = BufferNew(firstbuf);
4585 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004586 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4587 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004588}
4589
4590static PyMappingMethods BufMapAsMapping = {
4591 (lenfunc) BufMapLength,
4592 (binaryfunc) BufMapItem,
4593 (objobjargproc) 0,
4594};
4595
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004596/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004597 */
4598
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004599static char *CurrentAttrs[] = {
4600 "buffer", "window", "line", "range", "tabpage",
4601 NULL
4602};
4603
4604 static PyObject *
4605CurrentDir(PyObject *self)
4606{
4607 return ObjectDir(self, CurrentAttrs);
4608}
4609
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004610 static PyObject *
4611CurrentGetattr(PyObject *self UNUSED, char *name)
4612{
4613 if (strcmp(name, "buffer") == 0)
4614 return (PyObject *)BufferNew(curbuf);
4615 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004616 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004617 else if (strcmp(name, "tabpage") == 0)
4618 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004619 else if (strcmp(name, "line") == 0)
4620 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4621 else if (strcmp(name, "range") == 0)
4622 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004623 else if (strcmp(name, "__members__") == 0)
4624 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004625 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004626#if PY_MAJOR_VERSION < 3
4627 return Py_FindMethod(WindowMethods, self, name);
4628#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004629 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004630#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004631}
4632
4633 static int
4634CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
4635{
4636 if (strcmp(name, "line") == 0)
4637 {
4638 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
4639 return -1;
4640
4641 return 0;
4642 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004643 else if (strcmp(name, "buffer") == 0)
4644 {
4645 int count;
4646
4647 if (value->ob_type != &BufferType)
4648 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004649 PyErr_SetString(PyExc_TypeError, _("expected vim.Buffer object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004650 return -1;
4651 }
4652
4653 if (CheckBuffer((BufferObject *)(value)))
4654 return -1;
4655 count = ((BufferObject *)(value))->buf->b_fnum;
4656
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004657 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004658 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4659 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004660 if (VimTryEnd())
4661 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004662 PyErr_SetVim(_("failed to switch to given buffer"));
4663 return -1;
4664 }
4665
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004666 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004667 }
4668 else if (strcmp(name, "window") == 0)
4669 {
4670 int count;
4671
4672 if (value->ob_type != &WindowType)
4673 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004674 PyErr_SetString(PyExc_TypeError, _("expected vim.Window object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004675 return -1;
4676 }
4677
4678 if (CheckWindow((WindowObject *)(value)))
4679 return -1;
4680 count = get_win_number(((WindowObject *)(value))->win, firstwin);
4681
4682 if (!count)
4683 {
4684 PyErr_SetString(PyExc_ValueError,
4685 _("failed to find window in the current tab page"));
4686 return -1;
4687 }
4688
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004689 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004690 win_goto(((WindowObject *)(value))->win);
4691 if (((WindowObject *)(value))->win != curwin)
4692 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004693 if (VimTryEnd())
4694 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004695 PyErr_SetString(PyExc_RuntimeError,
4696 _("did not switch to the specified window"));
4697 return -1;
4698 }
4699
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004700 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004701 }
4702 else if (strcmp(name, "tabpage") == 0)
4703 {
4704 if (value->ob_type != &TabPageType)
4705 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004706 PyErr_SetString(PyExc_TypeError, _("expected vim.TabPage object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004707 return -1;
4708 }
4709
4710 if (CheckTabPage((TabPageObject *)(value)))
4711 return -1;
4712
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004713 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004714 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
4715 if (((TabPageObject *)(value))->tab != curtab)
4716 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004717 if (VimTryEnd())
4718 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004719 PyErr_SetString(PyExc_RuntimeError,
4720 _("did not switch to the specified tab page"));
4721 return -1;
4722 }
4723
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004724 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004725 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004726 else
4727 {
4728 PyErr_SetString(PyExc_AttributeError, name);
4729 return -1;
4730 }
4731}
4732
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004733static struct PyMethodDef CurrentMethods[] = {
4734 /* name, function, calling, documentation */
4735 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4736 { NULL, NULL, 0, NULL}
4737};
4738
Bram Moolenaardb913952012-06-29 12:54:53 +02004739 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004740init_range_cmd(exarg_T *eap)
4741{
4742 RangeStart = eap->line1;
4743 RangeEnd = eap->line2;
4744}
4745
4746 static void
4747init_range_eval(typval_T *rettv UNUSED)
4748{
4749 RangeStart = (PyInt) curwin->w_cursor.lnum;
4750 RangeEnd = RangeStart;
4751}
4752
4753 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004754run_cmd(const char *cmd, void *arg UNUSED
4755#ifdef PY_CAN_RECURSE
4756 , PyGILState_STATE *pygilstate UNUSED
4757#endif
4758 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004759{
4760 PyRun_SimpleString((char *) cmd);
4761}
4762
4763static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4764static int code_hdr_len = 30;
4765
4766 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004767run_do(const char *cmd, void *arg UNUSED
4768#ifdef PY_CAN_RECURSE
4769 , PyGILState_STATE *pygilstate
4770#endif
4771 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004772{
4773 PyInt lnum;
4774 size_t len;
4775 char *code;
4776 int status;
4777 PyObject *pyfunc, *pymain;
4778
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004779 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004780 {
4781 EMSG(_("cannot save undo information"));
4782 return;
4783 }
4784
4785 len = code_hdr_len + STRLEN(cmd);
4786 code = PyMem_New(char, len + 1);
4787 memcpy(code, code_hdr, code_hdr_len);
4788 STRCPY(code + code_hdr_len, cmd);
4789 status = PyRun_SimpleString(code);
4790 PyMem_Free(code);
4791
4792 if (status)
4793 {
4794 EMSG(_("failed to run the code"));
4795 return;
4796 }
4797
4798 status = 0;
4799 pymain = PyImport_AddModule("__main__");
4800 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004801#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004802 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004803#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004804
4805 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4806 {
4807 PyObject *line, *linenr, *ret;
4808
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004809#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004810 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004811#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004812 if (!(line = GetBufferLine(curbuf, lnum)))
4813 goto err;
4814 if (!(linenr = PyInt_FromLong((long) lnum)))
4815 {
4816 Py_DECREF(line);
4817 goto err;
4818 }
4819 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4820 Py_DECREF(line);
4821 Py_DECREF(linenr);
4822 if (!ret)
4823 goto err;
4824
4825 if (ret != Py_None)
4826 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
4827 goto err;
4828
4829 Py_XDECREF(ret);
4830 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004831#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004832 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004833#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004834 }
4835 goto out;
4836err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004837#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004838 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004839#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004840 PyErr_PrintEx(0);
4841 PythonIO_Flush();
4842 status = 1;
4843out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004844#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004845 if (!status)
4846 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004847#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004848 Py_DECREF(pyfunc);
4849 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
4850 if (status)
4851 return;
4852 check_cursor();
4853 update_curbuf(NOT_VALID);
4854}
4855
4856 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004857run_eval(const char *cmd, typval_T *rettv
4858#ifdef PY_CAN_RECURSE
4859 , PyGILState_STATE *pygilstate UNUSED
4860#endif
4861 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004862{
4863 PyObject *r;
4864
4865 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
4866 if (r == NULL)
4867 {
4868 if (PyErr_Occurred() && !msg_silent)
4869 PyErr_PrintEx(0);
4870 EMSG(_("E858: Eval did not return a valid python object"));
4871 }
4872 else
4873 {
4874 if (ConvertFromPyObject(r, rettv) == -1)
4875 EMSG(_("E859: Failed to convert returned python object to vim value"));
4876 Py_DECREF(r);
4877 }
4878 PyErr_Clear();
4879}
4880
4881 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02004882set_ref_in_py(const int copyID)
4883{
4884 pylinkedlist_T *cur;
4885 dict_T *dd;
4886 list_T *ll;
4887
4888 if (lastdict != NULL)
4889 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
4890 {
4891 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
4892 if (dd->dv_copyID != copyID)
4893 {
4894 dd->dv_copyID = copyID;
4895 set_ref_in_ht(&dd->dv_hashtab, copyID);
4896 }
4897 }
4898
4899 if (lastlist != NULL)
4900 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
4901 {
4902 ll = ((ListObject *) (cur->pll_obj))->list;
4903 if (ll->lv_copyID != copyID)
4904 {
4905 ll->lv_copyID = copyID;
4906 set_ref_in_list(ll, copyID);
4907 }
4908 }
4909}
4910
4911 static int
4912set_string_copy(char_u *str, typval_T *tv)
4913{
4914 tv->vval.v_string = vim_strsave(str);
4915 if (tv->vval.v_string == NULL)
4916 {
4917 PyErr_NoMemory();
4918 return -1;
4919 }
4920 return 0;
4921}
4922
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004923 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004924pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004925{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004926 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004927 char_u *key;
4928 dictitem_T *di;
4929 PyObject *keyObject;
4930 PyObject *valObject;
4931 Py_ssize_t iter = 0;
4932
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004933 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004934 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004935
4936 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004937 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004938
4939 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4940 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004941 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004942
Bram Moolenaara03e6312013-05-29 22:49:26 +02004943 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004944 {
4945 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004946 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004947 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004948
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004949 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004950 {
4951 dict_unref(dict);
4952 return -1;
4953 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004954
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004955 if (*key == NUL)
4956 {
4957 dict_unref(dict);
4958 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004959 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004960 return -1;
4961 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004962
4963 di = dictitem_alloc(key);
4964
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004965 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004966
4967 if (di == NULL)
4968 {
4969 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004970 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004971 return -1;
4972 }
4973 di->di_tv.v_lock = 0;
4974
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004975 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004976 {
4977 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004978 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004979 return -1;
4980 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004981
4982 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004983 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02004984 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004985 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004986 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004987 PyErr_SetVim(_("failed to add key to dictionary"));
4988 return -1;
4989 }
4990 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004991
4992 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004993 return 0;
4994}
4995
4996 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004997pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004998{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004999 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005000 char_u *key;
5001 dictitem_T *di;
5002 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005003 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005004 PyObject *keyObject;
5005 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005006
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005007 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005008 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005009
5010 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005011 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005012
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005013 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005014 {
5015 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005016 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005017 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005018
5019 if (!(iterator = PyObject_GetIter(list)))
5020 {
5021 dict_unref(dict);
5022 Py_DECREF(list);
5023 return -1;
5024 }
5025 Py_DECREF(list);
5026
5027 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005028 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005029 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005030
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005031 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005032 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005033 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005034 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005035 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005036 return -1;
5037 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005038
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005039 if (*key == NUL)
5040 {
5041 Py_DECREF(keyObject);
5042 Py_DECREF(iterator);
5043 Py_XDECREF(todecref);
5044 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005045 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005046 return -1;
5047 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005048
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005049 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005050 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005051 Py_DECREF(keyObject);
5052 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005053 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005054 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005055 return -1;
5056 }
5057
5058 di = dictitem_alloc(key);
5059
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005060 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005061 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005062
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005063 if (di == NULL)
5064 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005065 Py_DECREF(iterator);
5066 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005067 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005068 PyErr_NoMemory();
5069 return -1;
5070 }
5071 di->di_tv.v_lock = 0;
5072
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005073 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005074 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005075 Py_DECREF(iterator);
5076 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005077 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005078 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005079 return -1;
5080 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02005081
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005082 Py_DECREF(valObject);
5083
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005084 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005085 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005086 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005087 dictitem_free(di);
5088 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005089 PyErr_SetVim(_("failed to add key to dictionary"));
5090 return -1;
5091 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005092 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005093 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005094 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005095 return 0;
5096}
5097
5098 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005099pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005100{
5101 list_T *l;
5102
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005103 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005104 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005105
5106 tv->v_type = VAR_LIST;
5107 tv->vval.v_list = l;
5108
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005109 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005110 {
5111 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005112 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005113 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005114
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005115 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005116 return 0;
5117}
5118
Bram Moolenaardb913952012-06-29 12:54:53 +02005119typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
5120
5121 static int
5122convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005123 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005124{
5125 PyObject *capsule;
5126 char hexBuf[sizeof(void *) * 2 + 3];
5127
5128 sprintf(hexBuf, "%p", obj);
5129
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005130# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005131 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005132# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005133 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005134# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02005135 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005136 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005137# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02005138 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02005139# else
5140 capsule = PyCObject_FromVoidPtr(tv, NULL);
5141# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02005142 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
5143 {
5144 Py_DECREF(capsule);
5145 tv->v_type = VAR_UNKNOWN;
5146 return -1;
5147 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005148 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02005149 {
5150 tv->v_type = VAR_UNKNOWN;
5151 return -1;
5152 }
5153 /* As we are not using copy_tv which increments reference count we must
5154 * do it ourself. */
5155 switch(tv->v_type)
5156 {
5157 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
5158 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
5159 }
5160 }
5161 else
5162 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005163 typval_T *v;
5164
5165# ifdef PY_USE_CAPSULE
5166 v = PyCapsule_GetPointer(capsule, NULL);
5167# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02005168 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005169# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02005170 copy_tv(v, tv);
5171 }
5172 return 0;
5173}
5174
5175 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02005176ConvertFromPyMapping(PyObject *obj, typval_T *tv)
5177{
5178 PyObject *lookup_dict;
5179 int r;
5180
5181 if (!(lookup_dict = PyDict_New()))
5182 return -1;
5183
5184 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
5185 {
5186 tv->v_type = VAR_DICT;
5187 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5188 ++tv->vval.v_dict->dv_refcount;
5189 r = 0;
5190 }
5191 else if (PyDict_Check(obj))
5192 r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
5193 else if (PyMapping_Check(obj))
5194 r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
5195 else
5196 {
5197 PyErr_SetString(PyExc_TypeError,
5198 _("unable to convert object to vim dictionary"));
5199 r = -1;
5200 }
5201 Py_DECREF(lookup_dict);
5202 return r;
5203}
5204
5205 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02005206ConvertFromPyObject(PyObject *obj, typval_T *tv)
5207{
5208 PyObject *lookup_dict;
5209 int r;
5210
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005211 if (!(lookup_dict = PyDict_New()))
5212 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005213 r = _ConvertFromPyObject(obj, tv, lookup_dict);
5214 Py_DECREF(lookup_dict);
5215 return r;
5216}
5217
5218 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005219_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005220{
Bram Moolenaara9922d62013-05-30 13:01:18 +02005221 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005222 {
5223 tv->v_type = VAR_DICT;
5224 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5225 ++tv->vval.v_dict->dv_refcount;
5226 }
5227 else if (obj->ob_type == &ListType)
5228 {
5229 tv->v_type = VAR_LIST;
5230 tv->vval.v_list = (((ListObject *)(obj))->list);
5231 ++tv->vval.v_list->lv_refcount;
5232 }
5233 else if (obj->ob_type == &FunctionType)
5234 {
5235 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
5236 return -1;
5237
5238 tv->v_type = VAR_FUNC;
5239 func_ref(tv->vval.v_string);
5240 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005241 else if (PyBytes_Check(obj))
5242 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005243 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02005244
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005245 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
5246 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005247 if (result == NULL)
5248 return -1;
5249
5250 if (set_string_copy(result, tv) == -1)
5251 return -1;
5252
5253 tv->v_type = VAR_STRING;
5254 }
5255 else if (PyUnicode_Check(obj))
5256 {
5257 PyObject *bytes;
5258 char_u *result;
5259
Bram Moolenaardb913952012-06-29 12:54:53 +02005260 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
5261 if (bytes == NULL)
5262 return -1;
5263
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005264 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
5265 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005266 if (result == NULL)
5267 return -1;
5268
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005269 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02005270 {
5271 Py_XDECREF(bytes);
5272 return -1;
5273 }
5274 Py_XDECREF(bytes);
5275
5276 tv->v_type = VAR_STRING;
5277 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02005278#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02005279 else if (PyInt_Check(obj))
5280 {
5281 tv->v_type = VAR_NUMBER;
5282 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
5283 }
5284#endif
5285 else if (PyLong_Check(obj))
5286 {
5287 tv->v_type = VAR_NUMBER;
5288 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
5289 }
5290 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005291 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005292#ifdef FEAT_FLOAT
5293 else if (PyFloat_Check(obj))
5294 {
5295 tv->v_type = VAR_FLOAT;
5296 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
5297 }
5298#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005299 else if (PyObject_HasAttrString(obj, "keys"))
5300 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005301 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005302 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005303 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005304 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005305 else
5306 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02005307 PyErr_SetString(PyExc_TypeError,
5308 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02005309 return -1;
5310 }
5311 return 0;
5312}
5313
5314 static PyObject *
5315ConvertToPyObject(typval_T *tv)
5316{
5317 if (tv == NULL)
5318 {
5319 PyErr_SetVim(_("NULL reference passed"));
5320 return NULL;
5321 }
5322 switch (tv->v_type)
5323 {
5324 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005325 return PyBytes_FromString(tv->vval.v_string == NULL
5326 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005327 case VAR_NUMBER:
5328 return PyLong_FromLong((long) tv->vval.v_number);
5329#ifdef FEAT_FLOAT
5330 case VAR_FLOAT:
5331 return PyFloat_FromDouble((double) tv->vval.v_float);
5332#endif
5333 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005334 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02005335 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02005336 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005337 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005338 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005339 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005340 case VAR_UNKNOWN:
5341 Py_INCREF(Py_None);
5342 return Py_None;
5343 default:
5344 PyErr_SetVim(_("internal error: invalid value type"));
5345 return NULL;
5346 }
5347}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005348
5349typedef struct
5350{
5351 PyObject_HEAD
5352} CurrentObject;
5353static PyTypeObject CurrentType;
5354
5355 static void
5356init_structs(void)
5357{
5358 vim_memset(&OutputType, 0, sizeof(OutputType));
5359 OutputType.tp_name = "vim.message";
5360 OutputType.tp_basicsize = sizeof(OutputObject);
5361 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
5362 OutputType.tp_doc = "vim message object";
5363 OutputType.tp_methods = OutputMethods;
5364#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005365 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
5366 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005367 OutputType.tp_alloc = call_PyType_GenericAlloc;
5368 OutputType.tp_new = call_PyType_GenericNew;
5369 OutputType.tp_free = call_PyObject_Free;
5370#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005371 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
5372 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005373#endif
5374
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005375 vim_memset(&IterType, 0, sizeof(IterType));
5376 IterType.tp_name = "vim.iter";
5377 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005378 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005379 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005380 IterType.tp_iter = (getiterfunc)IterIter;
5381 IterType.tp_iternext = (iternextfunc)IterNext;
5382 IterType.tp_dealloc = (destructor)IterDestructor;
5383 IterType.tp_traverse = (traverseproc)IterTraverse;
5384 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005385
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005386 vim_memset(&BufferType, 0, sizeof(BufferType));
5387 BufferType.tp_name = "vim.buffer";
5388 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005389 BufferType.tp_dealloc = (destructor)BufferDestructor;
5390 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005391 BufferType.tp_as_sequence = &BufferAsSeq;
5392 BufferType.tp_as_mapping = &BufferAsMapping;
5393 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5394 BufferType.tp_doc = "vim buffer object";
5395 BufferType.tp_methods = BufferMethods;
5396#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005397 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005398 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005399 BufferType.tp_alloc = call_PyType_GenericAlloc;
5400 BufferType.tp_new = call_PyType_GenericNew;
5401 BufferType.tp_free = call_PyObject_Free;
5402#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005403 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005404 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005405#endif
5406
5407 vim_memset(&WindowType, 0, sizeof(WindowType));
5408 WindowType.tp_name = "vim.window";
5409 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005410 WindowType.tp_dealloc = (destructor)WindowDestructor;
5411 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005412 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005413 WindowType.tp_doc = "vim Window object";
5414 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005415 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5416 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005417#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005418 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5419 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005420 WindowType.tp_alloc = call_PyType_GenericAlloc;
5421 WindowType.tp_new = call_PyType_GenericNew;
5422 WindowType.tp_free = call_PyObject_Free;
5423#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005424 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5425 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005426#endif
5427
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005428 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5429 TabPageType.tp_name = "vim.tabpage";
5430 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005431 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5432 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005433 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5434 TabPageType.tp_doc = "vim tab page object";
5435 TabPageType.tp_methods = TabPageMethods;
5436#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005437 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005438 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5439 TabPageType.tp_new = call_PyType_GenericNew;
5440 TabPageType.tp_free = call_PyObject_Free;
5441#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005442 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005443#endif
5444
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005445 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5446 BufMapType.tp_name = "vim.bufferlist";
5447 BufMapType.tp_basicsize = sizeof(BufMapObject);
5448 BufMapType.tp_as_mapping = &BufMapAsMapping;
5449 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005450 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005451 BufferType.tp_doc = "vim buffer list";
5452
5453 vim_memset(&WinListType, 0, sizeof(WinListType));
5454 WinListType.tp_name = "vim.windowlist";
5455 WinListType.tp_basicsize = sizeof(WinListType);
5456 WinListType.tp_as_sequence = &WinListAsSeq;
5457 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5458 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005459 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005460
5461 vim_memset(&TabListType, 0, sizeof(TabListType));
5462 TabListType.tp_name = "vim.tabpagelist";
5463 TabListType.tp_basicsize = sizeof(TabListType);
5464 TabListType.tp_as_sequence = &TabListAsSeq;
5465 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5466 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005467
5468 vim_memset(&RangeType, 0, sizeof(RangeType));
5469 RangeType.tp_name = "vim.range";
5470 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005471 RangeType.tp_dealloc = (destructor)RangeDestructor;
5472 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005473 RangeType.tp_as_sequence = &RangeAsSeq;
5474 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005475 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005476 RangeType.tp_doc = "vim Range object";
5477 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005478 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5479 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005480#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005481 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005482 RangeType.tp_alloc = call_PyType_GenericAlloc;
5483 RangeType.tp_new = call_PyType_GenericNew;
5484 RangeType.tp_free = call_PyObject_Free;
5485#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005486 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005487#endif
5488
5489 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5490 CurrentType.tp_name = "vim.currentdata";
5491 CurrentType.tp_basicsize = sizeof(CurrentObject);
5492 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5493 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005494 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005495#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005496 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5497 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005498#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005499 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5500 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005501#endif
5502
5503 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5504 DictionaryType.tp_name = "vim.dictionary";
5505 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005506 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005507 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005508 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005509 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005510 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5511 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005512 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5513 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5514 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005515#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005516 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5517 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005518#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005519 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5520 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005521#endif
5522
5523 vim_memset(&ListType, 0, sizeof(ListType));
5524 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005525 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005526 ListType.tp_basicsize = sizeof(ListObject);
5527 ListType.tp_as_sequence = &ListAsSeq;
5528 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005529 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005530 ListType.tp_doc = "list pushing modifications to vim structure";
5531 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005532 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005533 ListType.tp_new = (newfunc)ListConstructor;
5534 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005535#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005536 ListType.tp_getattro = (getattrofunc)ListGetattro;
5537 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005538#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005539 ListType.tp_getattr = (getattrfunc)ListGetattr;
5540 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005541#endif
5542
5543 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005544 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005545 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005546 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5547 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005548 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005549 FunctionType.tp_doc = "object that calls vim function";
5550 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005551 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005552 FunctionType.tp_new = (newfunc)FunctionConstructor;
5553 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005554#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005555 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005556#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005557 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005558#endif
5559
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005560 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5561 OptionsType.tp_name = "vim.options";
5562 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005563 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005564 OptionsType.tp_doc = "object for manipulating options";
5565 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005566 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5567 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5568 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005569
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005570 vim_memset(&LoaderType, 0, sizeof(LoaderType));
5571 LoaderType.tp_name = "vim.Loader";
5572 LoaderType.tp_basicsize = sizeof(LoaderObject);
5573 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
5574 LoaderType.tp_doc = "vim message object";
5575 LoaderType.tp_methods = LoaderMethods;
5576 LoaderType.tp_dealloc = (destructor)LoaderDestructor;
5577
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005578#if PY_MAJOR_VERSION >= 3
5579 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5580 vimmodule.m_name = "vim";
5581 vimmodule.m_doc = "Vim Python interface\n";
5582 vimmodule.m_size = -1;
5583 vimmodule.m_methods = VimMethods;
5584#endif
5585}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005586
5587#define PYTYPE_READY(type) \
5588 if (PyType_Ready(&type)) \
5589 return -1;
5590
5591 static int
5592init_types()
5593{
5594 PYTYPE_READY(IterType);
5595 PYTYPE_READY(BufferType);
5596 PYTYPE_READY(RangeType);
5597 PYTYPE_READY(WindowType);
5598 PYTYPE_READY(TabPageType);
5599 PYTYPE_READY(BufMapType);
5600 PYTYPE_READY(WinListType);
5601 PYTYPE_READY(TabListType);
5602 PYTYPE_READY(CurrentType);
5603 PYTYPE_READY(DictionaryType);
5604 PYTYPE_READY(ListType);
5605 PYTYPE_READY(FunctionType);
5606 PYTYPE_READY(OptionsType);
5607 PYTYPE_READY(OutputType);
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005608 PYTYPE_READY(LoaderType);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005609 return 0;
5610}
5611
5612 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02005613init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005614{
5615 PyObject *path;
5616 PyObject *path_hook;
5617 PyObject *path_hooks;
5618
5619 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
5620 return -1;
5621
5622 if (!(path_hooks = PySys_GetObject("path_hooks")))
5623 {
5624 PyErr_Clear();
5625 path_hooks = PyList_New(1);
5626 PyList_SET_ITEM(path_hooks, 0, path_hook);
5627 if (PySys_SetObject("path_hooks", path_hooks))
5628 {
5629 Py_DECREF(path_hooks);
5630 return -1;
5631 }
5632 Py_DECREF(path_hooks);
5633 }
5634 else if (PyList_Check(path_hooks))
5635 {
5636 if (PyList_Append(path_hooks, path_hook))
5637 {
5638 Py_DECREF(path_hook);
5639 return -1;
5640 }
5641 Py_DECREF(path_hook);
5642 }
5643 else
5644 {
5645 VimTryStart();
5646 EMSG(_("Failed to set path hook: sys.path_hooks is not a list\n"
5647 "You should now do the following:\n"
5648 "- append vim.path_hook to sys.path_hooks\n"
5649 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
5650 VimTryEnd(); /* Discard the error */
5651 Py_DECREF(path_hook);
5652 return 0;
5653 }
5654
5655 if (!(path = PySys_GetObject("path")))
5656 {
5657 PyErr_Clear();
5658 path = PyList_New(1);
5659 Py_INCREF(vim_special_path_object);
5660 PyList_SET_ITEM(path, 0, vim_special_path_object);
5661 if (PySys_SetObject("path", path))
5662 {
5663 Py_DECREF(path);
5664 return -1;
5665 }
5666 Py_DECREF(path);
5667 }
5668 else if (PyList_Check(path))
5669 {
5670 if (PyList_Append(path, vim_special_path_object))
5671 return -1;
5672 }
5673 else
5674 {
5675 VimTryStart();
5676 EMSG(_("Failed to set path: sys.path is not a list\n"
5677 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
5678 VimTryEnd(); /* Discard the error */
5679 }
5680
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005681 return 0;
5682}
5683
5684static BufMapObject TheBufferMap =
5685{
5686 PyObject_HEAD_INIT(&BufMapType)
5687};
5688
5689static WinListObject TheWindowList =
5690{
5691 PyObject_HEAD_INIT(&WinListType)
5692 NULL
5693};
5694
5695static CurrentObject TheCurrent =
5696{
5697 PyObject_HEAD_INIT(&CurrentType)
5698};
5699
5700static TabListObject TheTabPageList =
5701{
5702 PyObject_HEAD_INIT(&TabListType)
5703};
5704
5705static struct numeric_constant {
5706 char *name;
5707 int value;
5708} numeric_constants[] = {
5709 {"VAR_LOCKED", VAR_LOCKED},
5710 {"VAR_FIXED", VAR_FIXED},
5711 {"VAR_SCOPE", VAR_SCOPE},
5712 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5713};
5714
5715static struct object_constant {
5716 char *name;
5717 PyObject *value;
5718} object_constants[] = {
5719 {"buffers", (PyObject *)(void *)&TheBufferMap},
5720 {"windows", (PyObject *)(void *)&TheWindowList},
5721 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5722 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005723
5724 {"Buffer", (PyObject *)&BufferType},
5725 {"Range", (PyObject *)&RangeType},
5726 {"Window", (PyObject *)&WindowType},
5727 {"TabPage", (PyObject *)&TabPageType},
5728 {"Dictionary", (PyObject *)&DictionaryType},
5729 {"List", (PyObject *)&ListType},
5730 {"Function", (PyObject *)&FunctionType},
5731 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005732 {"_Loader", (PyObject *)&LoaderType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005733};
5734
5735typedef int (*object_adder)(PyObject *, const char *, PyObject *);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005736typedef PyObject *(*attr_getter)(PyObject *, const char *);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005737
5738#define ADD_OBJECT(m, name, obj) \
5739 if (add_object(m, name, obj)) \
5740 return -1;
5741
5742#define ADD_CHECKED_OBJECT(m, name, obj) \
5743 { \
5744 PyObject *value = obj; \
5745 if (!value) \
5746 return -1; \
5747 ADD_OBJECT(m, name, value); \
5748 }
5749
5750 static int
Bram Moolenaarf4258302013-06-02 18:20:17 +02005751populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005752{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005753 int i;
5754 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005755 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005756 PyObject *imp;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005757
5758 for (i = 0; i < (int)(sizeof(numeric_constants)
5759 / sizeof(struct numeric_constant));
5760 ++i)
5761 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
5762 PyInt_FromLong(numeric_constants[i].value));
5763
5764 for (i = 0; i < (int)(sizeof(object_constants)
5765 / sizeof(struct object_constant));
5766 ++i)
5767 {
5768 PyObject *value;
5769
5770 value = object_constants[i].value;
5771 Py_INCREF(value);
5772 ADD_OBJECT(m, object_constants[i].name, value);
5773 }
5774
5775 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5776 return -1;
5777 ADD_OBJECT(m, "error", VimError);
5778
Bram Moolenaara9922d62013-05-30 13:01:18 +02005779 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5780 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005781 ADD_CHECKED_OBJECT(m, "options",
5782 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02005783
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005784 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005785 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005786 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005787
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005788 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005789 return -1;
5790 ADD_OBJECT(m, "_getcwd", py_getcwd)
5791
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005792 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005793 return -1;
5794 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005795 if (!(attr = get_attr(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005796 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005797 if (PyObject_SetAttrString(other_module, "chdir", attr))
5798 {
5799 Py_DECREF(attr);
5800 return -1;
5801 }
5802 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005803
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005804 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005805 {
5806 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005807 if (!(attr = get_attr(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005808 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005809 if (PyObject_SetAttrString(other_module, "fchdir", attr))
5810 {
5811 Py_DECREF(attr);
5812 return -1;
5813 }
5814 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005815 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02005816 else
5817 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02005818
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005819 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
5820 return -1;
5821
5822 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
5823
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005824 if (!(imp = PyImport_ImportModule("imp")))
5825 return -1;
5826
5827 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
5828 {
5829 Py_DECREF(imp);
5830 return -1;
5831 }
5832
5833 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
5834 {
5835 Py_DECREF(py_find_module);
5836 Py_DECREF(imp);
5837 return -1;
5838 }
5839
5840 Py_DECREF(imp);
5841
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005842 ADD_OBJECT(m, "_find_module", py_find_module);
5843 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005844
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005845 return 0;
5846}