blob: f78eccbd041ed1aa18557fed651f4c217c1bf60c [file] [log] [blame]
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02001/* vi:set ts=8 sts=4 sw=4:
2 *
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/*
10 * Python extensions by Paul Moore, David Leonard, Roland Puntaier.
11 *
12 * Common code for if_python.c and if_python3.c.
13 */
14
15/*
16 * obtain a lock on the Vim data structures
17 */
18 static void
19Python_Lock_Vim(void)
20{
21}
22
23/*
24 * release a lock on the Vim data structures
25 */
26 static void
27Python_Release_Vim(void)
28{
29}
30
31/* Output object definition
32 */
33
34static PyObject *OutputWrite(PyObject *, PyObject *);
35static PyObject *OutputWritelines(PyObject *, PyObject *);
Bram Moolenaara29a37d2011-03-22 15:47:44 +010036static PyObject *OutputFlush(PyObject *, PyObject *);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020037
Bram Moolenaar2eea1982010-09-21 16:49:37 +020038/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020039typedef void (*writefn)(char_u *);
40static void writer(writefn fn, char_u *str, PyInt n);
41
42typedef struct
43{
44 PyObject_HEAD
45 long softspace;
46 long error;
47} OutputObject;
48
49static struct PyMethodDef OutputMethods[] = {
50 /* name, function, calling, documentation */
Bram Moolenaara29a37d2011-03-22 15:47:44 +010051 {"write", OutputWrite, 1, ""},
52 {"writelines", OutputWritelines, 1, ""},
53 {"flush", OutputFlush, 1, ""},
54 { NULL, NULL, 0, NULL}
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020055};
56
Bram Moolenaarca8a4df2010-07-31 19:54:14 +020057#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
58
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020059/*************/
60
61/* Output buffer management
62 */
63
64 static PyObject *
65OutputWrite(PyObject *self, PyObject *args)
66{
67 int len;
68 char *str;
69 int error = ((OutputObject *)(self))->error;
70
71 if (!PyArg_ParseTuple(args, "s#", &str, &len))
72 return NULL;
73
74 Py_BEGIN_ALLOW_THREADS
75 Python_Lock_Vim();
76 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
77 Python_Release_Vim();
78 Py_END_ALLOW_THREADS
79
80 Py_INCREF(Py_None);
81 return Py_None;
82}
83
84 static PyObject *
85OutputWritelines(PyObject *self, PyObject *args)
86{
87 PyInt n;
88 PyInt i;
89 PyObject *list;
90 int error = ((OutputObject *)(self))->error;
91
92 if (!PyArg_ParseTuple(args, "O", &list))
93 return NULL;
94 Py_INCREF(list);
95
96 if (!PyList_Check(list)) {
97 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
98 Py_DECREF(list);
99 return NULL;
100 }
101
102 n = PyList_Size(list);
103
104 for (i = 0; i < n; ++i)
105 {
106 PyObject *line = PyList_GetItem(list, i);
107 char *str;
108 PyInt len;
109
110 if (!PyArg_Parse(line, "s#", &str, &len)) {
111 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
112 Py_DECREF(list);
113 return NULL;
114 }
115
116 Py_BEGIN_ALLOW_THREADS
117 Python_Lock_Vim();
118 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
119 Python_Release_Vim();
120 Py_END_ALLOW_THREADS
121 }
122
123 Py_DECREF(list);
124 Py_INCREF(Py_None);
125 return Py_None;
126}
127
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100128 static PyObject *
129OutputFlush(PyObject *self UNUSED, PyObject *args UNUSED)
130{
131 /* do nothing */
132 Py_INCREF(Py_None);
133 return Py_None;
134}
135
136
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200137/* Buffer IO, we write one whole line at a time. */
138static garray_T io_ga = {0, 0, 1, 80, NULL};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200139static writefn old_fn = NULL;
140
141 static void
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200142PythonIO_Flush(void)
143{
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200144 if (old_fn != NULL && io_ga.ga_len > 0)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200145 {
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200146 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
147 old_fn((char_u *)io_ga.ga_data);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200148 }
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200149 io_ga.ga_len = 0;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200150}
151
152 static void
153writer(writefn fn, char_u *str, PyInt n)
154{
155 char_u *ptr;
156
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200157 /* Flush when switching output function. */
158 if (fn != old_fn)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200159 PythonIO_Flush();
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200160 old_fn = fn;
161
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200162 /* Write each NL separated line. Text after the last NL is kept for
163 * writing later. */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200164 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
165 {
166 PyInt len = ptr - str;
167
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200168 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200169 break;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200170
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200171 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
172 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
173 fn((char_u *)io_ga.ga_data);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200174 str = ptr + 1;
175 n -= len + 1;
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200176 io_ga.ga_len = 0;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200177 }
178
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200179 /* Put the remaining text into io_ga for later printing. */
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200180 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200181 {
182 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200183 io_ga.ga_len += (int)n;
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200184 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200185}
186
187/***************/
188
189static PyTypeObject OutputType;
190
191static OutputObject Output =
192{
193 PyObject_HEAD_INIT(&OutputType)
194 0,
195 0
196};
197
198static OutputObject Error =
199{
200 PyObject_HEAD_INIT(&OutputType)
201 0,
202 1
203};
204
205 static int
206PythonIO_Init_io(void)
207{
208 PySys_SetObject("stdout", (PyObject *)(void *)&Output);
209 PySys_SetObject("stderr", (PyObject *)(void *)&Error);
210
211 if (PyErr_Occurred())
212 {
213 EMSG(_("E264: Python: Error initialising I/O objects"));
214 return -1;
215 }
216
217 return 0;
218}
219
220
221static PyObject *VimError;
222
223/* Check to see whether a Vim error has been reported, or a keyboard
224 * interrupt has been detected.
225 */
226 static int
227VimErrorCheck(void)
228{
229 if (got_int)
230 {
231 PyErr_SetNone(PyExc_KeyboardInterrupt);
232 return 1;
233 }
234 else if (did_emsg && !PyErr_Occurred())
235 {
236 PyErr_SetNone(VimError);
237 return 1;
238 }
239
240 return 0;
241}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200242
243/* Vim module - Implementation
244 */
245 static PyObject *
246VimCommand(PyObject *self UNUSED, PyObject *args)
247{
248 char *cmd;
249 PyObject *result;
250
251 if (!PyArg_ParseTuple(args, "s", &cmd))
252 return NULL;
253
254 PyErr_Clear();
255
256 Py_BEGIN_ALLOW_THREADS
257 Python_Lock_Vim();
258
259 do_cmdline_cmd((char_u *)cmd);
260 update_screen(VALID);
261
262 Python_Release_Vim();
263 Py_END_ALLOW_THREADS
264
265 if (VimErrorCheck())
266 result = NULL;
267 else
268 result = Py_None;
269
270 Py_XINCREF(result);
271 return result;
272}
273
274#ifdef FEAT_EVAL
275/*
276 * Function to translate a typval_T into a PyObject; this will recursively
277 * translate lists/dictionaries into their Python equivalents.
278 *
279 * The depth parameter is to avoid infinite recursion, set it to 1 when
280 * you call VimToPython.
281 */
282 static PyObject *
283VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
284{
285 PyObject *result;
286 PyObject *newObj;
287 char ptrBuf[NUMBUFLEN];
288
289 /* Avoid infinite recursion */
290 if (depth > 100)
291 {
292 Py_INCREF(Py_None);
293 result = Py_None;
294 return result;
295 }
296
297 /* Check if we run into a recursive loop. The item must be in lookupDict
298 * then and we can use it again. */
299 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
300 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
301 {
302 sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U,
303 our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list
304 : (long_u)our_tv->vval.v_dict);
305 result = PyDict_GetItemString(lookupDict, ptrBuf);
306 if (result != NULL)
307 {
308 Py_INCREF(result);
309 return result;
310 }
311 }
312
313 if (our_tv->v_type == VAR_STRING)
314 {
315 result = Py_BuildValue("s", our_tv->vval.v_string);
316 }
317 else if (our_tv->v_type == VAR_NUMBER)
318 {
319 char buf[NUMBUFLEN];
320
321 /* For backwards compatibility numbers are stored as strings. */
322 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
323 result = Py_BuildValue("s", buf);
324 }
325# ifdef FEAT_FLOAT
326 else if (our_tv->v_type == VAR_FLOAT)
327 {
328 char buf[NUMBUFLEN];
329
330 sprintf(buf, "%f", our_tv->vval.v_float);
331 result = Py_BuildValue("s", buf);
332 }
333# endif
334 else if (our_tv->v_type == VAR_LIST)
335 {
336 list_T *list = our_tv->vval.v_list;
337 listitem_T *curr;
338
339 result = PyList_New(0);
340
341 if (list != NULL)
342 {
343 PyDict_SetItemString(lookupDict, ptrBuf, result);
344
345 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
346 {
347 newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict);
348 PyList_Append(result, newObj);
349 Py_DECREF(newObj);
350 }
351 }
352 }
353 else if (our_tv->v_type == VAR_DICT)
354 {
355 result = PyDict_New();
356
357 if (our_tv->vval.v_dict != NULL)
358 {
359 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
360 long_u todo = ht->ht_used;
361 hashitem_T *hi;
362 dictitem_T *di;
363
364 PyDict_SetItemString(lookupDict, ptrBuf, result);
365
366 for (hi = ht->ht_array; todo > 0; ++hi)
367 {
368 if (!HASHITEM_EMPTY(hi))
369 {
370 --todo;
371
372 di = dict_lookup(hi);
373 newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
374 PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
375 Py_DECREF(newObj);
376 }
377 }
378 }
379 }
380 else
381 {
382 Py_INCREF(Py_None);
383 result = Py_None;
384 }
385
386 return result;
387}
388#endif
389
390 static PyObject *
Bram Moolenaar09092152010-08-08 16:38:42 +0200391VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200392{
393#ifdef FEAT_EVAL
394 char *expr;
395 typval_T *our_tv;
396 PyObject *result;
397 PyObject *lookup_dict;
398
399 if (!PyArg_ParseTuple(args, "s", &expr))
400 return NULL;
401
402 Py_BEGIN_ALLOW_THREADS
403 Python_Lock_Vim();
404 our_tv = eval_expr((char_u *)expr, NULL);
405
406 Python_Release_Vim();
407 Py_END_ALLOW_THREADS
408
409 if (our_tv == NULL)
410 {
411 PyErr_SetVim(_("invalid expression"));
412 return NULL;
413 }
414
415 /* Convert the Vim type into a Python type. Create a dictionary that's
416 * used to check for recursive loops. */
417 lookup_dict = PyDict_New();
418 result = VimToPython(our_tv, 1, lookup_dict);
419 Py_DECREF(lookup_dict);
420
421
422 Py_BEGIN_ALLOW_THREADS
423 Python_Lock_Vim();
424 free_tv(our_tv);
425 Python_Release_Vim();
426 Py_END_ALLOW_THREADS
427
428 return result;
429#else
430 PyErr_SetVim(_("expressions disabled at compile time"));
431 return NULL;
432#endif
433}
434
435/*
436 * Vim module - Definitions
437 */
438
439static struct PyMethodDef VimMethods[] = {
440 /* name, function, calling, documentation */
441 {"command", VimCommand, 1, "Execute a Vim ex-mode command" },
442 {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" },
443 { NULL, NULL, 0, NULL }
444};
445
446typedef struct
447{
448 PyObject_HEAD
449 buf_T *buf;
450}
451BufferObject;
452
453#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
454
455/*
456 * Buffer list object - Implementation
457 */
458
459 static PyInt
460BufListLength(PyObject *self UNUSED)
461{
462 buf_T *b = firstbuf;
463 PyInt n = 0;
464
465 while (b)
466 {
467 ++n;
468 b = b->b_next;
469 }
470
471 return n;
472}
473
474 static PyObject *
475BufListItem(PyObject *self UNUSED, PyInt n)
476{
477 buf_T *b;
478
479 for (b = firstbuf; b; b = b->b_next, --n)
480 {
481 if (n == 0)
482 return BufferNew(b);
483 }
484
485 PyErr_SetString(PyExc_IndexError, _("no such buffer"));
486 return NULL;
487}
488
489typedef struct
490{
491 PyObject_HEAD
492 win_T *win;
493} WindowObject;
494
495#define INVALID_WINDOW_VALUE ((win_T *)(-1))
496
497 static int
498CheckWindow(WindowObject *this)
499{
500 if (this->win == INVALID_WINDOW_VALUE)
501 {
502 PyErr_SetVim(_("attempt to refer to deleted window"));
503 return -1;
504 }
505
506 return 0;
507}
508
509static int WindowSetattr(PyObject *, char *, PyObject *);
510static PyObject *WindowRepr(PyObject *);
511
512 static int
513WindowSetattr(PyObject *self, char *name, PyObject *val)
514{
515 WindowObject *this = (WindowObject *)(self);
516
517 if (CheckWindow(this))
518 return -1;
519
520 if (strcmp(name, "buffer") == 0)
521 {
522 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
523 return -1;
524 }
525 else if (strcmp(name, "cursor") == 0)
526 {
527 long lnum;
528 long col;
529 long len;
530
531 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
532 return -1;
533
534 if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count)
535 {
536 PyErr_SetVim(_("cursor position outside buffer"));
537 return -1;
538 }
539
540 /* Check for keyboard interrupts */
541 if (VimErrorCheck())
542 return -1;
543
544 /* When column is out of range silently correct it. */
545 len = (long)STRLEN(ml_get_buf(this->win->w_buffer, lnum, FALSE));
546 if (col > len)
547 col = len;
548
549 this->win->w_cursor.lnum = lnum;
550 this->win->w_cursor.col = col;
551#ifdef FEAT_VIRTUALEDIT
552 this->win->w_cursor.coladd = 0;
553#endif
554 update_screen(VALID);
555
556 return 0;
557 }
558 else if (strcmp(name, "height") == 0)
559 {
560 int height;
561 win_T *savewin;
562
563 if (!PyArg_Parse(val, "i", &height))
564 return -1;
565
566#ifdef FEAT_GUI
567 need_mouse_correct = TRUE;
568#endif
569 savewin = curwin;
570 curwin = this->win;
571 win_setheight(height);
572 curwin = savewin;
573
574 /* Check for keyboard interrupts */
575 if (VimErrorCheck())
576 return -1;
577
578 return 0;
579 }
580#ifdef FEAT_VERTSPLIT
581 else if (strcmp(name, "width") == 0)
582 {
583 int width;
584 win_T *savewin;
585
586 if (!PyArg_Parse(val, "i", &width))
587 return -1;
588
589#ifdef FEAT_GUI
590 need_mouse_correct = TRUE;
591#endif
592 savewin = curwin;
593 curwin = this->win;
594 win_setwidth(width);
595 curwin = savewin;
596
597 /* Check for keyboard interrupts */
598 if (VimErrorCheck())
599 return -1;
600
601 return 0;
602 }
603#endif
604 else
605 {
606 PyErr_SetString(PyExc_AttributeError, name);
607 return -1;
608 }
609}
610
611 static PyObject *
612WindowRepr(PyObject *self)
613{
614 static char repr[100];
615 WindowObject *this = (WindowObject *)(self);
616
617 if (this->win == INVALID_WINDOW_VALUE)
618 {
619 vim_snprintf(repr, 100, _("<window object (deleted) at %p>"), (self));
620 return PyString_FromString(repr);
621 }
622 else
623 {
624 int i = 0;
625 win_T *w;
626
627 for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w))
628 ++i;
629
630 if (w == NULL)
631 vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
632 (self));
633 else
634 vim_snprintf(repr, 100, _("<window %d>"), i);
635
636 return PyString_FromString(repr);
637 }
638}
639
640/*
641 * Window list object - Implementation
642 */
643 static PyInt
644WinListLength(PyObject *self UNUSED)
645{
646 win_T *w = firstwin;
647 PyInt n = 0;
648
649 while (w != NULL)
650 {
651 ++n;
652 w = W_NEXT(w);
653 }
654
655 return n;
656}
657
658 static PyObject *
659WinListItem(PyObject *self UNUSED, PyInt n)
660{
661 win_T *w;
662
663 for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
664 if (n == 0)
665 return WindowNew(w);
666
667 PyErr_SetString(PyExc_IndexError, _("no such window"));
668 return NULL;
669}
670
671/* Convert a Python string into a Vim line.
672 *
673 * The result is in allocated memory. All internal nulls are replaced by
674 * newline characters. It is an error for the string to contain newline
675 * characters.
676 *
677 * On errors, the Python exception data is set, and NULL is returned.
678 */
679 static char *
680StringToLine(PyObject *obj)
681{
682 const char *str;
683 char *save;
684 PyInt len;
685 PyInt i;
686 char *p;
687
688 if (obj == NULL || !PyString_Check(obj))
689 {
690 PyErr_BadArgument();
691 return NULL;
692 }
693
694 str = PyString_AsString(obj);
695 len = PyString_Size(obj);
696
697 /*
698 * Error checking: String must not contain newlines, as we
699 * are replacing a single line, and we must replace it with
700 * a single line.
701 * A trailing newline is removed, so that append(f.readlines()) works.
702 */
703 p = memchr(str, '\n', len);
704 if (p != NULL)
705 {
706 if (p == str + len - 1)
707 --len;
708 else
709 {
710 PyErr_SetVim(_("string cannot contain newlines"));
711 return NULL;
712 }
713 }
714
715 /* Create a copy of the string, with internal nulls replaced by
716 * newline characters, as is the vim convention.
717 */
718 save = (char *)alloc((unsigned)(len+1));
719 if (save == NULL)
720 {
721 PyErr_NoMemory();
722 return NULL;
723 }
724
725 for (i = 0; i < len; ++i)
726 {
727 if (str[i] == '\0')
728 save[i] = '\n';
729 else
730 save[i] = str[i];
731 }
732
733 save[i] = '\0';
734
735 return save;
736}
737
738/* Get a line from the specified buffer. The line number is
739 * in Vim format (1-based). The line is returned as a Python
740 * string object.
741 */
742 static PyObject *
743GetBufferLine(buf_T *buf, PyInt n)
744{
745 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
746}
747
748
749/* Get a list of lines from the specified buffer. The line numbers
750 * are in Vim format (1-based). The range is from lo up to, but not
751 * including, hi. The list is returned as a Python list of string objects.
752 */
753 static PyObject *
754GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
755{
756 PyInt i;
757 PyInt n = hi - lo;
758 PyObject *list = PyList_New(n);
759
760 if (list == NULL)
761 return NULL;
762
763 for (i = 0; i < n; ++i)
764 {
765 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
766
767 /* Error check - was the Python string creation OK? */
768 if (str == NULL)
769 {
770 Py_DECREF(list);
771 return NULL;
772 }
773
774 /* Set the list item */
775 if (PyList_SetItem(list, i, str))
776 {
777 Py_DECREF(str);
778 Py_DECREF(list);
779 return NULL;
780 }
781 }
782
783 /* The ownership of the Python list is passed to the caller (ie,
784 * the caller should Py_DECREF() the object when it is finished
785 * with it).
786 */
787
788 return list;
789}
790
791/*
792 * Check if deleting lines made the cursor position invalid.
793 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
794 * deleted).
795 */
796 static void
797py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
798{
799 if (curwin->w_cursor.lnum >= lo)
800 {
801 /* Adjust the cursor position if it's in/after the changed
802 * lines. */
803 if (curwin->w_cursor.lnum >= hi)
804 {
805 curwin->w_cursor.lnum += extra;
806 check_cursor_col();
807 }
808 else if (extra < 0)
809 {
810 curwin->w_cursor.lnum = lo;
811 check_cursor();
812 }
813 else
814 check_cursor_col();
815 changed_cline_bef_curs();
816 }
817 invalidate_botline();
818}
819
820/* Replace a line in the specified buffer. The line number is
821 * in Vim format (1-based). The replacement line is given as
822 * a Python string object. The object is checked for validity
823 * and correct format. Errors are returned as a value of FAIL.
824 * The return value is OK on success.
825 * If OK is returned and len_change is not NULL, *len_change
826 * is set to the change in the buffer length.
827 */
828 static int
829SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
830{
831 /* First of all, we check the thpe of the supplied Python object.
832 * There are three cases:
833 * 1. NULL, or None - this is a deletion.
834 * 2. A string - this is a replacement.
835 * 3. Anything else - this is an error.
836 */
837 if (line == Py_None || line == NULL)
838 {
839 buf_T *savebuf = curbuf;
840
841 PyErr_Clear();
842 curbuf = buf;
843
844 if (u_savedel((linenr_T)n, 1L) == FAIL)
845 PyErr_SetVim(_("cannot save undo information"));
846 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
847 PyErr_SetVim(_("cannot delete line"));
848 else
849 {
850 if (buf == curwin->w_buffer)
851 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
852 deleted_lines_mark((linenr_T)n, 1L);
853 }
854
855 curbuf = savebuf;
856
857 if (PyErr_Occurred() || VimErrorCheck())
858 return FAIL;
859
860 if (len_change)
861 *len_change = -1;
862
863 return OK;
864 }
865 else if (PyString_Check(line))
866 {
867 char *save = StringToLine(line);
868 buf_T *savebuf = curbuf;
869
870 if (save == NULL)
871 return FAIL;
872
873 /* We do not need to free "save" if ml_replace() consumes it. */
874 PyErr_Clear();
875 curbuf = buf;
876
877 if (u_savesub((linenr_T)n) == FAIL)
878 {
879 PyErr_SetVim(_("cannot save undo information"));
880 vim_free(save);
881 }
882 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
883 {
884 PyErr_SetVim(_("cannot replace line"));
885 vim_free(save);
886 }
887 else
888 changed_bytes((linenr_T)n, 0);
889
890 curbuf = savebuf;
891
892 /* Check that the cursor is not beyond the end of the line now. */
893 if (buf == curwin->w_buffer)
894 check_cursor_col();
895
896 if (PyErr_Occurred() || VimErrorCheck())
897 return FAIL;
898
899 if (len_change)
900 *len_change = 0;
901
902 return OK;
903 }
904 else
905 {
906 PyErr_BadArgument();
907 return FAIL;
908 }
909}
910
911
912/* Insert a number of lines into the specified buffer after the specifed line.
913 * The line number is in Vim format (1-based). The lines to be inserted are
914 * given as a Python list of string objects or as a single string. The lines
915 * to be added are checked for validity and correct format. Errors are
916 * returned as a value of FAIL. The return value is OK on success.
917 * If OK is returned and len_change is not NULL, *len_change
918 * is set to the change in the buffer length.
919 */
920 static int
921InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
922{
923 /* First of all, we check the type of the supplied Python object.
924 * It must be a string or a list, or the call is in error.
925 */
926 if (PyString_Check(lines))
927 {
928 char *str = StringToLine(lines);
929 buf_T *savebuf;
930
931 if (str == NULL)
932 return FAIL;
933
934 savebuf = curbuf;
935
936 PyErr_Clear();
937 curbuf = buf;
938
939 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
940 PyErr_SetVim(_("cannot save undo information"));
941 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
942 PyErr_SetVim(_("cannot insert line"));
943 else
944 appended_lines_mark((linenr_T)n, 1L);
945
946 vim_free(str);
947 curbuf = savebuf;
948 update_screen(VALID);
949
950 if (PyErr_Occurred() || VimErrorCheck())
951 return FAIL;
952
953 if (len_change)
954 *len_change = 1;
955
956 return OK;
957 }
958 else if (PyList_Check(lines))
959 {
960 PyInt i;
961 PyInt size = PyList_Size(lines);
962 char **array;
963 buf_T *savebuf;
964
965 array = (char **)alloc((unsigned)(size * sizeof(char *)));
966 if (array == NULL)
967 {
968 PyErr_NoMemory();
969 return FAIL;
970 }
971
972 for (i = 0; i < size; ++i)
973 {
974 PyObject *line = PyList_GetItem(lines, i);
975 array[i] = StringToLine(line);
976
977 if (array[i] == NULL)
978 {
979 while (i)
980 vim_free(array[--i]);
981 vim_free(array);
982 return FAIL;
983 }
984 }
985
986 savebuf = curbuf;
987
988 PyErr_Clear();
989 curbuf = buf;
990
991 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
992 PyErr_SetVim(_("cannot save undo information"));
993 else
994 {
995 for (i = 0; i < size; ++i)
996 {
997 if (ml_append((linenr_T)(n + i),
998 (char_u *)array[i], 0, FALSE) == FAIL)
999 {
1000 PyErr_SetVim(_("cannot insert line"));
1001
1002 /* Free the rest of the lines */
1003 while (i < size)
1004 vim_free(array[i++]);
1005
1006 break;
1007 }
1008 vim_free(array[i]);
1009 }
1010 if (i > 0)
1011 appended_lines_mark((linenr_T)n, (long)i);
1012 }
1013
1014 /* Free the array of lines. All of its contents have now
1015 * been freed.
1016 */
1017 vim_free(array);
1018
1019 curbuf = savebuf;
1020 update_screen(VALID);
1021
1022 if (PyErr_Occurred() || VimErrorCheck())
1023 return FAIL;
1024
1025 if (len_change)
1026 *len_change = size;
1027
1028 return OK;
1029 }
1030 else
1031 {
1032 PyErr_BadArgument();
1033 return FAIL;
1034 }
1035}
1036
1037/*
1038 * Common routines for buffers and line ranges
1039 * -------------------------------------------
1040 */
1041
1042 static int
1043CheckBuffer(BufferObject *this)
1044{
1045 if (this->buf == INVALID_BUFFER_VALUE)
1046 {
1047 PyErr_SetVim(_("attempt to refer to deleted buffer"));
1048 return -1;
1049 }
1050
1051 return 0;
1052}
1053
1054 static PyObject *
1055RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
1056{
1057 if (CheckBuffer(self))
1058 return NULL;
1059
1060 if (n < 0 || n > end - start)
1061 {
1062 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
1063 return NULL;
1064 }
1065
1066 return GetBufferLine(self->buf, n+start);
1067}
1068
1069 static PyObject *
1070RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
1071{
1072 PyInt size;
1073
1074 if (CheckBuffer(self))
1075 return NULL;
1076
1077 size = end - start + 1;
1078
1079 if (lo < 0)
1080 lo = 0;
1081 else if (lo > size)
1082 lo = size;
1083 if (hi < 0)
1084 hi = 0;
1085 if (hi < lo)
1086 hi = lo;
1087 else if (hi > size)
1088 hi = size;
1089
1090 return GetBufferLineList(self->buf, lo+start, hi+start);
1091}
1092
1093 static PyInt
1094RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
1095{
1096 PyInt len_change;
1097
1098 if (CheckBuffer(self))
1099 return -1;
1100
1101 if (n < 0 || n > end - start)
1102 {
1103 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
1104 return -1;
1105 }
1106
1107 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
1108 return -1;
1109
1110 if (new_end)
1111 *new_end = end + len_change;
1112
1113 return 0;
1114}
1115
1116
1117 static PyObject *
1118RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
1119{
1120 PyObject *lines;
1121 PyInt len_change;
1122 PyInt max;
1123 PyInt n;
1124
1125 if (CheckBuffer(self))
1126 return NULL;
1127
1128 max = n = end - start + 1;
1129
1130 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
1131 return NULL;
1132
1133 if (n < 0 || n > max)
1134 {
1135 PyErr_SetString(PyExc_ValueError, _("line number out of range"));
1136 return NULL;
1137 }
1138
1139 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
1140 return NULL;
1141
1142 if (new_end)
1143 *new_end = end + len_change;
1144
1145 Py_INCREF(Py_None);
1146 return Py_None;
1147}
1148
1149
1150/* Buffer object - Definitions
1151 */
1152
1153typedef struct
1154{
1155 PyObject_HEAD
1156 BufferObject *buf;
1157 PyInt start;
1158 PyInt end;
1159} RangeObject;
1160
1161 static PyObject *
1162RangeNew(buf_T *buf, PyInt start, PyInt end)
1163{
1164 BufferObject *bufr;
1165 RangeObject *self;
1166 self = PyObject_NEW(RangeObject, &RangeType);
1167 if (self == NULL)
1168 return NULL;
1169
1170 bufr = (BufferObject *)BufferNew(buf);
1171 if (bufr == NULL)
1172 {
1173 Py_DECREF(self);
1174 return NULL;
1175 }
1176 Py_INCREF(bufr);
1177
1178 self->buf = bufr;
1179 self->start = start;
1180 self->end = end;
1181
1182 return (PyObject *)(self);
1183}
1184
1185 static PyObject *
1186BufferAppend(PyObject *self, PyObject *args)
1187{
1188 return RBAppend((BufferObject *)(self), args, 1,
1189 (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
1190 NULL);
1191}
1192
1193 static PyObject *
1194BufferMark(PyObject *self, PyObject *args)
1195{
1196 pos_T *posp;
1197 char *pmark;
1198 char mark;
1199 buf_T *curbuf_save;
1200
1201 if (CheckBuffer((BufferObject *)(self)))
1202 return NULL;
1203
1204 if (!PyArg_ParseTuple(args, "s", &pmark))
1205 return NULL;
1206 mark = *pmark;
1207
1208 curbuf_save = curbuf;
1209 curbuf = ((BufferObject *)(self))->buf;
1210 posp = getmark(mark, FALSE);
1211 curbuf = curbuf_save;
1212
1213 if (posp == NULL)
1214 {
1215 PyErr_SetVim(_("invalid mark name"));
1216 return NULL;
1217 }
1218
1219 /* Ckeck for keyboard interrupt */
1220 if (VimErrorCheck())
1221 return NULL;
1222
1223 if (posp->lnum <= 0)
1224 {
1225 /* Or raise an error? */
1226 Py_INCREF(Py_None);
1227 return Py_None;
1228 }
1229
1230 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
1231}
1232
1233 static PyObject *
1234BufferRange(PyObject *self, PyObject *args)
1235{
1236 PyInt start;
1237 PyInt end;
1238
1239 if (CheckBuffer((BufferObject *)(self)))
1240 return NULL;
1241
1242 if (!PyArg_ParseTuple(args, "nn", &start, &end))
1243 return NULL;
1244
1245 return RangeNew(((BufferObject *)(self))->buf, start, end);
1246}
1247
1248static struct PyMethodDef BufferMethods[] = {
1249 /* name, function, calling, documentation */
1250 {"append", BufferAppend, 1, "Append data to Vim buffer" },
1251 {"mark", BufferMark, 1, "Return (row,col) representing position of named mark" },
1252 {"range", BufferRange, 1, "Return a range object which represents the part of the given buffer between line numbers s and e" },
1253 { NULL, NULL, 0, NULL }
1254};
1255
1256 static PyObject *
1257RangeAppend(PyObject *self, PyObject *args)
1258{
1259 return RBAppend(((RangeObject *)(self))->buf, args,
1260 ((RangeObject *)(self))->start,
1261 ((RangeObject *)(self))->end,
1262 &((RangeObject *)(self))->end);
1263}
1264
1265 static PyInt
1266RangeLength(PyObject *self)
1267{
1268 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
1269 if (CheckBuffer(((RangeObject *)(self))->buf))
1270 return -1; /* ??? */
1271
1272 return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1);
1273}
1274
1275 static PyObject *
1276RangeItem(PyObject *self, PyInt n)
1277{
1278 return RBItem(((RangeObject *)(self))->buf, n,
1279 ((RangeObject *)(self))->start,
1280 ((RangeObject *)(self))->end);
1281}
1282
1283 static PyObject *
1284RangeRepr(PyObject *self)
1285{
1286 static char repr[100];
1287 RangeObject *this = (RangeObject *)(self);
1288
1289 if (this->buf->buf == INVALID_BUFFER_VALUE)
1290 {
1291 vim_snprintf(repr, 100, "<range object (for deleted buffer) at %p>",
1292 (self));
1293 return PyString_FromString(repr);
1294 }
1295 else
1296 {
1297 char *name = (char *)this->buf->buf->b_fname;
1298 int len;
1299
1300 if (name == NULL)
1301 name = "";
1302 len = (int)strlen(name);
1303
1304 if (len > 45)
1305 name = name + (45 - len);
1306
1307 vim_snprintf(repr, 100, "<range %s%s (%d:%d)>",
1308 len > 45 ? "..." : "", name,
1309 this->start, this->end);
1310
1311 return PyString_FromString(repr);
1312 }
1313}
1314
1315 static PyObject *
1316RangeSlice(PyObject *self, PyInt lo, PyInt hi)
1317{
1318 return RBSlice(((RangeObject *)(self))->buf, lo, hi,
1319 ((RangeObject *)(self))->start,
1320 ((RangeObject *)(self))->end);
1321}
1322
1323/*
1324 * Line range object - Definitions
1325 */
1326
1327static struct PyMethodDef RangeMethods[] = {
1328 /* name, function, calling, documentation */
1329 {"append", RangeAppend, 1, "Append data to the Vim range" },
1330 { NULL, NULL, 0, NULL }
1331};
1332