blob: 287191a4ea9f575b26c7eac7c4f41f93e9f00f56 [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 Moolenaar3d0c52d2013-05-12 19:45:35 +020027#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
28
Bram Moolenaar35eacd72013-05-30 22:06:33 +020029#define RAISE_NO_EMPTY_KEYS PyErr_SetString(PyExc_ValueError, \
30 _("empty keys are not allowed"))
31
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020032#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
33#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020034#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020035
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020036typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020037typedef void (*runner)(const char *, void *
38#ifdef PY_CAN_RECURSE
39 , PyGILState_STATE *
40#endif
41 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020042
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020043static int ConvertFromPyObject(PyObject *, typval_T *);
44static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +020045static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020046static PyObject *WindowNew(win_T *, tabpage_T *);
47static PyObject *BufferNew (buf_T *);
48static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020049
50static PyInt RangeStart;
51static PyInt RangeEnd;
52
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020053static PyObject *globals;
54
Bram Moolenaarf4258302013-06-02 18:20:17 +020055static PyObject *py_chdir;
56static PyObject *py_fchdir;
57static PyObject *py_getcwd;
58
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020059/*
60 * obtain a lock on the Vim data structures
61 */
62 static void
63Python_Lock_Vim(void)
64{
65}
66
67/*
68 * release a lock on the Vim data structures
69 */
70 static void
71Python_Release_Vim(void)
72{
73}
74
Bram Moolenaare9ba5162013-05-29 22:02:22 +020075/*
76 * The "todecref" argument holds a pointer to PyObject * that must be
77 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
78 * was needed to generate returned value is object.
79 *
80 * Use Py_XDECREF to decrement reference count.
81 */
82 static char_u *
83StringToChars(PyObject *object, PyObject **todecref)
84{
85 char_u *p;
86 PyObject *bytes = NULL;
87
88 if (PyBytes_Check(object))
89 {
90
91 if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1)
92 return NULL;
93 if (p == NULL)
94 return NULL;
95
96 *todecref = NULL;
97 }
98 else if (PyUnicode_Check(object))
99 {
100 bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL);
101 if (bytes == NULL)
102 return NULL;
103
104 if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1)
105 return NULL;
106 if (p == NULL)
107 return NULL;
108
109 *todecref = bytes;
110 }
111 else
112 {
113 PyErr_SetString(PyExc_TypeError, _("object must be string"));
114 return NULL;
115 }
116
117 return (char_u *) p;
118}
119
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200120 static int
121add_string(PyObject *list, char *s)
122{
123 PyObject *string;
124
125 if (!(string = PyString_FromString(s)))
126 return -1;
127 if (PyList_Append(list, string))
128 {
129 Py_DECREF(string);
130 return -1;
131 }
132
133 Py_DECREF(string);
134 return 0;
135}
136
137 static PyObject *
138ObjectDir(PyObject *self, char **attributes)
139{
140 PyMethodDef *method;
141 char **attr;
142 PyObject *r;
143
144 if (!(r = PyList_New(0)))
145 return NULL;
146
147 if (self)
148 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
149 if (add_string(r, (char *) method->ml_name))
150 {
151 Py_DECREF(r);
152 return NULL;
153 }
154
155 for (attr = attributes ; *attr ; ++attr)
156 if (add_string(r, *attr))
157 {
158 Py_DECREF(r);
159 return NULL;
160 }
161
162#if PY_MAJOR_VERSION < 3
163 if (add_string(r, "__members__"))
164 {
165 Py_DECREF(r);
166 return NULL;
167 }
168#endif
169
170 return r;
171}
172
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200173/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200174 */
175
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200176/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200177typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200178
179static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200180
181typedef struct
182{
183 PyObject_HEAD
184 long softspace;
185 long error;
186} OutputObject;
187
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200188static char *OutputAttrs[] = {
189 "softspace",
190 NULL
191};
192
193 static PyObject *
194OutputDir(PyObject *self)
195{
196 return ObjectDir(self, OutputAttrs);
197}
198
Bram Moolenaar77045652012-09-21 13:46:06 +0200199 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200200OutputSetattr(OutputObject *self, char *name, PyObject *val)
Bram Moolenaar77045652012-09-21 13:46:06 +0200201{
202 if (val == NULL)
203 {
Bram Moolenaar8661b172013-05-15 15:44:28 +0200204 PyErr_SetString(PyExc_AttributeError,
205 _("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200206 return -1;
207 }
208
209 if (strcmp(name, "softspace") == 0)
210 {
211 if (!PyInt_Check(val))
212 {
213 PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
214 return -1;
215 }
216
Bram Moolenaard6e39182013-05-21 18:30:34 +0200217 self->softspace = PyInt_AsLong(val);
Bram Moolenaar77045652012-09-21 13:46:06 +0200218 return 0;
219 }
220
221 PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
222 return -1;
223}
224
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200225/* Buffer IO, we write one whole line at a time. */
226static garray_T io_ga = {0, 0, 1, 80, NULL};
227static writefn old_fn = NULL;
228
229 static void
230PythonIO_Flush(void)
231{
232 if (old_fn != NULL && io_ga.ga_len > 0)
233 {
234 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
235 old_fn((char_u *)io_ga.ga_data);
236 }
237 io_ga.ga_len = 0;
238}
239
240 static void
241writer(writefn fn, char_u *str, PyInt n)
242{
243 char_u *ptr;
244
245 /* Flush when switching output function. */
246 if (fn != old_fn)
247 PythonIO_Flush();
248 old_fn = fn;
249
250 /* Write each NL separated line. Text after the last NL is kept for
251 * writing later. */
252 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
253 {
254 PyInt len = ptr - str;
255
256 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
257 break;
258
259 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
260 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
261 fn((char_u *)io_ga.ga_data);
262 str = ptr + 1;
263 n -= len + 1;
264 io_ga.ga_len = 0;
265 }
266
267 /* Put the remaining text into io_ga for later printing. */
268 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
269 {
270 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
271 io_ga.ga_len += (int)n;
272 }
273}
274
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200275 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200276OutputWrite(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200277{
Bram Moolenaare8cdcef2012-09-12 20:21:43 +0200278 Py_ssize_t len = 0;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200279 char *str = NULL;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200280 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200281
Bram Moolenaar27564802011-09-07 19:30:21 +0200282 if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200283 return NULL;
284
285 Py_BEGIN_ALLOW_THREADS
286 Python_Lock_Vim();
287 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
288 Python_Release_Vim();
289 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200290 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200291
292 Py_INCREF(Py_None);
293 return Py_None;
294}
295
296 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200297OutputWritelines(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200298{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200299 PyObject *seq;
300 PyObject *iterator;
301 PyObject *item;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200302 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200303
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200304 if (!PyArg_ParseTuple(args, "O", &seq))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200305 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200306
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200307 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200308 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200309
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200310 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200311 {
Bram Moolenaar19e60942011-06-19 00:27:51 +0200312 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200313 PyInt len;
314
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200315 if (!PyArg_Parse(item, "et#", ENC_OPT, &str, &len))
Bram Moolenaardb913952012-06-29 12:54:53 +0200316 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200317 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200318 Py_DECREF(iterator);
319 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200320 return NULL;
321 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200322 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200323
324 Py_BEGIN_ALLOW_THREADS
325 Python_Lock_Vim();
326 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
327 Python_Release_Vim();
328 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200329 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200330 }
331
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200332 Py_DECREF(iterator);
333
334 /* Iterator may have finished due to an exception */
335 if (PyErr_Occurred())
336 return NULL;
337
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200338 Py_INCREF(Py_None);
339 return Py_None;
340}
341
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100342 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200343OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100344{
345 /* do nothing */
346 Py_INCREF(Py_None);
347 return Py_None;
348}
349
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200350/***************/
351
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200352static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200353 /* name, function, calling, doc */
354 {"write", (PyCFunction)OutputWrite, METH_VARARGS, ""},
355 {"writelines", (PyCFunction)OutputWritelines, METH_VARARGS, ""},
356 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200357 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200358 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200359};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200360
361static OutputObject Output =
362{
363 PyObject_HEAD_INIT(&OutputType)
364 0,
365 0
366};
367
368static OutputObject Error =
369{
370 PyObject_HEAD_INIT(&OutputType)
371 0,
372 1
373};
374
375 static int
376PythonIO_Init_io(void)
377{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200378 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
379 return -1;
380 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
381 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200382
383 if (PyErr_Occurred())
384 {
385 EMSG(_("E264: Python: Error initialising I/O objects"));
386 return -1;
387 }
388
389 return 0;
390}
391
392
393static PyObject *VimError;
394
395/* Check to see whether a Vim error has been reported, or a keyboard
396 * interrupt has been detected.
397 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200398
399 static void
400VimTryStart(void)
401{
402 ++trylevel;
403}
404
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200405 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200406VimTryEnd(void)
407{
408 --trylevel;
409 if (got_int)
410 {
411 PyErr_SetNone(PyExc_KeyboardInterrupt);
412 return 1;
413 }
414 else if (!did_throw)
415 return 0;
416 else if (PyErr_Occurred())
417 return 1;
418 else
419 {
420 PyErr_SetVim((char *) current_exception->value);
421 discard_current_exception();
422 return 1;
423 }
424}
425
426 static int
427VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200428{
429 if (got_int)
430 {
431 PyErr_SetNone(PyExc_KeyboardInterrupt);
432 return 1;
433 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200434 return 0;
435}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200436
437/* Vim module - Implementation
438 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200439
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200440 static PyObject *
441VimCommand(PyObject *self UNUSED, PyObject *args)
442{
443 char *cmd;
444 PyObject *result;
445
446 if (!PyArg_ParseTuple(args, "s", &cmd))
447 return NULL;
448
449 PyErr_Clear();
450
451 Py_BEGIN_ALLOW_THREADS
452 Python_Lock_Vim();
453
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200454 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200455 do_cmdline_cmd((char_u *)cmd);
456 update_screen(VALID);
457
458 Python_Release_Vim();
459 Py_END_ALLOW_THREADS
460
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200461 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200462 result = NULL;
463 else
464 result = Py_None;
465
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200466
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200467 Py_XINCREF(result);
468 return result;
469}
470
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200471/*
472 * Function to translate a typval_T into a PyObject; this will recursively
473 * translate lists/dictionaries into their Python equivalents.
474 *
475 * The depth parameter is to avoid infinite recursion, set it to 1 when
476 * you call VimToPython.
477 */
478 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200479VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200480{
481 PyObject *result;
482 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200483 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200484
485 /* Avoid infinite recursion */
486 if (depth > 100)
487 {
488 Py_INCREF(Py_None);
489 result = Py_None;
490 return result;
491 }
492
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200493 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200494 * then and we can use it again. */
495 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
496 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
497 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200498 sprintf(ptrBuf, "%p",
499 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
500 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200501
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200502 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200503 {
504 Py_INCREF(result);
505 return result;
506 }
507 }
508
509 if (our_tv->v_type == VAR_STRING)
510 {
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200511 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200512 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200513 }
514 else if (our_tv->v_type == VAR_NUMBER)
515 {
516 char buf[NUMBUFLEN];
517
518 /* For backwards compatibility numbers are stored as strings. */
519 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200520 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200521 }
522# ifdef FEAT_FLOAT
523 else if (our_tv->v_type == VAR_FLOAT)
524 {
525 char buf[NUMBUFLEN];
526
527 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200528 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200529 }
530# endif
531 else if (our_tv->v_type == VAR_LIST)
532 {
533 list_T *list = our_tv->vval.v_list;
534 listitem_T *curr;
535
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200536 if (list == NULL)
537 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200538
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200539 if (!(result = PyList_New(0)))
540 return NULL;
541
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200542 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200543 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200544 Py_DECREF(result);
545 return NULL;
546 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200547
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200548 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
549 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200550 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200551 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200552 Py_DECREF(result);
553 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200554 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200555 if (PyList_Append(result, newObj))
556 {
557 Py_DECREF(newObj);
558 Py_DECREF(result);
559 return NULL;
560 }
561 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200562 }
563 }
564 else if (our_tv->v_type == VAR_DICT)
565 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200566
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200567 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
568 long_u todo = ht->ht_used;
569 hashitem_T *hi;
570 dictitem_T *di;
571 if (our_tv->vval.v_dict == NULL)
572 return NULL;
573
574 if (!(result = PyDict_New()))
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 (hi = ht->ht_array; todo > 0; ++hi)
584 {
585 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200586 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200587 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200588
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200589 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200590 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200591 {
592 Py_DECREF(result);
593 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200594 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200595 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
596 {
597 Py_DECREF(result);
598 Py_DECREF(newObj);
599 return NULL;
600 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200601 }
602 }
603 }
604 else
605 {
606 Py_INCREF(Py_None);
607 result = Py_None;
608 }
609
610 return result;
611}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200612
613 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200614VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200615{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200616 char *expr;
617 typval_T *our_tv;
618 PyObject *result;
619 PyObject *lookup_dict;
620
621 if (!PyArg_ParseTuple(args, "s", &expr))
622 return NULL;
623
624 Py_BEGIN_ALLOW_THREADS
625 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200626 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200627 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200628 Python_Release_Vim();
629 Py_END_ALLOW_THREADS
630
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200631 if (VimTryEnd())
632 return NULL;
633
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200634 if (our_tv == NULL)
635 {
636 PyErr_SetVim(_("invalid expression"));
637 return NULL;
638 }
639
640 /* Convert the Vim type into a Python type. Create a dictionary that's
641 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200642 if (!(lookup_dict = PyDict_New()))
643 result = NULL;
644 else
645 {
646 result = VimToPython(our_tv, 1, lookup_dict);
647 Py_DECREF(lookup_dict);
648 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200649
650
651 Py_BEGIN_ALLOW_THREADS
652 Python_Lock_Vim();
653 free_tv(our_tv);
654 Python_Release_Vim();
655 Py_END_ALLOW_THREADS
656
657 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200658}
659
Bram Moolenaardb913952012-06-29 12:54:53 +0200660static PyObject *ConvertToPyObject(typval_T *);
661
662 static PyObject *
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200663VimEvalPy(PyObject *self UNUSED, PyObject *args)
Bram Moolenaardb913952012-06-29 12:54:53 +0200664{
Bram Moolenaardb913952012-06-29 12:54:53 +0200665 char *expr;
666 typval_T *our_tv;
667 PyObject *result;
668
669 if (!PyArg_ParseTuple(args, "s", &expr))
670 return NULL;
671
672 Py_BEGIN_ALLOW_THREADS
673 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200674 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +0200675 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200676 Python_Release_Vim();
677 Py_END_ALLOW_THREADS
678
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200679 if (VimTryEnd())
680 return NULL;
681
Bram Moolenaardb913952012-06-29 12:54:53 +0200682 if (our_tv == NULL)
683 {
684 PyErr_SetVim(_("invalid expression"));
685 return NULL;
686 }
687
688 result = ConvertToPyObject(our_tv);
689 Py_BEGIN_ALLOW_THREADS
690 Python_Lock_Vim();
691 free_tv(our_tv);
692 Python_Release_Vim();
693 Py_END_ALLOW_THREADS
694
695 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200696}
697
698 static PyObject *
699VimStrwidth(PyObject *self UNUSED, PyObject *args)
700{
701 char *expr;
702
703 if (!PyArg_ParseTuple(args, "s", &expr))
704 return NULL;
705
Bram Moolenaara54bf402012-12-05 16:30:07 +0100706 return PyLong_FromLong(
707#ifdef FEAT_MBYTE
708 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
709#else
710 STRLEN(expr)
711#endif
712 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200713}
714
Bram Moolenaarf4258302013-06-02 18:20:17 +0200715 static PyObject *
716_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
717{
718 PyObject *r;
719 PyObject *newwd;
720 PyObject *todecref;
721 char_u *new_dir;
722
Bram Moolenaard4209d22013-06-05 20:34:15 +0200723 if (_chdir == NULL)
724 return NULL;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200725 if (!(r = PyObject_Call(_chdir, args, kwargs)))
726 return NULL;
727
728 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
729 {
730 Py_DECREF(r);
731 return NULL;
732 }
733
734 if (!(new_dir = StringToChars(newwd, &todecref)))
735 {
736 Py_DECREF(r);
737 Py_DECREF(newwd);
738 return NULL;
739 }
740
741 VimTryStart();
742
743 if (vim_chdir(new_dir))
744 {
745 Py_DECREF(r);
746 Py_DECREF(newwd);
747 Py_XDECREF(todecref);
748
749 if (VimTryEnd())
750 return NULL;
751
752 PyErr_SetVim(_("failed to change directory"));
753 return NULL;
754 }
755
756 Py_DECREF(newwd);
757 Py_XDECREF(todecref);
758
759 post_chdir(FALSE);
760
761 if (VimTryEnd())
762 {
763 Py_DECREF(r);
764 return NULL;
765 }
766
767 return r;
768}
769
770 static PyObject *
771VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
772{
773 return _VimChdir(py_chdir, args, kwargs);
774}
775
776 static PyObject *
777VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
778{
779 return _VimChdir(py_fchdir, args, kwargs);
780}
781
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200782/*
783 * Vim module - Definitions
784 */
785
786static struct PyMethodDef VimMethods[] = {
Bram Moolenaarf4258302013-06-02 18:20:17 +0200787 /* name, function, calling, documentation */
788 {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" },
789 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
790 {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"},
791 {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"},
792 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
793 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
794 { NULL, NULL, 0, NULL }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200795};
796
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200797/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200798 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200799 */
800
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200801static PyTypeObject IterType;
802
803typedef PyObject *(*nextfun)(void **);
804typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200805typedef int (*traversefun)(void *, visitproc, void *);
806typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200807
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200808/* Main purpose of this object is removing the need for do python
809 * initialization (i.e. PyType_Ready and setting type attributes) for a big
810 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200811
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200812typedef struct
813{
814 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200815 void *cur;
816 nextfun next;
817 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200818 traversefun traverse;
819 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200820} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200821
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200822 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200823IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
824 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200825{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200826 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200827
Bram Moolenaar774267b2013-05-21 20:51:59 +0200828 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200829 self->cur = start;
830 self->next = next;
831 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200832 self->traverse = traverse;
833 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200834
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200835 return (PyObject *)(self);
836}
837
838 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200839IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200840{
Bram Moolenaar774267b2013-05-21 20:51:59 +0200841 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +0200842 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +0200843 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200844}
845
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200846 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200847IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200848{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200849 if (self->traverse != NULL)
850 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200851 else
852 return 0;
853}
854
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200855/* Mac OSX defines clear() somewhere. */
856#ifdef clear
857# undef clear
858#endif
859
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200860 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200861IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200862{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200863 if (self->clear != NULL)
864 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200865 else
866 return 0;
867}
868
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200869 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200870IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200871{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200872 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200873}
874
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200875 static PyObject *
876IterIter(PyObject *self)
877{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +0200878 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200879 return self;
880}
Bram Moolenaardfa38d42013-05-15 13:38:47 +0200881
Bram Moolenaardb913952012-06-29 12:54:53 +0200882typedef struct pylinkedlist_S {
883 struct pylinkedlist_S *pll_next;
884 struct pylinkedlist_S *pll_prev;
885 PyObject *pll_obj;
886} pylinkedlist_T;
887
888static pylinkedlist_T *lastdict = NULL;
889static pylinkedlist_T *lastlist = NULL;
890
891 static void
892pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
893{
894 if (ref->pll_prev == NULL)
895 {
896 if (ref->pll_next == NULL)
897 {
898 *last = NULL;
899 return;
900 }
901 }
902 else
903 ref->pll_prev->pll_next = ref->pll_next;
904
905 if (ref->pll_next == NULL)
906 *last = ref->pll_prev;
907 else
908 ref->pll_next->pll_prev = ref->pll_prev;
909}
910
911 static void
912pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
913{
914 if (*last == NULL)
915 ref->pll_prev = NULL;
916 else
917 {
918 (*last)->pll_next = ref;
919 ref->pll_prev = *last;
920 }
921 ref->pll_next = NULL;
922 ref->pll_obj = self;
923 *last = ref;
924}
925
926static PyTypeObject DictionaryType;
927
928typedef struct
929{
930 PyObject_HEAD
931 dict_T *dict;
932 pylinkedlist_T ref;
933} DictionaryObject;
934
Bram Moolenaara9922d62013-05-30 13:01:18 +0200935static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
936
937#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
938
Bram Moolenaardb913952012-06-29 12:54:53 +0200939 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +0200940DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +0200941{
942 DictionaryObject *self;
943
Bram Moolenaara9922d62013-05-30 13:01:18 +0200944 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +0200945 if (self == NULL)
946 return NULL;
947 self->dict = dict;
948 ++dict->dv_refcount;
949
950 pyll_add((PyObject *)(self), &self->ref, &lastdict);
951
952 return (PyObject *)(self);
953}
954
Bram Moolenaara9922d62013-05-30 13:01:18 +0200955 static dict_T *
956py_dict_alloc()
957{
958 dict_T *r;
959
960 if (!(r = dict_alloc()))
961 {
962 PyErr_NoMemory();
963 return NULL;
964 }
965 ++r->dv_refcount;
966
967 return r;
968}
969
970 static PyObject *
971DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
972{
973 DictionaryObject *self;
974 dict_T *dict;
975
976 if (!(dict = py_dict_alloc()))
977 return NULL;
978
979 self = (DictionaryObject *) DictionaryNew(subtype, dict);
980
981 --dict->dv_refcount;
982
983 if (kwargs || PyTuple_Size(args))
984 {
985 PyObject *tmp;
986 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
987 {
988 Py_DECREF(self);
989 return NULL;
990 }
991
992 Py_DECREF(tmp);
993 }
994
995 return (PyObject *)(self);
996}
997
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200998 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200999DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001000{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001001 pyll_remove(&self->ref, &lastdict);
1002 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001003
1004 DESTRUCTOR_FINISH(self);
1005}
1006
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001007static char *DictionaryAttrs[] = {
1008 "locked", "scope",
1009 NULL
1010};
1011
1012 static PyObject *
1013DictionaryDir(PyObject *self)
1014{
1015 return ObjectDir(self, DictionaryAttrs);
1016}
1017
Bram Moolenaardb913952012-06-29 12:54:53 +02001018 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001019DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001020{
1021 if (val == NULL)
1022 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001023 PyErr_SetString(PyExc_AttributeError,
1024 _("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001025 return -1;
1026 }
1027
1028 if (strcmp(name, "locked") == 0)
1029 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001030 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001031 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001032 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001033 return -1;
1034 }
1035 else
1036 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001037 int istrue = PyObject_IsTrue(val);
1038 if (istrue == -1)
1039 return -1;
1040 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001041 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001042 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001043 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001044 }
1045 return 0;
1046 }
1047 else
1048 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001049 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001050 return -1;
1051 }
1052}
1053
1054 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001055DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001056{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001057 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001058}
1059
Bram Moolenaara9922d62013-05-30 13:01:18 +02001060#define DICT_FLAG_HAS_DEFAULT 0x01
1061#define DICT_FLAG_POP 0x02
1062#define DICT_FLAG_NONE_DEFAULT 0x04
1063#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
1064#define DICT_FLAG_RETURN_PAIR 0x10
1065
Bram Moolenaardb913952012-06-29 12:54:53 +02001066 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001067_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001068{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001069 PyObject *keyObject;
1070 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
1071 PyObject *r;
Bram Moolenaardb913952012-06-29 12:54:53 +02001072 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001073 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001074 dict_T *dict = self->dict;
1075 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001076 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001077
Bram Moolenaara9922d62013-05-30 13:01:18 +02001078 if (flags & DICT_FLAG_HAS_DEFAULT)
1079 {
1080 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1081 return NULL;
1082 }
1083 else
1084 keyObject = args;
1085
1086 if (flags & DICT_FLAG_RETURN_BOOL)
1087 defObject = Py_False;
1088
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001089 if (!(key = StringToChars(keyObject, &todecref)))
1090 return NULL;
1091
1092 if (*key == NUL)
1093 {
1094 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001095 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001096 return NULL;
1097 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001098
Bram Moolenaara9922d62013-05-30 13:01:18 +02001099 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001100
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001101 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001102
Bram Moolenaara9922d62013-05-30 13:01:18 +02001103 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001104 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001105 if (defObject)
1106 {
1107 Py_INCREF(defObject);
1108 return defObject;
1109 }
1110 else
1111 {
1112 PyErr_SetObject(PyExc_KeyError, keyObject);
1113 return NULL;
1114 }
1115 }
1116 else if (flags & DICT_FLAG_RETURN_BOOL)
1117 {
1118 Py_INCREF(Py_True);
1119 return Py_True;
1120 }
1121
1122 di = dict_lookup(hi);
1123
1124 if (!(r = ConvertToPyObject(&di->di_tv)))
1125 return NULL;
1126
1127 if (flags & DICT_FLAG_POP)
1128 {
1129 if (dict->dv_lock)
1130 {
1131 PyErr_SetVim(_("dict is locked"));
1132 Py_DECREF(r);
1133 return NULL;
1134 }
1135
1136 hash_remove(&dict->dv_hashtab, hi);
1137 dictitem_free(di);
1138 }
1139
Bram Moolenaara9922d62013-05-30 13:01:18 +02001140 return r;
1141}
1142
1143 static PyObject *
1144DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1145{
1146 return _DictionaryItem(self, keyObject, 0);
1147}
1148
1149 static int
1150DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1151{
1152 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1153 int r;
1154
1155 r = (rObj == Py_True);
1156
1157 Py_DECREF(Py_True);
1158
1159 return r;
1160}
1161
1162typedef struct
1163{
1164 hashitem_T *ht_array;
1165 long_u ht_used;
1166 hashtab_T *ht;
1167 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001168 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001169} dictiterinfo_T;
1170
1171 static PyObject *
1172DictionaryIterNext(dictiterinfo_T **dii)
1173{
1174 PyObject *r;
1175
1176 if (!(*dii)->todo)
1177 return NULL;
1178
1179 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1180 (*dii)->ht->ht_used != (*dii)->ht_used)
1181 {
1182 PyErr_SetString(PyExc_RuntimeError,
1183 _("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001184 return NULL;
1185 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001186
Bram Moolenaara9922d62013-05-30 13:01:18 +02001187 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1188 ++((*dii)->hi);
1189
1190 --((*dii)->todo);
1191
1192 if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1193 return NULL;
1194
1195 return r;
1196}
1197
1198 static PyObject *
1199DictionaryIter(DictionaryObject *self)
1200{
1201 dictiterinfo_T *dii;
1202 hashtab_T *ht;
1203
1204 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1205 {
1206 PyErr_NoMemory();
1207 return NULL;
1208 }
1209
1210 ht = &self->dict->dv_hashtab;
1211 dii->ht_array = ht->ht_array;
1212 dii->ht_used = ht->ht_used;
1213 dii->ht = ht;
1214 dii->hi = dii->ht_array;
1215 dii->todo = dii->ht_used;
1216
1217 return IterNew(dii,
1218 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1219 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001220}
1221
1222 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001223DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001224{
1225 char_u *key;
1226 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001227 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001228 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001229 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001230
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001231 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001232 {
1233 PyErr_SetVim(_("dict is locked"));
1234 return -1;
1235 }
1236
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001237 if (!(key = StringToChars(keyObject, &todecref)))
1238 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001239
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001240 if (*key == NUL)
1241 {
1242 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001243 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001244 return -1;
1245 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001246
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001247 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001248
1249 if (valObject == NULL)
1250 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001251 hashitem_T *hi;
1252
Bram Moolenaardb913952012-06-29 12:54:53 +02001253 if (di == NULL)
1254 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001255 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001256 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001257 return -1;
1258 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001259 hi = hash_find(&dict->dv_hashtab, di->di_key);
1260 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001261 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001262 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001263 return 0;
1264 }
1265
1266 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001267 {
1268 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001269 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001270 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001271
1272 if (di == NULL)
1273 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001274 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001275 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001276 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001277 PyErr_NoMemory();
1278 return -1;
1279 }
1280 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001281 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001282
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001283 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001284 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001285 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001286 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001287 dictitem_free(di);
Bram Moolenaardb913952012-06-29 12:54:53 +02001288 PyErr_SetVim(_("failed to add key to dictionary"));
1289 return -1;
1290 }
1291 }
1292 else
1293 clear_tv(&di->di_tv);
1294
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001295 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001296
1297 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001298 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001299 return 0;
1300}
1301
Bram Moolenaara9922d62013-05-30 13:01:18 +02001302typedef PyObject *(*hi_to_py)(hashitem_T *);
1303
Bram Moolenaardb913952012-06-29 12:54:53 +02001304 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001305DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001306{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001307 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001308 long_u todo = dict->dv_hashtab.ht_used;
1309 Py_ssize_t i = 0;
1310 PyObject *r;
1311 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001312 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001313
1314 r = PyList_New(todo);
1315 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1316 {
1317 if (!HASHITEM_EMPTY(hi))
1318 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001319 if (!(newObj = hiconvert(hi)))
1320 {
1321 Py_DECREF(r);
1322 return NULL;
1323 }
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02001324 PyList_SET_ITEM(r, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001325 --todo;
1326 ++i;
1327 }
1328 }
1329 return r;
1330}
1331
Bram Moolenaara9922d62013-05-30 13:01:18 +02001332 static PyObject *
1333dict_key(hashitem_T *hi)
1334{
1335 return PyBytes_FromString((char *)(hi->hi_key));
1336}
1337
1338 static PyObject *
1339DictionaryListKeys(DictionaryObject *self)
1340{
1341 return DictionaryListObjects(self, dict_key);
1342}
1343
1344 static PyObject *
1345dict_val(hashitem_T *hi)
1346{
1347 dictitem_T *di;
1348
1349 di = dict_lookup(hi);
1350 return ConvertToPyObject(&di->di_tv);
1351}
1352
1353 static PyObject *
1354DictionaryListValues(DictionaryObject *self)
1355{
1356 return DictionaryListObjects(self, dict_val);
1357}
1358
1359 static PyObject *
1360dict_item(hashitem_T *hi)
1361{
1362 PyObject *keyObject;
1363 PyObject *valObject;
1364 PyObject *r;
1365
1366 if (!(keyObject = dict_key(hi)))
1367 return NULL;
1368
1369 if (!(valObject = dict_val(hi)))
1370 {
1371 Py_DECREF(keyObject);
1372 return NULL;
1373 }
1374
1375 r = Py_BuildValue("(OO)", keyObject, valObject);
1376
1377 Py_DECREF(keyObject);
1378 Py_DECREF(valObject);
1379
1380 return r;
1381}
1382
1383 static PyObject *
1384DictionaryListItems(DictionaryObject *self)
1385{
1386 return DictionaryListObjects(self, dict_item);
1387}
1388
1389 static PyObject *
1390DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1391{
1392 dict_T *dict = self->dict;
1393
1394 if (dict->dv_lock)
1395 {
1396 PyErr_SetVim(_("dict is locked"));
1397 return NULL;
1398 }
1399
1400 if (kwargs)
1401 {
1402 typval_T tv;
1403
1404 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1405 return NULL;
1406
1407 VimTryStart();
1408 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1409 clear_tv(&tv);
1410 if (VimTryEnd())
1411 return NULL;
1412 }
1413 else
1414 {
1415 PyObject *object;
1416
1417 if (!PyArg_Parse(args, "(O)", &object))
1418 return NULL;
1419
1420 if (PyObject_HasAttrString(object, "keys"))
1421 return DictionaryUpdate(self, NULL, object);
1422 else
1423 {
1424 PyObject *iterator;
1425 PyObject *item;
1426
1427 if (!(iterator = PyObject_GetIter(object)))
1428 return NULL;
1429
1430 while ((item = PyIter_Next(iterator)))
1431 {
1432 PyObject *fast;
1433 PyObject *keyObject;
1434 PyObject *valObject;
1435 PyObject *todecref;
1436 char_u *key;
1437 dictitem_T *di;
1438
1439 if (!(fast = PySequence_Fast(item, "")))
1440 {
1441 Py_DECREF(iterator);
1442 Py_DECREF(item);
1443 return NULL;
1444 }
1445
1446 Py_DECREF(item);
1447
1448 if (PySequence_Fast_GET_SIZE(fast) != 2)
1449 {
1450 Py_DECREF(iterator);
1451 Py_DECREF(fast);
1452 PyErr_SetString(PyExc_ValueError,
1453 _("expected sequence element of size 2"));
1454 return NULL;
1455 }
1456
1457 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1458
1459 if (!(key = StringToChars(keyObject, &todecref)))
1460 {
1461 Py_DECREF(iterator);
1462 Py_DECREF(fast);
1463 return NULL;
1464 }
1465
1466 di = dictitem_alloc(key);
1467
1468 Py_XDECREF(todecref);
1469
1470 if (di == NULL)
1471 {
1472 Py_DECREF(fast);
1473 Py_DECREF(iterator);
1474 PyErr_NoMemory();
1475 return NULL;
1476 }
1477 di->di_tv.v_lock = 0;
1478 di->di_tv.v_type = VAR_UNKNOWN;
1479
1480 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1481
1482 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1483 {
1484 Py_DECREF(iterator);
1485 Py_DECREF(fast);
1486 dictitem_free(di);
1487 return NULL;
1488 }
1489
1490 Py_DECREF(fast);
1491
1492 if (dict_add(dict, di) == FAIL)
1493 {
1494 Py_DECREF(iterator);
1495 dictitem_free(di);
1496 PyErr_SetVim(_("failed to add key to dictionary"));
1497 return NULL;
1498 }
1499 }
1500
1501 Py_DECREF(iterator);
1502
1503 /* Iterator may have finished due to an exception */
1504 if (PyErr_Occurred())
1505 return NULL;
1506 }
1507 }
1508 Py_INCREF(Py_None);
1509 return Py_None;
1510}
1511
1512 static PyObject *
1513DictionaryGet(DictionaryObject *self, PyObject *args)
1514{
1515 return _DictionaryItem(self, args,
1516 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1517}
1518
1519 static PyObject *
1520DictionaryPop(DictionaryObject *self, PyObject *args)
1521{
1522 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1523}
1524
1525 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001526DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001527{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001528 hashitem_T *hi;
1529 PyObject *r;
1530 PyObject *valObject;
1531 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001532
Bram Moolenaarde71b562013-06-02 17:41:54 +02001533 if (self->dict->dv_hashtab.ht_used == 0)
1534 {
1535 PyErr_SetNone(PyExc_KeyError);
1536 return NULL;
1537 }
1538
1539 hi = self->dict->dv_hashtab.ht_array;
1540 while (HASHITEM_EMPTY(hi))
1541 ++hi;
1542
1543 di = dict_lookup(hi);
1544
1545 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001546 return NULL;
1547
Bram Moolenaarde71b562013-06-02 17:41:54 +02001548 if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
1549 {
1550 Py_DECREF(valObject);
1551 return NULL;
1552 }
1553
1554 hash_remove(&self->dict->dv_hashtab, hi);
1555 dictitem_free(di);
1556
1557 return r;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001558}
1559
1560 static PyObject *
1561DictionaryHasKey(DictionaryObject *self, PyObject *args)
1562{
1563 PyObject *keyObject;
1564
1565 if (!PyArg_ParseTuple(args, "O", &keyObject))
1566 return NULL;
1567
1568 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1569}
1570
1571static PySequenceMethods DictionaryAsSeq = {
1572 0, /* sq_length */
1573 0, /* sq_concat */
1574 0, /* sq_repeat */
1575 0, /* sq_item */
1576 0, /* sq_slice */
1577 0, /* sq_ass_item */
1578 0, /* sq_ass_slice */
1579 (objobjproc) DictionaryContains, /* sq_contains */
1580 0, /* sq_inplace_concat */
1581 0, /* sq_inplace_repeat */
1582};
1583
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001584static PyMappingMethods DictionaryAsMapping = {
1585 (lenfunc) DictionaryLength,
1586 (binaryfunc) DictionaryItem,
1587 (objobjargproc) DictionaryAssItem,
1588};
1589
Bram Moolenaardb913952012-06-29 12:54:53 +02001590static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001591 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001592 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
1593 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
1594 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
1595 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
1596 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02001597 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001598 {"has_key", (PyCFunction)DictionaryHasKey, METH_VARARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001599 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1600 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001601};
1602
1603static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001604static PySequenceMethods ListAsSeq;
1605static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001606
1607typedef struct
1608{
1609 PyObject_HEAD
1610 list_T *list;
1611 pylinkedlist_T ref;
1612} ListObject;
1613
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001614#define NEW_LIST(list) ListNew(&ListType, list)
1615
Bram Moolenaardb913952012-06-29 12:54:53 +02001616 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001617ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02001618{
1619 ListObject *self;
1620
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001621 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001622 if (self == NULL)
1623 return NULL;
1624 self->list = list;
1625 ++list->lv_refcount;
1626
1627 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1628
1629 return (PyObject *)(self);
1630}
1631
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001632 static list_T *
1633py_list_alloc()
1634{
1635 list_T *r;
1636
1637 if (!(r = list_alloc()))
1638 {
1639 PyErr_NoMemory();
1640 return NULL;
1641 }
1642 ++r->lv_refcount;
1643
1644 return r;
1645}
1646
1647 static int
1648list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
1649{
1650 PyObject *iterator;
1651 PyObject *item;
1652 listitem_T *li;
1653
1654 if (!(iterator = PyObject_GetIter(obj)))
1655 return -1;
1656
1657 while ((item = PyIter_Next(iterator)))
1658 {
1659 if (!(li = listitem_alloc()))
1660 {
1661 PyErr_NoMemory();
1662 Py_DECREF(item);
1663 Py_DECREF(iterator);
1664 return -1;
1665 }
1666 li->li_tv.v_lock = 0;
1667 li->li_tv.v_type = VAR_UNKNOWN;
1668
1669 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
1670 {
1671 Py_DECREF(item);
1672 Py_DECREF(iterator);
1673 listitem_free(li);
1674 return -1;
1675 }
1676
1677 Py_DECREF(item);
1678
1679 list_append(l, li);
1680 }
1681
1682 Py_DECREF(iterator);
1683
1684 /* Iterator may have finished due to an exception */
1685 if (PyErr_Occurred())
1686 return -1;
1687
1688 return 0;
1689}
1690
1691 static PyObject *
1692ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1693{
1694 list_T *list;
1695 PyObject *obj = NULL;
1696
1697 if (kwargs)
1698 {
1699 PyErr_SetString(PyExc_TypeError,
1700 _("list constructor does not accept keyword arguments"));
1701 return NULL;
1702 }
1703
1704 if (!PyArg_ParseTuple(args, "|O", &obj))
1705 return NULL;
1706
1707 if (!(list = py_list_alloc()))
1708 return NULL;
1709
1710 if (obj)
1711 {
1712 PyObject *lookup_dict;
1713
1714 if (!(lookup_dict = PyDict_New()))
1715 {
1716 list_unref(list);
1717 return NULL;
1718 }
1719
1720 if (list_py_concat(list, obj, lookup_dict) == -1)
1721 {
1722 Py_DECREF(lookup_dict);
1723 list_unref(list);
1724 return NULL;
1725 }
1726
1727 Py_DECREF(lookup_dict);
1728 }
1729
1730 return ListNew(subtype, list);
1731}
1732
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001733 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001734ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001735{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001736 pyll_remove(&self->ref, &lastlist);
1737 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001738
1739 DESTRUCTOR_FINISH(self);
1740}
1741
Bram Moolenaardb913952012-06-29 12:54:53 +02001742 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001743ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001744{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001745 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02001746}
1747
1748 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001749ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02001750{
1751 listitem_T *li;
1752
Bram Moolenaard6e39182013-05-21 18:30:34 +02001753 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02001754 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001755 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001756 return NULL;
1757 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02001758 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02001759 if (li == NULL)
1760 {
1761 PyErr_SetVim(_("internal error: failed to get vim list item"));
1762 return NULL;
1763 }
1764 return ConvertToPyObject(&li->li_tv);
1765}
1766
1767#define PROC_RANGE \
1768 if (last < 0) {\
1769 if (last < -size) \
1770 last = 0; \
1771 else \
1772 last += size; \
1773 } \
1774 if (first < 0) \
1775 first = 0; \
1776 if (first > size) \
1777 first = size; \
1778 if (last > size) \
1779 last = size;
1780
1781 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001782ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02001783{
1784 PyInt i;
1785 PyInt size = ListLength(self);
1786 PyInt n;
1787 PyObject *list;
1788 int reversed = 0;
1789
1790 PROC_RANGE
1791 if (first >= last)
1792 first = last;
1793
1794 n = last-first;
1795 list = PyList_New(n);
1796 if (list == NULL)
1797 return NULL;
1798
1799 for (i = 0; i < n; ++i)
1800 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02001801 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02001802 if (item == NULL)
1803 {
1804 Py_DECREF(list);
1805 return NULL;
1806 }
1807
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02001808 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
Bram Moolenaardb913952012-06-29 12:54:53 +02001809 }
1810
1811 return list;
1812}
1813
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001814typedef struct
1815{
1816 listwatch_T lw;
1817 list_T *list;
1818} listiterinfo_T;
1819
1820 static void
1821ListIterDestruct(listiterinfo_T *lii)
1822{
1823 list_rem_watch(lii->list, &lii->lw);
1824 PyMem_Free(lii);
1825}
1826
1827 static PyObject *
1828ListIterNext(listiterinfo_T **lii)
1829{
1830 PyObject *r;
1831
1832 if (!((*lii)->lw.lw_item))
1833 return NULL;
1834
1835 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
1836 return NULL;
1837
1838 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
1839
1840 return r;
1841}
1842
1843 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001844ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001845{
1846 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001847 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001848
1849 if (!(lii = PyMem_New(listiterinfo_T, 1)))
1850 {
1851 PyErr_NoMemory();
1852 return NULL;
1853 }
1854
1855 list_add_watch(l, &lii->lw);
1856 lii->lw.lw_item = l->lv_first;
1857 lii->list = l;
1858
1859 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001860 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
1861 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001862}
1863
Bram Moolenaardb913952012-06-29 12:54:53 +02001864 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001865ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001866{
1867 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001868 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001869 listitem_T *li;
1870 Py_ssize_t length = ListLength(self);
1871
1872 if (l->lv_lock)
1873 {
1874 PyErr_SetVim(_("list is locked"));
1875 return -1;
1876 }
1877 if (index>length || (index==length && obj==NULL))
1878 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001879 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001880 return -1;
1881 }
1882
1883 if (obj == NULL)
1884 {
1885 li = list_find(l, (long) index);
1886 list_remove(l, li, li);
1887 clear_tv(&li->li_tv);
1888 vim_free(li);
1889 return 0;
1890 }
1891
1892 if (ConvertFromPyObject(obj, &tv) == -1)
1893 return -1;
1894
1895 if (index == length)
1896 {
1897 if (list_append_tv(l, &tv) == FAIL)
1898 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001899 clear_tv(&tv);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001900 PyErr_SetVim(_("failed to add item to list"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001901 return -1;
1902 }
1903 }
1904 else
1905 {
1906 li = list_find(l, (long) index);
1907 clear_tv(&li->li_tv);
1908 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001909 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001910 }
1911 return 0;
1912}
1913
1914 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001915ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001916{
1917 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001918 PyObject *iterator;
1919 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02001920 listitem_T *li;
1921 listitem_T *next;
1922 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001923 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001924 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02001925
1926 if (l->lv_lock)
1927 {
1928 PyErr_SetVim(_("list is locked"));
1929 return -1;
1930 }
1931
1932 PROC_RANGE
1933
1934 if (first == size)
1935 li = NULL;
1936 else
1937 {
1938 li = list_find(l, (long) first);
1939 if (li == NULL)
1940 {
1941 PyErr_SetVim(_("internal error: no vim list item"));
1942 return -1;
1943 }
1944 if (last > first)
1945 {
1946 i = last - first;
1947 while (i-- && li != NULL)
1948 {
1949 next = li->li_next;
1950 listitem_remove(l, li);
1951 li = next;
1952 }
1953 }
1954 }
1955
1956 if (obj == NULL)
1957 return 0;
1958
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001959 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001960 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02001961
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001962 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001963 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001964 if (ConvertFromPyObject(item, &v) == -1)
1965 {
1966 Py_DECREF(iterator);
1967 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02001968 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001969 }
1970 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02001971 if (list_insert_tv(l, &v, li) == FAIL)
1972 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001973 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001974 PyErr_SetVim(_("internal error: failed to add item to list"));
1975 return -1;
1976 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001977 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001978 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001979 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02001980 return 0;
1981}
1982
1983 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001984ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001985{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001986 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001987 PyObject *lookup_dict;
1988
1989 if (l->lv_lock)
1990 {
1991 PyErr_SetVim(_("list is locked"));
1992 return NULL;
1993 }
1994
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001995 if (!(lookup_dict = PyDict_New()))
1996 return NULL;
1997
Bram Moolenaardb913952012-06-29 12:54:53 +02001998 if (list_py_concat(l, obj, lookup_dict) == -1)
1999 {
2000 Py_DECREF(lookup_dict);
2001 return NULL;
2002 }
2003 Py_DECREF(lookup_dict);
2004
2005 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02002006 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002007}
2008
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002009static char *ListAttrs[] = {
2010 "locked",
2011 NULL
2012};
2013
2014 static PyObject *
2015ListDir(PyObject *self)
2016{
2017 return ObjectDir(self, ListAttrs);
2018}
2019
Bram Moolenaar66b79852012-09-21 14:00:35 +02002020 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002021ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002022{
2023 if (val == NULL)
2024 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002025 PyErr_SetString(PyExc_AttributeError,
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002026 _("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002027 return -1;
2028 }
2029
2030 if (strcmp(name, "locked") == 0)
2031 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002032 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002033 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002034 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002035 return -1;
2036 }
2037 else
2038 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002039 int istrue = PyObject_IsTrue(val);
2040 if (istrue == -1)
2041 return -1;
2042 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002043 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002044 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002045 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002046 }
2047 return 0;
2048 }
2049 else
2050 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002051 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002052 return -1;
2053 }
2054}
2055
Bram Moolenaardb913952012-06-29 12:54:53 +02002056static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002057 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2058 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2059 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002060};
2061
2062typedef struct
2063{
2064 PyObject_HEAD
2065 char_u *name;
2066} FunctionObject;
2067
2068static PyTypeObject FunctionType;
2069
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002070#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
2071
Bram Moolenaardb913952012-06-29 12:54:53 +02002072 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002073FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002074{
2075 FunctionObject *self;
2076
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002077 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2078
Bram Moolenaardb913952012-06-29 12:54:53 +02002079 if (self == NULL)
2080 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002081
2082 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002083 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002084 if (!translated_function_exists(name))
2085 {
2086 PyErr_SetString(PyExc_ValueError,
2087 _("unnamed function does not exist"));
2088 return NULL;
2089 }
2090 self->name = vim_strsave(name);
2091 func_ref(self->name);
2092 }
2093 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002094 if ((self->name = get_expanded_name(name,
2095 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2096 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002097 {
Bram Moolenaar018acca2013-05-30 13:37:28 +02002098 PyErr_SetString(PyExc_ValueError, _("function does not exist"));
2099 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002100 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002101
2102 return (PyObject *)(self);
2103}
2104
2105 static PyObject *
2106FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2107{
2108 PyObject *self;
2109 char_u *name;
2110
2111 if (kwargs)
2112 {
2113 PyErr_SetString(PyExc_TypeError,
2114 _("function constructor does not accept keyword arguments"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002115 return NULL;
2116 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002117
2118 if (!PyArg_ParseTuple(args, "s", &name))
2119 return NULL;
2120
2121 self = FunctionNew(subtype, name);
2122
2123 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002124}
2125
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002126 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002127FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002128{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002129 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002130 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002131
2132 DESTRUCTOR_FINISH(self);
2133}
2134
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002135static char *FunctionAttrs[] = {
2136 "softspace",
2137 NULL
2138};
2139
2140 static PyObject *
2141FunctionDir(PyObject *self)
2142{
2143 return ObjectDir(self, FunctionAttrs);
2144}
2145
Bram Moolenaardb913952012-06-29 12:54:53 +02002146 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002147FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002148{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002149 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002150 typval_T args;
2151 typval_T selfdicttv;
2152 typval_T rettv;
2153 dict_T *selfdict = NULL;
2154 PyObject *selfdictObject;
2155 PyObject *result;
2156 int error;
2157
2158 if (ConvertFromPyObject(argsObject, &args) == -1)
2159 return NULL;
2160
2161 if (kwargs != NULL)
2162 {
2163 selfdictObject = PyDict_GetItemString(kwargs, "self");
2164 if (selfdictObject != NULL)
2165 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002166 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002167 {
2168 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002169 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002170 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002171 selfdict = selfdicttv.vval.v_dict;
2172 }
2173 }
2174
Bram Moolenaar71700b82013-05-15 17:49:05 +02002175 Py_BEGIN_ALLOW_THREADS
2176 Python_Lock_Vim();
2177
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002178 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002179 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002180
2181 Python_Release_Vim();
2182 Py_END_ALLOW_THREADS
2183
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002184 if (VimTryEnd())
2185 result = NULL;
2186 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002187 {
2188 result = NULL;
2189 PyErr_SetVim(_("failed to run function"));
2190 }
2191 else
2192 result = ConvertToPyObject(&rettv);
2193
Bram Moolenaardb913952012-06-29 12:54:53 +02002194 clear_tv(&args);
2195 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002196 if (selfdict != NULL)
2197 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002198
2199 return result;
2200}
2201
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002202 static PyObject *
2203FunctionRepr(FunctionObject *self)
2204{
2205 return PyString_FromFormat("<vim.Function '%s'>", self->name);
2206}
2207
Bram Moolenaardb913952012-06-29 12:54:53 +02002208static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002209 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2210 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002211};
2212
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002213/*
2214 * Options object
2215 */
2216
2217static PyTypeObject OptionsType;
2218
2219typedef int (*checkfun)(void *);
2220
2221typedef struct
2222{
2223 PyObject_HEAD
2224 int opt_type;
2225 void *from;
2226 checkfun Check;
2227 PyObject *fromObj;
2228} OptionsObject;
2229
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002230 static int
2231dummy_check(void *arg UNUSED)
2232{
2233 return 0;
2234}
2235
2236 static PyObject *
2237OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2238{
2239 OptionsObject *self;
2240
Bram Moolenaar774267b2013-05-21 20:51:59 +02002241 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002242 if (self == NULL)
2243 return NULL;
2244
2245 self->opt_type = opt_type;
2246 self->from = from;
2247 self->Check = Check;
2248 self->fromObj = fromObj;
2249 if (fromObj)
2250 Py_INCREF(fromObj);
2251
2252 return (PyObject *)(self);
2253}
2254
2255 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002256OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002257{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002258 PyObject_GC_UnTrack((void *)(self));
2259 Py_XDECREF(self->fromObj);
2260 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002261}
2262
2263 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002264OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002265{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002266 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002267 return 0;
2268}
2269
2270 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002271OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002272{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002273 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002274 return 0;
2275}
2276
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002277 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002278OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002279{
2280 char_u *key;
2281 int flags;
2282 long numval;
2283 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002284 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002285
Bram Moolenaard6e39182013-05-21 18:30:34 +02002286 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002287 return NULL;
2288
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002289 if (!(key = StringToChars(keyObject, &todecref)))
2290 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002291
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002292 if (*key == NUL)
2293 {
2294 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002295 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002296 return NULL;
2297 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002298
2299 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002300 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002301
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002302 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002303
2304 if (flags == 0)
2305 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002306 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002307 return NULL;
2308 }
2309
2310 if (flags & SOPT_UNSET)
2311 {
2312 Py_INCREF(Py_None);
2313 return Py_None;
2314 }
2315 else if (flags & SOPT_BOOL)
2316 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002317 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002318 r = numval ? Py_True : Py_False;
2319 Py_INCREF(r);
2320 return r;
2321 }
2322 else if (flags & SOPT_NUM)
2323 return PyInt_FromLong(numval);
2324 else if (flags & SOPT_STRING)
2325 {
2326 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002327 {
2328 PyObject *r = PyBytes_FromString((char *) stringval);
2329 vim_free(stringval);
2330 return r;
2331 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002332 else
2333 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002334 PyErr_SetString(PyExc_RuntimeError,
2335 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002336 return NULL;
2337 }
2338 }
2339 else
2340 {
2341 PyErr_SetVim("Internal error: unknown option type. Should not happen");
2342 return NULL;
2343 }
2344}
2345
2346 static int
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002347set_option_value_err(key, numval, stringval, opt_flags)
2348 char_u *key;
2349 int numval;
2350 char_u *stringval;
2351 int opt_flags;
2352{
2353 char_u *errmsg;
2354
2355 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2356 {
2357 if (VimTryEnd())
2358 return FAIL;
2359 PyErr_SetVim((char *)errmsg);
2360 return FAIL;
2361 }
2362 return OK;
2363}
2364
2365 static int
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002366set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
2367 char_u *key;
2368 int numval;
2369 char_u *stringval;
2370 int opt_flags;
2371 int opt_type;
2372 void *from;
2373{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002374 win_T *save_curwin = NULL;
2375 tabpage_T *save_curtab = NULL;
2376 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002377 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002378
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002379 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002380 switch (opt_type)
2381 {
2382 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002383 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
2384 win_find_tabpage((win_T *)from)) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002385 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002386 if (VimTryEnd())
2387 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002388 PyErr_SetVim("Problem while switching windows.");
2389 return -1;
2390 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002391 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002392 restore_win(save_curwin, save_curtab);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002393 if (r == FAIL)
2394 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002395 break;
2396 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002397 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002398 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002399 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002400 if (r == FAIL)
2401 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002402 break;
2403 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002404 r = set_option_value_err(key, numval, stringval, opt_flags);
2405 if (r == FAIL)
2406 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002407 break;
2408 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002409 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002410}
2411
2412 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002413OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002414{
2415 char_u *key;
2416 int flags;
2417 int opt_flags;
2418 int r = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002419 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002420
Bram Moolenaard6e39182013-05-21 18:30:34 +02002421 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002422 return -1;
2423
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002424 if (!(key = StringToChars(keyObject, &todecref)))
2425 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002426
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002427 if (*key == NUL)
2428 {
2429 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002430 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002431 return -1;
2432 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002433
2434 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002435 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002436
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002437 if (flags == 0)
2438 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002439 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002440 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002441 return -1;
2442 }
2443
2444 if (valObject == NULL)
2445 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002446 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002447 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002448 PyErr_SetString(PyExc_ValueError,
2449 _("unable to unset global option"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002450 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002451 return -1;
2452 }
2453 else if (!(flags & SOPT_GLOBAL))
2454 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002455 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
2456 "without global value"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002457 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002458 return -1;
2459 }
2460 else
2461 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002462 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002463 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002464 return 0;
2465 }
2466 }
2467
Bram Moolenaard6e39182013-05-21 18:30:34 +02002468 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002469
2470 if (flags & SOPT_BOOL)
2471 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002472 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002473
Bram Moolenaarb983f752013-05-15 16:11:50 +02002474 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002475 r = -1;
2476 else
2477 r = set_option_value_for(key, istrue, NULL,
2478 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002479 }
2480 else if (flags & SOPT_NUM)
2481 {
2482 int val;
2483
2484#if PY_MAJOR_VERSION < 3
2485 if (PyInt_Check(valObject))
2486 val = PyInt_AsLong(valObject);
2487 else
2488#endif
2489 if (PyLong_Check(valObject))
2490 val = PyLong_AsLong(valObject);
2491 else
2492 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002493 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002494 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002495 return -1;
2496 }
2497
2498 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002499 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002500 }
2501 else
2502 {
2503 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002504 PyObject *todecref;
2505
2506 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002507 r = set_option_value_for(key, 0, val, opt_flags,
2508 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002509 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002510 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002511 }
2512
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002513 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002514
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002515 return r;
2516}
2517
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002518static PyMappingMethods OptionsAsMapping = {
2519 (lenfunc) NULL,
2520 (binaryfunc) OptionsItem,
2521 (objobjargproc) OptionsAssItem,
2522};
2523
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002524/* Tabpage object
2525 */
2526
2527typedef struct
2528{
2529 PyObject_HEAD
2530 tabpage_T *tab;
2531} TabPageObject;
2532
2533static PyObject *WinListNew(TabPageObject *tabObject);
2534
2535static PyTypeObject TabPageType;
2536
2537 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002538CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002539{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002540 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002541 {
2542 PyErr_SetVim(_("attempt to refer to deleted tab page"));
2543 return -1;
2544 }
2545
2546 return 0;
2547}
2548
2549 static PyObject *
2550TabPageNew(tabpage_T *tab)
2551{
2552 TabPageObject *self;
2553
2554 if (TAB_PYTHON_REF(tab))
2555 {
2556 self = TAB_PYTHON_REF(tab);
2557 Py_INCREF(self);
2558 }
2559 else
2560 {
2561 self = PyObject_NEW(TabPageObject, &TabPageType);
2562 if (self == NULL)
2563 return NULL;
2564 self->tab = tab;
2565 TAB_PYTHON_REF(tab) = self;
2566 }
2567
2568 return (PyObject *)(self);
2569}
2570
2571 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002572TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002573{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002574 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
2575 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002576
2577 DESTRUCTOR_FINISH(self);
2578}
2579
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002580static char *TabPageAttrs[] = {
2581 "windows", "number", "vars", "window", "valid",
2582 NULL
2583};
2584
2585 static PyObject *
2586TabPageDir(PyObject *self)
2587{
2588 return ObjectDir(self, TabPageAttrs);
2589}
2590
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002591 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002592TabPageAttrValid(TabPageObject *self, char *name)
2593{
2594 PyObject *r;
2595
2596 if (strcmp(name, "valid") != 0)
2597 return NULL;
2598
2599 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
2600 Py_INCREF(r);
2601 return r;
2602}
2603
2604 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002605TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002606{
2607 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002608 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002609 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002610 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002611 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002612 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002613 else if (strcmp(name, "window") == 0)
2614 {
2615 /* For current tab window.c does not bother to set or update tp_curwin
2616 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002617 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002618 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002619 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002620 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002621 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002622 else if (strcmp(name, "__members__") == 0)
2623 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002624 return NULL;
2625}
2626
2627 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002628TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002629{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002630 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002631 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002632 else
2633 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002634 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002635
2636 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002637 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2638 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002639 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002640 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002641 }
2642}
2643
2644static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002645 /* name, function, calling, documentation */
2646 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2647 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002648};
2649
2650/*
2651 * Window list object
2652 */
2653
2654static PyTypeObject TabListType;
2655static PySequenceMethods TabListAsSeq;
2656
2657typedef struct
2658{
2659 PyObject_HEAD
2660} TabListObject;
2661
2662 static PyInt
2663TabListLength(PyObject *self UNUSED)
2664{
2665 tabpage_T *tp = first_tabpage;
2666 PyInt n = 0;
2667
2668 while (tp != NULL)
2669 {
2670 ++n;
2671 tp = tp->tp_next;
2672 }
2673
2674 return n;
2675}
2676
2677 static PyObject *
2678TabListItem(PyObject *self UNUSED, PyInt n)
2679{
2680 tabpage_T *tp;
2681
2682 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
2683 if (n == 0)
2684 return TabPageNew(tp);
2685
2686 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
2687 return NULL;
2688}
2689
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002690/* Window object
2691 */
2692
2693typedef struct
2694{
2695 PyObject_HEAD
2696 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002697 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002698} WindowObject;
2699
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002700static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002701
2702 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002703CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002704{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002705 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002706 {
2707 PyErr_SetVim(_("attempt to refer to deleted window"));
2708 return -1;
2709 }
2710
2711 return 0;
2712}
2713
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002714 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002715WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02002716{
2717 /* We need to handle deletion of windows underneath us.
2718 * If we add a "w_python*_ref" field to the win_T structure,
2719 * then we can get at it in win_free() in vim. We then
2720 * need to create only ONE Python object per window - if
2721 * we try to create a second, just INCREF the existing one
2722 * and return it. The (single) Python object referring to
2723 * the window is stored in "w_python*_ref".
2724 * On a win_free() we set the Python object's win_T* field
2725 * to an invalid value. We trap all uses of a window
2726 * object, and reject them if the win_T* field is invalid.
2727 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002728 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02002729 * w_python_ref and w_python3_ref fields respectively.
2730 */
2731
2732 WindowObject *self;
2733
2734 if (WIN_PYTHON_REF(win))
2735 {
2736 self = WIN_PYTHON_REF(win);
2737 Py_INCREF(self);
2738 }
2739 else
2740 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02002741 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02002742 if (self == NULL)
2743 return NULL;
2744 self->win = win;
2745 WIN_PYTHON_REF(win) = self;
2746 }
2747
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002748 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
2749
Bram Moolenaar971db462013-05-12 18:44:48 +02002750 return (PyObject *)(self);
2751}
2752
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002753 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002754WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002755{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002756 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02002757 if (self->win && self->win != INVALID_WINDOW_VALUE)
2758 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02002759 Py_XDECREF(((PyObject *)(self->tabObject)));
2760 PyObject_GC_Del((void *)(self));
2761}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002762
Bram Moolenaar774267b2013-05-21 20:51:59 +02002763 static int
2764WindowTraverse(WindowObject *self, visitproc visit, void *arg)
2765{
2766 Py_VISIT(((PyObject *)(self->tabObject)));
2767 return 0;
2768}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002769
Bram Moolenaar774267b2013-05-21 20:51:59 +02002770 static int
2771WindowClear(WindowObject *self)
2772{
2773 Py_CLEAR(self->tabObject);
2774 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002775}
2776
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002777 static win_T *
2778get_firstwin(TabPageObject *tabObject)
2779{
2780 if (tabObject)
2781 {
2782 if (CheckTabPage(tabObject))
2783 return NULL;
2784 /* For current tab window.c does not bother to set or update tp_firstwin
2785 */
2786 else if (tabObject->tab == curtab)
2787 return firstwin;
2788 else
2789 return tabObject->tab->tp_firstwin;
2790 }
2791 else
2792 return firstwin;
2793}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002794static char *WindowAttrs[] = {
2795 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
2796 "tabpage", "valid",
2797 NULL
2798};
2799
2800 static PyObject *
2801WindowDir(PyObject *self)
2802{
2803 return ObjectDir(self, WindowAttrs);
2804}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002805
Bram Moolenaar971db462013-05-12 18:44:48 +02002806 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002807WindowAttrValid(WindowObject *self, char *name)
2808{
2809 PyObject *r;
2810
2811 if (strcmp(name, "valid") != 0)
2812 return NULL;
2813
2814 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
2815 Py_INCREF(r);
2816 return r;
2817}
2818
2819 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002820WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002821{
2822 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002823 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002824 else if (strcmp(name, "cursor") == 0)
2825 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002826 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002827
2828 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
2829 }
2830 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002831 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002832#ifdef FEAT_WINDOWS
2833 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002834 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002835#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002836#ifdef FEAT_VERTSPLIT
2837 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002838 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002839 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002840 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002841#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02002842 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002843 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002844 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002845 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
2846 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02002847 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002848 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002849 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002850 return NULL;
2851 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002852 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002853 }
2854 else if (strcmp(name, "tabpage") == 0)
2855 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002856 Py_INCREF(self->tabObject);
2857 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002858 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002859 else if (strcmp(name, "__members__") == 0)
2860 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002861 else
2862 return NULL;
2863}
2864
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002865 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002866WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002867{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002868 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002869 return -1;
2870
2871 if (strcmp(name, "buffer") == 0)
2872 {
2873 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
2874 return -1;
2875 }
2876 else if (strcmp(name, "cursor") == 0)
2877 {
2878 long lnum;
2879 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002880
2881 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
2882 return -1;
2883
Bram Moolenaard6e39182013-05-21 18:30:34 +02002884 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002885 {
2886 PyErr_SetVim(_("cursor position outside buffer"));
2887 return -1;
2888 }
2889
2890 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002891 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002892 return -1;
2893
Bram Moolenaard6e39182013-05-21 18:30:34 +02002894 self->win->w_cursor.lnum = lnum;
2895 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002896#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02002897 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002898#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002899 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002900 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002901
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002902 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002903 return 0;
2904 }
2905 else if (strcmp(name, "height") == 0)
2906 {
2907 int height;
2908 win_T *savewin;
2909
2910 if (!PyArg_Parse(val, "i", &height))
2911 return -1;
2912
2913#ifdef FEAT_GUI
2914 need_mouse_correct = TRUE;
2915#endif
2916 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002917 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002918
2919 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002920 win_setheight(height);
2921 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002922 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002923 return -1;
2924
2925 return 0;
2926 }
2927#ifdef FEAT_VERTSPLIT
2928 else if (strcmp(name, "width") == 0)
2929 {
2930 int width;
2931 win_T *savewin;
2932
2933 if (!PyArg_Parse(val, "i", &width))
2934 return -1;
2935
2936#ifdef FEAT_GUI
2937 need_mouse_correct = TRUE;
2938#endif
2939 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002940 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002941
2942 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002943 win_setwidth(width);
2944 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002945 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002946 return -1;
2947
2948 return 0;
2949 }
2950#endif
2951 else
2952 {
2953 PyErr_SetString(PyExc_AttributeError, name);
2954 return -1;
2955 }
2956}
2957
2958 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002959WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002960{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002961 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002962 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002963 else
2964 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002965 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002966
Bram Moolenaar6d216452013-05-12 19:00:41 +02002967 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002968 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002969 (self));
2970 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002971 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002972 }
2973}
2974
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002975static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002976 /* name, function, calling, documentation */
2977 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
2978 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002979};
2980
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002981/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002982 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002983 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002984
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002985static PyTypeObject WinListType;
2986static PySequenceMethods WinListAsSeq;
2987
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002988typedef struct
2989{
2990 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002991 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002992} WinListObject;
2993
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002994 static PyObject *
2995WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002996{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002997 WinListObject *self;
2998
2999 self = PyObject_NEW(WinListObject, &WinListType);
3000 self->tabObject = tabObject;
3001 Py_INCREF(tabObject);
3002
3003 return (PyObject *)(self);
3004}
3005
3006 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003007WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003008{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003009 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003010
3011 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02003012 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003013 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02003014 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003015
3016 DESTRUCTOR_FINISH(self);
3017}
3018
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003019 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003020WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003021{
3022 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003023 PyInt n = 0;
3024
Bram Moolenaard6e39182013-05-21 18:30:34 +02003025 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003026 return -1;
3027
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003028 while (w != NULL)
3029 {
3030 ++n;
3031 w = W_NEXT(w);
3032 }
3033
3034 return n;
3035}
3036
3037 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003038WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003039{
3040 win_T *w;
3041
Bram Moolenaard6e39182013-05-21 18:30:34 +02003042 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003043 return NULL;
3044
3045 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003046 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003047 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003048
3049 PyErr_SetString(PyExc_IndexError, _("no such window"));
3050 return NULL;
3051}
3052
3053/* Convert a Python string into a Vim line.
3054 *
3055 * The result is in allocated memory. All internal nulls are replaced by
3056 * newline characters. It is an error for the string to contain newline
3057 * characters.
3058 *
3059 * On errors, the Python exception data is set, and NULL is returned.
3060 */
3061 static char *
3062StringToLine(PyObject *obj)
3063{
3064 const char *str;
3065 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003066 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003067 PyInt len;
3068 PyInt i;
3069 char *p;
3070
3071 if (obj == NULL || !PyString_Check(obj))
3072 {
3073 PyErr_BadArgument();
3074 return NULL;
3075 }
3076
Bram Moolenaar19e60942011-06-19 00:27:51 +02003077 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
3078 str = PyString_AsString(bytes);
3079 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003080
3081 /*
3082 * Error checking: String must not contain newlines, as we
3083 * are replacing a single line, and we must replace it with
3084 * a single line.
3085 * A trailing newline is removed, so that append(f.readlines()) works.
3086 */
3087 p = memchr(str, '\n', len);
3088 if (p != NULL)
3089 {
3090 if (p == str + len - 1)
3091 --len;
3092 else
3093 {
3094 PyErr_SetVim(_("string cannot contain newlines"));
3095 return NULL;
3096 }
3097 }
3098
3099 /* Create a copy of the string, with internal nulls replaced by
3100 * newline characters, as is the vim convention.
3101 */
3102 save = (char *)alloc((unsigned)(len+1));
3103 if (save == NULL)
3104 {
3105 PyErr_NoMemory();
3106 return NULL;
3107 }
3108
3109 for (i = 0; i < len; ++i)
3110 {
3111 if (str[i] == '\0')
3112 save[i] = '\n';
3113 else
3114 save[i] = str[i];
3115 }
3116
3117 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02003118 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003119
3120 return save;
3121}
3122
3123/* Get a line from the specified buffer. The line number is
3124 * in Vim format (1-based). The line is returned as a Python
3125 * string object.
3126 */
3127 static PyObject *
3128GetBufferLine(buf_T *buf, PyInt n)
3129{
3130 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3131}
3132
3133
3134/* Get a list of lines from the specified buffer. The line numbers
3135 * are in Vim format (1-based). The range is from lo up to, but not
3136 * including, hi. The list is returned as a Python list of string objects.
3137 */
3138 static PyObject *
3139GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3140{
3141 PyInt i;
3142 PyInt n = hi - lo;
3143 PyObject *list = PyList_New(n);
3144
3145 if (list == NULL)
3146 return NULL;
3147
3148 for (i = 0; i < n; ++i)
3149 {
3150 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
3151
3152 /* Error check - was the Python string creation OK? */
3153 if (str == NULL)
3154 {
3155 Py_DECREF(list);
3156 return NULL;
3157 }
3158
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02003159 PyList_SET_ITEM(list, i, str);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003160 }
3161
3162 /* The ownership of the Python list is passed to the caller (ie,
3163 * the caller should Py_DECREF() the object when it is finished
3164 * with it).
3165 */
3166
3167 return list;
3168}
3169
3170/*
3171 * Check if deleting lines made the cursor position invalid.
3172 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3173 * deleted).
3174 */
3175 static void
3176py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3177{
3178 if (curwin->w_cursor.lnum >= lo)
3179 {
3180 /* Adjust the cursor position if it's in/after the changed
3181 * lines. */
3182 if (curwin->w_cursor.lnum >= hi)
3183 {
3184 curwin->w_cursor.lnum += extra;
3185 check_cursor_col();
3186 }
3187 else if (extra < 0)
3188 {
3189 curwin->w_cursor.lnum = lo;
3190 check_cursor();
3191 }
3192 else
3193 check_cursor_col();
3194 changed_cline_bef_curs();
3195 }
3196 invalidate_botline();
3197}
3198
Bram Moolenaar19e60942011-06-19 00:27:51 +02003199/*
3200 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003201 * in Vim format (1-based). The replacement line is given as
3202 * a Python string object. The object is checked for validity
3203 * and correct format. Errors are returned as a value of FAIL.
3204 * The return value is OK on success.
3205 * If OK is returned and len_change is not NULL, *len_change
3206 * is set to the change in the buffer length.
3207 */
3208 static int
3209SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3210{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003211 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003212 * There are three cases:
3213 * 1. NULL, or None - this is a deletion.
3214 * 2. A string - this is a replacement.
3215 * 3. Anything else - this is an error.
3216 */
3217 if (line == Py_None || line == NULL)
3218 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003219 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003220
3221 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003222 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003223
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003224 VimTryStart();
3225
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003226 if (u_savedel((linenr_T)n, 1L) == FAIL)
3227 PyErr_SetVim(_("cannot save undo information"));
3228 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
3229 PyErr_SetVim(_("cannot delete line"));
3230 else
3231 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003232 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003233 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3234 deleted_lines_mark((linenr_T)n, 1L);
3235 }
3236
Bram Moolenaar105bc352013-05-17 16:03:57 +02003237 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003238
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003239 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003240 return FAIL;
3241
3242 if (len_change)
3243 *len_change = -1;
3244
3245 return OK;
3246 }
3247 else if (PyString_Check(line))
3248 {
3249 char *save = StringToLine(line);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003250 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003251
3252 if (save == NULL)
3253 return FAIL;
3254
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003255 VimTryStart();
3256
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003257 /* We do not need to free "save" if ml_replace() consumes it. */
3258 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003259 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003260
3261 if (u_savesub((linenr_T)n) == FAIL)
3262 {
3263 PyErr_SetVim(_("cannot save undo information"));
3264 vim_free(save);
3265 }
3266 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3267 {
3268 PyErr_SetVim(_("cannot replace line"));
3269 vim_free(save);
3270 }
3271 else
3272 changed_bytes((linenr_T)n, 0);
3273
Bram Moolenaar105bc352013-05-17 16:03:57 +02003274 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003275
3276 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003277 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003278 check_cursor_col();
3279
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003280 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003281 return FAIL;
3282
3283 if (len_change)
3284 *len_change = 0;
3285
3286 return OK;
3287 }
3288 else
3289 {
3290 PyErr_BadArgument();
3291 return FAIL;
3292 }
3293}
3294
Bram Moolenaar19e60942011-06-19 00:27:51 +02003295/* Replace a range of lines in the specified buffer. The line numbers are in
3296 * Vim format (1-based). The range is from lo up to, but not including, hi.
3297 * The replacement lines are given as a Python list of string objects. The
3298 * list is checked for validity and correct format. Errors are returned as a
3299 * value of FAIL. The return value is OK on success.
3300 * If OK is returned and len_change is not NULL, *len_change
3301 * is set to the change in the buffer length.
3302 */
3303 static int
3304SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
3305{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003306 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003307 * There are three cases:
3308 * 1. NULL, or None - this is a deletion.
3309 * 2. A list - this is a replacement.
3310 * 3. Anything else - this is an error.
3311 */
3312 if (list == Py_None || list == NULL)
3313 {
3314 PyInt i;
3315 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003316 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003317
3318 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003319 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003320 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003321
3322 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
3323 PyErr_SetVim(_("cannot save undo information"));
3324 else
3325 {
3326 for (i = 0; i < n; ++i)
3327 {
3328 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3329 {
3330 PyErr_SetVim(_("cannot delete line"));
3331 break;
3332 }
3333 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003334 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003335 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3336 deleted_lines_mark((linenr_T)lo, (long)i);
3337 }
3338
Bram Moolenaar105bc352013-05-17 16:03:57 +02003339 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003340
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003341 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003342 return FAIL;
3343
3344 if (len_change)
3345 *len_change = -n;
3346
3347 return OK;
3348 }
3349 else if (PyList_Check(list))
3350 {
3351 PyInt i;
3352 PyInt new_len = PyList_Size(list);
3353 PyInt old_len = hi - lo;
3354 PyInt extra = 0; /* lines added to text, can be negative */
3355 char **array;
3356 buf_T *savebuf;
3357
3358 if (new_len == 0) /* avoid allocating zero bytes */
3359 array = NULL;
3360 else
3361 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003362 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003363 if (array == NULL)
3364 {
3365 PyErr_NoMemory();
3366 return FAIL;
3367 }
3368 }
3369
3370 for (i = 0; i < new_len; ++i)
3371 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003372 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003373
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003374 if (!(line = PyList_GetItem(list, i)) ||
3375 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003376 {
3377 while (i)
3378 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003379 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003380 return FAIL;
3381 }
3382 }
3383
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003384 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003385 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003386
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003387 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003388 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003389
3390 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
3391 PyErr_SetVim(_("cannot save undo information"));
3392
3393 /* If the size of the range is reducing (ie, new_len < old_len) we
3394 * need to delete some old_len. We do this at the start, by
3395 * repeatedly deleting line "lo".
3396 */
3397 if (!PyErr_Occurred())
3398 {
3399 for (i = 0; i < old_len - new_len; ++i)
3400 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3401 {
3402 PyErr_SetVim(_("cannot delete line"));
3403 break;
3404 }
3405 extra -= i;
3406 }
3407
3408 /* For as long as possible, replace the existing old_len with the
3409 * new old_len. This is a more efficient operation, as it requires
3410 * less memory allocation and freeing.
3411 */
3412 if (!PyErr_Occurred())
3413 {
3414 for (i = 0; i < old_len && i < new_len; ++i)
3415 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3416 == FAIL)
3417 {
3418 PyErr_SetVim(_("cannot replace line"));
3419 break;
3420 }
3421 }
3422 else
3423 i = 0;
3424
3425 /* Now we may need to insert the remaining new old_len. If we do, we
3426 * must free the strings as we finish with them (we can't pass the
3427 * responsibility to vim in this case).
3428 */
3429 if (!PyErr_Occurred())
3430 {
3431 while (i < new_len)
3432 {
3433 if (ml_append((linenr_T)(lo + i - 1),
3434 (char_u *)array[i], 0, FALSE) == FAIL)
3435 {
3436 PyErr_SetVim(_("cannot insert line"));
3437 break;
3438 }
3439 vim_free(array[i]);
3440 ++i;
3441 ++extra;
3442 }
3443 }
3444
3445 /* Free any left-over old_len, as a result of an error */
3446 while (i < new_len)
3447 {
3448 vim_free(array[i]);
3449 ++i;
3450 }
3451
3452 /* Free the array of old_len. All of its contents have now
3453 * been dealt with (either freed, or the responsibility passed
3454 * to vim.
3455 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003456 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003457
3458 /* Adjust marks. Invalidate any which lie in the
3459 * changed range, and move any in the remainder of the buffer.
3460 */
3461 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3462 (long)MAXLNUM, (long)extra);
3463 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3464
Bram Moolenaar105bc352013-05-17 16:03:57 +02003465 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003466 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3467
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003468 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003469 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003470
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003471 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003472 return FAIL;
3473
3474 if (len_change)
3475 *len_change = new_len - old_len;
3476
3477 return OK;
3478 }
3479 else
3480 {
3481 PyErr_BadArgument();
3482 return FAIL;
3483 }
3484}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003485
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003486/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003487 * The line number is in Vim format (1-based). The lines to be inserted are
3488 * given as a Python list of string objects or as a single string. The lines
3489 * to be added are checked for validity and correct format. Errors are
3490 * returned as a value of FAIL. The return value is OK on success.
3491 * If OK is returned and len_change is not NULL, *len_change
3492 * is set to the change in the buffer length.
3493 */
3494 static int
3495InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3496{
3497 /* First of all, we check the type of the supplied Python object.
3498 * It must be a string or a list, or the call is in error.
3499 */
3500 if (PyString_Check(lines))
3501 {
3502 char *str = StringToLine(lines);
3503 buf_T *savebuf;
3504
3505 if (str == NULL)
3506 return FAIL;
3507
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003508 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003509 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003510 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003511
3512 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
3513 PyErr_SetVim(_("cannot save undo information"));
3514 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
3515 PyErr_SetVim(_("cannot insert line"));
3516 else
3517 appended_lines_mark((linenr_T)n, 1L);
3518
3519 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003520 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003521 update_screen(VALID);
3522
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003523 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003524 return FAIL;
3525
3526 if (len_change)
3527 *len_change = 1;
3528
3529 return OK;
3530 }
3531 else if (PyList_Check(lines))
3532 {
3533 PyInt i;
3534 PyInt size = PyList_Size(lines);
3535 char **array;
3536 buf_T *savebuf;
3537
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003538 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003539 if (array == NULL)
3540 {
3541 PyErr_NoMemory();
3542 return FAIL;
3543 }
3544
3545 for (i = 0; i < size; ++i)
3546 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003547 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003548
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003549 if (!(line = PyList_GetItem(lines, i)) ||
3550 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003551 {
3552 while (i)
3553 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003554 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003555 return FAIL;
3556 }
3557 }
3558
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003559 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003560 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003561 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003562
3563 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
3564 PyErr_SetVim(_("cannot save undo information"));
3565 else
3566 {
3567 for (i = 0; i < size; ++i)
3568 {
3569 if (ml_append((linenr_T)(n + i),
3570 (char_u *)array[i], 0, FALSE) == FAIL)
3571 {
3572 PyErr_SetVim(_("cannot insert line"));
3573
3574 /* Free the rest of the lines */
3575 while (i < size)
3576 vim_free(array[i++]);
3577
3578 break;
3579 }
3580 vim_free(array[i]);
3581 }
3582 if (i > 0)
3583 appended_lines_mark((linenr_T)n, (long)i);
3584 }
3585
3586 /* Free the array of lines. All of its contents have now
3587 * been freed.
3588 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003589 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003590
Bram Moolenaar105bc352013-05-17 16:03:57 +02003591 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003592 update_screen(VALID);
3593
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003594 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003595 return FAIL;
3596
3597 if (len_change)
3598 *len_change = size;
3599
3600 return OK;
3601 }
3602 else
3603 {
3604 PyErr_BadArgument();
3605 return FAIL;
3606 }
3607}
3608
3609/*
3610 * Common routines for buffers and line ranges
3611 * -------------------------------------------
3612 */
3613
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003614typedef struct
3615{
3616 PyObject_HEAD
3617 buf_T *buf;
3618} BufferObject;
3619
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003620 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003621CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003622{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003623 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003624 {
3625 PyErr_SetVim(_("attempt to refer to deleted buffer"));
3626 return -1;
3627 }
3628
3629 return 0;
3630}
3631
3632 static PyObject *
3633RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3634{
3635 if (CheckBuffer(self))
3636 return NULL;
3637
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003638 if (end == -1)
3639 end = self->buf->b_ml.ml_line_count;
3640
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003641 if (n < 0)
3642 n += end - start + 1;
3643
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003644 if (n < 0 || n > end - start)
3645 {
3646 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3647 return NULL;
3648 }
3649
3650 return GetBufferLine(self->buf, n+start);
3651}
3652
3653 static PyObject *
3654RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3655{
3656 PyInt size;
3657
3658 if (CheckBuffer(self))
3659 return NULL;
3660
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003661 if (end == -1)
3662 end = self->buf->b_ml.ml_line_count;
3663
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003664 size = end - start + 1;
3665
3666 if (lo < 0)
3667 lo = 0;
3668 else if (lo > size)
3669 lo = size;
3670 if (hi < 0)
3671 hi = 0;
3672 if (hi < lo)
3673 hi = lo;
3674 else if (hi > size)
3675 hi = size;
3676
3677 return GetBufferLineList(self->buf, lo+start, hi+start);
3678}
3679
3680 static PyInt
3681RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3682{
3683 PyInt len_change;
3684
3685 if (CheckBuffer(self))
3686 return -1;
3687
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003688 if (end == -1)
3689 end = self->buf->b_ml.ml_line_count;
3690
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003691 if (n < 0)
3692 n += end - start + 1;
3693
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003694 if (n < 0 || n > end - start)
3695 {
3696 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3697 return -1;
3698 }
3699
3700 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
3701 return -1;
3702
3703 if (new_end)
3704 *new_end = end + len_change;
3705
3706 return 0;
3707}
3708
Bram Moolenaar19e60942011-06-19 00:27:51 +02003709 static PyInt
3710RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3711{
3712 PyInt size;
3713 PyInt len_change;
3714
3715 /* Self must be a valid buffer */
3716 if (CheckBuffer(self))
3717 return -1;
3718
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003719 if (end == -1)
3720 end = self->buf->b_ml.ml_line_count;
3721
Bram Moolenaar19e60942011-06-19 00:27:51 +02003722 /* Sort out the slice range */
3723 size = end - start + 1;
3724
3725 if (lo < 0)
3726 lo = 0;
3727 else if (lo > size)
3728 lo = size;
3729 if (hi < 0)
3730 hi = 0;
3731 if (hi < lo)
3732 hi = lo;
3733 else if (hi > size)
3734 hi = size;
3735
3736 if (SetBufferLineList(self->buf, lo + start, hi + start,
3737 val, &len_change) == FAIL)
3738 return -1;
3739
3740 if (new_end)
3741 *new_end = end + len_change;
3742
3743 return 0;
3744}
3745
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003746
3747 static PyObject *
3748RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
3749{
3750 PyObject *lines;
3751 PyInt len_change;
3752 PyInt max;
3753 PyInt n;
3754
3755 if (CheckBuffer(self))
3756 return NULL;
3757
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003758 if (end == -1)
3759 end = self->buf->b_ml.ml_line_count;
3760
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003761 max = n = end - start + 1;
3762
3763 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
3764 return NULL;
3765
3766 if (n < 0 || n > max)
3767 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003768 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003769 return NULL;
3770 }
3771
3772 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
3773 return NULL;
3774
3775 if (new_end)
3776 *new_end = end + len_change;
3777
3778 Py_INCREF(Py_None);
3779 return Py_None;
3780}
3781
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003782/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003783 */
3784
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003785static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003786static PySequenceMethods RangeAsSeq;
3787static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003788
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003789typedef struct
3790{
3791 PyObject_HEAD
3792 BufferObject *buf;
3793 PyInt start;
3794 PyInt end;
3795} RangeObject;
3796
3797 static PyObject *
3798RangeNew(buf_T *buf, PyInt start, PyInt end)
3799{
3800 BufferObject *bufr;
3801 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003802 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003803 if (self == NULL)
3804 return NULL;
3805
3806 bufr = (BufferObject *)BufferNew(buf);
3807 if (bufr == NULL)
3808 {
3809 Py_DECREF(self);
3810 return NULL;
3811 }
3812 Py_INCREF(bufr);
3813
3814 self->buf = bufr;
3815 self->start = start;
3816 self->end = end;
3817
3818 return (PyObject *)(self);
3819}
3820
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003821 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003822RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003823{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003824 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003825 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02003826 PyObject_GC_Del((void *)(self));
3827}
3828
3829 static int
3830RangeTraverse(RangeObject *self, visitproc visit, void *arg)
3831{
3832 Py_VISIT(((PyObject *)(self->buf)));
3833 return 0;
3834}
3835
3836 static int
3837RangeClear(RangeObject *self)
3838{
3839 Py_CLEAR(self->buf);
3840 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003841}
3842
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003843 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003844RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003845{
3846 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003847 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003848 return -1; /* ??? */
3849
Bram Moolenaard6e39182013-05-21 18:30:34 +02003850 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003851}
3852
3853 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003854RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003855{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003856 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003857}
3858
3859 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003860RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003861{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003862 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003863}
3864
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003865static char *RangeAttrs[] = {
3866 "start", "end",
3867 NULL
3868};
3869
3870 static PyObject *
3871RangeDir(PyObject *self)
3872{
3873 return ObjectDir(self, RangeAttrs);
3874}
3875
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003876 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003877RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003878{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003879 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003880}
3881
3882 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003883RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003884{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003885 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003886 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
3887 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003888 else
3889 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003890 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003891
3892 if (name == NULL)
3893 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003894
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003895 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02003896 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003897 }
3898}
3899
3900static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02003901 /* name, function, calling, documentation */
3902 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003903 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
3904 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003905};
3906
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003907static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003908static PySequenceMethods BufferAsSeq;
3909static PyMappingMethods BufferAsMapping;
3910
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003911 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02003912BufferNew(buf_T *buf)
3913{
3914 /* We need to handle deletion of buffers underneath us.
3915 * If we add a "b_python*_ref" field to the buf_T structure,
3916 * then we can get at it in buf_freeall() in vim. We then
3917 * need to create only ONE Python object per buffer - if
3918 * we try to create a second, just INCREF the existing one
3919 * and return it. The (single) Python object referring to
3920 * the buffer is stored in "b_python*_ref".
3921 * Question: what to do on a buf_freeall(). We'll probably
3922 * have to either delete the Python object (DECREF it to
3923 * zero - a bad idea, as it leaves dangling refs!) or
3924 * set the buf_T * value to an invalid value (-1?), which
3925 * means we need checks in all access functions... Bah.
3926 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003927 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003928 * b_python_ref and b_python3_ref fields respectively.
3929 */
3930
3931 BufferObject *self;
3932
3933 if (BUF_PYTHON_REF(buf) != NULL)
3934 {
3935 self = BUF_PYTHON_REF(buf);
3936 Py_INCREF(self);
3937 }
3938 else
3939 {
3940 self = PyObject_NEW(BufferObject, &BufferType);
3941 if (self == NULL)
3942 return NULL;
3943 self->buf = buf;
3944 BUF_PYTHON_REF(buf) = self;
3945 }
3946
3947 return (PyObject *)(self);
3948}
3949
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003950 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003951BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003952{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003953 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
3954 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003955
3956 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003957}
3958
Bram Moolenaar971db462013-05-12 18:44:48 +02003959 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003960BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02003961{
3962 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003963 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02003964 return -1; /* ??? */
3965
Bram Moolenaard6e39182013-05-21 18:30:34 +02003966 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02003967}
3968
3969 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003970BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02003971{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003972 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003973}
3974
3975 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003976BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02003977{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003978 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003979}
3980
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003981static char *BufferAttrs[] = {
3982 "name", "number", "vars", "options", "valid",
3983 NULL
3984};
3985
3986 static PyObject *
3987BufferDir(PyObject *self)
3988{
3989 return ObjectDir(self, BufferAttrs);
3990}
3991
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003992 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003993BufferAttrValid(BufferObject *self, char *name)
3994{
3995 PyObject *r;
3996
3997 if (strcmp(name, "valid") != 0)
3998 return NULL;
3999
4000 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
4001 Py_INCREF(r);
4002 return r;
4003}
4004
4005 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004006BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004007{
4008 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02004009 return PyString_FromString((self->buf->b_ffname == NULL
4010 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004011 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004012 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004013 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004014 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004015 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004016 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
4017 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004018 else if (strcmp(name, "__members__") == 0)
4019 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004020 else
4021 return NULL;
4022}
4023
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004024 static int
4025BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
4026{
4027 if (CheckBuffer(self))
4028 return -1;
4029
4030 if (strcmp(name, "name") == 0)
4031 {
4032 char_u *val;
4033 aco_save_T aco;
4034 int r;
4035 PyObject *todecref;
4036
4037 if (!(val = StringToChars(valObject, &todecref)))
4038 return -1;
4039
4040 VimTryStart();
4041 /* Using aucmd_*: autocommands will be executed by rename_buffer */
4042 aucmd_prepbuf(&aco, self->buf);
4043 r = rename_buffer(val);
4044 aucmd_restbuf(&aco);
4045 Py_XDECREF(todecref);
4046 if (VimTryEnd())
4047 return -1;
4048
4049 if (r == FAIL)
4050 {
4051 PyErr_SetVim(_("failed to rename buffer"));
4052 return -1;
4053 }
4054 return 0;
4055 }
4056 else
4057 {
4058 PyErr_SetString(PyExc_AttributeError, name);
4059 return -1;
4060 }
4061}
4062
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004063 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004064BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004065{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004066 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004067}
4068
4069 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004070BufferMark(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004071{
4072 pos_T *posp;
4073 char *pmark;
4074 char mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004075 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004076
Bram Moolenaard6e39182013-05-21 18:30:34 +02004077 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004078 return NULL;
4079
4080 if (!PyArg_ParseTuple(args, "s", &pmark))
4081 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004082
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004083 if (STRLEN(pmark) != 1)
4084 {
4085 PyErr_SetString(PyExc_ValueError,
4086 _("mark name must be a single character"));
4087 return NULL;
4088 }
4089
4090 mark = *pmark;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004091 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004092 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004093 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004094 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004095 if (VimTryEnd())
4096 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004097
4098 if (posp == NULL)
4099 {
4100 PyErr_SetVim(_("invalid mark name"));
4101 return NULL;
4102 }
4103
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004104 if (posp->lnum <= 0)
4105 {
4106 /* Or raise an error? */
4107 Py_INCREF(Py_None);
4108 return Py_None;
4109 }
4110
4111 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4112}
4113
4114 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004115BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004116{
4117 PyInt start;
4118 PyInt end;
4119
Bram Moolenaard6e39182013-05-21 18:30:34 +02004120 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004121 return NULL;
4122
4123 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4124 return NULL;
4125
Bram Moolenaard6e39182013-05-21 18:30:34 +02004126 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004127}
4128
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004129 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004130BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004131{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004132 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004133 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004134 else
4135 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004136 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004137
4138 if (name == NULL)
4139 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004140
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004141 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004142 }
4143}
4144
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004145static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004146 /* name, function, calling, documentation */
4147 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
4148 {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" },
4149 {"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 +02004150 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4151 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004152};
4153
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004154/*
4155 * Buffer list object - Implementation
4156 */
4157
4158static PyTypeObject BufMapType;
4159
4160typedef struct
4161{
4162 PyObject_HEAD
4163} BufMapObject;
4164
4165 static PyInt
4166BufMapLength(PyObject *self UNUSED)
4167{
4168 buf_T *b = firstbuf;
4169 PyInt n = 0;
4170
4171 while (b)
4172 {
4173 ++n;
4174 b = b->b_next;
4175 }
4176
4177 return n;
4178}
4179
4180 static PyObject *
4181BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4182{
4183 buf_T *b;
4184 int bnr;
4185
4186#if PY_MAJOR_VERSION < 3
4187 if (PyInt_Check(keyObject))
4188 bnr = PyInt_AsLong(keyObject);
4189 else
4190#endif
4191 if (PyLong_Check(keyObject))
4192 bnr = PyLong_AsLong(keyObject);
4193 else
4194 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004195 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004196 return NULL;
4197 }
4198
4199 b = buflist_findnr(bnr);
4200
4201 if (b)
4202 return BufferNew(b);
4203 else
4204 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004205 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004206 return NULL;
4207 }
4208}
4209
4210 static void
4211BufMapIterDestruct(PyObject *buffer)
4212{
4213 /* Iteration was stopped before all buffers were processed */
4214 if (buffer)
4215 {
4216 Py_DECREF(buffer);
4217 }
4218}
4219
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004220 static int
4221BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4222{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004223 if (buffer)
4224 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004225 return 0;
4226}
4227
4228 static int
4229BufMapIterClear(PyObject **buffer)
4230{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004231 if (*buffer)
4232 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004233 return 0;
4234}
4235
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004236 static PyObject *
4237BufMapIterNext(PyObject **buffer)
4238{
4239 PyObject *next;
4240 PyObject *r;
4241
4242 if (!*buffer)
4243 return NULL;
4244
4245 r = *buffer;
4246
4247 if (CheckBuffer((BufferObject *)(r)))
4248 {
4249 *buffer = NULL;
4250 return NULL;
4251 }
4252
4253 if (!((BufferObject *)(r))->buf->b_next)
4254 next = NULL;
4255 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
4256 return NULL;
4257 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004258 /* Do not increment reference: we no longer hold it (decref), but whoever
4259 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004260 return r;
4261}
4262
4263 static PyObject *
4264BufMapIter(PyObject *self UNUSED)
4265{
4266 PyObject *buffer;
4267
4268 buffer = BufferNew(firstbuf);
4269 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004270 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4271 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004272}
4273
4274static PyMappingMethods BufMapAsMapping = {
4275 (lenfunc) BufMapLength,
4276 (binaryfunc) BufMapItem,
4277 (objobjargproc) 0,
4278};
4279
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004280/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004281 */
4282
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004283static char *CurrentAttrs[] = {
4284 "buffer", "window", "line", "range", "tabpage",
4285 NULL
4286};
4287
4288 static PyObject *
4289CurrentDir(PyObject *self)
4290{
4291 return ObjectDir(self, CurrentAttrs);
4292}
4293
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004294 static PyObject *
4295CurrentGetattr(PyObject *self UNUSED, char *name)
4296{
4297 if (strcmp(name, "buffer") == 0)
4298 return (PyObject *)BufferNew(curbuf);
4299 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004300 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004301 else if (strcmp(name, "tabpage") == 0)
4302 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004303 else if (strcmp(name, "line") == 0)
4304 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4305 else if (strcmp(name, "range") == 0)
4306 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004307 else if (strcmp(name, "__members__") == 0)
4308 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004309 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004310#if PY_MAJOR_VERSION < 3
4311 return Py_FindMethod(WindowMethods, self, name);
4312#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004313 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004314#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004315}
4316
4317 static int
4318CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
4319{
4320 if (strcmp(name, "line") == 0)
4321 {
4322 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
4323 return -1;
4324
4325 return 0;
4326 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004327 else if (strcmp(name, "buffer") == 0)
4328 {
4329 int count;
4330
4331 if (value->ob_type != &BufferType)
4332 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004333 PyErr_SetString(PyExc_TypeError, _("expected vim.Buffer object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004334 return -1;
4335 }
4336
4337 if (CheckBuffer((BufferObject *)(value)))
4338 return -1;
4339 count = ((BufferObject *)(value))->buf->b_fnum;
4340
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004341 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004342 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4343 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004344 if (VimTryEnd())
4345 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004346 PyErr_SetVim(_("failed to switch to given buffer"));
4347 return -1;
4348 }
4349
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004350 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004351 }
4352 else if (strcmp(name, "window") == 0)
4353 {
4354 int count;
4355
4356 if (value->ob_type != &WindowType)
4357 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004358 PyErr_SetString(PyExc_TypeError, _("expected vim.Window object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004359 return -1;
4360 }
4361
4362 if (CheckWindow((WindowObject *)(value)))
4363 return -1;
4364 count = get_win_number(((WindowObject *)(value))->win, firstwin);
4365
4366 if (!count)
4367 {
4368 PyErr_SetString(PyExc_ValueError,
4369 _("failed to find window in the current tab page"));
4370 return -1;
4371 }
4372
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004373 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004374 win_goto(((WindowObject *)(value))->win);
4375 if (((WindowObject *)(value))->win != curwin)
4376 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004377 if (VimTryEnd())
4378 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004379 PyErr_SetString(PyExc_RuntimeError,
4380 _("did not switch to the specified window"));
4381 return -1;
4382 }
4383
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004384 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004385 }
4386 else if (strcmp(name, "tabpage") == 0)
4387 {
4388 if (value->ob_type != &TabPageType)
4389 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004390 PyErr_SetString(PyExc_TypeError, _("expected vim.TabPage object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004391 return -1;
4392 }
4393
4394 if (CheckTabPage((TabPageObject *)(value)))
4395 return -1;
4396
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004397 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004398 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
4399 if (((TabPageObject *)(value))->tab != curtab)
4400 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004401 if (VimTryEnd())
4402 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004403 PyErr_SetString(PyExc_RuntimeError,
4404 _("did not switch to the specified tab page"));
4405 return -1;
4406 }
4407
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004408 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004409 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004410 else
4411 {
4412 PyErr_SetString(PyExc_AttributeError, name);
4413 return -1;
4414 }
4415}
4416
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004417static struct PyMethodDef CurrentMethods[] = {
4418 /* name, function, calling, documentation */
4419 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4420 { NULL, NULL, 0, NULL}
4421};
4422
Bram Moolenaardb913952012-06-29 12:54:53 +02004423 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004424init_range_cmd(exarg_T *eap)
4425{
4426 RangeStart = eap->line1;
4427 RangeEnd = eap->line2;
4428}
4429
4430 static void
4431init_range_eval(typval_T *rettv UNUSED)
4432{
4433 RangeStart = (PyInt) curwin->w_cursor.lnum;
4434 RangeEnd = RangeStart;
4435}
4436
4437 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004438run_cmd(const char *cmd, void *arg UNUSED
4439#ifdef PY_CAN_RECURSE
4440 , PyGILState_STATE *pygilstate UNUSED
4441#endif
4442 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004443{
4444 PyRun_SimpleString((char *) cmd);
4445}
4446
4447static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4448static int code_hdr_len = 30;
4449
4450 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004451run_do(const char *cmd, void *arg UNUSED
4452#ifdef PY_CAN_RECURSE
4453 , PyGILState_STATE *pygilstate
4454#endif
4455 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004456{
4457 PyInt lnum;
4458 size_t len;
4459 char *code;
4460 int status;
4461 PyObject *pyfunc, *pymain;
4462
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004463 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004464 {
4465 EMSG(_("cannot save undo information"));
4466 return;
4467 }
4468
4469 len = code_hdr_len + STRLEN(cmd);
4470 code = PyMem_New(char, len + 1);
4471 memcpy(code, code_hdr, code_hdr_len);
4472 STRCPY(code + code_hdr_len, cmd);
4473 status = PyRun_SimpleString(code);
4474 PyMem_Free(code);
4475
4476 if (status)
4477 {
4478 EMSG(_("failed to run the code"));
4479 return;
4480 }
4481
4482 status = 0;
4483 pymain = PyImport_AddModule("__main__");
4484 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004485#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004486 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004487#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004488
4489 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4490 {
4491 PyObject *line, *linenr, *ret;
4492
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004493#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004494 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004495#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004496 if (!(line = GetBufferLine(curbuf, lnum)))
4497 goto err;
4498 if (!(linenr = PyInt_FromLong((long) lnum)))
4499 {
4500 Py_DECREF(line);
4501 goto err;
4502 }
4503 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4504 Py_DECREF(line);
4505 Py_DECREF(linenr);
4506 if (!ret)
4507 goto err;
4508
4509 if (ret != Py_None)
4510 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
4511 goto err;
4512
4513 Py_XDECREF(ret);
4514 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004515#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004516 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004517#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004518 }
4519 goto out;
4520err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004521#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004522 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004523#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004524 PyErr_PrintEx(0);
4525 PythonIO_Flush();
4526 status = 1;
4527out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004528#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004529 if (!status)
4530 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004531#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004532 Py_DECREF(pyfunc);
4533 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
4534 if (status)
4535 return;
4536 check_cursor();
4537 update_curbuf(NOT_VALID);
4538}
4539
4540 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004541run_eval(const char *cmd, typval_T *rettv
4542#ifdef PY_CAN_RECURSE
4543 , PyGILState_STATE *pygilstate UNUSED
4544#endif
4545 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004546{
4547 PyObject *r;
4548
4549 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
4550 if (r == NULL)
4551 {
4552 if (PyErr_Occurred() && !msg_silent)
4553 PyErr_PrintEx(0);
4554 EMSG(_("E858: Eval did not return a valid python object"));
4555 }
4556 else
4557 {
4558 if (ConvertFromPyObject(r, rettv) == -1)
4559 EMSG(_("E859: Failed to convert returned python object to vim value"));
4560 Py_DECREF(r);
4561 }
4562 PyErr_Clear();
4563}
4564
4565 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02004566set_ref_in_py(const int copyID)
4567{
4568 pylinkedlist_T *cur;
4569 dict_T *dd;
4570 list_T *ll;
4571
4572 if (lastdict != NULL)
4573 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
4574 {
4575 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
4576 if (dd->dv_copyID != copyID)
4577 {
4578 dd->dv_copyID = copyID;
4579 set_ref_in_ht(&dd->dv_hashtab, copyID);
4580 }
4581 }
4582
4583 if (lastlist != NULL)
4584 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
4585 {
4586 ll = ((ListObject *) (cur->pll_obj))->list;
4587 if (ll->lv_copyID != copyID)
4588 {
4589 ll->lv_copyID = copyID;
4590 set_ref_in_list(ll, copyID);
4591 }
4592 }
4593}
4594
4595 static int
4596set_string_copy(char_u *str, typval_T *tv)
4597{
4598 tv->vval.v_string = vim_strsave(str);
4599 if (tv->vval.v_string == NULL)
4600 {
4601 PyErr_NoMemory();
4602 return -1;
4603 }
4604 return 0;
4605}
4606
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004607 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004608pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004609{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004610 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004611 char_u *key;
4612 dictitem_T *di;
4613 PyObject *keyObject;
4614 PyObject *valObject;
4615 Py_ssize_t iter = 0;
4616
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004617 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004618 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004619
4620 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004621 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004622
4623 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4624 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004625 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004626
Bram Moolenaara03e6312013-05-29 22:49:26 +02004627 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004628 {
4629 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004630 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004631 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004632
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004633 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004634 {
4635 dict_unref(dict);
4636 return -1;
4637 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004638
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004639 if (*key == NUL)
4640 {
4641 dict_unref(dict);
4642 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004643 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004644 return -1;
4645 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004646
4647 di = dictitem_alloc(key);
4648
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004649 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004650
4651 if (di == NULL)
4652 {
4653 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004654 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004655 return -1;
4656 }
4657 di->di_tv.v_lock = 0;
4658
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004659 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004660 {
4661 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004662 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004663 return -1;
4664 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004665
4666 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004667 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02004668 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004669 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004670 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004671 PyErr_SetVim(_("failed to add key to dictionary"));
4672 return -1;
4673 }
4674 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004675
4676 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004677 return 0;
4678}
4679
4680 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004681pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004682{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004683 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004684 char_u *key;
4685 dictitem_T *di;
4686 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004687 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004688 PyObject *keyObject;
4689 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004690
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004691 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004692 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004693
4694 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004695 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004696
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004697 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004698 {
4699 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004700 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004701 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004702
4703 if (!(iterator = PyObject_GetIter(list)))
4704 {
4705 dict_unref(dict);
4706 Py_DECREF(list);
4707 return -1;
4708 }
4709 Py_DECREF(list);
4710
4711 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004712 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004713 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004714
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004715 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004716 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004717 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004718 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004719 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004720 return -1;
4721 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004722
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004723 if (*key == NUL)
4724 {
4725 Py_DECREF(keyObject);
4726 Py_DECREF(iterator);
4727 Py_XDECREF(todecref);
4728 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004729 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004730 return -1;
4731 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004732
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004733 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004734 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004735 Py_DECREF(keyObject);
4736 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004737 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004738 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004739 return -1;
4740 }
4741
4742 di = dictitem_alloc(key);
4743
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004744 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004745 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004746
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004747 if (di == NULL)
4748 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004749 Py_DECREF(iterator);
4750 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004751 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004752 PyErr_NoMemory();
4753 return -1;
4754 }
4755 di->di_tv.v_lock = 0;
4756
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004757 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004758 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004759 Py_DECREF(iterator);
4760 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004761 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004762 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004763 return -1;
4764 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02004765
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004766 Py_DECREF(valObject);
4767
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004768 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004769 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004770 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004771 dictitem_free(di);
4772 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004773 PyErr_SetVim(_("failed to add key to dictionary"));
4774 return -1;
4775 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004776 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004777 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004778 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004779 return 0;
4780}
4781
4782 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004783pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004784{
4785 list_T *l;
4786
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004787 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004788 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004789
4790 tv->v_type = VAR_LIST;
4791 tv->vval.v_list = l;
4792
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004793 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004794 {
4795 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004796 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004797 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004798
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004799 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004800 return 0;
4801}
4802
Bram Moolenaardb913952012-06-29 12:54:53 +02004803typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
4804
4805 static int
4806convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004807 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004808{
4809 PyObject *capsule;
4810 char hexBuf[sizeof(void *) * 2 + 3];
4811
4812 sprintf(hexBuf, "%p", obj);
4813
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004814# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004815 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004816# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004817 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004818# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02004819 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02004820 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004821# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02004822 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02004823# else
4824 capsule = PyCObject_FromVoidPtr(tv, NULL);
4825# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02004826 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
4827 {
4828 Py_DECREF(capsule);
4829 tv->v_type = VAR_UNKNOWN;
4830 return -1;
4831 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004832 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02004833 {
4834 tv->v_type = VAR_UNKNOWN;
4835 return -1;
4836 }
4837 /* As we are not using copy_tv which increments reference count we must
4838 * do it ourself. */
4839 switch(tv->v_type)
4840 {
4841 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
4842 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
4843 }
4844 }
4845 else
4846 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004847 typval_T *v;
4848
4849# ifdef PY_USE_CAPSULE
4850 v = PyCapsule_GetPointer(capsule, NULL);
4851# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02004852 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004853# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02004854 copy_tv(v, tv);
4855 }
4856 return 0;
4857}
4858
4859 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02004860ConvertFromPyMapping(PyObject *obj, typval_T *tv)
4861{
4862 PyObject *lookup_dict;
4863 int r;
4864
4865 if (!(lookup_dict = PyDict_New()))
4866 return -1;
4867
4868 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
4869 {
4870 tv->v_type = VAR_DICT;
4871 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
4872 ++tv->vval.v_dict->dv_refcount;
4873 r = 0;
4874 }
4875 else if (PyDict_Check(obj))
4876 r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
4877 else if (PyMapping_Check(obj))
4878 r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
4879 else
4880 {
4881 PyErr_SetString(PyExc_TypeError,
4882 _("unable to convert object to vim dictionary"));
4883 r = -1;
4884 }
4885 Py_DECREF(lookup_dict);
4886 return r;
4887}
4888
4889 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02004890ConvertFromPyObject(PyObject *obj, typval_T *tv)
4891{
4892 PyObject *lookup_dict;
4893 int r;
4894
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004895 if (!(lookup_dict = PyDict_New()))
4896 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004897 r = _ConvertFromPyObject(obj, tv, lookup_dict);
4898 Py_DECREF(lookup_dict);
4899 return r;
4900}
4901
4902 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004903_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004904{
Bram Moolenaara9922d62013-05-30 13:01:18 +02004905 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02004906 {
4907 tv->v_type = VAR_DICT;
4908 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
4909 ++tv->vval.v_dict->dv_refcount;
4910 }
4911 else if (obj->ob_type == &ListType)
4912 {
4913 tv->v_type = VAR_LIST;
4914 tv->vval.v_list = (((ListObject *)(obj))->list);
4915 ++tv->vval.v_list->lv_refcount;
4916 }
4917 else if (obj->ob_type == &FunctionType)
4918 {
4919 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
4920 return -1;
4921
4922 tv->v_type = VAR_FUNC;
4923 func_ref(tv->vval.v_string);
4924 }
Bram Moolenaardb913952012-06-29 12:54:53 +02004925 else if (PyBytes_Check(obj))
4926 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004927 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02004928
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004929 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
4930 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004931 if (result == NULL)
4932 return -1;
4933
4934 if (set_string_copy(result, tv) == -1)
4935 return -1;
4936
4937 tv->v_type = VAR_STRING;
4938 }
4939 else if (PyUnicode_Check(obj))
4940 {
4941 PyObject *bytes;
4942 char_u *result;
4943
Bram Moolenaardb913952012-06-29 12:54:53 +02004944 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
4945 if (bytes == NULL)
4946 return -1;
4947
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004948 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
4949 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004950 if (result == NULL)
4951 return -1;
4952
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004953 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02004954 {
4955 Py_XDECREF(bytes);
4956 return -1;
4957 }
4958 Py_XDECREF(bytes);
4959
4960 tv->v_type = VAR_STRING;
4961 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02004962#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02004963 else if (PyInt_Check(obj))
4964 {
4965 tv->v_type = VAR_NUMBER;
4966 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
4967 }
4968#endif
4969 else if (PyLong_Check(obj))
4970 {
4971 tv->v_type = VAR_NUMBER;
4972 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
4973 }
4974 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004975 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004976#ifdef FEAT_FLOAT
4977 else if (PyFloat_Check(obj))
4978 {
4979 tv->v_type = VAR_FLOAT;
4980 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
4981 }
4982#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004983 else if (PyObject_HasAttrString(obj, "keys"))
4984 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02004985 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004986 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004987 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004988 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004989 else
4990 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004991 PyErr_SetString(PyExc_TypeError,
4992 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02004993 return -1;
4994 }
4995 return 0;
4996}
4997
4998 static PyObject *
4999ConvertToPyObject(typval_T *tv)
5000{
5001 if (tv == NULL)
5002 {
5003 PyErr_SetVim(_("NULL reference passed"));
5004 return NULL;
5005 }
5006 switch (tv->v_type)
5007 {
5008 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005009 return PyBytes_FromString(tv->vval.v_string == NULL
5010 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005011 case VAR_NUMBER:
5012 return PyLong_FromLong((long) tv->vval.v_number);
5013#ifdef FEAT_FLOAT
5014 case VAR_FLOAT:
5015 return PyFloat_FromDouble((double) tv->vval.v_float);
5016#endif
5017 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005018 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02005019 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02005020 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005021 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005022 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005023 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005024 case VAR_UNKNOWN:
5025 Py_INCREF(Py_None);
5026 return Py_None;
5027 default:
5028 PyErr_SetVim(_("internal error: invalid value type"));
5029 return NULL;
5030 }
5031}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005032
5033typedef struct
5034{
5035 PyObject_HEAD
5036} CurrentObject;
5037static PyTypeObject CurrentType;
5038
5039 static void
5040init_structs(void)
5041{
5042 vim_memset(&OutputType, 0, sizeof(OutputType));
5043 OutputType.tp_name = "vim.message";
5044 OutputType.tp_basicsize = sizeof(OutputObject);
5045 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
5046 OutputType.tp_doc = "vim message object";
5047 OutputType.tp_methods = OutputMethods;
5048#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005049 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
5050 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005051 OutputType.tp_alloc = call_PyType_GenericAlloc;
5052 OutputType.tp_new = call_PyType_GenericNew;
5053 OutputType.tp_free = call_PyObject_Free;
5054#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005055 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
5056 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005057#endif
5058
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005059 vim_memset(&IterType, 0, sizeof(IterType));
5060 IterType.tp_name = "vim.iter";
5061 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005062 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005063 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005064 IterType.tp_iter = (getiterfunc)IterIter;
5065 IterType.tp_iternext = (iternextfunc)IterNext;
5066 IterType.tp_dealloc = (destructor)IterDestructor;
5067 IterType.tp_traverse = (traverseproc)IterTraverse;
5068 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005069
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005070 vim_memset(&BufferType, 0, sizeof(BufferType));
5071 BufferType.tp_name = "vim.buffer";
5072 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005073 BufferType.tp_dealloc = (destructor)BufferDestructor;
5074 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005075 BufferType.tp_as_sequence = &BufferAsSeq;
5076 BufferType.tp_as_mapping = &BufferAsMapping;
5077 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5078 BufferType.tp_doc = "vim buffer object";
5079 BufferType.tp_methods = BufferMethods;
5080#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005081 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005082 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005083 BufferType.tp_alloc = call_PyType_GenericAlloc;
5084 BufferType.tp_new = call_PyType_GenericNew;
5085 BufferType.tp_free = call_PyObject_Free;
5086#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005087 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005088 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005089#endif
5090
5091 vim_memset(&WindowType, 0, sizeof(WindowType));
5092 WindowType.tp_name = "vim.window";
5093 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005094 WindowType.tp_dealloc = (destructor)WindowDestructor;
5095 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005096 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005097 WindowType.tp_doc = "vim Window object";
5098 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005099 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5100 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005101#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005102 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5103 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005104 WindowType.tp_alloc = call_PyType_GenericAlloc;
5105 WindowType.tp_new = call_PyType_GenericNew;
5106 WindowType.tp_free = call_PyObject_Free;
5107#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005108 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5109 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005110#endif
5111
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005112 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5113 TabPageType.tp_name = "vim.tabpage";
5114 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005115 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5116 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005117 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5118 TabPageType.tp_doc = "vim tab page object";
5119 TabPageType.tp_methods = TabPageMethods;
5120#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005121 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005122 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5123 TabPageType.tp_new = call_PyType_GenericNew;
5124 TabPageType.tp_free = call_PyObject_Free;
5125#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005126 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005127#endif
5128
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005129 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5130 BufMapType.tp_name = "vim.bufferlist";
5131 BufMapType.tp_basicsize = sizeof(BufMapObject);
5132 BufMapType.tp_as_mapping = &BufMapAsMapping;
5133 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005134 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005135 BufferType.tp_doc = "vim buffer list";
5136
5137 vim_memset(&WinListType, 0, sizeof(WinListType));
5138 WinListType.tp_name = "vim.windowlist";
5139 WinListType.tp_basicsize = sizeof(WinListType);
5140 WinListType.tp_as_sequence = &WinListAsSeq;
5141 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5142 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005143 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005144
5145 vim_memset(&TabListType, 0, sizeof(TabListType));
5146 TabListType.tp_name = "vim.tabpagelist";
5147 TabListType.tp_basicsize = sizeof(TabListType);
5148 TabListType.tp_as_sequence = &TabListAsSeq;
5149 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5150 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005151
5152 vim_memset(&RangeType, 0, sizeof(RangeType));
5153 RangeType.tp_name = "vim.range";
5154 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005155 RangeType.tp_dealloc = (destructor)RangeDestructor;
5156 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005157 RangeType.tp_as_sequence = &RangeAsSeq;
5158 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005159 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005160 RangeType.tp_doc = "vim Range object";
5161 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005162 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5163 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005164#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005165 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005166 RangeType.tp_alloc = call_PyType_GenericAlloc;
5167 RangeType.tp_new = call_PyType_GenericNew;
5168 RangeType.tp_free = call_PyObject_Free;
5169#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005170 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005171#endif
5172
5173 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5174 CurrentType.tp_name = "vim.currentdata";
5175 CurrentType.tp_basicsize = sizeof(CurrentObject);
5176 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5177 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005178 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005179#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005180 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5181 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005182#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005183 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5184 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005185#endif
5186
5187 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5188 DictionaryType.tp_name = "vim.dictionary";
5189 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005190 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005191 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005192 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005193 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005194 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5195 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005196 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5197 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5198 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005199#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005200 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5201 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005202#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005203 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5204 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005205#endif
5206
5207 vim_memset(&ListType, 0, sizeof(ListType));
5208 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005209 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005210 ListType.tp_basicsize = sizeof(ListObject);
5211 ListType.tp_as_sequence = &ListAsSeq;
5212 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005213 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005214 ListType.tp_doc = "list pushing modifications to vim structure";
5215 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005216 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005217 ListType.tp_new = (newfunc)ListConstructor;
5218 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005219#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005220 ListType.tp_getattro = (getattrofunc)ListGetattro;
5221 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005222#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005223 ListType.tp_getattr = (getattrfunc)ListGetattr;
5224 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005225#endif
5226
5227 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005228 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005229 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005230 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5231 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005232 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005233 FunctionType.tp_doc = "object that calls vim function";
5234 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005235 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005236 FunctionType.tp_new = (newfunc)FunctionConstructor;
5237 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005238#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005239 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005240#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005241 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005242#endif
5243
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005244 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5245 OptionsType.tp_name = "vim.options";
5246 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005247 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005248 OptionsType.tp_doc = "object for manipulating options";
5249 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005250 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5251 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5252 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005253
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005254#if PY_MAJOR_VERSION >= 3
5255 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5256 vimmodule.m_name = "vim";
5257 vimmodule.m_doc = "Vim Python interface\n";
5258 vimmodule.m_size = -1;
5259 vimmodule.m_methods = VimMethods;
5260#endif
5261}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005262
5263#define PYTYPE_READY(type) \
5264 if (PyType_Ready(&type)) \
5265 return -1;
5266
5267 static int
5268init_types()
5269{
5270 PYTYPE_READY(IterType);
5271 PYTYPE_READY(BufferType);
5272 PYTYPE_READY(RangeType);
5273 PYTYPE_READY(WindowType);
5274 PYTYPE_READY(TabPageType);
5275 PYTYPE_READY(BufMapType);
5276 PYTYPE_READY(WinListType);
5277 PYTYPE_READY(TabListType);
5278 PYTYPE_READY(CurrentType);
5279 PYTYPE_READY(DictionaryType);
5280 PYTYPE_READY(ListType);
5281 PYTYPE_READY(FunctionType);
5282 PYTYPE_READY(OptionsType);
5283 PYTYPE_READY(OutputType);
5284 return 0;
5285}
5286
5287static BufMapObject TheBufferMap =
5288{
5289 PyObject_HEAD_INIT(&BufMapType)
5290};
5291
5292static WinListObject TheWindowList =
5293{
5294 PyObject_HEAD_INIT(&WinListType)
5295 NULL
5296};
5297
5298static CurrentObject TheCurrent =
5299{
5300 PyObject_HEAD_INIT(&CurrentType)
5301};
5302
5303static TabListObject TheTabPageList =
5304{
5305 PyObject_HEAD_INIT(&TabListType)
5306};
5307
5308static struct numeric_constant {
5309 char *name;
5310 int value;
5311} numeric_constants[] = {
5312 {"VAR_LOCKED", VAR_LOCKED},
5313 {"VAR_FIXED", VAR_FIXED},
5314 {"VAR_SCOPE", VAR_SCOPE},
5315 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5316};
5317
5318static struct object_constant {
5319 char *name;
5320 PyObject *value;
5321} object_constants[] = {
5322 {"buffers", (PyObject *)(void *)&TheBufferMap},
5323 {"windows", (PyObject *)(void *)&TheWindowList},
5324 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5325 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005326
5327 {"Buffer", (PyObject *)&BufferType},
5328 {"Range", (PyObject *)&RangeType},
5329 {"Window", (PyObject *)&WindowType},
5330 {"TabPage", (PyObject *)&TabPageType},
5331 {"Dictionary", (PyObject *)&DictionaryType},
5332 {"List", (PyObject *)&ListType},
5333 {"Function", (PyObject *)&FunctionType},
5334 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005335};
5336
5337typedef int (*object_adder)(PyObject *, const char *, PyObject *);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005338typedef PyObject *(*attr_getter)(PyObject *, const char *);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005339
5340#define ADD_OBJECT(m, name, obj) \
5341 if (add_object(m, name, obj)) \
5342 return -1;
5343
5344#define ADD_CHECKED_OBJECT(m, name, obj) \
5345 { \
5346 PyObject *value = obj; \
5347 if (!value) \
5348 return -1; \
5349 ADD_OBJECT(m, name, value); \
5350 }
5351
5352 static int
Bram Moolenaarf4258302013-06-02 18:20:17 +02005353populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005354{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005355 int i;
5356 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005357 PyObject *attr;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005358
5359 for (i = 0; i < (int)(sizeof(numeric_constants)
5360 / sizeof(struct numeric_constant));
5361 ++i)
5362 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
5363 PyInt_FromLong(numeric_constants[i].value));
5364
5365 for (i = 0; i < (int)(sizeof(object_constants)
5366 / sizeof(struct object_constant));
5367 ++i)
5368 {
5369 PyObject *value;
5370
5371 value = object_constants[i].value;
5372 Py_INCREF(value);
5373 ADD_OBJECT(m, object_constants[i].name, value);
5374 }
5375
5376 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5377 return -1;
5378 ADD_OBJECT(m, "error", VimError);
5379
Bram Moolenaara9922d62013-05-30 13:01:18 +02005380 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5381 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005382 ADD_CHECKED_OBJECT(m, "options",
5383 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02005384
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005385 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005386 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005387 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005388
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005389 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005390 return -1;
5391 ADD_OBJECT(m, "_getcwd", py_getcwd)
5392
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005393 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005394 return -1;
5395 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005396 if (!(attr = get_attr(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005397 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005398 if (PyObject_SetAttrString(other_module, "chdir", attr))
5399 {
5400 Py_DECREF(attr);
5401 return -1;
5402 }
5403 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005404
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005405 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005406 {
5407 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005408 if (!(attr = get_attr(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005409 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005410 if (PyObject_SetAttrString(other_module, "fchdir", attr))
5411 {
5412 Py_DECREF(attr);
5413 return -1;
5414 }
5415 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005416 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02005417 else
5418 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02005419
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005420 return 0;
5421}