blob: 2fef1e42699a23520e3490de85645e9ad9765680 [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
25
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020026#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
27
28#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
29#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020030#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020031
32static int ConvertFromPyObject(PyObject *, typval_T *);
33static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
34
35static PyInt RangeStart;
36static PyInt RangeEnd;
37
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020038/*
39 * obtain a lock on the Vim data structures
40 */
41 static void
42Python_Lock_Vim(void)
43{
44}
45
46/*
47 * release a lock on the Vim data structures
48 */
49 static void
50Python_Release_Vim(void)
51{
52}
53
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020054/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020055 */
56
Bram Moolenaar2eea1982010-09-21 16:49:37 +020057/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020058typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020059
60static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020061
62typedef struct
63{
64 PyObject_HEAD
65 long softspace;
66 long error;
67} OutputObject;
68
Bram Moolenaar77045652012-09-21 13:46:06 +020069 static int
70OutputSetattr(PyObject *self, char *name, PyObject *val)
71{
72 if (val == NULL)
73 {
Bram Moolenaar8661b172013-05-15 15:44:28 +020074 PyErr_SetString(PyExc_AttributeError,
75 _("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +020076 return -1;
77 }
78
79 if (strcmp(name, "softspace") == 0)
80 {
81 if (!PyInt_Check(val))
82 {
83 PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
84 return -1;
85 }
86
87 ((OutputObject *)(self))->softspace = PyInt_AsLong(val);
88 return 0;
89 }
90
91 PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
92 return -1;
93}
94
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020095/* Buffer IO, we write one whole line at a time. */
96static garray_T io_ga = {0, 0, 1, 80, NULL};
97static writefn old_fn = NULL;
98
99 static void
100PythonIO_Flush(void)
101{
102 if (old_fn != NULL && io_ga.ga_len > 0)
103 {
104 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
105 old_fn((char_u *)io_ga.ga_data);
106 }
107 io_ga.ga_len = 0;
108}
109
110 static void
111writer(writefn fn, char_u *str, PyInt n)
112{
113 char_u *ptr;
114
115 /* Flush when switching output function. */
116 if (fn != old_fn)
117 PythonIO_Flush();
118 old_fn = fn;
119
120 /* Write each NL separated line. Text after the last NL is kept for
121 * writing later. */
122 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
123 {
124 PyInt len = ptr - str;
125
126 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
127 break;
128
129 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
130 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
131 fn((char_u *)io_ga.ga_data);
132 str = ptr + 1;
133 n -= len + 1;
134 io_ga.ga_len = 0;
135 }
136
137 /* Put the remaining text into io_ga for later printing. */
138 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
139 {
140 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
141 io_ga.ga_len += (int)n;
142 }
143}
144
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200145 static PyObject *
146OutputWrite(PyObject *self, PyObject *args)
147{
Bram Moolenaare8cdcef2012-09-12 20:21:43 +0200148 Py_ssize_t len = 0;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200149 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200150 int error = ((OutputObject *)(self))->error;
151
Bram Moolenaar27564802011-09-07 19:30:21 +0200152 if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200153 return NULL;
154
155 Py_BEGIN_ALLOW_THREADS
156 Python_Lock_Vim();
157 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
158 Python_Release_Vim();
159 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200160 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200161
162 Py_INCREF(Py_None);
163 return Py_None;
164}
165
166 static PyObject *
167OutputWritelines(PyObject *self, PyObject *args)
168{
169 PyInt n;
170 PyInt i;
171 PyObject *list;
172 int error = ((OutputObject *)(self))->error;
173
174 if (!PyArg_ParseTuple(args, "O", &list))
175 return NULL;
176 Py_INCREF(list);
177
Bram Moolenaardb913952012-06-29 12:54:53 +0200178 if (!PyList_Check(list))
179 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200180 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
181 Py_DECREF(list);
182 return NULL;
183 }
184
185 n = PyList_Size(list);
186
187 for (i = 0; i < n; ++i)
188 {
189 PyObject *line = PyList_GetItem(list, i);
Bram Moolenaar19e60942011-06-19 00:27:51 +0200190 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200191 PyInt len;
192
Bram Moolenaardb913952012-06-29 12:54:53 +0200193 if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len))
194 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200195 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
196 Py_DECREF(list);
197 return NULL;
198 }
199
200 Py_BEGIN_ALLOW_THREADS
201 Python_Lock_Vim();
202 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
203 Python_Release_Vim();
204 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200205 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200206 }
207
208 Py_DECREF(list);
209 Py_INCREF(Py_None);
210 return Py_None;
211}
212
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100213 static PyObject *
214OutputFlush(PyObject *self UNUSED, PyObject *args UNUSED)
215{
216 /* do nothing */
217 Py_INCREF(Py_None);
218 return Py_None;
219}
220
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200221/***************/
222
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200223static struct PyMethodDef OutputMethods[] = {
224 /* name, function, calling, documentation */
225 {"write", OutputWrite, 1, ""},
226 {"writelines", OutputWritelines, 1, ""},
227 {"flush", OutputFlush, 1, ""},
228 { NULL, NULL, 0, NULL}
229};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200230
231static OutputObject Output =
232{
233 PyObject_HEAD_INIT(&OutputType)
234 0,
235 0
236};
237
238static OutputObject Error =
239{
240 PyObject_HEAD_INIT(&OutputType)
241 0,
242 1
243};
244
245 static int
246PythonIO_Init_io(void)
247{
248 PySys_SetObject("stdout", (PyObject *)(void *)&Output);
249 PySys_SetObject("stderr", (PyObject *)(void *)&Error);
250
251 if (PyErr_Occurred())
252 {
253 EMSG(_("E264: Python: Error initialising I/O objects"));
254 return -1;
255 }
256
257 return 0;
258}
259
260
261static PyObject *VimError;
262
263/* Check to see whether a Vim error has been reported, or a keyboard
264 * interrupt has been detected.
265 */
266 static int
267VimErrorCheck(void)
268{
269 if (got_int)
270 {
271 PyErr_SetNone(PyExc_KeyboardInterrupt);
272 return 1;
273 }
274 else if (did_emsg && !PyErr_Occurred())
275 {
276 PyErr_SetNone(VimError);
277 return 1;
278 }
279
280 return 0;
281}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200282
283/* Vim module - Implementation
284 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200285
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200286 static PyObject *
287VimCommand(PyObject *self UNUSED, PyObject *args)
288{
289 char *cmd;
290 PyObject *result;
291
292 if (!PyArg_ParseTuple(args, "s", &cmd))
293 return NULL;
294
295 PyErr_Clear();
296
297 Py_BEGIN_ALLOW_THREADS
298 Python_Lock_Vim();
299
300 do_cmdline_cmd((char_u *)cmd);
301 update_screen(VALID);
302
303 Python_Release_Vim();
304 Py_END_ALLOW_THREADS
305
306 if (VimErrorCheck())
307 result = NULL;
308 else
309 result = Py_None;
310
311 Py_XINCREF(result);
312 return result;
313}
314
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200315/*
316 * Function to translate a typval_T into a PyObject; this will recursively
317 * translate lists/dictionaries into their Python equivalents.
318 *
319 * The depth parameter is to avoid infinite recursion, set it to 1 when
320 * you call VimToPython.
321 */
322 static PyObject *
323VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
324{
325 PyObject *result;
326 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200327 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200328
329 /* Avoid infinite recursion */
330 if (depth > 100)
331 {
332 Py_INCREF(Py_None);
333 result = Py_None;
334 return result;
335 }
336
337 /* Check if we run into a recursive loop. The item must be in lookupDict
338 * then and we can use it again. */
339 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
340 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
341 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200342 sprintf(ptrBuf, "%p",
343 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
344 : (void *)our_tv->vval.v_dict);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200345 result = PyDict_GetItemString(lookupDict, ptrBuf);
346 if (result != NULL)
347 {
348 Py_INCREF(result);
349 return result;
350 }
351 }
352
353 if (our_tv->v_type == VAR_STRING)
354 {
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200355 result = Py_BuildValue("s", our_tv->vval.v_string == NULL
356 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200357 }
358 else if (our_tv->v_type == VAR_NUMBER)
359 {
360 char buf[NUMBUFLEN];
361
362 /* For backwards compatibility numbers are stored as strings. */
363 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
364 result = Py_BuildValue("s", buf);
365 }
366# ifdef FEAT_FLOAT
367 else if (our_tv->v_type == VAR_FLOAT)
368 {
369 char buf[NUMBUFLEN];
370
371 sprintf(buf, "%f", our_tv->vval.v_float);
372 result = Py_BuildValue("s", buf);
373 }
374# endif
375 else if (our_tv->v_type == VAR_LIST)
376 {
377 list_T *list = our_tv->vval.v_list;
378 listitem_T *curr;
379
380 result = PyList_New(0);
381
382 if (list != NULL)
383 {
384 PyDict_SetItemString(lookupDict, ptrBuf, result);
385
386 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
387 {
388 newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict);
389 PyList_Append(result, newObj);
390 Py_DECREF(newObj);
391 }
392 }
393 }
394 else if (our_tv->v_type == VAR_DICT)
395 {
396 result = PyDict_New();
397
398 if (our_tv->vval.v_dict != NULL)
399 {
400 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
401 long_u todo = ht->ht_used;
402 hashitem_T *hi;
403 dictitem_T *di;
404
405 PyDict_SetItemString(lookupDict, ptrBuf, result);
406
407 for (hi = ht->ht_array; todo > 0; ++hi)
408 {
409 if (!HASHITEM_EMPTY(hi))
410 {
411 --todo;
412
413 di = dict_lookup(hi);
414 newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
415 PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
416 Py_DECREF(newObj);
417 }
418 }
419 }
420 }
421 else
422 {
423 Py_INCREF(Py_None);
424 result = Py_None;
425 }
426
427 return result;
428}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200429
430 static PyObject *
Bram Moolenaar09092152010-08-08 16:38:42 +0200431VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200432{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200433 char *expr;
434 typval_T *our_tv;
435 PyObject *result;
436 PyObject *lookup_dict;
437
438 if (!PyArg_ParseTuple(args, "s", &expr))
439 return NULL;
440
441 Py_BEGIN_ALLOW_THREADS
442 Python_Lock_Vim();
443 our_tv = eval_expr((char_u *)expr, NULL);
444
445 Python_Release_Vim();
446 Py_END_ALLOW_THREADS
447
448 if (our_tv == NULL)
449 {
450 PyErr_SetVim(_("invalid expression"));
451 return NULL;
452 }
453
454 /* Convert the Vim type into a Python type. Create a dictionary that's
455 * used to check for recursive loops. */
456 lookup_dict = PyDict_New();
457 result = VimToPython(our_tv, 1, lookup_dict);
458 Py_DECREF(lookup_dict);
459
460
461 Py_BEGIN_ALLOW_THREADS
462 Python_Lock_Vim();
463 free_tv(our_tv);
464 Python_Release_Vim();
465 Py_END_ALLOW_THREADS
466
467 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200468}
469
Bram Moolenaardb913952012-06-29 12:54:53 +0200470static PyObject *ConvertToPyObject(typval_T *);
471
472 static PyObject *
473VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED)
474{
Bram Moolenaardb913952012-06-29 12:54:53 +0200475 char *expr;
476 typval_T *our_tv;
477 PyObject *result;
478
479 if (!PyArg_ParseTuple(args, "s", &expr))
480 return NULL;
481
482 Py_BEGIN_ALLOW_THREADS
483 Python_Lock_Vim();
484 our_tv = eval_expr((char_u *)expr, NULL);
485
486 Python_Release_Vim();
487 Py_END_ALLOW_THREADS
488
489 if (our_tv == NULL)
490 {
491 PyErr_SetVim(_("invalid expression"));
492 return NULL;
493 }
494
495 result = ConvertToPyObject(our_tv);
496 Py_BEGIN_ALLOW_THREADS
497 Python_Lock_Vim();
498 free_tv(our_tv);
499 Python_Release_Vim();
500 Py_END_ALLOW_THREADS
501
502 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200503}
504
505 static PyObject *
506VimStrwidth(PyObject *self UNUSED, PyObject *args)
507{
508 char *expr;
509
510 if (!PyArg_ParseTuple(args, "s", &expr))
511 return NULL;
512
Bram Moolenaara54bf402012-12-05 16:30:07 +0100513 return PyLong_FromLong(
514#ifdef FEAT_MBYTE
515 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
516#else
517 STRLEN(expr)
518#endif
519 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200520}
521
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200522/*
523 * Vim module - Definitions
524 */
525
526static struct PyMethodDef VimMethods[] = {
527 /* name, function, calling, documentation */
528 {"command", VimCommand, 1, "Execute a Vim ex-mode command" },
529 {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" },
Bram Moolenaar2afa3232012-06-29 16:28:28 +0200530 {"bindeval", VimEvalPy, 1, "Like eval(), but returns objects attached to vim ones"},
531 {"strwidth", VimStrwidth, 1, "Screen string width, counts <Tab> as having width 1"},
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200532 { NULL, NULL, 0, NULL }
533};
534
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200535/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200536 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200537 */
538
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200539static PyTypeObject IterType;
540
541typedef PyObject *(*nextfun)(void **);
542typedef void (*destructorfun)(void *);
543
544/* Main purpose of this object is removing the need for do python initialization
545 * (i.e. PyType_Ready and setting type attributes) for a big bunch of objects.
546 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200547
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200548typedef struct
549{
550 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200551 void *cur;
552 nextfun next;
553 destructorfun destruct;
554} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200555
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200556 static PyObject *
557IterNew(void *start, destructorfun destruct, nextfun next)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200558{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200559 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200560
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200561 self = PyObject_NEW(IterObject, &IterType);
562 self->cur = start;
563 self->next = next;
564 self->destruct = destruct;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200565
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200566 return (PyObject *)(self);
567}
568
Bram Moolenaar03db85b2013-05-15 14:51:35 +0200569#if 0 /* unused */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200570 static void
571IterDestructor(PyObject *self)
572{
573 IterObject *this = (IterObject *)(self);
574
575 this->destruct(this->cur);
576
577 DESTRUCTOR_FINISH(self);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200578}
Bram Moolenaar03db85b2013-05-15 14:51:35 +0200579#endif
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200580
581 static PyObject *
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200582IterNext(PyObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200583{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200584 IterObject *this = (IterObject *)(self);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200585
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200586 return this->next(&this->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200587}
588
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200589 static PyObject *
590IterIter(PyObject *self)
591{
592 return self;
593}
Bram Moolenaardfa38d42013-05-15 13:38:47 +0200594
Bram Moolenaardb913952012-06-29 12:54:53 +0200595typedef struct pylinkedlist_S {
596 struct pylinkedlist_S *pll_next;
597 struct pylinkedlist_S *pll_prev;
598 PyObject *pll_obj;
599} pylinkedlist_T;
600
601static pylinkedlist_T *lastdict = NULL;
602static pylinkedlist_T *lastlist = NULL;
603
604 static void
605pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
606{
607 if (ref->pll_prev == NULL)
608 {
609 if (ref->pll_next == NULL)
610 {
611 *last = NULL;
612 return;
613 }
614 }
615 else
616 ref->pll_prev->pll_next = ref->pll_next;
617
618 if (ref->pll_next == NULL)
619 *last = ref->pll_prev;
620 else
621 ref->pll_next->pll_prev = ref->pll_prev;
622}
623
624 static void
625pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
626{
627 if (*last == NULL)
628 ref->pll_prev = NULL;
629 else
630 {
631 (*last)->pll_next = ref;
632 ref->pll_prev = *last;
633 }
634 ref->pll_next = NULL;
635 ref->pll_obj = self;
636 *last = ref;
637}
638
639static PyTypeObject DictionaryType;
640
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200641#define DICTKEY_GET_NOTEMPTY(err) \
642 DICTKEY_GET(err) \
643 if (*key == NUL) \
644 { \
645 PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
646 return err; \
647 }
648
Bram Moolenaardb913952012-06-29 12:54:53 +0200649typedef struct
650{
651 PyObject_HEAD
652 dict_T *dict;
653 pylinkedlist_T ref;
654} DictionaryObject;
655
656 static PyObject *
657DictionaryNew(dict_T *dict)
658{
659 DictionaryObject *self;
660
661 self = PyObject_NEW(DictionaryObject, &DictionaryType);
662 if (self == NULL)
663 return NULL;
664 self->dict = dict;
665 ++dict->dv_refcount;
666
667 pyll_add((PyObject *)(self), &self->ref, &lastdict);
668
669 return (PyObject *)(self);
670}
671
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200672 static void
673DictionaryDestructor(PyObject *self)
674{
675 DictionaryObject *this = ((DictionaryObject *) (self));
676
677 pyll_remove(&this->ref, &lastdict);
678 dict_unref(this->dict);
679
680 DESTRUCTOR_FINISH(self);
681}
682
Bram Moolenaardb913952012-06-29 12:54:53 +0200683 static int
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200684DictionarySetattr(PyObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200685{
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200686 DictionaryObject *this = (DictionaryObject *)(self);
687
Bram Moolenaar66b79852012-09-21 14:00:35 +0200688 if (val == NULL)
689 {
690 PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
691 return -1;
692 }
693
694 if (strcmp(name, "locked") == 0)
695 {
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200696 if (this->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200697 {
698 PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed dictionary"));
699 return -1;
700 }
701 else
702 {
Bram Moolenaarb983f752013-05-15 16:11:50 +0200703 int istrue = PyObject_IsTrue(val);
704 if (istrue == -1)
705 return -1;
706 else if (istrue)
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200707 this->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200708 else
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200709 this->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200710 }
711 return 0;
712 }
713 else
714 {
715 PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute"));
716 return -1;
717 }
718}
719
720 static PyInt
Bram Moolenaardb913952012-06-29 12:54:53 +0200721DictionaryLength(PyObject *self)
722{
723 return ((PyInt) ((((DictionaryObject *)(self))->dict->dv_hashtab.ht_used)));
724}
725
726 static PyObject *
727DictionaryItem(PyObject *self, PyObject *keyObject)
728{
729 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200730 dictitem_T *di;
Bram Moolenaardb913952012-06-29 12:54:53 +0200731 DICTKEY_DECL
732
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200733 DICTKEY_GET_NOTEMPTY(NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +0200734
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200735 di = dict_find(((DictionaryObject *) (self))->dict, key, -1);
736
Bram Moolenaar696c2112012-09-21 13:43:14 +0200737 DICTKEY_UNREF
738
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200739 if (di == NULL)
740 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +0200741 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200742 return NULL;
743 }
Bram Moolenaardb913952012-06-29 12:54:53 +0200744
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200745 return ConvertToPyObject(&di->di_tv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200746}
747
748 static PyInt
749DictionaryAssItem(PyObject *self, PyObject *keyObject, PyObject *valObject)
750{
751 char_u *key;
752 typval_T tv;
753 dict_T *d = ((DictionaryObject *)(self))->dict;
754 dictitem_T *di;
755 DICTKEY_DECL
756
757 if (d->dv_lock)
758 {
759 PyErr_SetVim(_("dict is locked"));
760 return -1;
761 }
762
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200763 DICTKEY_GET_NOTEMPTY(-1)
Bram Moolenaardb913952012-06-29 12:54:53 +0200764
765 di = dict_find(d, key, -1);
766
767 if (valObject == NULL)
768 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +0200769 hashitem_T *hi;
770
Bram Moolenaardb913952012-06-29 12:54:53 +0200771 if (di == NULL)
772 {
Bram Moolenaar696c2112012-09-21 13:43:14 +0200773 DICTKEY_UNREF
Bram Moolenaar4d188da2013-05-15 15:35:09 +0200774 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +0200775 return -1;
776 }
Bram Moolenaarf27839c2012-06-29 16:19:50 +0200777 hi = hash_find(&d->dv_hashtab, di->di_key);
Bram Moolenaardb913952012-06-29 12:54:53 +0200778 hash_remove(&d->dv_hashtab, hi);
779 dictitem_free(di);
780 return 0;
781 }
782
783 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +0200784 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +0200785
786 if (di == NULL)
787 {
788 di = dictitem_alloc(key);
789 if (di == NULL)
790 {
791 PyErr_NoMemory();
792 return -1;
793 }
794 di->di_tv.v_lock = 0;
795
796 if (dict_add(d, di) == FAIL)
797 {
Bram Moolenaar696c2112012-09-21 13:43:14 +0200798 DICTKEY_UNREF
Bram Moolenaardb913952012-06-29 12:54:53 +0200799 vim_free(di);
800 PyErr_SetVim(_("failed to add key to dictionary"));
801 return -1;
802 }
803 }
804 else
805 clear_tv(&di->di_tv);
806
807 DICTKEY_UNREF
808
809 copy_tv(&tv, &di->di_tv);
810 return 0;
811}
812
813 static PyObject *
Bram Moolenaarb2c5a5a2013-02-14 22:11:39 +0100814DictionaryListKeys(PyObject *self UNUSED)
Bram Moolenaardb913952012-06-29 12:54:53 +0200815{
816 dict_T *dict = ((DictionaryObject *)(self))->dict;
817 long_u todo = dict->dv_hashtab.ht_used;
818 Py_ssize_t i = 0;
819 PyObject *r;
820 hashitem_T *hi;
821
822 r = PyList_New(todo);
823 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
824 {
825 if (!HASHITEM_EMPTY(hi))
826 {
827 PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key)));
828 --todo;
829 ++i;
830 }
831 }
832 return r;
833}
834
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200835static PyMappingMethods DictionaryAsMapping = {
836 (lenfunc) DictionaryLength,
837 (binaryfunc) DictionaryItem,
838 (objobjargproc) DictionaryAssItem,
839};
840
Bram Moolenaardb913952012-06-29 12:54:53 +0200841static struct PyMethodDef DictionaryMethods[] = {
842 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
843 { NULL, NULL, 0, NULL }
844};
845
846static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200847static PySequenceMethods ListAsSeq;
848static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +0200849
850typedef struct
851{
852 PyObject_HEAD
853 list_T *list;
854 pylinkedlist_T ref;
855} ListObject;
856
857 static PyObject *
858ListNew(list_T *list)
859{
860 ListObject *self;
861
862 self = PyObject_NEW(ListObject, &ListType);
863 if (self == NULL)
864 return NULL;
865 self->list = list;
866 ++list->lv_refcount;
867
868 pyll_add((PyObject *)(self), &self->ref, &lastlist);
869
870 return (PyObject *)(self);
871}
872
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200873 static void
874ListDestructor(PyObject *self)
875{
876 ListObject *this = (ListObject *)(self);
877
878 pyll_remove(&this->ref, &lastlist);
879 list_unref(this->list);
880
881 DESTRUCTOR_FINISH(self);
882}
883
Bram Moolenaardb913952012-06-29 12:54:53 +0200884 static int
885list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict)
886{
887 Py_ssize_t i;
888 Py_ssize_t lsize = PySequence_Size(obj);
889 PyObject *litem;
890 listitem_T *li;
891
892 for(i=0; i<lsize; i++)
893 {
894 li = listitem_alloc();
895 if (li == NULL)
896 {
897 PyErr_NoMemory();
898 return -1;
899 }
900 li->li_tv.v_lock = 0;
901
902 litem = PySequence_GetItem(obj, i);
903 if (litem == NULL)
904 return -1;
905 if (_ConvertFromPyObject(litem, &li->li_tv, lookupDict) == -1)
906 return -1;
907
908 list_append(l, li);
909 }
910 return 0;
911}
912
Bram Moolenaardb913952012-06-29 12:54:53 +0200913 static PyInt
914ListLength(PyObject *self)
915{
916 return ((PyInt) (((ListObject *) (self))->list->lv_len));
917}
918
919 static PyObject *
920ListItem(PyObject *self, Py_ssize_t index)
921{
922 listitem_T *li;
923
924 if (index>=ListLength(self))
925 {
Bram Moolenaar8661b172013-05-15 15:44:28 +0200926 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +0200927 return NULL;
928 }
929 li = list_find(((ListObject *) (self))->list, (long) index);
930 if (li == NULL)
931 {
932 PyErr_SetVim(_("internal error: failed to get vim list item"));
933 return NULL;
934 }
935 return ConvertToPyObject(&li->li_tv);
936}
937
938#define PROC_RANGE \
939 if (last < 0) {\
940 if (last < -size) \
941 last = 0; \
942 else \
943 last += size; \
944 } \
945 if (first < 0) \
946 first = 0; \
947 if (first > size) \
948 first = size; \
949 if (last > size) \
950 last = size;
951
952 static PyObject *
953ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last)
954{
955 PyInt i;
956 PyInt size = ListLength(self);
957 PyInt n;
958 PyObject *list;
959 int reversed = 0;
960
961 PROC_RANGE
962 if (first >= last)
963 first = last;
964
965 n = last-first;
966 list = PyList_New(n);
967 if (list == NULL)
968 return NULL;
969
970 for (i = 0; i < n; ++i)
971 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +0200972 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +0200973 if (item == NULL)
974 {
975 Py_DECREF(list);
976 return NULL;
977 }
978
979 if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item)))
980 {
981 Py_DECREF(item);
982 Py_DECREF(list);
983 return NULL;
984 }
985 }
986
987 return list;
988}
989
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200990typedef struct
991{
992 listwatch_T lw;
993 list_T *list;
994} listiterinfo_T;
995
996 static void
997ListIterDestruct(listiterinfo_T *lii)
998{
999 list_rem_watch(lii->list, &lii->lw);
1000 PyMem_Free(lii);
1001}
1002
1003 static PyObject *
1004ListIterNext(listiterinfo_T **lii)
1005{
1006 PyObject *r;
1007
1008 if (!((*lii)->lw.lw_item))
1009 return NULL;
1010
1011 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
1012 return NULL;
1013
1014 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
1015
1016 return r;
1017}
1018
1019 static PyObject *
1020ListIter(PyObject *self)
1021{
1022 listiterinfo_T *lii;
1023 list_T *l = ((ListObject *) (self))->list;
1024
1025 if (!(lii = PyMem_New(listiterinfo_T, 1)))
1026 {
1027 PyErr_NoMemory();
1028 return NULL;
1029 }
1030
1031 list_add_watch(l, &lii->lw);
1032 lii->lw.lw_item = l->lv_first;
1033 lii->list = l;
1034
1035 return IterNew(lii,
1036 (destructorfun) ListIterDestruct, (nextfun) ListIterNext);
1037}
1038
Bram Moolenaardb913952012-06-29 12:54:53 +02001039 static int
1040ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
1041{
1042 typval_T tv;
1043 list_T *l = ((ListObject *) (self))->list;
1044 listitem_T *li;
1045 Py_ssize_t length = ListLength(self);
1046
1047 if (l->lv_lock)
1048 {
1049 PyErr_SetVim(_("list is locked"));
1050 return -1;
1051 }
1052 if (index>length || (index==length && obj==NULL))
1053 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001054 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001055 return -1;
1056 }
1057
1058 if (obj == NULL)
1059 {
1060 li = list_find(l, (long) index);
1061 list_remove(l, li, li);
1062 clear_tv(&li->li_tv);
1063 vim_free(li);
1064 return 0;
1065 }
1066
1067 if (ConvertFromPyObject(obj, &tv) == -1)
1068 return -1;
1069
1070 if (index == length)
1071 {
1072 if (list_append_tv(l, &tv) == FAIL)
1073 {
1074 PyErr_SetVim(_("Failed to add item to list"));
1075 return -1;
1076 }
1077 }
1078 else
1079 {
1080 li = list_find(l, (long) index);
1081 clear_tv(&li->li_tv);
1082 copy_tv(&tv, &li->li_tv);
1083 }
1084 return 0;
1085}
1086
1087 static int
1088ListAssSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
1089{
1090 PyInt size = ListLength(self);
1091 Py_ssize_t i;
1092 Py_ssize_t lsize;
1093 PyObject *litem;
1094 listitem_T *li;
1095 listitem_T *next;
1096 typval_T v;
1097 list_T *l = ((ListObject *) (self))->list;
1098
1099 if (l->lv_lock)
1100 {
1101 PyErr_SetVim(_("list is locked"));
1102 return -1;
1103 }
1104
1105 PROC_RANGE
1106
1107 if (first == size)
1108 li = NULL;
1109 else
1110 {
1111 li = list_find(l, (long) first);
1112 if (li == NULL)
1113 {
1114 PyErr_SetVim(_("internal error: no vim list item"));
1115 return -1;
1116 }
1117 if (last > first)
1118 {
1119 i = last - first;
1120 while (i-- && li != NULL)
1121 {
1122 next = li->li_next;
1123 listitem_remove(l, li);
1124 li = next;
1125 }
1126 }
1127 }
1128
1129 if (obj == NULL)
1130 return 0;
1131
1132 if (!PyList_Check(obj))
1133 {
1134 PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
1135 return -1;
1136 }
1137
1138 lsize = PyList_Size(obj);
1139
1140 for(i=0; i<lsize; i++)
1141 {
1142 litem = PyList_GetItem(obj, i);
1143 if (litem == NULL)
1144 return -1;
1145 if (ConvertFromPyObject(litem, &v) == -1)
1146 return -1;
1147 if (list_insert_tv(l, &v, li) == FAIL)
1148 {
1149 PyErr_SetVim(_("internal error: failed to add item to list"));
1150 return -1;
1151 }
1152 }
1153 return 0;
1154}
1155
1156 static PyObject *
1157ListConcatInPlace(PyObject *self, PyObject *obj)
1158{
1159 list_T *l = ((ListObject *) (self))->list;
1160 PyObject *lookup_dict;
1161
1162 if (l->lv_lock)
1163 {
1164 PyErr_SetVim(_("list is locked"));
1165 return NULL;
1166 }
1167
1168 if (!PySequence_Check(obj))
1169 {
1170 PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
1171 return NULL;
1172 }
1173
1174 lookup_dict = PyDict_New();
1175 if (list_py_concat(l, obj, lookup_dict) == -1)
1176 {
1177 Py_DECREF(lookup_dict);
1178 return NULL;
1179 }
1180 Py_DECREF(lookup_dict);
1181
1182 Py_INCREF(self);
1183 return self;
1184}
1185
Bram Moolenaar66b79852012-09-21 14:00:35 +02001186 static int
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001187ListSetattr(PyObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001188{
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001189 ListObject *this = (ListObject *)(self);
1190
Bram Moolenaar66b79852012-09-21 14:00:35 +02001191 if (val == NULL)
1192 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001193 PyErr_SetString(PyExc_AttributeError,
1194 _("cannot delete vim.dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001195 return -1;
1196 }
1197
1198 if (strcmp(name, "locked") == 0)
1199 {
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001200 if (this->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001201 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001202 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001203 return -1;
1204 }
1205 else
1206 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001207 int istrue = PyObject_IsTrue(val);
1208 if (istrue == -1)
1209 return -1;
1210 else if (istrue)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001211 this->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001212 else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001213 this->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001214 }
1215 return 0;
1216 }
1217 else
1218 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001219 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001220 return -1;
1221 }
1222}
1223
Bram Moolenaardb913952012-06-29 12:54:53 +02001224static struct PyMethodDef ListMethods[] = {
1225 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
1226 { NULL, NULL, 0, NULL }
1227};
1228
1229typedef struct
1230{
1231 PyObject_HEAD
1232 char_u *name;
1233} FunctionObject;
1234
1235static PyTypeObject FunctionType;
1236
1237 static PyObject *
1238FunctionNew(char_u *name)
1239{
1240 FunctionObject *self;
1241
1242 self = PyObject_NEW(FunctionObject, &FunctionType);
1243 if (self == NULL)
1244 return NULL;
1245 self->name = PyMem_New(char_u, STRLEN(name) + 1);
1246 if (self->name == NULL)
1247 {
1248 PyErr_NoMemory();
1249 return NULL;
1250 }
1251 STRCPY(self->name, name);
1252 func_ref(name);
1253 return (PyObject *)(self);
1254}
1255
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001256 static void
1257FunctionDestructor(PyObject *self)
1258{
1259 FunctionObject *this = (FunctionObject *) (self);
1260
1261 func_unref(this->name);
1262 PyMem_Del(this->name);
1263
1264 DESTRUCTOR_FINISH(self);
1265}
1266
Bram Moolenaardb913952012-06-29 12:54:53 +02001267 static PyObject *
1268FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs)
1269{
1270 FunctionObject *this = (FunctionObject *)(self);
1271 char_u *name = this->name;
1272 typval_T args;
1273 typval_T selfdicttv;
1274 typval_T rettv;
1275 dict_T *selfdict = NULL;
1276 PyObject *selfdictObject;
1277 PyObject *result;
1278 int error;
1279
1280 if (ConvertFromPyObject(argsObject, &args) == -1)
1281 return NULL;
1282
1283 if (kwargs != NULL)
1284 {
1285 selfdictObject = PyDict_GetItemString(kwargs, "self");
1286 if (selfdictObject != NULL)
1287 {
Bram Moolenaar9581b5f2012-07-25 15:36:04 +02001288 if (!PyMapping_Check(selfdictObject))
Bram Moolenaardb913952012-06-29 12:54:53 +02001289 {
Bram Moolenaar9581b5f2012-07-25 15:36:04 +02001290 PyErr_SetString(PyExc_TypeError,
1291 _("'self' argument must be a dictionary"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001292 clear_tv(&args);
1293 return NULL;
1294 }
1295 if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
1296 return NULL;
1297 selfdict = selfdicttv.vval.v_dict;
1298 }
1299 }
1300
Bram Moolenaar71700b82013-05-15 17:49:05 +02001301 Py_BEGIN_ALLOW_THREADS
1302 Python_Lock_Vim();
1303
Bram Moolenaardb913952012-06-29 12:54:53 +02001304 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02001305
1306 Python_Release_Vim();
1307 Py_END_ALLOW_THREADS
1308
Bram Moolenaardb913952012-06-29 12:54:53 +02001309 if (error != OK)
1310 {
1311 result = NULL;
1312 PyErr_SetVim(_("failed to run function"));
1313 }
1314 else
1315 result = ConvertToPyObject(&rettv);
1316
1317 /* FIXME Check what should really be cleared. */
1318 clear_tv(&args);
1319 clear_tv(&rettv);
1320 /*
1321 * if (selfdict!=NULL)
1322 * clear_tv(selfdicttv);
1323 */
1324
1325 return result;
1326}
1327
1328static struct PyMethodDef FunctionMethods[] = {
1329 {"__call__", (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
1330 { NULL, NULL, 0, NULL }
1331};
1332
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001333/*
1334 * Options object
1335 */
1336
1337static PyTypeObject OptionsType;
1338
1339typedef int (*checkfun)(void *);
1340
1341typedef struct
1342{
1343 PyObject_HEAD
1344 int opt_type;
1345 void *from;
1346 checkfun Check;
1347 PyObject *fromObj;
1348} OptionsObject;
1349
1350 static PyObject *
1351OptionsItem(OptionsObject *this, PyObject *keyObject)
1352{
1353 char_u *key;
1354 int flags;
1355 long numval;
1356 char_u *stringval;
Bram Moolenaar161fb5e2013-05-06 06:26:15 +02001357 DICTKEY_DECL
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001358
1359 if (this->Check(this->from))
1360 return NULL;
1361
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001362 DICTKEY_GET_NOTEMPTY(NULL)
1363
1364 flags = get_option_value_strict(key, &numval, &stringval,
1365 this->opt_type, this->from);
1366
1367 DICTKEY_UNREF
1368
1369 if (flags == 0)
1370 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001371 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001372 return NULL;
1373 }
1374
1375 if (flags & SOPT_UNSET)
1376 {
1377 Py_INCREF(Py_None);
1378 return Py_None;
1379 }
1380 else if (flags & SOPT_BOOL)
1381 {
1382 PyObject *r;
1383 r = numval ? Py_True : Py_False;
1384 Py_INCREF(r);
1385 return r;
1386 }
1387 else if (flags & SOPT_NUM)
1388 return PyInt_FromLong(numval);
1389 else if (flags & SOPT_STRING)
1390 {
1391 if (stringval)
1392 return PyBytes_FromString((char *) stringval);
1393 else
1394 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001395 PyErr_SetString(PyExc_RuntimeError,
1396 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001397 return NULL;
1398 }
1399 }
1400 else
1401 {
1402 PyErr_SetVim("Internal error: unknown option type. Should not happen");
1403 return NULL;
1404 }
1405}
1406
1407 static int
1408set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
1409 char_u *key;
1410 int numval;
1411 char_u *stringval;
1412 int opt_flags;
1413 int opt_type;
1414 void *from;
1415{
1416 win_T *save_curwin;
1417 tabpage_T *save_curtab;
1418 aco_save_T aco;
1419 int r = 0;
1420
1421 switch (opt_type)
1422 {
1423 case SREQ_WIN:
1424 if (switch_win(&save_curwin, &save_curtab, (win_T *) from, curtab)
1425 == FAIL)
1426 {
1427 PyErr_SetVim("Problem while switching windows.");
1428 return -1;
1429 }
1430 set_option_value(key, numval, stringval, opt_flags);
1431 restore_win(save_curwin, save_curtab);
1432 break;
1433 case SREQ_BUF:
1434 aucmd_prepbuf(&aco, (buf_T *) from);
1435 set_option_value(key, numval, stringval, opt_flags);
1436 aucmd_restbuf(&aco);
1437 break;
1438 case SREQ_GLOBAL:
1439 set_option_value(key, numval, stringval, opt_flags);
1440 break;
1441 }
1442 return r;
1443}
1444
1445 static int
1446OptionsAssItem(OptionsObject *this, PyObject *keyObject, PyObject *valObject)
1447{
1448 char_u *key;
1449 int flags;
1450 int opt_flags;
1451 int r = 0;
Bram Moolenaar161fb5e2013-05-06 06:26:15 +02001452 DICTKEY_DECL
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001453
1454 if (this->Check(this->from))
1455 return -1;
1456
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001457 DICTKEY_GET_NOTEMPTY(-1)
1458
1459 flags = get_option_value_strict(key, NULL, NULL,
1460 this->opt_type, this->from);
1461
1462 DICTKEY_UNREF
1463
1464 if (flags == 0)
1465 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001466 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001467 return -1;
1468 }
1469
1470 if (valObject == NULL)
1471 {
1472 if (this->opt_type == SREQ_GLOBAL)
1473 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001474 PyErr_SetString(PyExc_ValueError,
1475 _("unable to unset global option"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001476 return -1;
1477 }
1478 else if (!(flags & SOPT_GLOBAL))
1479 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001480 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
1481 "without global value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001482 return -1;
1483 }
1484 else
1485 {
1486 unset_global_local_option(key, this->from);
1487 return 0;
1488 }
1489 }
1490
1491 opt_flags = (this->opt_type ? OPT_LOCAL : OPT_GLOBAL);
1492
1493 if (flags & SOPT_BOOL)
1494 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001495 int istrue = PyObject_IsTrue(valObject);
1496 if (istrue == -1)
1497 return -1;
1498 r = set_option_value_for(key, istrue, NULL,
Bram Moolenaar03db85b2013-05-15 14:51:35 +02001499 opt_flags, this->opt_type, this->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001500 }
1501 else if (flags & SOPT_NUM)
1502 {
1503 int val;
1504
1505#if PY_MAJOR_VERSION < 3
1506 if (PyInt_Check(valObject))
1507 val = PyInt_AsLong(valObject);
1508 else
1509#endif
1510 if (PyLong_Check(valObject))
1511 val = PyLong_AsLong(valObject);
1512 else
1513 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001514 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001515 return -1;
1516 }
1517
1518 r = set_option_value_for(key, val, NULL, opt_flags,
1519 this->opt_type, this->from);
1520 }
1521 else
1522 {
1523 char_u *val;
1524 if (PyBytes_Check(valObject))
1525 {
1526
1527 if (PyString_AsStringAndSize(valObject, (char **) &val, NULL) == -1)
1528 return -1;
1529 if (val == NULL)
1530 return -1;
1531
1532 val = vim_strsave(val);
1533 }
1534 else if (PyUnicode_Check(valObject))
1535 {
1536 PyObject *bytes;
1537
1538 bytes = PyUnicode_AsEncodedString(valObject, (char *)ENC_OPT, NULL);
1539 if (bytes == NULL)
1540 return -1;
1541
1542 if(PyString_AsStringAndSize(bytes, (char **) &val, NULL) == -1)
1543 return -1;
1544 if (val == NULL)
1545 return -1;
1546
1547 val = vim_strsave(val);
1548 Py_XDECREF(bytes);
1549 }
1550 else
1551 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001552 PyErr_SetString(PyExc_TypeError, _("object must be string"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001553 return -1;
1554 }
1555
1556 r = set_option_value_for(key, 0, val, opt_flags,
1557 this->opt_type, this->from);
1558 vim_free(val);
1559 }
1560
1561 return r;
1562}
1563
1564 static int
1565dummy_check(void *arg UNUSED)
1566{
1567 return 0;
1568}
1569
1570 static PyObject *
1571OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
1572{
1573 OptionsObject *self;
1574
1575 self = PyObject_NEW(OptionsObject, &OptionsType);
1576 if (self == NULL)
1577 return NULL;
1578
1579 self->opt_type = opt_type;
1580 self->from = from;
1581 self->Check = Check;
1582 self->fromObj = fromObj;
1583 if (fromObj)
1584 Py_INCREF(fromObj);
1585
1586 return (PyObject *)(self);
1587}
1588
1589 static void
1590OptionsDestructor(PyObject *self)
1591{
1592 if (((OptionsObject *)(self))->fromObj)
1593 Py_DECREF(((OptionsObject *)(self))->fromObj);
1594 DESTRUCTOR_FINISH(self);
1595}
1596
1597static PyMappingMethods OptionsAsMapping = {
1598 (lenfunc) NULL,
1599 (binaryfunc) OptionsItem,
1600 (objobjargproc) OptionsAssItem,
1601};
1602
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001603/* Tabpage object
1604 */
1605
1606typedef struct
1607{
1608 PyObject_HEAD
1609 tabpage_T *tab;
1610} TabPageObject;
1611
1612static PyObject *WinListNew(TabPageObject *tabObject);
1613
1614static PyTypeObject TabPageType;
1615
1616 static int
1617CheckTabPage(TabPageObject *this)
1618{
1619 if (this->tab == INVALID_TABPAGE_VALUE)
1620 {
1621 PyErr_SetVim(_("attempt to refer to deleted tab page"));
1622 return -1;
1623 }
1624
1625 return 0;
1626}
1627
1628 static PyObject *
1629TabPageNew(tabpage_T *tab)
1630{
1631 TabPageObject *self;
1632
1633 if (TAB_PYTHON_REF(tab))
1634 {
1635 self = TAB_PYTHON_REF(tab);
1636 Py_INCREF(self);
1637 }
1638 else
1639 {
1640 self = PyObject_NEW(TabPageObject, &TabPageType);
1641 if (self == NULL)
1642 return NULL;
1643 self->tab = tab;
1644 TAB_PYTHON_REF(tab) = self;
1645 }
1646
1647 return (PyObject *)(self);
1648}
1649
1650 static void
1651TabPageDestructor(PyObject *self)
1652{
1653 TabPageObject *this = (TabPageObject *)(self);
1654
1655 if (this->tab && this->tab != INVALID_TABPAGE_VALUE)
1656 TAB_PYTHON_REF(this->tab) = NULL;
1657
1658 DESTRUCTOR_FINISH(self);
1659}
1660
1661 static PyObject *
1662TabPageAttr(TabPageObject *this, char *name)
1663{
1664 if (strcmp(name, "windows") == 0)
1665 return WinListNew(this);
1666 else if (strcmp(name, "number") == 0)
1667 return PyLong_FromLong((long) get_tab_number(this->tab));
1668 else if (strcmp(name, "vars") == 0)
1669 return DictionaryNew(this->tab->tp_vars);
1670 else if (strcmp(name, "window") == 0)
1671 {
1672 /* For current tab window.c does not bother to set or update tp_curwin
1673 */
1674 if (this->tab == curtab)
1675 return WindowNew(curwin);
1676 else
1677 return WindowNew(this->tab->tp_curwin);
1678 }
1679 return NULL;
1680}
1681
1682 static PyObject *
1683TabPageRepr(PyObject *self)
1684{
1685 static char repr[100];
1686 TabPageObject *this = (TabPageObject *)(self);
1687
1688 if (this->tab == INVALID_TABPAGE_VALUE)
1689 {
1690 vim_snprintf(repr, 100, _("<tabpage object (deleted) at %p>"), (self));
1691 return PyString_FromString(repr);
1692 }
1693 else
1694 {
1695 int t = get_tab_number(this->tab);
1696
1697 if (t == 0)
1698 vim_snprintf(repr, 100, _("<tabpage object (unknown) at %p>"),
1699 (self));
1700 else
1701 vim_snprintf(repr, 100, _("<tabpage %d>"), t - 1);
1702
1703 return PyString_FromString(repr);
1704 }
1705}
1706
1707static struct PyMethodDef TabPageMethods[] = {
1708 /* name, function, calling, documentation */
1709 { NULL, NULL, 0, NULL }
1710};
1711
1712/*
1713 * Window list object
1714 */
1715
1716static PyTypeObject TabListType;
1717static PySequenceMethods TabListAsSeq;
1718
1719typedef struct
1720{
1721 PyObject_HEAD
1722} TabListObject;
1723
1724 static PyInt
1725TabListLength(PyObject *self UNUSED)
1726{
1727 tabpage_T *tp = first_tabpage;
1728 PyInt n = 0;
1729
1730 while (tp != NULL)
1731 {
1732 ++n;
1733 tp = tp->tp_next;
1734 }
1735
1736 return n;
1737}
1738
1739 static PyObject *
1740TabListItem(PyObject *self UNUSED, PyInt n)
1741{
1742 tabpage_T *tp;
1743
1744 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
1745 if (n == 0)
1746 return TabPageNew(tp);
1747
1748 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
1749 return NULL;
1750}
1751
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001752/* Window object
1753 */
1754
1755typedef struct
1756{
1757 PyObject_HEAD
1758 win_T *win;
1759} WindowObject;
1760
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001761static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001762
1763 static int
1764CheckWindow(WindowObject *this)
1765{
1766 if (this->win == INVALID_WINDOW_VALUE)
1767 {
1768 PyErr_SetVim(_("attempt to refer to deleted window"));
1769 return -1;
1770 }
1771
1772 return 0;
1773}
1774
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001775 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02001776WindowNew(win_T *win)
1777{
1778 /* We need to handle deletion of windows underneath us.
1779 * If we add a "w_python*_ref" field to the win_T structure,
1780 * then we can get at it in win_free() in vim. We then
1781 * need to create only ONE Python object per window - if
1782 * we try to create a second, just INCREF the existing one
1783 * and return it. The (single) Python object referring to
1784 * the window is stored in "w_python*_ref".
1785 * On a win_free() we set the Python object's win_T* field
1786 * to an invalid value. We trap all uses of a window
1787 * object, and reject them if the win_T* field is invalid.
1788 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001789 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02001790 * w_python_ref and w_python3_ref fields respectively.
1791 */
1792
1793 WindowObject *self;
1794
1795 if (WIN_PYTHON_REF(win))
1796 {
1797 self = WIN_PYTHON_REF(win);
1798 Py_INCREF(self);
1799 }
1800 else
1801 {
1802 self = PyObject_NEW(WindowObject, &WindowType);
1803 if (self == NULL)
1804 return NULL;
1805 self->win = win;
1806 WIN_PYTHON_REF(win) = self;
1807 }
1808
1809 return (PyObject *)(self);
1810}
1811
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001812 static void
1813WindowDestructor(PyObject *self)
1814{
1815 WindowObject *this = (WindowObject *)(self);
1816
1817 if (this->win && this->win != INVALID_WINDOW_VALUE)
1818 WIN_PYTHON_REF(this->win) = NULL;
1819
1820 DESTRUCTOR_FINISH(self);
1821}
1822
Bram Moolenaar971db462013-05-12 18:44:48 +02001823 static PyObject *
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001824WindowAttr(WindowObject *this, char *name)
1825{
1826 if (strcmp(name, "buffer") == 0)
1827 return (PyObject *)BufferNew(this->win->w_buffer);
1828 else if (strcmp(name, "cursor") == 0)
1829 {
1830 pos_T *pos = &this->win->w_cursor;
1831
1832 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
1833 }
1834 else if (strcmp(name, "height") == 0)
Bram Moolenaar99add412013-05-12 19:09:51 +02001835 return PyLong_FromLong((long)(this->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02001836#ifdef FEAT_WINDOWS
1837 else if (strcmp(name, "row") == 0)
1838 return PyLong_FromLong((long)(this->win->w_winrow));
1839#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001840#ifdef FEAT_VERTSPLIT
1841 else if (strcmp(name, "width") == 0)
Bram Moolenaar99add412013-05-12 19:09:51 +02001842 return PyLong_FromLong((long)(W_WIDTH(this->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02001843 else if (strcmp(name, "col") == 0)
1844 return PyLong_FromLong((long)(W_WINCOL(this->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001845#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02001846 else if (strcmp(name, "vars") == 0)
1847 return DictionaryNew(this->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001848 else if (strcmp(name, "options") == 0)
1849 return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
1850 (PyObject *) this);
Bram Moolenaar6d216452013-05-12 19:00:41 +02001851 else if (strcmp(name, "number") == 0)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001852 return PyLong_FromLong((long) get_win_number(this->win, firstwin));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001853 else if (strcmp(name,"__members__") == 0)
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02001854 return Py_BuildValue("[ssssssss]", "buffer", "cursor", "height", "vars",
1855 "options", "number", "row", "col");
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001856 else
1857 return NULL;
1858}
1859
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001860 static int
1861WindowSetattr(PyObject *self, char *name, PyObject *val)
1862{
1863 WindowObject *this = (WindowObject *)(self);
1864
1865 if (CheckWindow(this))
1866 return -1;
1867
1868 if (strcmp(name, "buffer") == 0)
1869 {
1870 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
1871 return -1;
1872 }
1873 else if (strcmp(name, "cursor") == 0)
1874 {
1875 long lnum;
1876 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001877
1878 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
1879 return -1;
1880
1881 if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count)
1882 {
1883 PyErr_SetVim(_("cursor position outside buffer"));
1884 return -1;
1885 }
1886
1887 /* Check for keyboard interrupts */
1888 if (VimErrorCheck())
1889 return -1;
1890
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001891 this->win->w_cursor.lnum = lnum;
1892 this->win->w_cursor.col = col;
1893#ifdef FEAT_VIRTUALEDIT
1894 this->win->w_cursor.coladd = 0;
1895#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02001896 /* When column is out of range silently correct it. */
1897 check_cursor_col_win(this->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001898
Bram Moolenaar03a807a2011-07-07 15:08:58 +02001899 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001900 return 0;
1901 }
1902 else if (strcmp(name, "height") == 0)
1903 {
1904 int height;
1905 win_T *savewin;
1906
1907 if (!PyArg_Parse(val, "i", &height))
1908 return -1;
1909
1910#ifdef FEAT_GUI
1911 need_mouse_correct = TRUE;
1912#endif
1913 savewin = curwin;
1914 curwin = this->win;
1915 win_setheight(height);
1916 curwin = savewin;
1917
1918 /* Check for keyboard interrupts */
1919 if (VimErrorCheck())
1920 return -1;
1921
1922 return 0;
1923 }
1924#ifdef FEAT_VERTSPLIT
1925 else if (strcmp(name, "width") == 0)
1926 {
1927 int width;
1928 win_T *savewin;
1929
1930 if (!PyArg_Parse(val, "i", &width))
1931 return -1;
1932
1933#ifdef FEAT_GUI
1934 need_mouse_correct = TRUE;
1935#endif
1936 savewin = curwin;
1937 curwin = this->win;
1938 win_setwidth(width);
1939 curwin = savewin;
1940
1941 /* Check for keyboard interrupts */
1942 if (VimErrorCheck())
1943 return -1;
1944
1945 return 0;
1946 }
1947#endif
1948 else
1949 {
1950 PyErr_SetString(PyExc_AttributeError, name);
1951 return -1;
1952 }
1953}
1954
1955 static PyObject *
1956WindowRepr(PyObject *self)
1957{
1958 static char repr[100];
1959 WindowObject *this = (WindowObject *)(self);
1960
1961 if (this->win == INVALID_WINDOW_VALUE)
1962 {
1963 vim_snprintf(repr, 100, _("<window object (deleted) at %p>"), (self));
1964 return PyString_FromString(repr);
1965 }
1966 else
1967 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001968 int w = get_win_number(this->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001969
Bram Moolenaar6d216452013-05-12 19:00:41 +02001970 if (w == 0)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001971 vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
1972 (self));
1973 else
Bram Moolenaar6d216452013-05-12 19:00:41 +02001974 vim_snprintf(repr, 100, _("<window %d>"), w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001975
1976 return PyString_FromString(repr);
1977 }
1978}
1979
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001980static struct PyMethodDef WindowMethods[] = {
1981 /* name, function, calling, documentation */
1982 { NULL, NULL, 0, NULL }
1983};
1984
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001985/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001986 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001987 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001988
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001989static PyTypeObject WinListType;
1990static PySequenceMethods WinListAsSeq;
1991
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001992typedef struct
1993{
1994 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001995 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001996} WinListObject;
1997
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001998 static PyObject *
1999WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002000{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002001 WinListObject *self;
2002
2003 self = PyObject_NEW(WinListObject, &WinListType);
2004 self->tabObject = tabObject;
2005 Py_INCREF(tabObject);
2006
2007 return (PyObject *)(self);
2008}
2009
2010 static void
2011WinListDestructor(PyObject *self)
2012{
2013 TabPageObject *tabObject = ((WinListObject *)(self))->tabObject;
2014
2015 if (tabObject)
2016 Py_DECREF((PyObject *)(tabObject));
2017
2018 DESTRUCTOR_FINISH(self);
2019}
2020
2021 static win_T *
2022get_firstwin(WinListObject *this)
2023{
2024 if (this->tabObject)
2025 {
2026 if (CheckTabPage(this->tabObject))
2027 return NULL;
2028 /* For current tab window.c does not bother to set or update tp_firstwin
2029 */
2030 else if (this->tabObject->tab == curtab)
2031 return firstwin;
2032 else
2033 return this->tabObject->tab->tp_firstwin;
2034 }
2035 else
2036 return firstwin;
2037}
2038
2039 static PyInt
2040WinListLength(PyObject *self)
2041{
2042 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002043 PyInt n = 0;
2044
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002045 if (!(w = get_firstwin((WinListObject *)(self))))
2046 return -1;
2047
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002048 while (w != NULL)
2049 {
2050 ++n;
2051 w = W_NEXT(w);
2052 }
2053
2054 return n;
2055}
2056
2057 static PyObject *
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002058WinListItem(PyObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002059{
2060 win_T *w;
2061
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002062 if (!(w = get_firstwin((WinListObject *)(self))))
2063 return NULL;
2064
2065 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002066 if (n == 0)
2067 return WindowNew(w);
2068
2069 PyErr_SetString(PyExc_IndexError, _("no such window"));
2070 return NULL;
2071}
2072
2073/* Convert a Python string into a Vim line.
2074 *
2075 * The result is in allocated memory. All internal nulls are replaced by
2076 * newline characters. It is an error for the string to contain newline
2077 * characters.
2078 *
2079 * On errors, the Python exception data is set, and NULL is returned.
2080 */
2081 static char *
2082StringToLine(PyObject *obj)
2083{
2084 const char *str;
2085 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02002086 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002087 PyInt len;
2088 PyInt i;
2089 char *p;
2090
2091 if (obj == NULL || !PyString_Check(obj))
2092 {
2093 PyErr_BadArgument();
2094 return NULL;
2095 }
2096
Bram Moolenaar19e60942011-06-19 00:27:51 +02002097 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
2098 str = PyString_AsString(bytes);
2099 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002100
2101 /*
2102 * Error checking: String must not contain newlines, as we
2103 * are replacing a single line, and we must replace it with
2104 * a single line.
2105 * A trailing newline is removed, so that append(f.readlines()) works.
2106 */
2107 p = memchr(str, '\n', len);
2108 if (p != NULL)
2109 {
2110 if (p == str + len - 1)
2111 --len;
2112 else
2113 {
2114 PyErr_SetVim(_("string cannot contain newlines"));
2115 return NULL;
2116 }
2117 }
2118
2119 /* Create a copy of the string, with internal nulls replaced by
2120 * newline characters, as is the vim convention.
2121 */
2122 save = (char *)alloc((unsigned)(len+1));
2123 if (save == NULL)
2124 {
2125 PyErr_NoMemory();
2126 return NULL;
2127 }
2128
2129 for (i = 0; i < len; ++i)
2130 {
2131 if (str[i] == '\0')
2132 save[i] = '\n';
2133 else
2134 save[i] = str[i];
2135 }
2136
2137 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02002138 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002139
2140 return save;
2141}
2142
2143/* Get a line from the specified buffer. The line number is
2144 * in Vim format (1-based). The line is returned as a Python
2145 * string object.
2146 */
2147 static PyObject *
2148GetBufferLine(buf_T *buf, PyInt n)
2149{
2150 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
2151}
2152
2153
2154/* Get a list of lines from the specified buffer. The line numbers
2155 * are in Vim format (1-based). The range is from lo up to, but not
2156 * including, hi. The list is returned as a Python list of string objects.
2157 */
2158 static PyObject *
2159GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
2160{
2161 PyInt i;
2162 PyInt n = hi - lo;
2163 PyObject *list = PyList_New(n);
2164
2165 if (list == NULL)
2166 return NULL;
2167
2168 for (i = 0; i < n; ++i)
2169 {
2170 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
2171
2172 /* Error check - was the Python string creation OK? */
2173 if (str == NULL)
2174 {
2175 Py_DECREF(list);
2176 return NULL;
2177 }
2178
2179 /* Set the list item */
2180 if (PyList_SetItem(list, i, str))
2181 {
2182 Py_DECREF(str);
2183 Py_DECREF(list);
2184 return NULL;
2185 }
2186 }
2187
2188 /* The ownership of the Python list is passed to the caller (ie,
2189 * the caller should Py_DECREF() the object when it is finished
2190 * with it).
2191 */
2192
2193 return list;
2194}
2195
2196/*
2197 * Check if deleting lines made the cursor position invalid.
2198 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
2199 * deleted).
2200 */
2201 static void
2202py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
2203{
2204 if (curwin->w_cursor.lnum >= lo)
2205 {
2206 /* Adjust the cursor position if it's in/after the changed
2207 * lines. */
2208 if (curwin->w_cursor.lnum >= hi)
2209 {
2210 curwin->w_cursor.lnum += extra;
2211 check_cursor_col();
2212 }
2213 else if (extra < 0)
2214 {
2215 curwin->w_cursor.lnum = lo;
2216 check_cursor();
2217 }
2218 else
2219 check_cursor_col();
2220 changed_cline_bef_curs();
2221 }
2222 invalidate_botline();
2223}
2224
Bram Moolenaar19e60942011-06-19 00:27:51 +02002225/*
2226 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002227 * in Vim format (1-based). The replacement line is given as
2228 * a Python string object. The object is checked for validity
2229 * and correct format. Errors are returned as a value of FAIL.
2230 * The return value is OK on success.
2231 * If OK is returned and len_change is not NULL, *len_change
2232 * is set to the change in the buffer length.
2233 */
2234 static int
2235SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
2236{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002237 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002238 * There are three cases:
2239 * 1. NULL, or None - this is a deletion.
2240 * 2. A string - this is a replacement.
2241 * 3. Anything else - this is an error.
2242 */
2243 if (line == Py_None || line == NULL)
2244 {
2245 buf_T *savebuf = curbuf;
2246
2247 PyErr_Clear();
2248 curbuf = buf;
2249
2250 if (u_savedel((linenr_T)n, 1L) == FAIL)
2251 PyErr_SetVim(_("cannot save undo information"));
2252 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
2253 PyErr_SetVim(_("cannot delete line"));
2254 else
2255 {
2256 if (buf == curwin->w_buffer)
2257 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
2258 deleted_lines_mark((linenr_T)n, 1L);
2259 }
2260
2261 curbuf = savebuf;
2262
2263 if (PyErr_Occurred() || VimErrorCheck())
2264 return FAIL;
2265
2266 if (len_change)
2267 *len_change = -1;
2268
2269 return OK;
2270 }
2271 else if (PyString_Check(line))
2272 {
2273 char *save = StringToLine(line);
2274 buf_T *savebuf = curbuf;
2275
2276 if (save == NULL)
2277 return FAIL;
2278
2279 /* We do not need to free "save" if ml_replace() consumes it. */
2280 PyErr_Clear();
2281 curbuf = buf;
2282
2283 if (u_savesub((linenr_T)n) == FAIL)
2284 {
2285 PyErr_SetVim(_("cannot save undo information"));
2286 vim_free(save);
2287 }
2288 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
2289 {
2290 PyErr_SetVim(_("cannot replace line"));
2291 vim_free(save);
2292 }
2293 else
2294 changed_bytes((linenr_T)n, 0);
2295
2296 curbuf = savebuf;
2297
2298 /* Check that the cursor is not beyond the end of the line now. */
2299 if (buf == curwin->w_buffer)
2300 check_cursor_col();
2301
2302 if (PyErr_Occurred() || VimErrorCheck())
2303 return FAIL;
2304
2305 if (len_change)
2306 *len_change = 0;
2307
2308 return OK;
2309 }
2310 else
2311 {
2312 PyErr_BadArgument();
2313 return FAIL;
2314 }
2315}
2316
Bram Moolenaar19e60942011-06-19 00:27:51 +02002317/* Replace a range of lines in the specified buffer. The line numbers are in
2318 * Vim format (1-based). The range is from lo up to, but not including, hi.
2319 * The replacement lines are given as a Python list of string objects. The
2320 * list is checked for validity and correct format. Errors are returned as a
2321 * value of FAIL. The return value is OK on success.
2322 * If OK is returned and len_change is not NULL, *len_change
2323 * is set to the change in the buffer length.
2324 */
2325 static int
2326SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
2327{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002328 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02002329 * There are three cases:
2330 * 1. NULL, or None - this is a deletion.
2331 * 2. A list - this is a replacement.
2332 * 3. Anything else - this is an error.
2333 */
2334 if (list == Py_None || list == NULL)
2335 {
2336 PyInt i;
2337 PyInt n = (int)(hi - lo);
2338 buf_T *savebuf = curbuf;
2339
2340 PyErr_Clear();
2341 curbuf = buf;
2342
2343 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
2344 PyErr_SetVim(_("cannot save undo information"));
2345 else
2346 {
2347 for (i = 0; i < n; ++i)
2348 {
2349 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
2350 {
2351 PyErr_SetVim(_("cannot delete line"));
2352 break;
2353 }
2354 }
2355 if (buf == curwin->w_buffer)
2356 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
2357 deleted_lines_mark((linenr_T)lo, (long)i);
2358 }
2359
2360 curbuf = savebuf;
2361
2362 if (PyErr_Occurred() || VimErrorCheck())
2363 return FAIL;
2364
2365 if (len_change)
2366 *len_change = -n;
2367
2368 return OK;
2369 }
2370 else if (PyList_Check(list))
2371 {
2372 PyInt i;
2373 PyInt new_len = PyList_Size(list);
2374 PyInt old_len = hi - lo;
2375 PyInt extra = 0; /* lines added to text, can be negative */
2376 char **array;
2377 buf_T *savebuf;
2378
2379 if (new_len == 0) /* avoid allocating zero bytes */
2380 array = NULL;
2381 else
2382 {
2383 array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
2384 if (array == NULL)
2385 {
2386 PyErr_NoMemory();
2387 return FAIL;
2388 }
2389 }
2390
2391 for (i = 0; i < new_len; ++i)
2392 {
2393 PyObject *line = PyList_GetItem(list, i);
2394
2395 array[i] = StringToLine(line);
2396 if (array[i] == NULL)
2397 {
2398 while (i)
2399 vim_free(array[--i]);
2400 vim_free(array);
2401 return FAIL;
2402 }
2403 }
2404
2405 savebuf = curbuf;
2406
2407 PyErr_Clear();
2408 curbuf = buf;
2409
2410 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
2411 PyErr_SetVim(_("cannot save undo information"));
2412
2413 /* If the size of the range is reducing (ie, new_len < old_len) we
2414 * need to delete some old_len. We do this at the start, by
2415 * repeatedly deleting line "lo".
2416 */
2417 if (!PyErr_Occurred())
2418 {
2419 for (i = 0; i < old_len - new_len; ++i)
2420 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
2421 {
2422 PyErr_SetVim(_("cannot delete line"));
2423 break;
2424 }
2425 extra -= i;
2426 }
2427
2428 /* For as long as possible, replace the existing old_len with the
2429 * new old_len. This is a more efficient operation, as it requires
2430 * less memory allocation and freeing.
2431 */
2432 if (!PyErr_Occurred())
2433 {
2434 for (i = 0; i < old_len && i < new_len; ++i)
2435 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
2436 == FAIL)
2437 {
2438 PyErr_SetVim(_("cannot replace line"));
2439 break;
2440 }
2441 }
2442 else
2443 i = 0;
2444
2445 /* Now we may need to insert the remaining new old_len. If we do, we
2446 * must free the strings as we finish with them (we can't pass the
2447 * responsibility to vim in this case).
2448 */
2449 if (!PyErr_Occurred())
2450 {
2451 while (i < new_len)
2452 {
2453 if (ml_append((linenr_T)(lo + i - 1),
2454 (char_u *)array[i], 0, FALSE) == FAIL)
2455 {
2456 PyErr_SetVim(_("cannot insert line"));
2457 break;
2458 }
2459 vim_free(array[i]);
2460 ++i;
2461 ++extra;
2462 }
2463 }
2464
2465 /* Free any left-over old_len, as a result of an error */
2466 while (i < new_len)
2467 {
2468 vim_free(array[i]);
2469 ++i;
2470 }
2471
2472 /* Free the array of old_len. All of its contents have now
2473 * been dealt with (either freed, or the responsibility passed
2474 * to vim.
2475 */
2476 vim_free(array);
2477
2478 /* Adjust marks. Invalidate any which lie in the
2479 * changed range, and move any in the remainder of the buffer.
2480 */
2481 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
2482 (long)MAXLNUM, (long)extra);
2483 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
2484
2485 if (buf == curwin->w_buffer)
2486 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
2487
2488 curbuf = savebuf;
2489
2490 if (PyErr_Occurred() || VimErrorCheck())
2491 return FAIL;
2492
2493 if (len_change)
2494 *len_change = new_len - old_len;
2495
2496 return OK;
2497 }
2498 else
2499 {
2500 PyErr_BadArgument();
2501 return FAIL;
2502 }
2503}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002504
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002505/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002506 * The line number is in Vim format (1-based). The lines to be inserted are
2507 * given as a Python list of string objects or as a single string. The lines
2508 * to be added are checked for validity and correct format. Errors are
2509 * returned as a value of FAIL. The return value is OK on success.
2510 * If OK is returned and len_change is not NULL, *len_change
2511 * is set to the change in the buffer length.
2512 */
2513 static int
2514InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
2515{
2516 /* First of all, we check the type of the supplied Python object.
2517 * It must be a string or a list, or the call is in error.
2518 */
2519 if (PyString_Check(lines))
2520 {
2521 char *str = StringToLine(lines);
2522 buf_T *savebuf;
2523
2524 if (str == NULL)
2525 return FAIL;
2526
2527 savebuf = curbuf;
2528
2529 PyErr_Clear();
2530 curbuf = buf;
2531
2532 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
2533 PyErr_SetVim(_("cannot save undo information"));
2534 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
2535 PyErr_SetVim(_("cannot insert line"));
2536 else
2537 appended_lines_mark((linenr_T)n, 1L);
2538
2539 vim_free(str);
2540 curbuf = savebuf;
2541 update_screen(VALID);
2542
2543 if (PyErr_Occurred() || VimErrorCheck())
2544 return FAIL;
2545
2546 if (len_change)
2547 *len_change = 1;
2548
2549 return OK;
2550 }
2551 else if (PyList_Check(lines))
2552 {
2553 PyInt i;
2554 PyInt size = PyList_Size(lines);
2555 char **array;
2556 buf_T *savebuf;
2557
2558 array = (char **)alloc((unsigned)(size * sizeof(char *)));
2559 if (array == NULL)
2560 {
2561 PyErr_NoMemory();
2562 return FAIL;
2563 }
2564
2565 for (i = 0; i < size; ++i)
2566 {
2567 PyObject *line = PyList_GetItem(lines, i);
2568 array[i] = StringToLine(line);
2569
2570 if (array[i] == NULL)
2571 {
2572 while (i)
2573 vim_free(array[--i]);
2574 vim_free(array);
2575 return FAIL;
2576 }
2577 }
2578
2579 savebuf = curbuf;
2580
2581 PyErr_Clear();
2582 curbuf = buf;
2583
2584 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
2585 PyErr_SetVim(_("cannot save undo information"));
2586 else
2587 {
2588 for (i = 0; i < size; ++i)
2589 {
2590 if (ml_append((linenr_T)(n + i),
2591 (char_u *)array[i], 0, FALSE) == FAIL)
2592 {
2593 PyErr_SetVim(_("cannot insert line"));
2594
2595 /* Free the rest of the lines */
2596 while (i < size)
2597 vim_free(array[i++]);
2598
2599 break;
2600 }
2601 vim_free(array[i]);
2602 }
2603 if (i > 0)
2604 appended_lines_mark((linenr_T)n, (long)i);
2605 }
2606
2607 /* Free the array of lines. All of its contents have now
2608 * been freed.
2609 */
2610 vim_free(array);
2611
2612 curbuf = savebuf;
2613 update_screen(VALID);
2614
2615 if (PyErr_Occurred() || VimErrorCheck())
2616 return FAIL;
2617
2618 if (len_change)
2619 *len_change = size;
2620
2621 return OK;
2622 }
2623 else
2624 {
2625 PyErr_BadArgument();
2626 return FAIL;
2627 }
2628}
2629
2630/*
2631 * Common routines for buffers and line ranges
2632 * -------------------------------------------
2633 */
2634
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002635typedef struct
2636{
2637 PyObject_HEAD
2638 buf_T *buf;
2639} BufferObject;
2640
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002641 static int
2642CheckBuffer(BufferObject *this)
2643{
2644 if (this->buf == INVALID_BUFFER_VALUE)
2645 {
2646 PyErr_SetVim(_("attempt to refer to deleted buffer"));
2647 return -1;
2648 }
2649
2650 return 0;
2651}
2652
2653 static PyObject *
2654RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
2655{
2656 if (CheckBuffer(self))
2657 return NULL;
2658
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002659 if (end == -1)
2660 end = self->buf->b_ml.ml_line_count;
2661
Bram Moolenaarbd80f352013-05-12 21:16:23 +02002662 if (n < 0)
2663 n += end - start + 1;
2664
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002665 if (n < 0 || n > end - start)
2666 {
2667 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
2668 return NULL;
2669 }
2670
2671 return GetBufferLine(self->buf, n+start);
2672}
2673
2674 static PyObject *
2675RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
2676{
2677 PyInt size;
2678
2679 if (CheckBuffer(self))
2680 return NULL;
2681
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002682 if (end == -1)
2683 end = self->buf->b_ml.ml_line_count;
2684
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002685 size = end - start + 1;
2686
2687 if (lo < 0)
2688 lo = 0;
2689 else if (lo > size)
2690 lo = size;
2691 if (hi < 0)
2692 hi = 0;
2693 if (hi < lo)
2694 hi = lo;
2695 else if (hi > size)
2696 hi = size;
2697
2698 return GetBufferLineList(self->buf, lo+start, hi+start);
2699}
2700
2701 static PyInt
2702RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
2703{
2704 PyInt len_change;
2705
2706 if (CheckBuffer(self))
2707 return -1;
2708
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002709 if (end == -1)
2710 end = self->buf->b_ml.ml_line_count;
2711
Bram Moolenaarbd80f352013-05-12 21:16:23 +02002712 if (n < 0)
2713 n += end - start + 1;
2714
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002715 if (n < 0 || n > end - start)
2716 {
2717 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
2718 return -1;
2719 }
2720
2721 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
2722 return -1;
2723
2724 if (new_end)
2725 *new_end = end + len_change;
2726
2727 return 0;
2728}
2729
Bram Moolenaar19e60942011-06-19 00:27:51 +02002730 static PyInt
2731RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
2732{
2733 PyInt size;
2734 PyInt len_change;
2735
2736 /* Self must be a valid buffer */
2737 if (CheckBuffer(self))
2738 return -1;
2739
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002740 if (end == -1)
2741 end = self->buf->b_ml.ml_line_count;
2742
Bram Moolenaar19e60942011-06-19 00:27:51 +02002743 /* Sort out the slice range */
2744 size = end - start + 1;
2745
2746 if (lo < 0)
2747 lo = 0;
2748 else if (lo > size)
2749 lo = size;
2750 if (hi < 0)
2751 hi = 0;
2752 if (hi < lo)
2753 hi = lo;
2754 else if (hi > size)
2755 hi = size;
2756
2757 if (SetBufferLineList(self->buf, lo + start, hi + start,
2758 val, &len_change) == FAIL)
2759 return -1;
2760
2761 if (new_end)
2762 *new_end = end + len_change;
2763
2764 return 0;
2765}
2766
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002767
2768 static PyObject *
2769RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
2770{
2771 PyObject *lines;
2772 PyInt len_change;
2773 PyInt max;
2774 PyInt n;
2775
2776 if (CheckBuffer(self))
2777 return NULL;
2778
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002779 if (end == -1)
2780 end = self->buf->b_ml.ml_line_count;
2781
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002782 max = n = end - start + 1;
2783
2784 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
2785 return NULL;
2786
2787 if (n < 0 || n > max)
2788 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02002789 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002790 return NULL;
2791 }
2792
2793 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
2794 return NULL;
2795
2796 if (new_end)
2797 *new_end = end + len_change;
2798
2799 Py_INCREF(Py_None);
2800 return Py_None;
2801}
2802
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002803/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002804 */
2805
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002806static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002807static PySequenceMethods RangeAsSeq;
2808static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002809
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002810typedef struct
2811{
2812 PyObject_HEAD
2813 BufferObject *buf;
2814 PyInt start;
2815 PyInt end;
2816} RangeObject;
2817
2818 static PyObject *
2819RangeNew(buf_T *buf, PyInt start, PyInt end)
2820{
2821 BufferObject *bufr;
2822 RangeObject *self;
2823 self = PyObject_NEW(RangeObject, &RangeType);
2824 if (self == NULL)
2825 return NULL;
2826
2827 bufr = (BufferObject *)BufferNew(buf);
2828 if (bufr == NULL)
2829 {
2830 Py_DECREF(self);
2831 return NULL;
2832 }
2833 Py_INCREF(bufr);
2834
2835 self->buf = bufr;
2836 self->start = start;
2837 self->end = end;
2838
2839 return (PyObject *)(self);
2840}
2841
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002842 static void
2843RangeDestructor(PyObject *self)
2844{
2845 Py_DECREF(((RangeObject *)(self))->buf);
2846 DESTRUCTOR_FINISH(self);
2847}
2848
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002849 static PyInt
2850RangeLength(PyObject *self)
2851{
2852 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
2853 if (CheckBuffer(((RangeObject *)(self))->buf))
2854 return -1; /* ??? */
2855
2856 return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1);
2857}
2858
2859 static PyObject *
2860RangeItem(PyObject *self, PyInt n)
2861{
2862 return RBItem(((RangeObject *)(self))->buf, n,
2863 ((RangeObject *)(self))->start,
2864 ((RangeObject *)(self))->end);
2865}
2866
2867 static PyObject *
2868RangeSlice(PyObject *self, PyInt lo, PyInt hi)
2869{
2870 return RBSlice(((RangeObject *)(self))->buf, lo, hi,
2871 ((RangeObject *)(self))->start,
2872 ((RangeObject *)(self))->end);
2873}
2874
2875 static PyObject *
2876RangeAppend(PyObject *self, PyObject *args)
2877{
2878 return RBAppend(((RangeObject *)(self))->buf, args,
2879 ((RangeObject *)(self))->start,
2880 ((RangeObject *)(self))->end,
2881 &((RangeObject *)(self))->end);
2882}
2883
2884 static PyObject *
2885RangeRepr(PyObject *self)
2886{
2887 static char repr[100];
2888 RangeObject *this = (RangeObject *)(self);
2889
2890 if (this->buf->buf == INVALID_BUFFER_VALUE)
2891 {
2892 vim_snprintf(repr, 100, "<range object (for deleted buffer) at %p>",
2893 (self));
2894 return PyString_FromString(repr);
2895 }
2896 else
2897 {
2898 char *name = (char *)this->buf->buf->b_fname;
2899 int len;
2900
2901 if (name == NULL)
2902 name = "";
2903 len = (int)strlen(name);
2904
2905 if (len > 45)
2906 name = name + (45 - len);
2907
2908 vim_snprintf(repr, 100, "<range %s%s (%d:%d)>",
2909 len > 45 ? "..." : "", name,
2910 this->start, this->end);
2911
2912 return PyString_FromString(repr);
2913 }
2914}
2915
2916static struct PyMethodDef RangeMethods[] = {
2917 /* name, function, calling, documentation */
2918 {"append", RangeAppend, 1, "Append data to the Vim range" },
2919 { NULL, NULL, 0, NULL }
2920};
2921
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002922static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002923static PySequenceMethods BufferAsSeq;
2924static PyMappingMethods BufferAsMapping;
2925
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002926 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02002927BufferNew(buf_T *buf)
2928{
2929 /* We need to handle deletion of buffers underneath us.
2930 * If we add a "b_python*_ref" field to the buf_T structure,
2931 * then we can get at it in buf_freeall() in vim. We then
2932 * need to create only ONE Python object per buffer - if
2933 * we try to create a second, just INCREF the existing one
2934 * and return it. The (single) Python object referring to
2935 * the buffer is stored in "b_python*_ref".
2936 * Question: what to do on a buf_freeall(). We'll probably
2937 * have to either delete the Python object (DECREF it to
2938 * zero - a bad idea, as it leaves dangling refs!) or
2939 * set the buf_T * value to an invalid value (-1?), which
2940 * means we need checks in all access functions... Bah.
2941 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002942 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02002943 * b_python_ref and b_python3_ref fields respectively.
2944 */
2945
2946 BufferObject *self;
2947
2948 if (BUF_PYTHON_REF(buf) != NULL)
2949 {
2950 self = BUF_PYTHON_REF(buf);
2951 Py_INCREF(self);
2952 }
2953 else
2954 {
2955 self = PyObject_NEW(BufferObject, &BufferType);
2956 if (self == NULL)
2957 return NULL;
2958 self->buf = buf;
2959 BUF_PYTHON_REF(buf) = self;
2960 }
2961
2962 return (PyObject *)(self);
2963}
2964
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002965 static void
2966BufferDestructor(PyObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002967{
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002968 BufferObject *this = (BufferObject *)(self);
2969
2970 if (this->buf && this->buf != INVALID_BUFFER_VALUE)
2971 BUF_PYTHON_REF(this->buf) = NULL;
2972
2973 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002974}
2975
Bram Moolenaar971db462013-05-12 18:44:48 +02002976 static PyInt
2977BufferLength(PyObject *self)
2978{
2979 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
2980 if (CheckBuffer((BufferObject *)(self)))
2981 return -1; /* ??? */
2982
2983 return (PyInt)(((BufferObject *)(self))->buf->b_ml.ml_line_count);
2984}
2985
2986 static PyObject *
2987BufferItem(PyObject *self, PyInt n)
2988{
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002989 return RBItem((BufferObject *)(self), n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02002990}
2991
2992 static PyObject *
2993BufferSlice(PyObject *self, PyInt lo, PyInt hi)
2994{
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02002995 return RBSlice((BufferObject *)(self), lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02002996}
2997
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002998 static PyObject *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002999BufferAttr(BufferObject *this, char *name)
3000{
3001 if (strcmp(name, "name") == 0)
3002 return Py_BuildValue("s", this->buf->b_ffname);
3003 else if (strcmp(name, "number") == 0)
3004 return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum);
3005 else if (strcmp(name, "vars") == 0)
3006 return DictionaryNew(this->buf->b_vars);
3007 else if (strcmp(name, "options") == 0)
3008 return OptionsNew(SREQ_BUF, this->buf, (checkfun) CheckBuffer,
3009 (PyObject *) this);
3010 else if (strcmp(name,"__members__") == 0)
3011 return Py_BuildValue("[ssss]", "name", "number", "vars", "options");
3012 else
3013 return NULL;
3014}
3015
3016 static PyObject *
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003017BufferAppend(PyObject *self, PyObject *args)
3018{
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003019 return RBAppend((BufferObject *)(self), args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003020}
3021
3022 static PyObject *
3023BufferMark(PyObject *self, PyObject *args)
3024{
3025 pos_T *posp;
3026 char *pmark;
3027 char mark;
3028 buf_T *curbuf_save;
3029
3030 if (CheckBuffer((BufferObject *)(self)))
3031 return NULL;
3032
3033 if (!PyArg_ParseTuple(args, "s", &pmark))
3034 return NULL;
3035 mark = *pmark;
3036
3037 curbuf_save = curbuf;
3038 curbuf = ((BufferObject *)(self))->buf;
3039 posp = getmark(mark, FALSE);
3040 curbuf = curbuf_save;
3041
3042 if (posp == NULL)
3043 {
3044 PyErr_SetVim(_("invalid mark name"));
3045 return NULL;
3046 }
3047
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003048 /* Check for keyboard interrupt */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003049 if (VimErrorCheck())
3050 return NULL;
3051
3052 if (posp->lnum <= 0)
3053 {
3054 /* Or raise an error? */
3055 Py_INCREF(Py_None);
3056 return Py_None;
3057 }
3058
3059 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
3060}
3061
3062 static PyObject *
3063BufferRange(PyObject *self, PyObject *args)
3064{
3065 PyInt start;
3066 PyInt end;
3067
3068 if (CheckBuffer((BufferObject *)(self)))
3069 return NULL;
3070
3071 if (!PyArg_ParseTuple(args, "nn", &start, &end))
3072 return NULL;
3073
3074 return RangeNew(((BufferObject *)(self))->buf, start, end);
3075}
3076
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003077 static PyObject *
3078BufferRepr(PyObject *self)
3079{
3080 static char repr[100];
3081 BufferObject *this = (BufferObject *)(self);
3082
3083 if (this->buf == INVALID_BUFFER_VALUE)
3084 {
3085 vim_snprintf(repr, 100, _("<buffer object (deleted) at %p>"), (self));
3086 return PyString_FromString(repr);
3087 }
3088 else
3089 {
3090 char *name = (char *)this->buf->b_fname;
3091 PyInt len;
3092
3093 if (name == NULL)
3094 name = "";
3095 len = strlen(name);
3096
3097 if (len > 35)
3098 name = name + (35 - len);
3099
3100 vim_snprintf(repr, 100, "<buffer %s%s>", len > 35 ? "..." : "", name);
3101
3102 return PyString_FromString(repr);
3103 }
3104}
3105
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003106static struct PyMethodDef BufferMethods[] = {
3107 /* name, function, calling, documentation */
3108 {"append", BufferAppend, 1, "Append data to Vim buffer" },
3109 {"mark", BufferMark, 1, "Return (row,col) representing position of named mark" },
3110 {"range", BufferRange, 1, "Return a range object which represents the part of the given buffer between line numbers s and e" },
Bram Moolenaar7f85d292012-02-04 20:17:26 +01003111#if PY_VERSION_HEX >= 0x03000000
3112 {"__dir__", BufferDir, 4, "List its attributes" },
3113#endif
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003114 { NULL, NULL, 0, NULL }
3115};
3116
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003117/*
3118 * Buffer list object - Implementation
3119 */
3120
3121static PyTypeObject BufMapType;
3122
3123typedef struct
3124{
3125 PyObject_HEAD
3126} BufMapObject;
3127
3128 static PyInt
3129BufMapLength(PyObject *self UNUSED)
3130{
3131 buf_T *b = firstbuf;
3132 PyInt n = 0;
3133
3134 while (b)
3135 {
3136 ++n;
3137 b = b->b_next;
3138 }
3139
3140 return n;
3141}
3142
3143 static PyObject *
3144BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
3145{
3146 buf_T *b;
3147 int bnr;
3148
3149#if PY_MAJOR_VERSION < 3
3150 if (PyInt_Check(keyObject))
3151 bnr = PyInt_AsLong(keyObject);
3152 else
3153#endif
3154 if (PyLong_Check(keyObject))
3155 bnr = PyLong_AsLong(keyObject);
3156 else
3157 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003158 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003159 return NULL;
3160 }
3161
3162 b = buflist_findnr(bnr);
3163
3164 if (b)
3165 return BufferNew(b);
3166 else
3167 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02003168 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003169 return NULL;
3170 }
3171}
3172
3173 static void
3174BufMapIterDestruct(PyObject *buffer)
3175{
3176 /* Iteration was stopped before all buffers were processed */
3177 if (buffer)
3178 {
3179 Py_DECREF(buffer);
3180 }
3181}
3182
3183 static PyObject *
3184BufMapIterNext(PyObject **buffer)
3185{
3186 PyObject *next;
3187 PyObject *r;
3188
3189 if (!*buffer)
3190 return NULL;
3191
3192 r = *buffer;
3193
3194 if (CheckBuffer((BufferObject *)(r)))
3195 {
3196 *buffer = NULL;
3197 return NULL;
3198 }
3199
3200 if (!((BufferObject *)(r))->buf->b_next)
3201 next = NULL;
3202 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
3203 return NULL;
3204 *buffer = next;
3205 /* Do not increment reference: we no longer hold it (decref), but whoever on
3206 * other side will hold (incref). Decref+incref = nothing.
3207 */
3208 return r;
3209}
3210
3211 static PyObject *
3212BufMapIter(PyObject *self UNUSED)
3213{
3214 PyObject *buffer;
3215
3216 buffer = BufferNew(firstbuf);
3217 return IterNew(buffer,
3218 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext);
3219}
3220
3221static PyMappingMethods BufMapAsMapping = {
3222 (lenfunc) BufMapLength,
3223 (binaryfunc) BufMapItem,
3224 (objobjargproc) 0,
3225};
3226
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003227/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003228 */
3229
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003230 static PyObject *
3231CurrentGetattr(PyObject *self UNUSED, char *name)
3232{
3233 if (strcmp(name, "buffer") == 0)
3234 return (PyObject *)BufferNew(curbuf);
3235 else if (strcmp(name, "window") == 0)
3236 return (PyObject *)WindowNew(curwin);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003237 else if (strcmp(name, "tabpage") == 0)
3238 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003239 else if (strcmp(name, "line") == 0)
3240 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
3241 else if (strcmp(name, "range") == 0)
3242 return RangeNew(curbuf, RangeStart, RangeEnd);
3243 else if (strcmp(name,"__members__") == 0)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003244 return Py_BuildValue("[sssss]", "buffer", "window", "line", "range",
3245 "tabpage");
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003246 else
3247 {
3248 PyErr_SetString(PyExc_AttributeError, name);
3249 return NULL;
3250 }
3251}
3252
3253 static int
3254CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
3255{
3256 if (strcmp(name, "line") == 0)
3257 {
3258 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
3259 return -1;
3260
3261 return 0;
3262 }
Bram Moolenaare7614592013-05-15 15:51:08 +02003263 else if (strcmp(name, "buffer") == 0)
3264 {
3265 int count;
3266
3267 if (value->ob_type != &BufferType)
3268 {
3269 PyErr_SetString(PyExc_TypeError, _("expected vim.buffer object"));
3270 return -1;
3271 }
3272
3273 if (CheckBuffer((BufferObject *)(value)))
3274 return -1;
3275 count = ((BufferObject *)(value))->buf->b_fnum;
3276
3277 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
3278 {
3279 PyErr_SetVim(_("failed to switch to given buffer"));
3280 return -1;
3281 }
3282
3283 return 0;
3284 }
3285 else if (strcmp(name, "window") == 0)
3286 {
3287 int count;
3288
3289 if (value->ob_type != &WindowType)
3290 {
3291 PyErr_SetString(PyExc_TypeError, _("expected vim.window object"));
3292 return -1;
3293 }
3294
3295 if (CheckWindow((WindowObject *)(value)))
3296 return -1;
3297 count = get_win_number(((WindowObject *)(value))->win, firstwin);
3298
3299 if (!count)
3300 {
3301 PyErr_SetString(PyExc_ValueError,
3302 _("failed to find window in the current tab page"));
3303 return -1;
3304 }
3305
3306 win_goto(((WindowObject *)(value))->win);
3307 if (((WindowObject *)(value))->win != curwin)
3308 {
3309 PyErr_SetString(PyExc_RuntimeError,
3310 _("did not switch to the specified window"));
3311 return -1;
3312 }
3313
3314 return 0;
3315 }
3316 else if (strcmp(name, "tabpage") == 0)
3317 {
3318 if (value->ob_type != &TabPageType)
3319 {
3320 PyErr_SetString(PyExc_TypeError, _("expected vim.tabpage object"));
3321 return -1;
3322 }
3323
3324 if (CheckTabPage((TabPageObject *)(value)))
3325 return -1;
3326
3327 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
3328 if (((TabPageObject *)(value))->tab != curtab)
3329 {
3330 PyErr_SetString(PyExc_RuntimeError,
3331 _("did not switch to the specified tab page"));
3332 return -1;
3333 }
3334
3335 return 0;
3336 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003337 else
3338 {
3339 PyErr_SetString(PyExc_AttributeError, name);
3340 return -1;
3341 }
3342}
3343
Bram Moolenaardb913952012-06-29 12:54:53 +02003344 static void
3345set_ref_in_py(const int copyID)
3346{
3347 pylinkedlist_T *cur;
3348 dict_T *dd;
3349 list_T *ll;
3350
3351 if (lastdict != NULL)
3352 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
3353 {
3354 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
3355 if (dd->dv_copyID != copyID)
3356 {
3357 dd->dv_copyID = copyID;
3358 set_ref_in_ht(&dd->dv_hashtab, copyID);
3359 }
3360 }
3361
3362 if (lastlist != NULL)
3363 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
3364 {
3365 ll = ((ListObject *) (cur->pll_obj))->list;
3366 if (ll->lv_copyID != copyID)
3367 {
3368 ll->lv_copyID = copyID;
3369 set_ref_in_list(ll, copyID);
3370 }
3371 }
3372}
3373
3374 static int
3375set_string_copy(char_u *str, typval_T *tv)
3376{
3377 tv->vval.v_string = vim_strsave(str);
3378 if (tv->vval.v_string == NULL)
3379 {
3380 PyErr_NoMemory();
3381 return -1;
3382 }
3383 return 0;
3384}
3385
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003386 static int
3387pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
3388{
3389 dict_T *d;
3390 char_u *key;
3391 dictitem_T *di;
3392 PyObject *keyObject;
3393 PyObject *valObject;
3394 Py_ssize_t iter = 0;
3395
3396 d = dict_alloc();
3397 if (d == NULL)
3398 {
3399 PyErr_NoMemory();
3400 return -1;
3401 }
3402
3403 tv->v_type = VAR_DICT;
3404 tv->vval.v_dict = d;
3405
3406 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
3407 {
3408 DICTKEY_DECL
3409
3410 if (keyObject == NULL)
3411 return -1;
3412 if (valObject == NULL)
3413 return -1;
3414
3415 DICTKEY_GET_NOTEMPTY(-1)
3416
3417 di = dictitem_alloc(key);
3418
3419 DICTKEY_UNREF
3420
3421 if (di == NULL)
3422 {
3423 PyErr_NoMemory();
3424 return -1;
3425 }
3426 di->di_tv.v_lock = 0;
3427
3428 if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
3429 {
3430 vim_free(di);
3431 return -1;
3432 }
3433 if (dict_add(d, di) == FAIL)
3434 {
3435 vim_free(di);
3436 PyErr_SetVim(_("failed to add key to dictionary"));
3437 return -1;
3438 }
3439 }
3440 return 0;
3441}
3442
3443 static int
3444pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
3445{
3446 dict_T *d;
3447 char_u *key;
3448 dictitem_T *di;
3449 PyObject *list;
3450 PyObject *litem;
3451 PyObject *keyObject;
3452 PyObject *valObject;
3453 Py_ssize_t lsize;
3454
3455 d = dict_alloc();
3456 if (d == NULL)
3457 {
3458 PyErr_NoMemory();
3459 return -1;
3460 }
3461
3462 tv->v_type = VAR_DICT;
3463 tv->vval.v_dict = d;
3464
3465 list = PyMapping_Items(obj);
3466 if (list == NULL)
3467 return -1;
3468 lsize = PyList_Size(list);
3469 while (lsize--)
3470 {
3471 DICTKEY_DECL
3472
3473 litem = PyList_GetItem(list, lsize);
3474 if (litem == NULL)
3475 {
3476 Py_DECREF(list);
3477 return -1;
3478 }
3479
3480 keyObject = PyTuple_GetItem(litem, 0);
3481 if (keyObject == NULL)
3482 {
3483 Py_DECREF(list);
3484 Py_DECREF(litem);
3485 return -1;
3486 }
3487
3488 DICTKEY_GET_NOTEMPTY(-1)
3489
3490 valObject = PyTuple_GetItem(litem, 1);
3491 if (valObject == NULL)
3492 {
3493 Py_DECREF(list);
3494 Py_DECREF(litem);
3495 return -1;
3496 }
3497
3498 di = dictitem_alloc(key);
3499
3500 DICTKEY_UNREF
3501
3502 if (di == NULL)
3503 {
3504 Py_DECREF(list);
3505 Py_DECREF(litem);
3506 PyErr_NoMemory();
3507 return -1;
3508 }
3509 di->di_tv.v_lock = 0;
3510
3511 if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
3512 {
3513 vim_free(di);
3514 Py_DECREF(list);
3515 Py_DECREF(litem);
3516 return -1;
3517 }
3518 if (dict_add(d, di) == FAIL)
3519 {
3520 vim_free(di);
3521 Py_DECREF(list);
3522 Py_DECREF(litem);
3523 PyErr_SetVim(_("failed to add key to dictionary"));
3524 return -1;
3525 }
3526 Py_DECREF(litem);
3527 }
3528 Py_DECREF(list);
3529 return 0;
3530}
3531
3532 static int
3533pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
3534{
3535 list_T *l;
3536
3537 l = list_alloc();
3538 if (l == NULL)
3539 {
3540 PyErr_NoMemory();
3541 return -1;
3542 }
3543
3544 tv->v_type = VAR_LIST;
3545 tv->vval.v_list = l;
3546
3547 if (list_py_concat(l, obj, lookupDict) == -1)
3548 return -1;
3549
3550 return 0;
3551}
3552
3553 static int
3554pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
3555{
3556 PyObject *iterator = PyObject_GetIter(obj);
3557 PyObject *item;
3558 list_T *l;
3559 listitem_T *li;
3560
3561 l = list_alloc();
3562
3563 if (l == NULL)
3564 {
3565 PyErr_NoMemory();
3566 return -1;
3567 }
3568
3569 tv->vval.v_list = l;
3570 tv->v_type = VAR_LIST;
3571
3572
3573 if (iterator == NULL)
3574 return -1;
3575
3576 while ((item = PyIter_Next(obj)))
3577 {
3578 li = listitem_alloc();
3579 if (li == NULL)
3580 {
3581 PyErr_NoMemory();
3582 return -1;
3583 }
3584 li->li_tv.v_lock = 0;
3585
3586 if (_ConvertFromPyObject(item, &li->li_tv, lookupDict) == -1)
3587 return -1;
3588
3589 list_append(l, li);
3590
3591 Py_DECREF(item);
3592 }
3593
3594 Py_DECREF(iterator);
3595 return 0;
3596}
3597
Bram Moolenaardb913952012-06-29 12:54:53 +02003598typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
3599
3600 static int
3601convert_dl(PyObject *obj, typval_T *tv,
3602 pytotvfunc py_to_tv, PyObject *lookupDict)
3603{
3604 PyObject *capsule;
3605 char hexBuf[sizeof(void *) * 2 + 3];
3606
3607 sprintf(hexBuf, "%p", obj);
3608
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003609# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02003610 capsule = PyDict_GetItemString(lookupDict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003611# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02003612 capsule = (PyObject *)PyDict_GetItemString(lookupDict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003613# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02003614 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02003615 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003616# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02003617 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02003618# else
3619 capsule = PyCObject_FromVoidPtr(tv, NULL);
3620# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02003621 PyDict_SetItemString(lookupDict, hexBuf, capsule);
3622 Py_DECREF(capsule);
3623 if (py_to_tv(obj, tv, lookupDict) == -1)
3624 {
3625 tv->v_type = VAR_UNKNOWN;
3626 return -1;
3627 }
3628 /* As we are not using copy_tv which increments reference count we must
3629 * do it ourself. */
3630 switch(tv->v_type)
3631 {
3632 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
3633 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
3634 }
3635 }
3636 else
3637 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003638 typval_T *v;
3639
3640# ifdef PY_USE_CAPSULE
3641 v = PyCapsule_GetPointer(capsule, NULL);
3642# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02003643 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02003644# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02003645 copy_tv(v, tv);
3646 }
3647 return 0;
3648}
3649
3650 static int
3651ConvertFromPyObject(PyObject *obj, typval_T *tv)
3652{
3653 PyObject *lookup_dict;
3654 int r;
3655
3656 lookup_dict = PyDict_New();
3657 r = _ConvertFromPyObject(obj, tv, lookup_dict);
3658 Py_DECREF(lookup_dict);
3659 return r;
3660}
3661
3662 static int
3663_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookupDict)
3664{
3665 if (obj->ob_type == &DictionaryType)
3666 {
3667 tv->v_type = VAR_DICT;
3668 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
3669 ++tv->vval.v_dict->dv_refcount;
3670 }
3671 else if (obj->ob_type == &ListType)
3672 {
3673 tv->v_type = VAR_LIST;
3674 tv->vval.v_list = (((ListObject *)(obj))->list);
3675 ++tv->vval.v_list->lv_refcount;
3676 }
3677 else if (obj->ob_type == &FunctionType)
3678 {
3679 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
3680 return -1;
3681
3682 tv->v_type = VAR_FUNC;
3683 func_ref(tv->vval.v_string);
3684 }
Bram Moolenaardb913952012-06-29 12:54:53 +02003685 else if (PyBytes_Check(obj))
3686 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02003687 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02003688
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02003689 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
3690 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02003691 if (result == NULL)
3692 return -1;
3693
3694 if (set_string_copy(result, tv) == -1)
3695 return -1;
3696
3697 tv->v_type = VAR_STRING;
3698 }
3699 else if (PyUnicode_Check(obj))
3700 {
3701 PyObject *bytes;
3702 char_u *result;
3703
Bram Moolenaardb913952012-06-29 12:54:53 +02003704 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
3705 if (bytes == NULL)
3706 return -1;
3707
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02003708 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
3709 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02003710 if (result == NULL)
3711 return -1;
3712
3713 if (set_string_copy(result, tv) == -1)
3714 {
3715 Py_XDECREF(bytes);
3716 return -1;
3717 }
3718 Py_XDECREF(bytes);
3719
3720 tv->v_type = VAR_STRING;
3721 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02003722#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02003723 else if (PyInt_Check(obj))
3724 {
3725 tv->v_type = VAR_NUMBER;
3726 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
3727 }
3728#endif
3729 else if (PyLong_Check(obj))
3730 {
3731 tv->v_type = VAR_NUMBER;
3732 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
3733 }
3734 else if (PyDict_Check(obj))
3735 return convert_dl(obj, tv, pydict_to_tv, lookupDict);
3736#ifdef FEAT_FLOAT
3737 else if (PyFloat_Check(obj))
3738 {
3739 tv->v_type = VAR_FLOAT;
3740 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
3741 }
3742#endif
3743 else if (PyIter_Check(obj))
3744 return convert_dl(obj, tv, pyiter_to_tv, lookupDict);
3745 else if (PySequence_Check(obj))
3746 return convert_dl(obj, tv, pyseq_to_tv, lookupDict);
3747 else if (PyMapping_Check(obj))
3748 return convert_dl(obj, tv, pymap_to_tv, lookupDict);
3749 else
3750 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003751 PyErr_SetString(PyExc_TypeError,
3752 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02003753 return -1;
3754 }
3755 return 0;
3756}
3757
3758 static PyObject *
3759ConvertToPyObject(typval_T *tv)
3760{
3761 if (tv == NULL)
3762 {
3763 PyErr_SetVim(_("NULL reference passed"));
3764 return NULL;
3765 }
3766 switch (tv->v_type)
3767 {
3768 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02003769 return PyBytes_FromString(tv->vval.v_string == NULL
3770 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02003771 case VAR_NUMBER:
3772 return PyLong_FromLong((long) tv->vval.v_number);
3773#ifdef FEAT_FLOAT
3774 case VAR_FLOAT:
3775 return PyFloat_FromDouble((double) tv->vval.v_float);
3776#endif
3777 case VAR_LIST:
3778 return ListNew(tv->vval.v_list);
3779 case VAR_DICT:
3780 return DictionaryNew(tv->vval.v_dict);
3781 case VAR_FUNC:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02003782 return FunctionNew(tv->vval.v_string == NULL
3783 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02003784 case VAR_UNKNOWN:
3785 Py_INCREF(Py_None);
3786 return Py_None;
3787 default:
3788 PyErr_SetVim(_("internal error: invalid value type"));
3789 return NULL;
3790 }
3791}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003792
3793typedef struct
3794{
3795 PyObject_HEAD
3796} CurrentObject;
3797static PyTypeObject CurrentType;
3798
3799 static void
3800init_structs(void)
3801{
3802 vim_memset(&OutputType, 0, sizeof(OutputType));
3803 OutputType.tp_name = "vim.message";
3804 OutputType.tp_basicsize = sizeof(OutputObject);
3805 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
3806 OutputType.tp_doc = "vim message object";
3807 OutputType.tp_methods = OutputMethods;
3808#if PY_MAJOR_VERSION >= 3
3809 OutputType.tp_getattro = OutputGetattro;
3810 OutputType.tp_setattro = OutputSetattro;
3811 OutputType.tp_alloc = call_PyType_GenericAlloc;
3812 OutputType.tp_new = call_PyType_GenericNew;
3813 OutputType.tp_free = call_PyObject_Free;
3814#else
3815 OutputType.tp_getattr = OutputGetattr;
3816 OutputType.tp_setattr = OutputSetattr;
3817#endif
3818
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003819 vim_memset(&IterType, 0, sizeof(IterType));
3820 IterType.tp_name = "vim.iter";
3821 IterType.tp_basicsize = sizeof(IterObject);
3822 IterType.tp_flags = Py_TPFLAGS_DEFAULT;
3823 IterType.tp_doc = "generic iterator object";
3824 IterType.tp_iter = IterIter;
3825 IterType.tp_iternext = IterNext;
3826
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003827 vim_memset(&BufferType, 0, sizeof(BufferType));
3828 BufferType.tp_name = "vim.buffer";
3829 BufferType.tp_basicsize = sizeof(BufferType);
3830 BufferType.tp_dealloc = BufferDestructor;
3831 BufferType.tp_repr = BufferRepr;
3832 BufferType.tp_as_sequence = &BufferAsSeq;
3833 BufferType.tp_as_mapping = &BufferAsMapping;
3834 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
3835 BufferType.tp_doc = "vim buffer object";
3836 BufferType.tp_methods = BufferMethods;
3837#if PY_MAJOR_VERSION >= 3
3838 BufferType.tp_getattro = BufferGetattro;
3839 BufferType.tp_alloc = call_PyType_GenericAlloc;
3840 BufferType.tp_new = call_PyType_GenericNew;
3841 BufferType.tp_free = call_PyObject_Free;
3842#else
3843 BufferType.tp_getattr = BufferGetattr;
3844#endif
3845
3846 vim_memset(&WindowType, 0, sizeof(WindowType));
3847 WindowType.tp_name = "vim.window";
3848 WindowType.tp_basicsize = sizeof(WindowObject);
3849 WindowType.tp_dealloc = WindowDestructor;
3850 WindowType.tp_repr = WindowRepr;
3851 WindowType.tp_flags = Py_TPFLAGS_DEFAULT;
3852 WindowType.tp_doc = "vim Window object";
3853 WindowType.tp_methods = WindowMethods;
3854#if PY_MAJOR_VERSION >= 3
3855 WindowType.tp_getattro = WindowGetattro;
3856 WindowType.tp_setattro = WindowSetattro;
3857 WindowType.tp_alloc = call_PyType_GenericAlloc;
3858 WindowType.tp_new = call_PyType_GenericNew;
3859 WindowType.tp_free = call_PyObject_Free;
3860#else
3861 WindowType.tp_getattr = WindowGetattr;
3862 WindowType.tp_setattr = WindowSetattr;
3863#endif
3864
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003865 vim_memset(&TabPageType, 0, sizeof(TabPageType));
3866 TabPageType.tp_name = "vim.tabpage";
3867 TabPageType.tp_basicsize = sizeof(TabPageObject);
3868 TabPageType.tp_dealloc = TabPageDestructor;
3869 TabPageType.tp_repr = TabPageRepr;
3870 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
3871 TabPageType.tp_doc = "vim tab page object";
3872 TabPageType.tp_methods = TabPageMethods;
3873#if PY_MAJOR_VERSION >= 3
3874 TabPageType.tp_getattro = TabPageGetattro;
3875 TabPageType.tp_alloc = call_PyType_GenericAlloc;
3876 TabPageType.tp_new = call_PyType_GenericNew;
3877 TabPageType.tp_free = call_PyObject_Free;
3878#else
3879 TabPageType.tp_getattr = TabPageGetattr;
3880#endif
3881
Bram Moolenaardfa38d42013-05-15 13:38:47 +02003882 vim_memset(&BufMapType, 0, sizeof(BufMapType));
3883 BufMapType.tp_name = "vim.bufferlist";
3884 BufMapType.tp_basicsize = sizeof(BufMapObject);
3885 BufMapType.tp_as_mapping = &BufMapAsMapping;
3886 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003887 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003888 BufferType.tp_doc = "vim buffer list";
3889
3890 vim_memset(&WinListType, 0, sizeof(WinListType));
3891 WinListType.tp_name = "vim.windowlist";
3892 WinListType.tp_basicsize = sizeof(WinListType);
3893 WinListType.tp_as_sequence = &WinListAsSeq;
3894 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
3895 WinListType.tp_doc = "vim window list";
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003896 WinListType.tp_dealloc = WinListDestructor;
3897
3898 vim_memset(&TabListType, 0, sizeof(TabListType));
3899 TabListType.tp_name = "vim.tabpagelist";
3900 TabListType.tp_basicsize = sizeof(TabListType);
3901 TabListType.tp_as_sequence = &TabListAsSeq;
3902 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
3903 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003904
3905 vim_memset(&RangeType, 0, sizeof(RangeType));
3906 RangeType.tp_name = "vim.range";
3907 RangeType.tp_basicsize = sizeof(RangeObject);
3908 RangeType.tp_dealloc = RangeDestructor;
3909 RangeType.tp_repr = RangeRepr;
3910 RangeType.tp_as_sequence = &RangeAsSeq;
3911 RangeType.tp_as_mapping = &RangeAsMapping;
3912 RangeType.tp_flags = Py_TPFLAGS_DEFAULT;
3913 RangeType.tp_doc = "vim Range object";
3914 RangeType.tp_methods = RangeMethods;
3915#if PY_MAJOR_VERSION >= 3
3916 RangeType.tp_getattro = RangeGetattro;
3917 RangeType.tp_alloc = call_PyType_GenericAlloc;
3918 RangeType.tp_new = call_PyType_GenericNew;
3919 RangeType.tp_free = call_PyObject_Free;
3920#else
3921 RangeType.tp_getattr = RangeGetattr;
3922#endif
3923
3924 vim_memset(&CurrentType, 0, sizeof(CurrentType));
3925 CurrentType.tp_name = "vim.currentdata";
3926 CurrentType.tp_basicsize = sizeof(CurrentObject);
3927 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
3928 CurrentType.tp_doc = "vim current object";
3929#if PY_MAJOR_VERSION >= 3
3930 CurrentType.tp_getattro = CurrentGetattro;
3931 CurrentType.tp_setattro = CurrentSetattro;
3932#else
3933 CurrentType.tp_getattr = CurrentGetattr;
3934 CurrentType.tp_setattr = CurrentSetattr;
3935#endif
3936
3937 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
3938 DictionaryType.tp_name = "vim.dictionary";
3939 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
3940 DictionaryType.tp_dealloc = DictionaryDestructor;
3941 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
3942 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT;
3943 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
3944 DictionaryType.tp_methods = DictionaryMethods;
3945#if PY_MAJOR_VERSION >= 3
3946 DictionaryType.tp_getattro = DictionaryGetattro;
3947 DictionaryType.tp_setattro = DictionarySetattro;
3948#else
3949 DictionaryType.tp_getattr = DictionaryGetattr;
3950 DictionaryType.tp_setattr = DictionarySetattr;
3951#endif
3952
3953 vim_memset(&ListType, 0, sizeof(ListType));
3954 ListType.tp_name = "vim.list";
3955 ListType.tp_dealloc = ListDestructor;
3956 ListType.tp_basicsize = sizeof(ListObject);
3957 ListType.tp_as_sequence = &ListAsSeq;
3958 ListType.tp_as_mapping = &ListAsMapping;
3959 ListType.tp_flags = Py_TPFLAGS_DEFAULT;
3960 ListType.tp_doc = "list pushing modifications to vim structure";
3961 ListType.tp_methods = ListMethods;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003962 ListType.tp_iter = ListIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003963#if PY_MAJOR_VERSION >= 3
3964 ListType.tp_getattro = ListGetattro;
3965 ListType.tp_setattro = ListSetattro;
3966#else
3967 ListType.tp_getattr = ListGetattr;
3968 ListType.tp_setattr = ListSetattr;
3969#endif
3970
3971 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003972 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003973 FunctionType.tp_basicsize = sizeof(FunctionObject);
3974 FunctionType.tp_dealloc = FunctionDestructor;
3975 FunctionType.tp_call = FunctionCall;
3976 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
3977 FunctionType.tp_doc = "object that calls vim function";
3978 FunctionType.tp_methods = FunctionMethods;
3979#if PY_MAJOR_VERSION >= 3
3980 FunctionType.tp_getattro = FunctionGetattro;
3981#else
3982 FunctionType.tp_getattr = FunctionGetattr;
3983#endif
3984
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003985 vim_memset(&OptionsType, 0, sizeof(OptionsType));
3986 OptionsType.tp_name = "vim.options";
3987 OptionsType.tp_basicsize = sizeof(OptionsObject);
3988 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT;
3989 OptionsType.tp_doc = "object for manipulating options";
3990 OptionsType.tp_as_mapping = &OptionsAsMapping;
3991 OptionsType.tp_dealloc = OptionsDestructor;
3992
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003993#if PY_MAJOR_VERSION >= 3
3994 vim_memset(&vimmodule, 0, sizeof(vimmodule));
3995 vimmodule.m_name = "vim";
3996 vimmodule.m_doc = "Vim Python interface\n";
3997 vimmodule.m_size = -1;
3998 vimmodule.m_methods = VimMethods;
3999#endif
4000}