blob: 9acb3105b2bc8b7f279fd8233617456ff7b06815 [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 Moolenaar170bf1a2010-07-24 23:51:45 +0200284 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200285OutputWrite(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200286{
Bram Moolenaare8cdcef2012-09-12 20:21:43 +0200287 Py_ssize_t len = 0;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200288 char *str = NULL;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200289 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200290
Bram Moolenaar27564802011-09-07 19:30:21 +0200291 if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200292 return NULL;
293
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
301 Py_INCREF(Py_None);
302 return Py_None;
303}
304
305 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200306OutputWritelines(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200307{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200308 PyObject *seq;
309 PyObject *iterator;
310 PyObject *item;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200311 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200312
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200313 if (!PyArg_ParseTuple(args, "O", &seq))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200314 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200315
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200316 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200317 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200318
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200319 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200320 {
Bram Moolenaar19e60942011-06-19 00:27:51 +0200321 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200322 PyInt len;
323
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200324 if (!PyArg_Parse(item, "et#", ENC_OPT, &str, &len))
Bram Moolenaardb913952012-06-29 12:54:53 +0200325 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200326 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
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 Py_BEGIN_ALLOW_THREADS
334 Python_Lock_Vim();
335 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
336 Python_Release_Vim();
337 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200338 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200339 }
340
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200341 Py_DECREF(iterator);
342
343 /* Iterator may have finished due to an exception */
344 if (PyErr_Occurred())
345 return NULL;
346
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200347 Py_INCREF(Py_None);
348 return Py_None;
349}
350
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100351 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200352OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100353{
354 /* do nothing */
355 Py_INCREF(Py_None);
356 return Py_None;
357}
358
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200359/***************/
360
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200361static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200362 /* name, function, calling, doc */
363 {"write", (PyCFunction)OutputWrite, METH_VARARGS, ""},
364 {"writelines", (PyCFunction)OutputWritelines, METH_VARARGS, ""},
365 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200366 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200367 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200368};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200369
370static OutputObject Output =
371{
372 PyObject_HEAD_INIT(&OutputType)
373 0,
374 0
375};
376
377static OutputObject Error =
378{
379 PyObject_HEAD_INIT(&OutputType)
380 0,
381 1
382};
383
384 static int
385PythonIO_Init_io(void)
386{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200387 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
388 return -1;
389 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
390 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200391
392 if (PyErr_Occurred())
393 {
394 EMSG(_("E264: Python: Error initialising I/O objects"));
395 return -1;
396 }
397
398 return 0;
399}
400
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200401typedef struct
402{
403 PyObject_HEAD
404 PyObject *module;
405} LoaderObject;
406static PyTypeObject LoaderType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200407
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200408 static void
409LoaderDestructor(LoaderObject *self)
410{
411 Py_DECREF(self->module);
412 DESTRUCTOR_FINISH(self);
413}
414
415 static PyObject *
416LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
417{
418 PyObject *r = self->module;
419
420 Py_INCREF(r);
421 return r;
422}
423
424static struct PyMethodDef LoaderMethods[] = {
425 /* name, function, calling, doc */
426 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
427 { NULL, NULL, 0, NULL}
428};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200429
430/* Check to see whether a Vim error has been reported, or a keyboard
431 * interrupt has been detected.
432 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200433
434 static void
435VimTryStart(void)
436{
437 ++trylevel;
438}
439
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200440 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200441VimTryEnd(void)
442{
443 --trylevel;
444 if (got_int)
445 {
446 PyErr_SetNone(PyExc_KeyboardInterrupt);
447 return 1;
448 }
449 else if (!did_throw)
450 return 0;
451 else if (PyErr_Occurred())
452 return 1;
453 else
454 {
455 PyErr_SetVim((char *) current_exception->value);
456 discard_current_exception();
457 return 1;
458 }
459}
460
461 static int
462VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200463{
464 if (got_int)
465 {
466 PyErr_SetNone(PyExc_KeyboardInterrupt);
467 return 1;
468 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200469 return 0;
470}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200471
472/* Vim module - Implementation
473 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200474
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200475 static PyObject *
476VimCommand(PyObject *self UNUSED, PyObject *args)
477{
478 char *cmd;
479 PyObject *result;
480
481 if (!PyArg_ParseTuple(args, "s", &cmd))
482 return NULL;
483
484 PyErr_Clear();
485
486 Py_BEGIN_ALLOW_THREADS
487 Python_Lock_Vim();
488
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200489 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200490 do_cmdline_cmd((char_u *)cmd);
491 update_screen(VALID);
492
493 Python_Release_Vim();
494 Py_END_ALLOW_THREADS
495
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200496 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200497 result = NULL;
498 else
499 result = Py_None;
500
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200501
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200502 Py_XINCREF(result);
503 return result;
504}
505
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200506/*
507 * Function to translate a typval_T into a PyObject; this will recursively
508 * translate lists/dictionaries into their Python equivalents.
509 *
510 * The depth parameter is to avoid infinite recursion, set it to 1 when
511 * you call VimToPython.
512 */
513 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200514VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200515{
516 PyObject *result;
517 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200518 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200519
520 /* Avoid infinite recursion */
521 if (depth > 100)
522 {
523 Py_INCREF(Py_None);
524 result = Py_None;
525 return result;
526 }
527
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200528 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200529 * then and we can use it again. */
530 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
531 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
532 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200533 sprintf(ptrBuf, "%p",
534 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
535 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200536
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200537 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200538 {
539 Py_INCREF(result);
540 return result;
541 }
542 }
543
544 if (our_tv->v_type == VAR_STRING)
545 {
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200546 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200547 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200548 }
549 else if (our_tv->v_type == VAR_NUMBER)
550 {
551 char buf[NUMBUFLEN];
552
553 /* For backwards compatibility numbers are stored as strings. */
554 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200555 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200556 }
557# ifdef FEAT_FLOAT
558 else if (our_tv->v_type == VAR_FLOAT)
559 {
560 char buf[NUMBUFLEN];
561
562 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200563 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200564 }
565# endif
566 else if (our_tv->v_type == VAR_LIST)
567 {
568 list_T *list = our_tv->vval.v_list;
569 listitem_T *curr;
570
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200571 if (list == NULL)
572 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200573
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200574 if (!(result = PyList_New(0)))
575 return NULL;
576
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200577 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200578 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200579 Py_DECREF(result);
580 return NULL;
581 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200582
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200583 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
584 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200585 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200586 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200587 Py_DECREF(result);
588 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200589 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200590 if (PyList_Append(result, newObj))
591 {
592 Py_DECREF(newObj);
593 Py_DECREF(result);
594 return NULL;
595 }
596 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200597 }
598 }
599 else if (our_tv->v_type == VAR_DICT)
600 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200601
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200602 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
603 long_u todo = ht->ht_used;
604 hashitem_T *hi;
605 dictitem_T *di;
606 if (our_tv->vval.v_dict == NULL)
607 return NULL;
608
609 if (!(result = PyDict_New()))
610 return NULL;
611
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200612 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200613 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200614 Py_DECREF(result);
615 return NULL;
616 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200617
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200618 for (hi = ht->ht_array; todo > 0; ++hi)
619 {
620 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200621 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200622 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200623
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200624 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200625 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200626 {
627 Py_DECREF(result);
628 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200629 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200630 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
631 {
632 Py_DECREF(result);
633 Py_DECREF(newObj);
634 return NULL;
635 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200636 }
637 }
638 }
639 else
640 {
641 Py_INCREF(Py_None);
642 result = Py_None;
643 }
644
645 return result;
646}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200647
648 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200649VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200650{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200651 char *expr;
652 typval_T *our_tv;
653 PyObject *result;
654 PyObject *lookup_dict;
655
656 if (!PyArg_ParseTuple(args, "s", &expr))
657 return NULL;
658
659 Py_BEGIN_ALLOW_THREADS
660 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200661 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200662 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200663 Python_Release_Vim();
664 Py_END_ALLOW_THREADS
665
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200666 if (VimTryEnd())
667 return NULL;
668
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200669 if (our_tv == NULL)
670 {
671 PyErr_SetVim(_("invalid expression"));
672 return NULL;
673 }
674
675 /* Convert the Vim type into a Python type. Create a dictionary that's
676 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200677 if (!(lookup_dict = PyDict_New()))
678 result = NULL;
679 else
680 {
681 result = VimToPython(our_tv, 1, lookup_dict);
682 Py_DECREF(lookup_dict);
683 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200684
685
686 Py_BEGIN_ALLOW_THREADS
687 Python_Lock_Vim();
688 free_tv(our_tv);
689 Python_Release_Vim();
690 Py_END_ALLOW_THREADS
691
692 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200693}
694
Bram Moolenaardb913952012-06-29 12:54:53 +0200695static PyObject *ConvertToPyObject(typval_T *);
696
697 static PyObject *
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200698VimEvalPy(PyObject *self UNUSED, PyObject *args)
Bram Moolenaardb913952012-06-29 12:54:53 +0200699{
Bram Moolenaardb913952012-06-29 12:54:53 +0200700 char *expr;
701 typval_T *our_tv;
702 PyObject *result;
703
704 if (!PyArg_ParseTuple(args, "s", &expr))
705 return NULL;
706
707 Py_BEGIN_ALLOW_THREADS
708 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200709 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +0200710 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200711 Python_Release_Vim();
712 Py_END_ALLOW_THREADS
713
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200714 if (VimTryEnd())
715 return NULL;
716
Bram Moolenaardb913952012-06-29 12:54:53 +0200717 if (our_tv == NULL)
718 {
719 PyErr_SetVim(_("invalid expression"));
720 return NULL;
721 }
722
723 result = ConvertToPyObject(our_tv);
724 Py_BEGIN_ALLOW_THREADS
725 Python_Lock_Vim();
726 free_tv(our_tv);
727 Python_Release_Vim();
728 Py_END_ALLOW_THREADS
729
730 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200731}
732
733 static PyObject *
734VimStrwidth(PyObject *self UNUSED, PyObject *args)
735{
736 char *expr;
737
738 if (!PyArg_ParseTuple(args, "s", &expr))
739 return NULL;
740
Bram Moolenaara54bf402012-12-05 16:30:07 +0100741 return PyLong_FromLong(
742#ifdef FEAT_MBYTE
743 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
744#else
745 STRLEN(expr)
746#endif
747 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200748}
749
Bram Moolenaarf4258302013-06-02 18:20:17 +0200750 static PyObject *
751_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
752{
753 PyObject *r;
754 PyObject *newwd;
755 PyObject *todecref;
756 char_u *new_dir;
757
Bram Moolenaard4209d22013-06-05 20:34:15 +0200758 if (_chdir == NULL)
759 return NULL;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200760 if (!(r = PyObject_Call(_chdir, args, kwargs)))
761 return NULL;
762
763 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
764 {
765 Py_DECREF(r);
766 return NULL;
767 }
768
769 if (!(new_dir = StringToChars(newwd, &todecref)))
770 {
771 Py_DECREF(r);
772 Py_DECREF(newwd);
773 return NULL;
774 }
775
776 VimTryStart();
777
778 if (vim_chdir(new_dir))
779 {
780 Py_DECREF(r);
781 Py_DECREF(newwd);
782 Py_XDECREF(todecref);
783
784 if (VimTryEnd())
785 return NULL;
786
787 PyErr_SetVim(_("failed to change directory"));
788 return NULL;
789 }
790
791 Py_DECREF(newwd);
792 Py_XDECREF(todecref);
793
794 post_chdir(FALSE);
795
796 if (VimTryEnd())
797 {
798 Py_DECREF(r);
799 return NULL;
800 }
801
802 return r;
803}
804
805 static PyObject *
806VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
807{
808 return _VimChdir(py_chdir, args, kwargs);
809}
810
811 static PyObject *
812VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
813{
814 return _VimChdir(py_fchdir, args, kwargs);
815}
816
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200817typedef struct {
818 PyObject *callable;
819 PyObject *result;
820} map_rtp_data;
821
822 static void
823map_rtp_callback(char_u *path, void *_data)
824{
825 void **data = (void **) _data;
826 PyObject *pathObject;
827 map_rtp_data *mr_data = *((map_rtp_data **) data);
828
829 if (!(pathObject = PyString_FromString((char *) path)))
830 {
831 *data = NULL;
832 return;
833 }
834
835 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
836 pathObject, NULL);
837
838 Py_DECREF(pathObject);
839
840 if (!mr_data->result || mr_data->result != Py_None)
841 *data = NULL;
842 else
843 {
844 Py_DECREF(mr_data->result);
845 mr_data->result = NULL;
846 }
847}
848
849 static PyObject *
850VimForeachRTP(PyObject *self UNUSED, PyObject *args)
851{
852 map_rtp_data data;
853
854 if (!PyArg_ParseTuple(args, "O", &data.callable))
855 return NULL;
856
857 data.result = NULL;
858
859 do_in_runtimepath(NULL, FALSE, &map_rtp_callback, &data);
860
861 if (data.result == NULL)
862 {
863 if (PyErr_Occurred())
864 return NULL;
865 else
866 {
867 Py_INCREF(Py_None);
868 return Py_None;
869 }
870 }
871 return data.result;
872}
873
874/*
875 * _vim_runtimepath_ special path implementation.
876 */
877
878 static void
879map_finder_callback(char_u *path, void *_data)
880{
881 void **data = (void **) _data;
882 PyObject *list = *((PyObject **) data);
883 PyObject *pathObject1, *pathObject2;
884 char *pathbuf;
885 size_t pathlen;
886
887 pathlen = STRLEN(path);
888
889#if PY_MAJOR_VERSION < 3
890# define PY_MAIN_DIR_STRING "python2"
891#else
892# define PY_MAIN_DIR_STRING "python3"
893#endif
894#define PY_ALTERNATE_DIR_STRING "pythonx"
895
896#define PYTHONX_STRING_LENGTH 7 /* STRLEN("pythonx") */
897 if (!(pathbuf = PyMem_New(char,
898 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
899 {
900 PyErr_NoMemory();
901 *data = NULL;
902 return;
903 }
904
905 mch_memmove(pathbuf, path, pathlen + 1);
906 add_pathsep((char_u *) pathbuf);
907
908 pathlen = STRLEN(pathbuf);
909 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
910 PYTHONX_STRING_LENGTH + 1);
911
912 if (!(pathObject1 = PyString_FromString(pathbuf)))
913 {
914 *data = NULL;
915 PyMem_Free(pathbuf);
916 return;
917 }
918
919 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
920 PYTHONX_STRING_LENGTH + 1);
921
922 if (!(pathObject2 = PyString_FromString(pathbuf)))
923 {
924 Py_DECREF(pathObject1);
925 PyMem_Free(pathbuf);
926 *data = NULL;
927 return;
928 }
929
930 PyMem_Free(pathbuf);
931
932 if (PyList_Append(list, pathObject1)
933 || PyList_Append(list, pathObject2))
934 *data = NULL;
935
936 Py_DECREF(pathObject1);
937 Py_DECREF(pathObject2);
938}
939
940 static PyObject *
941Vim_GetPaths(PyObject *self UNUSED)
942{
943 PyObject *r;
944
945 if (!(r = PyList_New(0)))
946 return NULL;
947
948 do_in_runtimepath(NULL, FALSE, &map_finder_callback, r);
949
950 if (PyErr_Occurred())
951 {
952 Py_DECREF(r);
953 return NULL;
954 }
955
956 return r;
957}
958
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200959 static PyObject *
960call_load_module(char *name, int len, PyObject *find_module_result)
961{
962 PyObject *fd, *pathname, *description;
963
964 if (!PyTuple_Check(find_module_result)
965 || PyTuple_GET_SIZE(find_module_result) != 3)
966 {
967 PyErr_SetString(PyExc_TypeError,
968 _("expected 3-tuple as imp.find_module() result"));
969 return NULL;
970 }
971
972 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
973 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
974 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
975 {
976 PyErr_SetString(PyExc_RuntimeError,
977 _("internal error: imp.find_module returned tuple with NULL"));
978 return NULL;
979 }
980
981 return PyObject_CallFunction(py_load_module,
982 "s#OOO", name, len, fd, pathname, description);
983}
984
985 static PyObject *
986find_module(char *fullname, char *tail, PyObject *new_path)
987{
988 PyObject *find_module_result;
989 PyObject *module;
990 char *dot;
991
992 if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
993 {
994 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +0200995 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200996 * first component
997 */
998 PyObject *newest_path;
999 int partlen = (int) (dot - 1 - tail);
1000
1001 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1002 "s#O", tail, partlen, new_path)))
1003 return NULL;
1004
1005 if (!(module = call_load_module(
1006 fullname,
1007 ((int) (tail - fullname)) + partlen,
1008 find_module_result)))
1009 {
1010 Py_DECREF(find_module_result);
1011 return NULL;
1012 }
1013
1014 Py_DECREF(find_module_result);
1015
1016 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1017 {
1018 Py_DECREF(module);
1019 return NULL;
1020 }
1021
1022 Py_DECREF(module);
1023
1024 module = find_module(fullname, dot + 1, newest_path);
1025
1026 Py_DECREF(newest_path);
1027
1028 return module;
1029 }
1030 else
1031 {
1032 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1033 "sO", tail, new_path)))
1034 return NULL;
1035
1036 if (!(module = call_load_module(
1037 fullname,
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001038 (int)STRLEN(fullname),
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001039 find_module_result)))
1040 {
1041 Py_DECREF(find_module_result);
1042 return NULL;
1043 }
1044
1045 Py_DECREF(find_module_result);
1046
1047 return module;
1048 }
1049}
1050
1051 static PyObject *
1052FinderFindModule(PyObject *self, PyObject *args)
1053{
1054 char *fullname;
1055 PyObject *module;
1056 PyObject *new_path;
1057 LoaderObject *loader;
1058
1059 if (!PyArg_ParseTuple(args, "s", &fullname))
1060 return NULL;
1061
1062 if (!(new_path = Vim_GetPaths(self)))
1063 return NULL;
1064
1065 module = find_module(fullname, fullname, new_path);
1066
1067 Py_DECREF(new_path);
1068
1069 if (!module)
1070 {
1071 Py_INCREF(Py_None);
1072 return Py_None;
1073 }
1074
1075 if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
1076 {
1077 Py_DECREF(module);
1078 return NULL;
1079 }
1080
1081 loader->module = module;
1082
1083 return (PyObject *) loader;
1084}
1085
1086 static PyObject *
1087VimPathHook(PyObject *self UNUSED, PyObject *args)
1088{
1089 char *path;
1090
1091 if (PyArg_ParseTuple(args, "s", &path)
1092 && STRCMP(path, vim_special_path) == 0)
1093 {
1094 Py_INCREF(vim_module);
1095 return vim_module;
1096 }
1097
1098 PyErr_Clear();
1099 PyErr_SetNone(PyExc_ImportError);
1100 return NULL;
1101}
1102
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001103/*
1104 * Vim module - Definitions
1105 */
1106
1107static struct PyMethodDef VimMethods[] = {
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001108 /* name, function, calling, documentation */
1109 {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" },
1110 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
1111 {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"},
1112 {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"},
1113 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1114 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1115 {"foreach_rtp", VimForeachRTP, METH_VARARGS, "Call given callable for each path in &rtp"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001116 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001117 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1118 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1119 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001120};
1121
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001122/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001123 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001124 */
1125
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001126static PyTypeObject IterType;
1127
1128typedef PyObject *(*nextfun)(void **);
1129typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001130typedef int (*traversefun)(void *, visitproc, void *);
1131typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001132
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001133/* Main purpose of this object is removing the need for do python
1134 * initialization (i.e. PyType_Ready and setting type attributes) for a big
1135 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001136
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001137typedef struct
1138{
1139 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001140 void *cur;
1141 nextfun next;
1142 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001143 traversefun traverse;
1144 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001145} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001146
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001147 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001148IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
1149 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001150{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001151 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001152
Bram Moolenaar774267b2013-05-21 20:51:59 +02001153 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001154 self->cur = start;
1155 self->next = next;
1156 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001157 self->traverse = traverse;
1158 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001159
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001160 return (PyObject *)(self);
1161}
1162
1163 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001164IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001165{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001166 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001167 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001168 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001169}
1170
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001171 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001172IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001173{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001174 if (self->traverse != NULL)
1175 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001176 else
1177 return 0;
1178}
1179
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001180/* Mac OSX defines clear() somewhere. */
1181#ifdef clear
1182# undef clear
1183#endif
1184
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001185 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001186IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001187{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001188 if (self->clear != NULL)
1189 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001190 else
1191 return 0;
1192}
1193
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001194 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001195IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001196{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001197 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001198}
1199
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001200 static PyObject *
1201IterIter(PyObject *self)
1202{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001203 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001204 return self;
1205}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001206
Bram Moolenaardb913952012-06-29 12:54:53 +02001207typedef struct pylinkedlist_S {
1208 struct pylinkedlist_S *pll_next;
1209 struct pylinkedlist_S *pll_prev;
1210 PyObject *pll_obj;
1211} pylinkedlist_T;
1212
1213static pylinkedlist_T *lastdict = NULL;
1214static pylinkedlist_T *lastlist = NULL;
1215
1216 static void
1217pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1218{
1219 if (ref->pll_prev == NULL)
1220 {
1221 if (ref->pll_next == NULL)
1222 {
1223 *last = NULL;
1224 return;
1225 }
1226 }
1227 else
1228 ref->pll_prev->pll_next = ref->pll_next;
1229
1230 if (ref->pll_next == NULL)
1231 *last = ref->pll_prev;
1232 else
1233 ref->pll_next->pll_prev = ref->pll_prev;
1234}
1235
1236 static void
1237pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1238{
1239 if (*last == NULL)
1240 ref->pll_prev = NULL;
1241 else
1242 {
1243 (*last)->pll_next = ref;
1244 ref->pll_prev = *last;
1245 }
1246 ref->pll_next = NULL;
1247 ref->pll_obj = self;
1248 *last = ref;
1249}
1250
1251static PyTypeObject DictionaryType;
1252
1253typedef struct
1254{
1255 PyObject_HEAD
1256 dict_T *dict;
1257 pylinkedlist_T ref;
1258} DictionaryObject;
1259
Bram Moolenaara9922d62013-05-30 13:01:18 +02001260static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1261
1262#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
1263
Bram Moolenaardb913952012-06-29 12:54:53 +02001264 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001265DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001266{
1267 DictionaryObject *self;
1268
Bram Moolenaara9922d62013-05-30 13:01:18 +02001269 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001270 if (self == NULL)
1271 return NULL;
1272 self->dict = dict;
1273 ++dict->dv_refcount;
1274
1275 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1276
1277 return (PyObject *)(self);
1278}
1279
Bram Moolenaara9922d62013-05-30 13:01:18 +02001280 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001281py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001282{
1283 dict_T *r;
1284
1285 if (!(r = dict_alloc()))
1286 {
1287 PyErr_NoMemory();
1288 return NULL;
1289 }
1290 ++r->dv_refcount;
1291
1292 return r;
1293}
1294
1295 static PyObject *
1296DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1297{
1298 DictionaryObject *self;
1299 dict_T *dict;
1300
1301 if (!(dict = py_dict_alloc()))
1302 return NULL;
1303
1304 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1305
1306 --dict->dv_refcount;
1307
1308 if (kwargs || PyTuple_Size(args))
1309 {
1310 PyObject *tmp;
1311 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1312 {
1313 Py_DECREF(self);
1314 return NULL;
1315 }
1316
1317 Py_DECREF(tmp);
1318 }
1319
1320 return (PyObject *)(self);
1321}
1322
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001323 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001324DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001325{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001326 pyll_remove(&self->ref, &lastdict);
1327 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001328
1329 DESTRUCTOR_FINISH(self);
1330}
1331
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001332static char *DictionaryAttrs[] = {
1333 "locked", "scope",
1334 NULL
1335};
1336
1337 static PyObject *
1338DictionaryDir(PyObject *self)
1339{
1340 return ObjectDir(self, DictionaryAttrs);
1341}
1342
Bram Moolenaardb913952012-06-29 12:54:53 +02001343 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001344DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001345{
1346 if (val == NULL)
1347 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001348 PyErr_SetString(PyExc_AttributeError,
1349 _("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001350 return -1;
1351 }
1352
1353 if (strcmp(name, "locked") == 0)
1354 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001355 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001356 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001357 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001358 return -1;
1359 }
1360 else
1361 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001362 int istrue = PyObject_IsTrue(val);
1363 if (istrue == -1)
1364 return -1;
1365 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001366 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001367 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001368 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001369 }
1370 return 0;
1371 }
1372 else
1373 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001374 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001375 return -1;
1376 }
1377}
1378
1379 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001380DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001381{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001382 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001383}
1384
Bram Moolenaara9922d62013-05-30 13:01:18 +02001385#define DICT_FLAG_HAS_DEFAULT 0x01
1386#define DICT_FLAG_POP 0x02
1387#define DICT_FLAG_NONE_DEFAULT 0x04
1388#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
1389#define DICT_FLAG_RETURN_PAIR 0x10
1390
Bram Moolenaardb913952012-06-29 12:54:53 +02001391 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001392_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001393{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001394 PyObject *keyObject;
1395 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
1396 PyObject *r;
Bram Moolenaardb913952012-06-29 12:54:53 +02001397 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001398 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001399 dict_T *dict = self->dict;
1400 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001401 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001402
Bram Moolenaara9922d62013-05-30 13:01:18 +02001403 if (flags & DICT_FLAG_HAS_DEFAULT)
1404 {
1405 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1406 return NULL;
1407 }
1408 else
1409 keyObject = args;
1410
1411 if (flags & DICT_FLAG_RETURN_BOOL)
1412 defObject = Py_False;
1413
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001414 if (!(key = StringToChars(keyObject, &todecref)))
1415 return NULL;
1416
1417 if (*key == NUL)
1418 {
1419 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001420 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001421 return NULL;
1422 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001423
Bram Moolenaara9922d62013-05-30 13:01:18 +02001424 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001425
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001426 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001427
Bram Moolenaara9922d62013-05-30 13:01:18 +02001428 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001429 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001430 if (defObject)
1431 {
1432 Py_INCREF(defObject);
1433 return defObject;
1434 }
1435 else
1436 {
1437 PyErr_SetObject(PyExc_KeyError, keyObject);
1438 return NULL;
1439 }
1440 }
1441 else if (flags & DICT_FLAG_RETURN_BOOL)
1442 {
1443 Py_INCREF(Py_True);
1444 return Py_True;
1445 }
1446
1447 di = dict_lookup(hi);
1448
1449 if (!(r = ConvertToPyObject(&di->di_tv)))
1450 return NULL;
1451
1452 if (flags & DICT_FLAG_POP)
1453 {
1454 if (dict->dv_lock)
1455 {
1456 PyErr_SetVim(_("dict is locked"));
1457 Py_DECREF(r);
1458 return NULL;
1459 }
1460
1461 hash_remove(&dict->dv_hashtab, hi);
1462 dictitem_free(di);
1463 }
1464
Bram Moolenaara9922d62013-05-30 13:01:18 +02001465 return r;
1466}
1467
1468 static PyObject *
1469DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1470{
1471 return _DictionaryItem(self, keyObject, 0);
1472}
1473
1474 static int
1475DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1476{
1477 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1478 int r;
1479
1480 r = (rObj == Py_True);
1481
1482 Py_DECREF(Py_True);
1483
1484 return r;
1485}
1486
1487typedef struct
1488{
1489 hashitem_T *ht_array;
1490 long_u ht_used;
1491 hashtab_T *ht;
1492 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001493 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001494} dictiterinfo_T;
1495
1496 static PyObject *
1497DictionaryIterNext(dictiterinfo_T **dii)
1498{
1499 PyObject *r;
1500
1501 if (!(*dii)->todo)
1502 return NULL;
1503
1504 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1505 (*dii)->ht->ht_used != (*dii)->ht_used)
1506 {
1507 PyErr_SetString(PyExc_RuntimeError,
1508 _("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001509 return NULL;
1510 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001511
Bram Moolenaara9922d62013-05-30 13:01:18 +02001512 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1513 ++((*dii)->hi);
1514
1515 --((*dii)->todo);
1516
1517 if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1518 return NULL;
1519
1520 return r;
1521}
1522
1523 static PyObject *
1524DictionaryIter(DictionaryObject *self)
1525{
1526 dictiterinfo_T *dii;
1527 hashtab_T *ht;
1528
1529 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1530 {
1531 PyErr_NoMemory();
1532 return NULL;
1533 }
1534
1535 ht = &self->dict->dv_hashtab;
1536 dii->ht_array = ht->ht_array;
1537 dii->ht_used = ht->ht_used;
1538 dii->ht = ht;
1539 dii->hi = dii->ht_array;
1540 dii->todo = dii->ht_used;
1541
1542 return IterNew(dii,
1543 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1544 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001545}
1546
1547 static PyInt
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001548DictionaryAssItem(
1549 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001550{
1551 char_u *key;
1552 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001553 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001554 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001555 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001556
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001557 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001558 {
1559 PyErr_SetVim(_("dict is locked"));
1560 return -1;
1561 }
1562
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001563 if (!(key = StringToChars(keyObject, &todecref)))
1564 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001565
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001566 if (*key == NUL)
1567 {
1568 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001569 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001570 return -1;
1571 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001572
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001573 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001574
1575 if (valObject == NULL)
1576 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001577 hashitem_T *hi;
1578
Bram Moolenaardb913952012-06-29 12:54:53 +02001579 if (di == NULL)
1580 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001581 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001582 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001583 return -1;
1584 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001585 hi = hash_find(&dict->dv_hashtab, di->di_key);
1586 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001587 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001588 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001589 return 0;
1590 }
1591
1592 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001593 {
1594 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001595 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001596 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001597
1598 if (di == NULL)
1599 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001600 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001601 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001602 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001603 PyErr_NoMemory();
1604 return -1;
1605 }
1606 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001607 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001608
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001609 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001610 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001611 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001612 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001613 dictitem_free(di);
Bram Moolenaardb913952012-06-29 12:54:53 +02001614 PyErr_SetVim(_("failed to add key to dictionary"));
1615 return -1;
1616 }
1617 }
1618 else
1619 clear_tv(&di->di_tv);
1620
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001621 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001622
1623 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001624 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001625 return 0;
1626}
1627
Bram Moolenaara9922d62013-05-30 13:01:18 +02001628typedef PyObject *(*hi_to_py)(hashitem_T *);
1629
Bram Moolenaardb913952012-06-29 12:54:53 +02001630 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001631DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001632{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001633 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001634 long_u todo = dict->dv_hashtab.ht_used;
1635 Py_ssize_t i = 0;
1636 PyObject *r;
1637 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001638 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001639
1640 r = PyList_New(todo);
1641 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1642 {
1643 if (!HASHITEM_EMPTY(hi))
1644 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001645 if (!(newObj = hiconvert(hi)))
1646 {
1647 Py_DECREF(r);
1648 return NULL;
1649 }
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02001650 PyList_SET_ITEM(r, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001651 --todo;
1652 ++i;
1653 }
1654 }
1655 return r;
1656}
1657
Bram Moolenaara9922d62013-05-30 13:01:18 +02001658 static PyObject *
1659dict_key(hashitem_T *hi)
1660{
1661 return PyBytes_FromString((char *)(hi->hi_key));
1662}
1663
1664 static PyObject *
1665DictionaryListKeys(DictionaryObject *self)
1666{
1667 return DictionaryListObjects(self, dict_key);
1668}
1669
1670 static PyObject *
1671dict_val(hashitem_T *hi)
1672{
1673 dictitem_T *di;
1674
1675 di = dict_lookup(hi);
1676 return ConvertToPyObject(&di->di_tv);
1677}
1678
1679 static PyObject *
1680DictionaryListValues(DictionaryObject *self)
1681{
1682 return DictionaryListObjects(self, dict_val);
1683}
1684
1685 static PyObject *
1686dict_item(hashitem_T *hi)
1687{
1688 PyObject *keyObject;
1689 PyObject *valObject;
1690 PyObject *r;
1691
1692 if (!(keyObject = dict_key(hi)))
1693 return NULL;
1694
1695 if (!(valObject = dict_val(hi)))
1696 {
1697 Py_DECREF(keyObject);
1698 return NULL;
1699 }
1700
1701 r = Py_BuildValue("(OO)", keyObject, valObject);
1702
1703 Py_DECREF(keyObject);
1704 Py_DECREF(valObject);
1705
1706 return r;
1707}
1708
1709 static PyObject *
1710DictionaryListItems(DictionaryObject *self)
1711{
1712 return DictionaryListObjects(self, dict_item);
1713}
1714
1715 static PyObject *
1716DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1717{
1718 dict_T *dict = self->dict;
1719
1720 if (dict->dv_lock)
1721 {
1722 PyErr_SetVim(_("dict is locked"));
1723 return NULL;
1724 }
1725
1726 if (kwargs)
1727 {
1728 typval_T tv;
1729
1730 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1731 return NULL;
1732
1733 VimTryStart();
1734 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1735 clear_tv(&tv);
1736 if (VimTryEnd())
1737 return NULL;
1738 }
1739 else
1740 {
1741 PyObject *object;
1742
1743 if (!PyArg_Parse(args, "(O)", &object))
1744 return NULL;
1745
1746 if (PyObject_HasAttrString(object, "keys"))
1747 return DictionaryUpdate(self, NULL, object);
1748 else
1749 {
1750 PyObject *iterator;
1751 PyObject *item;
1752
1753 if (!(iterator = PyObject_GetIter(object)))
1754 return NULL;
1755
1756 while ((item = PyIter_Next(iterator)))
1757 {
1758 PyObject *fast;
1759 PyObject *keyObject;
1760 PyObject *valObject;
1761 PyObject *todecref;
1762 char_u *key;
1763 dictitem_T *di;
1764
1765 if (!(fast = PySequence_Fast(item, "")))
1766 {
1767 Py_DECREF(iterator);
1768 Py_DECREF(item);
1769 return NULL;
1770 }
1771
1772 Py_DECREF(item);
1773
1774 if (PySequence_Fast_GET_SIZE(fast) != 2)
1775 {
1776 Py_DECREF(iterator);
1777 Py_DECREF(fast);
1778 PyErr_SetString(PyExc_ValueError,
1779 _("expected sequence element of size 2"));
1780 return NULL;
1781 }
1782
1783 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1784
1785 if (!(key = StringToChars(keyObject, &todecref)))
1786 {
1787 Py_DECREF(iterator);
1788 Py_DECREF(fast);
1789 return NULL;
1790 }
1791
1792 di = dictitem_alloc(key);
1793
1794 Py_XDECREF(todecref);
1795
1796 if (di == NULL)
1797 {
1798 Py_DECREF(fast);
1799 Py_DECREF(iterator);
1800 PyErr_NoMemory();
1801 return NULL;
1802 }
1803 di->di_tv.v_lock = 0;
1804 di->di_tv.v_type = VAR_UNKNOWN;
1805
1806 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1807
1808 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1809 {
1810 Py_DECREF(iterator);
1811 Py_DECREF(fast);
1812 dictitem_free(di);
1813 return NULL;
1814 }
1815
1816 Py_DECREF(fast);
1817
1818 if (dict_add(dict, di) == FAIL)
1819 {
1820 Py_DECREF(iterator);
1821 dictitem_free(di);
1822 PyErr_SetVim(_("failed to add key to dictionary"));
1823 return NULL;
1824 }
1825 }
1826
1827 Py_DECREF(iterator);
1828
1829 /* Iterator may have finished due to an exception */
1830 if (PyErr_Occurred())
1831 return NULL;
1832 }
1833 }
1834 Py_INCREF(Py_None);
1835 return Py_None;
1836}
1837
1838 static PyObject *
1839DictionaryGet(DictionaryObject *self, PyObject *args)
1840{
1841 return _DictionaryItem(self, args,
1842 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1843}
1844
1845 static PyObject *
1846DictionaryPop(DictionaryObject *self, PyObject *args)
1847{
1848 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1849}
1850
1851 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001852DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001853{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001854 hashitem_T *hi;
1855 PyObject *r;
1856 PyObject *valObject;
1857 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001858
Bram Moolenaarde71b562013-06-02 17:41:54 +02001859 if (self->dict->dv_hashtab.ht_used == 0)
1860 {
1861 PyErr_SetNone(PyExc_KeyError);
1862 return NULL;
1863 }
1864
1865 hi = self->dict->dv_hashtab.ht_array;
1866 while (HASHITEM_EMPTY(hi))
1867 ++hi;
1868
1869 di = dict_lookup(hi);
1870
1871 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001872 return NULL;
1873
Bram Moolenaarde71b562013-06-02 17:41:54 +02001874 if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
1875 {
1876 Py_DECREF(valObject);
1877 return NULL;
1878 }
1879
1880 hash_remove(&self->dict->dv_hashtab, hi);
1881 dictitem_free(di);
1882
1883 return r;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001884}
1885
1886 static PyObject *
1887DictionaryHasKey(DictionaryObject *self, PyObject *args)
1888{
1889 PyObject *keyObject;
1890
1891 if (!PyArg_ParseTuple(args, "O", &keyObject))
1892 return NULL;
1893
1894 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1895}
1896
1897static PySequenceMethods DictionaryAsSeq = {
1898 0, /* sq_length */
1899 0, /* sq_concat */
1900 0, /* sq_repeat */
1901 0, /* sq_item */
1902 0, /* sq_slice */
1903 0, /* sq_ass_item */
1904 0, /* sq_ass_slice */
1905 (objobjproc) DictionaryContains, /* sq_contains */
1906 0, /* sq_inplace_concat */
1907 0, /* sq_inplace_repeat */
1908};
1909
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001910static PyMappingMethods DictionaryAsMapping = {
1911 (lenfunc) DictionaryLength,
1912 (binaryfunc) DictionaryItem,
1913 (objobjargproc) DictionaryAssItem,
1914};
1915
Bram Moolenaardb913952012-06-29 12:54:53 +02001916static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001917 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001918 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
1919 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
1920 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
1921 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
1922 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02001923 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001924 {"has_key", (PyCFunction)DictionaryHasKey, METH_VARARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001925 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1926 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001927};
1928
1929static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001930static PySequenceMethods ListAsSeq;
1931static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001932
1933typedef struct
1934{
1935 PyObject_HEAD
1936 list_T *list;
1937 pylinkedlist_T ref;
1938} ListObject;
1939
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001940#define NEW_LIST(list) ListNew(&ListType, list)
1941
Bram Moolenaardb913952012-06-29 12:54:53 +02001942 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001943ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02001944{
1945 ListObject *self;
1946
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001947 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001948 if (self == NULL)
1949 return NULL;
1950 self->list = list;
1951 ++list->lv_refcount;
1952
1953 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1954
1955 return (PyObject *)(self);
1956}
1957
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001958 static list_T *
1959py_list_alloc()
1960{
1961 list_T *r;
1962
1963 if (!(r = list_alloc()))
1964 {
1965 PyErr_NoMemory();
1966 return NULL;
1967 }
1968 ++r->lv_refcount;
1969
1970 return r;
1971}
1972
1973 static int
1974list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
1975{
1976 PyObject *iterator;
1977 PyObject *item;
1978 listitem_T *li;
1979
1980 if (!(iterator = PyObject_GetIter(obj)))
1981 return -1;
1982
1983 while ((item = PyIter_Next(iterator)))
1984 {
1985 if (!(li = listitem_alloc()))
1986 {
1987 PyErr_NoMemory();
1988 Py_DECREF(item);
1989 Py_DECREF(iterator);
1990 return -1;
1991 }
1992 li->li_tv.v_lock = 0;
1993 li->li_tv.v_type = VAR_UNKNOWN;
1994
1995 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
1996 {
1997 Py_DECREF(item);
1998 Py_DECREF(iterator);
1999 listitem_free(li);
2000 return -1;
2001 }
2002
2003 Py_DECREF(item);
2004
2005 list_append(l, li);
2006 }
2007
2008 Py_DECREF(iterator);
2009
2010 /* Iterator may have finished due to an exception */
2011 if (PyErr_Occurred())
2012 return -1;
2013
2014 return 0;
2015}
2016
2017 static PyObject *
2018ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2019{
2020 list_T *list;
2021 PyObject *obj = NULL;
2022
2023 if (kwargs)
2024 {
2025 PyErr_SetString(PyExc_TypeError,
2026 _("list constructor does not accept keyword arguments"));
2027 return NULL;
2028 }
2029
2030 if (!PyArg_ParseTuple(args, "|O", &obj))
2031 return NULL;
2032
2033 if (!(list = py_list_alloc()))
2034 return NULL;
2035
2036 if (obj)
2037 {
2038 PyObject *lookup_dict;
2039
2040 if (!(lookup_dict = PyDict_New()))
2041 {
2042 list_unref(list);
2043 return NULL;
2044 }
2045
2046 if (list_py_concat(list, obj, lookup_dict) == -1)
2047 {
2048 Py_DECREF(lookup_dict);
2049 list_unref(list);
2050 return NULL;
2051 }
2052
2053 Py_DECREF(lookup_dict);
2054 }
2055
2056 return ListNew(subtype, list);
2057}
2058
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002059 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002060ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002061{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002062 pyll_remove(&self->ref, &lastlist);
2063 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002064
2065 DESTRUCTOR_FINISH(self);
2066}
2067
Bram Moolenaardb913952012-06-29 12:54:53 +02002068 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002069ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002070{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002071 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002072}
2073
2074 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002075ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002076{
2077 listitem_T *li;
2078
Bram Moolenaard6e39182013-05-21 18:30:34 +02002079 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002080 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002081 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002082 return NULL;
2083 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002084 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002085 if (li == NULL)
2086 {
2087 PyErr_SetVim(_("internal error: failed to get vim list item"));
2088 return NULL;
2089 }
2090 return ConvertToPyObject(&li->li_tv);
2091}
2092
2093#define PROC_RANGE \
2094 if (last < 0) {\
2095 if (last < -size) \
2096 last = 0; \
2097 else \
2098 last += size; \
2099 } \
2100 if (first < 0) \
2101 first = 0; \
2102 if (first > size) \
2103 first = size; \
2104 if (last > size) \
2105 last = size;
2106
2107 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002108ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02002109{
2110 PyInt i;
2111 PyInt size = ListLength(self);
2112 PyInt n;
2113 PyObject *list;
2114 int reversed = 0;
2115
2116 PROC_RANGE
2117 if (first >= last)
2118 first = last;
2119
2120 n = last-first;
2121 list = PyList_New(n);
2122 if (list == NULL)
2123 return NULL;
2124
2125 for (i = 0; i < n; ++i)
2126 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02002127 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02002128 if (item == NULL)
2129 {
2130 Py_DECREF(list);
2131 return NULL;
2132 }
2133
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02002134 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002135 }
2136
2137 return list;
2138}
2139
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002140typedef struct
2141{
2142 listwatch_T lw;
2143 list_T *list;
2144} listiterinfo_T;
2145
2146 static void
2147ListIterDestruct(listiterinfo_T *lii)
2148{
2149 list_rem_watch(lii->list, &lii->lw);
2150 PyMem_Free(lii);
2151}
2152
2153 static PyObject *
2154ListIterNext(listiterinfo_T **lii)
2155{
2156 PyObject *r;
2157
2158 if (!((*lii)->lw.lw_item))
2159 return NULL;
2160
2161 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
2162 return NULL;
2163
2164 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2165
2166 return r;
2167}
2168
2169 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002170ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002171{
2172 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002173 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002174
2175 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2176 {
2177 PyErr_NoMemory();
2178 return NULL;
2179 }
2180
2181 list_add_watch(l, &lii->lw);
2182 lii->lw.lw_item = l->lv_first;
2183 lii->list = l;
2184
2185 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002186 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2187 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002188}
2189
Bram Moolenaardb913952012-06-29 12:54:53 +02002190 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002191ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002192{
2193 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002194 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002195 listitem_T *li;
2196 Py_ssize_t length = ListLength(self);
2197
2198 if (l->lv_lock)
2199 {
2200 PyErr_SetVim(_("list is locked"));
2201 return -1;
2202 }
2203 if (index>length || (index==length && obj==NULL))
2204 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002205 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002206 return -1;
2207 }
2208
2209 if (obj == NULL)
2210 {
2211 li = list_find(l, (long) index);
2212 list_remove(l, li, li);
2213 clear_tv(&li->li_tv);
2214 vim_free(li);
2215 return 0;
2216 }
2217
2218 if (ConvertFromPyObject(obj, &tv) == -1)
2219 return -1;
2220
2221 if (index == length)
2222 {
2223 if (list_append_tv(l, &tv) == FAIL)
2224 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002225 clear_tv(&tv);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002226 PyErr_SetVim(_("failed to add item to list"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002227 return -1;
2228 }
2229 }
2230 else
2231 {
2232 li = list_find(l, (long) index);
2233 clear_tv(&li->li_tv);
2234 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002235 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002236 }
2237 return 0;
2238}
2239
2240 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002241ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002242{
2243 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002244 PyObject *iterator;
2245 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02002246 listitem_T *li;
2247 listitem_T *next;
2248 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002249 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002250 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002251
2252 if (l->lv_lock)
2253 {
2254 PyErr_SetVim(_("list is locked"));
2255 return -1;
2256 }
2257
2258 PROC_RANGE
2259
2260 if (first == size)
2261 li = NULL;
2262 else
2263 {
2264 li = list_find(l, (long) first);
2265 if (li == NULL)
2266 {
2267 PyErr_SetVim(_("internal error: no vim list item"));
2268 return -1;
2269 }
2270 if (last > first)
2271 {
2272 i = last - first;
2273 while (i-- && li != NULL)
2274 {
2275 next = li->li_next;
2276 listitem_remove(l, li);
2277 li = next;
2278 }
2279 }
2280 }
2281
2282 if (obj == NULL)
2283 return 0;
2284
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002285 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002286 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02002287
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002288 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002289 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002290 if (ConvertFromPyObject(item, &v) == -1)
2291 {
2292 Py_DECREF(iterator);
2293 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002294 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002295 }
2296 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002297 if (list_insert_tv(l, &v, li) == FAIL)
2298 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002299 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002300 PyErr_SetVim(_("internal error: failed to add item to list"));
2301 return -1;
2302 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002303 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002304 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002305 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02002306 return 0;
2307}
2308
2309 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002310ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002311{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002312 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002313 PyObject *lookup_dict;
2314
2315 if (l->lv_lock)
2316 {
2317 PyErr_SetVim(_("list is locked"));
2318 return NULL;
2319 }
2320
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02002321 if (!(lookup_dict = PyDict_New()))
2322 return NULL;
2323
Bram Moolenaardb913952012-06-29 12:54:53 +02002324 if (list_py_concat(l, obj, lookup_dict) == -1)
2325 {
2326 Py_DECREF(lookup_dict);
2327 return NULL;
2328 }
2329 Py_DECREF(lookup_dict);
2330
2331 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02002332 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002333}
2334
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002335static char *ListAttrs[] = {
2336 "locked",
2337 NULL
2338};
2339
2340 static PyObject *
2341ListDir(PyObject *self)
2342{
2343 return ObjectDir(self, ListAttrs);
2344}
2345
Bram Moolenaar66b79852012-09-21 14:00:35 +02002346 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002347ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002348{
2349 if (val == NULL)
2350 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002351 PyErr_SetString(PyExc_AttributeError,
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002352 _("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002353 return -1;
2354 }
2355
2356 if (strcmp(name, "locked") == 0)
2357 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002358 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002359 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002360 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002361 return -1;
2362 }
2363 else
2364 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002365 int istrue = PyObject_IsTrue(val);
2366 if (istrue == -1)
2367 return -1;
2368 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002369 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002370 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002371 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002372 }
2373 return 0;
2374 }
2375 else
2376 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002377 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002378 return -1;
2379 }
2380}
2381
Bram Moolenaardb913952012-06-29 12:54:53 +02002382static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002383 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2384 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2385 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002386};
2387
2388typedef struct
2389{
2390 PyObject_HEAD
2391 char_u *name;
2392} FunctionObject;
2393
2394static PyTypeObject FunctionType;
2395
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002396#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
2397
Bram Moolenaardb913952012-06-29 12:54:53 +02002398 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002399FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002400{
2401 FunctionObject *self;
2402
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002403 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2404
Bram Moolenaardb913952012-06-29 12:54:53 +02002405 if (self == NULL)
2406 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002407
2408 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002409 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002410 if (!translated_function_exists(name))
2411 {
2412 PyErr_SetString(PyExc_ValueError,
2413 _("unnamed function does not exist"));
2414 return NULL;
2415 }
2416 self->name = vim_strsave(name);
2417 func_ref(self->name);
2418 }
2419 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002420 if ((self->name = get_expanded_name(name,
2421 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2422 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002423 {
Bram Moolenaar018acca2013-05-30 13:37:28 +02002424 PyErr_SetString(PyExc_ValueError, _("function does not exist"));
2425 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002426 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002427
2428 return (PyObject *)(self);
2429}
2430
2431 static PyObject *
2432FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2433{
2434 PyObject *self;
2435 char_u *name;
2436
2437 if (kwargs)
2438 {
2439 PyErr_SetString(PyExc_TypeError,
2440 _("function constructor does not accept keyword arguments"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002441 return NULL;
2442 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002443
2444 if (!PyArg_ParseTuple(args, "s", &name))
2445 return NULL;
2446
2447 self = FunctionNew(subtype, name);
2448
2449 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002450}
2451
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002452 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002453FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002454{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002455 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002456 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002457
2458 DESTRUCTOR_FINISH(self);
2459}
2460
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002461static char *FunctionAttrs[] = {
2462 "softspace",
2463 NULL
2464};
2465
2466 static PyObject *
2467FunctionDir(PyObject *self)
2468{
2469 return ObjectDir(self, FunctionAttrs);
2470}
2471
Bram Moolenaardb913952012-06-29 12:54:53 +02002472 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002473FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002474{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002475 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002476 typval_T args;
2477 typval_T selfdicttv;
2478 typval_T rettv;
2479 dict_T *selfdict = NULL;
2480 PyObject *selfdictObject;
2481 PyObject *result;
2482 int error;
2483
2484 if (ConvertFromPyObject(argsObject, &args) == -1)
2485 return NULL;
2486
2487 if (kwargs != NULL)
2488 {
2489 selfdictObject = PyDict_GetItemString(kwargs, "self");
2490 if (selfdictObject != NULL)
2491 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002492 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002493 {
2494 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002495 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002496 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002497 selfdict = selfdicttv.vval.v_dict;
2498 }
2499 }
2500
Bram Moolenaar71700b82013-05-15 17:49:05 +02002501 Py_BEGIN_ALLOW_THREADS
2502 Python_Lock_Vim();
2503
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002504 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002505 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002506
2507 Python_Release_Vim();
2508 Py_END_ALLOW_THREADS
2509
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002510 if (VimTryEnd())
2511 result = NULL;
2512 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002513 {
2514 result = NULL;
2515 PyErr_SetVim(_("failed to run function"));
2516 }
2517 else
2518 result = ConvertToPyObject(&rettv);
2519
Bram Moolenaardb913952012-06-29 12:54:53 +02002520 clear_tv(&args);
2521 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002522 if (selfdict != NULL)
2523 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002524
2525 return result;
2526}
2527
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002528 static PyObject *
2529FunctionRepr(FunctionObject *self)
2530{
2531 return PyString_FromFormat("<vim.Function '%s'>", self->name);
2532}
2533
Bram Moolenaardb913952012-06-29 12:54:53 +02002534static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002535 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2536 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002537};
2538
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002539/*
2540 * Options object
2541 */
2542
2543static PyTypeObject OptionsType;
2544
2545typedef int (*checkfun)(void *);
2546
2547typedef struct
2548{
2549 PyObject_HEAD
2550 int opt_type;
2551 void *from;
2552 checkfun Check;
2553 PyObject *fromObj;
2554} OptionsObject;
2555
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002556 static int
2557dummy_check(void *arg UNUSED)
2558{
2559 return 0;
2560}
2561
2562 static PyObject *
2563OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2564{
2565 OptionsObject *self;
2566
Bram Moolenaar774267b2013-05-21 20:51:59 +02002567 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002568 if (self == NULL)
2569 return NULL;
2570
2571 self->opt_type = opt_type;
2572 self->from = from;
2573 self->Check = Check;
2574 self->fromObj = fromObj;
2575 if (fromObj)
2576 Py_INCREF(fromObj);
2577
2578 return (PyObject *)(self);
2579}
2580
2581 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002582OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002583{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002584 PyObject_GC_UnTrack((void *)(self));
2585 Py_XDECREF(self->fromObj);
2586 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002587}
2588
2589 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002590OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002591{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002592 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002593 return 0;
2594}
2595
2596 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002597OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002598{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002599 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002600 return 0;
2601}
2602
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002603 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002604OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002605{
2606 char_u *key;
2607 int flags;
2608 long numval;
2609 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002610 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002611
Bram Moolenaard6e39182013-05-21 18:30:34 +02002612 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002613 return NULL;
2614
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002615 if (!(key = StringToChars(keyObject, &todecref)))
2616 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002617
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002618 if (*key == NUL)
2619 {
2620 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002621 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002622 return NULL;
2623 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002624
2625 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002626 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002627
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002628 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002629
2630 if (flags == 0)
2631 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002632 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002633 return NULL;
2634 }
2635
2636 if (flags & SOPT_UNSET)
2637 {
2638 Py_INCREF(Py_None);
2639 return Py_None;
2640 }
2641 else if (flags & SOPT_BOOL)
2642 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002643 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002644 r = numval ? Py_True : Py_False;
2645 Py_INCREF(r);
2646 return r;
2647 }
2648 else if (flags & SOPT_NUM)
2649 return PyInt_FromLong(numval);
2650 else if (flags & SOPT_STRING)
2651 {
2652 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002653 {
2654 PyObject *r = PyBytes_FromString((char *) stringval);
2655 vim_free(stringval);
2656 return r;
2657 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002658 else
2659 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002660 PyErr_SetString(PyExc_RuntimeError,
2661 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002662 return NULL;
2663 }
2664 }
2665 else
2666 {
2667 PyErr_SetVim("Internal error: unknown option type. Should not happen");
2668 return NULL;
2669 }
2670}
2671
2672 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002673set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002674{
2675 char_u *errmsg;
2676
2677 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2678 {
2679 if (VimTryEnd())
2680 return FAIL;
2681 PyErr_SetVim((char *)errmsg);
2682 return FAIL;
2683 }
2684 return OK;
2685}
2686
2687 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002688set_option_value_for(
2689 char_u *key,
2690 int numval,
2691 char_u *stringval,
2692 int opt_flags,
2693 int opt_type,
2694 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002695{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002696 win_T *save_curwin = NULL;
2697 tabpage_T *save_curtab = NULL;
2698 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002699 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002700
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002701 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002702 switch (opt_type)
2703 {
2704 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002705 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02002706 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002707 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002708 if (VimTryEnd())
2709 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002710 PyErr_SetVim("Problem while switching windows.");
2711 return -1;
2712 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002713 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaard6949742013-06-16 14:18:28 +02002714 restore_win(save_curwin, save_curtab, FALSE);
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_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002719 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002720 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002721 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002722 if (r == FAIL)
2723 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002724 break;
2725 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002726 r = set_option_value_err(key, numval, stringval, opt_flags);
2727 if (r == FAIL)
2728 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002729 break;
2730 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002731 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002732}
2733
2734 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002735OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002736{
2737 char_u *key;
2738 int flags;
2739 int opt_flags;
2740 int r = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002741 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002742
Bram Moolenaard6e39182013-05-21 18:30:34 +02002743 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002744 return -1;
2745
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002746 if (!(key = StringToChars(keyObject, &todecref)))
2747 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002748
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002749 if (*key == NUL)
2750 {
2751 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002752 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002753 return -1;
2754 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002755
2756 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002757 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002758
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002759 if (flags == 0)
2760 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002761 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002762 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002763 return -1;
2764 }
2765
2766 if (valObject == NULL)
2767 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002768 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002769 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002770 PyErr_SetString(PyExc_ValueError,
2771 _("unable to unset global option"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002772 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002773 return -1;
2774 }
2775 else if (!(flags & SOPT_GLOBAL))
2776 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002777 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
2778 "without global value"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002779 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002780 return -1;
2781 }
2782 else
2783 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002784 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002785 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002786 return 0;
2787 }
2788 }
2789
Bram Moolenaard6e39182013-05-21 18:30:34 +02002790 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002791
2792 if (flags & SOPT_BOOL)
2793 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002794 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002795
Bram Moolenaarb983f752013-05-15 16:11:50 +02002796 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002797 r = -1;
2798 else
2799 r = set_option_value_for(key, istrue, NULL,
2800 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002801 }
2802 else if (flags & SOPT_NUM)
2803 {
2804 int val;
2805
2806#if PY_MAJOR_VERSION < 3
2807 if (PyInt_Check(valObject))
2808 val = PyInt_AsLong(valObject);
2809 else
2810#endif
2811 if (PyLong_Check(valObject))
2812 val = PyLong_AsLong(valObject);
2813 else
2814 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002815 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002816 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002817 return -1;
2818 }
2819
2820 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002821 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002822 }
2823 else
2824 {
2825 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002826 PyObject *todecref;
2827
2828 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002829 r = set_option_value_for(key, 0, val, opt_flags,
2830 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002831 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002832 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002833 }
2834
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002835 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002836
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002837 return r;
2838}
2839
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002840static PyMappingMethods OptionsAsMapping = {
2841 (lenfunc) NULL,
2842 (binaryfunc) OptionsItem,
2843 (objobjargproc) OptionsAssItem,
2844};
2845
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002846/* Tabpage object
2847 */
2848
2849typedef struct
2850{
2851 PyObject_HEAD
2852 tabpage_T *tab;
2853} TabPageObject;
2854
2855static PyObject *WinListNew(TabPageObject *tabObject);
2856
2857static PyTypeObject TabPageType;
2858
2859 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002860CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002861{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002862 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002863 {
2864 PyErr_SetVim(_("attempt to refer to deleted tab page"));
2865 return -1;
2866 }
2867
2868 return 0;
2869}
2870
2871 static PyObject *
2872TabPageNew(tabpage_T *tab)
2873{
2874 TabPageObject *self;
2875
2876 if (TAB_PYTHON_REF(tab))
2877 {
2878 self = TAB_PYTHON_REF(tab);
2879 Py_INCREF(self);
2880 }
2881 else
2882 {
2883 self = PyObject_NEW(TabPageObject, &TabPageType);
2884 if (self == NULL)
2885 return NULL;
2886 self->tab = tab;
2887 TAB_PYTHON_REF(tab) = self;
2888 }
2889
2890 return (PyObject *)(self);
2891}
2892
2893 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002894TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002895{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002896 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
2897 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002898
2899 DESTRUCTOR_FINISH(self);
2900}
2901
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002902static char *TabPageAttrs[] = {
2903 "windows", "number", "vars", "window", "valid",
2904 NULL
2905};
2906
2907 static PyObject *
2908TabPageDir(PyObject *self)
2909{
2910 return ObjectDir(self, TabPageAttrs);
2911}
2912
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002913 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002914TabPageAttrValid(TabPageObject *self, char *name)
2915{
2916 PyObject *r;
2917
2918 if (strcmp(name, "valid") != 0)
2919 return NULL;
2920
2921 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
2922 Py_INCREF(r);
2923 return r;
2924}
2925
2926 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002927TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002928{
2929 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002930 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002931 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002932 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002933 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002934 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002935 else if (strcmp(name, "window") == 0)
2936 {
2937 /* For current tab window.c does not bother to set or update tp_curwin
2938 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002939 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002940 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002941 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002942 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002943 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002944 else if (strcmp(name, "__members__") == 0)
2945 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002946 return NULL;
2947}
2948
2949 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002950TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002951{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002952 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002953 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002954 else
2955 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002956 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002957
2958 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002959 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2960 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002961 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002962 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002963 }
2964}
2965
2966static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002967 /* name, function, calling, documentation */
2968 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2969 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002970};
2971
2972/*
2973 * Window list object
2974 */
2975
2976static PyTypeObject TabListType;
2977static PySequenceMethods TabListAsSeq;
2978
2979typedef struct
2980{
2981 PyObject_HEAD
2982} TabListObject;
2983
2984 static PyInt
2985TabListLength(PyObject *self UNUSED)
2986{
2987 tabpage_T *tp = first_tabpage;
2988 PyInt n = 0;
2989
2990 while (tp != NULL)
2991 {
2992 ++n;
2993 tp = tp->tp_next;
2994 }
2995
2996 return n;
2997}
2998
2999 static PyObject *
3000TabListItem(PyObject *self UNUSED, PyInt n)
3001{
3002 tabpage_T *tp;
3003
3004 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
3005 if (n == 0)
3006 return TabPageNew(tp);
3007
3008 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
3009 return NULL;
3010}
3011
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003012/* Window object
3013 */
3014
3015typedef struct
3016{
3017 PyObject_HEAD
3018 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003019 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003020} WindowObject;
3021
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003022static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003023
3024 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003025CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003026{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003027 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003028 {
3029 PyErr_SetVim(_("attempt to refer to deleted window"));
3030 return -1;
3031 }
3032
3033 return 0;
3034}
3035
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003036 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003037WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02003038{
3039 /* We need to handle deletion of windows underneath us.
3040 * If we add a "w_python*_ref" field to the win_T structure,
3041 * then we can get at it in win_free() in vim. We then
3042 * need to create only ONE Python object per window - if
3043 * we try to create a second, just INCREF the existing one
3044 * and return it. The (single) Python object referring to
3045 * the window is stored in "w_python*_ref".
3046 * On a win_free() we set the Python object's win_T* field
3047 * to an invalid value. We trap all uses of a window
3048 * object, and reject them if the win_T* field is invalid.
3049 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003050 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003051 * w_python_ref and w_python3_ref fields respectively.
3052 */
3053
3054 WindowObject *self;
3055
3056 if (WIN_PYTHON_REF(win))
3057 {
3058 self = WIN_PYTHON_REF(win);
3059 Py_INCREF(self);
3060 }
3061 else
3062 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02003063 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02003064 if (self == NULL)
3065 return NULL;
3066 self->win = win;
3067 WIN_PYTHON_REF(win) = self;
3068 }
3069
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003070 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
3071
Bram Moolenaar971db462013-05-12 18:44:48 +02003072 return (PyObject *)(self);
3073}
3074
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003075 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003076WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003077{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003078 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02003079 if (self->win && self->win != INVALID_WINDOW_VALUE)
3080 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003081 Py_XDECREF(((PyObject *)(self->tabObject)));
3082 PyObject_GC_Del((void *)(self));
3083}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003084
Bram Moolenaar774267b2013-05-21 20:51:59 +02003085 static int
3086WindowTraverse(WindowObject *self, visitproc visit, void *arg)
3087{
3088 Py_VISIT(((PyObject *)(self->tabObject)));
3089 return 0;
3090}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003091
Bram Moolenaar774267b2013-05-21 20:51:59 +02003092 static int
3093WindowClear(WindowObject *self)
3094{
3095 Py_CLEAR(self->tabObject);
3096 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003097}
3098
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003099 static win_T *
3100get_firstwin(TabPageObject *tabObject)
3101{
3102 if (tabObject)
3103 {
3104 if (CheckTabPage(tabObject))
3105 return NULL;
3106 /* For current tab window.c does not bother to set or update tp_firstwin
3107 */
3108 else if (tabObject->tab == curtab)
3109 return firstwin;
3110 else
3111 return tabObject->tab->tp_firstwin;
3112 }
3113 else
3114 return firstwin;
3115}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003116static char *WindowAttrs[] = {
3117 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
3118 "tabpage", "valid",
3119 NULL
3120};
3121
3122 static PyObject *
3123WindowDir(PyObject *self)
3124{
3125 return ObjectDir(self, WindowAttrs);
3126}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003127
Bram Moolenaar971db462013-05-12 18:44:48 +02003128 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003129WindowAttrValid(WindowObject *self, char *name)
3130{
3131 PyObject *r;
3132
3133 if (strcmp(name, "valid") != 0)
3134 return NULL;
3135
3136 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
3137 Py_INCREF(r);
3138 return r;
3139}
3140
3141 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003142WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003143{
3144 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003145 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003146 else if (strcmp(name, "cursor") == 0)
3147 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003148 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003149
3150 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
3151 }
3152 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003153 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003154#ifdef FEAT_WINDOWS
3155 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003156 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003157#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003158#ifdef FEAT_VERTSPLIT
3159 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003160 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003161 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003162 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003163#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02003164 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003165 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003166 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003167 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
3168 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02003169 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003170 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003171 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003172 return NULL;
3173 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003174 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003175 }
3176 else if (strcmp(name, "tabpage") == 0)
3177 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003178 Py_INCREF(self->tabObject);
3179 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003180 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003181 else if (strcmp(name, "__members__") == 0)
3182 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003183 else
3184 return NULL;
3185}
3186
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003187 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003188WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003189{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003190 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003191 return -1;
3192
3193 if (strcmp(name, "buffer") == 0)
3194 {
3195 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
3196 return -1;
3197 }
3198 else if (strcmp(name, "cursor") == 0)
3199 {
3200 long lnum;
3201 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003202
3203 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
3204 return -1;
3205
Bram Moolenaard6e39182013-05-21 18:30:34 +02003206 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003207 {
3208 PyErr_SetVim(_("cursor position outside buffer"));
3209 return -1;
3210 }
3211
3212 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003213 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003214 return -1;
3215
Bram Moolenaard6e39182013-05-21 18:30:34 +02003216 self->win->w_cursor.lnum = lnum;
3217 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003218#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02003219 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003220#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003221 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003222 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003223
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003224 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003225 return 0;
3226 }
3227 else if (strcmp(name, "height") == 0)
3228 {
3229 int height;
3230 win_T *savewin;
3231
3232 if (!PyArg_Parse(val, "i", &height))
3233 return -1;
3234
3235#ifdef FEAT_GUI
3236 need_mouse_correct = TRUE;
3237#endif
3238 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003239 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003240
3241 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003242 win_setheight(height);
3243 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003244 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003245 return -1;
3246
3247 return 0;
3248 }
3249#ifdef FEAT_VERTSPLIT
3250 else if (strcmp(name, "width") == 0)
3251 {
3252 int width;
3253 win_T *savewin;
3254
3255 if (!PyArg_Parse(val, "i", &width))
3256 return -1;
3257
3258#ifdef FEAT_GUI
3259 need_mouse_correct = TRUE;
3260#endif
3261 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003262 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003263
3264 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003265 win_setwidth(width);
3266 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003267 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003268 return -1;
3269
3270 return 0;
3271 }
3272#endif
3273 else
3274 {
3275 PyErr_SetString(PyExc_AttributeError, name);
3276 return -1;
3277 }
3278}
3279
3280 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003281WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003282{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003283 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003284 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003285 else
3286 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003287 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003288
Bram Moolenaar6d216452013-05-12 19:00:41 +02003289 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003290 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003291 (self));
3292 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003293 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003294 }
3295}
3296
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003297static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003298 /* name, function, calling, documentation */
3299 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
3300 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003301};
3302
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003303/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003304 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003305 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003306
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003307static PyTypeObject WinListType;
3308static PySequenceMethods WinListAsSeq;
3309
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003310typedef struct
3311{
3312 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003313 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003314} WinListObject;
3315
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003316 static PyObject *
3317WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003318{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003319 WinListObject *self;
3320
3321 self = PyObject_NEW(WinListObject, &WinListType);
3322 self->tabObject = tabObject;
3323 Py_INCREF(tabObject);
3324
3325 return (PyObject *)(self);
3326}
3327
3328 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003329WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003330{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003331 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003332
3333 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02003334 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003335 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02003336 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003337
3338 DESTRUCTOR_FINISH(self);
3339}
3340
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003341 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003342WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003343{
3344 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003345 PyInt n = 0;
3346
Bram Moolenaard6e39182013-05-21 18:30:34 +02003347 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003348 return -1;
3349
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003350 while (w != NULL)
3351 {
3352 ++n;
3353 w = W_NEXT(w);
3354 }
3355
3356 return n;
3357}
3358
3359 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003360WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003361{
3362 win_T *w;
3363
Bram Moolenaard6e39182013-05-21 18:30:34 +02003364 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003365 return NULL;
3366
3367 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003368 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003369 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003370
3371 PyErr_SetString(PyExc_IndexError, _("no such window"));
3372 return NULL;
3373}
3374
3375/* Convert a Python string into a Vim line.
3376 *
3377 * The result is in allocated memory. All internal nulls are replaced by
3378 * newline characters. It is an error for the string to contain newline
3379 * characters.
3380 *
3381 * On errors, the Python exception data is set, and NULL is returned.
3382 */
3383 static char *
3384StringToLine(PyObject *obj)
3385{
3386 const char *str;
3387 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003388 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003389 PyInt len;
3390 PyInt i;
3391 char *p;
3392
3393 if (obj == NULL || !PyString_Check(obj))
3394 {
3395 PyErr_BadArgument();
3396 return NULL;
3397 }
3398
Bram Moolenaar19e60942011-06-19 00:27:51 +02003399 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
3400 str = PyString_AsString(bytes);
3401 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003402
3403 /*
3404 * Error checking: String must not contain newlines, as we
3405 * are replacing a single line, and we must replace it with
3406 * a single line.
3407 * A trailing newline is removed, so that append(f.readlines()) works.
3408 */
3409 p = memchr(str, '\n', len);
3410 if (p != NULL)
3411 {
3412 if (p == str + len - 1)
3413 --len;
3414 else
3415 {
3416 PyErr_SetVim(_("string cannot contain newlines"));
3417 return NULL;
3418 }
3419 }
3420
3421 /* Create a copy of the string, with internal nulls replaced by
3422 * newline characters, as is the vim convention.
3423 */
3424 save = (char *)alloc((unsigned)(len+1));
3425 if (save == NULL)
3426 {
3427 PyErr_NoMemory();
3428 return NULL;
3429 }
3430
3431 for (i = 0; i < len; ++i)
3432 {
3433 if (str[i] == '\0')
3434 save[i] = '\n';
3435 else
3436 save[i] = str[i];
3437 }
3438
3439 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02003440 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003441
3442 return save;
3443}
3444
3445/* Get a line from the specified buffer. The line number is
3446 * in Vim format (1-based). The line is returned as a Python
3447 * string object.
3448 */
3449 static PyObject *
3450GetBufferLine(buf_T *buf, PyInt n)
3451{
3452 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3453}
3454
3455
3456/* Get a list of lines from the specified buffer. The line numbers
3457 * are in Vim format (1-based). The range is from lo up to, but not
3458 * including, hi. The list is returned as a Python list of string objects.
3459 */
3460 static PyObject *
3461GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3462{
3463 PyInt i;
3464 PyInt n = hi - lo;
3465 PyObject *list = PyList_New(n);
3466
3467 if (list == NULL)
3468 return NULL;
3469
3470 for (i = 0; i < n; ++i)
3471 {
3472 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
3473
3474 /* Error check - was the Python string creation OK? */
3475 if (str == NULL)
3476 {
3477 Py_DECREF(list);
3478 return NULL;
3479 }
3480
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02003481 PyList_SET_ITEM(list, i, str);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003482 }
3483
3484 /* The ownership of the Python list is passed to the caller (ie,
3485 * the caller should Py_DECREF() the object when it is finished
3486 * with it).
3487 */
3488
3489 return list;
3490}
3491
3492/*
3493 * Check if deleting lines made the cursor position invalid.
3494 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3495 * deleted).
3496 */
3497 static void
3498py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3499{
3500 if (curwin->w_cursor.lnum >= lo)
3501 {
3502 /* Adjust the cursor position if it's in/after the changed
3503 * lines. */
3504 if (curwin->w_cursor.lnum >= hi)
3505 {
3506 curwin->w_cursor.lnum += extra;
3507 check_cursor_col();
3508 }
3509 else if (extra < 0)
3510 {
3511 curwin->w_cursor.lnum = lo;
3512 check_cursor();
3513 }
3514 else
3515 check_cursor_col();
3516 changed_cline_bef_curs();
3517 }
3518 invalidate_botline();
3519}
3520
Bram Moolenaar19e60942011-06-19 00:27:51 +02003521/*
3522 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003523 * in Vim format (1-based). The replacement line is given as
3524 * a Python string object. The object is checked for validity
3525 * and correct format. Errors are returned as a value of FAIL.
3526 * The return value is OK on success.
3527 * If OK is returned and len_change is not NULL, *len_change
3528 * is set to the change in the buffer length.
3529 */
3530 static int
3531SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3532{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003533 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003534 * There are three cases:
3535 * 1. NULL, or None - this is a deletion.
3536 * 2. A string - this is a replacement.
3537 * 3. Anything else - this is an error.
3538 */
3539 if (line == Py_None || line == NULL)
3540 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003541 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003542
3543 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003544 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003545
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003546 VimTryStart();
3547
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003548 if (u_savedel((linenr_T)n, 1L) == FAIL)
3549 PyErr_SetVim(_("cannot save undo information"));
3550 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
3551 PyErr_SetVim(_("cannot delete line"));
3552 else
3553 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003554 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003555 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3556 deleted_lines_mark((linenr_T)n, 1L);
3557 }
3558
Bram Moolenaar105bc352013-05-17 16:03:57 +02003559 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003560
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003561 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003562 return FAIL;
3563
3564 if (len_change)
3565 *len_change = -1;
3566
3567 return OK;
3568 }
3569 else if (PyString_Check(line))
3570 {
3571 char *save = StringToLine(line);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003572 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003573
3574 if (save == NULL)
3575 return FAIL;
3576
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003577 VimTryStart();
3578
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003579 /* We do not need to free "save" if ml_replace() consumes it. */
3580 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003581 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003582
3583 if (u_savesub((linenr_T)n) == FAIL)
3584 {
3585 PyErr_SetVim(_("cannot save undo information"));
3586 vim_free(save);
3587 }
3588 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3589 {
3590 PyErr_SetVim(_("cannot replace line"));
3591 vim_free(save);
3592 }
3593 else
3594 changed_bytes((linenr_T)n, 0);
3595
Bram Moolenaar105bc352013-05-17 16:03:57 +02003596 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003597
3598 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003599 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003600 check_cursor_col();
3601
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003602 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003603 return FAIL;
3604
3605 if (len_change)
3606 *len_change = 0;
3607
3608 return OK;
3609 }
3610 else
3611 {
3612 PyErr_BadArgument();
3613 return FAIL;
3614 }
3615}
3616
Bram Moolenaar19e60942011-06-19 00:27:51 +02003617/* Replace a range of lines in the specified buffer. The line numbers are in
3618 * Vim format (1-based). The range is from lo up to, but not including, hi.
3619 * The replacement lines are given as a Python list of string objects. The
3620 * list is checked for validity and correct format. Errors are returned as a
3621 * value of FAIL. The return value is OK on success.
3622 * If OK is returned and len_change is not NULL, *len_change
3623 * is set to the change in the buffer length.
3624 */
3625 static int
3626SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
3627{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003628 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003629 * There are three cases:
3630 * 1. NULL, or None - this is a deletion.
3631 * 2. A list - this is a replacement.
3632 * 3. Anything else - this is an error.
3633 */
3634 if (list == Py_None || list == NULL)
3635 {
3636 PyInt i;
3637 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003638 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003639
3640 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003641 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003642 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003643
3644 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
3645 PyErr_SetVim(_("cannot save undo information"));
3646 else
3647 {
3648 for (i = 0; i < n; ++i)
3649 {
3650 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3651 {
3652 PyErr_SetVim(_("cannot delete line"));
3653 break;
3654 }
3655 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003656 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003657 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3658 deleted_lines_mark((linenr_T)lo, (long)i);
3659 }
3660
Bram Moolenaar105bc352013-05-17 16:03:57 +02003661 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003662
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003663 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003664 return FAIL;
3665
3666 if (len_change)
3667 *len_change = -n;
3668
3669 return OK;
3670 }
3671 else if (PyList_Check(list))
3672 {
3673 PyInt i;
3674 PyInt new_len = PyList_Size(list);
3675 PyInt old_len = hi - lo;
3676 PyInt extra = 0; /* lines added to text, can be negative */
3677 char **array;
3678 buf_T *savebuf;
3679
3680 if (new_len == 0) /* avoid allocating zero bytes */
3681 array = NULL;
3682 else
3683 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003684 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003685 if (array == NULL)
3686 {
3687 PyErr_NoMemory();
3688 return FAIL;
3689 }
3690 }
3691
3692 for (i = 0; i < new_len; ++i)
3693 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003694 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003695
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003696 if (!(line = PyList_GetItem(list, i)) ||
3697 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003698 {
3699 while (i)
3700 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003701 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003702 return FAIL;
3703 }
3704 }
3705
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003706 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003707 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003708
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003709 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003710 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003711
3712 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
3713 PyErr_SetVim(_("cannot save undo information"));
3714
3715 /* If the size of the range is reducing (ie, new_len < old_len) we
3716 * need to delete some old_len. We do this at the start, by
3717 * repeatedly deleting line "lo".
3718 */
3719 if (!PyErr_Occurred())
3720 {
3721 for (i = 0; i < old_len - new_len; ++i)
3722 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3723 {
3724 PyErr_SetVim(_("cannot delete line"));
3725 break;
3726 }
3727 extra -= i;
3728 }
3729
3730 /* For as long as possible, replace the existing old_len with the
3731 * new old_len. This is a more efficient operation, as it requires
3732 * less memory allocation and freeing.
3733 */
3734 if (!PyErr_Occurred())
3735 {
3736 for (i = 0; i < old_len && i < new_len; ++i)
3737 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3738 == FAIL)
3739 {
3740 PyErr_SetVim(_("cannot replace line"));
3741 break;
3742 }
3743 }
3744 else
3745 i = 0;
3746
3747 /* Now we may need to insert the remaining new old_len. If we do, we
3748 * must free the strings as we finish with them (we can't pass the
3749 * responsibility to vim in this case).
3750 */
3751 if (!PyErr_Occurred())
3752 {
3753 while (i < new_len)
3754 {
3755 if (ml_append((linenr_T)(lo + i - 1),
3756 (char_u *)array[i], 0, FALSE) == FAIL)
3757 {
3758 PyErr_SetVim(_("cannot insert line"));
3759 break;
3760 }
3761 vim_free(array[i]);
3762 ++i;
3763 ++extra;
3764 }
3765 }
3766
3767 /* Free any left-over old_len, as a result of an error */
3768 while (i < new_len)
3769 {
3770 vim_free(array[i]);
3771 ++i;
3772 }
3773
3774 /* Free the array of old_len. All of its contents have now
3775 * been dealt with (either freed, or the responsibility passed
3776 * to vim.
3777 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003778 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003779
3780 /* Adjust marks. Invalidate any which lie in the
3781 * changed range, and move any in the remainder of the buffer.
3782 */
3783 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3784 (long)MAXLNUM, (long)extra);
3785 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3786
Bram Moolenaar105bc352013-05-17 16:03:57 +02003787 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003788 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3789
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003790 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003791 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003792
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003793 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003794 return FAIL;
3795
3796 if (len_change)
3797 *len_change = new_len - old_len;
3798
3799 return OK;
3800 }
3801 else
3802 {
3803 PyErr_BadArgument();
3804 return FAIL;
3805 }
3806}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003807
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003808/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003809 * The line number is in Vim format (1-based). The lines to be inserted are
3810 * given as a Python list of string objects or as a single string. The lines
3811 * to be added are checked for validity and correct format. Errors are
3812 * returned as a value of FAIL. The return value is OK on success.
3813 * If OK is returned and len_change is not NULL, *len_change
3814 * is set to the change in the buffer length.
3815 */
3816 static int
3817InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3818{
3819 /* First of all, we check the type of the supplied Python object.
3820 * It must be a string or a list, or the call is in error.
3821 */
3822 if (PyString_Check(lines))
3823 {
3824 char *str = StringToLine(lines);
3825 buf_T *savebuf;
3826
3827 if (str == NULL)
3828 return FAIL;
3829
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003830 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003831 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003832 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003833
3834 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
3835 PyErr_SetVim(_("cannot save undo information"));
3836 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
3837 PyErr_SetVim(_("cannot insert line"));
3838 else
3839 appended_lines_mark((linenr_T)n, 1L);
3840
3841 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003842 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003843 update_screen(VALID);
3844
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003845 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003846 return FAIL;
3847
3848 if (len_change)
3849 *len_change = 1;
3850
3851 return OK;
3852 }
3853 else if (PyList_Check(lines))
3854 {
3855 PyInt i;
3856 PyInt size = PyList_Size(lines);
3857 char **array;
3858 buf_T *savebuf;
3859
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003860 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003861 if (array == NULL)
3862 {
3863 PyErr_NoMemory();
3864 return FAIL;
3865 }
3866
3867 for (i = 0; i < size; ++i)
3868 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003869 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003870
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003871 if (!(line = PyList_GetItem(lines, i)) ||
3872 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003873 {
3874 while (i)
3875 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003876 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003877 return FAIL;
3878 }
3879 }
3880
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003881 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003882 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003883 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003884
3885 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
3886 PyErr_SetVim(_("cannot save undo information"));
3887 else
3888 {
3889 for (i = 0; i < size; ++i)
3890 {
3891 if (ml_append((linenr_T)(n + i),
3892 (char_u *)array[i], 0, FALSE) == FAIL)
3893 {
3894 PyErr_SetVim(_("cannot insert line"));
3895
3896 /* Free the rest of the lines */
3897 while (i < size)
3898 vim_free(array[i++]);
3899
3900 break;
3901 }
3902 vim_free(array[i]);
3903 }
3904 if (i > 0)
3905 appended_lines_mark((linenr_T)n, (long)i);
3906 }
3907
3908 /* Free the array of lines. All of its contents have now
3909 * been freed.
3910 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003911 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003912
Bram Moolenaar105bc352013-05-17 16:03:57 +02003913 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003914 update_screen(VALID);
3915
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003916 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003917 return FAIL;
3918
3919 if (len_change)
3920 *len_change = size;
3921
3922 return OK;
3923 }
3924 else
3925 {
3926 PyErr_BadArgument();
3927 return FAIL;
3928 }
3929}
3930
3931/*
3932 * Common routines for buffers and line ranges
3933 * -------------------------------------------
3934 */
3935
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003936typedef struct
3937{
3938 PyObject_HEAD
3939 buf_T *buf;
3940} BufferObject;
3941
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003942 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003943CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003944{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003945 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003946 {
3947 PyErr_SetVim(_("attempt to refer to deleted buffer"));
3948 return -1;
3949 }
3950
3951 return 0;
3952}
3953
3954 static PyObject *
3955RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3956{
3957 if (CheckBuffer(self))
3958 return NULL;
3959
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003960 if (end == -1)
3961 end = self->buf->b_ml.ml_line_count;
3962
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003963 if (n < 0)
3964 n += end - start + 1;
3965
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003966 if (n < 0 || n > end - start)
3967 {
3968 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3969 return NULL;
3970 }
3971
3972 return GetBufferLine(self->buf, n+start);
3973}
3974
3975 static PyObject *
3976RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3977{
3978 PyInt size;
3979
3980 if (CheckBuffer(self))
3981 return NULL;
3982
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003983 if (end == -1)
3984 end = self->buf->b_ml.ml_line_count;
3985
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003986 size = end - start + 1;
3987
3988 if (lo < 0)
3989 lo = 0;
3990 else if (lo > size)
3991 lo = size;
3992 if (hi < 0)
3993 hi = 0;
3994 if (hi < lo)
3995 hi = lo;
3996 else if (hi > size)
3997 hi = size;
3998
3999 return GetBufferLineList(self->buf, lo+start, hi+start);
4000}
4001
4002 static PyInt
4003RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
4004{
4005 PyInt len_change;
4006
4007 if (CheckBuffer(self))
4008 return -1;
4009
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004010 if (end == -1)
4011 end = self->buf->b_ml.ml_line_count;
4012
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004013 if (n < 0)
4014 n += end - start + 1;
4015
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004016 if (n < 0 || n > end - start)
4017 {
4018 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
4019 return -1;
4020 }
4021
4022 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
4023 return -1;
4024
4025 if (new_end)
4026 *new_end = end + len_change;
4027
4028 return 0;
4029}
4030
Bram Moolenaar19e60942011-06-19 00:27:51 +02004031 static PyInt
4032RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
4033{
4034 PyInt size;
4035 PyInt len_change;
4036
4037 /* Self must be a valid buffer */
4038 if (CheckBuffer(self))
4039 return -1;
4040
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004041 if (end == -1)
4042 end = self->buf->b_ml.ml_line_count;
4043
Bram Moolenaar19e60942011-06-19 00:27:51 +02004044 /* Sort out the slice range */
4045 size = end - start + 1;
4046
4047 if (lo < 0)
4048 lo = 0;
4049 else if (lo > size)
4050 lo = size;
4051 if (hi < 0)
4052 hi = 0;
4053 if (hi < lo)
4054 hi = lo;
4055 else if (hi > size)
4056 hi = size;
4057
4058 if (SetBufferLineList(self->buf, lo + start, hi + start,
4059 val, &len_change) == FAIL)
4060 return -1;
4061
4062 if (new_end)
4063 *new_end = end + len_change;
4064
4065 return 0;
4066}
4067
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004068
4069 static PyObject *
4070RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
4071{
4072 PyObject *lines;
4073 PyInt len_change;
4074 PyInt max;
4075 PyInt n;
4076
4077 if (CheckBuffer(self))
4078 return NULL;
4079
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004080 if (end == -1)
4081 end = self->buf->b_ml.ml_line_count;
4082
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004083 max = n = end - start + 1;
4084
4085 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
4086 return NULL;
4087
4088 if (n < 0 || n > max)
4089 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004090 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004091 return NULL;
4092 }
4093
4094 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
4095 return NULL;
4096
4097 if (new_end)
4098 *new_end = end + len_change;
4099
4100 Py_INCREF(Py_None);
4101 return Py_None;
4102}
4103
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004104/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004105 */
4106
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004107static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004108static PySequenceMethods RangeAsSeq;
4109static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004110
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004111typedef struct
4112{
4113 PyObject_HEAD
4114 BufferObject *buf;
4115 PyInt start;
4116 PyInt end;
4117} RangeObject;
4118
4119 static PyObject *
4120RangeNew(buf_T *buf, PyInt start, PyInt end)
4121{
4122 BufferObject *bufr;
4123 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004124 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004125 if (self == NULL)
4126 return NULL;
4127
4128 bufr = (BufferObject *)BufferNew(buf);
4129 if (bufr == NULL)
4130 {
4131 Py_DECREF(self);
4132 return NULL;
4133 }
4134 Py_INCREF(bufr);
4135
4136 self->buf = bufr;
4137 self->start = start;
4138 self->end = end;
4139
4140 return (PyObject *)(self);
4141}
4142
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004143 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004144RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004145{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004146 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004147 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02004148 PyObject_GC_Del((void *)(self));
4149}
4150
4151 static int
4152RangeTraverse(RangeObject *self, visitproc visit, void *arg)
4153{
4154 Py_VISIT(((PyObject *)(self->buf)));
4155 return 0;
4156}
4157
4158 static int
4159RangeClear(RangeObject *self)
4160{
4161 Py_CLEAR(self->buf);
4162 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004163}
4164
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004165 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004166RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004167{
4168 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004169 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004170 return -1; /* ??? */
4171
Bram Moolenaard6e39182013-05-21 18:30:34 +02004172 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004173}
4174
4175 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004176RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004177{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004178 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004179}
4180
4181 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004182RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004183{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004184 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004185}
4186
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004187static char *RangeAttrs[] = {
4188 "start", "end",
4189 NULL
4190};
4191
4192 static PyObject *
4193RangeDir(PyObject *self)
4194{
4195 return ObjectDir(self, RangeAttrs);
4196}
4197
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004198 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004199RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004200{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004201 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004202}
4203
4204 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004205RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004206{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004207 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004208 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
4209 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004210 else
4211 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004212 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004213
4214 if (name == NULL)
4215 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004216
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004217 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02004218 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004219 }
4220}
4221
4222static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004223 /* name, function, calling, documentation */
4224 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004225 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
4226 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004227};
4228
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004229static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004230static PySequenceMethods BufferAsSeq;
4231static PyMappingMethods BufferAsMapping;
4232
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004233 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02004234BufferNew(buf_T *buf)
4235{
4236 /* We need to handle deletion of buffers underneath us.
4237 * If we add a "b_python*_ref" field to the buf_T structure,
4238 * then we can get at it in buf_freeall() in vim. We then
4239 * need to create only ONE Python object per buffer - if
4240 * we try to create a second, just INCREF the existing one
4241 * and return it. The (single) Python object referring to
4242 * the buffer is stored in "b_python*_ref".
4243 * Question: what to do on a buf_freeall(). We'll probably
4244 * have to either delete the Python object (DECREF it to
4245 * zero - a bad idea, as it leaves dangling refs!) or
4246 * set the buf_T * value to an invalid value (-1?), which
4247 * means we need checks in all access functions... Bah.
4248 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004249 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02004250 * b_python_ref and b_python3_ref fields respectively.
4251 */
4252
4253 BufferObject *self;
4254
4255 if (BUF_PYTHON_REF(buf) != NULL)
4256 {
4257 self = BUF_PYTHON_REF(buf);
4258 Py_INCREF(self);
4259 }
4260 else
4261 {
4262 self = PyObject_NEW(BufferObject, &BufferType);
4263 if (self == NULL)
4264 return NULL;
4265 self->buf = buf;
4266 BUF_PYTHON_REF(buf) = self;
4267 }
4268
4269 return (PyObject *)(self);
4270}
4271
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004272 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004273BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004274{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004275 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
4276 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004277
4278 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004279}
4280
Bram Moolenaar971db462013-05-12 18:44:48 +02004281 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004282BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02004283{
4284 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004285 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02004286 return -1; /* ??? */
4287
Bram Moolenaard6e39182013-05-21 18:30:34 +02004288 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02004289}
4290
4291 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004292BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02004293{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004294 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004295}
4296
4297 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004298BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02004299{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004300 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004301}
4302
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004303static char *BufferAttrs[] = {
4304 "name", "number", "vars", "options", "valid",
4305 NULL
4306};
4307
4308 static PyObject *
4309BufferDir(PyObject *self)
4310{
4311 return ObjectDir(self, BufferAttrs);
4312}
4313
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004314 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004315BufferAttrValid(BufferObject *self, char *name)
4316{
4317 PyObject *r;
4318
4319 if (strcmp(name, "valid") != 0)
4320 return NULL;
4321
4322 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
4323 Py_INCREF(r);
4324 return r;
4325}
4326
4327 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004328BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004329{
4330 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02004331 return PyString_FromString((self->buf->b_ffname == NULL
4332 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004333 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004334 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004335 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004336 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004337 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004338 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
4339 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004340 else if (strcmp(name, "__members__") == 0)
4341 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004342 else
4343 return NULL;
4344}
4345
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004346 static int
4347BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
4348{
4349 if (CheckBuffer(self))
4350 return -1;
4351
4352 if (strcmp(name, "name") == 0)
4353 {
4354 char_u *val;
4355 aco_save_T aco;
4356 int r;
4357 PyObject *todecref;
4358
4359 if (!(val = StringToChars(valObject, &todecref)))
4360 return -1;
4361
4362 VimTryStart();
4363 /* Using aucmd_*: autocommands will be executed by rename_buffer */
4364 aucmd_prepbuf(&aco, self->buf);
4365 r = rename_buffer(val);
4366 aucmd_restbuf(&aco);
4367 Py_XDECREF(todecref);
4368 if (VimTryEnd())
4369 return -1;
4370
4371 if (r == FAIL)
4372 {
4373 PyErr_SetVim(_("failed to rename buffer"));
4374 return -1;
4375 }
4376 return 0;
4377 }
4378 else
4379 {
4380 PyErr_SetString(PyExc_AttributeError, name);
4381 return -1;
4382 }
4383}
4384
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004385 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004386BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004387{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004388 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004389}
4390
4391 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004392BufferMark(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004393{
4394 pos_T *posp;
4395 char *pmark;
4396 char mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004397 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004398
Bram Moolenaard6e39182013-05-21 18:30:34 +02004399 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004400 return NULL;
4401
4402 if (!PyArg_ParseTuple(args, "s", &pmark))
4403 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004404
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004405 if (STRLEN(pmark) != 1)
4406 {
4407 PyErr_SetString(PyExc_ValueError,
4408 _("mark name must be a single character"));
4409 return NULL;
4410 }
4411
4412 mark = *pmark;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004413 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004414 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004415 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004416 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004417 if (VimTryEnd())
4418 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004419
4420 if (posp == NULL)
4421 {
4422 PyErr_SetVim(_("invalid mark name"));
4423 return NULL;
4424 }
4425
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004426 if (posp->lnum <= 0)
4427 {
4428 /* Or raise an error? */
4429 Py_INCREF(Py_None);
4430 return Py_None;
4431 }
4432
4433 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4434}
4435
4436 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004437BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004438{
4439 PyInt start;
4440 PyInt end;
4441
Bram Moolenaard6e39182013-05-21 18:30:34 +02004442 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004443 return NULL;
4444
4445 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4446 return NULL;
4447
Bram Moolenaard6e39182013-05-21 18:30:34 +02004448 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004449}
4450
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004451 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004452BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004453{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004454 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004455 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004456 else
4457 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004458 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004459
4460 if (name == NULL)
4461 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004462
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004463 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004464 }
4465}
4466
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004467static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004468 /* name, function, calling, documentation */
4469 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
4470 {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" },
4471 {"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 +02004472 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4473 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004474};
4475
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004476/*
4477 * Buffer list object - Implementation
4478 */
4479
4480static PyTypeObject BufMapType;
4481
4482typedef struct
4483{
4484 PyObject_HEAD
4485} BufMapObject;
4486
4487 static PyInt
4488BufMapLength(PyObject *self UNUSED)
4489{
4490 buf_T *b = firstbuf;
4491 PyInt n = 0;
4492
4493 while (b)
4494 {
4495 ++n;
4496 b = b->b_next;
4497 }
4498
4499 return n;
4500}
4501
4502 static PyObject *
4503BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4504{
4505 buf_T *b;
4506 int bnr;
4507
4508#if PY_MAJOR_VERSION < 3
4509 if (PyInt_Check(keyObject))
4510 bnr = PyInt_AsLong(keyObject);
4511 else
4512#endif
4513 if (PyLong_Check(keyObject))
4514 bnr = PyLong_AsLong(keyObject);
4515 else
4516 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004517 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004518 return NULL;
4519 }
4520
4521 b = buflist_findnr(bnr);
4522
4523 if (b)
4524 return BufferNew(b);
4525 else
4526 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004527 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004528 return NULL;
4529 }
4530}
4531
4532 static void
4533BufMapIterDestruct(PyObject *buffer)
4534{
4535 /* Iteration was stopped before all buffers were processed */
4536 if (buffer)
4537 {
4538 Py_DECREF(buffer);
4539 }
4540}
4541
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004542 static int
4543BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4544{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004545 if (buffer)
4546 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004547 return 0;
4548}
4549
4550 static int
4551BufMapIterClear(PyObject **buffer)
4552{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004553 if (*buffer)
4554 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004555 return 0;
4556}
4557
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004558 static PyObject *
4559BufMapIterNext(PyObject **buffer)
4560{
4561 PyObject *next;
4562 PyObject *r;
4563
4564 if (!*buffer)
4565 return NULL;
4566
4567 r = *buffer;
4568
4569 if (CheckBuffer((BufferObject *)(r)))
4570 {
4571 *buffer = NULL;
4572 return NULL;
4573 }
4574
4575 if (!((BufferObject *)(r))->buf->b_next)
4576 next = NULL;
4577 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
4578 return NULL;
4579 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004580 /* Do not increment reference: we no longer hold it (decref), but whoever
4581 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004582 return r;
4583}
4584
4585 static PyObject *
4586BufMapIter(PyObject *self UNUSED)
4587{
4588 PyObject *buffer;
4589
4590 buffer = BufferNew(firstbuf);
4591 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004592 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4593 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004594}
4595
4596static PyMappingMethods BufMapAsMapping = {
4597 (lenfunc) BufMapLength,
4598 (binaryfunc) BufMapItem,
4599 (objobjargproc) 0,
4600};
4601
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004602/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004603 */
4604
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004605static char *CurrentAttrs[] = {
4606 "buffer", "window", "line", "range", "tabpage",
4607 NULL
4608};
4609
4610 static PyObject *
4611CurrentDir(PyObject *self)
4612{
4613 return ObjectDir(self, CurrentAttrs);
4614}
4615
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004616 static PyObject *
4617CurrentGetattr(PyObject *self UNUSED, char *name)
4618{
4619 if (strcmp(name, "buffer") == 0)
4620 return (PyObject *)BufferNew(curbuf);
4621 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004622 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004623 else if (strcmp(name, "tabpage") == 0)
4624 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004625 else if (strcmp(name, "line") == 0)
4626 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4627 else if (strcmp(name, "range") == 0)
4628 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004629 else if (strcmp(name, "__members__") == 0)
4630 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004631 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004632#if PY_MAJOR_VERSION < 3
4633 return Py_FindMethod(WindowMethods, self, name);
4634#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004635 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004636#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004637}
4638
4639 static int
4640CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
4641{
4642 if (strcmp(name, "line") == 0)
4643 {
4644 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
4645 return -1;
4646
4647 return 0;
4648 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004649 else if (strcmp(name, "buffer") == 0)
4650 {
4651 int count;
4652
4653 if (value->ob_type != &BufferType)
4654 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004655 PyErr_SetString(PyExc_TypeError, _("expected vim.Buffer object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004656 return -1;
4657 }
4658
4659 if (CheckBuffer((BufferObject *)(value)))
4660 return -1;
4661 count = ((BufferObject *)(value))->buf->b_fnum;
4662
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004663 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004664 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4665 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004666 if (VimTryEnd())
4667 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004668 PyErr_SetVim(_("failed to switch to given buffer"));
4669 return -1;
4670 }
4671
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004672 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004673 }
4674 else if (strcmp(name, "window") == 0)
4675 {
4676 int count;
4677
4678 if (value->ob_type != &WindowType)
4679 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004680 PyErr_SetString(PyExc_TypeError, _("expected vim.Window object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004681 return -1;
4682 }
4683
4684 if (CheckWindow((WindowObject *)(value)))
4685 return -1;
4686 count = get_win_number(((WindowObject *)(value))->win, firstwin);
4687
4688 if (!count)
4689 {
4690 PyErr_SetString(PyExc_ValueError,
4691 _("failed to find window in the current tab page"));
4692 return -1;
4693 }
4694
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004695 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004696 win_goto(((WindowObject *)(value))->win);
4697 if (((WindowObject *)(value))->win != curwin)
4698 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004699 if (VimTryEnd())
4700 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004701 PyErr_SetString(PyExc_RuntimeError,
4702 _("did not switch to the specified window"));
4703 return -1;
4704 }
4705
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004706 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004707 }
4708 else if (strcmp(name, "tabpage") == 0)
4709 {
4710 if (value->ob_type != &TabPageType)
4711 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004712 PyErr_SetString(PyExc_TypeError, _("expected vim.TabPage object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004713 return -1;
4714 }
4715
4716 if (CheckTabPage((TabPageObject *)(value)))
4717 return -1;
4718
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004719 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004720 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
4721 if (((TabPageObject *)(value))->tab != curtab)
4722 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004723 if (VimTryEnd())
4724 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004725 PyErr_SetString(PyExc_RuntimeError,
4726 _("did not switch to the specified tab page"));
4727 return -1;
4728 }
4729
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004730 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004731 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004732 else
4733 {
4734 PyErr_SetString(PyExc_AttributeError, name);
4735 return -1;
4736 }
4737}
4738
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004739static struct PyMethodDef CurrentMethods[] = {
4740 /* name, function, calling, documentation */
4741 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4742 { NULL, NULL, 0, NULL}
4743};
4744
Bram Moolenaardb913952012-06-29 12:54:53 +02004745 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004746init_range_cmd(exarg_T *eap)
4747{
4748 RangeStart = eap->line1;
4749 RangeEnd = eap->line2;
4750}
4751
4752 static void
4753init_range_eval(typval_T *rettv UNUSED)
4754{
4755 RangeStart = (PyInt) curwin->w_cursor.lnum;
4756 RangeEnd = RangeStart;
4757}
4758
4759 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004760run_cmd(const char *cmd, void *arg UNUSED
4761#ifdef PY_CAN_RECURSE
4762 , PyGILState_STATE *pygilstate UNUSED
4763#endif
4764 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004765{
4766 PyRun_SimpleString((char *) cmd);
4767}
4768
4769static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4770static int code_hdr_len = 30;
4771
4772 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004773run_do(const char *cmd, void *arg UNUSED
4774#ifdef PY_CAN_RECURSE
4775 , PyGILState_STATE *pygilstate
4776#endif
4777 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004778{
4779 PyInt lnum;
4780 size_t len;
4781 char *code;
4782 int status;
4783 PyObject *pyfunc, *pymain;
4784
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004785 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004786 {
4787 EMSG(_("cannot save undo information"));
4788 return;
4789 }
4790
4791 len = code_hdr_len + STRLEN(cmd);
4792 code = PyMem_New(char, len + 1);
4793 memcpy(code, code_hdr, code_hdr_len);
4794 STRCPY(code + code_hdr_len, cmd);
4795 status = PyRun_SimpleString(code);
4796 PyMem_Free(code);
4797
4798 if (status)
4799 {
4800 EMSG(_("failed to run the code"));
4801 return;
4802 }
4803
4804 status = 0;
4805 pymain = PyImport_AddModule("__main__");
4806 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004807#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004808 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004809#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004810
4811 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4812 {
4813 PyObject *line, *linenr, *ret;
4814
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004815#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004816 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004817#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004818 if (!(line = GetBufferLine(curbuf, lnum)))
4819 goto err;
4820 if (!(linenr = PyInt_FromLong((long) lnum)))
4821 {
4822 Py_DECREF(line);
4823 goto err;
4824 }
4825 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4826 Py_DECREF(line);
4827 Py_DECREF(linenr);
4828 if (!ret)
4829 goto err;
4830
4831 if (ret != Py_None)
4832 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
4833 goto err;
4834
4835 Py_XDECREF(ret);
4836 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004837#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004838 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004839#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004840 }
4841 goto out;
4842err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004843#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004844 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004845#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004846 PyErr_PrintEx(0);
4847 PythonIO_Flush();
4848 status = 1;
4849out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004850#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004851 if (!status)
4852 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004853#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004854 Py_DECREF(pyfunc);
4855 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
4856 if (status)
4857 return;
4858 check_cursor();
4859 update_curbuf(NOT_VALID);
4860}
4861
4862 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004863run_eval(const char *cmd, typval_T *rettv
4864#ifdef PY_CAN_RECURSE
4865 , PyGILState_STATE *pygilstate UNUSED
4866#endif
4867 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004868{
4869 PyObject *r;
4870
4871 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
4872 if (r == NULL)
4873 {
4874 if (PyErr_Occurred() && !msg_silent)
4875 PyErr_PrintEx(0);
4876 EMSG(_("E858: Eval did not return a valid python object"));
4877 }
4878 else
4879 {
4880 if (ConvertFromPyObject(r, rettv) == -1)
4881 EMSG(_("E859: Failed to convert returned python object to vim value"));
4882 Py_DECREF(r);
4883 }
4884 PyErr_Clear();
4885}
4886
4887 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02004888set_ref_in_py(const int copyID)
4889{
4890 pylinkedlist_T *cur;
4891 dict_T *dd;
4892 list_T *ll;
4893
4894 if (lastdict != NULL)
4895 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
4896 {
4897 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
4898 if (dd->dv_copyID != copyID)
4899 {
4900 dd->dv_copyID = copyID;
4901 set_ref_in_ht(&dd->dv_hashtab, copyID);
4902 }
4903 }
4904
4905 if (lastlist != NULL)
4906 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
4907 {
4908 ll = ((ListObject *) (cur->pll_obj))->list;
4909 if (ll->lv_copyID != copyID)
4910 {
4911 ll->lv_copyID = copyID;
4912 set_ref_in_list(ll, copyID);
4913 }
4914 }
4915}
4916
4917 static int
4918set_string_copy(char_u *str, typval_T *tv)
4919{
4920 tv->vval.v_string = vim_strsave(str);
4921 if (tv->vval.v_string == NULL)
4922 {
4923 PyErr_NoMemory();
4924 return -1;
4925 }
4926 return 0;
4927}
4928
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004929 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004930pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004931{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004932 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004933 char_u *key;
4934 dictitem_T *di;
4935 PyObject *keyObject;
4936 PyObject *valObject;
4937 Py_ssize_t iter = 0;
4938
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004939 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004940 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004941
4942 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004943 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004944
4945 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4946 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004947 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004948
Bram Moolenaara03e6312013-05-29 22:49:26 +02004949 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004950 {
4951 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004952 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004953 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004954
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004955 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004956 {
4957 dict_unref(dict);
4958 return -1;
4959 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004960
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004961 if (*key == NUL)
4962 {
4963 dict_unref(dict);
4964 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004965 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004966 return -1;
4967 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004968
4969 di = dictitem_alloc(key);
4970
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004971 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004972
4973 if (di == NULL)
4974 {
4975 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004976 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004977 return -1;
4978 }
4979 di->di_tv.v_lock = 0;
4980
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004981 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004982 {
4983 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004984 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004985 return -1;
4986 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004987
4988 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004989 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02004990 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004991 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004992 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004993 PyErr_SetVim(_("failed to add key to dictionary"));
4994 return -1;
4995 }
4996 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004997
4998 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004999 return 0;
5000}
5001
5002 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005003pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005004{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005005 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005006 char_u *key;
5007 dictitem_T *di;
5008 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005009 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005010 PyObject *keyObject;
5011 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005012
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005013 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005014 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005015
5016 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005017 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005018
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005019 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005020 {
5021 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005022 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005023 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005024
5025 if (!(iterator = PyObject_GetIter(list)))
5026 {
5027 dict_unref(dict);
5028 Py_DECREF(list);
5029 return -1;
5030 }
5031 Py_DECREF(list);
5032
5033 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005034 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005035 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005036
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005037 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005038 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005039 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005040 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005041 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005042 return -1;
5043 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005044
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005045 if (*key == NUL)
5046 {
5047 Py_DECREF(keyObject);
5048 Py_DECREF(iterator);
5049 Py_XDECREF(todecref);
5050 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005051 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005052 return -1;
5053 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005054
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005055 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005056 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005057 Py_DECREF(keyObject);
5058 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005059 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005060 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005061 return -1;
5062 }
5063
5064 di = dictitem_alloc(key);
5065
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005066 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005067 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005068
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005069 if (di == NULL)
5070 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005071 Py_DECREF(iterator);
5072 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005073 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005074 PyErr_NoMemory();
5075 return -1;
5076 }
5077 di->di_tv.v_lock = 0;
5078
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005079 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005080 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005081 Py_DECREF(iterator);
5082 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005083 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005084 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005085 return -1;
5086 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02005087
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005088 Py_DECREF(valObject);
5089
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005090 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005091 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005092 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005093 dictitem_free(di);
5094 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005095 PyErr_SetVim(_("failed to add key to dictionary"));
5096 return -1;
5097 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005098 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005099 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005100 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005101 return 0;
5102}
5103
5104 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005105pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005106{
5107 list_T *l;
5108
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005109 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005110 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005111
5112 tv->v_type = VAR_LIST;
5113 tv->vval.v_list = l;
5114
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005115 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005116 {
5117 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005118 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005119 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005120
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005121 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005122 return 0;
5123}
5124
Bram Moolenaardb913952012-06-29 12:54:53 +02005125typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
5126
5127 static int
5128convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005129 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005130{
5131 PyObject *capsule;
5132 char hexBuf[sizeof(void *) * 2 + 3];
5133
5134 sprintf(hexBuf, "%p", obj);
5135
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005136# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005137 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005138# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005139 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005140# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02005141 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005142 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005143# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02005144 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02005145# else
5146 capsule = PyCObject_FromVoidPtr(tv, NULL);
5147# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02005148 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
5149 {
5150 Py_DECREF(capsule);
5151 tv->v_type = VAR_UNKNOWN;
5152 return -1;
5153 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005154 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02005155 {
5156 tv->v_type = VAR_UNKNOWN;
5157 return -1;
5158 }
5159 /* As we are not using copy_tv which increments reference count we must
5160 * do it ourself. */
5161 switch(tv->v_type)
5162 {
5163 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
5164 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
5165 }
5166 }
5167 else
5168 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005169 typval_T *v;
5170
5171# ifdef PY_USE_CAPSULE
5172 v = PyCapsule_GetPointer(capsule, NULL);
5173# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02005174 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005175# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02005176 copy_tv(v, tv);
5177 }
5178 return 0;
5179}
5180
5181 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02005182ConvertFromPyMapping(PyObject *obj, typval_T *tv)
5183{
5184 PyObject *lookup_dict;
5185 int r;
5186
5187 if (!(lookup_dict = PyDict_New()))
5188 return -1;
5189
5190 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
5191 {
5192 tv->v_type = VAR_DICT;
5193 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5194 ++tv->vval.v_dict->dv_refcount;
5195 r = 0;
5196 }
5197 else if (PyDict_Check(obj))
5198 r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
5199 else if (PyMapping_Check(obj))
5200 r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
5201 else
5202 {
5203 PyErr_SetString(PyExc_TypeError,
5204 _("unable to convert object to vim dictionary"));
5205 r = -1;
5206 }
5207 Py_DECREF(lookup_dict);
5208 return r;
5209}
5210
5211 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02005212ConvertFromPyObject(PyObject *obj, typval_T *tv)
5213{
5214 PyObject *lookup_dict;
5215 int r;
5216
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005217 if (!(lookup_dict = PyDict_New()))
5218 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005219 r = _ConvertFromPyObject(obj, tv, lookup_dict);
5220 Py_DECREF(lookup_dict);
5221 return r;
5222}
5223
5224 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005225_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005226{
Bram Moolenaara9922d62013-05-30 13:01:18 +02005227 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005228 {
5229 tv->v_type = VAR_DICT;
5230 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5231 ++tv->vval.v_dict->dv_refcount;
5232 }
5233 else if (obj->ob_type == &ListType)
5234 {
5235 tv->v_type = VAR_LIST;
5236 tv->vval.v_list = (((ListObject *)(obj))->list);
5237 ++tv->vval.v_list->lv_refcount;
5238 }
5239 else if (obj->ob_type == &FunctionType)
5240 {
5241 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
5242 return -1;
5243
5244 tv->v_type = VAR_FUNC;
5245 func_ref(tv->vval.v_string);
5246 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005247 else if (PyBytes_Check(obj))
5248 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005249 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02005250
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005251 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
5252 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005253 if (result == NULL)
5254 return -1;
5255
5256 if (set_string_copy(result, tv) == -1)
5257 return -1;
5258
5259 tv->v_type = VAR_STRING;
5260 }
5261 else if (PyUnicode_Check(obj))
5262 {
5263 PyObject *bytes;
5264 char_u *result;
5265
Bram Moolenaardb913952012-06-29 12:54:53 +02005266 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
5267 if (bytes == NULL)
5268 return -1;
5269
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005270 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
5271 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005272 if (result == NULL)
5273 return -1;
5274
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005275 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02005276 {
5277 Py_XDECREF(bytes);
5278 return -1;
5279 }
5280 Py_XDECREF(bytes);
5281
5282 tv->v_type = VAR_STRING;
5283 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02005284#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02005285 else if (PyInt_Check(obj))
5286 {
5287 tv->v_type = VAR_NUMBER;
5288 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
5289 }
5290#endif
5291 else if (PyLong_Check(obj))
5292 {
5293 tv->v_type = VAR_NUMBER;
5294 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
5295 }
5296 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005297 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005298#ifdef FEAT_FLOAT
5299 else if (PyFloat_Check(obj))
5300 {
5301 tv->v_type = VAR_FLOAT;
5302 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
5303 }
5304#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005305 else if (PyObject_HasAttrString(obj, "keys"))
5306 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005307 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005308 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005309 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005310 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005311 else
5312 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02005313 PyErr_SetString(PyExc_TypeError,
5314 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02005315 return -1;
5316 }
5317 return 0;
5318}
5319
5320 static PyObject *
5321ConvertToPyObject(typval_T *tv)
5322{
5323 if (tv == NULL)
5324 {
5325 PyErr_SetVim(_("NULL reference passed"));
5326 return NULL;
5327 }
5328 switch (tv->v_type)
5329 {
5330 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005331 return PyBytes_FromString(tv->vval.v_string == NULL
5332 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005333 case VAR_NUMBER:
5334 return PyLong_FromLong((long) tv->vval.v_number);
5335#ifdef FEAT_FLOAT
5336 case VAR_FLOAT:
5337 return PyFloat_FromDouble((double) tv->vval.v_float);
5338#endif
5339 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005340 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02005341 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02005342 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005343 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005344 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005345 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005346 case VAR_UNKNOWN:
5347 Py_INCREF(Py_None);
5348 return Py_None;
5349 default:
5350 PyErr_SetVim(_("internal error: invalid value type"));
5351 return NULL;
5352 }
5353}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005354
5355typedef struct
5356{
5357 PyObject_HEAD
5358} CurrentObject;
5359static PyTypeObject CurrentType;
5360
5361 static void
5362init_structs(void)
5363{
5364 vim_memset(&OutputType, 0, sizeof(OutputType));
5365 OutputType.tp_name = "vim.message";
5366 OutputType.tp_basicsize = sizeof(OutputObject);
5367 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
5368 OutputType.tp_doc = "vim message object";
5369 OutputType.tp_methods = OutputMethods;
5370#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005371 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
5372 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005373 OutputType.tp_alloc = call_PyType_GenericAlloc;
5374 OutputType.tp_new = call_PyType_GenericNew;
5375 OutputType.tp_free = call_PyObject_Free;
5376#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005377 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
5378 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005379#endif
5380
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005381 vim_memset(&IterType, 0, sizeof(IterType));
5382 IterType.tp_name = "vim.iter";
5383 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005384 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005385 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005386 IterType.tp_iter = (getiterfunc)IterIter;
5387 IterType.tp_iternext = (iternextfunc)IterNext;
5388 IterType.tp_dealloc = (destructor)IterDestructor;
5389 IterType.tp_traverse = (traverseproc)IterTraverse;
5390 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005391
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005392 vim_memset(&BufferType, 0, sizeof(BufferType));
5393 BufferType.tp_name = "vim.buffer";
5394 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005395 BufferType.tp_dealloc = (destructor)BufferDestructor;
5396 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005397 BufferType.tp_as_sequence = &BufferAsSeq;
5398 BufferType.tp_as_mapping = &BufferAsMapping;
5399 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5400 BufferType.tp_doc = "vim buffer object";
5401 BufferType.tp_methods = BufferMethods;
5402#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005403 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005404 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005405 BufferType.tp_alloc = call_PyType_GenericAlloc;
5406 BufferType.tp_new = call_PyType_GenericNew;
5407 BufferType.tp_free = call_PyObject_Free;
5408#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005409 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005410 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005411#endif
5412
5413 vim_memset(&WindowType, 0, sizeof(WindowType));
5414 WindowType.tp_name = "vim.window";
5415 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005416 WindowType.tp_dealloc = (destructor)WindowDestructor;
5417 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005418 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005419 WindowType.tp_doc = "vim Window object";
5420 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005421 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5422 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005423#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005424 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5425 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005426 WindowType.tp_alloc = call_PyType_GenericAlloc;
5427 WindowType.tp_new = call_PyType_GenericNew;
5428 WindowType.tp_free = call_PyObject_Free;
5429#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005430 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5431 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005432#endif
5433
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005434 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5435 TabPageType.tp_name = "vim.tabpage";
5436 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005437 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5438 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005439 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5440 TabPageType.tp_doc = "vim tab page object";
5441 TabPageType.tp_methods = TabPageMethods;
5442#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005443 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005444 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5445 TabPageType.tp_new = call_PyType_GenericNew;
5446 TabPageType.tp_free = call_PyObject_Free;
5447#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005448 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005449#endif
5450
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005451 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5452 BufMapType.tp_name = "vim.bufferlist";
5453 BufMapType.tp_basicsize = sizeof(BufMapObject);
5454 BufMapType.tp_as_mapping = &BufMapAsMapping;
5455 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005456 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005457 BufferType.tp_doc = "vim buffer list";
5458
5459 vim_memset(&WinListType, 0, sizeof(WinListType));
5460 WinListType.tp_name = "vim.windowlist";
5461 WinListType.tp_basicsize = sizeof(WinListType);
5462 WinListType.tp_as_sequence = &WinListAsSeq;
5463 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5464 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005465 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005466
5467 vim_memset(&TabListType, 0, sizeof(TabListType));
5468 TabListType.tp_name = "vim.tabpagelist";
5469 TabListType.tp_basicsize = sizeof(TabListType);
5470 TabListType.tp_as_sequence = &TabListAsSeq;
5471 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5472 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005473
5474 vim_memset(&RangeType, 0, sizeof(RangeType));
5475 RangeType.tp_name = "vim.range";
5476 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005477 RangeType.tp_dealloc = (destructor)RangeDestructor;
5478 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005479 RangeType.tp_as_sequence = &RangeAsSeq;
5480 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005481 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005482 RangeType.tp_doc = "vim Range object";
5483 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005484 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5485 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005486#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005487 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005488 RangeType.tp_alloc = call_PyType_GenericAlloc;
5489 RangeType.tp_new = call_PyType_GenericNew;
5490 RangeType.tp_free = call_PyObject_Free;
5491#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005492 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005493#endif
5494
5495 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5496 CurrentType.tp_name = "vim.currentdata";
5497 CurrentType.tp_basicsize = sizeof(CurrentObject);
5498 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5499 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005500 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005501#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005502 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5503 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005504#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005505 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5506 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005507#endif
5508
5509 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5510 DictionaryType.tp_name = "vim.dictionary";
5511 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005512 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005513 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005514 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005515 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005516 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5517 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005518 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5519 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5520 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005521#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005522 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5523 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005524#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005525 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5526 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005527#endif
5528
5529 vim_memset(&ListType, 0, sizeof(ListType));
5530 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005531 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005532 ListType.tp_basicsize = sizeof(ListObject);
5533 ListType.tp_as_sequence = &ListAsSeq;
5534 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005535 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005536 ListType.tp_doc = "list pushing modifications to vim structure";
5537 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005538 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005539 ListType.tp_new = (newfunc)ListConstructor;
5540 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005541#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005542 ListType.tp_getattro = (getattrofunc)ListGetattro;
5543 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005544#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005545 ListType.tp_getattr = (getattrfunc)ListGetattr;
5546 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005547#endif
5548
5549 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005550 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005551 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005552 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5553 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005554 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005555 FunctionType.tp_doc = "object that calls vim function";
5556 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005557 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005558 FunctionType.tp_new = (newfunc)FunctionConstructor;
5559 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005560#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005561 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005562#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005563 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005564#endif
5565
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005566 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5567 OptionsType.tp_name = "vim.options";
5568 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005569 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005570 OptionsType.tp_doc = "object for manipulating options";
5571 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005572 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5573 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5574 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005575
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005576 vim_memset(&LoaderType, 0, sizeof(LoaderType));
5577 LoaderType.tp_name = "vim.Loader";
5578 LoaderType.tp_basicsize = sizeof(LoaderObject);
5579 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
5580 LoaderType.tp_doc = "vim message object";
5581 LoaderType.tp_methods = LoaderMethods;
5582 LoaderType.tp_dealloc = (destructor)LoaderDestructor;
5583
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005584#if PY_MAJOR_VERSION >= 3
5585 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5586 vimmodule.m_name = "vim";
5587 vimmodule.m_doc = "Vim Python interface\n";
5588 vimmodule.m_size = -1;
5589 vimmodule.m_methods = VimMethods;
5590#endif
5591}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005592
5593#define PYTYPE_READY(type) \
5594 if (PyType_Ready(&type)) \
5595 return -1;
5596
5597 static int
5598init_types()
5599{
5600 PYTYPE_READY(IterType);
5601 PYTYPE_READY(BufferType);
5602 PYTYPE_READY(RangeType);
5603 PYTYPE_READY(WindowType);
5604 PYTYPE_READY(TabPageType);
5605 PYTYPE_READY(BufMapType);
5606 PYTYPE_READY(WinListType);
5607 PYTYPE_READY(TabListType);
5608 PYTYPE_READY(CurrentType);
5609 PYTYPE_READY(DictionaryType);
5610 PYTYPE_READY(ListType);
5611 PYTYPE_READY(FunctionType);
5612 PYTYPE_READY(OptionsType);
5613 PYTYPE_READY(OutputType);
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005614 PYTYPE_READY(LoaderType);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005615 return 0;
5616}
5617
5618 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02005619init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005620{
5621 PyObject *path;
5622 PyObject *path_hook;
5623 PyObject *path_hooks;
5624
5625 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
5626 return -1;
5627
5628 if (!(path_hooks = PySys_GetObject("path_hooks")))
5629 {
5630 PyErr_Clear();
5631 path_hooks = PyList_New(1);
5632 PyList_SET_ITEM(path_hooks, 0, path_hook);
5633 if (PySys_SetObject("path_hooks", path_hooks))
5634 {
5635 Py_DECREF(path_hooks);
5636 return -1;
5637 }
5638 Py_DECREF(path_hooks);
5639 }
5640 else if (PyList_Check(path_hooks))
5641 {
5642 if (PyList_Append(path_hooks, path_hook))
5643 {
5644 Py_DECREF(path_hook);
5645 return -1;
5646 }
5647 Py_DECREF(path_hook);
5648 }
5649 else
5650 {
5651 VimTryStart();
5652 EMSG(_("Failed to set path hook: sys.path_hooks is not a list\n"
5653 "You should now do the following:\n"
5654 "- append vim.path_hook to sys.path_hooks\n"
5655 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
5656 VimTryEnd(); /* Discard the error */
5657 Py_DECREF(path_hook);
5658 return 0;
5659 }
5660
5661 if (!(path = PySys_GetObject("path")))
5662 {
5663 PyErr_Clear();
5664 path = PyList_New(1);
5665 Py_INCREF(vim_special_path_object);
5666 PyList_SET_ITEM(path, 0, vim_special_path_object);
5667 if (PySys_SetObject("path", path))
5668 {
5669 Py_DECREF(path);
5670 return -1;
5671 }
5672 Py_DECREF(path);
5673 }
5674 else if (PyList_Check(path))
5675 {
5676 if (PyList_Append(path, vim_special_path_object))
5677 return -1;
5678 }
5679 else
5680 {
5681 VimTryStart();
5682 EMSG(_("Failed to set path: sys.path is not a list\n"
5683 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
5684 VimTryEnd(); /* Discard the error */
5685 }
5686
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005687 return 0;
5688}
5689
5690static BufMapObject TheBufferMap =
5691{
5692 PyObject_HEAD_INIT(&BufMapType)
5693};
5694
5695static WinListObject TheWindowList =
5696{
5697 PyObject_HEAD_INIT(&WinListType)
5698 NULL
5699};
5700
5701static CurrentObject TheCurrent =
5702{
5703 PyObject_HEAD_INIT(&CurrentType)
5704};
5705
5706static TabListObject TheTabPageList =
5707{
5708 PyObject_HEAD_INIT(&TabListType)
5709};
5710
5711static struct numeric_constant {
5712 char *name;
5713 int value;
5714} numeric_constants[] = {
5715 {"VAR_LOCKED", VAR_LOCKED},
5716 {"VAR_FIXED", VAR_FIXED},
5717 {"VAR_SCOPE", VAR_SCOPE},
5718 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5719};
5720
5721static struct object_constant {
5722 char *name;
5723 PyObject *value;
5724} object_constants[] = {
5725 {"buffers", (PyObject *)(void *)&TheBufferMap},
5726 {"windows", (PyObject *)(void *)&TheWindowList},
5727 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5728 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005729
5730 {"Buffer", (PyObject *)&BufferType},
5731 {"Range", (PyObject *)&RangeType},
5732 {"Window", (PyObject *)&WindowType},
5733 {"TabPage", (PyObject *)&TabPageType},
5734 {"Dictionary", (PyObject *)&DictionaryType},
5735 {"List", (PyObject *)&ListType},
5736 {"Function", (PyObject *)&FunctionType},
5737 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005738 {"_Loader", (PyObject *)&LoaderType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005739};
5740
5741typedef int (*object_adder)(PyObject *, const char *, PyObject *);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005742typedef PyObject *(*attr_getter)(PyObject *, const char *);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005743
5744#define ADD_OBJECT(m, name, obj) \
5745 if (add_object(m, name, obj)) \
5746 return -1;
5747
5748#define ADD_CHECKED_OBJECT(m, name, obj) \
5749 { \
5750 PyObject *value = obj; \
5751 if (!value) \
5752 return -1; \
5753 ADD_OBJECT(m, name, value); \
5754 }
5755
5756 static int
Bram Moolenaarf4258302013-06-02 18:20:17 +02005757populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005758{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005759 int i;
5760 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005761 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005762 PyObject *imp;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005763
5764 for (i = 0; i < (int)(sizeof(numeric_constants)
5765 / sizeof(struct numeric_constant));
5766 ++i)
5767 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
5768 PyInt_FromLong(numeric_constants[i].value));
5769
5770 for (i = 0; i < (int)(sizeof(object_constants)
5771 / sizeof(struct object_constant));
5772 ++i)
5773 {
5774 PyObject *value;
5775
5776 value = object_constants[i].value;
5777 Py_INCREF(value);
5778 ADD_OBJECT(m, object_constants[i].name, value);
5779 }
5780
5781 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5782 return -1;
5783 ADD_OBJECT(m, "error", VimError);
5784
Bram Moolenaara9922d62013-05-30 13:01:18 +02005785 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5786 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005787 ADD_CHECKED_OBJECT(m, "options",
5788 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02005789
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005790 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005791 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005792 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005793
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005794 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005795 return -1;
5796 ADD_OBJECT(m, "_getcwd", py_getcwd)
5797
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005798 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005799 return -1;
5800 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005801 if (!(attr = get_attr(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005802 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005803 if (PyObject_SetAttrString(other_module, "chdir", attr))
5804 {
5805 Py_DECREF(attr);
5806 return -1;
5807 }
5808 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005809
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005810 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005811 {
5812 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005813 if (!(attr = get_attr(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005814 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005815 if (PyObject_SetAttrString(other_module, "fchdir", attr))
5816 {
5817 Py_DECREF(attr);
5818 return -1;
5819 }
5820 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005821 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02005822 else
5823 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02005824
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005825 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
5826 return -1;
5827
5828 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
5829
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005830 if (!(imp = PyImport_ImportModule("imp")))
5831 return -1;
5832
5833 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
5834 {
5835 Py_DECREF(imp);
5836 return -1;
5837 }
5838
5839 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
5840 {
5841 Py_DECREF(py_find_module);
5842 Py_DECREF(imp);
5843 return -1;
5844 }
5845
5846 Py_DECREF(imp);
5847
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005848 ADD_OBJECT(m, "_find_module", py_find_module);
5849 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005850
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005851 return 0;
5852}