blob: 46625049d8256fc4759fbd02c29bf848a803f9b9 [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
Bram Moolenaar808c2bc2013-06-23 13:11:18 +020021# define ENC_OPT ((char *)p_enc)
Bram Moolenaar91805fc2011-06-26 04:01:44 +020022#else
23# define ENC_OPT "latin1"
24#endif
Bram Moolenaard620aa92013-05-17 16:40:06 +020025#define DOPY_FUNC "_vim_pydo"
Bram Moolenaar91805fc2011-06-26 04:01:44 +020026
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020027static const char *vim_special_path = "_vim_path_";
28
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020029#define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020030#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020031#define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020032
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020033#define RAISE_NO_EMPTY_KEYS PyErr_SET_STRING(PyExc_ValueError, \
34 "empty keys are not allowed")
Bram Moolenaar35eacd72013-05-30 22:06:33 +020035
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020036#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
37#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020038#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020039
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020040typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020041typedef void (*runner)(const char *, void *
42#ifdef PY_CAN_RECURSE
43 , PyGILState_STATE *
44#endif
45 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020046
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020047static int ConvertFromPyObject(PyObject *, typval_T *);
48static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +020049static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020050static PyObject *WindowNew(win_T *, tabpage_T *);
51static PyObject *BufferNew (buf_T *);
52static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020053
54static PyInt RangeStart;
55static PyInt RangeEnd;
56
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020057static PyObject *globals;
58
Bram Moolenaarf4258302013-06-02 18:20:17 +020059static PyObject *py_chdir;
60static PyObject *py_fchdir;
61static PyObject *py_getcwd;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020062static PyObject *vim_module;
63static PyObject *vim_special_path_object;
Bram Moolenaarf4258302013-06-02 18:20:17 +020064
Bram Moolenaar81c40c52013-06-12 14:41:04 +020065static PyObject *py_find_module;
66static PyObject *py_load_module;
67
68static PyObject *VimError;
69
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020070/*
71 * obtain a lock on the Vim data structures
72 */
73 static void
74Python_Lock_Vim(void)
75{
76}
77
78/*
79 * release a lock on the Vim data structures
80 */
81 static void
82Python_Release_Vim(void)
83{
84}
85
Bram Moolenaare9ba5162013-05-29 22:02:22 +020086/*
87 * The "todecref" argument holds a pointer to PyObject * that must be
88 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
89 * was needed to generate returned value is object.
90 *
91 * Use Py_XDECREF to decrement reference count.
92 */
93 static char_u *
94StringToChars(PyObject *object, PyObject **todecref)
95{
96 char_u *p;
Bram Moolenaare9ba5162013-05-29 22:02:22 +020097
98 if (PyBytes_Check(object))
99 {
100
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200101 if (PyBytes_AsStringAndSize(object, (char **) &p, NULL) == -1
102 || p == NULL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200103 return NULL;
104
105 *todecref = NULL;
106 }
107 else if (PyUnicode_Check(object))
108 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200109 PyObject *bytes;
110
111 if (!(bytes = PyUnicode_AsEncodedString(object, ENC_OPT, NULL)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200112 return NULL;
113
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200114 if(PyBytes_AsStringAndSize(bytes, (char **) &p, NULL) == -1
115 || p == NULL)
116 {
117 Py_DECREF(bytes);
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200118 return NULL;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200119 }
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200120
121 *todecref = bytes;
122 }
123 else
124 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200125 PyErr_SET_STRING(PyExc_TypeError, "object must be string");
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200126 return NULL;
127 }
128
129 return (char_u *) p;
130}
131
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200132 static int
133add_string(PyObject *list, char *s)
134{
135 PyObject *string;
136
137 if (!(string = PyString_FromString(s)))
138 return -1;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200139
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200140 if (PyList_Append(list, string))
141 {
142 Py_DECREF(string);
143 return -1;
144 }
145
146 Py_DECREF(string);
147 return 0;
148}
149
150 static PyObject *
151ObjectDir(PyObject *self, char **attributes)
152{
153 PyMethodDef *method;
154 char **attr;
155 PyObject *r;
156
157 if (!(r = PyList_New(0)))
158 return NULL;
159
160 if (self)
161 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
162 if (add_string(r, (char *) method->ml_name))
163 {
164 Py_DECREF(r);
165 return NULL;
166 }
167
168 for (attr = attributes ; *attr ; ++attr)
169 if (add_string(r, *attr))
170 {
171 Py_DECREF(r);
172 return NULL;
173 }
174
175#if PY_MAJOR_VERSION < 3
176 if (add_string(r, "__members__"))
177 {
178 Py_DECREF(r);
179 return NULL;
180 }
181#endif
182
183 return r;
184}
185
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200186/* Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200187 */
188
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200189/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200190typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200191
192static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200193
194typedef struct
195{
196 PyObject_HEAD
197 long softspace;
198 long error;
199} OutputObject;
200
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200201static char *OutputAttrs[] = {
202 "softspace",
203 NULL
204};
205
206 static PyObject *
207OutputDir(PyObject *self)
208{
209 return ObjectDir(self, OutputAttrs);
210}
211
Bram Moolenaar77045652012-09-21 13:46:06 +0200212 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +0200213OutputSetattr(OutputObject *self, char *name, PyObject *val)
Bram Moolenaar77045652012-09-21 13:46:06 +0200214{
215 if (val == NULL)
216 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200217 PyErr_SET_STRING(PyExc_AttributeError,
218 "can't delete OutputObject attributes");
Bram Moolenaar77045652012-09-21 13:46:06 +0200219 return -1;
220 }
221
222 if (strcmp(name, "softspace") == 0)
223 {
224 if (!PyInt_Check(val))
225 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200226 PyErr_SET_STRING(PyExc_TypeError, "softspace must be an integer");
Bram Moolenaar77045652012-09-21 13:46:06 +0200227 return -1;
228 }
229
Bram Moolenaard6e39182013-05-21 18:30:34 +0200230 self->softspace = PyInt_AsLong(val);
Bram Moolenaar77045652012-09-21 13:46:06 +0200231 return 0;
232 }
233
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200234 PyErr_SET_STRING(PyExc_AttributeError, "invalid attribute");
Bram Moolenaar77045652012-09-21 13:46:06 +0200235 return -1;
236}
237
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200238/* Buffer IO, we write one whole line at a time. */
239static garray_T io_ga = {0, 0, 1, 80, NULL};
240static writefn old_fn = NULL;
241
242 static void
243PythonIO_Flush(void)
244{
245 if (old_fn != NULL && io_ga.ga_len > 0)
246 {
247 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
248 old_fn((char_u *)io_ga.ga_data);
249 }
250 io_ga.ga_len = 0;
251}
252
253 static void
254writer(writefn fn, char_u *str, PyInt n)
255{
256 char_u *ptr;
257
258 /* Flush when switching output function. */
259 if (fn != old_fn)
260 PythonIO_Flush();
261 old_fn = fn;
262
263 /* Write each NL separated line. Text after the last NL is kept for
264 * writing later. */
265 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
266 {
267 PyInt len = ptr - str;
268
269 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
270 break;
271
272 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
273 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
274 fn((char_u *)io_ga.ga_data);
275 str = ptr + 1;
276 n -= len + 1;
277 io_ga.ga_len = 0;
278 }
279
280 /* Put the remaining text into io_ga for later printing. */
281 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
282 {
283 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
284 io_ga.ga_len += (int)n;
285 }
286}
287
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200288 static int
289write_output(OutputObject *self, PyObject *string)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200290{
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200291 Py_ssize_t len = 0;
292 char *str = NULL;
293 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200294
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200295 if (!PyArg_Parse(string, "et#", ENC_OPT, &str, &len))
296 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200297
298 Py_BEGIN_ALLOW_THREADS
299 Python_Lock_Vim();
300 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
301 Python_Release_Vim();
302 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200303 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200304
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200305 return 0;
306}
307
308 static PyObject *
309OutputWrite(OutputObject *self, PyObject *string)
310{
311 if (write_output(self, string))
312 return NULL;
313
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200314 Py_INCREF(Py_None);
315 return Py_None;
316}
317
318 static PyObject *
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200319OutputWritelines(OutputObject *self, PyObject *seq)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200320{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200321 PyObject *iterator;
322 PyObject *item;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200323
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200324 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200325 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200326
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200327 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200328 {
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200329 if (write_output(self, item))
Bram Moolenaardb913952012-06-29 12:54:53 +0200330 {
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200331 Py_DECREF(iterator);
332 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200333 return NULL;
334 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200335 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200336 }
337
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200338 Py_DECREF(iterator);
339
340 /* Iterator may have finished due to an exception */
341 if (PyErr_Occurred())
342 return NULL;
343
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200344 Py_INCREF(Py_None);
345 return Py_None;
346}
347
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100348 static PyObject *
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200349OutputFlush(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100350{
351 /* do nothing */
352 Py_INCREF(Py_None);
353 return Py_None;
354}
355
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200356/***************/
357
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200358static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200359 /* name, function, calling, doc */
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200360 {"write", (PyCFunction)OutputWrite, METH_O, ""},
361 {"writelines", (PyCFunction)OutputWritelines, METH_O, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200362 {"flush", (PyCFunction)OutputFlush, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200363 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200364 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200365};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200366
367static OutputObject Output =
368{
369 PyObject_HEAD_INIT(&OutputType)
370 0,
371 0
372};
373
374static OutputObject Error =
375{
376 PyObject_HEAD_INIT(&OutputType)
377 0,
378 1
379};
380
381 static int
382PythonIO_Init_io(void)
383{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200384 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
385 return -1;
386 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
387 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200388
389 if (PyErr_Occurred())
390 {
391 EMSG(_("E264: Python: Error initialising I/O objects"));
392 return -1;
393 }
394
395 return 0;
396}
397
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200398typedef struct
399{
400 PyObject_HEAD
401 PyObject *module;
402} LoaderObject;
403static PyTypeObject LoaderType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200404
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200405 static void
406LoaderDestructor(LoaderObject *self)
407{
408 Py_DECREF(self->module);
409 DESTRUCTOR_FINISH(self);
410}
411
412 static PyObject *
413LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
414{
415 PyObject *r = self->module;
416
417 Py_INCREF(r);
418 return r;
419}
420
421static struct PyMethodDef LoaderMethods[] = {
422 /* name, function, calling, doc */
423 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
424 { NULL, NULL, 0, NULL}
425};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200426
427/* Check to see whether a Vim error has been reported, or a keyboard
428 * interrupt has been detected.
429 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200430
431 static void
432VimTryStart(void)
433{
434 ++trylevel;
435}
436
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200437 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200438VimTryEnd(void)
439{
440 --trylevel;
441 if (got_int)
442 {
443 PyErr_SetNone(PyExc_KeyboardInterrupt);
444 return 1;
445 }
446 else if (!did_throw)
447 return 0;
448 else if (PyErr_Occurred())
449 return 1;
450 else
451 {
452 PyErr_SetVim((char *) current_exception->value);
453 discard_current_exception();
454 return 1;
455 }
456}
457
458 static int
459VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200460{
461 if (got_int)
462 {
463 PyErr_SetNone(PyExc_KeyboardInterrupt);
464 return 1;
465 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200466 return 0;
467}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200468
469/* Vim module - Implementation
470 */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200471
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200472 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200473VimCommand(PyObject *self UNUSED, PyObject *string)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200474{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200475 char_u *cmd;
476 PyObject *result;
477 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200478
Bram Moolenaar389a1792013-06-23 13:00:44 +0200479 if (!(cmd = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200480 return NULL;
481
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200482 Py_BEGIN_ALLOW_THREADS
483 Python_Lock_Vim();
484
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200485 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200486 do_cmdline_cmd(cmd);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200487 update_screen(VALID);
488
489 Python_Release_Vim();
490 Py_END_ALLOW_THREADS
491
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200492 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200493 result = NULL;
494 else
495 result = Py_None;
496
497 Py_XINCREF(result);
Bram Moolenaar389a1792013-06-23 13:00:44 +0200498 Py_XDECREF(todecref);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200499 return result;
500}
501
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200502/*
503 * Function to translate a typval_T into a PyObject; this will recursively
504 * translate lists/dictionaries into their Python equivalents.
505 *
506 * The depth parameter is to avoid infinite recursion, set it to 1 when
507 * you call VimToPython.
508 */
509 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200510VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200511{
512 PyObject *result;
513 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200514 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200515
516 /* Avoid infinite recursion */
517 if (depth > 100)
518 {
519 Py_INCREF(Py_None);
520 result = Py_None;
521 return result;
522 }
523
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200524 /* Check if we run into a recursive loop. The item must be in lookup_dict
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200525 * then and we can use it again. */
526 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
527 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
528 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200529 sprintf(ptrBuf, "%p",
530 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
531 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200532
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200533 if ((result = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200534 {
535 Py_INCREF(result);
536 return result;
537 }
538 }
539
540 if (our_tv->v_type == VAR_STRING)
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200541 result = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200542 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200543 else if (our_tv->v_type == VAR_NUMBER)
544 {
545 char buf[NUMBUFLEN];
546
547 /* For backwards compatibility numbers are stored as strings. */
548 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200549 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200550 }
551# ifdef FEAT_FLOAT
552 else if (our_tv->v_type == VAR_FLOAT)
553 {
554 char buf[NUMBUFLEN];
555
556 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar432b09c2013-05-29 22:26:18 +0200557 result = PyString_FromString((char *) buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200558 }
559# endif
560 else if (our_tv->v_type == VAR_LIST)
561 {
562 list_T *list = our_tv->vval.v_list;
563 listitem_T *curr;
564
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200565 if (list == NULL)
566 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200567
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200568 if (!(result = PyList_New(0)))
569 return NULL;
570
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200571 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200572 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200573 Py_DECREF(result);
574 return NULL;
575 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200576
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200577 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
578 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200579 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200580 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200581 Py_DECREF(result);
582 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200583 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200584 if (PyList_Append(result, newObj))
585 {
586 Py_DECREF(newObj);
587 Py_DECREF(result);
588 return NULL;
589 }
590 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200591 }
592 }
593 else if (our_tv->v_type == VAR_DICT)
594 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200595
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200596 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
597 long_u todo = ht->ht_used;
598 hashitem_T *hi;
599 dictitem_T *di;
600 if (our_tv->vval.v_dict == NULL)
601 return NULL;
602
603 if (!(result = PyDict_New()))
604 return NULL;
605
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200606 if (PyDict_SetItemString(lookup_dict, ptrBuf, result))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200607 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200608 Py_DECREF(result);
609 return NULL;
610 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200611
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200612 for (hi = ht->ht_array; todo > 0; ++hi)
613 {
614 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200615 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200616 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200617
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200618 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200619 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200620 {
621 Py_DECREF(result);
622 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200623 }
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200624 if (PyDict_SetItemString(result, (char *)hi->hi_key, newObj))
625 {
626 Py_DECREF(result);
627 Py_DECREF(newObj);
628 return NULL;
629 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200630 }
631 }
632 }
633 else
634 {
635 Py_INCREF(Py_None);
636 result = Py_None;
637 }
638
639 return result;
640}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200641
642 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200643VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200644{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200645 char_u *expr;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200646 typval_T *our_tv;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200647 PyObject *string;
648 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200649 PyObject *result;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200650 PyObject *lookup_dict;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200651
Bram Moolenaar389a1792013-06-23 13:00:44 +0200652 if (!PyArg_ParseTuple(args, "O", &string))
653 return NULL;
654
655 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200656 return NULL;
657
658 Py_BEGIN_ALLOW_THREADS
659 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200660 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200661 our_tv = eval_expr(expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200662 Python_Release_Vim();
663 Py_END_ALLOW_THREADS
664
Bram Moolenaar389a1792013-06-23 13:00:44 +0200665 Py_XDECREF(todecref);
666
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200667 if (VimTryEnd())
668 return NULL;
669
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200670 if (our_tv == NULL)
671 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200672 PyErr_SET_VIM("invalid expression");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200673 return NULL;
674 }
675
676 /* Convert the Vim type into a Python type. Create a dictionary that's
677 * used to check for recursive loops. */
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200678 if (!(lookup_dict = PyDict_New()))
679 result = NULL;
680 else
681 {
682 result = VimToPython(our_tv, 1, lookup_dict);
683 Py_DECREF(lookup_dict);
684 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200685
686
687 Py_BEGIN_ALLOW_THREADS
688 Python_Lock_Vim();
689 free_tv(our_tv);
690 Python_Release_Vim();
691 Py_END_ALLOW_THREADS
692
693 return result;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200694}
695
Bram Moolenaardb913952012-06-29 12:54:53 +0200696static PyObject *ConvertToPyObject(typval_T *);
697
698 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200699VimEvalPy(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200700{
Bram Moolenaardb913952012-06-29 12:54:53 +0200701 typval_T *our_tv;
702 PyObject *result;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200703 char_u *expr;
704 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +0200705
Bram Moolenaar389a1792013-06-23 13:00:44 +0200706 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200707 return NULL;
708
709 Py_BEGIN_ALLOW_THREADS
710 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200711 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200712 our_tv = eval_expr(expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200713 Python_Release_Vim();
714 Py_END_ALLOW_THREADS
715
Bram Moolenaar389a1792013-06-23 13:00:44 +0200716 Py_XDECREF(todecref);
717
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200718 if (VimTryEnd())
719 return NULL;
720
Bram Moolenaardb913952012-06-29 12:54:53 +0200721 if (our_tv == NULL)
722 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200723 PyErr_SET_VIM("invalid expression");
Bram Moolenaardb913952012-06-29 12:54:53 +0200724 return NULL;
725 }
726
727 result = ConvertToPyObject(our_tv);
728 Py_BEGIN_ALLOW_THREADS
729 Python_Lock_Vim();
730 free_tv(our_tv);
731 Python_Release_Vim();
732 Py_END_ALLOW_THREADS
733
734 return result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200735}
736
737 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200738VimStrwidth(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200739{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200740 char_u *str;
741 PyObject *todecref;
742 int result;
Bram Moolenaardb913952012-06-29 12:54:53 +0200743
Bram Moolenaar389a1792013-06-23 13:00:44 +0200744 if (!(str = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200745 return NULL;
746
Bram Moolenaara54bf402012-12-05 16:30:07 +0100747#ifdef FEAT_MBYTE
Bram Moolenaar389a1792013-06-23 13:00:44 +0200748 result = mb_string2cells(str, (int)STRLEN(str));
Bram Moolenaara54bf402012-12-05 16:30:07 +0100749#else
Bram Moolenaar389a1792013-06-23 13:00:44 +0200750 result = STRLEN(str);
Bram Moolenaara54bf402012-12-05 16:30:07 +0100751#endif
Bram Moolenaar389a1792013-06-23 13:00:44 +0200752
753 Py_XDECREF(todecref);
754
755 return PyLong_FromLong(result);
Bram Moolenaardb913952012-06-29 12:54:53 +0200756}
757
Bram Moolenaarf4258302013-06-02 18:20:17 +0200758 static PyObject *
759_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
760{
761 PyObject *r;
762 PyObject *newwd;
763 PyObject *todecref;
764 char_u *new_dir;
765
Bram Moolenaard4209d22013-06-05 20:34:15 +0200766 if (_chdir == NULL)
767 return NULL;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200768 if (!(r = PyObject_Call(_chdir, args, kwargs)))
769 return NULL;
770
771 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
772 {
773 Py_DECREF(r);
774 return NULL;
775 }
776
777 if (!(new_dir = StringToChars(newwd, &todecref)))
778 {
779 Py_DECREF(r);
780 Py_DECREF(newwd);
781 return NULL;
782 }
783
784 VimTryStart();
785
786 if (vim_chdir(new_dir))
787 {
788 Py_DECREF(r);
789 Py_DECREF(newwd);
790 Py_XDECREF(todecref);
791
792 if (VimTryEnd())
793 return NULL;
794
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200795 PyErr_SET_VIM("failed to change directory");
Bram Moolenaarf4258302013-06-02 18:20:17 +0200796 return NULL;
797 }
798
799 Py_DECREF(newwd);
800 Py_XDECREF(todecref);
801
802 post_chdir(FALSE);
803
804 if (VimTryEnd())
805 {
806 Py_DECREF(r);
807 return NULL;
808 }
809
810 return r;
811}
812
813 static PyObject *
814VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
815{
816 return _VimChdir(py_chdir, args, kwargs);
817}
818
819 static PyObject *
820VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
821{
822 return _VimChdir(py_fchdir, args, kwargs);
823}
824
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200825typedef struct {
826 PyObject *callable;
827 PyObject *result;
828} map_rtp_data;
829
830 static void
831map_rtp_callback(char_u *path, void *_data)
832{
833 void **data = (void **) _data;
834 PyObject *pathObject;
835 map_rtp_data *mr_data = *((map_rtp_data **) data);
836
837 if (!(pathObject = PyString_FromString((char *) path)))
838 {
839 *data = NULL;
840 return;
841 }
842
843 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
844 pathObject, NULL);
845
846 Py_DECREF(pathObject);
847
848 if (!mr_data->result || mr_data->result != Py_None)
849 *data = NULL;
850 else
851 {
852 Py_DECREF(mr_data->result);
853 mr_data->result = NULL;
854 }
855}
856
857 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200858VimForeachRTP(PyObject *self UNUSED, PyObject *callable)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200859{
860 map_rtp_data data;
861
Bram Moolenaar389a1792013-06-23 13:00:44 +0200862 data.callable = callable;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +0200863 data.result = NULL;
864
865 do_in_runtimepath(NULL, FALSE, &map_rtp_callback, &data);
866
867 if (data.result == NULL)
868 {
869 if (PyErr_Occurred())
870 return NULL;
871 else
872 {
873 Py_INCREF(Py_None);
874 return Py_None;
875 }
876 }
877 return data.result;
878}
879
880/*
881 * _vim_runtimepath_ special path implementation.
882 */
883
884 static void
885map_finder_callback(char_u *path, void *_data)
886{
887 void **data = (void **) _data;
888 PyObject *list = *((PyObject **) data);
889 PyObject *pathObject1, *pathObject2;
890 char *pathbuf;
891 size_t pathlen;
892
893 pathlen = STRLEN(path);
894
895#if PY_MAJOR_VERSION < 3
896# define PY_MAIN_DIR_STRING "python2"
897#else
898# define PY_MAIN_DIR_STRING "python3"
899#endif
900#define PY_ALTERNATE_DIR_STRING "pythonx"
901
902#define PYTHONX_STRING_LENGTH 7 /* STRLEN("pythonx") */
903 if (!(pathbuf = PyMem_New(char,
904 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
905 {
906 PyErr_NoMemory();
907 *data = NULL;
908 return;
909 }
910
911 mch_memmove(pathbuf, path, pathlen + 1);
912 add_pathsep((char_u *) pathbuf);
913
914 pathlen = STRLEN(pathbuf);
915 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
916 PYTHONX_STRING_LENGTH + 1);
917
918 if (!(pathObject1 = PyString_FromString(pathbuf)))
919 {
920 *data = NULL;
921 PyMem_Free(pathbuf);
922 return;
923 }
924
925 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
926 PYTHONX_STRING_LENGTH + 1);
927
928 if (!(pathObject2 = PyString_FromString(pathbuf)))
929 {
930 Py_DECREF(pathObject1);
931 PyMem_Free(pathbuf);
932 *data = NULL;
933 return;
934 }
935
936 PyMem_Free(pathbuf);
937
938 if (PyList_Append(list, pathObject1)
939 || PyList_Append(list, pathObject2))
940 *data = NULL;
941
942 Py_DECREF(pathObject1);
943 Py_DECREF(pathObject2);
944}
945
946 static PyObject *
947Vim_GetPaths(PyObject *self UNUSED)
948{
949 PyObject *r;
950
951 if (!(r = PyList_New(0)))
952 return NULL;
953
954 do_in_runtimepath(NULL, FALSE, &map_finder_callback, r);
955
956 if (PyErr_Occurred())
957 {
958 Py_DECREF(r);
959 return NULL;
960 }
961
962 return r;
963}
964
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200965 static PyObject *
966call_load_module(char *name, int len, PyObject *find_module_result)
967{
968 PyObject *fd, *pathname, *description;
969
970 if (!PyTuple_Check(find_module_result)
971 || PyTuple_GET_SIZE(find_module_result) != 3)
972 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200973 PyErr_SET_STRING(PyExc_TypeError,
974 "expected 3-tuple as imp.find_module() result");
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200975 return NULL;
976 }
977
978 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
979 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
980 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
981 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200982 PyErr_SET_STRING(PyExc_RuntimeError,
983 "internal error: imp.find_module returned tuple with NULL");
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200984 return NULL;
985 }
986
987 return PyObject_CallFunction(py_load_module,
988 "s#OOO", name, len, fd, pathname, description);
989}
990
991 static PyObject *
992find_module(char *fullname, char *tail, PyObject *new_path)
993{
994 PyObject *find_module_result;
995 PyObject *module;
996 char *dot;
997
998 if ((dot = (char *) vim_strchr((char_u *) tail, '.')))
999 {
1000 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001001 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001002 * first component
1003 */
1004 PyObject *newest_path;
1005 int partlen = (int) (dot - 1 - tail);
1006
1007 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1008 "s#O", tail, partlen, new_path)))
1009 return NULL;
1010
1011 if (!(module = call_load_module(
1012 fullname,
1013 ((int) (tail - fullname)) + partlen,
1014 find_module_result)))
1015 {
1016 Py_DECREF(find_module_result);
1017 return NULL;
1018 }
1019
1020 Py_DECREF(find_module_result);
1021
1022 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1023 {
1024 Py_DECREF(module);
1025 return NULL;
1026 }
1027
1028 Py_DECREF(module);
1029
1030 module = find_module(fullname, dot + 1, newest_path);
1031
1032 Py_DECREF(newest_path);
1033
1034 return module;
1035 }
1036 else
1037 {
1038 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1039 "sO", tail, new_path)))
1040 return NULL;
1041
1042 if (!(module = call_load_module(
1043 fullname,
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001044 (int)STRLEN(fullname),
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001045 find_module_result)))
1046 {
1047 Py_DECREF(find_module_result);
1048 return NULL;
1049 }
1050
1051 Py_DECREF(find_module_result);
1052
1053 return module;
1054 }
1055}
1056
1057 static PyObject *
1058FinderFindModule(PyObject *self, PyObject *args)
1059{
1060 char *fullname;
1061 PyObject *module;
1062 PyObject *new_path;
1063 LoaderObject *loader;
1064
1065 if (!PyArg_ParseTuple(args, "s", &fullname))
1066 return NULL;
1067
1068 if (!(new_path = Vim_GetPaths(self)))
1069 return NULL;
1070
1071 module = find_module(fullname, fullname, new_path);
1072
1073 Py_DECREF(new_path);
1074
1075 if (!module)
1076 {
1077 Py_INCREF(Py_None);
1078 return Py_None;
1079 }
1080
1081 if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
1082 {
1083 Py_DECREF(module);
1084 return NULL;
1085 }
1086
1087 loader->module = module;
1088
1089 return (PyObject *) loader;
1090}
1091
1092 static PyObject *
1093VimPathHook(PyObject *self UNUSED, PyObject *args)
1094{
1095 char *path;
1096
1097 if (PyArg_ParseTuple(args, "s", &path)
1098 && STRCMP(path, vim_special_path) == 0)
1099 {
1100 Py_INCREF(vim_module);
1101 return vim_module;
1102 }
1103
1104 PyErr_Clear();
1105 PyErr_SetNone(PyExc_ImportError);
1106 return NULL;
1107}
1108
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001109/*
1110 * Vim module - Definitions
1111 */
1112
1113static struct PyMethodDef VimMethods[] = {
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001114 /* name, function, calling, documentation */
Bram Moolenaar389a1792013-06-23 13:00:44 +02001115 {"command", VimCommand, METH_O, "Execute a Vim ex-mode command" },
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001116 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02001117 {"bindeval", VimEvalPy, METH_O, "Like eval(), but returns objects attached to vim ones"},
1118 {"strwidth", VimStrwidth, METH_O, "Screen string width, counts <Tab> as having width 1"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001119 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1120 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001121 {"foreach_rtp", VimForeachRTP, METH_O, "Call given callable for each path in &rtp"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001122 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001123 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1124 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1125 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001126};
1127
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001128/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001129 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001130 */
1131
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001132static PyTypeObject IterType;
1133
1134typedef PyObject *(*nextfun)(void **);
1135typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001136typedef int (*traversefun)(void *, visitproc, void *);
1137typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001138
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001139/* Main purpose of this object is removing the need for do python
1140 * initialization (i.e. PyType_Ready and setting type attributes) for a big
1141 * bunch of objects. */
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001142
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001143typedef struct
1144{
1145 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001146 void *cur;
1147 nextfun next;
1148 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001149 traversefun traverse;
1150 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001151} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001152
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001153 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001154IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
1155 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001156{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001157 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001158
Bram Moolenaar774267b2013-05-21 20:51:59 +02001159 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001160 self->cur = start;
1161 self->next = next;
1162 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001163 self->traverse = traverse;
1164 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001165
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001166 return (PyObject *)(self);
1167}
1168
1169 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001170IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001171{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001172 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001173 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001174 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001175}
1176
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001177 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001178IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001179{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001180 if (self->traverse != NULL)
1181 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001182 else
1183 return 0;
1184}
1185
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001186/* Mac OSX defines clear() somewhere. */
1187#ifdef clear
1188# undef clear
1189#endif
1190
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001191 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001192IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001193{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001194 if (self->clear != NULL)
1195 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001196 else
1197 return 0;
1198}
1199
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001200 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001201IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001202{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001203 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001204}
1205
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001206 static PyObject *
1207IterIter(PyObject *self)
1208{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001209 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001210 return self;
1211}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001212
Bram Moolenaardb913952012-06-29 12:54:53 +02001213typedef struct pylinkedlist_S {
1214 struct pylinkedlist_S *pll_next;
1215 struct pylinkedlist_S *pll_prev;
1216 PyObject *pll_obj;
1217} pylinkedlist_T;
1218
1219static pylinkedlist_T *lastdict = NULL;
1220static pylinkedlist_T *lastlist = NULL;
1221
1222 static void
1223pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1224{
1225 if (ref->pll_prev == NULL)
1226 {
1227 if (ref->pll_next == NULL)
1228 {
1229 *last = NULL;
1230 return;
1231 }
1232 }
1233 else
1234 ref->pll_prev->pll_next = ref->pll_next;
1235
1236 if (ref->pll_next == NULL)
1237 *last = ref->pll_prev;
1238 else
1239 ref->pll_next->pll_prev = ref->pll_prev;
1240}
1241
1242 static void
1243pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1244{
1245 if (*last == NULL)
1246 ref->pll_prev = NULL;
1247 else
1248 {
1249 (*last)->pll_next = ref;
1250 ref->pll_prev = *last;
1251 }
1252 ref->pll_next = NULL;
1253 ref->pll_obj = self;
1254 *last = ref;
1255}
1256
1257static PyTypeObject DictionaryType;
1258
1259typedef struct
1260{
1261 PyObject_HEAD
1262 dict_T *dict;
1263 pylinkedlist_T ref;
1264} DictionaryObject;
1265
Bram Moolenaara9922d62013-05-30 13:01:18 +02001266static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1267
1268#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
1269
Bram Moolenaardb913952012-06-29 12:54:53 +02001270 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001271DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001272{
1273 DictionaryObject *self;
1274
Bram Moolenaara9922d62013-05-30 13:01:18 +02001275 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001276 if (self == NULL)
1277 return NULL;
1278 self->dict = dict;
1279 ++dict->dv_refcount;
1280
1281 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1282
1283 return (PyObject *)(self);
1284}
1285
Bram Moolenaara9922d62013-05-30 13:01:18 +02001286 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001287py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001288{
1289 dict_T *r;
1290
1291 if (!(r = dict_alloc()))
1292 {
1293 PyErr_NoMemory();
1294 return NULL;
1295 }
1296 ++r->dv_refcount;
1297
1298 return r;
1299}
1300
1301 static PyObject *
1302DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1303{
1304 DictionaryObject *self;
1305 dict_T *dict;
1306
1307 if (!(dict = py_dict_alloc()))
1308 return NULL;
1309
1310 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1311
1312 --dict->dv_refcount;
1313
1314 if (kwargs || PyTuple_Size(args))
1315 {
1316 PyObject *tmp;
1317 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1318 {
1319 Py_DECREF(self);
1320 return NULL;
1321 }
1322
1323 Py_DECREF(tmp);
1324 }
1325
1326 return (PyObject *)(self);
1327}
1328
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001329 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001330DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001331{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001332 pyll_remove(&self->ref, &lastdict);
1333 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001334
1335 DESTRUCTOR_FINISH(self);
1336}
1337
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001338static char *DictionaryAttrs[] = {
1339 "locked", "scope",
1340 NULL
1341};
1342
1343 static PyObject *
1344DictionaryDir(PyObject *self)
1345{
1346 return ObjectDir(self, DictionaryAttrs);
1347}
1348
Bram Moolenaardb913952012-06-29 12:54:53 +02001349 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001350DictionarySetattr(DictionaryObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001351{
1352 if (val == NULL)
1353 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001354 PyErr_SET_STRING(PyExc_AttributeError,
1355 "cannot delete vim.Dictionary attributes");
Bram Moolenaar66b79852012-09-21 14:00:35 +02001356 return -1;
1357 }
1358
1359 if (strcmp(name, "locked") == 0)
1360 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001361 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001362 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001363 PyErr_SET_STRING(PyExc_TypeError, "cannot modify fixed dictionary");
Bram Moolenaar66b79852012-09-21 14:00:35 +02001364 return -1;
1365 }
1366 else
1367 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02001368 int istrue = PyObject_IsTrue(val);
1369 if (istrue == -1)
1370 return -1;
1371 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001372 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001373 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001374 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001375 }
1376 return 0;
1377 }
1378 else
1379 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001380 PyErr_SET_STRING(PyExc_AttributeError, "cannot set this attribute");
Bram Moolenaar66b79852012-09-21 14:00:35 +02001381 return -1;
1382 }
1383}
1384
1385 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001386DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001387{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001388 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001389}
1390
Bram Moolenaara9922d62013-05-30 13:01:18 +02001391#define DICT_FLAG_HAS_DEFAULT 0x01
1392#define DICT_FLAG_POP 0x02
1393#define DICT_FLAG_NONE_DEFAULT 0x04
1394#define DICT_FLAG_RETURN_BOOL 0x08 /* Incompatible with DICT_FLAG_POP */
1395#define DICT_FLAG_RETURN_PAIR 0x10
1396
Bram Moolenaardb913952012-06-29 12:54:53 +02001397 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001398_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001399{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001400 PyObject *keyObject;
1401 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
1402 PyObject *r;
Bram Moolenaardb913952012-06-29 12:54:53 +02001403 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001404 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001405 dict_T *dict = self->dict;
1406 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001407 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001408
Bram Moolenaara9922d62013-05-30 13:01:18 +02001409 if (flags & DICT_FLAG_HAS_DEFAULT)
1410 {
1411 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1412 return NULL;
1413 }
1414 else
1415 keyObject = args;
1416
1417 if (flags & DICT_FLAG_RETURN_BOOL)
1418 defObject = Py_False;
1419
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001420 if (!(key = StringToChars(keyObject, &todecref)))
1421 return NULL;
1422
1423 if (*key == NUL)
1424 {
1425 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001426 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001427 return NULL;
1428 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001429
Bram Moolenaara9922d62013-05-30 13:01:18 +02001430 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001431
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001432 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001433
Bram Moolenaara9922d62013-05-30 13:01:18 +02001434 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001435 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001436 if (defObject)
1437 {
1438 Py_INCREF(defObject);
1439 return defObject;
1440 }
1441 else
1442 {
1443 PyErr_SetObject(PyExc_KeyError, keyObject);
1444 return NULL;
1445 }
1446 }
1447 else if (flags & DICT_FLAG_RETURN_BOOL)
1448 {
1449 Py_INCREF(Py_True);
1450 return Py_True;
1451 }
1452
1453 di = dict_lookup(hi);
1454
1455 if (!(r = ConvertToPyObject(&di->di_tv)))
1456 return NULL;
1457
1458 if (flags & DICT_FLAG_POP)
1459 {
1460 if (dict->dv_lock)
1461 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001462 PyErr_SET_VIM("dict is locked");
Bram Moolenaara9922d62013-05-30 13:01:18 +02001463 Py_DECREF(r);
1464 return NULL;
1465 }
1466
1467 hash_remove(&dict->dv_hashtab, hi);
1468 dictitem_free(di);
1469 }
1470
Bram Moolenaara9922d62013-05-30 13:01:18 +02001471 return r;
1472}
1473
1474 static PyObject *
1475DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1476{
1477 return _DictionaryItem(self, keyObject, 0);
1478}
1479
1480 static int
1481DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1482{
1483 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1484 int r;
1485
1486 r = (rObj == Py_True);
1487
1488 Py_DECREF(Py_True);
1489
1490 return r;
1491}
1492
1493typedef struct
1494{
1495 hashitem_T *ht_array;
1496 long_u ht_used;
1497 hashtab_T *ht;
1498 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001499 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001500} dictiterinfo_T;
1501
1502 static PyObject *
1503DictionaryIterNext(dictiterinfo_T **dii)
1504{
1505 PyObject *r;
1506
1507 if (!(*dii)->todo)
1508 return NULL;
1509
1510 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1511 (*dii)->ht->ht_used != (*dii)->ht_used)
1512 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001513 PyErr_SET_STRING(PyExc_RuntimeError,
1514 "hashtab changed during iteration");
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001515 return NULL;
1516 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001517
Bram Moolenaara9922d62013-05-30 13:01:18 +02001518 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1519 ++((*dii)->hi);
1520
1521 --((*dii)->todo);
1522
1523 if (!(r = PyBytes_FromString((char *) (*dii)->hi->hi_key)))
1524 return NULL;
1525
1526 return r;
1527}
1528
1529 static PyObject *
1530DictionaryIter(DictionaryObject *self)
1531{
1532 dictiterinfo_T *dii;
1533 hashtab_T *ht;
1534
1535 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1536 {
1537 PyErr_NoMemory();
1538 return NULL;
1539 }
1540
1541 ht = &self->dict->dv_hashtab;
1542 dii->ht_array = ht->ht_array;
1543 dii->ht_used = ht->ht_used;
1544 dii->ht = ht;
1545 dii->hi = dii->ht_array;
1546 dii->todo = dii->ht_used;
1547
1548 return IterNew(dii,
1549 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1550 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001551}
1552
1553 static PyInt
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001554DictionaryAssItem(
1555 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001556{
1557 char_u *key;
1558 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001559 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001560 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001561 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001562
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001563 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001564 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001565 PyErr_SET_VIM("dict is locked");
Bram Moolenaardb913952012-06-29 12:54:53 +02001566 return -1;
1567 }
1568
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001569 if (!(key = StringToChars(keyObject, &todecref)))
1570 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001571
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001572 if (*key == NUL)
1573 {
1574 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001575 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001576 return -1;
1577 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001578
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001579 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001580
1581 if (valObject == NULL)
1582 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001583 hashitem_T *hi;
1584
Bram Moolenaardb913952012-06-29 12:54:53 +02001585 if (di == NULL)
1586 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001587 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001588 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001589 return -1;
1590 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001591 hi = hash_find(&dict->dv_hashtab, di->di_key);
1592 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001593 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001594 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001595 return 0;
1596 }
1597
1598 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001599 {
1600 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001601 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001602 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001603
1604 if (di == NULL)
1605 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001606 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001607 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001608 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001609 PyErr_NoMemory();
1610 return -1;
1611 }
1612 di->di_tv.v_lock = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001613 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001614
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001615 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001616 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001617 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001618 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001619 dictitem_free(di);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001620 PyErr_SET_VIM("failed to add key to dictionary");
Bram Moolenaardb913952012-06-29 12:54:53 +02001621 return -1;
1622 }
1623 }
1624 else
1625 clear_tv(&di->di_tv);
1626
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001627 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001628
1629 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001630 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001631 return 0;
1632}
1633
Bram Moolenaara9922d62013-05-30 13:01:18 +02001634typedef PyObject *(*hi_to_py)(hashitem_T *);
1635
Bram Moolenaardb913952012-06-29 12:54:53 +02001636 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001637DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001638{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001639 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001640 long_u todo = dict->dv_hashtab.ht_used;
1641 Py_ssize_t i = 0;
1642 PyObject *r;
1643 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001644 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001645
1646 r = PyList_New(todo);
1647 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1648 {
1649 if (!HASHITEM_EMPTY(hi))
1650 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001651 if (!(newObj = hiconvert(hi)))
1652 {
1653 Py_DECREF(r);
1654 return NULL;
1655 }
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02001656 PyList_SET_ITEM(r, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001657 --todo;
1658 ++i;
1659 }
1660 }
1661 return r;
1662}
1663
Bram Moolenaara9922d62013-05-30 13:01:18 +02001664 static PyObject *
1665dict_key(hashitem_T *hi)
1666{
1667 return PyBytes_FromString((char *)(hi->hi_key));
1668}
1669
1670 static PyObject *
1671DictionaryListKeys(DictionaryObject *self)
1672{
1673 return DictionaryListObjects(self, dict_key);
1674}
1675
1676 static PyObject *
1677dict_val(hashitem_T *hi)
1678{
1679 dictitem_T *di;
1680
1681 di = dict_lookup(hi);
1682 return ConvertToPyObject(&di->di_tv);
1683}
1684
1685 static PyObject *
1686DictionaryListValues(DictionaryObject *self)
1687{
1688 return DictionaryListObjects(self, dict_val);
1689}
1690
1691 static PyObject *
1692dict_item(hashitem_T *hi)
1693{
1694 PyObject *keyObject;
1695 PyObject *valObject;
1696 PyObject *r;
1697
1698 if (!(keyObject = dict_key(hi)))
1699 return NULL;
1700
1701 if (!(valObject = dict_val(hi)))
1702 {
1703 Py_DECREF(keyObject);
1704 return NULL;
1705 }
1706
1707 r = Py_BuildValue("(OO)", keyObject, valObject);
1708
1709 Py_DECREF(keyObject);
1710 Py_DECREF(valObject);
1711
1712 return r;
1713}
1714
1715 static PyObject *
1716DictionaryListItems(DictionaryObject *self)
1717{
1718 return DictionaryListObjects(self, dict_item);
1719}
1720
1721 static PyObject *
1722DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
1723{
1724 dict_T *dict = self->dict;
1725
1726 if (dict->dv_lock)
1727 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001728 PyErr_SET_VIM("dict is locked");
Bram Moolenaara9922d62013-05-30 13:01:18 +02001729 return NULL;
1730 }
1731
1732 if (kwargs)
1733 {
1734 typval_T tv;
1735
1736 if (ConvertFromPyMapping(kwargs, &tv) == -1)
1737 return NULL;
1738
1739 VimTryStart();
1740 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
1741 clear_tv(&tv);
1742 if (VimTryEnd())
1743 return NULL;
1744 }
1745 else
1746 {
1747 PyObject *object;
1748
Bram Moolenaar389a1792013-06-23 13:00:44 +02001749 if (!PyArg_ParseTuple(args, "O", &object))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001750 return NULL;
1751
1752 if (PyObject_HasAttrString(object, "keys"))
1753 return DictionaryUpdate(self, NULL, object);
1754 else
1755 {
1756 PyObject *iterator;
1757 PyObject *item;
1758
1759 if (!(iterator = PyObject_GetIter(object)))
1760 return NULL;
1761
1762 while ((item = PyIter_Next(iterator)))
1763 {
1764 PyObject *fast;
1765 PyObject *keyObject;
1766 PyObject *valObject;
1767 PyObject *todecref;
1768 char_u *key;
1769 dictitem_T *di;
1770
1771 if (!(fast = PySequence_Fast(item, "")))
1772 {
1773 Py_DECREF(iterator);
1774 Py_DECREF(item);
1775 return NULL;
1776 }
1777
1778 Py_DECREF(item);
1779
1780 if (PySequence_Fast_GET_SIZE(fast) != 2)
1781 {
1782 Py_DECREF(iterator);
1783 Py_DECREF(fast);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001784 PyErr_SET_STRING(PyExc_ValueError,
1785 "expected sequence element of size 2");
Bram Moolenaara9922d62013-05-30 13:01:18 +02001786 return NULL;
1787 }
1788
1789 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
1790
1791 if (!(key = StringToChars(keyObject, &todecref)))
1792 {
1793 Py_DECREF(iterator);
1794 Py_DECREF(fast);
1795 return NULL;
1796 }
1797
1798 di = dictitem_alloc(key);
1799
1800 Py_XDECREF(todecref);
1801
1802 if (di == NULL)
1803 {
1804 Py_DECREF(fast);
1805 Py_DECREF(iterator);
1806 PyErr_NoMemory();
1807 return NULL;
1808 }
1809 di->di_tv.v_lock = 0;
1810 di->di_tv.v_type = VAR_UNKNOWN;
1811
1812 valObject = PySequence_Fast_GET_ITEM(fast, 1);
1813
1814 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
1815 {
1816 Py_DECREF(iterator);
1817 Py_DECREF(fast);
1818 dictitem_free(di);
1819 return NULL;
1820 }
1821
1822 Py_DECREF(fast);
1823
1824 if (dict_add(dict, di) == FAIL)
1825 {
1826 Py_DECREF(iterator);
1827 dictitem_free(di);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001828 PyErr_SET_VIM("failed to add key to dictionary");
Bram Moolenaara9922d62013-05-30 13:01:18 +02001829 return NULL;
1830 }
1831 }
1832
1833 Py_DECREF(iterator);
1834
1835 /* Iterator may have finished due to an exception */
1836 if (PyErr_Occurred())
1837 return NULL;
1838 }
1839 }
1840 Py_INCREF(Py_None);
1841 return Py_None;
1842}
1843
1844 static PyObject *
1845DictionaryGet(DictionaryObject *self, PyObject *args)
1846{
1847 return _DictionaryItem(self, args,
1848 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
1849}
1850
1851 static PyObject *
1852DictionaryPop(DictionaryObject *self, PyObject *args)
1853{
1854 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
1855}
1856
1857 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02001858DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001859{
Bram Moolenaarde71b562013-06-02 17:41:54 +02001860 hashitem_T *hi;
1861 PyObject *r;
1862 PyObject *valObject;
1863 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001864
Bram Moolenaarde71b562013-06-02 17:41:54 +02001865 if (self->dict->dv_hashtab.ht_used == 0)
1866 {
1867 PyErr_SetNone(PyExc_KeyError);
1868 return NULL;
1869 }
1870
1871 hi = self->dict->dv_hashtab.ht_array;
1872 while (HASHITEM_EMPTY(hi))
1873 ++hi;
1874
1875 di = dict_lookup(hi);
1876
1877 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001878 return NULL;
1879
Bram Moolenaarde71b562013-06-02 17:41:54 +02001880 if (!(r = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
1881 {
1882 Py_DECREF(valObject);
1883 return NULL;
1884 }
1885
1886 hash_remove(&self->dict->dv_hashtab, hi);
1887 dictitem_free(di);
1888
1889 return r;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001890}
1891
1892 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02001893DictionaryHasKey(DictionaryObject *self, PyObject *keyObject)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001894{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001895 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
1896}
1897
1898static PySequenceMethods DictionaryAsSeq = {
1899 0, /* sq_length */
1900 0, /* sq_concat */
1901 0, /* sq_repeat */
1902 0, /* sq_item */
1903 0, /* sq_slice */
1904 0, /* sq_ass_item */
1905 0, /* sq_ass_slice */
1906 (objobjproc) DictionaryContains, /* sq_contains */
1907 0, /* sq_inplace_concat */
1908 0, /* sq_inplace_repeat */
1909};
1910
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02001911static PyMappingMethods DictionaryAsMapping = {
1912 (lenfunc) DictionaryLength,
1913 (binaryfunc) DictionaryItem,
1914 (objobjargproc) DictionaryAssItem,
1915};
1916
Bram Moolenaardb913952012-06-29 12:54:53 +02001917static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02001918 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02001919 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
1920 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
1921 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
1922 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
1923 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02001924 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001925 {"has_key", (PyCFunction)DictionaryHasKey, METH_O, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001926 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
1927 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02001928};
1929
1930static PyTypeObject ListType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001931static PySequenceMethods ListAsSeq;
1932static PyMappingMethods ListAsMapping;
Bram Moolenaardb913952012-06-29 12:54:53 +02001933
1934typedef struct
1935{
1936 PyObject_HEAD
1937 list_T *list;
1938 pylinkedlist_T ref;
1939} ListObject;
1940
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001941#define NEW_LIST(list) ListNew(&ListType, list)
1942
Bram Moolenaardb913952012-06-29 12:54:53 +02001943 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001944ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02001945{
1946 ListObject *self;
1947
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001948 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001949 if (self == NULL)
1950 return NULL;
1951 self->list = list;
1952 ++list->lv_refcount;
1953
1954 pyll_add((PyObject *)(self), &self->ref, &lastlist);
1955
1956 return (PyObject *)(self);
1957}
1958
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02001959 static list_T *
1960py_list_alloc()
1961{
1962 list_T *r;
1963
1964 if (!(r = list_alloc()))
1965 {
1966 PyErr_NoMemory();
1967 return NULL;
1968 }
1969 ++r->lv_refcount;
1970
1971 return r;
1972}
1973
1974 static int
1975list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
1976{
1977 PyObject *iterator;
1978 PyObject *item;
1979 listitem_T *li;
1980
1981 if (!(iterator = PyObject_GetIter(obj)))
1982 return -1;
1983
1984 while ((item = PyIter_Next(iterator)))
1985 {
1986 if (!(li = listitem_alloc()))
1987 {
1988 PyErr_NoMemory();
1989 Py_DECREF(item);
1990 Py_DECREF(iterator);
1991 return -1;
1992 }
1993 li->li_tv.v_lock = 0;
1994 li->li_tv.v_type = VAR_UNKNOWN;
1995
1996 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
1997 {
1998 Py_DECREF(item);
1999 Py_DECREF(iterator);
2000 listitem_free(li);
2001 return -1;
2002 }
2003
2004 Py_DECREF(item);
2005
2006 list_append(l, li);
2007 }
2008
2009 Py_DECREF(iterator);
2010
2011 /* Iterator may have finished due to an exception */
2012 if (PyErr_Occurred())
2013 return -1;
2014
2015 return 0;
2016}
2017
2018 static PyObject *
2019ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2020{
2021 list_T *list;
2022 PyObject *obj = NULL;
2023
2024 if (kwargs)
2025 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002026 PyErr_SET_STRING(PyExc_TypeError,
2027 "list constructor does not accept keyword arguments");
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002028 return NULL;
2029 }
2030
2031 if (!PyArg_ParseTuple(args, "|O", &obj))
2032 return NULL;
2033
2034 if (!(list = py_list_alloc()))
2035 return NULL;
2036
2037 if (obj)
2038 {
2039 PyObject *lookup_dict;
2040
2041 if (!(lookup_dict = PyDict_New()))
2042 {
2043 list_unref(list);
2044 return NULL;
2045 }
2046
2047 if (list_py_concat(list, obj, lookup_dict) == -1)
2048 {
2049 Py_DECREF(lookup_dict);
2050 list_unref(list);
2051 return NULL;
2052 }
2053
2054 Py_DECREF(lookup_dict);
2055 }
2056
2057 return ListNew(subtype, list);
2058}
2059
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002060 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002061ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002062{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002063 pyll_remove(&self->ref, &lastlist);
2064 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002065
2066 DESTRUCTOR_FINISH(self);
2067}
2068
Bram Moolenaardb913952012-06-29 12:54:53 +02002069 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002070ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002071{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002072 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002073}
2074
2075 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002076ListItem(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002077{
2078 listitem_T *li;
2079
Bram Moolenaard6e39182013-05-21 18:30:34 +02002080 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002081 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002082 PyErr_SET_STRING(PyExc_IndexError, "list index out of range");
Bram Moolenaardb913952012-06-29 12:54:53 +02002083 return NULL;
2084 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002085 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002086 if (li == NULL)
2087 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002088 PyErr_SET_VIM("internal error: failed to get vim list item");
Bram Moolenaardb913952012-06-29 12:54:53 +02002089 return NULL;
2090 }
2091 return ConvertToPyObject(&li->li_tv);
2092}
2093
2094#define PROC_RANGE \
2095 if (last < 0) {\
2096 if (last < -size) \
2097 last = 0; \
2098 else \
2099 last += size; \
2100 } \
2101 if (first < 0) \
2102 first = 0; \
2103 if (first > size) \
2104 first = size; \
2105 if (last > size) \
2106 last = size;
2107
2108 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002109ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last)
Bram Moolenaardb913952012-06-29 12:54:53 +02002110{
2111 PyInt i;
2112 PyInt size = ListLength(self);
2113 PyInt n;
2114 PyObject *list;
2115 int reversed = 0;
2116
2117 PROC_RANGE
2118 if (first >= last)
2119 first = last;
2120
2121 n = last-first;
2122 list = PyList_New(n);
2123 if (list == NULL)
2124 return NULL;
2125
2126 for (i = 0; i < n; ++i)
2127 {
Bram Moolenaar24b11fb2013-04-05 19:32:36 +02002128 PyObject *item = ListItem(self, first + i);
Bram Moolenaardb913952012-06-29 12:54:53 +02002129 if (item == NULL)
2130 {
2131 Py_DECREF(list);
2132 return NULL;
2133 }
2134
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02002135 PyList_SET_ITEM(list, ((reversed)?(n-i-1):(i)), item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002136 }
2137
2138 return list;
2139}
2140
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002141typedef struct
2142{
2143 listwatch_T lw;
2144 list_T *list;
2145} listiterinfo_T;
2146
2147 static void
2148ListIterDestruct(listiterinfo_T *lii)
2149{
2150 list_rem_watch(lii->list, &lii->lw);
2151 PyMem_Free(lii);
2152}
2153
2154 static PyObject *
2155ListIterNext(listiterinfo_T **lii)
2156{
2157 PyObject *r;
2158
2159 if (!((*lii)->lw.lw_item))
2160 return NULL;
2161
2162 if (!(r = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
2163 return NULL;
2164
2165 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2166
2167 return r;
2168}
2169
2170 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002171ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002172{
2173 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002174 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002175
2176 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2177 {
2178 PyErr_NoMemory();
2179 return NULL;
2180 }
2181
2182 list_add_watch(l, &lii->lw);
2183 lii->lw.lw_item = l->lv_first;
2184 lii->list = l;
2185
2186 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002187 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2188 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002189}
2190
Bram Moolenaardb913952012-06-29 12:54:53 +02002191 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002192ListAssItem(ListObject *self, Py_ssize_t index, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002193{
2194 typval_T tv;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002195 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002196 listitem_T *li;
2197 Py_ssize_t length = ListLength(self);
2198
2199 if (l->lv_lock)
2200 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002201 PyErr_SET_VIM("list is locked");
Bram Moolenaardb913952012-06-29 12:54:53 +02002202 return -1;
2203 }
2204 if (index>length || (index==length && obj==NULL))
2205 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002206 PyErr_SET_STRING(PyExc_IndexError, "list index out of range");
Bram Moolenaardb913952012-06-29 12:54:53 +02002207 return -1;
2208 }
2209
2210 if (obj == NULL)
2211 {
2212 li = list_find(l, (long) index);
2213 list_remove(l, li, li);
2214 clear_tv(&li->li_tv);
2215 vim_free(li);
2216 return 0;
2217 }
2218
2219 if (ConvertFromPyObject(obj, &tv) == -1)
2220 return -1;
2221
2222 if (index == length)
2223 {
2224 if (list_append_tv(l, &tv) == FAIL)
2225 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002226 clear_tv(&tv);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002227 PyErr_SET_VIM("failed to add item to list");
Bram Moolenaardb913952012-06-29 12:54:53 +02002228 return -1;
2229 }
2230 }
2231 else
2232 {
2233 li = list_find(l, (long) index);
2234 clear_tv(&li->li_tv);
2235 copy_tv(&tv, &li->li_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002236 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002237 }
2238 return 0;
2239}
2240
2241 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002242ListAssSlice(ListObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002243{
2244 PyInt size = ListLength(self);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002245 PyObject *iterator;
2246 PyObject *item;
Bram Moolenaardb913952012-06-29 12:54:53 +02002247 listitem_T *li;
2248 listitem_T *next;
2249 typval_T v;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002250 list_T *l = self->list;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002251 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002252
2253 if (l->lv_lock)
2254 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002255 PyErr_SET_VIM("list is locked");
Bram Moolenaardb913952012-06-29 12:54:53 +02002256 return -1;
2257 }
2258
2259 PROC_RANGE
2260
2261 if (first == size)
2262 li = NULL;
2263 else
2264 {
2265 li = list_find(l, (long) first);
2266 if (li == NULL)
2267 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002268 PyErr_SET_VIM("internal error: no vim list item");
Bram Moolenaardb913952012-06-29 12:54:53 +02002269 return -1;
2270 }
2271 if (last > first)
2272 {
2273 i = last - first;
2274 while (i-- && li != NULL)
2275 {
2276 next = li->li_next;
2277 listitem_remove(l, li);
2278 li = next;
2279 }
2280 }
2281 }
2282
2283 if (obj == NULL)
2284 return 0;
2285
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002286 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002287 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02002288
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002289 while ((item = PyIter_Next(iterator)))
Bram Moolenaardb913952012-06-29 12:54:53 +02002290 {
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002291 if (ConvertFromPyObject(item, &v) == -1)
2292 {
2293 Py_DECREF(iterator);
2294 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002295 return -1;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002296 }
2297 Py_DECREF(item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002298 if (list_insert_tv(l, &v, li) == FAIL)
2299 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002300 clear_tv(&v);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002301 PyErr_SET_VIM("internal error: failed to add item to list");
Bram Moolenaardb913952012-06-29 12:54:53 +02002302 return -1;
2303 }
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002304 clear_tv(&v);
Bram Moolenaardb913952012-06-29 12:54:53 +02002305 }
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002306 Py_DECREF(iterator);
Bram Moolenaardb913952012-06-29 12:54:53 +02002307 return 0;
2308}
2309
2310 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002311ListConcatInPlace(ListObject *self, PyObject *obj)
Bram Moolenaardb913952012-06-29 12:54:53 +02002312{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002313 list_T *l = self->list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002314 PyObject *lookup_dict;
2315
2316 if (l->lv_lock)
2317 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002318 PyErr_SET_VIM("list is locked");
Bram Moolenaardb913952012-06-29 12:54:53 +02002319 return NULL;
2320 }
2321
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02002322 if (!(lookup_dict = PyDict_New()))
2323 return NULL;
2324
Bram Moolenaardb913952012-06-29 12:54:53 +02002325 if (list_py_concat(l, obj, lookup_dict) == -1)
2326 {
2327 Py_DECREF(lookup_dict);
2328 return NULL;
2329 }
2330 Py_DECREF(lookup_dict);
2331
2332 Py_INCREF(self);
Bram Moolenaard6e39182013-05-21 18:30:34 +02002333 return (PyObject *)(self);
Bram Moolenaardb913952012-06-29 12:54:53 +02002334}
2335
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002336static char *ListAttrs[] = {
2337 "locked",
2338 NULL
2339};
2340
2341 static PyObject *
2342ListDir(PyObject *self)
2343{
2344 return ObjectDir(self, ListAttrs);
2345}
2346
Bram Moolenaar66b79852012-09-21 14:00:35 +02002347 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002348ListSetattr(ListObject *self, char *name, PyObject *val)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002349{
2350 if (val == NULL)
2351 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002352 PyErr_SET_STRING(PyExc_AttributeError,
2353 "cannot delete vim.List attributes");
Bram Moolenaar66b79852012-09-21 14:00:35 +02002354 return -1;
2355 }
2356
2357 if (strcmp(name, "locked") == 0)
2358 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002359 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002360 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002361 PyErr_SET_STRING(PyExc_TypeError, "cannot modify fixed list");
Bram Moolenaar66b79852012-09-21 14:00:35 +02002362 return -1;
2363 }
2364 else
2365 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002366 int istrue = PyObject_IsTrue(val);
2367 if (istrue == -1)
2368 return -1;
2369 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002370 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002371 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002372 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002373 }
2374 return 0;
2375 }
2376 else
2377 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002378 PyErr_SET_STRING(PyExc_AttributeError, "cannot set this attribute");
Bram Moolenaar66b79852012-09-21 14:00:35 +02002379 return -1;
2380 }
2381}
2382
Bram Moolenaardb913952012-06-29 12:54:53 +02002383static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002384 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2385 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2386 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002387};
2388
2389typedef struct
2390{
2391 PyObject_HEAD
2392 char_u *name;
2393} FunctionObject;
2394
2395static PyTypeObject FunctionType;
2396
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002397#define NEW_FUNCTION(name) FunctionNew(&FunctionType, name)
2398
Bram Moolenaardb913952012-06-29 12:54:53 +02002399 static PyObject *
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002400FunctionNew(PyTypeObject *subtype, char_u *name)
Bram Moolenaardb913952012-06-29 12:54:53 +02002401{
2402 FunctionObject *self;
2403
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002404 self = (FunctionObject *) subtype->tp_alloc(subtype, 0);
2405
Bram Moolenaardb913952012-06-29 12:54:53 +02002406 if (self == NULL)
2407 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002408
2409 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002410 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002411 if (!translated_function_exists(name))
2412 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002413 PyErr_SET_STRING(PyExc_ValueError,
2414 "unnamed function does not exist");
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002415 return NULL;
2416 }
2417 self->name = vim_strsave(name);
2418 func_ref(self->name);
2419 }
2420 else
Bram Moolenaar018acca2013-05-30 13:37:28 +02002421 if ((self->name = get_expanded_name(name,
2422 vim_strchr(name, AUTOLOAD_CHAR) == NULL))
2423 == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002424 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002425 PyErr_SET_STRING(PyExc_ValueError, "function does not exist");
Bram Moolenaar018acca2013-05-30 13:37:28 +02002426 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002427 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002428
2429 return (PyObject *)(self);
2430}
2431
2432 static PyObject *
2433FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2434{
2435 PyObject *self;
2436 char_u *name;
2437
2438 if (kwargs)
2439 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002440 PyErr_SET_STRING(PyExc_TypeError,
2441 "function constructor does not accept keyword arguments");
Bram Moolenaardb913952012-06-29 12:54:53 +02002442 return NULL;
2443 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002444
Bram Moolenaar389a1792013-06-23 13:00:44 +02002445 if (!PyArg_ParseTuple(args, "et", "ascii", &name))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002446 return NULL;
2447
2448 self = FunctionNew(subtype, name);
2449
Bram Moolenaar389a1792013-06-23 13:00:44 +02002450 PyMem_Free(name);
2451
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002452 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02002453}
2454
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002455 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002456FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002457{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002458 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002459 vim_free(self->name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002460
2461 DESTRUCTOR_FINISH(self);
2462}
2463
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002464static char *FunctionAttrs[] = {
2465 "softspace",
2466 NULL
2467};
2468
2469 static PyObject *
2470FunctionDir(PyObject *self)
2471{
2472 return ObjectDir(self, FunctionAttrs);
2473}
2474
Bram Moolenaardb913952012-06-29 12:54:53 +02002475 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002476FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02002477{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002478 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02002479 typval_T args;
2480 typval_T selfdicttv;
2481 typval_T rettv;
2482 dict_T *selfdict = NULL;
2483 PyObject *selfdictObject;
2484 PyObject *result;
2485 int error;
2486
2487 if (ConvertFromPyObject(argsObject, &args) == -1)
2488 return NULL;
2489
2490 if (kwargs != NULL)
2491 {
2492 selfdictObject = PyDict_GetItemString(kwargs, "self");
2493 if (selfdictObject != NULL)
2494 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02002495 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002496 {
2497 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02002498 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002499 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002500 selfdict = selfdicttv.vval.v_dict;
2501 }
2502 }
2503
Bram Moolenaar71700b82013-05-15 17:49:05 +02002504 Py_BEGIN_ALLOW_THREADS
2505 Python_Lock_Vim();
2506
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002507 VimTryStart();
Bram Moolenaardb913952012-06-29 12:54:53 +02002508 error = func_call(name, &args, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02002509
2510 Python_Release_Vim();
2511 Py_END_ALLOW_THREADS
2512
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002513 if (VimTryEnd())
2514 result = NULL;
2515 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02002516 {
2517 result = NULL;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002518 PyErr_SET_VIM("failed to run function");
Bram Moolenaardb913952012-06-29 12:54:53 +02002519 }
2520 else
2521 result = ConvertToPyObject(&rettv);
2522
Bram Moolenaardb913952012-06-29 12:54:53 +02002523 clear_tv(&args);
2524 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002525 if (selfdict != NULL)
2526 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02002527
2528 return result;
2529}
2530
Bram Moolenaara5b725c2013-05-30 12:43:54 +02002531 static PyObject *
2532FunctionRepr(FunctionObject *self)
2533{
2534 return PyString_FromFormat("<vim.Function '%s'>", self->name);
2535}
2536
Bram Moolenaardb913952012-06-29 12:54:53 +02002537static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002538 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
2539 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002540};
2541
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002542/*
2543 * Options object
2544 */
2545
2546static PyTypeObject OptionsType;
2547
2548typedef int (*checkfun)(void *);
2549
2550typedef struct
2551{
2552 PyObject_HEAD
2553 int opt_type;
2554 void *from;
2555 checkfun Check;
2556 PyObject *fromObj;
2557} OptionsObject;
2558
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002559 static int
2560dummy_check(void *arg UNUSED)
2561{
2562 return 0;
2563}
2564
2565 static PyObject *
2566OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
2567{
2568 OptionsObject *self;
2569
Bram Moolenaar774267b2013-05-21 20:51:59 +02002570 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002571 if (self == NULL)
2572 return NULL;
2573
2574 self->opt_type = opt_type;
2575 self->from = from;
2576 self->Check = Check;
2577 self->fromObj = fromObj;
2578 if (fromObj)
2579 Py_INCREF(fromObj);
2580
2581 return (PyObject *)(self);
2582}
2583
2584 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002585OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002586{
Bram Moolenaar774267b2013-05-21 20:51:59 +02002587 PyObject_GC_UnTrack((void *)(self));
2588 Py_XDECREF(self->fromObj);
2589 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002590}
2591
2592 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002593OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002594{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002595 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002596 return 0;
2597}
2598
2599 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002600OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002601{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002602 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002603 return 0;
2604}
2605
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002606 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002607OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002608{
2609 char_u *key;
2610 int flags;
2611 long numval;
2612 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002613 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002614
Bram Moolenaard6e39182013-05-21 18:30:34 +02002615 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002616 return NULL;
2617
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002618 if (!(key = StringToChars(keyObject, &todecref)))
2619 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002620
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002621 if (*key == NUL)
2622 {
2623 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002624 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002625 return NULL;
2626 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002627
2628 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002629 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002630
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002631 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002632
2633 if (flags == 0)
2634 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002635 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002636 return NULL;
2637 }
2638
2639 if (flags & SOPT_UNSET)
2640 {
2641 Py_INCREF(Py_None);
2642 return Py_None;
2643 }
2644 else if (flags & SOPT_BOOL)
2645 {
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002646 PyObject *r;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002647 r = numval ? Py_True : Py_False;
2648 Py_INCREF(r);
2649 return r;
2650 }
2651 else if (flags & SOPT_NUM)
2652 return PyInt_FromLong(numval);
2653 else if (flags & SOPT_STRING)
2654 {
2655 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002656 {
2657 PyObject *r = PyBytes_FromString((char *) stringval);
2658 vim_free(stringval);
2659 return r;
2660 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002661 else
2662 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002663 PyErr_SET_STRING(PyExc_RuntimeError,
2664 "unable to get option value");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002665 return NULL;
2666 }
2667 }
2668 else
2669 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002670 PyErr_SET_VIM("internal error: unknown option type");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002671 return NULL;
2672 }
2673}
2674
2675 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002676set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002677{
2678 char_u *errmsg;
2679
2680 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
2681 {
2682 if (VimTryEnd())
2683 return FAIL;
2684 PyErr_SetVim((char *)errmsg);
2685 return FAIL;
2686 }
2687 return OK;
2688}
2689
2690 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02002691set_option_value_for(
2692 char_u *key,
2693 int numval,
2694 char_u *stringval,
2695 int opt_flags,
2696 int opt_type,
2697 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002698{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02002699 win_T *save_curwin = NULL;
2700 tabpage_T *save_curtab = NULL;
2701 buf_T *save_curbuf = NULL;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002702 int r = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002703
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002704 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002705 switch (opt_type)
2706 {
2707 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002708 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02002709 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002710 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002711 if (VimTryEnd())
2712 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002713 PyErr_SET_VIM("problem while switching windows");
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002714 return -1;
2715 }
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002716 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaard6949742013-06-16 14:18:28 +02002717 restore_win(save_curwin, save_curtab, FALSE);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002718 if (r == FAIL)
2719 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002720 break;
2721 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02002722 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002723 r = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar105bc352013-05-17 16:03:57 +02002724 restore_buffer(save_curbuf);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002725 if (r == FAIL)
2726 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002727 break;
2728 case SREQ_GLOBAL:
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002729 r = set_option_value_err(key, numval, stringval, opt_flags);
2730 if (r == FAIL)
2731 return -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002732 break;
2733 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02002734 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002735}
2736
2737 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002738OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002739{
2740 char_u *key;
2741 int flags;
2742 int opt_flags;
2743 int r = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002744 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002745
Bram Moolenaard6e39182013-05-21 18:30:34 +02002746 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002747 return -1;
2748
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002749 if (!(key = StringToChars(keyObject, &todecref)))
2750 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002751
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002752 if (*key == NUL)
2753 {
2754 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02002755 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002756 return -1;
2757 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002758
2759 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002760 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002761
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002762 if (flags == 0)
2763 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02002764 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002765 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002766 return -1;
2767 }
2768
2769 if (valObject == NULL)
2770 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002771 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002772 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002773 PyErr_SET_STRING(PyExc_ValueError, "unable to unset global option");
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002774 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002775 return -1;
2776 }
2777 else if (!(flags & SOPT_GLOBAL))
2778 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002779 PyErr_SET_STRING(PyExc_ValueError, "unable to unset option "
2780 "without global value");
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002781 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002782 return -1;
2783 }
2784 else
2785 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002786 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002787 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002788 return 0;
2789 }
2790 }
2791
Bram Moolenaard6e39182013-05-21 18:30:34 +02002792 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002793
2794 if (flags & SOPT_BOOL)
2795 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02002796 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02002797
Bram Moolenaarb983f752013-05-15 16:11:50 +02002798 if (istrue == -1)
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002799 r = -1;
2800 else
2801 r = set_option_value_for(key, istrue, NULL,
2802 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002803 }
2804 else if (flags & SOPT_NUM)
2805 {
2806 int val;
2807
2808#if PY_MAJOR_VERSION < 3
2809 if (PyInt_Check(valObject))
2810 val = PyInt_AsLong(valObject);
2811 else
2812#endif
2813 if (PyLong_Check(valObject))
2814 val = PyLong_AsLong(valObject);
2815 else
2816 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002817 PyErr_SET_STRING(PyExc_TypeError, "object must be integer");
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002818 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002819 return -1;
2820 }
2821
2822 r = set_option_value_for(key, val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02002823 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002824 }
2825 else
2826 {
2827 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002828 PyObject *todecref;
2829
2830 if ((val = StringToChars(valObject, &todecref)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002831 r = set_option_value_for(key, 0, val, opt_flags,
2832 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002833 else
Bram Moolenaare9ba5162013-05-29 22:02:22 +02002834 r = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002835 }
2836
Bram Moolenaar35eacd72013-05-30 22:06:33 +02002837 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02002838
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002839 return r;
2840}
2841
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02002842static PyMappingMethods OptionsAsMapping = {
2843 (lenfunc) NULL,
2844 (binaryfunc) OptionsItem,
2845 (objobjargproc) OptionsAssItem,
2846};
2847
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002848/* Tabpage object
2849 */
2850
2851typedef struct
2852{
2853 PyObject_HEAD
2854 tabpage_T *tab;
2855} TabPageObject;
2856
2857static PyObject *WinListNew(TabPageObject *tabObject);
2858
2859static PyTypeObject TabPageType;
2860
2861 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02002862CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002863{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002864 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002865 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002866 PyErr_SET_VIM("attempt to refer to deleted tab page");
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002867 return -1;
2868 }
2869
2870 return 0;
2871}
2872
2873 static PyObject *
2874TabPageNew(tabpage_T *tab)
2875{
2876 TabPageObject *self;
2877
2878 if (TAB_PYTHON_REF(tab))
2879 {
2880 self = TAB_PYTHON_REF(tab);
2881 Py_INCREF(self);
2882 }
2883 else
2884 {
2885 self = PyObject_NEW(TabPageObject, &TabPageType);
2886 if (self == NULL)
2887 return NULL;
2888 self->tab = tab;
2889 TAB_PYTHON_REF(tab) = self;
2890 }
2891
2892 return (PyObject *)(self);
2893}
2894
2895 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002896TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002897{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002898 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
2899 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002900
2901 DESTRUCTOR_FINISH(self);
2902}
2903
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002904static char *TabPageAttrs[] = {
2905 "windows", "number", "vars", "window", "valid",
2906 NULL
2907};
2908
2909 static PyObject *
2910TabPageDir(PyObject *self)
2911{
2912 return ObjectDir(self, TabPageAttrs);
2913}
2914
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002915 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02002916TabPageAttrValid(TabPageObject *self, char *name)
2917{
2918 PyObject *r;
2919
2920 if (strcmp(name, "valid") != 0)
2921 return NULL;
2922
2923 r = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
2924 Py_INCREF(r);
2925 return r;
2926}
2927
2928 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002929TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002930{
2931 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002932 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002933 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002934 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002935 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002936 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002937 else if (strcmp(name, "window") == 0)
2938 {
2939 /* For current tab window.c does not bother to set or update tp_curwin
2940 */
Bram Moolenaard6e39182013-05-21 18:30:34 +02002941 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02002942 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002943 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002944 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002945 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002946 else if (strcmp(name, "__members__") == 0)
2947 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002948 return NULL;
2949}
2950
2951 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002952TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002953{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002954 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002955 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002956 else
2957 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002958 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002959
2960 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002961 return PyString_FromFormat("<tabpage object (unknown) at %p>",
2962 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002963 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02002964 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002965 }
2966}
2967
2968static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002969 /* name, function, calling, documentation */
2970 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
2971 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02002972};
2973
2974/*
2975 * Window list object
2976 */
2977
2978static PyTypeObject TabListType;
2979static PySequenceMethods TabListAsSeq;
2980
2981typedef struct
2982{
2983 PyObject_HEAD
2984} TabListObject;
2985
2986 static PyInt
2987TabListLength(PyObject *self UNUSED)
2988{
2989 tabpage_T *tp = first_tabpage;
2990 PyInt n = 0;
2991
2992 while (tp != NULL)
2993 {
2994 ++n;
2995 tp = tp->tp_next;
2996 }
2997
2998 return n;
2999}
3000
3001 static PyObject *
3002TabListItem(PyObject *self UNUSED, PyInt n)
3003{
3004 tabpage_T *tp;
3005
3006 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
3007 if (n == 0)
3008 return TabPageNew(tp);
3009
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003010 PyErr_SET_STRING(PyExc_IndexError, "no such tab page");
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003011 return NULL;
3012}
3013
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +02003014/*
3015 * Window object
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003016 */
3017
3018typedef struct
3019{
3020 PyObject_HEAD
3021 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003022 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003023} WindowObject;
3024
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003025static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003026
3027 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003028CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003029{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003030 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003031 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003032 PyErr_SET_VIM("attempt to refer to deleted window");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003033 return -1;
3034 }
3035
3036 return 0;
3037}
3038
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003039 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003040WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02003041{
3042 /* We need to handle deletion of windows underneath us.
3043 * If we add a "w_python*_ref" field to the win_T structure,
3044 * then we can get at it in win_free() in vim. We then
3045 * need to create only ONE Python object per window - if
3046 * we try to create a second, just INCREF the existing one
3047 * and return it. The (single) Python object referring to
3048 * the window is stored in "w_python*_ref".
3049 * On a win_free() we set the Python object's win_T* field
3050 * to an invalid value. We trap all uses of a window
3051 * object, and reject them if the win_T* field is invalid.
3052 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003053 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003054 * w_python_ref and w_python3_ref fields respectively.
3055 */
3056
3057 WindowObject *self;
3058
3059 if (WIN_PYTHON_REF(win))
3060 {
3061 self = WIN_PYTHON_REF(win);
3062 Py_INCREF(self);
3063 }
3064 else
3065 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02003066 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02003067 if (self == NULL)
3068 return NULL;
3069 self->win = win;
3070 WIN_PYTHON_REF(win) = self;
3071 }
3072
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003073 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
3074
Bram Moolenaar971db462013-05-12 18:44:48 +02003075 return (PyObject *)(self);
3076}
3077
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003078 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003079WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003080{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003081 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02003082 if (self->win && self->win != INVALID_WINDOW_VALUE)
3083 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003084 Py_XDECREF(((PyObject *)(self->tabObject)));
3085 PyObject_GC_Del((void *)(self));
3086}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003087
Bram Moolenaar774267b2013-05-21 20:51:59 +02003088 static int
3089WindowTraverse(WindowObject *self, visitproc visit, void *arg)
3090{
3091 Py_VISIT(((PyObject *)(self->tabObject)));
3092 return 0;
3093}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003094
Bram Moolenaar774267b2013-05-21 20:51:59 +02003095 static int
3096WindowClear(WindowObject *self)
3097{
3098 Py_CLEAR(self->tabObject);
3099 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003100}
3101
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003102 static win_T *
3103get_firstwin(TabPageObject *tabObject)
3104{
3105 if (tabObject)
3106 {
3107 if (CheckTabPage(tabObject))
3108 return NULL;
3109 /* For current tab window.c does not bother to set or update tp_firstwin
3110 */
3111 else if (tabObject->tab == curtab)
3112 return firstwin;
3113 else
3114 return tabObject->tab->tp_firstwin;
3115 }
3116 else
3117 return firstwin;
3118}
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003119static char *WindowAttrs[] = {
3120 "buffer", "cursor", "height", "vars", "options", "number", "row", "col",
3121 "tabpage", "valid",
3122 NULL
3123};
3124
3125 static PyObject *
3126WindowDir(PyObject *self)
3127{
3128 return ObjectDir(self, WindowAttrs);
3129}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003130
Bram Moolenaar971db462013-05-12 18:44:48 +02003131 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003132WindowAttrValid(WindowObject *self, char *name)
3133{
3134 PyObject *r;
3135
3136 if (strcmp(name, "valid") != 0)
3137 return NULL;
3138
3139 r = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
3140 Py_INCREF(r);
3141 return r;
3142}
3143
3144 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003145WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003146{
3147 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003148 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003149 else if (strcmp(name, "cursor") == 0)
3150 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003151 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003152
3153 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
3154 }
3155 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003156 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003157#ifdef FEAT_WINDOWS
3158 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003159 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003160#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003161#ifdef FEAT_VERTSPLIT
3162 else if (strcmp(name, "width") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003163 return PyLong_FromLong((long)(W_WIDTH(self->win)));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003164 else if (strcmp(name, "col") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003165 return PyLong_FromLong((long)(W_WINCOL(self->win)));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003166#endif
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02003167 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003168 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003169 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003170 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
3171 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02003172 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003173 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003174 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003175 return NULL;
3176 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003177 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003178 }
3179 else if (strcmp(name, "tabpage") == 0)
3180 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003181 Py_INCREF(self->tabObject);
3182 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003183 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003184 else if (strcmp(name, "__members__") == 0)
3185 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003186 else
3187 return NULL;
3188}
3189
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003190 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003191WindowSetattr(WindowObject *self, char *name, PyObject *val)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003192{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003193 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003194 return -1;
3195
3196 if (strcmp(name, "buffer") == 0)
3197 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003198 PyErr_SET_STRING(PyExc_TypeError, "readonly attribute");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003199 return -1;
3200 }
3201 else if (strcmp(name, "cursor") == 0)
3202 {
3203 long lnum;
3204 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003205
3206 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
3207 return -1;
3208
Bram Moolenaard6e39182013-05-21 18:30:34 +02003209 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003210 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003211 PyErr_SET_VIM("cursor position outside buffer");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003212 return -1;
3213 }
3214
3215 /* Check for keyboard interrupts */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003216 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003217 return -1;
3218
Bram Moolenaard6e39182013-05-21 18:30:34 +02003219 self->win->w_cursor.lnum = lnum;
3220 self->win->w_cursor.col = col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003221#ifdef FEAT_VIRTUALEDIT
Bram Moolenaard6e39182013-05-21 18:30:34 +02003222 self->win->w_cursor.coladd = 0;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003223#endif
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003224 /* When column is out of range silently correct it. */
Bram Moolenaard6e39182013-05-21 18:30:34 +02003225 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003226
Bram Moolenaar03a807a2011-07-07 15:08:58 +02003227 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003228 return 0;
3229 }
3230 else if (strcmp(name, "height") == 0)
3231 {
3232 int height;
3233 win_T *savewin;
3234
3235 if (!PyArg_Parse(val, "i", &height))
3236 return -1;
3237
3238#ifdef FEAT_GUI
3239 need_mouse_correct = TRUE;
3240#endif
3241 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003242 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003243
3244 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003245 win_setheight(height);
3246 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003247 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003248 return -1;
3249
3250 return 0;
3251 }
3252#ifdef FEAT_VERTSPLIT
3253 else if (strcmp(name, "width") == 0)
3254 {
3255 int width;
3256 win_T *savewin;
3257
3258 if (!PyArg_Parse(val, "i", &width))
3259 return -1;
3260
3261#ifdef FEAT_GUI
3262 need_mouse_correct = TRUE;
3263#endif
3264 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003265 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003266
3267 VimTryStart();
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003268 win_setwidth(width);
3269 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003270 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003271 return -1;
3272
3273 return 0;
3274 }
3275#endif
3276 else
3277 {
3278 PyErr_SetString(PyExc_AttributeError, name);
3279 return -1;
3280 }
3281}
3282
3283 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003284WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003285{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003286 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003287 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003288 else
3289 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003290 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003291
Bram Moolenaar6d216452013-05-12 19:00:41 +02003292 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003293 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003294 (self));
3295 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003296 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003297 }
3298}
3299
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003300static struct PyMethodDef WindowMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003301 /* name, function, calling, documentation */
3302 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
3303 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003304};
3305
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003306/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003307 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003308 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003309
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003310static PyTypeObject WinListType;
3311static PySequenceMethods WinListAsSeq;
3312
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003313typedef struct
3314{
3315 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003316 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003317} WinListObject;
3318
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003319 static PyObject *
3320WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003321{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003322 WinListObject *self;
3323
3324 self = PyObject_NEW(WinListObject, &WinListType);
3325 self->tabObject = tabObject;
3326 Py_INCREF(tabObject);
3327
3328 return (PyObject *)(self);
3329}
3330
3331 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003332WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003333{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003334 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003335
3336 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02003337 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003338 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02003339 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003340
3341 DESTRUCTOR_FINISH(self);
3342}
3343
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003344 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02003345WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003346{
3347 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003348 PyInt n = 0;
3349
Bram Moolenaard6e39182013-05-21 18:30:34 +02003350 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003351 return -1;
3352
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003353 while (w != NULL)
3354 {
3355 ++n;
3356 w = W_NEXT(w);
3357 }
3358
3359 return n;
3360}
3361
3362 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003363WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003364{
3365 win_T *w;
3366
Bram Moolenaard6e39182013-05-21 18:30:34 +02003367 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003368 return NULL;
3369
3370 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003371 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003372 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003373
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003374 PyErr_SET_STRING(PyExc_IndexError, "no such window");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003375 return NULL;
3376}
3377
3378/* Convert a Python string into a Vim line.
3379 *
3380 * The result is in allocated memory. All internal nulls are replaced by
3381 * newline characters. It is an error for the string to contain newline
3382 * characters.
3383 *
3384 * On errors, the Python exception data is set, and NULL is returned.
3385 */
3386 static char *
3387StringToLine(PyObject *obj)
3388{
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003389 char *str;
3390 char *save;
3391 PyObject *bytes = NULL;
3392 Py_ssize_t len;
3393 PyInt i;
3394 char *p;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003395
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003396 if (PyBytes_Check(obj))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003397 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003398 if (PyBytes_AsStringAndSize(obj, &str, &len) == -1
3399 || str == NULL)
3400 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003401 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003402 else if (PyUnicode_Check(obj))
3403 {
3404 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL)))
3405 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003406
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003407 if(PyBytes_AsStringAndSize(bytes, &str, &len) == -1
3408 || str == NULL)
3409 {
3410 Py_DECREF(bytes);
3411 return NULL;
3412 }
3413 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003414
3415 /*
3416 * Error checking: String must not contain newlines, as we
3417 * are replacing a single line, and we must replace it with
3418 * a single line.
3419 * A trailing newline is removed, so that append(f.readlines()) works.
3420 */
3421 p = memchr(str, '\n', len);
3422 if (p != NULL)
3423 {
3424 if (p == str + len - 1)
3425 --len;
3426 else
3427 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003428 PyErr_SET_VIM("string cannot contain newlines");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003429 return NULL;
3430 }
3431 }
3432
3433 /* Create a copy of the string, with internal nulls replaced by
3434 * newline characters, as is the vim convention.
3435 */
3436 save = (char *)alloc((unsigned)(len+1));
3437 if (save == NULL)
3438 {
3439 PyErr_NoMemory();
3440 return NULL;
3441 }
3442
3443 for (i = 0; i < len; ++i)
3444 {
3445 if (str[i] == '\0')
3446 save[i] = '\n';
3447 else
3448 save[i] = str[i];
3449 }
3450
3451 save[i] = '\0';
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003452 Py_XDECREF(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003453
3454 return save;
3455}
3456
3457/* Get a line from the specified buffer. The line number is
3458 * in Vim format (1-based). The line is returned as a Python
3459 * string object.
3460 */
3461 static PyObject *
3462GetBufferLine(buf_T *buf, PyInt n)
3463{
3464 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
3465}
3466
3467
3468/* Get a list of lines from the specified buffer. The line numbers
3469 * are in Vim format (1-based). The range is from lo up to, but not
3470 * including, hi. The list is returned as a Python list of string objects.
3471 */
3472 static PyObject *
3473GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
3474{
3475 PyInt i;
3476 PyInt n = hi - lo;
3477 PyObject *list = PyList_New(n);
3478
3479 if (list == NULL)
3480 return NULL;
3481
3482 for (i = 0; i < n; ++i)
3483 {
3484 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
3485
3486 /* Error check - was the Python string creation OK? */
3487 if (str == NULL)
3488 {
3489 Py_DECREF(list);
3490 return NULL;
3491 }
3492
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02003493 PyList_SET_ITEM(list, i, str);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003494 }
3495
3496 /* The ownership of the Python list is passed to the caller (ie,
3497 * the caller should Py_DECREF() the object when it is finished
3498 * with it).
3499 */
3500
3501 return list;
3502}
3503
3504/*
3505 * Check if deleting lines made the cursor position invalid.
3506 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
3507 * deleted).
3508 */
3509 static void
3510py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
3511{
3512 if (curwin->w_cursor.lnum >= lo)
3513 {
3514 /* Adjust the cursor position if it's in/after the changed
3515 * lines. */
3516 if (curwin->w_cursor.lnum >= hi)
3517 {
3518 curwin->w_cursor.lnum += extra;
3519 check_cursor_col();
3520 }
3521 else if (extra < 0)
3522 {
3523 curwin->w_cursor.lnum = lo;
3524 check_cursor();
3525 }
3526 else
3527 check_cursor_col();
3528 changed_cline_bef_curs();
3529 }
3530 invalidate_botline();
3531}
3532
Bram Moolenaar19e60942011-06-19 00:27:51 +02003533/*
3534 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003535 * in Vim format (1-based). The replacement line is given as
3536 * a Python string object. The object is checked for validity
3537 * and correct format. Errors are returned as a value of FAIL.
3538 * The return value is OK on success.
3539 * If OK is returned and len_change is not NULL, *len_change
3540 * is set to the change in the buffer length.
3541 */
3542 static int
3543SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
3544{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003545 /* First of all, we check the type of the supplied Python object.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003546 * There are three cases:
3547 * 1. NULL, or None - this is a deletion.
3548 * 2. A string - this is a replacement.
3549 * 3. Anything else - this is an error.
3550 */
3551 if (line == Py_None || line == NULL)
3552 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003553 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003554
3555 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003556 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003557
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003558 VimTryStart();
3559
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003560 if (u_savedel((linenr_T)n, 1L) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003561 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003562 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003563 PyErr_SET_VIM("cannot delete line");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003564 else
3565 {
Bram Moolenaar105bc352013-05-17 16:03:57 +02003566 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003567 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
3568 deleted_lines_mark((linenr_T)n, 1L);
3569 }
3570
Bram Moolenaar105bc352013-05-17 16:03:57 +02003571 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003572
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003573 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003574 return FAIL;
3575
3576 if (len_change)
3577 *len_change = -1;
3578
3579 return OK;
3580 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003581 else if (PyBytes_Check(line) || PyUnicode_Check(line))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003582 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003583 char *save = StringToLine(line);
3584 buf_T *savebuf;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003585
3586 if (save == NULL)
3587 return FAIL;
3588
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003589 VimTryStart();
3590
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003591 /* We do not need to free "save" if ml_replace() consumes it. */
3592 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003593 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003594
3595 if (u_savesub((linenr_T)n) == FAIL)
3596 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003597 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003598 vim_free(save);
3599 }
3600 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
3601 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003602 PyErr_SET_VIM("cannot replace line");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003603 vim_free(save);
3604 }
3605 else
3606 changed_bytes((linenr_T)n, 0);
3607
Bram Moolenaar105bc352013-05-17 16:03:57 +02003608 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003609
3610 /* Check that the cursor is not beyond the end of the line now. */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003611 if (buf == savebuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003612 check_cursor_col();
3613
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003614 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003615 return FAIL;
3616
3617 if (len_change)
3618 *len_change = 0;
3619
3620 return OK;
3621 }
3622 else
3623 {
3624 PyErr_BadArgument();
3625 return FAIL;
3626 }
3627}
3628
Bram Moolenaar19e60942011-06-19 00:27:51 +02003629/* Replace a range of lines in the specified buffer. The line numbers are in
3630 * Vim format (1-based). The range is from lo up to, but not including, hi.
3631 * The replacement lines are given as a Python list of string objects. The
3632 * list is checked for validity and correct format. Errors are returned as a
3633 * value of FAIL. The return value is OK on success.
3634 * If OK is returned and len_change is not NULL, *len_change
3635 * is set to the change in the buffer length.
3636 */
3637 static int
3638SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
3639{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003640 /* First of all, we check the type of the supplied Python object.
Bram Moolenaar19e60942011-06-19 00:27:51 +02003641 * There are three cases:
3642 * 1. NULL, or None - this is a deletion.
3643 * 2. A list - this is a replacement.
3644 * 3. Anything else - this is an error.
3645 */
3646 if (list == Py_None || list == NULL)
3647 {
3648 PyInt i;
3649 PyInt n = (int)(hi - lo);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003650 buf_T *savebuf;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003651
3652 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003653 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003654 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003655
3656 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003657 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003658 else
3659 {
3660 for (i = 0; i < n; ++i)
3661 {
3662 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3663 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003664 PyErr_SET_VIM("cannot delete line");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003665 break;
3666 }
3667 }
Bram Moolenaar105bc352013-05-17 16:03:57 +02003668 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003669 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
3670 deleted_lines_mark((linenr_T)lo, (long)i);
3671 }
3672
Bram Moolenaar105bc352013-05-17 16:03:57 +02003673 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003674
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003675 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003676 return FAIL;
3677
3678 if (len_change)
3679 *len_change = -n;
3680
3681 return OK;
3682 }
3683 else if (PyList_Check(list))
3684 {
3685 PyInt i;
3686 PyInt new_len = PyList_Size(list);
3687 PyInt old_len = hi - lo;
3688 PyInt extra = 0; /* lines added to text, can be negative */
3689 char **array;
3690 buf_T *savebuf;
3691
3692 if (new_len == 0) /* avoid allocating zero bytes */
3693 array = NULL;
3694 else
3695 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003696 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003697 if (array == NULL)
3698 {
3699 PyErr_NoMemory();
3700 return FAIL;
3701 }
3702 }
3703
3704 for (i = 0; i < new_len; ++i)
3705 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003706 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02003707
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003708 if (!(line = PyList_GetItem(list, i)) ||
3709 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02003710 {
3711 while (i)
3712 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003713 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003714 return FAIL;
3715 }
3716 }
3717
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003718 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02003719 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003720
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003721 /* START of region without "return". Must call restore_buffer()! */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003722 switch_buffer(&savebuf, buf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003723
3724 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003725 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003726
3727 /* If the size of the range is reducing (ie, new_len < old_len) we
3728 * need to delete some old_len. We do this at the start, by
3729 * repeatedly deleting line "lo".
3730 */
3731 if (!PyErr_Occurred())
3732 {
3733 for (i = 0; i < old_len - new_len; ++i)
3734 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
3735 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003736 PyErr_SET_VIM("cannot delete line");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003737 break;
3738 }
3739 extra -= i;
3740 }
3741
3742 /* For as long as possible, replace the existing old_len with the
3743 * new old_len. This is a more efficient operation, as it requires
3744 * less memory allocation and freeing.
3745 */
3746 if (!PyErr_Occurred())
3747 {
3748 for (i = 0; i < old_len && i < new_len; ++i)
3749 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
3750 == FAIL)
3751 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003752 PyErr_SET_VIM("cannot replace line");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003753 break;
3754 }
3755 }
3756 else
3757 i = 0;
3758
3759 /* Now we may need to insert the remaining new old_len. If we do, we
3760 * must free the strings as we finish with them (we can't pass the
3761 * responsibility to vim in this case).
3762 */
3763 if (!PyErr_Occurred())
3764 {
3765 while (i < new_len)
3766 {
3767 if (ml_append((linenr_T)(lo + i - 1),
3768 (char_u *)array[i], 0, FALSE) == FAIL)
3769 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003770 PyErr_SET_VIM("cannot insert line");
Bram Moolenaar19e60942011-06-19 00:27:51 +02003771 break;
3772 }
3773 vim_free(array[i]);
3774 ++i;
3775 ++extra;
3776 }
3777 }
3778
3779 /* Free any left-over old_len, as a result of an error */
3780 while (i < new_len)
3781 {
3782 vim_free(array[i]);
3783 ++i;
3784 }
3785
3786 /* Free the array of old_len. All of its contents have now
3787 * been dealt with (either freed, or the responsibility passed
3788 * to vim.
3789 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003790 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003791
3792 /* Adjust marks. Invalidate any which lie in the
3793 * changed range, and move any in the remainder of the buffer.
3794 */
3795 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
3796 (long)MAXLNUM, (long)extra);
3797 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
3798
Bram Moolenaar105bc352013-05-17 16:03:57 +02003799 if (buf == savebuf)
Bram Moolenaar19e60942011-06-19 00:27:51 +02003800 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
3801
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003802 /* END of region without "return". */
Bram Moolenaar105bc352013-05-17 16:03:57 +02003803 restore_buffer(savebuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02003804
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003805 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02003806 return FAIL;
3807
3808 if (len_change)
3809 *len_change = new_len - old_len;
3810
3811 return OK;
3812 }
3813 else
3814 {
3815 PyErr_BadArgument();
3816 return FAIL;
3817 }
3818}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003819
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02003820/* Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003821 * The line number is in Vim format (1-based). The lines to be inserted are
3822 * given as a Python list of string objects or as a single string. The lines
3823 * to be added are checked for validity and correct format. Errors are
3824 * returned as a value of FAIL. The return value is OK on success.
3825 * If OK is returned and len_change is not NULL, *len_change
3826 * is set to the change in the buffer length.
3827 */
3828 static int
3829InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
3830{
3831 /* First of all, we check the type of the supplied Python object.
3832 * It must be a string or a list, or the call is in error.
3833 */
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02003834 if (PyBytes_Check(lines) || PyUnicode_Check(lines))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003835 {
3836 char *str = StringToLine(lines);
3837 buf_T *savebuf;
3838
3839 if (str == NULL)
3840 return FAIL;
3841
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003842 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003843 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003844 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003845
3846 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003847 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003848 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003849 PyErr_SET_VIM("cannot insert line");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003850 else
3851 appended_lines_mark((linenr_T)n, 1L);
3852
3853 vim_free(str);
Bram Moolenaar105bc352013-05-17 16:03:57 +02003854 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003855 update_screen(VALID);
3856
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003857 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003858 return FAIL;
3859
3860 if (len_change)
3861 *len_change = 1;
3862
3863 return OK;
3864 }
3865 else if (PyList_Check(lines))
3866 {
3867 PyInt i;
3868 PyInt size = PyList_Size(lines);
3869 char **array;
3870 buf_T *savebuf;
3871
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003872 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003873 if (array == NULL)
3874 {
3875 PyErr_NoMemory();
3876 return FAIL;
3877 }
3878
3879 for (i = 0; i < size; ++i)
3880 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003881 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003882
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02003883 if (!(line = PyList_GetItem(lines, i)) ||
3884 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003885 {
3886 while (i)
3887 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003888 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003889 return FAIL;
3890 }
3891 }
3892
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003893 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003894 VimTryStart();
Bram Moolenaar105bc352013-05-17 16:03:57 +02003895 switch_buffer(&savebuf, buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003896
3897 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003898 PyErr_SET_VIM("cannot save undo information");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003899 else
3900 {
3901 for (i = 0; i < size; ++i)
3902 {
3903 if (ml_append((linenr_T)(n + i),
3904 (char_u *)array[i], 0, FALSE) == FAIL)
3905 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003906 PyErr_SET_VIM("cannot insert line");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003907
3908 /* Free the rest of the lines */
3909 while (i < size)
3910 vim_free(array[i++]);
3911
3912 break;
3913 }
3914 vim_free(array[i]);
3915 }
3916 if (i > 0)
3917 appended_lines_mark((linenr_T)n, (long)i);
3918 }
3919
3920 /* Free the array of lines. All of its contents have now
3921 * been freed.
3922 */
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003923 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003924
Bram Moolenaar105bc352013-05-17 16:03:57 +02003925 restore_buffer(savebuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003926 update_screen(VALID);
3927
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003928 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003929 return FAIL;
3930
3931 if (len_change)
3932 *len_change = size;
3933
3934 return OK;
3935 }
3936 else
3937 {
3938 PyErr_BadArgument();
3939 return FAIL;
3940 }
3941}
3942
3943/*
3944 * Common routines for buffers and line ranges
3945 * -------------------------------------------
3946 */
3947
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003948typedef struct
3949{
3950 PyObject_HEAD
3951 buf_T *buf;
3952} BufferObject;
3953
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003954 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003955CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003956{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003957 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003958 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003959 PyErr_SET_VIM("attempt to refer to deleted buffer");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003960 return -1;
3961 }
3962
3963 return 0;
3964}
3965
3966 static PyObject *
3967RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
3968{
3969 if (CheckBuffer(self))
3970 return NULL;
3971
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003972 if (end == -1)
3973 end = self->buf->b_ml.ml_line_count;
3974
Bram Moolenaarbd80f352013-05-12 21:16:23 +02003975 if (n < 0)
3976 n += end - start + 1;
3977
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003978 if (n < 0 || n > end - start)
3979 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003980 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003981 return NULL;
3982 }
3983
3984 return GetBufferLine(self->buf, n+start);
3985}
3986
3987 static PyObject *
3988RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
3989{
3990 PyInt size;
3991
3992 if (CheckBuffer(self))
3993 return NULL;
3994
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02003995 if (end == -1)
3996 end = self->buf->b_ml.ml_line_count;
3997
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003998 size = end - start + 1;
3999
4000 if (lo < 0)
4001 lo = 0;
4002 else if (lo > size)
4003 lo = size;
4004 if (hi < 0)
4005 hi = 0;
4006 if (hi < lo)
4007 hi = lo;
4008 else if (hi > size)
4009 hi = size;
4010
4011 return GetBufferLineList(self->buf, lo+start, hi+start);
4012}
4013
4014 static PyInt
4015RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
4016{
4017 PyInt len_change;
4018
4019 if (CheckBuffer(self))
4020 return -1;
4021
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004022 if (end == -1)
4023 end = self->buf->b_ml.ml_line_count;
4024
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004025 if (n < 0)
4026 n += end - start + 1;
4027
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004028 if (n < 0 || n > end - start)
4029 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004030 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004031 return -1;
4032 }
4033
4034 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
4035 return -1;
4036
4037 if (new_end)
4038 *new_end = end + len_change;
4039
4040 return 0;
4041}
4042
Bram Moolenaar19e60942011-06-19 00:27:51 +02004043 static PyInt
4044RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
4045{
4046 PyInt size;
4047 PyInt len_change;
4048
4049 /* Self must be a valid buffer */
4050 if (CheckBuffer(self))
4051 return -1;
4052
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004053 if (end == -1)
4054 end = self->buf->b_ml.ml_line_count;
4055
Bram Moolenaar19e60942011-06-19 00:27:51 +02004056 /* Sort out the slice range */
4057 size = end - start + 1;
4058
4059 if (lo < 0)
4060 lo = 0;
4061 else if (lo > size)
4062 lo = size;
4063 if (hi < 0)
4064 hi = 0;
4065 if (hi < lo)
4066 hi = lo;
4067 else if (hi > size)
4068 hi = size;
4069
4070 if (SetBufferLineList(self->buf, lo + start, hi + start,
4071 val, &len_change) == FAIL)
4072 return -1;
4073
4074 if (new_end)
4075 *new_end = end + len_change;
4076
4077 return 0;
4078}
4079
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004080
4081 static PyObject *
4082RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
4083{
4084 PyObject *lines;
4085 PyInt len_change;
4086 PyInt max;
4087 PyInt n;
4088
4089 if (CheckBuffer(self))
4090 return NULL;
4091
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004092 if (end == -1)
4093 end = self->buf->b_ml.ml_line_count;
4094
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004095 max = n = end - start + 1;
4096
4097 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
4098 return NULL;
4099
4100 if (n < 0 || n > max)
4101 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004102 PyErr_SET_STRING(PyExc_IndexError, "line number out of range");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004103 return NULL;
4104 }
4105
4106 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
4107 return NULL;
4108
4109 if (new_end)
4110 *new_end = end + len_change;
4111
4112 Py_INCREF(Py_None);
4113 return Py_None;
4114}
4115
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004116/* Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004117 */
4118
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004119static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004120static PySequenceMethods RangeAsSeq;
4121static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004122
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004123typedef struct
4124{
4125 PyObject_HEAD
4126 BufferObject *buf;
4127 PyInt start;
4128 PyInt end;
4129} RangeObject;
4130
4131 static PyObject *
4132RangeNew(buf_T *buf, PyInt start, PyInt end)
4133{
4134 BufferObject *bufr;
4135 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02004136 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004137 if (self == NULL)
4138 return NULL;
4139
4140 bufr = (BufferObject *)BufferNew(buf);
4141 if (bufr == NULL)
4142 {
4143 Py_DECREF(self);
4144 return NULL;
4145 }
4146 Py_INCREF(bufr);
4147
4148 self->buf = bufr;
4149 self->start = start;
4150 self->end = end;
4151
4152 return (PyObject *)(self);
4153}
4154
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004155 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004156RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004157{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004158 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004159 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02004160 PyObject_GC_Del((void *)(self));
4161}
4162
4163 static int
4164RangeTraverse(RangeObject *self, visitproc visit, void *arg)
4165{
4166 Py_VISIT(((PyObject *)(self->buf)));
4167 return 0;
4168}
4169
4170 static int
4171RangeClear(RangeObject *self)
4172{
4173 Py_CLEAR(self->buf);
4174 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004175}
4176
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004177 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004178RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004179{
4180 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004181 if (CheckBuffer(self->buf))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004182 return -1; /* ??? */
4183
Bram Moolenaard6e39182013-05-21 18:30:34 +02004184 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004185}
4186
4187 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004188RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004189{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004190 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004191}
4192
4193 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004194RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004195{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004196 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004197}
4198
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004199static char *RangeAttrs[] = {
4200 "start", "end",
4201 NULL
4202};
4203
4204 static PyObject *
4205RangeDir(PyObject *self)
4206{
4207 return ObjectDir(self, RangeAttrs);
4208}
4209
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004210 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004211RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004212{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004213 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004214}
4215
4216 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004217RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004218{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004219 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004220 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
4221 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004222 else
4223 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004224 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004225
4226 if (name == NULL)
4227 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004228
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004229 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02004230 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004231 }
4232}
4233
4234static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004235 /* name, function, calling, documentation */
4236 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004237 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
4238 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004239};
4240
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004241static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004242static PySequenceMethods BufferAsSeq;
4243static PyMappingMethods BufferAsMapping;
4244
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004245 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02004246BufferNew(buf_T *buf)
4247{
4248 /* We need to handle deletion of buffers underneath us.
4249 * If we add a "b_python*_ref" field to the buf_T structure,
4250 * then we can get at it in buf_freeall() in vim. We then
4251 * need to create only ONE Python object per buffer - if
4252 * we try to create a second, just INCREF the existing one
4253 * and return it. The (single) Python object referring to
4254 * the buffer is stored in "b_python*_ref".
4255 * Question: what to do on a buf_freeall(). We'll probably
4256 * have to either delete the Python object (DECREF it to
4257 * zero - a bad idea, as it leaves dangling refs!) or
4258 * set the buf_T * value to an invalid value (-1?), which
4259 * means we need checks in all access functions... Bah.
4260 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004261 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02004262 * b_python_ref and b_python3_ref fields respectively.
4263 */
4264
4265 BufferObject *self;
4266
4267 if (BUF_PYTHON_REF(buf) != NULL)
4268 {
4269 self = BUF_PYTHON_REF(buf);
4270 Py_INCREF(self);
4271 }
4272 else
4273 {
4274 self = PyObject_NEW(BufferObject, &BufferType);
4275 if (self == NULL)
4276 return NULL;
4277 self->buf = buf;
4278 BUF_PYTHON_REF(buf) = self;
4279 }
4280
4281 return (PyObject *)(self);
4282}
4283
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004284 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004285BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004286{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004287 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
4288 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004289
4290 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004291}
4292
Bram Moolenaar971db462013-05-12 18:44:48 +02004293 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004294BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02004295{
4296 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
Bram Moolenaard6e39182013-05-21 18:30:34 +02004297 if (CheckBuffer(self))
Bram Moolenaar971db462013-05-12 18:44:48 +02004298 return -1; /* ??? */
4299
Bram Moolenaard6e39182013-05-21 18:30:34 +02004300 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02004301}
4302
4303 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004304BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02004305{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004306 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004307}
4308
4309 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004310BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02004311{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004312 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02004313}
4314
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004315static char *BufferAttrs[] = {
4316 "name", "number", "vars", "options", "valid",
4317 NULL
4318};
4319
4320 static PyObject *
4321BufferDir(PyObject *self)
4322{
4323 return ObjectDir(self, BufferAttrs);
4324}
4325
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004326 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02004327BufferAttrValid(BufferObject *self, char *name)
4328{
4329 PyObject *r;
4330
4331 if (strcmp(name, "valid") != 0)
4332 return NULL;
4333
4334 r = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
4335 Py_INCREF(r);
4336 return r;
4337}
4338
4339 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004340BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004341{
4342 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02004343 return PyString_FromString((self->buf->b_ffname == NULL
4344 ? "" : (char *) self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004345 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004346 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004347 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02004348 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004349 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004350 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
4351 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004352 else if (strcmp(name, "__members__") == 0)
4353 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004354 else
4355 return NULL;
4356}
4357
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004358 static int
4359BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
4360{
4361 if (CheckBuffer(self))
4362 return -1;
4363
4364 if (strcmp(name, "name") == 0)
4365 {
4366 char_u *val;
4367 aco_save_T aco;
4368 int r;
4369 PyObject *todecref;
4370
4371 if (!(val = StringToChars(valObject, &todecref)))
4372 return -1;
4373
4374 VimTryStart();
4375 /* Using aucmd_*: autocommands will be executed by rename_buffer */
4376 aucmd_prepbuf(&aco, self->buf);
4377 r = rename_buffer(val);
4378 aucmd_restbuf(&aco);
4379 Py_XDECREF(todecref);
4380 if (VimTryEnd())
4381 return -1;
4382
4383 if (r == FAIL)
4384 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004385 PyErr_SET_VIM("failed to rename buffer");
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004386 return -1;
4387 }
4388 return 0;
4389 }
4390 else
4391 {
4392 PyErr_SetString(PyExc_AttributeError, name);
4393 return -1;
4394 }
4395}
4396
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004397 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004398BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004399{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004400 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004401}
4402
4403 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02004404BufferMark(BufferObject *self, PyObject *pmarkObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004405{
4406 pos_T *posp;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004407 char_u *pmark;
4408 char_u mark;
Bram Moolenaar105bc352013-05-17 16:03:57 +02004409 buf_T *savebuf;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004410 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004411
Bram Moolenaard6e39182013-05-21 18:30:34 +02004412 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004413 return NULL;
4414
Bram Moolenaar389a1792013-06-23 13:00:44 +02004415 if (!(pmark = StringToChars(pmarkObject, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004416 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004417
Bram Moolenaar389a1792013-06-23 13:00:44 +02004418 if (pmark[0] == '\0' || pmark[1] != '\0')
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004419 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004420 PyErr_SET_STRING(PyExc_ValueError,
4421 "mark name must be a single character");
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004422 return NULL;
4423 }
4424
4425 mark = *pmark;
Bram Moolenaar389a1792013-06-23 13:00:44 +02004426
4427 Py_XDECREF(todecref);
4428
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004429 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02004430 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004431 posp = getmark(mark, FALSE);
Bram Moolenaar105bc352013-05-17 16:03:57 +02004432 restore_buffer(savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004433 if (VimTryEnd())
4434 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004435
4436 if (posp == NULL)
4437 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004438 PyErr_SET_VIM("invalid mark name");
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004439 return NULL;
4440 }
4441
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004442 if (posp->lnum <= 0)
4443 {
4444 /* Or raise an error? */
4445 Py_INCREF(Py_None);
4446 return Py_None;
4447 }
4448
4449 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
4450}
4451
4452 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004453BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004454{
4455 PyInt start;
4456 PyInt end;
4457
Bram Moolenaard6e39182013-05-21 18:30:34 +02004458 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004459 return NULL;
4460
4461 if (!PyArg_ParseTuple(args, "nn", &start, &end))
4462 return NULL;
4463
Bram Moolenaard6e39182013-05-21 18:30:34 +02004464 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004465}
4466
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004467 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004468BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004469{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004470 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004471 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004472 else
4473 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004474 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004475
4476 if (name == NULL)
4477 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004478
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004479 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004480 }
4481}
4482
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004483static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004484 /* name, function, calling, documentation */
4485 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02004486 {"mark", (PyCFunction)BufferMark, METH_O, "Return (row,col) representing position of named mark" },
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02004487 {"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 +02004488 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
4489 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004490};
4491
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004492/*
4493 * Buffer list object - Implementation
4494 */
4495
4496static PyTypeObject BufMapType;
4497
4498typedef struct
4499{
4500 PyObject_HEAD
4501} BufMapObject;
4502
4503 static PyInt
4504BufMapLength(PyObject *self UNUSED)
4505{
4506 buf_T *b = firstbuf;
4507 PyInt n = 0;
4508
4509 while (b)
4510 {
4511 ++n;
4512 b = b->b_next;
4513 }
4514
4515 return n;
4516}
4517
4518 static PyObject *
4519BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
4520{
4521 buf_T *b;
4522 int bnr;
4523
4524#if PY_MAJOR_VERSION < 3
4525 if (PyInt_Check(keyObject))
4526 bnr = PyInt_AsLong(keyObject);
4527 else
4528#endif
4529 if (PyLong_Check(keyObject))
4530 bnr = PyLong_AsLong(keyObject);
4531 else
4532 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004533 PyErr_SET_STRING(PyExc_TypeError, "key must be integer");
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004534 return NULL;
4535 }
4536
4537 b = buflist_findnr(bnr);
4538
4539 if (b)
4540 return BufferNew(b);
4541 else
4542 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02004543 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004544 return NULL;
4545 }
4546}
4547
4548 static void
4549BufMapIterDestruct(PyObject *buffer)
4550{
4551 /* Iteration was stopped before all buffers were processed */
4552 if (buffer)
4553 {
4554 Py_DECREF(buffer);
4555 }
4556}
4557
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004558 static int
4559BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
4560{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004561 if (buffer)
4562 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004563 return 0;
4564}
4565
4566 static int
4567BufMapIterClear(PyObject **buffer)
4568{
Bram Moolenaar774267b2013-05-21 20:51:59 +02004569 if (*buffer)
4570 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004571 return 0;
4572}
4573
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004574 static PyObject *
4575BufMapIterNext(PyObject **buffer)
4576{
4577 PyObject *next;
4578 PyObject *r;
4579
4580 if (!*buffer)
4581 return NULL;
4582
4583 r = *buffer;
4584
4585 if (CheckBuffer((BufferObject *)(r)))
4586 {
4587 *buffer = NULL;
4588 return NULL;
4589 }
4590
4591 if (!((BufferObject *)(r))->buf->b_next)
4592 next = NULL;
4593 else if (!(next = BufferNew(((BufferObject *)(r))->buf->b_next)))
4594 return NULL;
4595 *buffer = next;
Bram Moolenaar9e74e302013-05-17 21:20:17 +02004596 /* Do not increment reference: we no longer hold it (decref), but whoever
4597 * on other side will hold (incref). Decref+incref = nothing. */
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004598 return r;
4599}
4600
4601 static PyObject *
4602BufMapIter(PyObject *self UNUSED)
4603{
4604 PyObject *buffer;
4605
4606 buffer = BufferNew(firstbuf);
4607 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02004608 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
4609 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02004610}
4611
4612static PyMappingMethods BufMapAsMapping = {
4613 (lenfunc) BufMapLength,
4614 (binaryfunc) BufMapItem,
4615 (objobjargproc) 0,
4616};
4617
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004618/* Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004619 */
4620
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004621static char *CurrentAttrs[] = {
4622 "buffer", "window", "line", "range", "tabpage",
4623 NULL
4624};
4625
4626 static PyObject *
4627CurrentDir(PyObject *self)
4628{
4629 return ObjectDir(self, CurrentAttrs);
4630}
4631
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004632 static PyObject *
4633CurrentGetattr(PyObject *self UNUSED, char *name)
4634{
4635 if (strcmp(name, "buffer") == 0)
4636 return (PyObject *)BufferNew(curbuf);
4637 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004638 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004639 else if (strcmp(name, "tabpage") == 0)
4640 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004641 else if (strcmp(name, "line") == 0)
4642 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
4643 else if (strcmp(name, "range") == 0)
4644 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004645 else if (strcmp(name, "__members__") == 0)
4646 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004647 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004648#if PY_MAJOR_VERSION < 3
4649 return Py_FindMethod(WindowMethods, self, name);
4650#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004651 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004652#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004653}
4654
4655 static int
4656CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
4657{
4658 if (strcmp(name, "line") == 0)
4659 {
4660 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, value, NULL) == FAIL)
4661 return -1;
4662
4663 return 0;
4664 }
Bram Moolenaare7614592013-05-15 15:51:08 +02004665 else if (strcmp(name, "buffer") == 0)
4666 {
4667 int count;
4668
4669 if (value->ob_type != &BufferType)
4670 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004671 PyErr_SET_STRING(PyExc_TypeError, "expected vim.Buffer object");
Bram Moolenaare7614592013-05-15 15:51:08 +02004672 return -1;
4673 }
4674
4675 if (CheckBuffer((BufferObject *)(value)))
4676 return -1;
4677 count = ((BufferObject *)(value))->buf->b_fnum;
4678
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004679 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004680 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
4681 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004682 if (VimTryEnd())
4683 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004684 PyErr_SET_VIM("failed to switch to given buffer");
Bram Moolenaare7614592013-05-15 15:51:08 +02004685 return -1;
4686 }
4687
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004688 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004689 }
4690 else if (strcmp(name, "window") == 0)
4691 {
4692 int count;
4693
4694 if (value->ob_type != &WindowType)
4695 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004696 PyErr_SET_STRING(PyExc_TypeError, "expected vim.Window object");
Bram Moolenaare7614592013-05-15 15:51:08 +02004697 return -1;
4698 }
4699
4700 if (CheckWindow((WindowObject *)(value)))
4701 return -1;
4702 count = get_win_number(((WindowObject *)(value))->win, firstwin);
4703
4704 if (!count)
4705 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004706 PyErr_SET_STRING(PyExc_ValueError,
4707 "failed to find window in the current tab page");
Bram Moolenaare7614592013-05-15 15:51:08 +02004708 return -1;
4709 }
4710
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004711 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004712 win_goto(((WindowObject *)(value))->win);
4713 if (((WindowObject *)(value))->win != curwin)
4714 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004715 if (VimTryEnd())
4716 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004717 PyErr_SET_STRING(PyExc_RuntimeError,
4718 "did not switch to the specified window");
Bram Moolenaare7614592013-05-15 15:51:08 +02004719 return -1;
4720 }
4721
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004722 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004723 }
4724 else if (strcmp(name, "tabpage") == 0)
4725 {
4726 if (value->ob_type != &TabPageType)
4727 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004728 PyErr_SET_STRING(PyExc_TypeError, "expected vim.TabPage object");
Bram Moolenaare7614592013-05-15 15:51:08 +02004729 return -1;
4730 }
4731
4732 if (CheckTabPage((TabPageObject *)(value)))
4733 return -1;
4734
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004735 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02004736 goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
4737 if (((TabPageObject *)(value))->tab != curtab)
4738 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004739 if (VimTryEnd())
4740 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02004741 PyErr_SET_STRING(PyExc_RuntimeError,
4742 "did not switch to the specified tab page");
Bram Moolenaare7614592013-05-15 15:51:08 +02004743 return -1;
4744 }
4745
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004746 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02004747 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004748 else
4749 {
4750 PyErr_SetString(PyExc_AttributeError, name);
4751 return -1;
4752 }
4753}
4754
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004755static struct PyMethodDef CurrentMethods[] = {
4756 /* name, function, calling, documentation */
4757 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
4758 { NULL, NULL, 0, NULL}
4759};
4760
Bram Moolenaardb913952012-06-29 12:54:53 +02004761 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004762init_range_cmd(exarg_T *eap)
4763{
4764 RangeStart = eap->line1;
4765 RangeEnd = eap->line2;
4766}
4767
4768 static void
4769init_range_eval(typval_T *rettv UNUSED)
4770{
4771 RangeStart = (PyInt) curwin->w_cursor.lnum;
4772 RangeEnd = RangeStart;
4773}
4774
4775 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004776run_cmd(const char *cmd, void *arg UNUSED
4777#ifdef PY_CAN_RECURSE
4778 , PyGILState_STATE *pygilstate UNUSED
4779#endif
4780 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004781{
4782 PyRun_SimpleString((char *) cmd);
4783}
4784
4785static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
4786static int code_hdr_len = 30;
4787
4788 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004789run_do(const char *cmd, void *arg UNUSED
4790#ifdef PY_CAN_RECURSE
4791 , PyGILState_STATE *pygilstate
4792#endif
4793 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004794{
4795 PyInt lnum;
4796 size_t len;
4797 char *code;
4798 int status;
4799 PyObject *pyfunc, *pymain;
4800
Bram Moolenaar4ac66762013-05-28 22:31:46 +02004801 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004802 {
4803 EMSG(_("cannot save undo information"));
4804 return;
4805 }
4806
4807 len = code_hdr_len + STRLEN(cmd);
4808 code = PyMem_New(char, len + 1);
4809 memcpy(code, code_hdr, code_hdr_len);
4810 STRCPY(code + code_hdr_len, cmd);
4811 status = PyRun_SimpleString(code);
4812 PyMem_Free(code);
4813
4814 if (status)
4815 {
4816 EMSG(_("failed to run the code"));
4817 return;
4818 }
4819
4820 status = 0;
4821 pymain = PyImport_AddModule("__main__");
4822 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004823#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004824 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004825#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004826
4827 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
4828 {
4829 PyObject *line, *linenr, *ret;
4830
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004831#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004832 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004833#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004834 if (!(line = GetBufferLine(curbuf, lnum)))
4835 goto err;
4836 if (!(linenr = PyInt_FromLong((long) lnum)))
4837 {
4838 Py_DECREF(line);
4839 goto err;
4840 }
4841 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
4842 Py_DECREF(line);
4843 Py_DECREF(linenr);
4844 if (!ret)
4845 goto err;
4846
4847 if (ret != Py_None)
4848 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
4849 goto err;
4850
4851 Py_XDECREF(ret);
4852 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004853#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004854 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004855#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004856 }
4857 goto out;
4858err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004859#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004860 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004861#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004862 PyErr_PrintEx(0);
4863 PythonIO_Flush();
4864 status = 1;
4865out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004866#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004867 if (!status)
4868 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004869#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004870 Py_DECREF(pyfunc);
4871 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
4872 if (status)
4873 return;
4874 check_cursor();
4875 update_curbuf(NOT_VALID);
4876}
4877
4878 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02004879run_eval(const char *cmd, typval_T *rettv
4880#ifdef PY_CAN_RECURSE
4881 , PyGILState_STATE *pygilstate UNUSED
4882#endif
4883 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02004884{
4885 PyObject *r;
4886
4887 r = PyRun_String((char *) cmd, Py_eval_input, globals, globals);
4888 if (r == NULL)
4889 {
4890 if (PyErr_Occurred() && !msg_silent)
4891 PyErr_PrintEx(0);
4892 EMSG(_("E858: Eval did not return a valid python object"));
4893 }
4894 else
4895 {
4896 if (ConvertFromPyObject(r, rettv) == -1)
4897 EMSG(_("E859: Failed to convert returned python object to vim value"));
4898 Py_DECREF(r);
4899 }
4900 PyErr_Clear();
4901}
4902
4903 static void
Bram Moolenaardb913952012-06-29 12:54:53 +02004904set_ref_in_py(const int copyID)
4905{
4906 pylinkedlist_T *cur;
4907 dict_T *dd;
4908 list_T *ll;
4909
4910 if (lastdict != NULL)
4911 for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
4912 {
4913 dd = ((DictionaryObject *) (cur->pll_obj))->dict;
4914 if (dd->dv_copyID != copyID)
4915 {
4916 dd->dv_copyID = copyID;
4917 set_ref_in_ht(&dd->dv_hashtab, copyID);
4918 }
4919 }
4920
4921 if (lastlist != NULL)
4922 for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
4923 {
4924 ll = ((ListObject *) (cur->pll_obj))->list;
4925 if (ll->lv_copyID != copyID)
4926 {
4927 ll->lv_copyID = copyID;
4928 set_ref_in_list(ll, copyID);
4929 }
4930 }
4931}
4932
4933 static int
4934set_string_copy(char_u *str, typval_T *tv)
4935{
4936 tv->vval.v_string = vim_strsave(str);
4937 if (tv->vval.v_string == NULL)
4938 {
4939 PyErr_NoMemory();
4940 return -1;
4941 }
4942 return 0;
4943}
4944
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004945 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004946pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004947{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004948 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004949 char_u *key;
4950 dictitem_T *di;
4951 PyObject *keyObject;
4952 PyObject *valObject;
4953 Py_ssize_t iter = 0;
4954
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004955 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004956 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004957
4958 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004959 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004960
4961 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
4962 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004963 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004964
Bram Moolenaara03e6312013-05-29 22:49:26 +02004965 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004966 {
4967 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004968 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004969 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004970
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004971 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004972 {
4973 dict_unref(dict);
4974 return -1;
4975 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02004976
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004977 if (*key == NUL)
4978 {
4979 dict_unref(dict);
4980 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02004981 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004982 return -1;
4983 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004984
4985 di = dictitem_alloc(key);
4986
Bram Moolenaarfc714b32013-05-30 14:52:37 +02004987 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004988
4989 if (di == NULL)
4990 {
4991 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02004992 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004993 return -1;
4994 }
4995 di->di_tv.v_lock = 0;
4996
Bram Moolenaarb38caae2013-05-29 22:39:52 +02004997 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004998 {
4999 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005000 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005001 return -1;
5002 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005003
5004 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005005 {
Bram Moolenaara03e6312013-05-29 22:49:26 +02005006 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005007 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005008 dict_unref(dict);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005009 PyErr_SET_VIM("failed to add key to dictionary");
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005010 return -1;
5011 }
5012 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005013
5014 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005015 return 0;
5016}
5017
5018 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005019pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005020{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005021 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005022 char_u *key;
5023 dictitem_T *di;
5024 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005025 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005026 PyObject *keyObject;
5027 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005028
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005029 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005030 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005031
5032 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005033 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005034
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005035 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005036 {
5037 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005038 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005039 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005040
5041 if (!(iterator = PyObject_GetIter(list)))
5042 {
5043 dict_unref(dict);
5044 Py_DECREF(list);
5045 return -1;
5046 }
5047 Py_DECREF(list);
5048
5049 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005050 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005051 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005052
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005053 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005054 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005055 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005056 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005057 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005058 return -1;
5059 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005060
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005061 if (*key == NUL)
5062 {
5063 Py_DECREF(keyObject);
5064 Py_DECREF(iterator);
5065 Py_XDECREF(todecref);
5066 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005067 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005068 return -1;
5069 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005070
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005071 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005072 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005073 Py_DECREF(keyObject);
5074 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005075 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005076 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005077 return -1;
5078 }
5079
5080 di = dictitem_alloc(key);
5081
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005082 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005083 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005084
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005085 if (di == NULL)
5086 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005087 Py_DECREF(iterator);
5088 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005089 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005090 PyErr_NoMemory();
5091 return -1;
5092 }
5093 di->di_tv.v_lock = 0;
5094
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005095 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005096 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005097 Py_DECREF(iterator);
5098 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005099 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005100 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005101 return -1;
5102 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02005103
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005104 Py_DECREF(valObject);
5105
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005106 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005107 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005108 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005109 dictitem_free(di);
5110 dict_unref(dict);
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005111 PyErr_SET_VIM("failed to add key to dictionary");
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005112 return -1;
5113 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005114 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005115 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005116 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005117 return 0;
5118}
5119
5120 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005121pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005122{
5123 list_T *l;
5124
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005125 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005126 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005127
5128 tv->v_type = VAR_LIST;
5129 tv->vval.v_list = l;
5130
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005131 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005132 {
5133 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005134 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005135 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005136
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005137 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005138 return 0;
5139}
5140
Bram Moolenaardb913952012-06-29 12:54:53 +02005141typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
5142
5143 static int
5144convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005145 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005146{
5147 PyObject *capsule;
5148 char hexBuf[sizeof(void *) * 2 + 3];
5149
5150 sprintf(hexBuf, "%p", obj);
5151
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005152# ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005153 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005154# else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005155 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005156# endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02005157 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02005158 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005159# ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02005160 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaar221d6872012-06-30 13:34:34 +02005161# else
5162 capsule = PyCObject_FromVoidPtr(tv, NULL);
5163# endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02005164 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
5165 {
5166 Py_DECREF(capsule);
5167 tv->v_type = VAR_UNKNOWN;
5168 return -1;
5169 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005170 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02005171 {
5172 tv->v_type = VAR_UNKNOWN;
5173 return -1;
5174 }
5175 /* As we are not using copy_tv which increments reference count we must
5176 * do it ourself. */
5177 switch(tv->v_type)
5178 {
5179 case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
5180 case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
5181 }
5182 }
5183 else
5184 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005185 typval_T *v;
5186
5187# ifdef PY_USE_CAPSULE
5188 v = PyCapsule_GetPointer(capsule, NULL);
5189# else
Bram Moolenaar221d6872012-06-30 13:34:34 +02005190 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaar2afa3232012-06-29 16:28:28 +02005191# endif
Bram Moolenaardb913952012-06-29 12:54:53 +02005192 copy_tv(v, tv);
5193 }
5194 return 0;
5195}
5196
5197 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02005198ConvertFromPyMapping(PyObject *obj, typval_T *tv)
5199{
5200 PyObject *lookup_dict;
5201 int r;
5202
5203 if (!(lookup_dict = PyDict_New()))
5204 return -1;
5205
5206 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
5207 {
5208 tv->v_type = VAR_DICT;
5209 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5210 ++tv->vval.v_dict->dv_refcount;
5211 r = 0;
5212 }
5213 else if (PyDict_Check(obj))
5214 r = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
5215 else if (PyMapping_Check(obj))
5216 r = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
5217 else
5218 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005219 PyErr_SET_STRING(PyExc_TypeError,
5220 "unable to convert object to vim dictionary");
Bram Moolenaara9922d62013-05-30 13:01:18 +02005221 r = -1;
5222 }
5223 Py_DECREF(lookup_dict);
5224 return r;
5225}
5226
5227 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02005228ConvertFromPyObject(PyObject *obj, typval_T *tv)
5229{
5230 PyObject *lookup_dict;
5231 int r;
5232
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005233 if (!(lookup_dict = PyDict_New()))
5234 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005235 r = _ConvertFromPyObject(obj, tv, lookup_dict);
5236 Py_DECREF(lookup_dict);
5237 return r;
5238}
5239
5240 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005241_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02005242{
Bram Moolenaara9922d62013-05-30 13:01:18 +02005243 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02005244 {
5245 tv->v_type = VAR_DICT;
5246 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
5247 ++tv->vval.v_dict->dv_refcount;
5248 }
5249 else if (obj->ob_type == &ListType)
5250 {
5251 tv->v_type = VAR_LIST;
5252 tv->vval.v_list = (((ListObject *)(obj))->list);
5253 ++tv->vval.v_list->lv_refcount;
5254 }
5255 else if (obj->ob_type == &FunctionType)
5256 {
5257 if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
5258 return -1;
5259
5260 tv->v_type = VAR_FUNC;
5261 func_ref(tv->vval.v_string);
5262 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005263 else if (PyBytes_Check(obj))
5264 {
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005265 char_u *result;
Bram Moolenaardb913952012-06-29 12:54:53 +02005266
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005267 if (PyBytes_AsStringAndSize(obj, (char **) &result, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005268 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005269 if (result == NULL)
5270 return -1;
5271
5272 if (set_string_copy(result, tv) == -1)
5273 return -1;
5274
5275 tv->v_type = VAR_STRING;
5276 }
5277 else if (PyUnicode_Check(obj))
5278 {
5279 PyObject *bytes;
5280 char_u *result;
5281
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005282 bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02005283 if (bytes == NULL)
5284 return -1;
5285
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02005286 if(PyBytes_AsStringAndSize(bytes, (char **) &result, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02005287 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02005288 if (result == NULL)
5289 return -1;
5290
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005291 if (set_string_copy(result, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02005292 {
5293 Py_XDECREF(bytes);
5294 return -1;
5295 }
5296 Py_XDECREF(bytes);
5297
5298 tv->v_type = VAR_STRING;
5299 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02005300#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02005301 else if (PyInt_Check(obj))
5302 {
5303 tv->v_type = VAR_NUMBER;
5304 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
5305 }
5306#endif
5307 else if (PyLong_Check(obj))
5308 {
5309 tv->v_type = VAR_NUMBER;
5310 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
5311 }
5312 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005313 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005314#ifdef FEAT_FLOAT
5315 else if (PyFloat_Check(obj))
5316 {
5317 tv->v_type = VAR_FLOAT;
5318 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
5319 }
5320#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005321 else if (PyObject_HasAttrString(obj, "keys"))
5322 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005323 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005324 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005325 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005326 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005327 else
5328 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005329 PyErr_SET_STRING(PyExc_TypeError,
5330 "unable to convert to vim structure");
Bram Moolenaardb913952012-06-29 12:54:53 +02005331 return -1;
5332 }
5333 return 0;
5334}
5335
5336 static PyObject *
5337ConvertToPyObject(typval_T *tv)
5338{
5339 if (tv == NULL)
5340 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005341 PyErr_SET_VIM("NULL reference passed");
Bram Moolenaardb913952012-06-29 12:54:53 +02005342 return NULL;
5343 }
5344 switch (tv->v_type)
5345 {
5346 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005347 return PyBytes_FromString(tv->vval.v_string == NULL
5348 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005349 case VAR_NUMBER:
5350 return PyLong_FromLong((long) tv->vval.v_number);
5351#ifdef FEAT_FLOAT
5352 case VAR_FLOAT:
5353 return PyFloat_FromDouble((double) tv->vval.v_float);
5354#endif
5355 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005356 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02005357 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02005358 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02005359 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005360 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02005361 ? (char_u *)"" : tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02005362 case VAR_UNKNOWN:
5363 Py_INCREF(Py_None);
5364 return Py_None;
5365 default:
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005366 PyErr_SET_VIM("internal error: invalid value type");
Bram Moolenaardb913952012-06-29 12:54:53 +02005367 return NULL;
5368 }
5369}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005370
5371typedef struct
5372{
5373 PyObject_HEAD
5374} CurrentObject;
5375static PyTypeObject CurrentType;
5376
5377 static void
5378init_structs(void)
5379{
5380 vim_memset(&OutputType, 0, sizeof(OutputType));
5381 OutputType.tp_name = "vim.message";
5382 OutputType.tp_basicsize = sizeof(OutputObject);
5383 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
5384 OutputType.tp_doc = "vim message object";
5385 OutputType.tp_methods = OutputMethods;
5386#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005387 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
5388 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005389 OutputType.tp_alloc = call_PyType_GenericAlloc;
5390 OutputType.tp_new = call_PyType_GenericNew;
5391 OutputType.tp_free = call_PyObject_Free;
5392#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005393 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
5394 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005395#endif
5396
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005397 vim_memset(&IterType, 0, sizeof(IterType));
5398 IterType.tp_name = "vim.iter";
5399 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005400 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005401 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005402 IterType.tp_iter = (getiterfunc)IterIter;
5403 IterType.tp_iternext = (iternextfunc)IterNext;
5404 IterType.tp_dealloc = (destructor)IterDestructor;
5405 IterType.tp_traverse = (traverseproc)IterTraverse;
5406 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005407
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005408 vim_memset(&BufferType, 0, sizeof(BufferType));
5409 BufferType.tp_name = "vim.buffer";
5410 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005411 BufferType.tp_dealloc = (destructor)BufferDestructor;
5412 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005413 BufferType.tp_as_sequence = &BufferAsSeq;
5414 BufferType.tp_as_mapping = &BufferAsMapping;
5415 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
5416 BufferType.tp_doc = "vim buffer object";
5417 BufferType.tp_methods = BufferMethods;
5418#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005419 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005420 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005421 BufferType.tp_alloc = call_PyType_GenericAlloc;
5422 BufferType.tp_new = call_PyType_GenericNew;
5423 BufferType.tp_free = call_PyObject_Free;
5424#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005425 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005426 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005427#endif
5428
5429 vim_memset(&WindowType, 0, sizeof(WindowType));
5430 WindowType.tp_name = "vim.window";
5431 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005432 WindowType.tp_dealloc = (destructor)WindowDestructor;
5433 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005434 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005435 WindowType.tp_doc = "vim Window object";
5436 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005437 WindowType.tp_traverse = (traverseproc)WindowTraverse;
5438 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005439#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005440 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
5441 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005442 WindowType.tp_alloc = call_PyType_GenericAlloc;
5443 WindowType.tp_new = call_PyType_GenericNew;
5444 WindowType.tp_free = call_PyObject_Free;
5445#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005446 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
5447 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005448#endif
5449
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005450 vim_memset(&TabPageType, 0, sizeof(TabPageType));
5451 TabPageType.tp_name = "vim.tabpage";
5452 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005453 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
5454 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005455 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
5456 TabPageType.tp_doc = "vim tab page object";
5457 TabPageType.tp_methods = TabPageMethods;
5458#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005459 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005460 TabPageType.tp_alloc = call_PyType_GenericAlloc;
5461 TabPageType.tp_new = call_PyType_GenericNew;
5462 TabPageType.tp_free = call_PyObject_Free;
5463#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005464 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005465#endif
5466
Bram Moolenaardfa38d42013-05-15 13:38:47 +02005467 vim_memset(&BufMapType, 0, sizeof(BufMapType));
5468 BufMapType.tp_name = "vim.bufferlist";
5469 BufMapType.tp_basicsize = sizeof(BufMapObject);
5470 BufMapType.tp_as_mapping = &BufMapAsMapping;
5471 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005472 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005473 BufferType.tp_doc = "vim buffer list";
5474
5475 vim_memset(&WinListType, 0, sizeof(WinListType));
5476 WinListType.tp_name = "vim.windowlist";
5477 WinListType.tp_basicsize = sizeof(WinListType);
5478 WinListType.tp_as_sequence = &WinListAsSeq;
5479 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
5480 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005481 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005482
5483 vim_memset(&TabListType, 0, sizeof(TabListType));
5484 TabListType.tp_name = "vim.tabpagelist";
5485 TabListType.tp_basicsize = sizeof(TabListType);
5486 TabListType.tp_as_sequence = &TabListAsSeq;
5487 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
5488 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005489
5490 vim_memset(&RangeType, 0, sizeof(RangeType));
5491 RangeType.tp_name = "vim.range";
5492 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005493 RangeType.tp_dealloc = (destructor)RangeDestructor;
5494 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005495 RangeType.tp_as_sequence = &RangeAsSeq;
5496 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02005497 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005498 RangeType.tp_doc = "vim Range object";
5499 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005500 RangeType.tp_traverse = (traverseproc)RangeTraverse;
5501 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005502#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005503 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005504 RangeType.tp_alloc = call_PyType_GenericAlloc;
5505 RangeType.tp_new = call_PyType_GenericNew;
5506 RangeType.tp_free = call_PyObject_Free;
5507#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005508 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005509#endif
5510
5511 vim_memset(&CurrentType, 0, sizeof(CurrentType));
5512 CurrentType.tp_name = "vim.currentdata";
5513 CurrentType.tp_basicsize = sizeof(CurrentObject);
5514 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
5515 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005516 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005517#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005518 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
5519 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005520#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005521 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
5522 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005523#endif
5524
5525 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
5526 DictionaryType.tp_name = "vim.dictionary";
5527 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005528 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005529 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005530 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005531 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005532 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
5533 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02005534 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
5535 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
5536 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005537#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005538 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
5539 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005540#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005541 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
5542 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005543#endif
5544
5545 vim_memset(&ListType, 0, sizeof(ListType));
5546 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02005547 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005548 ListType.tp_basicsize = sizeof(ListObject);
5549 ListType.tp_as_sequence = &ListAsSeq;
5550 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005551 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005552 ListType.tp_doc = "list pushing modifications to vim structure";
5553 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005554 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02005555 ListType.tp_new = (newfunc)ListConstructor;
5556 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005557#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005558 ListType.tp_getattro = (getattrofunc)ListGetattro;
5559 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005560#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005561 ListType.tp_getattr = (getattrfunc)ListGetattr;
5562 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005563#endif
5564
5565 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005566 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005567 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02005568 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
5569 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005570 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005571 FunctionType.tp_doc = "object that calls vim function";
5572 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02005573 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02005574 FunctionType.tp_new = (newfunc)FunctionConstructor;
5575 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005576#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02005577 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005578#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02005579 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005580#endif
5581
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005582 vim_memset(&OptionsType, 0, sizeof(OptionsType));
5583 OptionsType.tp_name = "vim.options";
5584 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02005585 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005586 OptionsType.tp_doc = "object for manipulating options";
5587 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02005588 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
5589 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
5590 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02005591
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005592 vim_memset(&LoaderType, 0, sizeof(LoaderType));
5593 LoaderType.tp_name = "vim.Loader";
5594 LoaderType.tp_basicsize = sizeof(LoaderObject);
5595 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
5596 LoaderType.tp_doc = "vim message object";
5597 LoaderType.tp_methods = LoaderMethods;
5598 LoaderType.tp_dealloc = (destructor)LoaderDestructor;
5599
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005600#if PY_MAJOR_VERSION >= 3
5601 vim_memset(&vimmodule, 0, sizeof(vimmodule));
5602 vimmodule.m_name = "vim";
5603 vimmodule.m_doc = "Vim Python interface\n";
5604 vimmodule.m_size = -1;
5605 vimmodule.m_methods = VimMethods;
5606#endif
5607}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005608
5609#define PYTYPE_READY(type) \
5610 if (PyType_Ready(&type)) \
5611 return -1;
5612
5613 static int
5614init_types()
5615{
5616 PYTYPE_READY(IterType);
5617 PYTYPE_READY(BufferType);
5618 PYTYPE_READY(RangeType);
5619 PYTYPE_READY(WindowType);
5620 PYTYPE_READY(TabPageType);
5621 PYTYPE_READY(BufMapType);
5622 PYTYPE_READY(WinListType);
5623 PYTYPE_READY(TabListType);
5624 PYTYPE_READY(CurrentType);
5625 PYTYPE_READY(DictionaryType);
5626 PYTYPE_READY(ListType);
5627 PYTYPE_READY(FunctionType);
5628 PYTYPE_READY(OptionsType);
5629 PYTYPE_READY(OutputType);
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005630 PYTYPE_READY(LoaderType);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005631 return 0;
5632}
5633
5634 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02005635init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005636{
5637 PyObject *path;
5638 PyObject *path_hook;
5639 PyObject *path_hooks;
5640
5641 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
5642 return -1;
5643
5644 if (!(path_hooks = PySys_GetObject("path_hooks")))
5645 {
5646 PyErr_Clear();
5647 path_hooks = PyList_New(1);
5648 PyList_SET_ITEM(path_hooks, 0, path_hook);
5649 if (PySys_SetObject("path_hooks", path_hooks))
5650 {
5651 Py_DECREF(path_hooks);
5652 return -1;
5653 }
5654 Py_DECREF(path_hooks);
5655 }
5656 else if (PyList_Check(path_hooks))
5657 {
5658 if (PyList_Append(path_hooks, path_hook))
5659 {
5660 Py_DECREF(path_hook);
5661 return -1;
5662 }
5663 Py_DECREF(path_hook);
5664 }
5665 else
5666 {
5667 VimTryStart();
5668 EMSG(_("Failed to set path hook: sys.path_hooks is not a list\n"
5669 "You should now do the following:\n"
5670 "- append vim.path_hook to sys.path_hooks\n"
5671 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
5672 VimTryEnd(); /* Discard the error */
5673 Py_DECREF(path_hook);
5674 return 0;
5675 }
5676
5677 if (!(path = PySys_GetObject("path")))
5678 {
5679 PyErr_Clear();
5680 path = PyList_New(1);
5681 Py_INCREF(vim_special_path_object);
5682 PyList_SET_ITEM(path, 0, vim_special_path_object);
5683 if (PySys_SetObject("path", path))
5684 {
5685 Py_DECREF(path);
5686 return -1;
5687 }
5688 Py_DECREF(path);
5689 }
5690 else if (PyList_Check(path))
5691 {
5692 if (PyList_Append(path, vim_special_path_object))
5693 return -1;
5694 }
5695 else
5696 {
5697 VimTryStart();
5698 EMSG(_("Failed to set path: sys.path is not a list\n"
5699 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
5700 VimTryEnd(); /* Discard the error */
5701 }
5702
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005703 return 0;
5704}
5705
5706static BufMapObject TheBufferMap =
5707{
5708 PyObject_HEAD_INIT(&BufMapType)
5709};
5710
5711static WinListObject TheWindowList =
5712{
5713 PyObject_HEAD_INIT(&WinListType)
5714 NULL
5715};
5716
5717static CurrentObject TheCurrent =
5718{
5719 PyObject_HEAD_INIT(&CurrentType)
5720};
5721
5722static TabListObject TheTabPageList =
5723{
5724 PyObject_HEAD_INIT(&TabListType)
5725};
5726
5727static struct numeric_constant {
5728 char *name;
5729 int value;
5730} numeric_constants[] = {
5731 {"VAR_LOCKED", VAR_LOCKED},
5732 {"VAR_FIXED", VAR_FIXED},
5733 {"VAR_SCOPE", VAR_SCOPE},
5734 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
5735};
5736
5737static struct object_constant {
5738 char *name;
5739 PyObject *value;
5740} object_constants[] = {
5741 {"buffers", (PyObject *)(void *)&TheBufferMap},
5742 {"windows", (PyObject *)(void *)&TheWindowList},
5743 {"tabpages", (PyObject *)(void *)&TheTabPageList},
5744 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02005745
5746 {"Buffer", (PyObject *)&BufferType},
5747 {"Range", (PyObject *)&RangeType},
5748 {"Window", (PyObject *)&WindowType},
5749 {"TabPage", (PyObject *)&TabPageType},
5750 {"Dictionary", (PyObject *)&DictionaryType},
5751 {"List", (PyObject *)&ListType},
5752 {"Function", (PyObject *)&FunctionType},
5753 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005754 {"_Loader", (PyObject *)&LoaderType},
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005755};
5756
5757typedef int (*object_adder)(PyObject *, const char *, PyObject *);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005758typedef PyObject *(*attr_getter)(PyObject *, const char *);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005759
5760#define ADD_OBJECT(m, name, obj) \
5761 if (add_object(m, name, obj)) \
5762 return -1;
5763
5764#define ADD_CHECKED_OBJECT(m, name, obj) \
5765 { \
5766 PyObject *value = obj; \
5767 if (!value) \
5768 return -1; \
5769 ADD_OBJECT(m, name, value); \
5770 }
5771
5772 static int
Bram Moolenaarf4258302013-06-02 18:20:17 +02005773populate_module(PyObject *m, object_adder add_object, attr_getter get_attr)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005774{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005775 int i;
5776 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005777 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005778 PyObject *imp;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005779
5780 for (i = 0; i < (int)(sizeof(numeric_constants)
5781 / sizeof(struct numeric_constant));
5782 ++i)
5783 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
5784 PyInt_FromLong(numeric_constants[i].value));
5785
5786 for (i = 0; i < (int)(sizeof(object_constants)
5787 / sizeof(struct object_constant));
5788 ++i)
5789 {
5790 PyObject *value;
5791
5792 value = object_constants[i].value;
5793 Py_INCREF(value);
5794 ADD_OBJECT(m, object_constants[i].name, value);
5795 }
5796
5797 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
5798 return -1;
5799 ADD_OBJECT(m, "error", VimError);
5800
Bram Moolenaara9922d62013-05-30 13:01:18 +02005801 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(&globvardict));
5802 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005803 ADD_CHECKED_OBJECT(m, "options",
5804 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02005805
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005806 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005807 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005808 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005809
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005810 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005811 return -1;
5812 ADD_OBJECT(m, "_getcwd", py_getcwd)
5813
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005814 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005815 return -1;
5816 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005817 if (!(attr = get_attr(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005818 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005819 if (PyObject_SetAttrString(other_module, "chdir", attr))
5820 {
5821 Py_DECREF(attr);
5822 return -1;
5823 }
5824 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005825
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02005826 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005827 {
5828 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005829 if (!(attr = get_attr(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02005830 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02005831 if (PyObject_SetAttrString(other_module, "fchdir", attr))
5832 {
5833 Py_DECREF(attr);
5834 return -1;
5835 }
5836 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02005837 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02005838 else
5839 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02005840
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005841 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
5842 return -1;
5843
5844 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
5845
Bram Moolenaar81c40c52013-06-12 14:41:04 +02005846 if (!(imp = PyImport_ImportModule("imp")))
5847 return -1;
5848
5849 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
5850 {
5851 Py_DECREF(imp);
5852 return -1;
5853 }
5854
5855 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
5856 {
5857 Py_DECREF(py_find_module);
5858 Py_DECREF(imp);
5859 return -1;
5860 }
5861
5862 Py_DECREF(imp);
5863
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02005864 ADD_OBJECT(m, "_find_module", py_find_module);
5865 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02005866
Bram Moolenaar1dc28782013-05-21 19:11:01 +02005867 return 0;
5868}