blob: edae12bef0b569e88f6c33afd50b4f1f59e5d345 [file] [log] [blame]
Bram Moolenaardb913952012-06-29 12:54:53 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020010 * Python extensions by Paul Moore, David Leonard, Roland Puntaier, Nikolay
11 * Pavlov.
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020012 *
13 * Common code for if_python.c and if_python3.c.
14 */
15
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020016#if PY_VERSION_HEX < 0x02050000
17typedef int Py_ssize_t; /* Python 2.4 and earlier don't have this type. */
18#endif
19
Bram Moolenaar91805fc2011-06-26 04:01:44 +020020#ifdef FEAT_MBYTE
21# define ENC_OPT p_enc
22#else
23# define ENC_OPT "latin1"
24#endif
Bram Moolenaard620aa92013-05-17 16:40:06 +020025#define DOPY_FUNC "_vim_pydo"
Bram Moolenaar91805fc2011-06-26 04:01:44 +020026
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020027#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
28
29#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
30#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020031#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020032
Bram Moolenaare9ba5162013-05-29 22:02:22 +020033#define DICTKEY_DECL \
34 PyObject *dictkey_todecref;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +020035#define DICTKEY_CHECK_EMPTY(err) \
36 if (*key == NUL) \
37 { \
38 PyErr_SetString(PyExc_ValueError, _("empty keys are not allowed")); \
39 return err; \
40 }
41#define DICTKEY_SET_KEY (key = StringToChars(keyObject, &dictkey_todecref))
Bram Moolenaara03e6312013-05-29 22:49:26 +020042#define DICTKEY_GET(err, decref) \
Bram Moolenaar9bb77d62013-05-30 12:14:49 +020043 if (!DICTKEY_SET_KEY) \
Bram Moolenaara03e6312013-05-29 22:49:26 +020044 { \
45 if (decref) \
46 { \
47 Py_DECREF(keyObject); \
48 } \
Bram Moolenaarc37b6ec2013-05-29 22:43:37 +020049 return err; \
Bram Moolenaara03e6312013-05-29 22:49:26 +020050 } \
51 if (decref && !dictkey_todecref) \
52 dictkey_todecref = keyObject; \
Bram Moolenaar9bb77d62013-05-30 12:14:49 +020053 DICTKEY_CHECK_EMPTY(err)
Bram Moolenaare9ba5162013-05-29 22:02:22 +020054#define DICTKEY_UNREF \
55 Py_XDECREF(dictkey_todecref);
56
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020057typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020058typedef void (*runner)(const char *, void *
59#ifdef PY_CAN_RECURSE
60 , PyGILState_STATE *
61#endif
62 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020063
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020064static int ConvertFromPyObject(PyObject *, typval_T *);
65static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020066static PyObject *WindowNew(win_T *, tabpage_T *);
67static PyObject *BufferNew (buf_T *);
68static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020069
70static PyInt RangeStart;
71static PyInt RangeEnd;
72
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020073static PyObject *globals;
74
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020075/*
76 * obtain a lock on the Vim data structures
77 */
78 static void
79Python_Lock_Vim(void)
80{
81}
82
83/*
84 * release a lock on the Vim data structures
85 */
86 static void
87Python_Release_Vim(void)
88{
89}
90
Bram Moolenaare9ba5162013-05-29 22:02:22 +020091/*
92 * The "todecref" argument holds a pointer to PyObject * that must be
93 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
94 * was needed to generate returned value is object.
95 *
96 * Use Py_XDECREF to decrement reference count.
97 */
98 static char_u *
99StringToChars(PyObject *object, PyObject **todecref)
100{
101 char_u *p;
102 PyObject *bytes = NULL;
103
104 if (PyBytes_Check(object))
105 {
106
107 if (PyString_AsStringAndSize(object, (char **) &p, NULL) == -1)
108 return NULL;
109 if (p == NULL)
110 return NULL;
111
112 *todecref = NULL;
113 }
114 else if (PyUnicode_Check(object))
115 {
116 bytes = PyUnicode_AsEncodedString(object, (char *)ENC_OPT, NULL);
117 if (bytes == NULL)
118 return NULL;
119
120 if(PyString_AsStringAndSize(bytes, (char **) &p, NULL) == -1)
121 return NULL;
122 if (p == NULL)
123 return NULL;
124
125 *todecref = bytes;
126 }
127 else
128 {
129 PyErr_SetString(PyExc_TypeError, _("object must be string"));
130 return NULL;
131 }
132
133 return (char_u *) p;
134}
135
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200136 static int
137add_string(PyObject *list, char *s)
138{
139 PyObject *string;
140
141 if (!(string = PyString_FromString(s)))
142 return -1;
143 if (PyList_Append(list, string))
144 {
145 Py_DECREF(string);
146 return -1;
147 }
148
149 Py_DECREF(string);
150 return 0;
151}
152
153 static PyObject *
154ObjectDir(PyObject *self, char **attributes)
155{
156 PyMethodDef *method;
157 char **attr;
158 PyObject *r;
159
160 if (!(r = PyList_New(0)))
161 return NULL;
162
163 if (self)
164 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
165 if (add_string(r, (char *) method->ml_name))
166 {
167 Py_DECREF(r);
168 return NULL;
169 }
170
171 for (attr = attributes ; *attr ; ++attr)
172 if (add_string(r, *attr))
173 {
174 Py_DECREF(r);
175 return NULL;
176 }
177
178#if PY_MAJOR_VERSION < 3
179 if (add_string(r, "__members__"))
180 {
181 Py_DECREF(r);
182 return NULL;
183 }
184#endif
185
186 return r;
187}
188
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200189/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200190 */
191
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200192/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200193typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200194
195static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200196
197typedef struct
198{
199 PyObject_HEAD
200 long softspace;
201 long error;
202} OutputObject;
203
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200204static char *OutputAttrs[] = {
205 "softspace",
206 NULL
207};
208
209 static PyObject *
210OutputDir(PyObject *self)
211{
212 return ObjectDir(self, OutputAttrs);
213}
214
Bram Moolenaar77045652012-09-21 13:46:06 +0200215 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200216OutputSetattr(OutputObject *self, char *name, PyObject *val)
Bram Moolenaar77045652012-09-21 13:46:06 +0200217{
218 if (val == NULL)
219 {
Bram Moolenaar8661b172013-05-15 15:44:28 +0200220 PyErr_SetString(PyExc_AttributeError,
221 _("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200222 return -1;
223 }
224
225 if (strcmp(name, "softspace") == 0)
226 {
227 if (!PyInt_Check(val))
228 {
229 PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
230 return -1;
231 }
232
Bram Moolenaard6e39182013-05-21 18:30:34 +0200233 self->softspace = PyInt_AsLong(val);
Bram Moolenaar77045652012-09-21 13:46:06 +0200234 return 0;
235 }
236
237 PyErr_SetString(PyExc_AttributeError, _("invalid attribute"));
238 return -1;
239}
240
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200241/* Buffer IO, we write one whole line at a time. */
242static garray_T io_ga = {0, 0, 1, 80, NULL};
243static writefn old_fn = NULL;
244
245 static void
246PythonIO_Flush(void)
247{
248 if (old_fn != NULL && io_ga.ga_len > 0)
249 {
250 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
251 old_fn((char_u *)io_ga.ga_data);
252 }
253 io_ga.ga_len = 0;
254}
255
256 static void
257writer(writefn fn, char_u *str, PyInt n)
258{
259 char_u *ptr;
260
261 /* Flush when switching output function. */
262 if (fn != old_fn)
263 PythonIO_Flush();
264 old_fn = fn;
265
266 /* Write each NL separated line. Text after the last NL is kept for
267 * writing later. */
268 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
269 {
270 PyInt len = ptr - str;
271
272 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
273 break;
274
275 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
276 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
277 fn((char_u *)io_ga.ga_data);
278 str = ptr + 1;
279 n -= len + 1;
280 io_ga.ga_len = 0;
281 }
282
283 /* Put the remaining text into io_ga for later printing. */
284 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
285 {
286 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
287 io_ga.ga_len += (int)n;
288 }
289}
290
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200291 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200292OutputWrite(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200293{
Bram Moolenaare8cdcef2012-09-12 20:21:43 +0200294 Py_ssize_t len = 0;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200295 char *str = NULL;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200296 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200297
Bram Moolenaar27564802011-09-07 19:30:21 +0200298 if (!PyArg_ParseTuple(args, "et#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200299 return NULL;
300
301 Py_BEGIN_ALLOW_THREADS
302 Python_Lock_Vim();
303 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
304 Python_Release_Vim();
305 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200306 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200307
308 Py_INCREF(Py_None);
309 return Py_None;
310}
311
312 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200313OutputWritelines(OutputObject *self, PyObject *args)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200314{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200315 PyObject *seq;
316 PyObject *iterator;
317 PyObject *item;
Bram Moolenaard6e39182013-05-21 18:30:34 +0200318 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200319
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200320 if (!PyArg_ParseTuple(args, "O", &seq))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200321 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200322
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200323 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200324 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200325
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200326 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200327 {
Bram Moolenaar19e60942011-06-19 00:27:51 +0200328 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200329 PyInt len;
330
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200331 if (!PyArg_Parse(item, "et#", ENC_OPT, &str, &len))
Bram Moolenaardb913952012-06-29 12:54:53 +0200332 {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200333 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200334 Py_DECREF(iterator);
335 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200336 return NULL;
337 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200338 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200339
340 Py_BEGIN_ALLOW_THREADS
341 Python_Lock_Vim();
342 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
343 Python_Release_Vim();
344 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200345 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200346 }
347
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200348 Py_DECREF(iterator);
349
350 /* Iterator may have finished due to an exception */
351 if (PyErr_Occurred())
352 return NULL;
353
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200354 Py_INCREF(Py_None);
355 return Py_None;
356}
357
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100358 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200359OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100360{
361 /* do nothing */
362 Py_INCREF(Py_None);
363 return Py_None;
364}
365
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200366/***************/
367
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200368static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200369 /* name, function, calling, doc */
370 {"write", (PyCFunction)OutputWrite, METH_VARARGS, ""},
371 {"writelines", (PyCFunction)OutputWritelines, METH_VARARGS, ""},
372 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200373 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200374 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200375};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200376
377static OutputObject Output =
378{
379 PyObject_HEAD_INIT(&OutputType)
380 0,
381 0
382};
383
384static OutputObject Error =
385{
386 PyObject_HEAD_INIT(&OutputType)
387 0,
388 1
389};
390
391 static int
392PythonIO_Init_io(void)
393{
394 PySys_SetObject("stdout", (PyObject *)(void *)&Output);
395 PySys_SetObject("stderr", (PyObject *)(void *)&Error);
396
397 if (PyErr_Occurred())
398 {
399 EMSG(_("E264: Python: Error initialising I/O objects"));
400 return -1;
401 }
402
403 return 0;
404}
405
406
407static PyObject *VimError;
408
409/* Check to see whether a Vim error has been reported, or a keyboard
410 * interrupt has been detected.
411 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200412
413 static void
414VimTryStart(void)
415{
416 ++trylevel;
417}
418
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200419 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200420VimTryEnd(void)
421{
422 --trylevel;
423 if (got_int)
424 {
425 PyErr_SetNone(PyExc_KeyboardInterrupt);
426 return 1;
427 }
428 else if (!did_throw)
429 return 0;
430 else if (PyErr_Occurred())
431 return 1;
432 else
433 {
434 PyErr_SetVim((char *) current_exception->value);
435 discard_current_exception();
436 return 1;
437 }
438}
439
440 static int
441VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200442{
443 if (got_int)
444 {
445 PyErr_SetNone(PyExc_KeyboardInterrupt);
446 return 1;
447 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200448 return 0;
449}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200450
451/* Vim module - Implementation
452 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200453
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200454 static PyObject *
455VimCommand(PyObject *self UNUSED, PyObject *args)
456{
457 char *cmd;
458 PyObject *result;
459
460 if (!PyArg_ParseTuple(args, "s", &cmd))
461 return NULL;
462
463 PyErr_Clear();
464
465 Py_BEGIN_ALLOW_THREADS
466 Python_Lock_Vim();
467
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200468 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200469 do_cmdline_cmd((char_u *)cmd);
470 update_screen(VALID);
471
472 Python_Release_Vim();
473 Py_END_ALLOW_THREADS
474
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200475 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200476 result = NULL;
477 else
478 result = Py_None;
479
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200480
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200481 Py_XINCREF(result);
482 return result;
483}
484
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200485/*
486 * Function to translate a typval_T into a PyObject; this will recursively
487 * translate lists/dictionaries into their Python equivalents.
488 *
489 * The depth parameter is to avoid infinite recursion, set it to 1 when
490 * you call VimToPython.
491 */
492 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200493VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200494{
495 PyObject *result;
496 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200497 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200498
499 /* Avoid infinite recursion */
500 if (depth > 100)
501 {
502 Py_INCREF(Py_None);
503 result = Py_None;
504 return result;
505 }
506
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200507 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200508 * then and we can use it again. */
509 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
510 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
511 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200512 sprintf(ptrBuf, "%p",
513 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
514 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200515
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200516 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200517 {
518 Py_INCREF(result);
519 return result;
520 }
521 }
522
523 if (our_tv->v_type == VAR_STRING)
524 {
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200525 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200526 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200527 }
528 else if (our_tv->v_type == VAR_NUMBER)
529 {
530 char buf[NUMBUFLEN];
531
532 /* For backwards compatibility numbers are stored as strings. */
533 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200534 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200535 }
536# ifdef FEAT_FLOAT
537 else if (our_tv->v_type == VAR_FLOAT)
538 {
539 char buf[NUMBUFLEN];
540
541 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200542 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200543 }
544# endif
545 else if (our_tv->v_type == VAR_LIST)
546 {
547 list_T *list = our_tv->vval.v_list;
548 listitem_T *curr;
549
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200550 if (list == NULL)
551 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200552
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200553 if (!(result = PyList_New(0)))
554 return NULL;
555
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200556 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200557 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200558 Py_DECREF(result);
559 return NULL;
560 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200561
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200562 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
563 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200564 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200565 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200566 Py_DECREF(result);
567 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200568 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200569 if (PyList_Append(result, newObj))
570 {
571 Py_DECREF(newObj);
572 Py_DECREF(result);
573 return NULL;
574 }
575 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200576 }
577 }
578 else if (our_tv->v_type == VAR_DICT)
579 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200580
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200581 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
582 long_u todo = ht->ht_used;
583 hashitem_T *hi;
584 dictitem_T *di;
585 if (our_tv->vval.v_dict == NULL)
586 return NULL;
587
588 if (!(result = PyDict_New()))
589 return NULL;
590
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200591 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200592 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200593 Py_DECREF(result);
594 return NULL;
595 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200596
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200597 for (hi = ht->ht_array; todo > 0; ++hi)
598 {
599 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200600 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200601 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200602
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200603 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200604 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200605 {
606 Py_DECREF(result);
607 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200608 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200609 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
610 {
611 Py_DECREF(result);
612 Py_DECREF(newObj);
613 return NULL;
614 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200615 }
616 }
617 }
618 else
619 {
620 Py_INCREF(Py_None);
621 result = Py_None;
622 }
623
624 return result;
625}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200626
627 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200628VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200629{
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200630 char *expr;
631 typval_T *our_tv;
632 PyObject *result;
633 PyObject *lookup_dict;
634
635 if (!PyArg_ParseTuple(args, "s", &expr))
636 return NULL;
637
638 Py_BEGIN_ALLOW_THREADS
639 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200640 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200641 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200642 Python_Release_Vim();
643 Py_END_ALLOW_THREADS
644
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200645 if (VimTryEnd())
646 return NULL;
647
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200648 if (our_tv == NULL)
649 {
650 PyErr_SetVim(_("invalid expression"));
651 return NULL;
652 }
653
654 /* Convert the Vim type into a Python type. Create a dictionary that's
655 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200656 if (!(lookup_dict = PyDict_New()))
657 result = NULL;
658 else
659 {
660 result = VimToPython(our_tv, 1, lookup_dict);
661 Py_DECREF(lookup_dict);
662 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200663
664
665 Py_BEGIN_ALLOW_THREADS
666 Python_Lock_Vim();
667 free_tv(our_tv);
668 Python_Release_Vim();
669 Py_END_ALLOW_THREADS
670
671 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200672}
673
Bram Moolenaardb913952012-06-29 12:54:53 +0200674static PyObject *ConvertToPyObject(typval_T *);
675
676 static PyObject *
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200677VimEvalPy(PyObject *self UNUSED, PyObject *args)
Bram Moolenaardb913952012-06-29 12:54:53 +0200678{
Bram Moolenaardb913952012-06-29 12:54:53 +0200679 char *expr;
680 typval_T *our_tv;
681 PyObject *result;
682
683 if (!PyArg_ParseTuple(args, "s", &expr))
684 return NULL;
685
686 Py_BEGIN_ALLOW_THREADS
687 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200688 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +0200689 our_tv = eval_expr((char_u *)expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200690 Python_Release_Vim();
691 Py_END_ALLOW_THREADS
692
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200693 if (VimTryEnd())
694 return NULL;
695
Bram Moolenaardb913952012-06-29 12:54:53 +0200696 if (our_tv == NULL)
697 {
698 PyErr_SetVim(_("invalid expression"));
699 return NULL;
700 }
701
702 result = ConvertToPyObject(our_tv);
703 Py_BEGIN_ALLOW_THREADS
704 Python_Lock_Vim();
705 free_tv(our_tv);
706 Python_Release_Vim();
707 Py_END_ALLOW_THREADS
708
709 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200710}
711
712 static PyObject *
713VimStrwidth(PyObject *self UNUSED, PyObject *args)
714{
715 char *expr;
716
717 if (!PyArg_ParseTuple(args, "s", &expr))
718 return NULL;
719
Bram Moolenaara54bf402012-12-05 16:30:07 +0100720 return PyLong_FromLong(
721#ifdef FEAT_MBYTE
722 mb_string2cells((char_u *)expr, (int)STRLEN(expr))
723#else
724 STRLEN(expr)
725#endif
726 );
Bram Moolenaardb913952012-06-29 12:54:53 +0200727}
728
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200729/*
730 * Vim module - Definitions
731 */
732
733static struct PyMethodDef VimMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200734 /* name, function, calling, documentation */
735 {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" },
736 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
737 {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"},
738 {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"},
739 { NULL, NULL, 0, NULL }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200740};
741
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200742/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200743 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200744 */
745
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200746static PyTypeObject IterType;
747
748typedef PyObject *(*nextfun)(void **);
749typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200750typedef int (*traversefun)(void *, visitproc, void *);
751typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200752
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200753/* Main purpose of this object is removing the need for do python
754 * initialization (i.e. PyType_Ready and setting type attributes) for a big
755 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200756
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200757typedef struct
758{
759 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200760 void *cur;
761 nextfun next;
762 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200763 traversefun traverse;
764 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200765} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200766
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200767 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200768IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
769 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200770{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200771 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200772
Bram Moolenaar774267b2013-05-21 20:51:59 +0200773 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200774 self->cur = start;
775 self->next = next;
776 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200777 self->traverse = traverse;
778 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200779
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200780 return (PyObject *)(self);
781}
782
783 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200784IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200785{
Bram Moolenaar774267b2013-05-21 20:51:59 +0200786 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +0200787 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +0200788 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200789}
790
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200791 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200792IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200793{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200794 if (self->traverse != NULL)
795 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200796 else
797 return 0;
798}
799
Bram Moolenaar9e74e302013-05-17 21:20:17 +0200800/* Mac OSX defines clear() somewhere. */
801#ifdef clear
802# undef clear
803#endif
804
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200805 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200806IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200807{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200808 if (self->clear != NULL)
809 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +0200810 else
811 return 0;
812}
813
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200814 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200815IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200816{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200817 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200818}
819
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200820 static PyObject *
821IterIter(PyObject *self)
822{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +0200823 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +0200824 return self;
825}
Bram Moolenaardfa38d42013-05-15 13:38:47 +0200826
Bram Moolenaardb913952012-06-29 12:54:53 +0200827typedef struct pylinkedlist_S {
828 struct pylinkedlist_S *pll_next;
829 struct pylinkedlist_S *pll_prev;
830 PyObject *pll_obj;
831} pylinkedlist_T;
832
833static pylinkedlist_T *lastdict = NULL;
834static pylinkedlist_T *lastlist = NULL;
835
836 static void
837pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
838{
839 if (ref->pll_prev == NULL)
840 {
841 if (ref->pll_next == NULL)
842 {
843 *last = NULL;
844 return;
845 }
846 }
847 else
848 ref->pll_prev->pll_next = ref->pll_next;
849
850 if (ref->pll_next == NULL)
851 *last = ref->pll_prev;
852 else
853 ref->pll_next->pll_prev = ref->pll_prev;
854}
855
856 static void
857pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
858{
859 if (*last == NULL)
860 ref->pll_prev = NULL;
861 else
862 {
863 (*last)->pll_next = ref;
864 ref->pll_prev = *last;
865 }
866 ref->pll_next = NULL;
867 ref->pll_obj = self;
868 *last = ref;
869}
870
871static PyTypeObject DictionaryType;
872
873typedef struct
874{
875 PyObject_HEAD
876 dict_T *dict;
877 pylinkedlist_T ref;
878} DictionaryObject;
879
880 static PyObject *
881DictionaryNew(dict_T *dict)
882{
883 DictionaryObject *self;
884
885 self = PyObject_NEW(DictionaryObject, &DictionaryType);
886 if (self == NULL)
887 return NULL;
888 self->dict = dict;
889 ++dict->dv_refcount;
890
891 pyll_add((PyObject *)(self), &self->ref, &lastdict);
892
893 return (PyObject *)(self);
894}
895
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200896 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +0200897DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200898{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200899 pyll_remove(&self->ref, &lastdict);
900 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +0200901
902 DESTRUCTOR_FINISH(self);
903}
904
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200905static char *DictionaryAttrs[] = {
906 "locked", "scope",
907 NULL
908};
909
910 static PyObject *
911DictionaryDir(PyObject *self)
912{
913 return ObjectDir(self, DictionaryAttrs);
914}
915
Bram Moolenaardb913952012-06-29 12:54:53 +0200916 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200917DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200918{
919 if (val == NULL)
920 {
921 PyErr_SetString(PyExc_AttributeError, _("Cannot delete DictionaryObject attributes"));
922 return -1;
923 }
924
925 if (strcmp(name, "locked") == 0)
926 {
Bram Moolenaard6e39182013-05-21 18:30:34 +0200927 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +0200928 {
929 PyErr_SetString(PyExc_TypeError, _("Cannot modify fixed dictionary"));
930 return -1;
931 }
932 else
933 {
Bram Moolenaarb983f752013-05-15 16:11:50 +0200934 int istrue = PyObject_IsTrue(val);
935 if (istrue == -1)
936 return -1;
937 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +0200938 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200939 else
Bram Moolenaard6e39182013-05-21 18:30:34 +0200940 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +0200941 }
942 return 0;
943 }
944 else
945 {
946 PyErr_SetString(PyExc_AttributeError, _("Cannot set this attribute"));
947 return -1;
948 }
949}
950
951 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +0200952DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +0200953{
Bram Moolenaard6e39182013-05-21 18:30:34 +0200954 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +0200955}
956
957 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +0200958DictionaryItem(DictionaryObject *self, PyObject *keyObject)
Bram Moolenaardb913952012-06-29 12:54:53 +0200959{
960 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200961 dictitem_T *di;
Bram Moolenaardb913952012-06-29 12:54:53 +0200962 DICTKEY_DECL
963
Bram Moolenaara03e6312013-05-29 22:49:26 +0200964 DICTKEY_GET(NULL, 0)
Bram Moolenaardb913952012-06-29 12:54:53 +0200965
Bram Moolenaard6e39182013-05-21 18:30:34 +0200966 di = dict_find(self->dict, key, -1);
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200967
Bram Moolenaar696c2112012-09-21 13:43:14 +0200968 DICTKEY_UNREF
969
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200970 if (di == NULL)
971 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +0200972 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200973 return NULL;
974 }
Bram Moolenaardb913952012-06-29 12:54:53 +0200975
Bram Moolenaar231e1a12012-09-05 18:45:28 +0200976 return ConvertToPyObject(&di->di_tv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200977}
978
979 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +0200980DictionaryAssItem(DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +0200981{
982 char_u *key;
983 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200984 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +0200985 dictitem_T *di;
986 DICTKEY_DECL
987
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200988 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +0200989 {
990 PyErr_SetVim(_("dict is locked"));
991 return -1;
992 }
993
Bram Moolenaara03e6312013-05-29 22:49:26 +0200994 DICTKEY_GET(-1, 0)
Bram Moolenaardb913952012-06-29 12:54:53 +0200995
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200996 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +0200997
998 if (valObject == NULL)
999 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001000 hashitem_T *hi;
1001
Bram Moolenaardb913952012-06-29 12:54:53 +02001002 if (di == NULL)
1003 {
Bram Moolenaar696c2112012-09-21 13:43:14 +02001004 DICTKEY_UNREF
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001005 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001006 return -1;
1007 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001008 hi = hash_find(&dict->dv_hashtab, di->di_key);
1009 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001010 dictitem_free(di);
1011 return 0;
1012 }
1013
1014 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02001015 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02001016
1017 if (di == NULL)
1018 {
1019 di = dictitem_alloc(key);
1020 if (di == NULL)
1021 {
1022 PyErr_NoMemory();
1023 return -1;
1024 }
1025 di->di_tv.v_lock = 0;
1026
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001027 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001028 {
Bram Moolenaar696c2112012-09-21 13:43:14 +02001029 DICTKEY_UNREF
Bram Moolenaardb913952012-06-29 12:54:53 +02001030 vim_free(di);
1031 PyErr_SetVim(_("failed to add key to dictionary"));
1032 return -1;
1033 }
1034 }
1035 else
1036 clear_tv(&di->di_tv);
1037
1038 DICTKEY_UNREF
1039
1040 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001041 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001042 return 0;
1043}
1044
1045 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001046DictionaryListKeys(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001047{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001048 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001049 long_u todo = dict->dv_hashtab.ht_used;
1050 Py_ssize_t i = 0;
1051 PyObject *r;
1052 hashitem_T *hi;
1053
1054 r = PyList_New(todo);
1055 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1056 {
1057 if (!HASHITEM_EMPTY(hi))
1058 {
1059 PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key)));
1060 --todo;
1061 ++i;
1062 }
1063 }
1064 return r;
1065}
1066
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001067static PyMappingMethods DictionaryAsMapping = {
1068 (lenfunc) DictionaryLength,
1069 (binaryfunc) DictionaryItem,
1070 (objobjargproc) DictionaryAssItem,
1071};
1072
Bram Moolenaardb913952012-06-29 12:54:53 +02001073static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001074 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001075 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1076 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001077};
1078
1079static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001080static PySequenceMethods ListAsSeq;
1081static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001082
1083typedef struct
1084{
1085 PyObject_HEAD
1086 list_T *list;
1087 pylinkedlist_T ref;
1088} ListObject;
1089
1090 static PyObject *
1091ListNew(list_T *list)
1092{
1093 ListObject *self;
1094
1095 self = PyObject_NEW(ListObject, &ListType);
1096 if (self == NULL)
1097 return NULL;
1098 self->list = list;
1099 ++list->lv_refcount;
1100
1101 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1102
1103 return (PyObject *)(self);
1104}
1105
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001106 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001107ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001108{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001109 pyll_remove(&self->ref, &lastlist);
1110 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001111
1112 DESTRUCTOR_FINISH(self);
1113}
1114
Bram Moolenaardb913952012-06-29 12:54:53 +02001115 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001116list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001117{
1118 Py_ssize_t i;
1119 Py_ssize_t lsize = PySequence_Size(obj);
1120 PyObject *litem;
1121 listitem_T *li;
1122
1123 for(i=0; i<lsize; i++)
1124 {
1125 li = listitem_alloc();
1126 if (li == NULL)
1127 {
1128 PyErr_NoMemory();
1129 return -1;
1130 }
1131 li->li_tv.v_lock = 0;
1132
1133 litem = PySequence_GetItem(obj, i);
1134 if (litem == NULL)
1135 return -1;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001136 if (_ConvertFromPyObject(litem, &li->li_tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02001137 return -1;
1138
1139 list_append(l, li);
1140 }
1141 return 0;
1142}
1143
Bram Moolenaardb913952012-06-29 12:54:53 +02001144 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001145ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001146{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001147 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02001148}
1149
1150 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001151ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02001152{
1153 listitem_T *li;
1154
Bram Moolenaard6e39182013-05-21 18:30:34 +02001155 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02001156 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001157 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001158 return NULL;
1159 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02001160 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02001161 if (li == NULL)
1162 {
1163 PyErr_SetVim(_("internal error: failed to get vim list item"));
1164 return NULL;
1165 }
1166 return ConvertToPyObject(&li->li_tv);
1167}
1168
1169#define PROC_RANGE \
1170 if (last < 0) {\
1171 if (last < -size) \
1172 last = 0; \
1173 else \
1174 last += size; \
1175 } \
1176 if (first < 0) \
1177 first = 0; \
1178 if (first > size) \
1179 first = size; \
1180 if (last > size) \
1181 last = size;
1182
1183 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001184ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02001185{
1186 PyInt i;
1187 PyInt size = ListLength(self);
1188 PyInt n;
1189 PyObject *list;
1190 int reversed = 0;
1191
1192 PROC_RANGE
1193 if (first >= last)
1194 first = last;
1195
1196 n = last-first;
1197 list = PyList_New(n);
1198 if (list == NULL)
1199 return NULL;
1200
1201 for (i = 0; i < n; ++i)
1202 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02001203 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02001204 if (item == NULL)
1205 {
1206 Py_DECREF(list);
1207 return NULL;
1208 }
1209
1210 if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item)))
1211 {
1212 Py_DECREF(item);
1213 Py_DECREF(list);
1214 return NULL;
1215 }
1216 }
1217
1218 return list;
1219}
1220
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001221typedef struct
1222{
1223 listwatch_T lw;
1224 list_T *list;
1225} listiterinfo_T;
1226
1227 static void
1228ListIterDestruct(listiterinfo_T *lii)
1229{
1230 list_rem_watch(lii->list, &lii->lw);
1231 PyMem_Free(lii);
1232}
1233
1234 static PyObject *
1235ListIterNext(listiterinfo_T **lii)
1236{
1237 PyObject *r;
1238
1239 if (!((*lii)->lw.lw_item))
1240 return NULL;
1241
1242 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
1243 return NULL;
1244
1245 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
1246
1247 return r;
1248}
1249
1250 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001251ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001252{
1253 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001254 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001255
1256 if (!(lii = PyMem_New(listiterinfo_T, 1)))
1257 {
1258 PyErr_NoMemory();
1259 return NULL;
1260 }
1261
1262 list_add_watch(l, &lii->lw);
1263 lii->lw.lw_item = l->lv_first;
1264 lii->list = l;
1265
1266 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001267 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
1268 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001269}
1270
Bram Moolenaardb913952012-06-29 12:54:53 +02001271 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001272ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001273{
1274 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001275 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001276 listitem_T *li;
1277 Py_ssize_t length = ListLength(self);
1278
1279 if (l->lv_lock)
1280 {
1281 PyErr_SetVim(_("list is locked"));
1282 return -1;
1283 }
1284 if (index>length || (index==length && obj==NULL))
1285 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001286 PyErr_SetString(PyExc_IndexError, _("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001287 return -1;
1288 }
1289
1290 if (obj == NULL)
1291 {
1292 li = list_find(l, (long) index);
1293 list_remove(l, li, li);
1294 clear_tv(&li->li_tv);
1295 vim_free(li);
1296 return 0;
1297 }
1298
1299 if (ConvertFromPyObject(obj, &tv) == -1)
1300 return -1;
1301
1302 if (index == length)
1303 {
1304 if (list_append_tv(l, &tv) == FAIL)
1305 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001306 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001307 PyErr_SetVim(_("Failed to add item to list"));
1308 return -1;
1309 }
1310 }
1311 else
1312 {
1313 li = list_find(l, (long) index);
1314 clear_tv(&li->li_tv);
1315 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001316 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001317 }
1318 return 0;
1319}
1320
1321 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001322ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001323{
1324 PyInt size = ListLength(self);
1325 Py_ssize_t i;
1326 Py_ssize_t lsize;
1327 PyObject *litem;
1328 listitem_T *li;
1329 listitem_T *next;
1330 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02001331 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001332
1333 if (l->lv_lock)
1334 {
1335 PyErr_SetVim(_("list is locked"));
1336 return -1;
1337 }
1338
1339 PROC_RANGE
1340
1341 if (first == size)
1342 li = NULL;
1343 else
1344 {
1345 li = list_find(l, (long) first);
1346 if (li == NULL)
1347 {
1348 PyErr_SetVim(_("internal error: no vim list item"));
1349 return -1;
1350 }
1351 if (last > first)
1352 {
1353 i = last - first;
1354 while (i-- && li != NULL)
1355 {
1356 next = li->li_next;
1357 listitem_remove(l, li);
1358 li = next;
1359 }
1360 }
1361 }
1362
1363 if (obj == NULL)
1364 return 0;
1365
1366 if (!PyList_Check(obj))
1367 {
1368 PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
1369 return -1;
1370 }
1371
1372 lsize = PyList_Size(obj);
1373
1374 for(i=0; i<lsize; i++)
1375 {
1376 litem = PyList_GetItem(obj, i);
1377 if (litem == NULL)
1378 return -1;
1379 if (ConvertFromPyObject(litem, &v) == -1)
1380 return -1;
1381 if (list_insert_tv(l, &v, li) == FAIL)
1382 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001383 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001384 PyErr_SetVim(_("internal error: failed to add item to list"));
1385 return -1;
1386 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001387 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02001388 }
1389 return 0;
1390}
1391
1392 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001393ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02001394{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001395 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02001396 PyObject *lookup_dict;
1397
1398 if (l->lv_lock)
1399 {
1400 PyErr_SetVim(_("list is locked"));
1401 return NULL;
1402 }
1403
1404 if (!PySequence_Check(obj))
1405 {
1406 PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
1407 return NULL;
1408 }
1409
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02001410 if (!(lookup_dict = PyDict_New()))
1411 return NULL;
1412
Bram Moolenaardb913952012-06-29 12:54:53 +02001413 if (list_py_concat(l, obj, lookup_dict) == -1)
1414 {
1415 Py_DECREF(lookup_dict);
1416 return NULL;
1417 }
1418 Py_DECREF(lookup_dict);
1419
1420 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02001421 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02001422}
1423
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001424static char *ListAttrs[] = {
1425 "locked",
1426 NULL
1427};
1428
1429 static PyObject *
1430ListDir(PyObject *self)
1431{
1432 return ObjectDir(self, ListAttrs);
1433}
1434
Bram Moolenaar66b79852012-09-21 14:00:35 +02001435 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001436ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001437{
1438 if (val == NULL)
1439 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001440 PyErr_SetString(PyExc_AttributeError,
1441 _("cannot delete vim.dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001442 return -1;
1443 }
1444
1445 if (strcmp(name, "locked") == 0)
1446 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001447 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001448 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001449 PyErr_SetString(PyExc_TypeError, _("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001450 return -1;
1451 }
1452 else
1453 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001454 int istrue = PyObject_IsTrue(val);
1455 if (istrue == -1)
1456 return -1;
1457 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001458 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001459 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001460 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001461 }
1462 return 0;
1463 }
1464 else
1465 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001466 PyErr_SetString(PyExc_AttributeError, _("cannot set this attribute"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001467 return -1;
1468 }
1469}
1470
Bram Moolenaardb913952012-06-29 12:54:53 +02001471static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001472 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
1473 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
1474 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001475};
1476
1477typedef struct
1478{
1479 PyObject_HEAD
1480 char_u *name;
1481} FunctionObject;
1482
1483static PyTypeObject FunctionType;
1484
1485 static PyObject *
1486FunctionNew(char_u *name)
1487{
1488 FunctionObject *self;
1489
1490 self = PyObject_NEW(FunctionObject, &FunctionType);
1491 if (self == NULL)
1492 return NULL;
1493 self->name = PyMem_New(char_u, STRLEN(name) + 1);
1494 if (self->name == NULL)
1495 {
1496 PyErr_NoMemory();
1497 return NULL;
1498 }
1499 STRCPY(self->name, name);
1500 func_ref(name);
1501 return (PyObject *)(self);
1502}
1503
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001504 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001505FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001506{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001507 func_unref(self->name);
1508 PyMem_Free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001509
1510 DESTRUCTOR_FINISH(self);
1511}
1512
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001513static char *FunctionAttrs[] = {
1514 "softspace",
1515 NULL
1516};
1517
1518 static PyObject *
1519FunctionDir(PyObject *self)
1520{
1521 return ObjectDir(self, FunctionAttrs);
1522}
1523
Bram Moolenaardb913952012-06-29 12:54:53 +02001524 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001525FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02001526{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001527 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02001528 typval_T args;
1529 typval_T selfdicttv;
1530 typval_T rettv;
1531 dict_T *selfdict = NULL;
1532 PyObject *selfdictObject;
1533 PyObject *result;
1534 int error;
1535
1536 if (ConvertFromPyObject(argsObject, &args) == -1)
1537 return NULL;
1538
1539 if (kwargs != NULL)
1540 {
1541 selfdictObject = PyDict_GetItemString(kwargs, "self");
1542 if (selfdictObject != NULL)
1543 {
Bram Moolenaar9581b5f2012-07-25 15:36:04 +02001544 if (!PyMapping_Check(selfdictObject))
Bram Moolenaardb913952012-06-29 12:54:53 +02001545 {
Bram Moolenaar9581b5f2012-07-25 15:36:04 +02001546 PyErr_SetString(PyExc_TypeError,
1547 _("'self' argument must be a dictionary"));
Bram Moolenaardb913952012-06-29 12:54:53 +02001548 clear_tv(&args);
1549 return NULL;
1550 }
1551 if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001552 {
1553 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02001554 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001555 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001556 selfdict = selfdicttv.vval.v_dict;
1557 }
1558 }
1559
Bram Moolenaar71700b82013-05-15 17:49:05 +02001560 Py_BEGIN_ALLOW_THREADS
1561 Python_Lock_Vim();
1562
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001563 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02001564 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02001565
1566 Python_Release_Vim();
1567 Py_END_ALLOW_THREADS
1568
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001569 if (VimTryEnd())
1570 result = NULL;
1571 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02001572 {
1573 result = NULL;
1574 PyErr_SetVim(_("failed to run function"));
1575 }
1576 else
1577 result = ConvertToPyObject(&rettv);
1578
Bram Moolenaardb913952012-06-29 12:54:53 +02001579 clear_tv(&args);
1580 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001581 if (selfdict != NULL)
1582 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001583
1584 return result;
1585}
1586
Bram Moolenaara5b725c2013-05-30 12:43:54 +02001587 static PyObject *
1588FunctionRepr(FunctionObject *self)
1589{
1590 return PyString_FromFormat("<vim.Function '%s'>", self->name);
1591}
1592
Bram Moolenaardb913952012-06-29 12:54:53 +02001593static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001594 {"__call__",(PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
1595 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
1596 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001597};
1598
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001599/*
1600 * Options object
1601 */
1602
1603static PyTypeObject OptionsType;
1604
1605typedef int (*checkfun)(void *);
1606
1607typedef struct
1608{
1609 PyObject_HEAD
1610 int opt_type;
1611 void *from;
1612 checkfun Check;
1613 PyObject *fromObj;
1614} OptionsObject;
1615
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001616 static int
1617dummy_check(void *arg UNUSED)
1618{
1619 return 0;
1620}
1621
1622 static PyObject *
1623OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
1624{
1625 OptionsObject *self;
1626
Bram Moolenaar774267b2013-05-21 20:51:59 +02001627 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001628 if (self == NULL)
1629 return NULL;
1630
1631 self->opt_type = opt_type;
1632 self->from = from;
1633 self->Check = Check;
1634 self->fromObj = fromObj;
1635 if (fromObj)
1636 Py_INCREF(fromObj);
1637
1638 return (PyObject *)(self);
1639}
1640
1641 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001642OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001643{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001644 PyObject_GC_UnTrack((void *)(self));
1645 Py_XDECREF(self->fromObj);
1646 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001647}
1648
1649 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001650OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001651{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001652 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001653 return 0;
1654}
1655
1656 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001657OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001658{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001659 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001660 return 0;
1661}
1662
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001663 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001664OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001665{
1666 char_u *key;
1667 int flags;
1668 long numval;
1669 char_u *stringval;
Bram Moolenaar161fb5e2013-05-06 06:26:15 +02001670 DICTKEY_DECL
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001671
Bram Moolenaard6e39182013-05-21 18:30:34 +02001672 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001673 return NULL;
1674
Bram Moolenaara03e6312013-05-29 22:49:26 +02001675 DICTKEY_GET(NULL, 0)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001676
1677 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02001678 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001679
1680 DICTKEY_UNREF
1681
1682 if (flags == 0)
1683 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001684 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001685 return NULL;
1686 }
1687
1688 if (flags & SOPT_UNSET)
1689 {
1690 Py_INCREF(Py_None);
1691 return Py_None;
1692 }
1693 else if (flags & SOPT_BOOL)
1694 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001695 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001696 r = numval ? Py_True : Py_False;
1697 Py_INCREF(r);
1698 return r;
1699 }
1700 else if (flags & SOPT_NUM)
1701 return PyInt_FromLong(numval);
1702 else if (flags & SOPT_STRING)
1703 {
1704 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001705 {
1706 PyObject *r = PyBytes_FromString((char *) stringval);
1707 vim_free(stringval);
1708 return r;
1709 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001710 else
1711 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001712 PyErr_SetString(PyExc_RuntimeError,
1713 _("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001714 return NULL;
1715 }
1716 }
1717 else
1718 {
1719 PyErr_SetVim("Internal error: unknown option type. Should not happen");
1720 return NULL;
1721 }
1722}
1723
1724 static int
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001725set_option_value_err(key, numval, stringval, opt_flags)
1726 char_u *key;
1727 int numval;
1728 char_u *stringval;
1729 int opt_flags;
1730{
1731 char_u *errmsg;
1732
1733 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
1734 {
1735 if (VimTryEnd())
1736 return FAIL;
1737 PyErr_SetVim((char *)errmsg);
1738 return FAIL;
1739 }
1740 return OK;
1741}
1742
1743 static int
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001744set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
1745 char_u *key;
1746 int numval;
1747 char_u *stringval;
1748 int opt_flags;
1749 int opt_type;
1750 void *from;
1751{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001752 win_T *save_curwin = NULL;
1753 tabpage_T *save_curtab = NULL;
1754 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001755 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001756
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001757 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001758 switch (opt_type)
1759 {
1760 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02001761 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
1762 win_find_tabpage((win_T *)from)) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001763 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001764 if (VimTryEnd())
1765 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001766 PyErr_SetVim("Problem while switching windows.");
1767 return -1;
1768 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001769 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001770 restore_win(save_curwin, save_curtab);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001771 if (r == FAIL)
1772 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001773 break;
1774 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02001775 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001776 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02001777 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001778 if (r == FAIL)
1779 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001780 break;
1781 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001782 r = set_option_value_err(key, numval, stringval, opt_flags);
1783 if (r == FAIL)
1784 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001785 break;
1786 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02001787 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001788}
1789
Bram Moolenaare9ba5162013-05-29 22:02:22 +02001790 static void *
1791py_memsave(void *p, size_t len)
1792{
1793 void *r;
1794 if (!(r = PyMem_Malloc(len)))
1795 return NULL;
1796 mch_memmove(r, p, len);
1797 return r;
1798}
1799
1800#define PY_STRSAVE(s) ((char_u *) py_memsave(s, STRLEN(s) + 1))
1801
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001802 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001803OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001804{
1805 char_u *key;
1806 int flags;
1807 int opt_flags;
1808 int r = 0;
Bram Moolenaar161fb5e2013-05-06 06:26:15 +02001809 DICTKEY_DECL
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001810
Bram Moolenaard6e39182013-05-21 18:30:34 +02001811 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001812 return -1;
1813
Bram Moolenaara03e6312013-05-29 22:49:26 +02001814 DICTKEY_GET(-1, 0)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001815
1816 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02001817 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001818
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001819 if (flags == 0)
1820 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001821 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001822 DICTKEY_UNREF
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001823 return -1;
1824 }
1825
1826 if (valObject == NULL)
1827 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001828 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001829 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001830 PyErr_SetString(PyExc_ValueError,
1831 _("unable to unset global option"));
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001832 DICTKEY_UNREF
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001833 return -1;
1834 }
1835 else if (!(flags & SOPT_GLOBAL))
1836 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001837 PyErr_SetString(PyExc_ValueError, _("unable to unset option "
1838 "without global value"));
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001839 DICTKEY_UNREF
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001840 return -1;
1841 }
1842 else
1843 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001844 unset_global_local_option(key, self->from);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001845 DICTKEY_UNREF
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001846 return 0;
1847 }
1848 }
1849
Bram Moolenaard6e39182013-05-21 18:30:34 +02001850 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001851
1852 if (flags & SOPT_BOOL)
1853 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001854 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02001855
Bram Moolenaarb983f752013-05-15 16:11:50 +02001856 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001857 r = -1;
1858 else
1859 r = set_option_value_for(key, istrue, NULL,
1860 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001861 }
1862 else if (flags & SOPT_NUM)
1863 {
1864 int val;
1865
1866#if PY_MAJOR_VERSION < 3
1867 if (PyInt_Check(valObject))
1868 val = PyInt_AsLong(valObject);
1869 else
1870#endif
1871 if (PyLong_Check(valObject))
1872 val = PyLong_AsLong(valObject);
1873 else
1874 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02001875 PyErr_SetString(PyExc_TypeError, _("object must be integer"));
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001876 DICTKEY_UNREF
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001877 return -1;
1878 }
1879
1880 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02001881 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001882 }
1883 else
1884 {
1885 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02001886 PyObject *todecref;
1887
1888 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001889 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02001890 r = set_option_value_for(key, 0, val, opt_flags,
1891 self->opt_type, self->from);
1892 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001893 }
1894 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02001895 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001896 }
1897
Bram Moolenaar1bc24282013-05-29 21:37:35 +02001898 DICTKEY_UNREF
1899
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001900 return r;
1901}
1902
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02001903static PyMappingMethods OptionsAsMapping = {
1904 (lenfunc) NULL,
1905 (binaryfunc) OptionsItem,
1906 (objobjargproc) OptionsAssItem,
1907};
1908
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001909/* Tabpage object
1910 */
1911
1912typedef struct
1913{
1914 PyObject_HEAD
1915 tabpage_T *tab;
1916} TabPageObject;
1917
1918static PyObject *WinListNew(TabPageObject *tabObject);
1919
1920static PyTypeObject TabPageType;
1921
1922 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001923CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001924{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001925 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001926 {
1927 PyErr_SetVim(_("attempt to refer to deleted tab page"));
1928 return -1;
1929 }
1930
1931 return 0;
1932}
1933
1934 static PyObject *
1935TabPageNew(tabpage_T *tab)
1936{
1937 TabPageObject *self;
1938
1939 if (TAB_PYTHON_REF(tab))
1940 {
1941 self = TAB_PYTHON_REF(tab);
1942 Py_INCREF(self);
1943 }
1944 else
1945 {
1946 self = PyObject_NEW(TabPageObject, &TabPageType);
1947 if (self == NULL)
1948 return NULL;
1949 self->tab = tab;
1950 TAB_PYTHON_REF(tab) = self;
1951 }
1952
1953 return (PyObject *)(self);
1954}
1955
1956 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001957TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001958{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001959 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
1960 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001961
1962 DESTRUCTOR_FINISH(self);
1963}
1964
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001965static char *TabPageAttrs[] = {
1966 "windows", "number", "vars", "window", "valid",
1967 NULL
1968};
1969
1970 static PyObject *
1971TabPageDir(PyObject *self)
1972{
1973 return ObjectDir(self, TabPageAttrs);
1974}
1975
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001976 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02001977TabPageAttrValid(TabPageObject *self, char *name)
1978{
1979 PyObject *r;
1980
1981 if (strcmp(name, "valid") != 0)
1982 return NULL;
1983
1984 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
1985 Py_INCREF(r);
1986 return r;
1987}
1988
1989 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001990TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001991{
1992 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001993 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001994 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001995 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001996 else if (strcmp(name, "vars") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001997 return DictionaryNew(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02001998 else if (strcmp(name, "window") == 0)
1999 {
2000 /* For current tab window.c does not bother to set or update tp_curwin
2001 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002002 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002003 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002004 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002005 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002006 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002007 else if (strcmp(name, "__members__") == 0)
2008 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002009 return NULL;
2010}
2011
2012 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002013TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002014{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002015 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002016 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002017 else
2018 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002019 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002020
2021 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002022 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2023 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002024 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002025 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002026 }
2027}
2028
2029static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002030 /* name, function, calling, documentation */
2031 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2032 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002033};
2034
2035/*
2036 * Window list object
2037 */
2038
2039static PyTypeObject TabListType;
2040static PySequenceMethods TabListAsSeq;
2041
2042typedef struct
2043{
2044 PyObject_HEAD
2045} TabListObject;
2046
2047 static PyInt
2048TabListLength(PyObject *self UNUSED)
2049{
2050 tabpage_T *tp = first_tabpage;
2051 PyInt n = 0;
2052
2053 while (tp != NULL)
2054 {
2055 ++n;
2056 tp = tp->tp_next;
2057 }
2058
2059 return n;
2060}
2061
2062 static PyObject *
2063TabListItem(PyObject *self UNUSED, PyInt n)
2064{
2065 tabpage_T *tp;
2066
2067 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
2068 if (n == 0)
2069 return TabPageNew(tp);
2070
2071 PyErr_SetString(PyExc_IndexError, _("no such tab page"));
2072 return NULL;
2073}
2074
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002075/* Window object
2076 */
2077
2078typedef struct
2079{
2080 PyObject_HEAD
2081 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002082 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002083} WindowObject;
2084
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002085static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002086
2087 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002088CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002089{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002090 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002091 {
2092 PyErr_SetVim(_("attempt to refer to deleted window"));
2093 return -1;
2094 }
2095
2096 return 0;
2097}
2098
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002099 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002100WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02002101{
2102 /* We need to handle deletion of windows underneath us.
2103 * If we add a "w_python*_ref" field to the win_T structure,
2104 * then we can get at it in win_free() in vim. We then
2105 * need to create only ONE Python object per window - if
2106 * we try to create a second, just INCREF the existing one
2107 * and return it. The (single) Python object referring to
2108 * the window is stored in "w_python*_ref".
2109 * On a win_free() we set the Python object's win_T* field
2110 * to an invalid value. We trap all uses of a window
2111 * object, and reject them if the win_T* field is invalid.
2112 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002113 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02002114 * w_python_ref and w_python3_ref fields respectively.
2115 */
2116
2117 WindowObject *self;
2118
2119 if (WIN_PYTHON_REF(win))
2120 {
2121 self = WIN_PYTHON_REF(win);
2122 Py_INCREF(self);
2123 }
2124 else
2125 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02002126 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02002127 if (self == NULL)
2128 return NULL;
2129 self->win = win;
2130 WIN_PYTHON_REF(win) = self;
2131 }
2132
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002133 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
2134
Bram Moolenaar971db462013-05-12 18:44:48 +02002135 return (PyObject *)(self);
2136}
2137
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002138 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002139WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002140{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002141 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02002142 if (self->win && self->win != INVALID_WINDOW_VALUE)
2143 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02002144 Py_XDECREF(((PyObject *)(self->tabObject)));
2145 PyObject_GC_Del((void *)(self));
2146}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002147
Bram Moolenaar774267b2013-05-21 20:51:59 +02002148 static int
2149WindowTraverse(WindowObject *self, visitproc visit, void *arg)
2150{
2151 Py_VISIT(((PyObject *)(self->tabObject)));
2152 return 0;
2153}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002154
Bram Moolenaar774267b2013-05-21 20:51:59 +02002155 static int
2156WindowClear(WindowObject *self)
2157{
2158 Py_CLEAR(self->tabObject);
2159 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002160}
2161
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002162 static win_T *
2163get_firstwin(TabPageObject *tabObject)
2164{
2165 if (tabObject)
2166 {
2167 if (CheckTabPage(tabObject))
2168 return NULL;
2169 /* For current tab window.c does not bother to set or update tp_firstwin
2170 */
2171 else if (tabObject->tab == curtab)
2172 return firstwin;
2173 else
2174 return tabObject->tab->tp_firstwin;
2175 }
2176 else
2177 return firstwin;
2178}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002179static char *WindowAttrs[] = {
2180 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
2181 "tabpage", "valid",
2182 NULL
2183};
2184
2185 static PyObject *
2186WindowDir(PyObject *self)
2187{
2188 return ObjectDir(self, WindowAttrs);
2189}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002190
Bram Moolenaar971db462013-05-12 18:44:48 +02002191 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002192WindowAttrValid(WindowObject *self, char *name)
2193{
2194 PyObject *r;
2195
2196 if (strcmp(name, "valid") != 0)
2197 return NULL;
2198
2199 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
2200 Py_INCREF(r);
2201 return r;
2202}
2203
2204 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002205WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002206{
2207 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002208 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002209 else if (strcmp(name, "cursor") == 0)
2210 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002211 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002212
2213 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
2214 }
2215 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002216 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002217#ifdef FEAT_WINDOWS
2218 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002219 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002220#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002221#ifdef FEAT_VERTSPLIT
2222 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002223 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02002224 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002225 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002226#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02002227 else if (strcmp(name, "vars") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002228 return DictionaryNew(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002229 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002230 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
2231 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02002232 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002233 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002234 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002235 return NULL;
2236 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002237 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002238 }
2239 else if (strcmp(name, "tabpage") == 0)
2240 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002241 Py_INCREF(self->tabObject);
2242 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002243 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002244 else if (strcmp(name, "__members__") == 0)
2245 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002246 else
2247 return NULL;
2248}
2249
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002250 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002251WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002252{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002253 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002254 return -1;
2255
2256 if (strcmp(name, "buffer") == 0)
2257 {
2258 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
2259 return -1;
2260 }
2261 else if (strcmp(name, "cursor") == 0)
2262 {
2263 long lnum;
2264 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002265
2266 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
2267 return -1;
2268
Bram Moolenaard6e39182013-05-21 18:30:34 +02002269 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002270 {
2271 PyErr_SetVim(_("cursor position outside buffer"));
2272 return -1;
2273 }
2274
2275 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002276 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002277 return -1;
2278
Bram Moolenaard6e39182013-05-21 18:30:34 +02002279 self->win->w_cursor.lnum = lnum;
2280 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002281#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02002282 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002283#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002284 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002285 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002286
Bram Moolenaar03a807a2011-07-07 15:08:58 +02002287 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002288 return 0;
2289 }
2290 else if (strcmp(name, "height") == 0)
2291 {
2292 int height;
2293 win_T *savewin;
2294
2295 if (!PyArg_Parse(val, "i", &height))
2296 return -1;
2297
2298#ifdef FEAT_GUI
2299 need_mouse_correct = TRUE;
2300#endif
2301 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002302 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002303
2304 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002305 win_setheight(height);
2306 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002307 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002308 return -1;
2309
2310 return 0;
2311 }
2312#ifdef FEAT_VERTSPLIT
2313 else if (strcmp(name, "width") == 0)
2314 {
2315 int width;
2316 win_T *savewin;
2317
2318 if (!PyArg_Parse(val, "i", &width))
2319 return -1;
2320
2321#ifdef FEAT_GUI
2322 need_mouse_correct = TRUE;
2323#endif
2324 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002325 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002326
2327 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002328 win_setwidth(width);
2329 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002330 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002331 return -1;
2332
2333 return 0;
2334 }
2335#endif
2336 else
2337 {
2338 PyErr_SetString(PyExc_AttributeError, name);
2339 return -1;
2340 }
2341}
2342
2343 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002344WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002345{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002346 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002347 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002348 else
2349 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002350 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002351
Bram Moolenaar6d216452013-05-12 19:00:41 +02002352 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002353 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002354 (self));
2355 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002356 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002357 }
2358}
2359
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002360static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002361 /* name, function, calling, documentation */
2362 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
2363 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002364};
2365
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002366/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002367 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002368 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002369
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002370static PyTypeObject WinListType;
2371static PySequenceMethods WinListAsSeq;
2372
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002373typedef struct
2374{
2375 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002376 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002377} WinListObject;
2378
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002379 static PyObject *
2380WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002381{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002382 WinListObject *self;
2383
2384 self = PyObject_NEW(WinListObject, &WinListType);
2385 self->tabObject = tabObject;
2386 Py_INCREF(tabObject);
2387
2388 return (PyObject *)(self);
2389}
2390
2391 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002392WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002393{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002394 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002395
2396 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02002397 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002398 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02002399 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002400
2401 DESTRUCTOR_FINISH(self);
2402}
2403
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002404 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002405WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002406{
2407 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002408 PyInt n = 0;
2409
Bram Moolenaard6e39182013-05-21 18:30:34 +02002410 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002411 return -1;
2412
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002413 while (w != NULL)
2414 {
2415 ++n;
2416 w = W_NEXT(w);
2417 }
2418
2419 return n;
2420}
2421
2422 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002423WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002424{
2425 win_T *w;
2426
Bram Moolenaard6e39182013-05-21 18:30:34 +02002427 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002428 return NULL;
2429
2430 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002431 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002432 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002433
2434 PyErr_SetString(PyExc_IndexError, _("no such window"));
2435 return NULL;
2436}
2437
2438/* Convert a Python string into a Vim line.
2439 *
2440 * The result is in allocated memory. All internal nulls are replaced by
2441 * newline characters. It is an error for the string to contain newline
2442 * characters.
2443 *
2444 * On errors, the Python exception data is set, and NULL is returned.
2445 */
2446 static char *
2447StringToLine(PyObject *obj)
2448{
2449 const char *str;
2450 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +02002451 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002452 PyInt len;
2453 PyInt i;
2454 char *p;
2455
2456 if (obj == NULL || !PyString_Check(obj))
2457 {
2458 PyErr_BadArgument();
2459 return NULL;
2460 }
2461
Bram Moolenaar19e60942011-06-19 00:27:51 +02002462 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
2463 str = PyString_AsString(bytes);
2464 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002465
2466 /*
2467 * Error checking: String must not contain newlines, as we
2468 * are replacing a single line, and we must replace it with
2469 * a single line.
2470 * A trailing newline is removed, so that append(f.readlines()) works.
2471 */
2472 p = memchr(str, '\n', len);
2473 if (p != NULL)
2474 {
2475 if (p == str + len - 1)
2476 --len;
2477 else
2478 {
2479 PyErr_SetVim(_("string cannot contain newlines"));
2480 return NULL;
2481 }
2482 }
2483
2484 /* Create a copy of the string, with internal nulls replaced by
2485 * newline characters, as is the vim convention.
2486 */
2487 save = (char *)alloc((unsigned)(len+1));
2488 if (save == NULL)
2489 {
2490 PyErr_NoMemory();
2491 return NULL;
2492 }
2493
2494 for (i = 0; i < len; ++i)
2495 {
2496 if (str[i] == '\0')
2497 save[i] = '\n';
2498 else
2499 save[i] = str[i];
2500 }
2501
2502 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +02002503 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002504
2505 return save;
2506}
2507
2508/* Get a line from the specified buffer. The line number is
2509 * in Vim format (1-based). The line is returned as a Python
2510 * string object.
2511 */
2512 static PyObject *
2513GetBufferLine(buf_T *buf, PyInt n)
2514{
2515 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
2516}
2517
2518
2519/* Get a list of lines from the specified buffer. The line numbers
2520 * are in Vim format (1-based). The range is from lo up to, but not
2521 * including, hi. The list is returned as a Python list of string objects.
2522 */
2523 static PyObject *
2524GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
2525{
2526 PyInt i;
2527 PyInt n = hi - lo;
2528 PyObject *list = PyList_New(n);
2529
2530 if (list == NULL)
2531 return NULL;
2532
2533 for (i = 0; i < n; ++i)
2534 {
2535 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
2536
2537 /* Error check - was the Python string creation OK? */
2538 if (str == NULL)
2539 {
2540 Py_DECREF(list);
2541 return NULL;
2542 }
2543
2544 /* Set the list item */
2545 if (PyList_SetItem(list, i, str))
2546 {
2547 Py_DECREF(str);
2548 Py_DECREF(list);
2549 return NULL;
2550 }
2551 }
2552
2553 /* The ownership of the Python list is passed to the caller (ie,
2554 * the caller should Py_DECREF() the object when it is finished
2555 * with it).
2556 */
2557
2558 return list;
2559}
2560
2561/*
2562 * Check if deleting lines made the cursor position invalid.
2563 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
2564 * deleted).
2565 */
2566 static void
2567py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
2568{
2569 if (curwin->w_cursor.lnum >= lo)
2570 {
2571 /* Adjust the cursor position if it's in/after the changed
2572 * lines. */
2573 if (curwin->w_cursor.lnum >= hi)
2574 {
2575 curwin->w_cursor.lnum += extra;
2576 check_cursor_col();
2577 }
2578 else if (extra < 0)
2579 {
2580 curwin->w_cursor.lnum = lo;
2581 check_cursor();
2582 }
2583 else
2584 check_cursor_col();
2585 changed_cline_bef_curs();
2586 }
2587 invalidate_botline();
2588}
2589
Bram Moolenaar19e60942011-06-19 00:27:51 +02002590/*
2591 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002592 * in Vim format (1-based). The replacement line is given as
2593 * a Python string object. The object is checked for validity
2594 * and correct format. Errors are returned as a value of FAIL.
2595 * The return value is OK on success.
2596 * If OK is returned and len_change is not NULL, *len_change
2597 * is set to the change in the buffer length.
2598 */
2599 static int
2600SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
2601{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002602 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002603 * There are three cases:
2604 * 1. NULL, or None - this is a deletion.
2605 * 2. A string - this is a replacement.
2606 * 3. Anything else - this is an error.
2607 */
2608 if (line == Py_None || line == NULL)
2609 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02002610 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002611
2612 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002613 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002614
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002615 VimTryStart();
2616
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002617 if (u_savedel((linenr_T)n, 1L) == FAIL)
2618 PyErr_SetVim(_("cannot save undo information"));
2619 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
2620 PyErr_SetVim(_("cannot delete line"));
2621 else
2622 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02002623 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002624 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
2625 deleted_lines_mark((linenr_T)n, 1L);
2626 }
2627
Bram Moolenaar105bc352013-05-17 16:03:57 +02002628 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002629
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002630 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002631 return FAIL;
2632
2633 if (len_change)
2634 *len_change = -1;
2635
2636 return OK;
2637 }
2638 else if (PyString_Check(line))
2639 {
2640 char *save = StringToLine(line);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002641 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002642
2643 if (save == NULL)
2644 return FAIL;
2645
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002646 VimTryStart();
2647
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002648 /* We do not need to free "save" if ml_replace() consumes it. */
2649 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002650 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002651
2652 if (u_savesub((linenr_T)n) == FAIL)
2653 {
2654 PyErr_SetVim(_("cannot save undo information"));
2655 vim_free(save);
2656 }
2657 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
2658 {
2659 PyErr_SetVim(_("cannot replace line"));
2660 vim_free(save);
2661 }
2662 else
2663 changed_bytes((linenr_T)n, 0);
2664
Bram Moolenaar105bc352013-05-17 16:03:57 +02002665 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002666
2667 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02002668 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002669 check_cursor_col();
2670
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002671 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002672 return FAIL;
2673
2674 if (len_change)
2675 *len_change = 0;
2676
2677 return OK;
2678 }
2679 else
2680 {
2681 PyErr_BadArgument();
2682 return FAIL;
2683 }
2684}
2685
Bram Moolenaar19e60942011-06-19 00:27:51 +02002686/* Replace a range of lines in the specified buffer. The line numbers are in
2687 * Vim format (1-based). The range is from lo up to, but not including, hi.
2688 * The replacement lines are given as a Python list of string objects. The
2689 * list is checked for validity and correct format. Errors are returned as a
2690 * value of FAIL. The return value is OK on success.
2691 * If OK is returned and len_change is not NULL, *len_change
2692 * is set to the change in the buffer length.
2693 */
2694 static int
2695SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
2696{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002697 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02002698 * There are three cases:
2699 * 1. NULL, or None - this is a deletion.
2700 * 2. A list - this is a replacement.
2701 * 3. Anything else - this is an error.
2702 */
2703 if (list == Py_None || list == NULL)
2704 {
2705 PyInt i;
2706 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002707 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02002708
2709 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002710 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002711 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002712
2713 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
2714 PyErr_SetVim(_("cannot save undo information"));
2715 else
2716 {
2717 for (i = 0; i < n; ++i)
2718 {
2719 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
2720 {
2721 PyErr_SetVim(_("cannot delete line"));
2722 break;
2723 }
2724 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02002725 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02002726 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
2727 deleted_lines_mark((linenr_T)lo, (long)i);
2728 }
2729
Bram Moolenaar105bc352013-05-17 16:03:57 +02002730 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002731
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002732 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02002733 return FAIL;
2734
2735 if (len_change)
2736 *len_change = -n;
2737
2738 return OK;
2739 }
2740 else if (PyList_Check(list))
2741 {
2742 PyInt i;
2743 PyInt new_len = PyList_Size(list);
2744 PyInt old_len = hi - lo;
2745 PyInt extra = 0; /* lines added to text, can be negative */
2746 char **array;
2747 buf_T *savebuf;
2748
2749 if (new_len == 0) /* avoid allocating zero bytes */
2750 array = NULL;
2751 else
2752 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002753 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002754 if (array == NULL)
2755 {
2756 PyErr_NoMemory();
2757 return FAIL;
2758 }
2759 }
2760
2761 for (i = 0; i < new_len; ++i)
2762 {
2763 PyObject *line = PyList_GetItem(list, i);
2764
2765 array[i] = StringToLine(line);
2766 if (array[i] == NULL)
2767 {
2768 while (i)
2769 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002770 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002771 return FAIL;
2772 }
2773 }
2774
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002775 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02002776 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002777
2778 // START of region without "return". Must call restore_buffer()!
2779 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002780
2781 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
2782 PyErr_SetVim(_("cannot save undo information"));
2783
2784 /* If the size of the range is reducing (ie, new_len < old_len) we
2785 * need to delete some old_len. We do this at the start, by
2786 * repeatedly deleting line "lo".
2787 */
2788 if (!PyErr_Occurred())
2789 {
2790 for (i = 0; i < old_len - new_len; ++i)
2791 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
2792 {
2793 PyErr_SetVim(_("cannot delete line"));
2794 break;
2795 }
2796 extra -= i;
2797 }
2798
2799 /* For as long as possible, replace the existing old_len with the
2800 * new old_len. This is a more efficient operation, as it requires
2801 * less memory allocation and freeing.
2802 */
2803 if (!PyErr_Occurred())
2804 {
2805 for (i = 0; i < old_len && i < new_len; ++i)
2806 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
2807 == FAIL)
2808 {
2809 PyErr_SetVim(_("cannot replace line"));
2810 break;
2811 }
2812 }
2813 else
2814 i = 0;
2815
2816 /* Now we may need to insert the remaining new old_len. If we do, we
2817 * must free the strings as we finish with them (we can't pass the
2818 * responsibility to vim in this case).
2819 */
2820 if (!PyErr_Occurred())
2821 {
2822 while (i < new_len)
2823 {
2824 if (ml_append((linenr_T)(lo + i - 1),
2825 (char_u *)array[i], 0, FALSE) == FAIL)
2826 {
2827 PyErr_SetVim(_("cannot insert line"));
2828 break;
2829 }
2830 vim_free(array[i]);
2831 ++i;
2832 ++extra;
2833 }
2834 }
2835
2836 /* Free any left-over old_len, as a result of an error */
2837 while (i < new_len)
2838 {
2839 vim_free(array[i]);
2840 ++i;
2841 }
2842
2843 /* Free the array of old_len. All of its contents have now
2844 * been dealt with (either freed, or the responsibility passed
2845 * to vim.
2846 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002847 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002848
2849 /* Adjust marks. Invalidate any which lie in the
2850 * changed range, and move any in the remainder of the buffer.
2851 */
2852 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
2853 (long)MAXLNUM, (long)extra);
2854 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
2855
Bram Moolenaar105bc352013-05-17 16:03:57 +02002856 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02002857 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
2858
Bram Moolenaar105bc352013-05-17 16:03:57 +02002859 // END of region without "return".
2860 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02002861
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002862 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02002863 return FAIL;
2864
2865 if (len_change)
2866 *len_change = new_len - old_len;
2867
2868 return OK;
2869 }
2870 else
2871 {
2872 PyErr_BadArgument();
2873 return FAIL;
2874 }
2875}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002876
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002877/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002878 * The line number is in Vim format (1-based). The lines to be inserted are
2879 * given as a Python list of string objects or as a single string. The lines
2880 * to be added are checked for validity and correct format. Errors are
2881 * returned as a value of FAIL. The return value is OK on success.
2882 * If OK is returned and len_change is not NULL, *len_change
2883 * is set to the change in the buffer length.
2884 */
2885 static int
2886InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
2887{
2888 /* First of all, we check the type of the supplied Python object.
2889 * It must be a string or a list, or the call is in error.
2890 */
2891 if (PyString_Check(lines))
2892 {
2893 char *str = StringToLine(lines);
2894 buf_T *savebuf;
2895
2896 if (str == NULL)
2897 return FAIL;
2898
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002899 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002900 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002901 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002902
2903 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
2904 PyErr_SetVim(_("cannot save undo information"));
2905 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
2906 PyErr_SetVim(_("cannot insert line"));
2907 else
2908 appended_lines_mark((linenr_T)n, 1L);
2909
2910 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002911 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002912 update_screen(VALID);
2913
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002914 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002915 return FAIL;
2916
2917 if (len_change)
2918 *len_change = 1;
2919
2920 return OK;
2921 }
2922 else if (PyList_Check(lines))
2923 {
2924 PyInt i;
2925 PyInt size = PyList_Size(lines);
2926 char **array;
2927 buf_T *savebuf;
2928
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002929 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002930 if (array == NULL)
2931 {
2932 PyErr_NoMemory();
2933 return FAIL;
2934 }
2935
2936 for (i = 0; i < size; ++i)
2937 {
2938 PyObject *line = PyList_GetItem(lines, i);
2939 array[i] = StringToLine(line);
2940
2941 if (array[i] == NULL)
2942 {
2943 while (i)
2944 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002945 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002946 return FAIL;
2947 }
2948 }
2949
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002950 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002951 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02002952 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002953
2954 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
2955 PyErr_SetVim(_("cannot save undo information"));
2956 else
2957 {
2958 for (i = 0; i < size; ++i)
2959 {
2960 if (ml_append((linenr_T)(n + i),
2961 (char_u *)array[i], 0, FALSE) == FAIL)
2962 {
2963 PyErr_SetVim(_("cannot insert line"));
2964
2965 /* Free the rest of the lines */
2966 while (i < size)
2967 vim_free(array[i++]);
2968
2969 break;
2970 }
2971 vim_free(array[i]);
2972 }
2973 if (i > 0)
2974 appended_lines_mark((linenr_T)n, (long)i);
2975 }
2976
2977 /* Free the array of lines. All of its contents have now
2978 * been freed.
2979 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002980 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002981
Bram Moolenaar105bc352013-05-17 16:03:57 +02002982 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002983 update_screen(VALID);
2984
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002985 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02002986 return FAIL;
2987
2988 if (len_change)
2989 *len_change = size;
2990
2991 return OK;
2992 }
2993 else
2994 {
2995 PyErr_BadArgument();
2996 return FAIL;
2997 }
2998}
2999
3000/*
3001 * Common routines for buffers and line ranges
3002 * -------------------------------------------
3003 */
3004
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003005typedef struct
3006{
3007 PyObject_HEAD
3008 buf_T *buf;
3009} BufferObject;
3010
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003011 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003012CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003013{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003014 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003015 {
3016 PyErr_SetVim(_("attempt to refer to deleted buffer"));
3017 return -1;
3018 }
3019
3020 return 0;
3021}
3022
3023 static PyObject *
3024RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3025{
3026 if (CheckBuffer(self))
3027 return NULL;
3028
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003029 if (end == -1)
3030 end = self->buf->b_ml.ml_line_count;
3031
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003032 if (n < 0)
3033 n += end - start + 1;
3034
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003035 if (n < 0 || n > end - start)
3036 {
3037 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3038 return NULL;
3039 }
3040
3041 return GetBufferLine(self->buf, n+start);
3042}
3043
3044 static PyObject *
3045RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3046{
3047 PyInt size;
3048
3049 if (CheckBuffer(self))
3050 return NULL;
3051
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003052 if (end == -1)
3053 end = self->buf->b_ml.ml_line_count;
3054
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003055 size = end - start + 1;
3056
3057 if (lo < 0)
3058 lo = 0;
3059 else if (lo > size)
3060 lo = size;
3061 if (hi < 0)
3062 hi = 0;
3063 if (hi < lo)
3064 hi = lo;
3065 else if (hi > size)
3066 hi = size;
3067
3068 return GetBufferLineList(self->buf, lo+start, hi+start);
3069}
3070
3071 static PyInt
3072RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3073{
3074 PyInt len_change;
3075
3076 if (CheckBuffer(self))
3077 return -1;
3078
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003079 if (end == -1)
3080 end = self->buf->b_ml.ml_line_count;
3081
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003082 if (n < 0)
3083 n += end - start + 1;
3084
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003085 if (n < 0 || n > end - start)
3086 {
3087 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
3088 return -1;
3089 }
3090
3091 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
3092 return -1;
3093
3094 if (new_end)
3095 *new_end = end + len_change;
3096
3097 return 0;
3098}
3099
Bram Moolenaar19e60942011-06-19 00:27:51 +02003100 static PyInt
3101RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
3102{
3103 PyInt size;
3104 PyInt len_change;
3105
3106 /* Self must be a valid buffer */
3107 if (CheckBuffer(self))
3108 return -1;
3109
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003110 if (end == -1)
3111 end = self->buf->b_ml.ml_line_count;
3112
Bram Moolenaar19e60942011-06-19 00:27:51 +02003113 /* Sort out the slice range */
3114 size = end - start + 1;
3115
3116 if (lo < 0)
3117 lo = 0;
3118 else if (lo > size)
3119 lo = size;
3120 if (hi < 0)
3121 hi = 0;
3122 if (hi < lo)
3123 hi = lo;
3124 else if (hi > size)
3125 hi = size;
3126
3127 if (SetBufferLineList(self->buf, lo + start, hi + start,
3128 val, &len_change) == FAIL)
3129 return -1;
3130
3131 if (new_end)
3132 *new_end = end + len_change;
3133
3134 return 0;
3135}
3136
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003137
3138 static PyObject *
3139RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
3140{
3141 PyObject *lines;
3142 PyInt len_change;
3143 PyInt max;
3144 PyInt n;
3145
3146 if (CheckBuffer(self))
3147 return NULL;
3148
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003149 if (end == -1)
3150 end = self->buf->b_ml.ml_line_count;
3151
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003152 max = n = end - start + 1;
3153
3154 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
3155 return NULL;
3156
3157 if (n < 0 || n > max)
3158 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003159 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003160 return NULL;
3161 }
3162
3163 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
3164 return NULL;
3165
3166 if (new_end)
3167 *new_end = end + len_change;
3168
3169 Py_INCREF(Py_None);
3170 return Py_None;
3171}
3172
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003173/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003174 */
3175
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003176static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003177static PySequenceMethods RangeAsSeq;
3178static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003179
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003180typedef struct
3181{
3182 PyObject_HEAD
3183 BufferObject *buf;
3184 PyInt start;
3185 PyInt end;
3186} RangeObject;
3187
3188 static PyObject *
3189RangeNew(buf_T *buf, PyInt start, PyInt end)
3190{
3191 BufferObject *bufr;
3192 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003193 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003194 if (self == NULL)
3195 return NULL;
3196
3197 bufr = (BufferObject *)BufferNew(buf);
3198 if (bufr == NULL)
3199 {
3200 Py_DECREF(self);
3201 return NULL;
3202 }
3203 Py_INCREF(bufr);
3204
3205 self->buf = bufr;
3206 self->start = start;
3207 self->end = end;
3208
3209 return (PyObject *)(self);
3210}
3211
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003212 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003213RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003214{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003215 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003216 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02003217 PyObject_GC_Del((void *)(self));
3218}
3219
3220 static int
3221RangeTraverse(RangeObject *self, visitproc visit, void *arg)
3222{
3223 Py_VISIT(((PyObject *)(self->buf)));
3224 return 0;
3225}
3226
3227 static int
3228RangeClear(RangeObject *self)
3229{
3230 Py_CLEAR(self->buf);
3231 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003232}
3233
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003234 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003235RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003236{
3237 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003238 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003239 return -1; /* ??? */
3240
Bram Moolenaard6e39182013-05-21 18:30:34 +02003241 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003242}
3243
3244 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003245RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003246{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003247 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003248}
3249
3250 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003251RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003252{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003253 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003254}
3255
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003256static char *RangeAttrs[] = {
3257 "start", "end",
3258 NULL
3259};
3260
3261 static PyObject *
3262RangeDir(PyObject *self)
3263{
3264 return ObjectDir(self, RangeAttrs);
3265}
3266
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003267 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003268RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003269{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003270 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003271}
3272
3273 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003274RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003275{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003276 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003277 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
3278 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003279 else
3280 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003281 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003282
3283 if (name == NULL)
3284 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003285
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003286 return PyString_FromFormat("<range %s (%d:%d)>",
3287 name, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003288 }
3289}
3290
3291static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02003292 /* name, function, calling, documentation */
3293 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003294 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
3295 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003296};
3297
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003298static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003299static PySequenceMethods BufferAsSeq;
3300static PyMappingMethods BufferAsMapping;
3301
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003302 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02003303BufferNew(buf_T *buf)
3304{
3305 /* We need to handle deletion of buffers underneath us.
3306 * If we add a "b_python*_ref" field to the buf_T structure,
3307 * then we can get at it in buf_freeall() in vim. We then
3308 * need to create only ONE Python object per buffer - if
3309 * we try to create a second, just INCREF the existing one
3310 * and return it. The (single) Python object referring to
3311 * the buffer is stored in "b_python*_ref".
3312 * Question: what to do on a buf_freeall(). We'll probably
3313 * have to either delete the Python object (DECREF it to
3314 * zero - a bad idea, as it leaves dangling refs!) or
3315 * set the buf_T * value to an invalid value (-1?), which
3316 * means we need checks in all access functions... Bah.
3317 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003318 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003319 * b_python_ref and b_python3_ref fields respectively.
3320 */
3321
3322 BufferObject *self;
3323
3324 if (BUF_PYTHON_REF(buf) != NULL)
3325 {
3326 self = BUF_PYTHON_REF(buf);
3327 Py_INCREF(self);
3328 }
3329 else
3330 {
3331 self = PyObject_NEW(BufferObject, &BufferType);
3332 if (self == NULL)
3333 return NULL;
3334 self->buf = buf;
3335 BUF_PYTHON_REF(buf) = self;
3336 }
3337
3338 return (PyObject *)(self);
3339}
3340
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003341 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003342BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003343{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003344 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
3345 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003346
3347 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003348}
3349
Bram Moolenaar971db462013-05-12 18:44:48 +02003350 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003351BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02003352{
3353 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003354 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02003355 return -1; /* ??? */
3356
Bram Moolenaard6e39182013-05-21 18:30:34 +02003357 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02003358}
3359
3360 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003361BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02003362{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003363 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003364}
3365
3366 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003367BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02003368{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003369 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02003370}
3371
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003372static char *BufferAttrs[] = {
3373 "name", "number", "vars", "options", "valid",
3374 NULL
3375};
3376
3377 static PyObject *
3378BufferDir(PyObject *self)
3379{
3380 return ObjectDir(self, BufferAttrs);
3381}
3382
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003383 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003384BufferAttrValid(BufferObject *self, char *name)
3385{
3386 PyObject *r;
3387
3388 if (strcmp(name, "valid") != 0)
3389 return NULL;
3390
3391 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
3392 Py_INCREF(r);
3393 return r;
3394}
3395
3396 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003397BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003398{
3399 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02003400 return PyString_FromString((self->buf->b_ffname == NULL
3401 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003402 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003403 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003404 else if (strcmp(name, "vars") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003405 return DictionaryNew(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003406 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003407 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
3408 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003409 else if (strcmp(name, "__members__") == 0)
3410 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003411 else
3412 return NULL;
3413}
3414
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003415 static int
3416BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
3417{
3418 if (CheckBuffer(self))
3419 return -1;
3420
3421 if (strcmp(name, "name") == 0)
3422 {
3423 char_u *val;
3424 aco_save_T aco;
3425 int r;
3426 PyObject *todecref;
3427
3428 if (!(val = StringToChars(valObject, &todecref)))
3429 return -1;
3430
3431 VimTryStart();
3432 /* Using aucmd_*: autocommands will be executed by rename_buffer */
3433 aucmd_prepbuf(&aco, self->buf);
3434 r = rename_buffer(val);
3435 aucmd_restbuf(&aco);
3436 Py_XDECREF(todecref);
3437 if (VimTryEnd())
3438 return -1;
3439
3440 if (r == FAIL)
3441 {
3442 PyErr_SetVim(_("failed to rename buffer"));
3443 return -1;
3444 }
3445 return 0;
3446 }
3447 else
3448 {
3449 PyErr_SetString(PyExc_AttributeError, name);
3450 return -1;
3451 }
3452}
3453
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003454 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003455BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003456{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003457 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003458}
3459
3460 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003461BufferMark(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003462{
3463 pos_T *posp;
3464 char *pmark;
3465 char mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02003466 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003467
Bram Moolenaard6e39182013-05-21 18:30:34 +02003468 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003469 return NULL;
3470
3471 if (!PyArg_ParseTuple(args, "s", &pmark))
3472 return NULL;
3473 mark = *pmark;
3474
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003475 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02003476 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003477 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003478 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003479 if (VimTryEnd())
3480 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003481
3482 if (posp == NULL)
3483 {
3484 PyErr_SetVim(_("invalid mark name"));
3485 return NULL;
3486 }
3487
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003488 if (posp->lnum <= 0)
3489 {
3490 /* Or raise an error? */
3491 Py_INCREF(Py_None);
3492 return Py_None;
3493 }
3494
3495 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
3496}
3497
3498 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003499BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003500{
3501 PyInt start;
3502 PyInt end;
3503
Bram Moolenaard6e39182013-05-21 18:30:34 +02003504 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003505 return NULL;
3506
3507 if (!PyArg_ParseTuple(args, "nn", &start, &end))
3508 return NULL;
3509
Bram Moolenaard6e39182013-05-21 18:30:34 +02003510 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003511}
3512
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003513 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003514BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003515{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003516 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003517 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003518 else
3519 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003520 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003521
3522 if (name == NULL)
3523 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003524
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003525 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003526 }
3527}
3528
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003529static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02003530 /* name, function, calling, documentation */
3531 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
3532 {"mark", (PyCFunction)BufferMark, METH_VARARGS, "Return (row,col) representing position of named mark" },
3533 {"range", (PyCFunction)BufferRange, METH_VARARGS, "Return a range object which represents the part of the given buffer between line numbers s and e" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003534 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
3535 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003536};
3537
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003538/*
3539 * Buffer list object - Implementation
3540 */
3541
3542static PyTypeObject BufMapType;
3543
3544typedef struct
3545{
3546 PyObject_HEAD
3547} BufMapObject;
3548
3549 static PyInt
3550BufMapLength(PyObject *self UNUSED)
3551{
3552 buf_T *b = firstbuf;
3553 PyInt n = 0;
3554
3555 while (b)
3556 {
3557 ++n;
3558 b = b->b_next;
3559 }
3560
3561 return n;
3562}
3563
3564 static PyObject *
3565BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
3566{
3567 buf_T *b;
3568 int bnr;
3569
3570#if PY_MAJOR_VERSION < 3
3571 if (PyInt_Check(keyObject))
3572 bnr = PyInt_AsLong(keyObject);
3573 else
3574#endif
3575 if (PyLong_Check(keyObject))
3576 bnr = PyLong_AsLong(keyObject);
3577 else
3578 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02003579 PyErr_SetString(PyExc_TypeError, _("key must be integer"));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003580 return NULL;
3581 }
3582
3583 b = buflist_findnr(bnr);
3584
3585 if (b)
3586 return BufferNew(b);
3587 else
3588 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02003589 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003590 return NULL;
3591 }
3592}
3593
3594 static void
3595BufMapIterDestruct(PyObject *buffer)
3596{
3597 /* Iteration was stopped before all buffers were processed */
3598 if (buffer)
3599 {
3600 Py_DECREF(buffer);
3601 }
3602}
3603
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003604 static int
3605BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
3606{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003607 if (buffer)
3608 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003609 return 0;
3610}
3611
3612 static int
3613BufMapIterClear(PyObject **buffer)
3614{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003615 if (*buffer)
3616 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003617 return 0;
3618}
3619
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003620 static PyObject *
3621BufMapIterNext(PyObject **buffer)
3622{
3623 PyObject *next;
3624 PyObject *r;
3625
3626 if (!*buffer)
3627 return NULL;
3628
3629 r = *buffer;
3630
3631 if (CheckBuffer((BufferObject *)(r)))
3632 {
3633 *buffer = NULL;
3634 return NULL;
3635 }
3636
3637 if (!((BufferObject *)(r))->buf->b_next)
3638 next = NULL;
3639 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
3640 return NULL;
3641 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02003642 /* Do not increment reference: we no longer hold it (decref), but whoever
3643 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003644 return r;
3645}
3646
3647 static PyObject *
3648BufMapIter(PyObject *self UNUSED)
3649{
3650 PyObject *buffer;
3651
3652 buffer = BufferNew(firstbuf);
3653 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003654 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
3655 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02003656}
3657
3658static PyMappingMethods BufMapAsMapping = {
3659 (lenfunc) BufMapLength,
3660 (binaryfunc) BufMapItem,
3661 (objobjargproc) 0,
3662};
3663
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003664/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003665 */
3666
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003667static char *CurrentAttrs[] = {
3668 "buffer", "window", "line", "range", "tabpage",
3669 NULL
3670};
3671
3672 static PyObject *
3673CurrentDir(PyObject *self)
3674{
3675 return ObjectDir(self, CurrentAttrs);
3676}
3677
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003678 static PyObject *
3679CurrentGetattr(PyObject *self UNUSED, char *name)
3680{
3681 if (strcmp(name, "buffer") == 0)
3682 return (PyObject *)BufferNew(curbuf);
3683 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003684 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003685 else if (strcmp(name, "tabpage") == 0)
3686 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003687 else if (strcmp(name, "line") == 0)
3688 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
3689 else if (strcmp(name, "range") == 0)
3690 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003691 else if (strcmp(name, "__members__") == 0)
3692 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003693 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003694#if PY_MAJOR_VERSION < 3
3695 return Py_FindMethod(WindowMethods, self, name);
3696#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003697 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003698#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003699}
3700
3701 static int
3702CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
3703{
3704 if (strcmp(name, "line") == 0)
3705 {
3706 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
3707 return -1;
3708
3709 return 0;
3710 }
Bram Moolenaare7614592013-05-15 15:51:08 +02003711 else if (strcmp(name, "buffer") == 0)
3712 {
3713 int count;
3714
3715 if (value->ob_type != &BufferType)
3716 {
3717 PyErr_SetString(PyExc_TypeError, _("expected vim.buffer object"));
3718 return -1;
3719 }
3720
3721 if (CheckBuffer((BufferObject *)(value)))
3722 return -1;
3723 count = ((BufferObject *)(value))->buf->b_fnum;
3724
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003725 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02003726 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
3727 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003728 if (VimTryEnd())
3729 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02003730 PyErr_SetVim(_("failed to switch to given buffer"));
3731 return -1;
3732 }
3733
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003734 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02003735 }
3736 else if (strcmp(name, "window") == 0)
3737 {
3738 int count;
3739
3740 if (value->ob_type != &WindowType)
3741 {
3742 PyErr_SetString(PyExc_TypeError, _("expected vim.window object"));
3743 return -1;
3744 }
3745
3746 if (CheckWindow((WindowObject *)(value)))
3747 return -1;
3748 count = get_win_number(((WindowObject *)(value))->win, firstwin);
3749
3750 if (!count)
3751 {
3752 PyErr_SetString(PyExc_ValueError,
3753 _("failed to find window in the current tab page"));
3754 return -1;
3755 }
3756
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003757 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02003758 win_goto(((WindowObject *)(value))->win);
3759 if (((WindowObject *)(value))->win != curwin)
3760 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003761 if (VimTryEnd())
3762 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02003763 PyErr_SetString(PyExc_RuntimeError,
3764 _("did not switch to the specified window"));
3765 return -1;
3766 }
3767
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003768 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02003769 }
3770 else if (strcmp(name, "tabpage") == 0)
3771 {
3772 if (value->ob_type != &TabPageType)
3773 {
3774 PyErr_SetString(PyExc_TypeError, _("expected vim.tabpage object"));
3775 return -1;
3776 }
3777
3778 if (CheckTabPage((TabPageObject *)(value)))
3779 return -1;
3780
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003781 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02003782 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
3783 if (((TabPageObject *)(value))->tab != curtab)
3784 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003785 if (VimTryEnd())
3786 return -1;
Bram Moolenaare7614592013-05-15 15:51:08 +02003787 PyErr_SetString(PyExc_RuntimeError,
3788 _("did not switch to the specified tab page"));
3789 return -1;
3790 }
3791
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003792 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02003793 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003794 else
3795 {
3796 PyErr_SetString(PyExc_AttributeError, name);
3797 return -1;
3798 }
3799}
3800
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003801static struct PyMethodDef CurrentMethods[] = {
3802 /* name, function, calling, documentation */
3803 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
3804 { NULL, NULL, 0, NULL}
3805};
3806
Bram Moolenaardb913952012-06-29 12:54:53 +02003807 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003808init_range_cmd(exarg_T *eap)
3809{
3810 RangeStart = eap->line1;
3811 RangeEnd = eap->line2;
3812}
3813
3814 static void
3815init_range_eval(typval_T *rettv UNUSED)
3816{
3817 RangeStart = (PyInt) curwin->w_cursor.lnum;
3818 RangeEnd = RangeStart;
3819}
3820
3821 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003822run_cmd(const char *cmd, void *arg UNUSED
3823#ifdef PY_CAN_RECURSE
3824 , PyGILState_STATE *pygilstate UNUSED
3825#endif
3826 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003827{
3828 PyRun_SimpleString((char *) cmd);
3829}
3830
3831static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
3832static int code_hdr_len = 30;
3833
3834 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003835run_do(const char *cmd, void *arg UNUSED
3836#ifdef PY_CAN_RECURSE
3837 , PyGILState_STATE *pygilstate
3838#endif
3839 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003840{
3841 PyInt lnum;
3842 size_t len;
3843 char *code;
3844 int status;
3845 PyObject *pyfunc, *pymain;
3846
Bram Moolenaar4ac66762013-05-28 22:31:46 +02003847 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003848 {
3849 EMSG(_("cannot save undo information"));
3850 return;
3851 }
3852
3853 len = code_hdr_len + STRLEN(cmd);
3854 code = PyMem_New(char, len + 1);
3855 memcpy(code, code_hdr, code_hdr_len);
3856 STRCPY(code + code_hdr_len, cmd);
3857 status = PyRun_SimpleString(code);
3858 PyMem_Free(code);
3859
3860 if (status)
3861 {
3862 EMSG(_("failed to run the code"));
3863 return;
3864 }
3865
3866 status = 0;
3867 pymain = PyImport_AddModule("__main__");
3868 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003869#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003870 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003871#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003872
3873 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
3874 {
3875 PyObject *line, *linenr, *ret;
3876
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003877#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003878 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003879#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003880 if (!(line = GetBufferLine(curbuf, lnum)))
3881 goto err;
3882 if (!(linenr = PyInt_FromLong((long) lnum)))
3883 {
3884 Py_DECREF(line);
3885 goto err;
3886 }
3887 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
3888 Py_DECREF(line);
3889 Py_DECREF(linenr);
3890 if (!ret)
3891 goto err;
3892
3893 if (ret != Py_None)
3894 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
3895 goto err;
3896
3897 Py_XDECREF(ret);
3898 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003899#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003900 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003901#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003902 }
3903 goto out;
3904err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003905#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003906 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003907#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003908 PyErr_PrintEx(0);
3909 PythonIO_Flush();
3910 status = 1;
3911out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003912#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003913 if (!status)
3914 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003915#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003916 Py_DECREF(pyfunc);
3917 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
3918 if (status)
3919 return;
3920 check_cursor();
3921 update_curbuf(NOT_VALID);
3922}
3923
3924 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02003925run_eval(const char *cmd, typval_T *rettv
3926#ifdef PY_CAN_RECURSE
3927 , PyGILState_STATE *pygilstate UNUSED
3928#endif
3929 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02003930{
3931 PyObject *r;
3932
3933 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
3934 if (r == NULL)
3935 {
3936 if (PyErr_Occurred() && !msg_silent)
3937 PyErr_PrintEx(0);
3938 EMSG(_("E858: Eval did not return a valid python object"));
3939 }
3940 else
3941 {
3942 if (ConvertFromPyObject(r, rettv) == -1)
3943 EMSG(_("E859: Failed to convert returned python object to vim value"));
3944 Py_DECREF(r);
3945 }
3946 PyErr_Clear();
3947}
3948
3949 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02003950set_ref_in_py(const int copyID)
3951{
3952 pylinkedlist_T *cur;
3953 dict_T *dd;
3954 list_T *ll;
3955
3956 if (lastdict != NULL)
3957 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
3958 {
3959 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
3960 if (dd->dv_copyID != copyID)
3961 {
3962 dd->dv_copyID = copyID;
3963 set_ref_in_ht(&dd->dv_hashtab, copyID);
3964 }
3965 }
3966
3967 if (lastlist != NULL)
3968 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
3969 {
3970 ll = ((ListObject *) (cur->pll_obj))->list;
3971 if (ll->lv_copyID != copyID)
3972 {
3973 ll->lv_copyID = copyID;
3974 set_ref_in_list(ll, copyID);
3975 }
3976 }
3977}
3978
3979 static int
3980set_string_copy(char_u *str, typval_T *tv)
3981{
3982 tv->vval.v_string = vim_strsave(str);
3983 if (tv->vval.v_string == NULL)
3984 {
3985 PyErr_NoMemory();
3986 return -1;
3987 }
3988 return 0;
3989}
3990
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003991 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02003992pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003993{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02003994 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003995 char_u *key;
3996 dictitem_T *di;
3997 PyObject *keyObject;
3998 PyObject *valObject;
3999 Py_ssize_t iter = 0;
4000
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004001 if (!(dict = dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004002 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004003
4004 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004005 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004006
4007 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4008 {
4009 DICTKEY_DECL
4010
Bram Moolenaara03e6312013-05-29 22:49:26 +02004011 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004012 {
4013 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004014 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004015 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004016
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004017 if (!DICTKEY_SET_KEY)
4018 {
4019 dict_unref(dict);
4020 return -1;
4021 }
4022 DICTKEY_CHECK_EMPTY(-1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004023
4024 di = dictitem_alloc(key);
4025
4026 DICTKEY_UNREF
4027
4028 if (di == NULL)
4029 {
4030 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004031 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004032 return -1;
4033 }
4034 di->di_tv.v_lock = 0;
4035
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004036 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004037 {
4038 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004039 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004040 return -1;
4041 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004042
4043 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004044 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02004045 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004046 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004047 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004048 PyErr_SetVim(_("failed to add key to dictionary"));
4049 return -1;
4050 }
4051 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004052
4053 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004054 return 0;
4055}
4056
4057 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004058pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004059{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004060 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004061 char_u *key;
4062 dictitem_T *di;
4063 PyObject *list;
4064 PyObject *litem;
4065 PyObject *keyObject;
4066 PyObject *valObject;
4067 Py_ssize_t lsize;
4068
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004069 if (!(dict = dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004070 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004071
4072 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004073 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004074
4075 list = PyMapping_Items(obj);
4076 if (list == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004077 {
4078 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004079 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004080 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004081 lsize = PyList_Size(list);
4082 while (lsize--)
4083 {
4084 DICTKEY_DECL
4085
4086 litem = PyList_GetItem(list, lsize);
4087 if (litem == NULL)
4088 {
4089 Py_DECREF(list);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004090 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004091 return -1;
4092 }
4093
Bram Moolenaara03e6312013-05-29 22:49:26 +02004094 if (!(keyObject = PyTuple_GetItem(litem, 0)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004095 {
4096 Py_DECREF(list);
4097 Py_DECREF(litem);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004098 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004099 return -1;
4100 }
4101
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004102 if (!DICTKEY_SET_KEY)
4103 {
4104 dict_unref(dict);
4105 Py_DECREF(list);
4106 Py_DECREF(litem);
4107 DICTKEY_UNREF
4108 return -1;
4109 }
4110 DICTKEY_CHECK_EMPTY(-1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004111
Bram Moolenaara03e6312013-05-29 22:49:26 +02004112 if (!(valObject = PyTuple_GetItem(litem, 1)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004113 {
4114 Py_DECREF(list);
4115 Py_DECREF(litem);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004116 dict_unref(dict);
Bram Moolenaara03e6312013-05-29 22:49:26 +02004117 DICTKEY_UNREF
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004118 return -1;
4119 }
4120
Bram Moolenaara03e6312013-05-29 22:49:26 +02004121 Py_DECREF(litem);
4122
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004123 di = dictitem_alloc(key);
4124
4125 DICTKEY_UNREF
4126
4127 if (di == NULL)
4128 {
4129 Py_DECREF(list);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004130 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004131 PyErr_NoMemory();
4132 return -1;
4133 }
4134 di->di_tv.v_lock = 0;
4135
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004136 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004137 {
4138 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004139 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004140 Py_DECREF(list);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004141 return -1;
4142 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02004143
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004144 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004145 {
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004146 dictitem_free(di);
4147 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004148 Py_DECREF(list);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004149 PyErr_SetVim(_("failed to add key to dictionary"));
4150 return -1;
4151 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004152 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004153 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004154 Py_DECREF(list);
4155 return 0;
4156}
4157
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004158 static list_T *
4159py_list_alloc()
4160{
4161 list_T *r;
4162
4163 if (!(r = list_alloc()))
4164 {
4165 PyErr_NoMemory();
4166 return NULL;
4167 }
4168 ++r->lv_refcount;
4169
4170 return r;
4171}
4172
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004173 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004174pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004175{
4176 list_T *l;
4177
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004178 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004179 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004180
4181 tv->v_type = VAR_LIST;
4182 tv->vval.v_list = l;
4183
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004184 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004185 {
4186 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004187 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004188 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004189
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004190 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004191 return 0;
4192}
4193
4194 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004195pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004196{
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004197 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004198 PyObject *item;
4199 list_T *l;
4200 listitem_T *li;
4201
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004202 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004203 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004204
4205 tv->vval.v_list = l;
4206 tv->v_type = VAR_LIST;
4207
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004208 if (!(iterator = PyObject_GetIter(obj)))
4209 {
4210 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004211 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004212 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004213
Bram Moolenaarc8366792013-05-29 22:46:26 +02004214 while ((item = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004215 {
4216 li = listitem_alloc();
4217 if (li == NULL)
4218 {
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004219 list_unref(l);
Bram Moolenaara03e6312013-05-29 22:49:26 +02004220 Py_DECREF(iterator);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004221 PyErr_NoMemory();
4222 return -1;
4223 }
4224 li->li_tv.v_lock = 0;
4225
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004226 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
Bram Moolenaara03e6312013-05-29 22:49:26 +02004227 {
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004228 list_unref(l);
4229 listitem_free(li);
Bram Moolenaara03e6312013-05-29 22:49:26 +02004230 Py_DECREF(item);
4231 Py_DECREF(iterator);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004232 return -1;
Bram Moolenaara03e6312013-05-29 22:49:26 +02004233 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004234
4235 list_append(l, li);
4236
4237 Py_DECREF(item);
4238 }
4239
4240 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004241
4242 /* Iterator may have finished due to an exception */
4243 if (PyErr_Occurred())
4244 {
4245 list_unref(l);
4246 return -1;
4247 }
4248
4249 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004250 return 0;
4251}
4252
Bram Moolenaardb913952012-06-29 12:54:53 +02004253typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
4254
4255 static int
4256convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004257 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004258{
4259 PyObject *capsule;
4260 char hexBuf[sizeof(void *) * 2 + 3];
4261
4262 sprintf(hexBuf, "%p", obj);
4263
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004264# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004265 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004266# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004267 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004268# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02004269 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02004270 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004271# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02004272 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02004273# else
4274 capsule = PyCObject_FromVoidPtr(tv, NULL);
4275# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02004276 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
4277 {
4278 Py_DECREF(capsule);
4279 tv->v_type = VAR_UNKNOWN;
4280 return -1;
4281 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004282 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02004283 {
4284 tv->v_type = VAR_UNKNOWN;
4285 return -1;
4286 }
4287 /* As we are not using copy_tv which increments reference count we must
4288 * do it ourself. */
4289 switch(tv->v_type)
4290 {
4291 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
4292 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
4293 }
4294 }
4295 else
4296 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004297 typval_T *v;
4298
4299# ifdef PY_USE_CAPSULE
4300 v = PyCapsule_GetPointer(capsule, NULL);
4301# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02004302 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02004303# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02004304 copy_tv(v, tv);
4305 }
4306 return 0;
4307}
4308
4309 static int
4310ConvertFromPyObject(PyObject *obj, typval_T *tv)
4311{
4312 PyObject *lookup_dict;
4313 int r;
4314
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004315 if (!(lookup_dict = PyDict_New()))
4316 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004317 r = _ConvertFromPyObject(obj, tv, lookup_dict);
4318 Py_DECREF(lookup_dict);
4319 return r;
4320}
4321
4322 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004323_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02004324{
4325 if (obj->ob_type == &DictionaryType)
4326 {
4327 tv->v_type = VAR_DICT;
4328 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
4329 ++tv->vval.v_dict->dv_refcount;
4330 }
4331 else if (obj->ob_type == &ListType)
4332 {
4333 tv->v_type = VAR_LIST;
4334 tv->vval.v_list = (((ListObject *)(obj))->list);
4335 ++tv->vval.v_list->lv_refcount;
4336 }
4337 else if (obj->ob_type == &FunctionType)
4338 {
4339 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
4340 return -1;
4341
4342 tv->v_type = VAR_FUNC;
4343 func_ref(tv->vval.v_string);
4344 }
Bram Moolenaardb913952012-06-29 12:54:53 +02004345 else if (PyBytes_Check(obj))
4346 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004347 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02004348
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004349 if (PyString_AsStringAndSize(obj, (char **) &result, NULL) == -1)
4350 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004351 if (result == NULL)
4352 return -1;
4353
4354 if (set_string_copy(result, tv) == -1)
4355 return -1;
4356
4357 tv->v_type = VAR_STRING;
4358 }
4359 else if (PyUnicode_Check(obj))
4360 {
4361 PyObject *bytes;
4362 char_u *result;
4363
Bram Moolenaardb913952012-06-29 12:54:53 +02004364 bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
4365 if (bytes == NULL)
4366 return -1;
4367
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02004368 if(PyString_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
4369 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02004370 if (result == NULL)
4371 return -1;
4372
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004373 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02004374 {
4375 Py_XDECREF(bytes);
4376 return -1;
4377 }
4378 Py_XDECREF(bytes);
4379
4380 tv->v_type = VAR_STRING;
4381 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02004382#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02004383 else if (PyInt_Check(obj))
4384 {
4385 tv->v_type = VAR_NUMBER;
4386 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
4387 }
4388#endif
4389 else if (PyLong_Check(obj))
4390 {
4391 tv->v_type = VAR_NUMBER;
4392 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
4393 }
4394 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004395 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004396#ifdef FEAT_FLOAT
4397 else if (PyFloat_Check(obj))
4398 {
4399 tv->v_type = VAR_FLOAT;
4400 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
4401 }
4402#endif
4403 else if (PyIter_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004404 return convert_dl(obj, tv, pyiter_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004405 else if (PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004406 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004407 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004408 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02004409 else
4410 {
Bram Moolenaar8661b172013-05-15 15:44:28 +02004411 PyErr_SetString(PyExc_TypeError,
4412 _("unable to convert to vim structure"));
Bram Moolenaardb913952012-06-29 12:54:53 +02004413 return -1;
4414 }
4415 return 0;
4416}
4417
4418 static PyObject *
4419ConvertToPyObject(typval_T *tv)
4420{
4421 if (tv == NULL)
4422 {
4423 PyErr_SetVim(_("NULL reference passed"));
4424 return NULL;
4425 }
4426 switch (tv->v_type)
4427 {
4428 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02004429 return PyBytes_FromString(tv->vval.v_string == NULL
4430 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02004431 case VAR_NUMBER:
4432 return PyLong_FromLong((long) tv->vval.v_number);
4433#ifdef FEAT_FLOAT
4434 case VAR_FLOAT:
4435 return PyFloat_FromDouble((double) tv->vval.v_float);
4436#endif
4437 case VAR_LIST:
4438 return ListNew(tv->vval.v_list);
4439 case VAR_DICT:
4440 return DictionaryNew(tv->vval.v_dict);
4441 case VAR_FUNC:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02004442 return FunctionNew(tv->vval.v_string == NULL
4443 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02004444 case VAR_UNKNOWN:
4445 Py_INCREF(Py_None);
4446 return Py_None;
4447 default:
4448 PyErr_SetVim(_("internal error: invalid value type"));
4449 return NULL;
4450 }
4451}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004452
4453typedef struct
4454{
4455 PyObject_HEAD
4456} CurrentObject;
4457static PyTypeObject CurrentType;
4458
4459 static void
4460init_structs(void)
4461{
4462 vim_memset(&OutputType, 0, sizeof(OutputType));
4463 OutputType.tp_name = "vim.message";
4464 OutputType.tp_basicsize = sizeof(OutputObject);
4465 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
4466 OutputType.tp_doc = "vim message object";
4467 OutputType.tp_methods = OutputMethods;
4468#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004469 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
4470 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004471 OutputType.tp_alloc = call_PyType_GenericAlloc;
4472 OutputType.tp_new = call_PyType_GenericNew;
4473 OutputType.tp_free = call_PyObject_Free;
4474#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004475 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
4476 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004477#endif
4478
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004479 vim_memset(&IterType, 0, sizeof(IterType));
4480 IterType.tp_name = "vim.iter";
4481 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02004482 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004483 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02004484 IterType.tp_iter = (getiterfunc)IterIter;
4485 IterType.tp_iternext = (iternextfunc)IterNext;
4486 IterType.tp_dealloc = (destructor)IterDestructor;
4487 IterType.tp_traverse = (traverseproc)IterTraverse;
4488 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004489
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004490 vim_memset(&BufferType, 0, sizeof(BufferType));
4491 BufferType.tp_name = "vim.buffer";
4492 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004493 BufferType.tp_dealloc = (destructor)BufferDestructor;
4494 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004495 BufferType.tp_as_sequence = &BufferAsSeq;
4496 BufferType.tp_as_mapping = &BufferAsMapping;
4497 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
4498 BufferType.tp_doc = "vim buffer object";
4499 BufferType.tp_methods = BufferMethods;
4500#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004501 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004502 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004503 BufferType.tp_alloc = call_PyType_GenericAlloc;
4504 BufferType.tp_new = call_PyType_GenericNew;
4505 BufferType.tp_free = call_PyObject_Free;
4506#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004507 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004508 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004509#endif
4510
4511 vim_memset(&WindowType, 0, sizeof(WindowType));
4512 WindowType.tp_name = "vim.window";
4513 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004514 WindowType.tp_dealloc = (destructor)WindowDestructor;
4515 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02004516 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004517 WindowType.tp_doc = "vim Window object";
4518 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004519 WindowType.tp_traverse = (traverseproc)WindowTraverse;
4520 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004521#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004522 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
4523 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004524 WindowType.tp_alloc = call_PyType_GenericAlloc;
4525 WindowType.tp_new = call_PyType_GenericNew;
4526 WindowType.tp_free = call_PyObject_Free;
4527#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004528 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
4529 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004530#endif
4531
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004532 vim_memset(&TabPageType, 0, sizeof(TabPageType));
4533 TabPageType.tp_name = "vim.tabpage";
4534 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004535 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
4536 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004537 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
4538 TabPageType.tp_doc = "vim tab page object";
4539 TabPageType.tp_methods = TabPageMethods;
4540#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004541 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004542 TabPageType.tp_alloc = call_PyType_GenericAlloc;
4543 TabPageType.tp_new = call_PyType_GenericNew;
4544 TabPageType.tp_free = call_PyObject_Free;
4545#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004546 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004547#endif
4548
Bram Moolenaardfa38d42013-05-15 13:38:47 +02004549 vim_memset(&BufMapType, 0, sizeof(BufMapType));
4550 BufMapType.tp_name = "vim.bufferlist";
4551 BufMapType.tp_basicsize = sizeof(BufMapObject);
4552 BufMapType.tp_as_mapping = &BufMapAsMapping;
4553 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004554 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004555 BufferType.tp_doc = "vim buffer list";
4556
4557 vim_memset(&WinListType, 0, sizeof(WinListType));
4558 WinListType.tp_name = "vim.windowlist";
4559 WinListType.tp_basicsize = sizeof(WinListType);
4560 WinListType.tp_as_sequence = &WinListAsSeq;
4561 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
4562 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02004563 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004564
4565 vim_memset(&TabListType, 0, sizeof(TabListType));
4566 TabListType.tp_name = "vim.tabpagelist";
4567 TabListType.tp_basicsize = sizeof(TabListType);
4568 TabListType.tp_as_sequence = &TabListAsSeq;
4569 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
4570 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004571
4572 vim_memset(&RangeType, 0, sizeof(RangeType));
4573 RangeType.tp_name = "vim.range";
4574 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004575 RangeType.tp_dealloc = (destructor)RangeDestructor;
4576 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004577 RangeType.tp_as_sequence = &RangeAsSeq;
4578 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02004579 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004580 RangeType.tp_doc = "vim Range object";
4581 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004582 RangeType.tp_traverse = (traverseproc)RangeTraverse;
4583 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004584#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004585 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004586 RangeType.tp_alloc = call_PyType_GenericAlloc;
4587 RangeType.tp_new = call_PyType_GenericNew;
4588 RangeType.tp_free = call_PyObject_Free;
4589#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004590 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004591#endif
4592
4593 vim_memset(&CurrentType, 0, sizeof(CurrentType));
4594 CurrentType.tp_name = "vim.currentdata";
4595 CurrentType.tp_basicsize = sizeof(CurrentObject);
4596 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
4597 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004598 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004599#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004600 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
4601 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004602#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004603 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
4604 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004605#endif
4606
4607 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
4608 DictionaryType.tp_name = "vim.dictionary";
4609 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004610 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004611 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
4612 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT;
4613 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
4614 DictionaryType.tp_methods = DictionaryMethods;
4615#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004616 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
4617 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004618#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004619 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
4620 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004621#endif
4622
4623 vim_memset(&ListType, 0, sizeof(ListType));
4624 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02004625 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004626 ListType.tp_basicsize = sizeof(ListObject);
4627 ListType.tp_as_sequence = &ListAsSeq;
4628 ListType.tp_as_mapping = &ListAsMapping;
4629 ListType.tp_flags = Py_TPFLAGS_DEFAULT;
4630 ListType.tp_doc = "list pushing modifications to vim structure";
4631 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004632 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004633#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004634 ListType.tp_getattro = (getattrofunc)ListGetattro;
4635 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004636#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004637 ListType.tp_getattr = (getattrfunc)ListGetattr;
4638 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004639#endif
4640
4641 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004642 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004643 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02004644 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
4645 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004646 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
4647 FunctionType.tp_doc = "object that calls vim function";
4648 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02004649 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004650#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02004651 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004652#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02004653 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004654#endif
4655
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004656 vim_memset(&OptionsType, 0, sizeof(OptionsType));
4657 OptionsType.tp_name = "vim.options";
4658 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02004659 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004660 OptionsType.tp_doc = "object for manipulating options";
4661 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004662 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
4663 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
4664 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02004665
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004666#if PY_MAJOR_VERSION >= 3
4667 vim_memset(&vimmodule, 0, sizeof(vimmodule));
4668 vimmodule.m_name = "vim";
4669 vimmodule.m_doc = "Vim Python interface\n";
4670 vimmodule.m_size = -1;
4671 vimmodule.m_methods = VimMethods;
4672#endif
4673}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02004674
4675#define PYTYPE_READY(type) \
4676 if (PyType_Ready(&type)) \
4677 return -1;
4678
4679 static int
4680init_types()
4681{
4682 PYTYPE_READY(IterType);
4683 PYTYPE_READY(BufferType);
4684 PYTYPE_READY(RangeType);
4685 PYTYPE_READY(WindowType);
4686 PYTYPE_READY(TabPageType);
4687 PYTYPE_READY(BufMapType);
4688 PYTYPE_READY(WinListType);
4689 PYTYPE_READY(TabListType);
4690 PYTYPE_READY(CurrentType);
4691 PYTYPE_READY(DictionaryType);
4692 PYTYPE_READY(ListType);
4693 PYTYPE_READY(FunctionType);
4694 PYTYPE_READY(OptionsType);
4695 PYTYPE_READY(OutputType);
4696 return 0;
4697}
4698
4699static BufMapObject TheBufferMap =
4700{
4701 PyObject_HEAD_INIT(&BufMapType)
4702};
4703
4704static WinListObject TheWindowList =
4705{
4706 PyObject_HEAD_INIT(&WinListType)
4707 NULL
4708};
4709
4710static CurrentObject TheCurrent =
4711{
4712 PyObject_HEAD_INIT(&CurrentType)
4713};
4714
4715static TabListObject TheTabPageList =
4716{
4717 PyObject_HEAD_INIT(&TabListType)
4718};
4719
4720static struct numeric_constant {
4721 char *name;
4722 int value;
4723} numeric_constants[] = {
4724 {"VAR_LOCKED", VAR_LOCKED},
4725 {"VAR_FIXED", VAR_FIXED},
4726 {"VAR_SCOPE", VAR_SCOPE},
4727 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
4728};
4729
4730static struct object_constant {
4731 char *name;
4732 PyObject *value;
4733} object_constants[] = {
4734 {"buffers", (PyObject *)(void *)&TheBufferMap},
4735 {"windows", (PyObject *)(void *)&TheWindowList},
4736 {"tabpages", (PyObject *)(void *)&TheTabPageList},
4737 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02004738
4739 {"Buffer", (PyObject *)&BufferType},
4740 {"Range", (PyObject *)&RangeType},
4741 {"Window", (PyObject *)&WindowType},
4742 {"TabPage", (PyObject *)&TabPageType},
4743 {"Dictionary", (PyObject *)&DictionaryType},
4744 {"List", (PyObject *)&ListType},
4745 {"Function", (PyObject *)&FunctionType},
4746 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02004747};
4748
4749typedef int (*object_adder)(PyObject *, const char *, PyObject *);
4750
4751#define ADD_OBJECT(m, name, obj) \
4752 if (add_object(m, name, obj)) \
4753 return -1;
4754
4755#define ADD_CHECKED_OBJECT(m, name, obj) \
4756 { \
4757 PyObject *value = obj; \
4758 if (!value) \
4759 return -1; \
4760 ADD_OBJECT(m, name, value); \
4761 }
4762
4763 static int
4764populate_module(PyObject *m, object_adder add_object)
4765{
4766 int i;
4767
4768 for (i = 0; i < (int)(sizeof(numeric_constants)
4769 / sizeof(struct numeric_constant));
4770 ++i)
4771 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
4772 PyInt_FromLong(numeric_constants[i].value));
4773
4774 for (i = 0; i < (int)(sizeof(object_constants)
4775 / sizeof(struct object_constant));
4776 ++i)
4777 {
4778 PyObject *value;
4779
4780 value = object_constants[i].value;
4781 Py_INCREF(value);
4782 ADD_OBJECT(m, object_constants[i].name, value);
4783 }
4784
4785 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
4786 return -1;
4787 ADD_OBJECT(m, "error", VimError);
4788
4789 ADD_CHECKED_OBJECT(m, "vars", DictionaryNew(&globvardict));
4790 ADD_CHECKED_OBJECT(m, "vvars", DictionaryNew(&vimvardict));
4791 ADD_CHECKED_OBJECT(m, "options",
4792 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
4793 return 0;
4794}