blob: eedbf1ca2d3c8e349613fb07e571f695ba76678f [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 Moolenaar170bf1a2010-07-24 23:51:45 +020055/*
56 * obtain a lock on the Vim data structures
57 */
58 static void
59Python_Lock_Vim(void)
60{
61}
62
63/*
64 * release a lock on the Vim data structures
65 */
66 static void
67Python_Release_Vim(void)
68{
69}
70
Bram Moolenaare9ba5162013-05-29 22:02:22 +020071/*
72 * The "todecref" argument holds a pointer to PyObject * that must be
73 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
74 * was needed to generate returned value is object.
75 *
76 * Use Py_XDECREF to decrement reference count.
77 */
78 static char_u *
79StringToChars(PyObject *object, PyObject **todecref)
80{
81 char_u *p;
82 PyObject *bytes = NULL;
83
84 if (PyBytes_Check(object))
85 {
86
87 if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1)
88 return NULL;
89 if (p == NULL)
90 return NULL;
91
92 *todecref = NULL;
93 }
94 else if (PyUnicode_Check(object))
95 {
96 bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL);
97 if (bytes == NULL)
98 return NULL;
99
100 if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1)
101 return NULL;
102 if (p == NULL)
103 return NULL;
104
105 *todecref = bytes;
106 }
107 else
108 {
109 PyErr_SetString(PyExc_TypeError, _("object must be string"));
110 return NULL;
111 }
112
113 return (char_u *) p;
114}
115
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200116 static int
117add_string(PyObject *list, char *s)
118{
119 PyObject *string;
120
121 if (!(string = PyString_FromString(s)))
122 return -1;
123 if (PyList_Append(list, string))
124 {
125 Py_DECREF(string);
126 return -1;
127 }
128
129 Py_DECREF(string);
130 return 0;
131}
132
133 static PyObject *
134ObjectDir(PyObject *self, char **attributes)
135{
136 PyMethodDef *method;
137 char **attr;
138 PyObject *r;
139
140 if (!(r = PyList_New(0)))
141 return NULL;
142
143 if (self)
144 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
145 if (add_string(r, (char *) method->ml_name))
146 {
147 Py_DECREF(r);
148 return NULL;
149 }
150
151 for (attr = attributes ; *attr ; ++attr)
152 if (add_string(r, *attr))
153 {
154 Py_DECREF(r);
155 return NULL;
156 }
157
158#if PY_MAJOR_VERSION < 3
159 if (add_string(r, "__members__"))
160 {
161 Py_DECREF(r);
162 return NULL;
163 }
164#endif
165
166 return r;
167}
168
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200169/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200170 */
171
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200172/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200173typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200174
175static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200176
177typedef struct
178{
179 PyObject_HEAD
180 long softspace;
181 long error;
182} OutputObject;
183
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200184static char *OutputAttrs[] = {
185 "softspace",
186 NULL
187};
188
189 static PyObject *
190OutputDir(PyObject *self)
191{
192 return ObjectDir(self, OutputAttrs);
193}
194
Bram Moolenaar77045652012-09-21 13:46:06 +0200195 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200196OutputSetattr(OutputObject *self, char *name, PyObject *val)
Bram Moolenaar77045652012-09-21 13:46:06 +0200197{
198 if (val == NULL)
199 {
Bram Moolenaar8661b172013-05-15 15:44:28 +0200200 PyErr_SetString(PyExc_AttributeError,
201 _("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200202 return -1;
203 }
204
205 if (strcmp(name, "softspace") == 0)
206 {
207 if (!PyInt_Check(val))
208 {
209 PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
210 return -1;
211 }
212
Bram Moolenaard6e39182013-05-21 18:30:34 +0200213 self->softspace = PyInt_AsLong(val);
Bram Moolenaar77045652012-09-21 13:46:06 +0200214 return 0;
215 }
216
217 PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
218 return -1;
219}
220
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200221/* Buffer IO, we write one whole line at a time. */
222static garray_T io_ga = {0, 0, 1, 80, NULL};
223static writefn old_fn = NULL;
224
225 static void
226PythonIO_Flush(void)
227{
228 if (old_fn != NULL && io_ga.ga_len > 0)
229 {
230 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
231 old_fn((char_u *)io_ga.ga_data);
232 }
233 io_ga.ga_len = 0;
234}
235
236 static void
237writer(writefn fn, char_u *str, PyInt n)
238{
239 char_u *ptr;
240
241 /* Flush when switching output function. */
242 if (fn != old_fn)
243 PythonIO_Flush();
244 old_fn = fn;
245
246 /* Write each NL separated line. Text after the last NL is kept for
247 * writing later. */
248 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
249 {
250 PyInt len = ptr - str;
251
252 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
253 break;
254
255 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
256 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
257 fn((char_u *)io_ga.ga_data);
258 str = ptr + 1;
259 n -= len + 1;
260 io_ga.ga_len = 0;
261 }
262
263 /* Put the remaining text into io_ga for later printing. */
264 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
265 {
266 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
267 io_ga.ga_len += (int)n;
268 }
269}
270
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200271 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200272OutputWrite(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200273{
Bram Moolenaare8cdcef2012-09-12 20:21:43 +0200274 Py_ssize_t len = 0;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200275 char *str = NULL;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200276 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200277
Bram Moolenaar27564802011-09-07 19:30:21 +0200278 if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200279 return NULL;
280
281 Py_BEGIN_ALLOW_THREADS
282 Python_Lock_Vim();
283 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
284 Python_Release_Vim();
285 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200286 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200287
288 Py_INCREF(Py_None);
289 return Py_None;
290}
291
292 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200293OutputWritelines(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200294{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200295 PyObject *seq;
296 PyObject *iterator;
297 PyObject *item;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200298 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200299
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200300 if (!PyArg_ParseTuple(args, "O", &seq))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200301 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200302
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200303 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200304 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200305
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200306 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200307 {
Bram Moolenaar19e60942011-06-19 00:27:51 +0200308 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200309 PyInt len;
310
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200311 if (!PyArg_Parse(item, "et#", ENC_OPT, &str, &len))
Bram Moolenaardb913952012-06-29 12:54:53 +0200312 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200313 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200314 Py_DECREF(iterator);
315 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200316 return NULL;
317 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200318 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200319
320 Py_BEGIN_ALLOW_THREADS
321 Python_Lock_Vim();
322 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
323 Python_Release_Vim();
324 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200325 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200326 }
327
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200328 Py_DECREF(iterator);
329
330 /* Iterator may have finished due to an exception */
331 if (PyErr_Occurred())
332 return NULL;
333
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200334 Py_INCREF(Py_None);
335 return Py_None;
336}
337
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100338 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200339OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100340{
341 /* do nothing */
342 Py_INCREF(Py_None);
343 return Py_None;
344}
345
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200346/***************/
347
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200348static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200349 /* name, function, calling, doc */
350 {"write", (PyCFunction)OutputWrite, METH_VARARGS, ""},
351 {"writelines", (PyCFunction)OutputWritelines, METH_VARARGS, ""},
352 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200353 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200354 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200355};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200356
357static OutputObject Output =
358{
359 PyObject_HEAD_INIT(&OutputType)
360 0,
361 0
362};
363
364static OutputObject Error =
365{
366 PyObject_HEAD_INIT(&OutputType)
367 0,
368 1
369};
370
371 static int
372PythonIO_Init_io(void)
373{
374 PySys_SetObject("stdout", (PyObject *)(void *)&Output);
375 PySys_SetObject("stderr", (PyObject *)(void *)&Error);
376
377 if (PyErr_Occurred())
378 {
379 EMSG(_("E264: Python: Error initialising I/O objects"));
380 return -1;
381 }
382
383 return 0;
384}
385
386
387static PyObject *VimError;
388
389/* Check to see whether a Vim error has been reported, or a keyboard
390 * interrupt has been detected.
391 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200392
393 static void
394VimTryStart(void)
395{
396 ++trylevel;
397}
398
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200399 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200400VimTryEnd(void)
401{
402 --trylevel;
403 if (got_int)
404 {
405 PyErr_SetNone(PyExc_KeyboardInterrupt);
406 return 1;
407 }
408 else if (!did_throw)
409 return 0;
410 else if (PyErr_Occurred())
411 return 1;
412 else
413 {
414 PyErr_SetVim((char *) current_exception->value);
415 discard_current_exception();
416 return 1;
417 }
418}
419
420 static int
421VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200422{
423 if (got_int)
424 {
425 PyErr_SetNone(PyExc_KeyboardInterrupt);
426 return 1;
427 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200428 return 0;
429}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200430
431/* Vim module - Implementation
432 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200433
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200434 static PyObject *
435VimCommand(PyObject *self UNUSED, PyObject *args)
436{
437 char *cmd;
438 PyObject *result;
439
440 if (!PyArg_ParseTuple(args, "s", &cmd))
441 return NULL;
442
443 PyErr_Clear();
444
445 Py_BEGIN_ALLOW_THREADS
446 Python_Lock_Vim();
447
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200448 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200449 do_cmdline_cmd((char_u *)cmd);
450 update_screen(VALID);
451
452 Python_Release_Vim();
453 Py_END_ALLOW_THREADS
454
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200455 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200456 result = NULL;
457 else
458 result = Py_None;
459
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200460
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200461 Py_XINCREF(result);
462 return result;
463}
464
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200465/*
466 * Function to translate a typval_T into a PyObject; this will recursively
467 * translate lists/dictionaries into their Python equivalents.
468 *
469 * The depth parameter is to avoid infinite recursion, set it to 1 when
470 * you call VimToPython.
471 */
472 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200473VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200474{
475 PyObject *result;
476 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200477 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200478
479 /* Avoid infinite recursion */
480 if (depth > 100)
481 {
482 Py_INCREF(Py_None);
483 result = Py_None;
484 return result;
485 }
486
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200487 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200488 * then and we can use it again. */
489 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
490 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
491 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200492 sprintf(ptrBuf, "%p",
493 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
494 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200495
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200496 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200497 {
498 Py_INCREF(result);
499 return result;
500 }
501 }
502
503 if (our_tv->v_type == VAR_STRING)
504 {
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200505 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200506 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200507 }
508 else if (our_tv->v_type == VAR_NUMBER)
509 {
510 char buf[NUMBUFLEN];
511
512 /* For backwards compatibility numbers are stored as strings. */
513 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200514 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200515 }
516# ifdef FEAT_FLOAT
517 else if (our_tv->v_type == VAR_FLOAT)
518 {
519 char buf[NUMBUFLEN];
520
521 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200522 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200523 }
524# endif
525 else if (our_tv->v_type == VAR_LIST)
526 {
527 list_T *list = our_tv->vval.v_list;
528 listitem_T *curr;
529
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200530 if (list == NULL)
531 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200532
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200533 if (!(result = PyList_New(0)))
534 return NULL;
535
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200536 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200537 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200538 Py_DECREF(result);
539 return NULL;
540 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200541
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200542 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
543 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200544 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200545 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200546 Py_DECREF(result);
547 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200548 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200549 if (PyList_Append(result, newObj))
550 {
551 Py_DECREF(newObj);
552 Py_DECREF(result);
553 return NULL;
554 }
555 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200556 }
557 }
558 else if (our_tv->v_type == VAR_DICT)
559 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200560
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200561 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
562 long_u todo = ht->ht_used;
563 hashitem_T *hi;
564 dictitem_T *di;
565 if (our_tv->vval.v_dict == NULL)
566 return NULL;
567
568 if (!(result = PyDict_New()))
569 return NULL;
570
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200571 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200572 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200573 Py_DECREF(result);
574 return NULL;
575 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200576
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200577 for (hi = ht->ht_array; todo > 0; ++hi)
578 {
579 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200580 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200581 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200582
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200583 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200584 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200585 {
586 Py_DECREF(result);
587 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200588 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200589 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
590 {
591 Py_DECREF(result);
592 Py_DECREF(newObj);
593 return NULL;
594 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200595 }
596 }
597 }
598 else
599 {
600 Py_INCREF(Py_None);
601 result = Py_None;
602 }
603
604 return result;
605}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200606
607 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200608VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200609{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200610 char *expr;
611 typval_T *our_tv;
612 PyObject *result;
613 PyObject *lookup_dict;
614
615 if (!PyArg_ParseTuple(args, "s", &expr))
616 return NULL;
617
618 Py_BEGIN_ALLOW_THREADS
619 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200620 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200621 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200622 Python_Release_Vim();
623 Py_END_ALLOW_THREADS
624
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200625 if (VimTryEnd())
626 return NULL;
627
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200628 if (our_tv == NULL)
629 {
630 PyErr_SetVim(_("invalid expression"));
631 return NULL;
632 }
633
634 /* Convert the Vim type into a Python type. Create a dictionary that's
635 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200636 if (!(lookup_dict = PyDict_New()))
637 result = NULL;
638 else
639 {
640 result = VimToPython(our_tv, 1, lookup_dict);
641 Py_DECREF(lookup_dict);
642 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200643
644
645 Py_BEGIN_ALLOW_THREADS
646 Python_Lock_Vim();
647 free_tv(our_tv);
648 Python_Release_Vim();
649 Py_END_ALLOW_THREADS
650
651 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200652}
653
Bram Moolenaardb913952012-06-29 12:54:53 +0200654static PyObject *ConvertToPyObject(typval_T *);
655
656 static PyObject *
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200657VimEvalPy(PyObject *self UNUSED, PyObject *args)
Bram Moolenaardb913952012-06-29 12:54:53 +0200658{
Bram Moolenaardb913952012-06-29 12:54:53 +0200659 char *expr;
660 typval_T *our_tv;
661 PyObject *result;
662
663 if (!PyArg_ParseTuple(args, "s", &expr))
664 return NULL;
665
666 Py_BEGIN_ALLOW_THREADS
667 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200668 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +0200669 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200670 Python_Release_Vim();
671 Py_END_ALLOW_THREADS
672
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200673 if (VimTryEnd())
674 return NULL;
675
Bram Moolenaardb913952012-06-29 12:54:53 +0200676 if (our_tv == NULL)
677 {
678 PyErr_SetVim(_("invalid expression"));
679 return NULL;
680 }
681
682 result = ConvertToPyObject(our_tv);
683 Py_BEGIN_ALLOW_THREADS
684 Python_Lock_Vim();
685 free_tv(our_tv);
686 Python_Release_Vim();
687 Py_END_ALLOW_THREADS
688
689 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200690}
691
692 static PyObject *
693VimStrwidth(PyObject *self UNUSED, PyObject *args)
694{
695 char *expr;
696
697 if (!PyArg_ParseTuple(args, "s", &expr))
698 return NULL;
699
Bram Moolenaara54bf402012-12-05 16:30:07 +0100700 return PyLong_FromLong(
701#ifdef FEAT_MBYTE
702 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
703#else
704 STRLEN(expr)
705#endif
706 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200707}
708
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200709/*
710 * Vim module - Definitions
711 */
712
713static struct PyMethodDef VimMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200714 /* name, function, calling, documentation */
715 {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" },
716 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
717 {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"},
718 {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"},
719 { NULL, NULL, 0, NULL }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200720};
721
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200722/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200723 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200724 */
725
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200726static PyTypeObject IterType;
727
728typedef PyObject *(*nextfun)(void **);
729typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200730typedef int (*traversefun)(void *, visitproc, void *);
731typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200732
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200733/* Main purpose of this object is removing the need for do python
734 * initialization (i.e. PyType_Ready and setting type attributes) for a big
735 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200736
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200737typedef struct
738{
739 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200740 void *cur;
741 nextfun next;
742 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200743 traversefun traverse;
744 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200745} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200746
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200747 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200748IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
749 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200750{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200751 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200752
Bram Moolenaar774267b2013-05-21 20:51:59 +0200753 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200754 self->cur = start;
755 self->next = next;
756 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200757 self->traverse = traverse;
758 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200759
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200760 return (PyObject *)(self);
761}
762
763 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200764IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200765{
Bram Moolenaar774267b2013-05-21 20:51:59 +0200766 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +0200767 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +0200768 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200769}
770
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200771 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200772IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200773{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200774 if (self->traverse != NULL)
775 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200776 else
777 return 0;
778}
779
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200780/* Mac OSX defines clear() somewhere. */
781#ifdef clear
782# undef clear
783#endif
784
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200785 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200786IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200787{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200788 if (self->clear != NULL)
789 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200790 else
791 return 0;
792}
793
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200794 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200795IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200796{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200797 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200798}
799
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200800 static PyObject *
801IterIter(PyObject *self)
802{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +0200803 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200804 return self;
805}
Bram Moolenaardfa38d42013-05-15 13:38:47 +0200806
Bram Moolenaardb913952012-06-29 12:54:53 +0200807typedef struct pylinkedlist_S {
808 struct pylinkedlist_S *pll_next;
809 struct pylinkedlist_S *pll_prev;
810 PyObject *pll_obj;
811} pylinkedlist_T;
812
813static pylinkedlist_T *lastdict = NULL;
814static pylinkedlist_T *lastlist = NULL;
815
816 static void
817pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
818{
819 if (ref->pll_prev == NULL)
820 {
821 if (ref->pll_next == NULL)
822 {
823 *last = NULL;
824 return;
825 }
826 }
827 else
828 ref->pll_prev->pll_next = ref->pll_next;
829
830 if (ref->pll_next == NULL)
831 *last = ref->pll_prev;
832 else
833 ref->pll_next->pll_prev = ref->pll_prev;
834}
835
836 static void
837pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
838{
839 if (*last == NULL)
840 ref->pll_prev = NULL;
841 else
842 {
843 (*last)->pll_next = ref;
844 ref->pll_prev = *last;
845 }
846 ref->pll_next = NULL;
847 ref->pll_obj = self;
848 *last = ref;
849}
850
851static PyTypeObject DictionaryType;
852
853typedef struct
854{
855 PyObject_HEAD
856 dict_T *dict;
857 pylinkedlist_T ref;
858} DictionaryObject;
859
Bram Moolenaara9922d62013-05-30 13:01:18 +0200860static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
861
862#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
863
Bram Moolenaardb913952012-06-29 12:54:53 +0200864 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +0200865DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +0200866{
867 DictionaryObject *self;
868
Bram Moolenaara9922d62013-05-30 13:01:18 +0200869 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +0200870 if (self == NULL)
871 return NULL;
872 self->dict = dict;
873 ++dict->dv_refcount;
874
875 pyll_add((PyObject *)(self), &self->ref, &lastdict);
876
877 return (PyObject *)(self);
878}
879
Bram Moolenaara9922d62013-05-30 13:01:18 +0200880 static dict_T *
881py_dict_alloc()
882{
883 dict_T *r;
884
885 if (!(r = dict_alloc()))
886 {
887 PyErr_NoMemory();
888 return NULL;
889 }
890 ++r->dv_refcount;
891
892 return r;
893}
894
895 static PyObject *
896DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
897{
898 DictionaryObject *self;
899 dict_T *dict;
900
901 if (!(dict = py_dict_alloc()))
902 return NULL;
903
904 self = (DictionaryObject *) DictionaryNew(subtype, dict);
905
906 --dict->dv_refcount;
907
908 if (kwargs || PyTuple_Size(args))
909 {
910 PyObject *tmp;
911 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
912 {
913 Py_DECREF(self);
914 return NULL;
915 }
916
917 Py_DECREF(tmp);
918 }
919
920 return (PyObject *)(self);
921}
922
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200923 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200924DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200925{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200926 pyll_remove(&self->ref, &lastdict);
927 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200928
929 DESTRUCTOR_FINISH(self);
930}
931
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200932static char *DictionaryAttrs[] = {
933 "locked", "scope",
934 NULL
935};
936
937 static PyObject *
938DictionaryDir(PyObject *self)
939{
940 return ObjectDir(self, DictionaryAttrs);
941}
942
Bram Moolenaardb913952012-06-29 12:54:53 +0200943 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200944DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200945{
946 if (val == NULL)
947 {
Bram Moolenaara9922d62013-05-30 13:01:18 +0200948 PyErr_SetString(PyExc_AttributeError,
949 _("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +0200950 return -1;
951 }
952
953 if (strcmp(name, "locked") == 0)
954 {
Bram Moolenaard6e39182013-05-21 18:30:34 +0200955 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200956 {
Bram Moolenaara9922d62013-05-30 13:01:18 +0200957 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +0200958 return -1;
959 }
960 else
961 {
Bram Moolenaarb983f752013-05-15 16:11:50 +0200962 int istrue = PyObject_IsTrue(val);
963 if (istrue == -1)
964 return -1;
965 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +0200966 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200967 else
Bram Moolenaard6e39182013-05-21 18:30:34 +0200968 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200969 }
970 return 0;
971 }
972 else
973 {
Bram Moolenaara9922d62013-05-30 13:01:18 +0200974 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +0200975 return -1;
976 }
977}
978
979 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +0200980DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +0200981{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200982 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +0200983}
984
Bram Moolenaara9922d62013-05-30 13:01:18 +0200985#define DICT_FLAG_HAS_DEFAULT 0x01
986#define DICT_FLAG_POP 0x02
987#define DICT_FLAG_NONE_DEFAULT 0x04
988#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
989#define DICT_FLAG_RETURN_PAIR 0x10
990
Bram Moolenaardb913952012-06-29 12:54:53 +0200991 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +0200992_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +0200993{
Bram Moolenaara9922d62013-05-30 13:01:18 +0200994 PyObject *keyObject;
995 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
996 PyObject *r;
Bram Moolenaardb913952012-06-29 12:54:53 +0200997 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200998 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +0200999 dict_T *dict = self->dict;
1000 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001001 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001002
Bram Moolenaara9922d62013-05-30 13:01:18 +02001003 if (flags & DICT_FLAG_HAS_DEFAULT)
1004 {
1005 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1006 return NULL;
1007 }
1008 else
1009 keyObject = args;
1010
1011 if (flags & DICT_FLAG_RETURN_BOOL)
1012 defObject = Py_False;
1013
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001014 if (!(key = StringToChars(keyObject, &todecref)))
1015 return NULL;
1016
1017 if (*key == NUL)
1018 {
1019 RAISE_NO_EMPTY_KEYS;
1020 return NULL;
1021 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001022
Bram Moolenaara9922d62013-05-30 13:01:18 +02001023 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001024
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001025 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001026
Bram Moolenaara9922d62013-05-30 13:01:18 +02001027 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001028 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001029 if (defObject)
1030 {
1031 Py_INCREF(defObject);
1032 return defObject;
1033 }
1034 else
1035 {
1036 PyErr_SetObject(PyExc_KeyError, keyObject);
1037 return NULL;
1038 }
1039 }
1040 else if (flags & DICT_FLAG_RETURN_BOOL)
1041 {
1042 Py_INCREF(Py_True);
1043 return Py_True;
1044 }
1045
1046 di = dict_lookup(hi);
1047
1048 if (!(r = ConvertToPyObject(&di->di_tv)))
1049 return NULL;
1050
1051 if (flags & DICT_FLAG_POP)
1052 {
1053 if (dict->dv_lock)
1054 {
1055 PyErr_SetVim(_("dict is locked"));
1056 Py_DECREF(r);
1057 return NULL;
1058 }
1059
1060 hash_remove(&dict->dv_hashtab, hi);
1061 dictitem_free(di);
1062 }
1063
Bram Moolenaara9922d62013-05-30 13:01:18 +02001064 return r;
1065}
1066
1067 static PyObject *
1068DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1069{
1070 return _DictionaryItem(self, keyObject, 0);
1071}
1072
1073 static int
1074DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1075{
1076 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1077 int r;
1078
1079 r = (rObj == Py_True);
1080
1081 Py_DECREF(Py_True);
1082
1083 return r;
1084}
1085
1086typedef struct
1087{
1088 hashitem_T *ht_array;
1089 long_u ht_used;
1090 hashtab_T *ht;
1091 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001092 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001093} dictiterinfo_T;
1094
1095 static PyObject *
1096DictionaryIterNext(dictiterinfo_T **dii)
1097{
1098 PyObject *r;
1099
1100 if (!(*dii)->todo)
1101 return NULL;
1102
1103 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1104 (*dii)->ht->ht_used != (*dii)->ht_used)
1105 {
1106 PyErr_SetString(PyExc_RuntimeError,
1107 _("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001108 return NULL;
1109 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001110
Bram Moolenaara9922d62013-05-30 13:01:18 +02001111 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1112 ++((*dii)->hi);
1113
1114 --((*dii)->todo);
1115
1116 if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1117 return NULL;
1118
1119 return r;
1120}
1121
1122 static PyObject *
1123DictionaryIter(DictionaryObject *self)
1124{
1125 dictiterinfo_T *dii;
1126 hashtab_T *ht;
1127
1128 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1129 {
1130 PyErr_NoMemory();
1131 return NULL;
1132 }
1133
1134 ht = &self->dict->dv_hashtab;
1135 dii->ht_array = ht->ht_array;
1136 dii->ht_used = ht->ht_used;
1137 dii->ht = ht;
1138 dii->hi = dii->ht_array;
1139 dii->todo = dii->ht_used;
1140
1141 return IterNew(dii,
1142 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1143 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001144}
1145
1146 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001147DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001148{
1149 char_u *key;
1150 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001151 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001152 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001153 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001154
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001155 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001156 {
1157 PyErr_SetVim(_("dict is locked"));
1158 return -1;
1159 }
1160
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001161 if (!(key = StringToChars(keyObject, &todecref)))
1162 return -1;
1163 if (*key == NUL)
1164 {
1165 RAISE_NO_EMPTY_KEYS;
1166 return -1;
1167 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001168
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001169 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001170
1171 if (valObject == NULL)
1172 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001173 hashitem_T *hi;
1174
Bram Moolenaardb913952012-06-29 12:54:53 +02001175 if (di == NULL)
1176 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001177 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001178 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001179 return -1;
1180 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001181 hi = hash_find(&dict->dv_hashtab, di->di_key);
1182 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001183 dictitem_free(di);
1184 return 0;
1185 }
1186
1187 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02001188 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02001189
1190 if (di == NULL)
1191 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001192 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001193 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001194 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001195 PyErr_NoMemory();
1196 return -1;
1197 }
1198 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001199 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001200
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001201 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001202 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001203 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001204 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001205 dictitem_free(di);
Bram Moolenaardb913952012-06-29 12:54:53 +02001206 PyErr_SetVim(_("failed to add key to dictionary"));
1207 return -1;
1208 }
1209 }
1210 else
1211 clear_tv(&di->di_tv);
1212
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001213 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001214
1215 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001216 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001217 return 0;
1218}
1219
Bram Moolenaara9922d62013-05-30 13:01:18 +02001220typedef PyObject *(*hi_to_py)(hashitem_T *);
1221
Bram Moolenaardb913952012-06-29 12:54:53 +02001222 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001223DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001224{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001225 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001226 long_u todo = dict->dv_hashtab.ht_used;
1227 Py_ssize_t i = 0;
1228 PyObject *r;
1229 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001230 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001231
1232 r = PyList_New(todo);
1233 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1234 {
1235 if (!HASHITEM_EMPTY(hi))
1236 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001237 if (!(newObj = hiconvert(hi)))
1238 {
1239 Py_DECREF(r);
1240 return NULL;
1241 }
1242 if (PyList_SetItem(r, i, newObj))
1243 {
1244 Py_DECREF(r);
1245 Py_DECREF(newObj);
1246 return NULL;
1247 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001248 --todo;
1249 ++i;
1250 }
1251 }
1252 return r;
1253}
1254
Bram Moolenaara9922d62013-05-30 13:01:18 +02001255 static PyObject *
1256dict_key(hashitem_T *hi)
1257{
1258 return PyBytes_FromString((char *)(hi->hi_key));
1259}
1260
1261 static PyObject *
1262DictionaryListKeys(DictionaryObject *self)
1263{
1264 return DictionaryListObjects(self, dict_key);
1265}
1266
1267 static PyObject *
1268dict_val(hashitem_T *hi)
1269{
1270 dictitem_T *di;
1271
1272 di = dict_lookup(hi);
1273 return ConvertToPyObject(&di->di_tv);
1274}
1275
1276 static PyObject *
1277DictionaryListValues(DictionaryObject *self)
1278{
1279 return DictionaryListObjects(self, dict_val);
1280}
1281
1282 static PyObject *
1283dict_item(hashitem_T *hi)
1284{
1285 PyObject *keyObject;
1286 PyObject *valObject;
1287 PyObject *r;
1288
1289 if (!(keyObject = dict_key(hi)))
1290 return NULL;
1291
1292 if (!(valObject = dict_val(hi)))
1293 {
1294 Py_DECREF(keyObject);
1295 return NULL;
1296 }
1297
1298 r = Py_BuildValue("(OO)", keyObject, valObject);
1299
1300 Py_DECREF(keyObject);
1301 Py_DECREF(valObject);
1302
1303 return r;
1304}
1305
1306 static PyObject *
1307DictionaryListItems(DictionaryObject *self)
1308{
1309 return DictionaryListObjects(self, dict_item);
1310}
1311
1312 static PyObject *
1313DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1314{
1315 dict_T *dict = self->dict;
1316
1317 if (dict->dv_lock)
1318 {
1319 PyErr_SetVim(_("dict is locked"));
1320 return NULL;
1321 }
1322
1323 if (kwargs)
1324 {
1325 typval_T tv;
1326
1327 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1328 return NULL;
1329
1330 VimTryStart();
1331 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1332 clear_tv(&tv);
1333 if (VimTryEnd())
1334 return NULL;
1335 }
1336 else
1337 {
1338 PyObject *object;
1339
1340 if (!PyArg_Parse(args, "(O)", &object))
1341 return NULL;
1342
1343 if (PyObject_HasAttrString(object, "keys"))
1344 return DictionaryUpdate(self, NULL, object);
1345 else
1346 {
1347 PyObject *iterator;
1348 PyObject *item;
1349
1350 if (!(iterator = PyObject_GetIter(object)))
1351 return NULL;
1352
1353 while ((item = PyIter_Next(iterator)))
1354 {
1355 PyObject *fast;
1356 PyObject *keyObject;
1357 PyObject *valObject;
1358 PyObject *todecref;
1359 char_u *key;
1360 dictitem_T *di;
1361
1362 if (!(fast = PySequence_Fast(item, "")))
1363 {
1364 Py_DECREF(iterator);
1365 Py_DECREF(item);
1366 return NULL;
1367 }
1368
1369 Py_DECREF(item);
1370
1371 if (PySequence_Fast_GET_SIZE(fast) != 2)
1372 {
1373 Py_DECREF(iterator);
1374 Py_DECREF(fast);
1375 PyErr_SetString(PyExc_ValueError,
1376 _("expected sequence element of size 2"));
1377 return NULL;
1378 }
1379
1380 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1381
1382 if (!(key = StringToChars(keyObject, &todecref)))
1383 {
1384 Py_DECREF(iterator);
1385 Py_DECREF(fast);
1386 return NULL;
1387 }
1388
1389 di = dictitem_alloc(key);
1390
1391 Py_XDECREF(todecref);
1392
1393 if (di == NULL)
1394 {
1395 Py_DECREF(fast);
1396 Py_DECREF(iterator);
1397 PyErr_NoMemory();
1398 return NULL;
1399 }
1400 di->di_tv.v_lock = 0;
1401 di->di_tv.v_type = VAR_UNKNOWN;
1402
1403 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1404
1405 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1406 {
1407 Py_DECREF(iterator);
1408 Py_DECREF(fast);
1409 dictitem_free(di);
1410 return NULL;
1411 }
1412
1413 Py_DECREF(fast);
1414
1415 if (dict_add(dict, di) == FAIL)
1416 {
1417 Py_DECREF(iterator);
1418 dictitem_free(di);
1419 PyErr_SetVim(_("failed to add key to dictionary"));
1420 return NULL;
1421 }
1422 }
1423
1424 Py_DECREF(iterator);
1425
1426 /* Iterator may have finished due to an exception */
1427 if (PyErr_Occurred())
1428 return NULL;
1429 }
1430 }
1431 Py_INCREF(Py_None);
1432 return Py_None;
1433}
1434
1435 static PyObject *
1436DictionaryGet(DictionaryObject *self, PyObject *args)
1437{
1438 return _DictionaryItem(self, args,
1439 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1440}
1441
1442 static PyObject *
1443DictionaryPop(DictionaryObject *self, PyObject *args)
1444{
1445 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1446}
1447
1448 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001449DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001450{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001451 hashitem_T *hi;
1452 PyObject *r;
1453 PyObject *valObject;
1454 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001455
Bram Moolenaarde71b562013-06-02 17:41:54 +02001456 if (self->dict->dv_hashtab.ht_used == 0)
1457 {
1458 PyErr_SetNone(PyExc_KeyError);
1459 return NULL;
1460 }
1461
1462 hi = self->dict->dv_hashtab.ht_array;
1463 while (HASHITEM_EMPTY(hi))
1464 ++hi;
1465
1466 di = dict_lookup(hi);
1467
1468 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001469 return NULL;
1470
Bram Moolenaarde71b562013-06-02 17:41:54 +02001471 if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
1472 {
1473 Py_DECREF(valObject);
1474 return NULL;
1475 }
1476
1477 hash_remove(&self->dict->dv_hashtab, hi);
1478 dictitem_free(di);
1479
1480 return r;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001481}
1482
1483 static PyObject *
1484DictionaryHasKey(DictionaryObject *self, PyObject *args)
1485{
1486 PyObject *keyObject;
1487
1488 if (!PyArg_ParseTuple(args, "O", &keyObject))
1489 return NULL;
1490
1491 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1492}
1493
1494static PySequenceMethods DictionaryAsSeq = {
1495 0, /* sq_length */
1496 0, /* sq_concat */
1497 0, /* sq_repeat */
1498 0, /* sq_item */
1499 0, /* sq_slice */
1500 0, /* sq_ass_item */
1501 0, /* sq_ass_slice */
1502 (objobjproc) DictionaryContains, /* sq_contains */
1503 0, /* sq_inplace_concat */
1504 0, /* sq_inplace_repeat */
1505};
1506
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001507static PyMappingMethods DictionaryAsMapping = {
1508 (lenfunc) DictionaryLength,
1509 (binaryfunc) DictionaryItem,
1510 (objobjargproc) DictionaryAssItem,
1511};
1512
Bram Moolenaardb913952012-06-29 12:54:53 +02001513static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001514 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001515 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
1516 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
1517 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
1518 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
1519 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02001520 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001521 {"has_key", (PyCFunction)DictionaryHasKey, METH_VARARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001522 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1523 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001524};
1525
1526static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001527static PySequenceMethods ListAsSeq;
1528static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001529
1530typedef struct
1531{
1532 PyObject_HEAD
1533 list_T *list;
1534 pylinkedlist_T ref;
1535} ListObject;
1536
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001537#define NEW_LIST(list) ListNew(&ListType, list)
1538
Bram Moolenaardb913952012-06-29 12:54:53 +02001539 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001540ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02001541{
1542 ListObject *self;
1543
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001544 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001545 if (self == NULL)
1546 return NULL;
1547 self->list = list;
1548 ++list->lv_refcount;
1549
1550 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1551
1552 return (PyObject *)(self);
1553}
1554
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001555 static list_T *
1556py_list_alloc()
1557{
1558 list_T *r;
1559
1560 if (!(r = list_alloc()))
1561 {
1562 PyErr_NoMemory();
1563 return NULL;
1564 }
1565 ++r->lv_refcount;
1566
1567 return r;
1568}
1569
1570 static int
1571list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
1572{
1573 PyObject *iterator;
1574 PyObject *item;
1575 listitem_T *li;
1576
1577 if (!(iterator = PyObject_GetIter(obj)))
1578 return -1;
1579
1580 while ((item = PyIter_Next(iterator)))
1581 {
1582 if (!(li = listitem_alloc()))
1583 {
1584 PyErr_NoMemory();
1585 Py_DECREF(item);
1586 Py_DECREF(iterator);
1587 return -1;
1588 }
1589 li->li_tv.v_lock = 0;
1590 li->li_tv.v_type = VAR_UNKNOWN;
1591
1592 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
1593 {
1594 Py_DECREF(item);
1595 Py_DECREF(iterator);
1596 listitem_free(li);
1597 return -1;
1598 }
1599
1600 Py_DECREF(item);
1601
1602 list_append(l, li);
1603 }
1604
1605 Py_DECREF(iterator);
1606
1607 /* Iterator may have finished due to an exception */
1608 if (PyErr_Occurred())
1609 return -1;
1610
1611 return 0;
1612}
1613
1614 static PyObject *
1615ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1616{
1617 list_T *list;
1618 PyObject *obj = NULL;
1619
1620 if (kwargs)
1621 {
1622 PyErr_SetString(PyExc_TypeError,
1623 _("list constructor does not accept keyword arguments"));
1624 return NULL;
1625 }
1626
1627 if (!PyArg_ParseTuple(args, "|O", &obj))
1628 return NULL;
1629
1630 if (!(list = py_list_alloc()))
1631 return NULL;
1632
1633 if (obj)
1634 {
1635 PyObject *lookup_dict;
1636
1637 if (!(lookup_dict = PyDict_New()))
1638 {
1639 list_unref(list);
1640 return NULL;
1641 }
1642
1643 if (list_py_concat(list, obj, lookup_dict) == -1)
1644 {
1645 Py_DECREF(lookup_dict);
1646 list_unref(list);
1647 return NULL;
1648 }
1649
1650 Py_DECREF(lookup_dict);
1651 }
1652
1653 return ListNew(subtype, list);
1654}
1655
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001656 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001657ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001658{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001659 pyll_remove(&self->ref, &lastlist);
1660 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001661
1662 DESTRUCTOR_FINISH(self);
1663}
1664
Bram Moolenaardb913952012-06-29 12:54:53 +02001665 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001666ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001667{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001668 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02001669}
1670
1671 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001672ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02001673{
1674 listitem_T *li;
1675
Bram Moolenaard6e39182013-05-21 18:30:34 +02001676 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02001677 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001678 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001679 return NULL;
1680 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02001681 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02001682 if (li == NULL)
1683 {
1684 PyErr_SetVim(_("internal error: failed to get vim list item"));
1685 return NULL;
1686 }
1687 return ConvertToPyObject(&li->li_tv);
1688}
1689
1690#define PROC_RANGE \
1691 if (last < 0) {\
1692 if (last < -size) \
1693 last = 0; \
1694 else \
1695 last += size; \
1696 } \
1697 if (first < 0) \
1698 first = 0; \
1699 if (first > size) \
1700 first = size; \
1701 if (last > size) \
1702 last = size;
1703
1704 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001705ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02001706{
1707 PyInt i;
1708 PyInt size = ListLength(self);
1709 PyInt n;
1710 PyObject *list;
1711 int reversed = 0;
1712
1713 PROC_RANGE
1714 if (first >= last)
1715 first = last;
1716
1717 n = last-first;
1718 list = PyList_New(n);
1719 if (list == NULL)
1720 return NULL;
1721
1722 for (i = 0; i < n; ++i)
1723 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02001724 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02001725 if (item == NULL)
1726 {
1727 Py_DECREF(list);
1728 return NULL;
1729 }
1730
1731 if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item)))
1732 {
1733 Py_DECREF(item);
1734 Py_DECREF(list);
1735 return NULL;
1736 }
1737 }
1738
1739 return list;
1740}
1741
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001742typedef struct
1743{
1744 listwatch_T lw;
1745 list_T *list;
1746} listiterinfo_T;
1747
1748 static void
1749ListIterDestruct(listiterinfo_T *lii)
1750{
1751 list_rem_watch(lii->list, &lii->lw);
1752 PyMem_Free(lii);
1753}
1754
1755 static PyObject *
1756ListIterNext(listiterinfo_T **lii)
1757{
1758 PyObject *r;
1759
1760 if (!((*lii)->lw.lw_item))
1761 return NULL;
1762
1763 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
1764 return NULL;
1765
1766 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
1767
1768 return r;
1769}
1770
1771 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001772ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001773{
1774 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001775 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001776
1777 if (!(lii = PyMem_New(listiterinfo_T, 1)))
1778 {
1779 PyErr_NoMemory();
1780 return NULL;
1781 }
1782
1783 list_add_watch(l, &lii->lw);
1784 lii->lw.lw_item = l->lv_first;
1785 lii->list = l;
1786
1787 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001788 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
1789 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001790}
1791
Bram Moolenaardb913952012-06-29 12:54:53 +02001792 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001793ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001794{
1795 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001796 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001797 listitem_T *li;
1798 Py_ssize_t length = ListLength(self);
1799
1800 if (l->lv_lock)
1801 {
1802 PyErr_SetVim(_("list is locked"));
1803 return -1;
1804 }
1805 if (index>length || (index==length && obj==NULL))
1806 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001807 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001808 return -1;
1809 }
1810
1811 if (obj == NULL)
1812 {
1813 li = list_find(l, (long) index);
1814 list_remove(l, li, li);
1815 clear_tv(&li->li_tv);
1816 vim_free(li);
1817 return 0;
1818 }
1819
1820 if (ConvertFromPyObject(obj, &tv) == -1)
1821 return -1;
1822
1823 if (index == length)
1824 {
1825 if (list_append_tv(l, &tv) == FAIL)
1826 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001827 clear_tv(&tv);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001828 PyErr_SetVim(_("failed to add item to list"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001829 return -1;
1830 }
1831 }
1832 else
1833 {
1834 li = list_find(l, (long) index);
1835 clear_tv(&li->li_tv);
1836 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001837 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001838 }
1839 return 0;
1840}
1841
1842 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001843ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001844{
1845 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001846 PyObject *iterator;
1847 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02001848 listitem_T *li;
1849 listitem_T *next;
1850 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001851 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001852 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02001853
1854 if (l->lv_lock)
1855 {
1856 PyErr_SetVim(_("list is locked"));
1857 return -1;
1858 }
1859
1860 PROC_RANGE
1861
1862 if (first == size)
1863 li = NULL;
1864 else
1865 {
1866 li = list_find(l, (long) first);
1867 if (li == NULL)
1868 {
1869 PyErr_SetVim(_("internal error: no vim list item"));
1870 return -1;
1871 }
1872 if (last > first)
1873 {
1874 i = last - first;
1875 while (i-- && li != NULL)
1876 {
1877 next = li->li_next;
1878 listitem_remove(l, li);
1879 li = next;
1880 }
1881 }
1882 }
1883
1884 if (obj == NULL)
1885 return 0;
1886
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001887 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001888 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02001889
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001890 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001891 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001892 if (ConvertFromPyObject(item, &v) == -1)
1893 {
1894 Py_DECREF(iterator);
1895 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02001896 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001897 }
1898 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02001899 if (list_insert_tv(l, &v, li) == FAIL)
1900 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001901 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001902 PyErr_SetVim(_("internal error: failed to add item to list"));
1903 return -1;
1904 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001905 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001906 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001907 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02001908 return 0;
1909}
1910
1911 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001912ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001913{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001914 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001915 PyObject *lookup_dict;
1916
1917 if (l->lv_lock)
1918 {
1919 PyErr_SetVim(_("list is locked"));
1920 return NULL;
1921 }
1922
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001923 if (!(lookup_dict = PyDict_New()))
1924 return NULL;
1925
Bram Moolenaardb913952012-06-29 12:54:53 +02001926 if (list_py_concat(l, obj, lookup_dict) == -1)
1927 {
1928 Py_DECREF(lookup_dict);
1929 return NULL;
1930 }
1931 Py_DECREF(lookup_dict);
1932
1933 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02001934 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02001935}
1936
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001937static char *ListAttrs[] = {
1938 "locked",
1939 NULL
1940};
1941
1942 static PyObject *
1943ListDir(PyObject *self)
1944{
1945 return ObjectDir(self, ListAttrs);
1946}
1947
Bram Moolenaar66b79852012-09-21 14:00:35 +02001948 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001949ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001950{
1951 if (val == NULL)
1952 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001953 PyErr_SetString(PyExc_AttributeError,
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001954 _("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001955 return -1;
1956 }
1957
1958 if (strcmp(name, "locked") == 0)
1959 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001960 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001961 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001962 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001963 return -1;
1964 }
1965 else
1966 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001967 int istrue = PyObject_IsTrue(val);
1968 if (istrue == -1)
1969 return -1;
1970 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001971 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001972 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001973 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001974 }
1975 return 0;
1976 }
1977 else
1978 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001979 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001980 return -1;
1981 }
1982}
1983
Bram Moolenaardb913952012-06-29 12:54:53 +02001984static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001985 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
1986 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
1987 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001988};
1989
1990typedef struct
1991{
1992 PyObject_HEAD
1993 char_u *name;
1994} FunctionObject;
1995
1996static PyTypeObject FunctionType;
1997
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02001998#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
1999
Bram Moolenaardb913952012-06-29 12:54:53 +02002000 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002001FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002002{
2003 FunctionObject *self;
2004
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002005 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2006
Bram Moolenaardb913952012-06-29 12:54:53 +02002007 if (self == NULL)
2008 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002009
2010 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002011 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002012 if (!translated_function_exists(name))
2013 {
2014 PyErr_SetString(PyExc_ValueError,
2015 _("unnamed function does not exist"));
2016 return NULL;
2017 }
2018 self->name = vim_strsave(name);
2019 func_ref(self->name);
2020 }
2021 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002022 if ((self->name = get_expanded_name(name,
2023 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2024 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002025 {
Bram Moolenaar018acca2013-05-30 13:37:28 +02002026 PyErr_SetString(PyExc_ValueError, _("function does not exist"));
2027 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002028 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002029
2030 return (PyObject *)(self);
2031}
2032
2033 static PyObject *
2034FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2035{
2036 PyObject *self;
2037 char_u *name;
2038
2039 if (kwargs)
2040 {
2041 PyErr_SetString(PyExc_TypeError,
2042 _("function constructor does not accept keyword arguments"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002043 return NULL;
2044 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002045
2046 if (!PyArg_ParseTuple(args, "s", &name))
2047 return NULL;
2048
2049 self = FunctionNew(subtype, name);
2050
2051 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002052}
2053
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002054 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002055FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002056{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002057 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002058 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002059
2060 DESTRUCTOR_FINISH(self);
2061}
2062
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002063static char *FunctionAttrs[] = {
2064 "softspace",
2065 NULL
2066};
2067
2068 static PyObject *
2069FunctionDir(PyObject *self)
2070{
2071 return ObjectDir(self, FunctionAttrs);
2072}
2073
Bram Moolenaardb913952012-06-29 12:54:53 +02002074 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002075FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002076{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002077 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002078 typval_T args;
2079 typval_T selfdicttv;
2080 typval_T rettv;
2081 dict_T *selfdict = NULL;
2082 PyObject *selfdictObject;
2083 PyObject *result;
2084 int error;
2085
2086 if (ConvertFromPyObject(argsObject, &args) == -1)
2087 return NULL;
2088
2089 if (kwargs != NULL)
2090 {
2091 selfdictObject = PyDict_GetItemString(kwargs, "self");
2092 if (selfdictObject != NULL)
2093 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002094 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002095 {
2096 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002097 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002098 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002099 selfdict = selfdicttv.vval.v_dict;
2100 }
2101 }
2102
Bram Moolenaar71700b82013-05-15 17:49:05 +02002103 Py_BEGIN_ALLOW_THREADS
2104 Python_Lock_Vim();
2105
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002106 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002107 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002108
2109 Python_Release_Vim();
2110 Py_END_ALLOW_THREADS
2111
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002112 if (VimTryEnd())
2113 result = NULL;
2114 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002115 {
2116 result = NULL;
2117 PyErr_SetVim(_("failed to run function"));
2118 }
2119 else
2120 result = ConvertToPyObject(&rettv);
2121
Bram Moolenaardb913952012-06-29 12:54:53 +02002122 clear_tv(&args);
2123 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002124 if (selfdict != NULL)
2125 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002126
2127 return result;
2128}
2129
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002130 static PyObject *
2131FunctionRepr(FunctionObject *self)
2132{
2133 return PyString_FromFormat("<vim.Function '%s'>", self->name);
2134}
2135
Bram Moolenaardb913952012-06-29 12:54:53 +02002136static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002137 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2138 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002139};
2140
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002141/*
2142 * Options object
2143 */
2144
2145static PyTypeObject OptionsType;
2146
2147typedef int (*checkfun)(void *);
2148
2149typedef struct
2150{
2151 PyObject_HEAD
2152 int opt_type;
2153 void *from;
2154 checkfun Check;
2155 PyObject *fromObj;
2156} OptionsObject;
2157
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002158 static int
2159dummy_check(void *arg UNUSED)
2160{
2161 return 0;
2162}
2163
2164 static PyObject *
2165OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2166{
2167 OptionsObject *self;
2168
Bram Moolenaar774267b2013-05-21 20:51:59 +02002169 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002170 if (self == NULL)
2171 return NULL;
2172
2173 self->opt_type = opt_type;
2174 self->from = from;
2175 self->Check = Check;
2176 self->fromObj = fromObj;
2177 if (fromObj)
2178 Py_INCREF(fromObj);
2179
2180 return (PyObject *)(self);
2181}
2182
2183 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002184OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002185{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002186 PyObject_GC_UnTrack((void *)(self));
2187 Py_XDECREF(self->fromObj);
2188 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002189}
2190
2191 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002192OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002193{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002194 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002195 return 0;
2196}
2197
2198 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002199OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002200{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002201 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002202 return 0;
2203}
2204
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002205 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002206OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002207{
2208 char_u *key;
2209 int flags;
2210 long numval;
2211 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002212 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002213
Bram Moolenaard6e39182013-05-21 18:30:34 +02002214 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002215 return NULL;
2216
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002217 if (!(key = StringToChars(keyObject, &todecref)))
2218 return NULL;
2219 if (*key == NUL)
2220 {
2221 RAISE_NO_EMPTY_KEYS;
2222 return NULL;
2223 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002224
2225 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002226 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002227
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002228 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002229
2230 if (flags == 0)
2231 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002232 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002233 return NULL;
2234 }
2235
2236 if (flags & SOPT_UNSET)
2237 {
2238 Py_INCREF(Py_None);
2239 return Py_None;
2240 }
2241 else if (flags & SOPT_BOOL)
2242 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002243 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002244 r = numval ? Py_True : Py_False;
2245 Py_INCREF(r);
2246 return r;
2247 }
2248 else if (flags & SOPT_NUM)
2249 return PyInt_FromLong(numval);
2250 else if (flags & SOPT_STRING)
2251 {
2252 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002253 {
2254 PyObject *r = PyBytes_FromString((char *) stringval);
2255 vim_free(stringval);
2256 return r;
2257 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002258 else
2259 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002260 PyErr_SetString(PyExc_RuntimeError,
2261 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002262 return NULL;
2263 }
2264 }
2265 else
2266 {
2267 PyErr_SetVim("Internal error: unknown option type. Should not happen");
2268 return NULL;
2269 }
2270}
2271
2272 static int
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002273set_option_value_err(key, numval, stringval, opt_flags)
2274 char_u *key;
2275 int numval;
2276 char_u *stringval;
2277 int opt_flags;
2278{
2279 char_u *errmsg;
2280
2281 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2282 {
2283 if (VimTryEnd())
2284 return FAIL;
2285 PyErr_SetVim((char *)errmsg);
2286 return FAIL;
2287 }
2288 return OK;
2289}
2290
2291 static int
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002292set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
2293 char_u *key;
2294 int numval;
2295 char_u *stringval;
2296 int opt_flags;
2297 int opt_type;
2298 void *from;
2299{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002300 win_T *save_curwin = NULL;
2301 tabpage_T *save_curtab = NULL;
2302 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002303 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002304
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002305 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002306 switch (opt_type)
2307 {
2308 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002309 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
2310 win_find_tabpage((win_T *)from)) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002311 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002312 if (VimTryEnd())
2313 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002314 PyErr_SetVim("Problem while switching windows.");
2315 return -1;
2316 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002317 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002318 restore_win(save_curwin, save_curtab);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002319 if (r == FAIL)
2320 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002321 break;
2322 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002323 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002324 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002325 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002326 if (r == FAIL)
2327 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002328 break;
2329 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002330 r = set_option_value_err(key, numval, stringval, opt_flags);
2331 if (r == FAIL)
2332 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002333 break;
2334 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002335 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002336}
2337
2338 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002339OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002340{
2341 char_u *key;
2342 int flags;
2343 int opt_flags;
2344 int r = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002345 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002346
Bram Moolenaard6e39182013-05-21 18:30:34 +02002347 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002348 return -1;
2349
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002350 if (!(key = StringToChars(keyObject, &todecref)))
2351 return -1;
2352 if (*key == NUL)
2353 {
2354 RAISE_NO_EMPTY_KEYS;
2355 return -1;
2356 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002357
2358 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002359 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002360
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002361 if (flags == 0)
2362 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002363 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002364 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002365 return -1;
2366 }
2367
2368 if (valObject == NULL)
2369 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002370 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002371 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002372 PyErr_SetString(PyExc_ValueError,
2373 _("unable to unset global option"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002374 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002375 return -1;
2376 }
2377 else if (!(flags & SOPT_GLOBAL))
2378 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002379 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
2380 "without global value"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002381 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002382 return -1;
2383 }
2384 else
2385 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002386 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002387 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002388 return 0;
2389 }
2390 }
2391
Bram Moolenaard6e39182013-05-21 18:30:34 +02002392 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002393
2394 if (flags & SOPT_BOOL)
2395 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002396 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002397
Bram Moolenaarb983f752013-05-15 16:11:50 +02002398 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002399 r = -1;
2400 else
2401 r = set_option_value_for(key, istrue, NULL,
2402 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002403 }
2404 else if (flags & SOPT_NUM)
2405 {
2406 int val;
2407
2408#if PY_MAJOR_VERSION < 3
2409 if (PyInt_Check(valObject))
2410 val = PyInt_AsLong(valObject);
2411 else
2412#endif
2413 if (PyLong_Check(valObject))
2414 val = PyLong_AsLong(valObject);
2415 else
2416 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002417 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002418 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002419 return -1;
2420 }
2421
2422 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002423 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002424 }
2425 else
2426 {
2427 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002428 PyObject *todecref;
2429
2430 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002431 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002432 r = set_option_value_for(key, 0, val, opt_flags,
2433 self->opt_type, self->from);
2434 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002435 }
2436 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002437 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002438 }
2439
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002440 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002441
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002442 return r;
2443}
2444
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002445static PyMappingMethods OptionsAsMapping = {
2446 (lenfunc) NULL,
2447 (binaryfunc) OptionsItem,
2448 (objobjargproc) OptionsAssItem,
2449};
2450
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002451/* Tabpage object
2452 */
2453
2454typedef struct
2455{
2456 PyObject_HEAD
2457 tabpage_T *tab;
2458} TabPageObject;
2459
2460static PyObject *WinListNew(TabPageObject *tabObject);
2461
2462static PyTypeObject TabPageType;
2463
2464 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002465CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002466{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002467 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002468 {
2469 PyErr_SetVim(_("attempt to refer to deleted tab page"));
2470 return -1;
2471 }
2472
2473 return 0;
2474}
2475
2476 static PyObject *
2477TabPageNew(tabpage_T *tab)
2478{
2479 TabPageObject *self;
2480
2481 if (TAB_PYTHON_REF(tab))
2482 {
2483 self = TAB_PYTHON_REF(tab);
2484 Py_INCREF(self);
2485 }
2486 else
2487 {
2488 self = PyObject_NEW(TabPageObject, &TabPageType);
2489 if (self == NULL)
2490 return NULL;
2491 self->tab = tab;
2492 TAB_PYTHON_REF(tab) = self;
2493 }
2494
2495 return (PyObject *)(self);
2496}
2497
2498 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002499TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002500{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002501 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
2502 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002503
2504 DESTRUCTOR_FINISH(self);
2505}
2506
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002507static char *TabPageAttrs[] = {
2508 "windows", "number", "vars", "window", "valid",
2509 NULL
2510};
2511
2512 static PyObject *
2513TabPageDir(PyObject *self)
2514{
2515 return ObjectDir(self, TabPageAttrs);
2516}
2517
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002518 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002519TabPageAttrValid(TabPageObject *self, char *name)
2520{
2521 PyObject *r;
2522
2523 if (strcmp(name, "valid") != 0)
2524 return NULL;
2525
2526 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
2527 Py_INCREF(r);
2528 return r;
2529}
2530
2531 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002532TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002533{
2534 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002535 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002536 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002537 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002538 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002539 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002540 else if (strcmp(name, "window") == 0)
2541 {
2542 /* For current tab window.c does not bother to set or update tp_curwin
2543 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002544 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002545 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002546 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002547 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002548 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002549 else if (strcmp(name, "__members__") == 0)
2550 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002551 return NULL;
2552}
2553
2554 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002555TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002556{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002557 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002558 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002559 else
2560 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002561 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002562
2563 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002564 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2565 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002566 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002567 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002568 }
2569}
2570
2571static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002572 /* name, function, calling, documentation */
2573 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2574 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002575};
2576
2577/*
2578 * Window list object
2579 */
2580
2581static PyTypeObject TabListType;
2582static PySequenceMethods TabListAsSeq;
2583
2584typedef struct
2585{
2586 PyObject_HEAD
2587} TabListObject;
2588
2589 static PyInt
2590TabListLength(PyObject *self UNUSED)
2591{
2592 tabpage_T *tp = first_tabpage;
2593 PyInt n = 0;
2594
2595 while (tp != NULL)
2596 {
2597 ++n;
2598 tp = tp->tp_next;
2599 }
2600
2601 return n;
2602}
2603
2604 static PyObject *
2605TabListItem(PyObject *self UNUSED, PyInt n)
2606{
2607 tabpage_T *tp;
2608
2609 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
2610 if (n == 0)
2611 return TabPageNew(tp);
2612
2613 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
2614 return NULL;
2615}
2616
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002617/* Window object
2618 */
2619
2620typedef struct
2621{
2622 PyObject_HEAD
2623 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002624 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002625} WindowObject;
2626
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002627static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002628
2629 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002630CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002631{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002632 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002633 {
2634 PyErr_SetVim(_("attempt to refer to deleted window"));
2635 return -1;
2636 }
2637
2638 return 0;
2639}
2640
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002641 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002642WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02002643{
2644 /* We need to handle deletion of windows underneath us.
2645 * If we add a "w_python*_ref" field to the win_T structure,
2646 * then we can get at it in win_free() in vim. We then
2647 * need to create only ONE Python object per window - if
2648 * we try to create a second, just INCREF the existing one
2649 * and return it. The (single) Python object referring to
2650 * the window is stored in "w_python*_ref".
2651 * On a win_free() we set the Python object's win_T* field
2652 * to an invalid value. We trap all uses of a window
2653 * object, and reject them if the win_T* field is invalid.
2654 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002655 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02002656 * w_python_ref and w_python3_ref fields respectively.
2657 */
2658
2659 WindowObject *self;
2660
2661 if (WIN_PYTHON_REF(win))
2662 {
2663 self = WIN_PYTHON_REF(win);
2664 Py_INCREF(self);
2665 }
2666 else
2667 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02002668 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02002669 if (self == NULL)
2670 return NULL;
2671 self->win = win;
2672 WIN_PYTHON_REF(win) = self;
2673 }
2674
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002675 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
2676
Bram Moolenaar971db462013-05-12 18:44:48 +02002677 return (PyObject *)(self);
2678}
2679
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002680 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002681WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002682{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002683 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02002684 if (self->win && self->win != INVALID_WINDOW_VALUE)
2685 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02002686 Py_XDECREF(((PyObject *)(self->tabObject)));
2687 PyObject_GC_Del((void *)(self));
2688}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002689
Bram Moolenaar774267b2013-05-21 20:51:59 +02002690 static int
2691WindowTraverse(WindowObject *self, visitproc visit, void *arg)
2692{
2693 Py_VISIT(((PyObject *)(self->tabObject)));
2694 return 0;
2695}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002696
Bram Moolenaar774267b2013-05-21 20:51:59 +02002697 static int
2698WindowClear(WindowObject *self)
2699{
2700 Py_CLEAR(self->tabObject);
2701 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002702}
2703
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002704 static win_T *
2705get_firstwin(TabPageObject *tabObject)
2706{
2707 if (tabObject)
2708 {
2709 if (CheckTabPage(tabObject))
2710 return NULL;
2711 /* For current tab window.c does not bother to set or update tp_firstwin
2712 */
2713 else if (tabObject->tab == curtab)
2714 return firstwin;
2715 else
2716 return tabObject->tab->tp_firstwin;
2717 }
2718 else
2719 return firstwin;
2720}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002721static char *WindowAttrs[] = {
2722 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
2723 "tabpage", "valid",
2724 NULL
2725};
2726
2727 static PyObject *
2728WindowDir(PyObject *self)
2729{
2730 return ObjectDir(self, WindowAttrs);
2731}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002732
Bram Moolenaar971db462013-05-12 18:44:48 +02002733 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002734WindowAttrValid(WindowObject *self, char *name)
2735{
2736 PyObject *r;
2737
2738 if (strcmp(name, "valid") != 0)
2739 return NULL;
2740
2741 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
2742 Py_INCREF(r);
2743 return r;
2744}
2745
2746 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002747WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002748{
2749 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002750 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002751 else if (strcmp(name, "cursor") == 0)
2752 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002753 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002754
2755 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
2756 }
2757 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002758 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002759#ifdef FEAT_WINDOWS
2760 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002761 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002762#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002763#ifdef FEAT_VERTSPLIT
2764 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002765 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002766 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002767 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002768#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02002769 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002770 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002771 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002772 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
2773 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02002774 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002775 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002776 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002777 return NULL;
2778 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002779 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002780 }
2781 else if (strcmp(name, "tabpage") == 0)
2782 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002783 Py_INCREF(self->tabObject);
2784 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002785 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002786 else if (strcmp(name, "__members__") == 0)
2787 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002788 else
2789 return NULL;
2790}
2791
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002792 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002793WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002794{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002795 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002796 return -1;
2797
2798 if (strcmp(name, "buffer") == 0)
2799 {
2800 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
2801 return -1;
2802 }
2803 else if (strcmp(name, "cursor") == 0)
2804 {
2805 long lnum;
2806 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002807
2808 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
2809 return -1;
2810
Bram Moolenaard6e39182013-05-21 18:30:34 +02002811 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002812 {
2813 PyErr_SetVim(_("cursor position outside buffer"));
2814 return -1;
2815 }
2816
2817 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002818 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002819 return -1;
2820
Bram Moolenaard6e39182013-05-21 18:30:34 +02002821 self->win->w_cursor.lnum = lnum;
2822 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002823#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02002824 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002825#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002826 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002827 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002828
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002829 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002830 return 0;
2831 }
2832 else if (strcmp(name, "height") == 0)
2833 {
2834 int height;
2835 win_T *savewin;
2836
2837 if (!PyArg_Parse(val, "i", &height))
2838 return -1;
2839
2840#ifdef FEAT_GUI
2841 need_mouse_correct = TRUE;
2842#endif
2843 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002844 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002845
2846 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002847 win_setheight(height);
2848 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002849 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002850 return -1;
2851
2852 return 0;
2853 }
2854#ifdef FEAT_VERTSPLIT
2855 else if (strcmp(name, "width") == 0)
2856 {
2857 int width;
2858 win_T *savewin;
2859
2860 if (!PyArg_Parse(val, "i", &width))
2861 return -1;
2862
2863#ifdef FEAT_GUI
2864 need_mouse_correct = TRUE;
2865#endif
2866 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002867 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002868
2869 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002870 win_setwidth(width);
2871 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002872 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002873 return -1;
2874
2875 return 0;
2876 }
2877#endif
2878 else
2879 {
2880 PyErr_SetString(PyExc_AttributeError, name);
2881 return -1;
2882 }
2883}
2884
2885 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002886WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002887{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002888 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002889 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002890 else
2891 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002892 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002893
Bram Moolenaar6d216452013-05-12 19:00:41 +02002894 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002895 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002896 (self));
2897 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002898 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002899 }
2900}
2901
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002902static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002903 /* name, function, calling, documentation */
2904 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
2905 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002906};
2907
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002908/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002909 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002910 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002911
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002912static PyTypeObject WinListType;
2913static PySequenceMethods WinListAsSeq;
2914
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002915typedef struct
2916{
2917 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002918 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002919} WinListObject;
2920
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002921 static PyObject *
2922WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002923{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002924 WinListObject *self;
2925
2926 self = PyObject_NEW(WinListObject, &WinListType);
2927 self->tabObject = tabObject;
2928 Py_INCREF(tabObject);
2929
2930 return (PyObject *)(self);
2931}
2932
2933 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002934WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002935{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002936 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002937
2938 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02002939 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002940 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02002941 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002942
2943 DESTRUCTOR_FINISH(self);
2944}
2945
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002946 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002947WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002948{
2949 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002950 PyInt n = 0;
2951
Bram Moolenaard6e39182013-05-21 18:30:34 +02002952 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002953 return -1;
2954
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002955 while (w != NULL)
2956 {
2957 ++n;
2958 w = W_NEXT(w);
2959 }
2960
2961 return n;
2962}
2963
2964 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002965WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002966{
2967 win_T *w;
2968
Bram Moolenaard6e39182013-05-21 18:30:34 +02002969 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002970 return NULL;
2971
2972 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002973 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002974 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002975
2976 PyErr_SetString(PyExc_IndexError, _("no such window"));
2977 return NULL;
2978}
2979
2980/* Convert a Python string into a Vim line.
2981 *
2982 * The result is in allocated memory. All internal nulls are replaced by
2983 * newline characters. It is an error for the string to contain newline
2984 * characters.
2985 *
2986 * On errors, the Python exception data is set, and NULL is returned.
2987 */
2988 static char *
2989StringToLine(PyObject *obj)
2990{
2991 const char *str;
2992 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02002993 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002994 PyInt len;
2995 PyInt i;
2996 char *p;
2997
2998 if (obj == NULL || !PyString_Check(obj))
2999 {
3000 PyErr_BadArgument();
3001 return NULL;
3002 }
3003
Bram Moolenaar19e60942011-06-19 00:27:51 +02003004 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
3005 str = PyString_AsString(bytes);
3006 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003007
3008 /*
3009 * Error checking: String must not contain newlines, as we
3010 * are replacing a single line, and we must replace it with
3011 * a single line.
3012 * A trailing newline is removed, so that append(f.readlines()) works.
3013 */
3014 p = memchr(str, '\n', len);
3015 if (p != NULL)
3016 {
3017 if (p == str + len - 1)
3018 --len;
3019 else
3020 {
3021 PyErr_SetVim(_("string cannot contain newlines"));
3022 return NULL;
3023 }
3024 }
3025
3026 /* Create a copy of the string, with internal nulls replaced by
3027 * newline characters, as is the vim convention.
3028 */
3029 save = (char *)alloc((unsigned)(len+1));
3030 if (save == NULL)
3031 {
3032 PyErr_NoMemory();
3033 return NULL;
3034 }
3035
3036 for (i = 0; i < len; ++i)
3037 {
3038 if (str[i] == '\0')
3039 save[i] = '\n';
3040 else
3041 save[i] = str[i];
3042 }
3043
3044 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02003045 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003046
3047 return save;
3048}
3049
3050/* Get a line from the specified buffer. The line number is
3051 * in Vim format (1-based). The line is returned as a Python
3052 * string object.
3053 */
3054 static PyObject *
3055GetBufferLine(buf_T *buf, PyInt n)
3056{
3057 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3058}
3059
3060
3061/* Get a list of lines from the specified buffer. The line numbers
3062 * are in Vim format (1-based). The range is from lo up to, but not
3063 * including, hi. The list is returned as a Python list of string objects.
3064 */
3065 static PyObject *
3066GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3067{
3068 PyInt i;
3069 PyInt n = hi - lo;
3070 PyObject *list = PyList_New(n);
3071
3072 if (list == NULL)
3073 return NULL;
3074
3075 for (i = 0; i < n; ++i)
3076 {
3077 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
3078
3079 /* Error check - was the Python string creation OK? */
3080 if (str == NULL)
3081 {
3082 Py_DECREF(list);
3083 return NULL;
3084 }
3085
3086 /* Set the list item */
3087 if (PyList_SetItem(list, i, str))
3088 {
3089 Py_DECREF(str);
3090 Py_DECREF(list);
3091 return NULL;
3092 }
3093 }
3094
3095 /* The ownership of the Python list is passed to the caller (ie,
3096 * the caller should Py_DECREF() the object when it is finished
3097 * with it).
3098 */
3099
3100 return list;
3101}
3102
3103/*
3104 * Check if deleting lines made the cursor position invalid.
3105 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3106 * deleted).
3107 */
3108 static void
3109py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3110{
3111 if (curwin->w_cursor.lnum >= lo)
3112 {
3113 /* Adjust the cursor position if it's in/after the changed
3114 * lines. */
3115 if (curwin->w_cursor.lnum >= hi)
3116 {
3117 curwin->w_cursor.lnum += extra;
3118 check_cursor_col();
3119 }
3120 else if (extra < 0)
3121 {
3122 curwin->w_cursor.lnum = lo;
3123 check_cursor();
3124 }
3125 else
3126 check_cursor_col();
3127 changed_cline_bef_curs();
3128 }
3129 invalidate_botline();
3130}
3131
Bram Moolenaar19e60942011-06-19 00:27:51 +02003132/*
3133 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003134 * in Vim format (1-based). The replacement line is given as
3135 * a Python string object. The object is checked for validity
3136 * and correct format. Errors are returned as a value of FAIL.
3137 * The return value is OK on success.
3138 * If OK is returned and len_change is not NULL, *len_change
3139 * is set to the change in the buffer length.
3140 */
3141 static int
3142SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3143{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003144 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003145 * There are three cases:
3146 * 1. NULL, or None - this is a deletion.
3147 * 2. A string - this is a replacement.
3148 * 3. Anything else - this is an error.
3149 */
3150 if (line == Py_None || line == NULL)
3151 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003152 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003153
3154 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003155 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003156
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003157 VimTryStart();
3158
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003159 if (u_savedel((linenr_T)n, 1L) == FAIL)
3160 PyErr_SetVim(_("cannot save undo information"));
3161 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
3162 PyErr_SetVim(_("cannot delete line"));
3163 else
3164 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003165 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003166 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3167 deleted_lines_mark((linenr_T)n, 1L);
3168 }
3169
Bram Moolenaar105bc352013-05-17 16:03:57 +02003170 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003171
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003172 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003173 return FAIL;
3174
3175 if (len_change)
3176 *len_change = -1;
3177
3178 return OK;
3179 }
3180 else if (PyString_Check(line))
3181 {
3182 char *save = StringToLine(line);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003183 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003184
3185 if (save == NULL)
3186 return FAIL;
3187
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003188 VimTryStart();
3189
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003190 /* We do not need to free "save" if ml_replace() consumes it. */
3191 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003192 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003193
3194 if (u_savesub((linenr_T)n) == FAIL)
3195 {
3196 PyErr_SetVim(_("cannot save undo information"));
3197 vim_free(save);
3198 }
3199 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3200 {
3201 PyErr_SetVim(_("cannot replace line"));
3202 vim_free(save);
3203 }
3204 else
3205 changed_bytes((linenr_T)n, 0);
3206
Bram Moolenaar105bc352013-05-17 16:03:57 +02003207 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003208
3209 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003210 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003211 check_cursor_col();
3212
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003213 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003214 return FAIL;
3215
3216 if (len_change)
3217 *len_change = 0;
3218
3219 return OK;
3220 }
3221 else
3222 {
3223 PyErr_BadArgument();
3224 return FAIL;
3225 }
3226}
3227
Bram Moolenaar19e60942011-06-19 00:27:51 +02003228/* Replace a range of lines in the specified buffer. The line numbers are in
3229 * Vim format (1-based). The range is from lo up to, but not including, hi.
3230 * The replacement lines are given as a Python list of string objects. The
3231 * list is checked for validity and correct format. Errors are returned as a
3232 * value of FAIL. The return value is OK on success.
3233 * If OK is returned and len_change is not NULL, *len_change
3234 * is set to the change in the buffer length.
3235 */
3236 static int
3237SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
3238{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003239 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003240 * There are three cases:
3241 * 1. NULL, or None - this is a deletion.
3242 * 2. A list - this is a replacement.
3243 * 3. Anything else - this is an error.
3244 */
3245 if (list == Py_None || list == NULL)
3246 {
3247 PyInt i;
3248 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003249 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003250
3251 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003252 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003253 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003254
3255 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
3256 PyErr_SetVim(_("cannot save undo information"));
3257 else
3258 {
3259 for (i = 0; i < n; ++i)
3260 {
3261 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3262 {
3263 PyErr_SetVim(_("cannot delete line"));
3264 break;
3265 }
3266 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003267 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003268 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3269 deleted_lines_mark((linenr_T)lo, (long)i);
3270 }
3271
Bram Moolenaar105bc352013-05-17 16:03:57 +02003272 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003273
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003274 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003275 return FAIL;
3276
3277 if (len_change)
3278 *len_change = -n;
3279
3280 return OK;
3281 }
3282 else if (PyList_Check(list))
3283 {
3284 PyInt i;
3285 PyInt new_len = PyList_Size(list);
3286 PyInt old_len = hi - lo;
3287 PyInt extra = 0; /* lines added to text, can be negative */
3288 char **array;
3289 buf_T *savebuf;
3290
3291 if (new_len == 0) /* avoid allocating zero bytes */
3292 array = NULL;
3293 else
3294 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003295 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003296 if (array == NULL)
3297 {
3298 PyErr_NoMemory();
3299 return FAIL;
3300 }
3301 }
3302
3303 for (i = 0; i < new_len; ++i)
3304 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003305 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003306
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003307 if (!(line = PyList_GetItem(list, i)) ||
3308 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003309 {
3310 while (i)
3311 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003312 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003313 return FAIL;
3314 }
3315 }
3316
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003317 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003318 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003319
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003320 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003321 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003322
3323 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
3324 PyErr_SetVim(_("cannot save undo information"));
3325
3326 /* If the size of the range is reducing (ie, new_len < old_len) we
3327 * need to delete some old_len. We do this at the start, by
3328 * repeatedly deleting line "lo".
3329 */
3330 if (!PyErr_Occurred())
3331 {
3332 for (i = 0; i < old_len - new_len; ++i)
3333 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3334 {
3335 PyErr_SetVim(_("cannot delete line"));
3336 break;
3337 }
3338 extra -= i;
3339 }
3340
3341 /* For as long as possible, replace the existing old_len with the
3342 * new old_len. This is a more efficient operation, as it requires
3343 * less memory allocation and freeing.
3344 */
3345 if (!PyErr_Occurred())
3346 {
3347 for (i = 0; i < old_len && i < new_len; ++i)
3348 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3349 == FAIL)
3350 {
3351 PyErr_SetVim(_("cannot replace line"));
3352 break;
3353 }
3354 }
3355 else
3356 i = 0;
3357
3358 /* Now we may need to insert the remaining new old_len. If we do, we
3359 * must free the strings as we finish with them (we can't pass the
3360 * responsibility to vim in this case).
3361 */
3362 if (!PyErr_Occurred())
3363 {
3364 while (i < new_len)
3365 {
3366 if (ml_append((linenr_T)(lo + i - 1),
3367 (char_u *)array[i], 0, FALSE) == FAIL)
3368 {
3369 PyErr_SetVim(_("cannot insert line"));
3370 break;
3371 }
3372 vim_free(array[i]);
3373 ++i;
3374 ++extra;
3375 }
3376 }
3377
3378 /* Free any left-over old_len, as a result of an error */
3379 while (i < new_len)
3380 {
3381 vim_free(array[i]);
3382 ++i;
3383 }
3384
3385 /* Free the array of old_len. All of its contents have now
3386 * been dealt with (either freed, or the responsibility passed
3387 * to vim.
3388 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003389 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003390
3391 /* Adjust marks. Invalidate any which lie in the
3392 * changed range, and move any in the remainder of the buffer.
3393 */
3394 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3395 (long)MAXLNUM, (long)extra);
3396 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3397
Bram Moolenaar105bc352013-05-17 16:03:57 +02003398 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003399 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3400
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003401 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003402 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003403
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003404 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003405 return FAIL;
3406
3407 if (len_change)
3408 *len_change = new_len - old_len;
3409
3410 return OK;
3411 }
3412 else
3413 {
3414 PyErr_BadArgument();
3415 return FAIL;
3416 }
3417}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003418
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003419/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003420 * The line number is in Vim format (1-based). The lines to be inserted are
3421 * given as a Python list of string objects or as a single string. The lines
3422 * to be added are checked for validity and correct format. Errors are
3423 * returned as a value of FAIL. The return value is OK on success.
3424 * If OK is returned and len_change is not NULL, *len_change
3425 * is set to the change in the buffer length.
3426 */
3427 static int
3428InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3429{
3430 /* First of all, we check the type of the supplied Python object.
3431 * It must be a string or a list, or the call is in error.
3432 */
3433 if (PyString_Check(lines))
3434 {
3435 char *str = StringToLine(lines);
3436 buf_T *savebuf;
3437
3438 if (str == NULL)
3439 return FAIL;
3440
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003441 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003442 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003443 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003444
3445 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
3446 PyErr_SetVim(_("cannot save undo information"));
3447 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
3448 PyErr_SetVim(_("cannot insert line"));
3449 else
3450 appended_lines_mark((linenr_T)n, 1L);
3451
3452 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003453 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003454 update_screen(VALID);
3455
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003456 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003457 return FAIL;
3458
3459 if (len_change)
3460 *len_change = 1;
3461
3462 return OK;
3463 }
3464 else if (PyList_Check(lines))
3465 {
3466 PyInt i;
3467 PyInt size = PyList_Size(lines);
3468 char **array;
3469 buf_T *savebuf;
3470
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003471 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003472 if (array == NULL)
3473 {
3474 PyErr_NoMemory();
3475 return FAIL;
3476 }
3477
3478 for (i = 0; i < size; ++i)
3479 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003480 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003481
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003482 if (!(line = PyList_GetItem(lines, i)) ||
3483 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003484 {
3485 while (i)
3486 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003487 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003488 return FAIL;
3489 }
3490 }
3491
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003492 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003493 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003494 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003495
3496 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
3497 PyErr_SetVim(_("cannot save undo information"));
3498 else
3499 {
3500 for (i = 0; i < size; ++i)
3501 {
3502 if (ml_append((linenr_T)(n + i),
3503 (char_u *)array[i], 0, FALSE) == FAIL)
3504 {
3505 PyErr_SetVim(_("cannot insert line"));
3506
3507 /* Free the rest of the lines */
3508 while (i < size)
3509 vim_free(array[i++]);
3510
3511 break;
3512 }
3513 vim_free(array[i]);
3514 }
3515 if (i > 0)
3516 appended_lines_mark((linenr_T)n, (long)i);
3517 }
3518
3519 /* Free the array of lines. All of its contents have now
3520 * been freed.
3521 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003522 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003523
Bram Moolenaar105bc352013-05-17 16:03:57 +02003524 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003525 update_screen(VALID);
3526
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003527 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003528 return FAIL;
3529
3530 if (len_change)
3531 *len_change = size;
3532
3533 return OK;
3534 }
3535 else
3536 {
3537 PyErr_BadArgument();
3538 return FAIL;
3539 }
3540}
3541
3542/*
3543 * Common routines for buffers and line ranges
3544 * -------------------------------------------
3545 */
3546
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003547typedef struct
3548{
3549 PyObject_HEAD
3550 buf_T *buf;
3551} BufferObject;
3552
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003553 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003554CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003555{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003556 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003557 {
3558 PyErr_SetVim(_("attempt to refer to deleted buffer"));
3559 return -1;
3560 }
3561
3562 return 0;
3563}
3564
3565 static PyObject *
3566RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3567{
3568 if (CheckBuffer(self))
3569 return NULL;
3570
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003571 if (end == -1)
3572 end = self->buf->b_ml.ml_line_count;
3573
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003574 if (n < 0)
3575 n += end - start + 1;
3576
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003577 if (n < 0 || n > end - start)
3578 {
3579 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3580 return NULL;
3581 }
3582
3583 return GetBufferLine(self->buf, n+start);
3584}
3585
3586 static PyObject *
3587RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3588{
3589 PyInt size;
3590
3591 if (CheckBuffer(self))
3592 return NULL;
3593
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003594 if (end == -1)
3595 end = self->buf->b_ml.ml_line_count;
3596
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003597 size = end - start + 1;
3598
3599 if (lo < 0)
3600 lo = 0;
3601 else if (lo > size)
3602 lo = size;
3603 if (hi < 0)
3604 hi = 0;
3605 if (hi < lo)
3606 hi = lo;
3607 else if (hi > size)
3608 hi = size;
3609
3610 return GetBufferLineList(self->buf, lo+start, hi+start);
3611}
3612
3613 static PyInt
3614RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3615{
3616 PyInt len_change;
3617
3618 if (CheckBuffer(self))
3619 return -1;
3620
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003621 if (end == -1)
3622 end = self->buf->b_ml.ml_line_count;
3623
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003624 if (n < 0)
3625 n += end - start + 1;
3626
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003627 if (n < 0 || n > end - start)
3628 {
3629 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3630 return -1;
3631 }
3632
3633 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
3634 return -1;
3635
3636 if (new_end)
3637 *new_end = end + len_change;
3638
3639 return 0;
3640}
3641
Bram Moolenaar19e60942011-06-19 00:27:51 +02003642 static PyInt
3643RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3644{
3645 PyInt size;
3646 PyInt len_change;
3647
3648 /* Self must be a valid buffer */
3649 if (CheckBuffer(self))
3650 return -1;
3651
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003652 if (end == -1)
3653 end = self->buf->b_ml.ml_line_count;
3654
Bram Moolenaar19e60942011-06-19 00:27:51 +02003655 /* Sort out the slice range */
3656 size = end - start + 1;
3657
3658 if (lo < 0)
3659 lo = 0;
3660 else if (lo > size)
3661 lo = size;
3662 if (hi < 0)
3663 hi = 0;
3664 if (hi < lo)
3665 hi = lo;
3666 else if (hi > size)
3667 hi = size;
3668
3669 if (SetBufferLineList(self->buf, lo + start, hi + start,
3670 val, &len_change) == FAIL)
3671 return -1;
3672
3673 if (new_end)
3674 *new_end = end + len_change;
3675
3676 return 0;
3677}
3678
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003679
3680 static PyObject *
3681RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
3682{
3683 PyObject *lines;
3684 PyInt len_change;
3685 PyInt max;
3686 PyInt n;
3687
3688 if (CheckBuffer(self))
3689 return NULL;
3690
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003691 if (end == -1)
3692 end = self->buf->b_ml.ml_line_count;
3693
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003694 max = n = end - start + 1;
3695
3696 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
3697 return NULL;
3698
3699 if (n < 0 || n > max)
3700 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003701 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003702 return NULL;
3703 }
3704
3705 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
3706 return NULL;
3707
3708 if (new_end)
3709 *new_end = end + len_change;
3710
3711 Py_INCREF(Py_None);
3712 return Py_None;
3713}
3714
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003715/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003716 */
3717
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003718static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003719static PySequenceMethods RangeAsSeq;
3720static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003721
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003722typedef struct
3723{
3724 PyObject_HEAD
3725 BufferObject *buf;
3726 PyInt start;
3727 PyInt end;
3728} RangeObject;
3729
3730 static PyObject *
3731RangeNew(buf_T *buf, PyInt start, PyInt end)
3732{
3733 BufferObject *bufr;
3734 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003735 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003736 if (self == NULL)
3737 return NULL;
3738
3739 bufr = (BufferObject *)BufferNew(buf);
3740 if (bufr == NULL)
3741 {
3742 Py_DECREF(self);
3743 return NULL;
3744 }
3745 Py_INCREF(bufr);
3746
3747 self->buf = bufr;
3748 self->start = start;
3749 self->end = end;
3750
3751 return (PyObject *)(self);
3752}
3753
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003754 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003755RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003756{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003757 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003758 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02003759 PyObject_GC_Del((void *)(self));
3760}
3761
3762 static int
3763RangeTraverse(RangeObject *self, visitproc visit, void *arg)
3764{
3765 Py_VISIT(((PyObject *)(self->buf)));
3766 return 0;
3767}
3768
3769 static int
3770RangeClear(RangeObject *self)
3771{
3772 Py_CLEAR(self->buf);
3773 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003774}
3775
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003776 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003777RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003778{
3779 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003780 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003781 return -1; /* ??? */
3782
Bram Moolenaard6e39182013-05-21 18:30:34 +02003783 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003784}
3785
3786 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003787RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003788{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003789 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003790}
3791
3792 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003793RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003794{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003795 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003796}
3797
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003798static char *RangeAttrs[] = {
3799 "start", "end",
3800 NULL
3801};
3802
3803 static PyObject *
3804RangeDir(PyObject *self)
3805{
3806 return ObjectDir(self, RangeAttrs);
3807}
3808
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003809 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003810RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003811{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003812 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003813}
3814
3815 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003816RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003817{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003818 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003819 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
3820 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003821 else
3822 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003823 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003824
3825 if (name == NULL)
3826 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003827
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003828 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02003829 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003830 }
3831}
3832
3833static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02003834 /* name, function, calling, documentation */
3835 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003836 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
3837 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003838};
3839
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003840static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003841static PySequenceMethods BufferAsSeq;
3842static PyMappingMethods BufferAsMapping;
3843
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003844 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02003845BufferNew(buf_T *buf)
3846{
3847 /* We need to handle deletion of buffers underneath us.
3848 * If we add a "b_python*_ref" field to the buf_T structure,
3849 * then we can get at it in buf_freeall() in vim. We then
3850 * need to create only ONE Python object per buffer - if
3851 * we try to create a second, just INCREF the existing one
3852 * and return it. The (single) Python object referring to
3853 * the buffer is stored in "b_python*_ref".
3854 * Question: what to do on a buf_freeall(). We'll probably
3855 * have to either delete the Python object (DECREF it to
3856 * zero - a bad idea, as it leaves dangling refs!) or
3857 * set the buf_T * value to an invalid value (-1?), which
3858 * means we need checks in all access functions... Bah.
3859 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003860 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003861 * b_python_ref and b_python3_ref fields respectively.
3862 */
3863
3864 BufferObject *self;
3865
3866 if (BUF_PYTHON_REF(buf) != NULL)
3867 {
3868 self = BUF_PYTHON_REF(buf);
3869 Py_INCREF(self);
3870 }
3871 else
3872 {
3873 self = PyObject_NEW(BufferObject, &BufferType);
3874 if (self == NULL)
3875 return NULL;
3876 self->buf = buf;
3877 BUF_PYTHON_REF(buf) = self;
3878 }
3879
3880 return (PyObject *)(self);
3881}
3882
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003883 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003884BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003885{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003886 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
3887 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003888
3889 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003890}
3891
Bram Moolenaar971db462013-05-12 18:44:48 +02003892 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003893BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02003894{
3895 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003896 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02003897 return -1; /* ??? */
3898
Bram Moolenaard6e39182013-05-21 18:30:34 +02003899 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02003900}
3901
3902 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003903BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02003904{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003905 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003906}
3907
3908 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003909BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02003910{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003911 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003912}
3913
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003914static char *BufferAttrs[] = {
3915 "name", "number", "vars", "options", "valid",
3916 NULL
3917};
3918
3919 static PyObject *
3920BufferDir(PyObject *self)
3921{
3922 return ObjectDir(self, BufferAttrs);
3923}
3924
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003925 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003926BufferAttrValid(BufferObject *self, char *name)
3927{
3928 PyObject *r;
3929
3930 if (strcmp(name, "valid") != 0)
3931 return NULL;
3932
3933 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
3934 Py_INCREF(r);
3935 return r;
3936}
3937
3938 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003939BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003940{
3941 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02003942 return PyString_FromString((self->buf->b_ffname == NULL
3943 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003944 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003945 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003946 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003947 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003948 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003949 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
3950 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003951 else if (strcmp(name, "__members__") == 0)
3952 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003953 else
3954 return NULL;
3955}
3956
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003957 static int
3958BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
3959{
3960 if (CheckBuffer(self))
3961 return -1;
3962
3963 if (strcmp(name, "name") == 0)
3964 {
3965 char_u *val;
3966 aco_save_T aco;
3967 int r;
3968 PyObject *todecref;
3969
3970 if (!(val = StringToChars(valObject, &todecref)))
3971 return -1;
3972
3973 VimTryStart();
3974 /* Using aucmd_*: autocommands will be executed by rename_buffer */
3975 aucmd_prepbuf(&aco, self->buf);
3976 r = rename_buffer(val);
3977 aucmd_restbuf(&aco);
3978 Py_XDECREF(todecref);
3979 if (VimTryEnd())
3980 return -1;
3981
3982 if (r == FAIL)
3983 {
3984 PyErr_SetVim(_("failed to rename buffer"));
3985 return -1;
3986 }
3987 return 0;
3988 }
3989 else
3990 {
3991 PyErr_SetString(PyExc_AttributeError, name);
3992 return -1;
3993 }
3994}
3995
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003996 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003997BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003998{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003999 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004000}
4001
4002 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004003BufferMark(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004004{
4005 pos_T *posp;
4006 char *pmark;
4007 char mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004008 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004009
Bram Moolenaard6e39182013-05-21 18:30:34 +02004010 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004011 return NULL;
4012
4013 if (!PyArg_ParseTuple(args, "s", &pmark))
4014 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004015
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004016 if (STRLEN(pmark) != 1)
4017 {
4018 PyErr_SetString(PyExc_ValueError,
4019 _("mark name must be a single character"));
4020 return NULL;
4021 }
4022
4023 mark = *pmark;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004024 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004025 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004026 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004027 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004028 if (VimTryEnd())
4029 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004030
4031 if (posp == NULL)
4032 {
4033 PyErr_SetVim(_("invalid mark name"));
4034 return NULL;
4035 }
4036
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004037 if (posp->lnum <= 0)
4038 {
4039 /* Or raise an error? */
4040 Py_INCREF(Py_None);
4041 return Py_None;
4042 }
4043
4044 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4045}
4046
4047 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004048BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004049{
4050 PyInt start;
4051 PyInt end;
4052
Bram Moolenaard6e39182013-05-21 18:30:34 +02004053 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004054 return NULL;
4055
4056 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4057 return NULL;
4058
Bram Moolenaard6e39182013-05-21 18:30:34 +02004059 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004060}
4061
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004062 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004063BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004064{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004065 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004066 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004067 else
4068 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004069 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004070
4071 if (name == NULL)
4072 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004073
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004074 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004075 }
4076}
4077
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004078static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004079 /* name, function, calling, documentation */
4080 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
4081 {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" },
4082 {"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 +02004083 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4084 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004085};
4086
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004087/*
4088 * Buffer list object - Implementation
4089 */
4090
4091static PyTypeObject BufMapType;
4092
4093typedef struct
4094{
4095 PyObject_HEAD
4096} BufMapObject;
4097
4098 static PyInt
4099BufMapLength(PyObject *self UNUSED)
4100{
4101 buf_T *b = firstbuf;
4102 PyInt n = 0;
4103
4104 while (b)
4105 {
4106 ++n;
4107 b = b->b_next;
4108 }
4109
4110 return n;
4111}
4112
4113 static PyObject *
4114BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4115{
4116 buf_T *b;
4117 int bnr;
4118
4119#if PY_MAJOR_VERSION < 3
4120 if (PyInt_Check(keyObject))
4121 bnr = PyInt_AsLong(keyObject);
4122 else
4123#endif
4124 if (PyLong_Check(keyObject))
4125 bnr = PyLong_AsLong(keyObject);
4126 else
4127 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004128 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004129 return NULL;
4130 }
4131
4132 b = buflist_findnr(bnr);
4133
4134 if (b)
4135 return BufferNew(b);
4136 else
4137 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004138 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004139 return NULL;
4140 }
4141}
4142
4143 static void
4144BufMapIterDestruct(PyObject *buffer)
4145{
4146 /* Iteration was stopped before all buffers were processed */
4147 if (buffer)
4148 {
4149 Py_DECREF(buffer);
4150 }
4151}
4152
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004153 static int
4154BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4155{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004156 if (buffer)
4157 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004158 return 0;
4159}
4160
4161 static int
4162BufMapIterClear(PyObject **buffer)
4163{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004164 if (*buffer)
4165 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004166 return 0;
4167}
4168
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004169 static PyObject *
4170BufMapIterNext(PyObject **buffer)
4171{
4172 PyObject *next;
4173 PyObject *r;
4174
4175 if (!*buffer)
4176 return NULL;
4177
4178 r = *buffer;
4179
4180 if (CheckBuffer((BufferObject *)(r)))
4181 {
4182 *buffer = NULL;
4183 return NULL;
4184 }
4185
4186 if (!((BufferObject *)(r))->buf->b_next)
4187 next = NULL;
4188 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
4189 return NULL;
4190 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004191 /* Do not increment reference: we no longer hold it (decref), but whoever
4192 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004193 return r;
4194}
4195
4196 static PyObject *
4197BufMapIter(PyObject *self UNUSED)
4198{
4199 PyObject *buffer;
4200
4201 buffer = BufferNew(firstbuf);
4202 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004203 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4204 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004205}
4206
4207static PyMappingMethods BufMapAsMapping = {
4208 (lenfunc) BufMapLength,
4209 (binaryfunc) BufMapItem,
4210 (objobjargproc) 0,
4211};
4212
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004213/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004214 */
4215
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004216static char *CurrentAttrs[] = {
4217 "buffer", "window", "line", "range", "tabpage",
4218 NULL
4219};
4220
4221 static PyObject *
4222CurrentDir(PyObject *self)
4223{
4224 return ObjectDir(self, CurrentAttrs);
4225}
4226
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004227 static PyObject *
4228CurrentGetattr(PyObject *self UNUSED, char *name)
4229{
4230 if (strcmp(name, "buffer") == 0)
4231 return (PyObject *)BufferNew(curbuf);
4232 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004233 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004234 else if (strcmp(name, "tabpage") == 0)
4235 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004236 else if (strcmp(name, "line") == 0)
4237 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4238 else if (strcmp(name, "range") == 0)
4239 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004240 else if (strcmp(name, "__members__") == 0)
4241 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004242 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004243#if PY_MAJOR_VERSION < 3
4244 return Py_FindMethod(WindowMethods, self, name);
4245#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004246 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004247#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004248}
4249
4250 static int
4251CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
4252{
4253 if (strcmp(name, "line") == 0)
4254 {
4255 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
4256 return -1;
4257
4258 return 0;
4259 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004260 else if (strcmp(name, "buffer") == 0)
4261 {
4262 int count;
4263
4264 if (value->ob_type != &BufferType)
4265 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004266 PyErr_SetString(PyExc_TypeError, _("expected vim.Buffer object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004267 return -1;
4268 }
4269
4270 if (CheckBuffer((BufferObject *)(value)))
4271 return -1;
4272 count = ((BufferObject *)(value))->buf->b_fnum;
4273
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004274 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004275 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4276 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004277 if (VimTryEnd())
4278 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004279 PyErr_SetVim(_("failed to switch to given buffer"));
4280 return -1;
4281 }
4282
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004283 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004284 }
4285 else if (strcmp(name, "window") == 0)
4286 {
4287 int count;
4288
4289 if (value->ob_type != &WindowType)
4290 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004291 PyErr_SetString(PyExc_TypeError, _("expected vim.Window object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004292 return -1;
4293 }
4294
4295 if (CheckWindow((WindowObject *)(value)))
4296 return -1;
4297 count = get_win_number(((WindowObject *)(value))->win, firstwin);
4298
4299 if (!count)
4300 {
4301 PyErr_SetString(PyExc_ValueError,
4302 _("failed to find window in the current tab page"));
4303 return -1;
4304 }
4305
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004306 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004307 win_goto(((WindowObject *)(value))->win);
4308 if (((WindowObject *)(value))->win != curwin)
4309 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004310 if (VimTryEnd())
4311 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004312 PyErr_SetString(PyExc_RuntimeError,
4313 _("did not switch to the specified window"));
4314 return -1;
4315 }
4316
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004317 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004318 }
4319 else if (strcmp(name, "tabpage") == 0)
4320 {
4321 if (value->ob_type != &TabPageType)
4322 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004323 PyErr_SetString(PyExc_TypeError, _("expected vim.TabPage object"));
Bram Moolenaare7614592013-05-15 15:51:08 +02004324 return -1;
4325 }
4326
4327 if (CheckTabPage((TabPageObject *)(value)))
4328 return -1;
4329
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004330 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004331 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
4332 if (((TabPageObject *)(value))->tab != curtab)
4333 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004334 if (VimTryEnd())
4335 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02004336 PyErr_SetString(PyExc_RuntimeError,
4337 _("did not switch to the specified tab page"));
4338 return -1;
4339 }
4340
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004341 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004342 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004343 else
4344 {
4345 PyErr_SetString(PyExc_AttributeError, name);
4346 return -1;
4347 }
4348}
4349
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004350static struct PyMethodDef CurrentMethods[] = {
4351 /* name, function, calling, documentation */
4352 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4353 { NULL, NULL, 0, NULL}
4354};
4355
Bram Moolenaardb913952012-06-29 12:54:53 +02004356 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004357init_range_cmd(exarg_T *eap)
4358{
4359 RangeStart = eap->line1;
4360 RangeEnd = eap->line2;
4361}
4362
4363 static void
4364init_range_eval(typval_T *rettv UNUSED)
4365{
4366 RangeStart = (PyInt) curwin->w_cursor.lnum;
4367 RangeEnd = RangeStart;
4368}
4369
4370 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004371run_cmd(const char *cmd, void *arg UNUSED
4372#ifdef PY_CAN_RECURSE
4373 , PyGILState_STATE *pygilstate UNUSED
4374#endif
4375 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004376{
4377 PyRun_SimpleString((char *) cmd);
4378}
4379
4380static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4381static int code_hdr_len = 30;
4382
4383 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004384run_do(const char *cmd, void *arg UNUSED
4385#ifdef PY_CAN_RECURSE
4386 , PyGILState_STATE *pygilstate
4387#endif
4388 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004389{
4390 PyInt lnum;
4391 size_t len;
4392 char *code;
4393 int status;
4394 PyObject *pyfunc, *pymain;
4395
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004396 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004397 {
4398 EMSG(_("cannot save undo information"));
4399 return;
4400 }
4401
4402 len = code_hdr_len + STRLEN(cmd);
4403 code = PyMem_New(char, len + 1);
4404 memcpy(code, code_hdr, code_hdr_len);
4405 STRCPY(code + code_hdr_len, cmd);
4406 status = PyRun_SimpleString(code);
4407 PyMem_Free(code);
4408
4409 if (status)
4410 {
4411 EMSG(_("failed to run the code"));
4412 return;
4413 }
4414
4415 status = 0;
4416 pymain = PyImport_AddModule("__main__");
4417 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004418#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004419 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004420#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004421
4422 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4423 {
4424 PyObject *line, *linenr, *ret;
4425
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004426#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004427 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004428#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004429 if (!(line = GetBufferLine(curbuf, lnum)))
4430 goto err;
4431 if (!(linenr = PyInt_FromLong((long) lnum)))
4432 {
4433 Py_DECREF(line);
4434 goto err;
4435 }
4436 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4437 Py_DECREF(line);
4438 Py_DECREF(linenr);
4439 if (!ret)
4440 goto err;
4441
4442 if (ret != Py_None)
4443 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
4444 goto err;
4445
4446 Py_XDECREF(ret);
4447 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004448#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004449 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004450#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004451 }
4452 goto out;
4453err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004454#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004455 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004456#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004457 PyErr_PrintEx(0);
4458 PythonIO_Flush();
4459 status = 1;
4460out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004461#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004462 if (!status)
4463 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004464#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004465 Py_DECREF(pyfunc);
4466 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
4467 if (status)
4468 return;
4469 check_cursor();
4470 update_curbuf(NOT_VALID);
4471}
4472
4473 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004474run_eval(const char *cmd, typval_T *rettv
4475#ifdef PY_CAN_RECURSE
4476 , PyGILState_STATE *pygilstate UNUSED
4477#endif
4478 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004479{
4480 PyObject *r;
4481
4482 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
4483 if (r == NULL)
4484 {
4485 if (PyErr_Occurred() && !msg_silent)
4486 PyErr_PrintEx(0);
4487 EMSG(_("E858: Eval did not return a valid python object"));
4488 }
4489 else
4490 {
4491 if (ConvertFromPyObject(r, rettv) == -1)
4492 EMSG(_("E859: Failed to convert returned python object to vim value"));
4493 Py_DECREF(r);
4494 }
4495 PyErr_Clear();
4496}
4497
4498 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02004499set_ref_in_py(const int copyID)
4500{
4501 pylinkedlist_T *cur;
4502 dict_T *dd;
4503 list_T *ll;
4504
4505 if (lastdict != NULL)
4506 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
4507 {
4508 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
4509 if (dd->dv_copyID != copyID)
4510 {
4511 dd->dv_copyID = copyID;
4512 set_ref_in_ht(&dd->dv_hashtab, copyID);
4513 }
4514 }
4515
4516 if (lastlist != NULL)
4517 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
4518 {
4519 ll = ((ListObject *) (cur->pll_obj))->list;
4520 if (ll->lv_copyID != copyID)
4521 {
4522 ll->lv_copyID = copyID;
4523 set_ref_in_list(ll, copyID);
4524 }
4525 }
4526}
4527
4528 static int
4529set_string_copy(char_u *str, typval_T *tv)
4530{
4531 tv->vval.v_string = vim_strsave(str);
4532 if (tv->vval.v_string == NULL)
4533 {
4534 PyErr_NoMemory();
4535 return -1;
4536 }
4537 return 0;
4538}
4539
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004540 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004541pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004542{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004543 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004544 char_u *key;
4545 dictitem_T *di;
4546 PyObject *keyObject;
4547 PyObject *valObject;
4548 Py_ssize_t iter = 0;
4549
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004550 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004551 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004552
4553 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004554 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004555
4556 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4557 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004558 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004559
Bram Moolenaara03e6312013-05-29 22:49:26 +02004560 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004561 {
4562 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004563 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004564 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004565
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004566 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004567 {
4568 dict_unref(dict);
4569 return -1;
4570 }
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004571 if (*key == NUL)
4572 {
4573 dict_unref(dict);
4574 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004575 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004576 return -1;
4577 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004578
4579 di = dictitem_alloc(key);
4580
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004581 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004582
4583 if (di == NULL)
4584 {
4585 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004586 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004587 return -1;
4588 }
4589 di->di_tv.v_lock = 0;
4590
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004591 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004592 {
4593 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004594 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004595 return -1;
4596 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004597
4598 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004599 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02004600 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004601 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004602 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004603 PyErr_SetVim(_("failed to add key to dictionary"));
4604 return -1;
4605 }
4606 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004607
4608 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004609 return 0;
4610}
4611
4612 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004613pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004614{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004615 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004616 char_u *key;
4617 dictitem_T *di;
4618 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004619 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004620 PyObject *keyObject;
4621 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004622
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004623 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004624 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004625
4626 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004627 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004628
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004629 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004630 {
4631 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004632 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004633 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004634
4635 if (!(iterator = PyObject_GetIter(list)))
4636 {
4637 dict_unref(dict);
4638 Py_DECREF(list);
4639 return -1;
4640 }
4641 Py_DECREF(list);
4642
4643 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004644 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004645 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004646
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004647 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004648 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004649 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004650 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004651 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004652 return -1;
4653 }
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004654 if (*key == NUL)
4655 {
4656 Py_DECREF(keyObject);
4657 Py_DECREF(iterator);
4658 Py_XDECREF(todecref);
4659 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004660 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004661 return -1;
4662 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004663
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004664 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004665 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004666 Py_DECREF(keyObject);
4667 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004668 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004669 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004670 return -1;
4671 }
4672
4673 di = dictitem_alloc(key);
4674
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004675 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004676 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004677
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004678 if (di == NULL)
4679 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004680 Py_DECREF(iterator);
4681 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004682 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004683 PyErr_NoMemory();
4684 return -1;
4685 }
4686 di->di_tv.v_lock = 0;
4687
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004688 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004689 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004690 Py_DECREF(iterator);
4691 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004692 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004693 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004694 return -1;
4695 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02004696
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004697 Py_DECREF(valObject);
4698
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004699 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004700 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004701 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004702 dictitem_free(di);
4703 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004704 PyErr_SetVim(_("failed to add key to dictionary"));
4705 return -1;
4706 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004707 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004708 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004709 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004710 return 0;
4711}
4712
4713 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004714pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004715{
4716 list_T *l;
4717
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004718 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004719 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004720
4721 tv->v_type = VAR_LIST;
4722 tv->vval.v_list = l;
4723
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004724 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004725 {
4726 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004727 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004728 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004729
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004730 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004731 return 0;
4732}
4733
Bram Moolenaardb913952012-06-29 12:54:53 +02004734typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
4735
4736 static int
4737convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004738 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004739{
4740 PyObject *capsule;
4741 char hexBuf[sizeof(void *) * 2 + 3];
4742
4743 sprintf(hexBuf, "%p", obj);
4744
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004745# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004746 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004747# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004748 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004749# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02004750 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02004751 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004752# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02004753 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02004754# else
4755 capsule = PyCObject_FromVoidPtr(tv, NULL);
4756# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02004757 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
4758 {
4759 Py_DECREF(capsule);
4760 tv->v_type = VAR_UNKNOWN;
4761 return -1;
4762 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004763 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02004764 {
4765 tv->v_type = VAR_UNKNOWN;
4766 return -1;
4767 }
4768 /* As we are not using copy_tv which increments reference count we must
4769 * do it ourself. */
4770 switch(tv->v_type)
4771 {
4772 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
4773 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
4774 }
4775 }
4776 else
4777 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004778 typval_T *v;
4779
4780# ifdef PY_USE_CAPSULE
4781 v = PyCapsule_GetPointer(capsule, NULL);
4782# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02004783 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004784# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02004785 copy_tv(v, tv);
4786 }
4787 return 0;
4788}
4789
4790 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02004791ConvertFromPyMapping(PyObject *obj, typval_T *tv)
4792{
4793 PyObject *lookup_dict;
4794 int r;
4795
4796 if (!(lookup_dict = PyDict_New()))
4797 return -1;
4798
4799 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
4800 {
4801 tv->v_type = VAR_DICT;
4802 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
4803 ++tv->vval.v_dict->dv_refcount;
4804 r = 0;
4805 }
4806 else if (PyDict_Check(obj))
4807 r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
4808 else if (PyMapping_Check(obj))
4809 r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
4810 else
4811 {
4812 PyErr_SetString(PyExc_TypeError,
4813 _("unable to convert object to vim dictionary"));
4814 r = -1;
4815 }
4816 Py_DECREF(lookup_dict);
4817 return r;
4818}
4819
4820 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02004821ConvertFromPyObject(PyObject *obj, typval_T *tv)
4822{
4823 PyObject *lookup_dict;
4824 int r;
4825
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004826 if (!(lookup_dict = PyDict_New()))
4827 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004828 r = _ConvertFromPyObject(obj, tv, lookup_dict);
4829 Py_DECREF(lookup_dict);
4830 return r;
4831}
4832
4833 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004834_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004835{
Bram Moolenaara9922d62013-05-30 13:01:18 +02004836 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02004837 {
4838 tv->v_type = VAR_DICT;
4839 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
4840 ++tv->vval.v_dict->dv_refcount;
4841 }
4842 else if (obj->ob_type == &ListType)
4843 {
4844 tv->v_type = VAR_LIST;
4845 tv->vval.v_list = (((ListObject *)(obj))->list);
4846 ++tv->vval.v_list->lv_refcount;
4847 }
4848 else if (obj->ob_type == &FunctionType)
4849 {
4850 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
4851 return -1;
4852
4853 tv->v_type = VAR_FUNC;
4854 func_ref(tv->vval.v_string);
4855 }
Bram Moolenaardb913952012-06-29 12:54:53 +02004856 else if (PyBytes_Check(obj))
4857 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004858 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02004859
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004860 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
4861 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004862 if (result == NULL)
4863 return -1;
4864
4865 if (set_string_copy(result, tv) == -1)
4866 return -1;
4867
4868 tv->v_type = VAR_STRING;
4869 }
4870 else if (PyUnicode_Check(obj))
4871 {
4872 PyObject *bytes;
4873 char_u *result;
4874
Bram Moolenaardb913952012-06-29 12:54:53 +02004875 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
4876 if (bytes == NULL)
4877 return -1;
4878
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004879 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
4880 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004881 if (result == NULL)
4882 return -1;
4883
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004884 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02004885 {
4886 Py_XDECREF(bytes);
4887 return -1;
4888 }
4889 Py_XDECREF(bytes);
4890
4891 tv->v_type = VAR_STRING;
4892 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02004893#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02004894 else if (PyInt_Check(obj))
4895 {
4896 tv->v_type = VAR_NUMBER;
4897 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
4898 }
4899#endif
4900 else if (PyLong_Check(obj))
4901 {
4902 tv->v_type = VAR_NUMBER;
4903 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
4904 }
4905 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004906 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004907#ifdef FEAT_FLOAT
4908 else if (PyFloat_Check(obj))
4909 {
4910 tv->v_type = VAR_FLOAT;
4911 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
4912 }
4913#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02004914 else if (PyObject_HasAttrString(obj, "keys"))
4915 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02004916 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004917 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004918 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004919 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004920 else
4921 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004922 PyErr_SetString(PyExc_TypeError,
4923 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02004924 return -1;
4925 }
4926 return 0;
4927}
4928
4929 static PyObject *
4930ConvertToPyObject(typval_T *tv)
4931{
4932 if (tv == NULL)
4933 {
4934 PyErr_SetVim(_("NULL reference passed"));
4935 return NULL;
4936 }
4937 switch (tv->v_type)
4938 {
4939 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02004940 return PyBytes_FromString(tv->vval.v_string == NULL
4941 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02004942 case VAR_NUMBER:
4943 return PyLong_FromLong((long) tv->vval.v_number);
4944#ifdef FEAT_FLOAT
4945 case VAR_FLOAT:
4946 return PyFloat_FromDouble((double) tv->vval.v_float);
4947#endif
4948 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02004949 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02004950 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02004951 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004952 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02004953 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02004954 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02004955 case VAR_UNKNOWN:
4956 Py_INCREF(Py_None);
4957 return Py_None;
4958 default:
4959 PyErr_SetVim(_("internal error: invalid value type"));
4960 return NULL;
4961 }
4962}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004963
4964typedef struct
4965{
4966 PyObject_HEAD
4967} CurrentObject;
4968static PyTypeObject CurrentType;
4969
4970 static void
4971init_structs(void)
4972{
4973 vim_memset(&OutputType, 0, sizeof(OutputType));
4974 OutputType.tp_name = "vim.message";
4975 OutputType.tp_basicsize = sizeof(OutputObject);
4976 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
4977 OutputType.tp_doc = "vim message object";
4978 OutputType.tp_methods = OutputMethods;
4979#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004980 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
4981 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004982 OutputType.tp_alloc = call_PyType_GenericAlloc;
4983 OutputType.tp_new = call_PyType_GenericNew;
4984 OutputType.tp_free = call_PyObject_Free;
4985#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004986 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
4987 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004988#endif
4989
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004990 vim_memset(&IterType, 0, sizeof(IterType));
4991 IterType.tp_name = "vim.iter";
4992 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02004993 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004994 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02004995 IterType.tp_iter = (getiterfunc)IterIter;
4996 IterType.tp_iternext = (iternextfunc)IterNext;
4997 IterType.tp_dealloc = (destructor)IterDestructor;
4998 IterType.tp_traverse = (traverseproc)IterTraverse;
4999 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005000
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005001 vim_memset(&BufferType, 0, sizeof(BufferType));
5002 BufferType.tp_name = "vim.buffer";
5003 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005004 BufferType.tp_dealloc = (destructor)BufferDestructor;
5005 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005006 BufferType.tp_as_sequence = &BufferAsSeq;
5007 BufferType.tp_as_mapping = &BufferAsMapping;
5008 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5009 BufferType.tp_doc = "vim buffer object";
5010 BufferType.tp_methods = BufferMethods;
5011#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005012 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005013 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005014 BufferType.tp_alloc = call_PyType_GenericAlloc;
5015 BufferType.tp_new = call_PyType_GenericNew;
5016 BufferType.tp_free = call_PyObject_Free;
5017#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005018 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005019 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005020#endif
5021
5022 vim_memset(&WindowType, 0, sizeof(WindowType));
5023 WindowType.tp_name = "vim.window";
5024 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005025 WindowType.tp_dealloc = (destructor)WindowDestructor;
5026 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005027 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005028 WindowType.tp_doc = "vim Window object";
5029 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005030 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5031 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005032#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005033 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5034 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005035 WindowType.tp_alloc = call_PyType_GenericAlloc;
5036 WindowType.tp_new = call_PyType_GenericNew;
5037 WindowType.tp_free = call_PyObject_Free;
5038#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005039 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5040 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005041#endif
5042
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005043 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5044 TabPageType.tp_name = "vim.tabpage";
5045 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005046 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5047 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005048 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5049 TabPageType.tp_doc = "vim tab page object";
5050 TabPageType.tp_methods = TabPageMethods;
5051#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005052 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005053 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5054 TabPageType.tp_new = call_PyType_GenericNew;
5055 TabPageType.tp_free = call_PyObject_Free;
5056#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005057 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005058#endif
5059
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005060 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5061 BufMapType.tp_name = "vim.bufferlist";
5062 BufMapType.tp_basicsize = sizeof(BufMapObject);
5063 BufMapType.tp_as_mapping = &BufMapAsMapping;
5064 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005065 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005066 BufferType.tp_doc = "vim buffer list";
5067
5068 vim_memset(&WinListType, 0, sizeof(WinListType));
5069 WinListType.tp_name = "vim.windowlist";
5070 WinListType.tp_basicsize = sizeof(WinListType);
5071 WinListType.tp_as_sequence = &WinListAsSeq;
5072 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5073 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005074 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005075
5076 vim_memset(&TabListType, 0, sizeof(TabListType));
5077 TabListType.tp_name = "vim.tabpagelist";
5078 TabListType.tp_basicsize = sizeof(TabListType);
5079 TabListType.tp_as_sequence = &TabListAsSeq;
5080 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5081 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005082
5083 vim_memset(&RangeType, 0, sizeof(RangeType));
5084 RangeType.tp_name = "vim.range";
5085 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005086 RangeType.tp_dealloc = (destructor)RangeDestructor;
5087 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005088 RangeType.tp_as_sequence = &RangeAsSeq;
5089 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005090 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005091 RangeType.tp_doc = "vim Range object";
5092 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005093 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5094 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005095#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005096 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005097 RangeType.tp_alloc = call_PyType_GenericAlloc;
5098 RangeType.tp_new = call_PyType_GenericNew;
5099 RangeType.tp_free = call_PyObject_Free;
5100#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005101 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005102#endif
5103
5104 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5105 CurrentType.tp_name = "vim.currentdata";
5106 CurrentType.tp_basicsize = sizeof(CurrentObject);
5107 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5108 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005109 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005110#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005111 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5112 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005113#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005114 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5115 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005116#endif
5117
5118 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5119 DictionaryType.tp_name = "vim.dictionary";
5120 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005121 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005122 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005123 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005124 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005125 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5126 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005127 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5128 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5129 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005130#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005131 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5132 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005133#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005134 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5135 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005136#endif
5137
5138 vim_memset(&ListType, 0, sizeof(ListType));
5139 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005140 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005141 ListType.tp_basicsize = sizeof(ListObject);
5142 ListType.tp_as_sequence = &ListAsSeq;
5143 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005144 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005145 ListType.tp_doc = "list pushing modifications to vim structure";
5146 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005147 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005148 ListType.tp_new = (newfunc)ListConstructor;
5149 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005150#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005151 ListType.tp_getattro = (getattrofunc)ListGetattro;
5152 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005153#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005154 ListType.tp_getattr = (getattrfunc)ListGetattr;
5155 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005156#endif
5157
5158 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005159 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005160 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005161 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5162 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005163 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005164 FunctionType.tp_doc = "object that calls vim function";
5165 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005166 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005167 FunctionType.tp_new = (newfunc)FunctionConstructor;
5168 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005169#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005170 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005171#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005172 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005173#endif
5174
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005175 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5176 OptionsType.tp_name = "vim.options";
5177 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005178 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005179 OptionsType.tp_doc = "object for manipulating options";
5180 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005181 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5182 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5183 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005184
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005185#if PY_MAJOR_VERSION >= 3
5186 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5187 vimmodule.m_name = "vim";
5188 vimmodule.m_doc = "Vim Python interface\n";
5189 vimmodule.m_size = -1;
5190 vimmodule.m_methods = VimMethods;
5191#endif
5192}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005193
5194#define PYTYPE_READY(type) \
5195 if (PyType_Ready(&type)) \
5196 return -1;
5197
5198 static int
5199init_types()
5200{
5201 PYTYPE_READY(IterType);
5202 PYTYPE_READY(BufferType);
5203 PYTYPE_READY(RangeType);
5204 PYTYPE_READY(WindowType);
5205 PYTYPE_READY(TabPageType);
5206 PYTYPE_READY(BufMapType);
5207 PYTYPE_READY(WinListType);
5208 PYTYPE_READY(TabListType);
5209 PYTYPE_READY(CurrentType);
5210 PYTYPE_READY(DictionaryType);
5211 PYTYPE_READY(ListType);
5212 PYTYPE_READY(FunctionType);
5213 PYTYPE_READY(OptionsType);
5214 PYTYPE_READY(OutputType);
5215 return 0;
5216}
5217
5218static BufMapObject TheBufferMap =
5219{
5220 PyObject_HEAD_INIT(&BufMapType)
5221};
5222
5223static WinListObject TheWindowList =
5224{
5225 PyObject_HEAD_INIT(&WinListType)
5226 NULL
5227};
5228
5229static CurrentObject TheCurrent =
5230{
5231 PyObject_HEAD_INIT(&CurrentType)
5232};
5233
5234static TabListObject TheTabPageList =
5235{
5236 PyObject_HEAD_INIT(&TabListType)
5237};
5238
5239static struct numeric_constant {
5240 char *name;
5241 int value;
5242} numeric_constants[] = {
5243 {"VAR_LOCKED", VAR_LOCKED},
5244 {"VAR_FIXED", VAR_FIXED},
5245 {"VAR_SCOPE", VAR_SCOPE},
5246 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5247};
5248
5249static struct object_constant {
5250 char *name;
5251 PyObject *value;
5252} object_constants[] = {
5253 {"buffers", (PyObject *)(void *)&TheBufferMap},
5254 {"windows", (PyObject *)(void *)&TheWindowList},
5255 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5256 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005257
5258 {"Buffer", (PyObject *)&BufferType},
5259 {"Range", (PyObject *)&RangeType},
5260 {"Window", (PyObject *)&WindowType},
5261 {"TabPage", (PyObject *)&TabPageType},
5262 {"Dictionary", (PyObject *)&DictionaryType},
5263 {"List", (PyObject *)&ListType},
5264 {"Function", (PyObject *)&FunctionType},
5265 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005266};
5267
5268typedef int (*object_adder)(PyObject *, const char *, PyObject *);
5269
5270#define ADD_OBJECT(m, name, obj) \
5271 if (add_object(m, name, obj)) \
5272 return -1;
5273
5274#define ADD_CHECKED_OBJECT(m, name, obj) \
5275 { \
5276 PyObject *value = obj; \
5277 if (!value) \
5278 return -1; \
5279 ADD_OBJECT(m, name, value); \
5280 }
5281
5282 static int
5283populate_module(PyObject *m, object_adder add_object)
5284{
5285 int i;
5286
5287 for (i = 0; i < (int)(sizeof(numeric_constants)
5288 / sizeof(struct numeric_constant));
5289 ++i)
5290 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
5291 PyInt_FromLong(numeric_constants[i].value));
5292
5293 for (i = 0; i < (int)(sizeof(object_constants)
5294 / sizeof(struct object_constant));
5295 ++i)
5296 {
5297 PyObject *value;
5298
5299 value = object_constants[i].value;
5300 Py_INCREF(value);
5301 ADD_OBJECT(m, object_constants[i].name, value);
5302 }
5303
5304 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5305 return -1;
5306 ADD_OBJECT(m, "error", VimError);
5307
Bram Moolenaara9922d62013-05-30 13:01:18 +02005308 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5309 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005310 ADD_CHECKED_OBJECT(m, "options",
5311 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
5312 return 0;
5313}