]> git.neil.brown.name Git - edlib.git/blob - lang-python.c
TODO: clean out done items.
[edlib.git] / lang-python.c
1 /*
2  * Copyright Neil Brown ©2015-2023 <neil@brown.name>
3  * May be distributed under terms of GPLv2 - see file:COPYING
4  *
5  * Python3 bindings for edlib.
6  * An edlib command "global-load-modules:python" will read and execute
7  * a python module.
8  * It must "import edlib" and it can use "edlib.editor" to get the editor
9  * instance.
10  *
11  * Types available are:
12  *  edlib.pane  - a generic pane.  These form a tree of which edlib.editor
13  *                is the root.
14  *                get/set operations for x,y,z,w,h,cx,cy as numbers
15  *                     changes x,y,w,h call pane_resize()
16  *                     z cannot be changed (only pane_register() does that )
17  *                     cx,cy can be changed freely.
18  *                  'parent' and 'focus' can be read but not written
19  *                method for 'children' provides first child as an iterator.
20  *                method abs() converts relative co-ords to absolute.
21  *                rel() converts absolute co-ords to relative.
22  *  edlib.mark  - these reference locations in a document.  The document is
23  *                not directly accessible, it can only be accessed through
24  *                a pane (which may translate events and results).
25  *                get/set for viewnum (cannot be set)
26  *                iterator for both 'all' and 'view' lists.
27  *                no methods yet.
28  *
29  *  edlib.comm  - a command which can be used to invoke code in other
30  *                module editors.  These look like any other python
31  *                callable.  They cannot be explicitly created, but can
32  *                be received from and passed to other commands.
33  *
34  */
35
36 #ifdef __CHECKER__
37 /* Need to define stuff that pyconfig needs */
38 #define __linux__
39 #define __x86_64__
40 #define __LP64__
41
42 //#define PyType_HasFeature __PyType_HasFeature
43 #include <Python.h>
44 #undef PyType_HasFeature __PyType_HasFeature
45 int PyType_HasFeature(PyTypeObject *type, unsigned long feature);
46
47 #undef Py_INCREF
48 #define Py_INCREF(op) (0)
49 #undef Py_DECREF
50 #define Py_DECREF(op) (0)
51 #undef Py_XDECREF
52 #define Py_XDECREF(op) (0)
53 #undef Py_IS_TYPE
54 #define Py_IS_TYPE(ob, type) (ob == (void*)type)
55 #else /* CHECKER */
56 #include <Python.h>
57 #endif
58 struct Mark;
59 #define MARK_DATA_PTR struct Mark
60 #define PRIVATE_DOC_REF
61
62 struct doc_ref {
63         PyObject *c;
64         int o;
65 };
66
67 #include <fcntl.h>
68 #include <signal.h>
69
70 #define DOC_DATA_TYPE struct python_doc
71 #define PANE_DATA_PTR_TYPE struct Pane *
72 struct Pane;
73 #include "core.h"
74 #include "misc.h"
75 #include "rexel.h"
76
77 struct python_doc {
78         struct doc      doc;
79         struct pydoc    *pdoc;
80 };
81
82 #include "core-pane.h"
83
84 #define SAFE_CI {.key=safe_cast NULL,\
85                  .home=safe_cast NULL,\
86                  .focus=safe_cast NULL,\
87                  .comm=safe_cast NULL,\
88         }
89
90 static PyObject *Edlib_CommandFailed;
91 static PyObject *EdlibModule;
92
93 static struct pane *ed_pane;
94
95 static char *module_dir;
96 static char *python_as_string(PyObject *s, PyObject **tofree safe);
97
98 /* Python commands visible to edlib are wrapped in
99  * the python_command.  There is only one per callback,
100  * so that edlib code can compare for equalty.
101  */
102 struct python_command {
103         struct command  c;
104         PyObject        *callable;
105         struct list_head lst;
106 };
107 static LIST_HEAD(exported_commands);
108
109 DEF_CMD(python_call);
110 DEF_CMD(python_pane_call);
111 DEF_CMD(python_doc_call);
112 static void python_free_command(struct command *c safe);
113
114 static struct python_command *export_callable(PyObject *callable safe,
115                                               PyObject *nm)
116 {
117         struct python_command *c;
118         const char *name = NULL;
119         int len;
120
121         if (nm && PyUnicode_Check(nm))
122                 name = PyUnicode_AsUTF8(nm);
123         if (!name)
124                 name = "";
125         len = strlen(name);
126
127         list_for_each_entry(c, &exported_commands, lst)
128                 if (c->callable == callable) {
129                         command_get(&c->c);
130                         return c;
131                 }
132
133         c = malloc(sizeof(*c));
134         c->c = python_call;
135         c->c.free = python_free_command;
136         c->c.refcnt = 0;
137         if (strcmp(name, "handle_close") == 0 ||
138             (len > 10 &&
139              strcmp(name+len-10, "_closed_ok") == 0))
140                 c->c.closed_ok = 1;
141         else
142                 c->c.closed_ok = 0;
143         command_get(&c->c);
144         Py_INCREF(callable);
145         c->callable = callable;
146         list_add(&c->lst, &exported_commands);
147         return c;
148 }
149
150 typedef struct Pane {
151         PyObject_HEAD;
152         struct pane     *pane;
153         struct command  cmd;
154         struct map      *map;
155         int             map_init;
156 } Pane;
157 static PyTypeObject PaneType;
158
159 typedef struct {
160         PyObject_HEAD;
161         struct pane     *pane;
162 } PaneIter;
163 static PyTypeObject PaneIterType;
164
165 typedef struct pydoc {
166         PyObject_HEAD;
167         struct pane     *pane;
168         struct command  cmd;
169         struct map      *map;
170         int             map_init;
171 } Doc;
172 static PyTypeObject DocType;
173
174 typedef struct Mark {
175         PyObject_HEAD;
176         struct mark     *mark;
177 } Mark;
178 static PyTypeObject MarkType;
179 static void mark_refcnt(struct mark *m safe, int inc);
180
181 typedef struct {
182         PyObject_HEAD;
183         struct command  *comm;
184 } Comm;
185 static PyTypeObject CommType;
186
187 static inline bool pane_valid(Pane *p safe)
188 {
189         if (p->pane && p->pane->handle)
190                 return True;
191         PyErr_SetString(PyExc_TypeError, "Pane has been freed");
192         return False;
193 }
194
195 static inline bool doc_valid(Doc *p safe)
196 {
197         if (p->pane && p->pane->handle)
198                 return True;
199         PyErr_SetString(PyExc_TypeError, "Doc pane has been freed");
200         return False;
201 }
202
203 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
204                          PyObject **s1 safe, PyObject **s2 safe);
205
206 static int in_pane_frompane = 0;
207 static inline PyObject *safe Pane_Frompane(struct pane *p)
208 {
209         Pane *pane;
210         if (p && p->handle && p->handle->func == python_pane_call.func) {
211                 pane = p->data;
212                 Py_INCREF(pane);
213         } else if (p && p->handle && p->handle->func == python_doc_call.func) {
214                 struct python_doc *pd = p->doc_data;
215                 Doc *pdoc = pd->pdoc;
216                 pane = (Pane*)pdoc;
217                 Py_INCREF(pane);
218         } else {
219                 in_pane_frompane = 1;
220                 pane = (Pane *)PyObject_CallObject((PyObject*)&PaneType, NULL);
221                 in_pane_frompane = 0;
222                 if (!pane)
223                         ;
224                 else if (p)
225                         pane->pane = pane_get(p);
226                 else
227                         pane->pane = p;
228         }
229         return (PyObject*)pane;
230 }
231
232 static inline PyObject *safe Mark_Frommark(struct mark *m safe)
233 {
234         Mark *mark;
235
236         if (mark_valid(m) && m->mtype == &MarkType && m->mdata) {
237                 /* This is a vmark, re-use the PyObject */
238                 Py_INCREF(m->mdata);
239                 return (PyObject*)m->mdata;
240         }
241         mark = (Mark *)PyObject_CallObject((PyObject*)&MarkType, NULL);
242         if (mark && mark_valid(m))
243                 mark->mark = m;
244         return (PyObject*)mark;
245 }
246
247 static inline PyObject *safe Comm_Fromcomm(struct command *c safe)
248 {
249         Comm *comm = (Comm *)PyObject_CallObject((PyObject*)&CommType, NULL);
250         if (comm)
251                 comm->comm = command_get(c);
252         return (PyObject*)comm;
253 }
254
255 static PyObject *py_LOG(PyObject *self, PyObject *args);
256 static void PyErr_LOG(void)
257 {
258         /* cribbed from https://groups.google.com/forum/#!topic/comp.lang.python/khLrxC6EOKc */
259         char *errorMsg = NULL;
260         PyObject *modIO = NULL;
261         PyObject *modTB = NULL;
262         PyObject *obFuncStringIO = NULL;
263         PyObject *obIO = NULL;
264         PyObject *obFuncTB = NULL;
265         PyObject *argsTB = NULL;
266         PyObject *obResult = NULL;
267         PyObject *tofree = NULL;
268         PyObject *exc_typ, *exc_val, *exc_tb;
269
270         if (!PyErr_Occurred())
271                 return;
272
273         PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
274         PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
275         if (exc_tb)
276                 PyException_SetTraceback(exc_val, exc_tb);
277
278         /* Import the modules we need - StringIO and traceback */
279         errorMsg = "Can't import io";
280         modIO = PyImport_ImportModule("io");
281         if (!modIO)
282                 goto out;
283
284         errorMsg = "Can't import traceback";
285         modTB = PyImport_ImportModule("traceback");
286         if (!modTB)
287                 goto out;
288
289         /* Construct a cStringIO object */
290         errorMsg = "Can't find io.StringIO";
291         obFuncStringIO = PyObject_GetAttrString(modIO, "StringIO");
292         if (!obFuncStringIO)
293                 goto out;
294         errorMsg = "io.StringIO() failed";
295         obIO = PyObject_CallObject(obFuncStringIO, NULL);
296         if (!obIO)
297                 goto out;
298
299         /* Get the traceback.print_exception function, and call it. */
300         errorMsg = "Can't find traceback.print_exception";
301         obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
302         if (!obFuncTB)
303                 goto out;
304         errorMsg = "can't make print_exception arguments";
305         argsTB = Py_BuildValue("OOOOO",
306                                exc_typ ? exc_typ : Py_None,
307                                exc_val ? exc_val : Py_None,
308                                exc_tb  ? exc_tb  : Py_None,
309                                Py_None,
310                                obIO);
311         if (!argsTB)
312                 goto out;
313
314         errorMsg = "traceback.print_exception() failed";
315         obResult = PyObject_CallObject(obFuncTB, argsTB);
316         if (!obResult) {
317                 PyErr_Print();
318                 goto out;
319         }
320
321         /* Now call the getvalue() method in the StringIO instance */
322         Py_DECREF(obFuncStringIO);
323         errorMsg = "cant find getvalue function";
324         obFuncStringIO = PyObject_GetAttrString(obIO, "getvalue");
325         if (!obFuncStringIO)
326                 goto out;
327         Py_XDECREF(obResult);
328         errorMsg = "getvalue() failed.";
329         obResult = PyObject_CallObject(obFuncStringIO, NULL);
330         if (!obResult)
331                 goto out;
332
333         /* And it should be a string all ready to go - report it. */
334         errorMsg = python_as_string(obResult, &tofree);;
335         LOG("Python error:\n%s", errorMsg);
336         if (errorMsg &&
337             (!ed_pane ||
338              call("editor:notify:Message:broadcast",ed_pane, 0, NULL,
339                   "Python Error - see log") <= 0))
340                 /* Failed to alert anyone - write to stderr */
341                 fwrite(errorMsg, 1, strlen(errorMsg), stderr);
342         Py_XDECREF(tofree);
343         errorMsg = NULL;
344 out:
345         if (errorMsg)
346                 LOG(errorMsg);
347         Py_XDECREF(modIO);
348         Py_XDECREF(modTB);
349         Py_XDECREF(obFuncStringIO);
350         Py_XDECREF(obIO);
351         Py_XDECREF(obFuncTB);
352         Py_XDECREF(argsTB);
353         Py_XDECREF(obResult);
354
355         Py_XDECREF(exc_typ);
356         Py_XDECREF(exc_val);
357         Py_XDECREF(exc_tb);
358 }
359
360 DEF_CMD(python_load_module)
361 {
362         const char *name = ci->str;
363         int fd;
364         long long size;
365         char *code;
366         char buf[PATH_MAX];
367         char buf2[PATH_MAX];
368         PyObject *builtins, *compile, *args, *bytecode;
369
370         if (!name)
371                 return Enoarg;
372         snprintf(buf, sizeof(buf), "%s/python/%s.py", module_dir, name);
373         fd = open(buf, O_RDONLY);
374         if (fd < 0)
375                 return Efail;
376         size = lseek(fd, 0, SEEK_END);
377         lseek(fd, 0, SEEK_SET);
378         code = malloc(size+1);
379         if (!code) {
380                 close(fd);
381                 return Efail;
382         }
383         size = read(fd, code, size);
384         close(fd);
385         if (size <= 0) {
386                 free(code);
387                 return Efail;
388         }
389         code[size] = 0;
390
391         LOG("Loading python module %s from %s", name, buf);
392
393         builtins = PyEval_GetBuiltins();
394         compile = PyDict_GetItemString(builtins, "compile");
395         args = safe_cast Py_BuildValue("(sss)", code, buf, "exec");
396         bytecode = PyObject_Call(compile, args, NULL);
397         Py_DECREF(args);
398         free(code);
399         if (bytecode == NULL) {
400                 PyErr_LOG();
401                 return Efail;
402         }
403
404         snprintf(buf2, sizeof(buf2), "edlib.%s", name);
405
406         if (PyImport_ExecCodeModule(buf2, bytecode) == NULL)
407                 PyErr_LOG();
408         Py_DECREF(bytecode);
409         return 1;
410 }
411
412 static PyObject *safe python_string(const char *s safe, int len)
413 {
414         const char *c = s;
415         const char *e = NULL;
416         wint_t wch;
417
418         if (len >= 0)
419                 e = s + len;
420         while ((!e || c < e) && *c && !(*c & 0x80))
421                 c++;
422         while ((wch = get_utf8(&c, e)) != WEOF)
423                 if (wch == WERR || wch > 0x10FFFF)
424                         break;
425
426         return safe_cast PyUnicode_DecodeUTF8(s, c - s, NULL);
427 }
428
429 static char *python_as_string(PyObject *s, PyObject **tofree safe)
430 {
431         if (s && PyUnicode_Check(s)) {
432                 s = PyUnicode_AsUTF8String(s);
433                 *tofree = s;
434         }
435         if (s && PyBytes_Check(s)) {
436                 char *ret = PyBytes_AsString(s);
437                 unsigned char *r = (unsigned char*)ret;
438                 if (r && r[0] == 0xef && r[1] == 0xbb && r[2] == 0xbf)
439                         /* UTF-8 Byte Order Mark */
440                         return ret+3;
441                 else
442                         return ret;
443         }
444         return NULL;
445 }
446
447 static int dict_add(PyObject *kwds, char *name, PyObject *val)
448 {
449         if (!val)
450                 return 0;
451         PyDict_SetItemString(kwds, name, val);
452         Py_DECREF(val);
453         return 1;
454 }
455
456 static bool python_running;
457 DEF_CB(handle_alarm)
458 {
459         if (python_running)
460                 PyErr_SetInterrupt();
461         return 1;
462 }
463
464 REDEF_CB(python_call)
465 {
466         struct python_command *pc = container_of(ci->comm, struct python_command, c);
467         PyObject *ret = NULL, *args, *kwds, *str;
468         int rv = 1;
469         bool unterminated = False;
470         int klen = strlen(ci->key);
471
472         if (klen > 13 &&
473             strcmp(ci->key + klen - 13, " unterminated") == 0)
474                 unterminated = True;
475
476         args = safe_cast Py_BuildValue("(s)", ci->key);
477         kwds = PyDict_New();
478         rv = rv && dict_add(kwds, "home", Pane_Frompane(ci->home));
479         rv = rv && dict_add(kwds, "focus",
480                             Pane_Frompane(ci->focus));
481         rv = rv && dict_add(kwds, "mark",
482                             ci->mark ? Mark_Frommark(ci->mark):
483                             (Py_INCREF(Py_None), Py_None));
484         rv = rv && dict_add(kwds, "mark2",
485                             ci->mark2 ? Mark_Frommark(ci->mark2):
486                             (Py_INCREF(Py_None), Py_None));
487
488         if (ci->str)
489                 str = python_string(ci->str, unterminated ? ci->num2 : -1);
490         else {
491                 str = Py_None;
492                 Py_INCREF(Py_None);
493         }
494         if (str) {
495                 dict_add(kwds, "str", str);
496                 dict_add(kwds, "str1", str);
497                 Py_INCREF(str);
498         } else {
499                 rv = 0;
500         }
501
502         rv = rv && dict_add(kwds, "str2",
503                             ci->str2 ? python_string(ci->str2, -1):
504                             (Py_INCREF(Py_None), safe_cast Py_None));
505         rv = rv && dict_add(kwds, "comm", Comm_Fromcomm(ci->comm));
506         rv = rv && dict_add(kwds, "comm2",
507                             ci->comm2 ? Comm_Fromcomm(ci->comm2):
508                             (Py_INCREF(Py_None), Py_None));
509         rv = rv && dict_add(kwds, "num",
510                             Py_BuildValue("i", ci->num));
511         rv = rv && dict_add(kwds, "rpt_num",
512                             Py_BuildValue("i", RPT_NUM(ci)));
513         rv = rv && dict_add(kwds, "num2",
514                             Py_BuildValue("i", ci->num2));
515         rv = rv && dict_add(kwds, "xy",
516                             Py_BuildValue("ii", ci->x, ci->y));
517
518         if (rv && pc->callable) {
519                 python_running = True;
520                 ret = PyObject_Call(pc->callable, args, kwds);
521                 python_running = False;
522         }
523
524         Py_DECREF(args);
525         Py_DECREF(kwds);
526         if (!ret) {
527                 PyErr_LOG();
528                 /* FIXME cancel error?? */
529                 return Efail;
530         }
531         if (ret == Py_None)
532                 rv = Efallthrough;
533         else if (PyLong_Check(ret))
534                 rv = PyLong_AsLong(ret);
535         else if (PyBool_Check(ret))
536                 rv = (ret == Py_True) ? 1 : Efalse;
537         else if (PyUnicode_Check(ret) && PyUnicode_GET_LENGTH(ret) >= 1)
538                 rv = CHAR_RET(PyUnicode_READ_CHAR(ret, 0));
539         else
540                 rv = 1;
541         Py_DECREF(ret);
542         return rv;
543 }
544
545 REDEF_CMD(python_doc_call)
546 {
547         int rv = python_pane_call_func(ci);
548         if (rv == Efallthrough)
549                 rv = key_lookup(doc_default_cmd, ci);
550         return rv;
551 }
552
553 static void do_map_init(Pane *self safe)
554 {
555         int i;
556         PyObject *l = PyObject_Dir((PyObject*)self);
557         int n;
558
559         if (!self->map || !self->pane || !l)
560                 return;
561         n = PyList_Size(l);
562         /* First add the ranges, so individuals can over-ride them */
563         for (i = 0; i < n ; i++) {
564                 PyObject *e = PyList_GetItem(l, i);
565                 PyObject *m = PyObject_GetAttr((PyObject*)self, e);
566
567                 if (m && PyMethod_Check(m)) {
568                         PyObject *doc = PyObject_GetAttrString(m, "__doc__");
569                         if (doc && doc != Py_None) {
570                                 PyObject *tofree = NULL;
571                                 char *docs = python_as_string(doc, &tofree);
572
573                                 if (docs &&
574                                     strstarts(docs, "handle-range") &&
575                                     docs[12]) {
576                                         char sep = docs[12];
577                                         char *s1 = strchr(docs+13, sep);
578                                         char *s2 = s1 ? strchr(s1+1, sep) : NULL;
579                                         if (s2) {
580                                                 char *a = strndup(docs+13, s1-(docs+13));
581                                                 char *b = strndup(s1+1, s2-(s1+1));
582
583                                                 struct python_command *comm =
584                                                         export_callable(m, e);
585                                                 key_add_range(self->map, a, b,
586                                                               &comm->c);
587                                                 free(a); free(b);
588                                                 command_put(&comm->c);
589                                         }
590                                 }
591                                 if (docs &&
592                                     strstarts(docs, "handle-prefix:")) {
593                                         char *a = strconcat(self->pane, docs+14);
594                                         char *b = strconcat(self->pane,
595                                                             a, "\xFF\xFF\xFF\xFF");
596                                         struct python_command *comm =
597                                                 export_callable(m, e);
598                                         key_add_range(self->map, a, b,
599                                                       &comm->c);
600                                         command_put(&comm->c);
601                                 }
602                                 Py_XDECREF(tofree);
603                         }
604                         Py_XDECREF(doc);
605                 }
606                 Py_XDECREF(m);
607         }
608         /* Now add the non-ranges */
609         for (i = 0; i < n ; i++) {
610                 PyObject *e = PyList_GetItem(l, i);
611                 PyObject *m = PyObject_GetAttr((PyObject*)self, e);
612
613                 if (m && PyMethod_Check(m)) {
614                         PyObject *doc = PyObject_GetAttrString(m, "__doc__");
615                         char *docs;
616                         PyObject *tofree = NULL;
617                         if (doc && doc != Py_None &&
618                             (docs = python_as_string(doc, &tofree)) != NULL) {
619
620                                 if (strstarts(docs, "handle:")) {
621                                         struct python_command *comm =
622                                                 export_callable(m, e);
623                                         key_add(self->map, docs+7, &comm->c);
624                                         command_put(&comm->c);
625                                 }
626                                 if (strstarts(docs, "handle-list") &&
627                                     docs[11]) {
628                                         char sep = docs[11];
629                                         char *s1 = docs + 12;
630                                         while (s1 && *s1 && *s1 != sep) {
631                                                 struct python_command *comm =
632                                                         export_callable(m, e);
633                                                 char *a;
634                                                 char *s2 = strchr(s1, sep);
635                                                 if (s2) {
636                                                         a = strndup(s1, s2-s1);
637                                                         s1 = s2+1;
638                                                 } else {
639                                                         a = strdup(s1);
640                                                         s1 = NULL;
641                                                 }
642                                                 key_add(self->map, a, &comm->c);
643                                                 free(a);
644                                                 command_put(&comm->c);
645                                         }
646                                 }
647                         }
648                         Py_XDECREF(tofree);
649                         Py_XDECREF(doc);
650                 }
651                 Py_XDECREF(m);
652         }
653         Py_XDECREF(l);
654         self->map_init = 1;
655 }
656
657 REDEF_CB(python_pane_call)
658 {
659         Pane *home = container_of(ci->comm, Pane, cmd);
660
661         if (!home || !home->map)
662                 return Efallthrough;
663
664         if (!home->map_init)
665                 do_map_init(home);
666         return key_lookup(home->map, ci);
667 }
668
669 static Pane *pane_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
670 {
671         Pane *self;
672
673         self = (Pane *)type->tp_alloc(type, 0);
674         if (self) {
675                 self->pane = NULL;
676         }
677         return self;
678 }
679
680 static Doc *Doc_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
681 {
682         Doc *self;
683
684         self = (Doc *)type->tp_alloc(type, 0);
685         if (self) {
686                 self->pane = NULL;
687         }
688         return self;
689 }
690
691 static void python_pane_free(struct command *c safe)
692 {
693         Pane *p = container_of(c, Pane, cmd);
694         struct pane *pn = p->pane;
695         /* pane has been closed */
696         p->pane = NULL;
697         if (p->map)
698                 key_free(p->map);
699         p->map = NULL;
700         if (pn && PyObject_TypeCheck(p, &DocType))
701                 doc_free(&pn->doc_data->doc, safe_cast pn);
702         if (pn)
703                 pane_put(pn);
704         Py_DECREF(p);
705 }
706
707 DEF_CMD_CLOSED(python_close_mark)
708 {
709         struct mark *m = ci->mark;
710
711         if (m && m->viewnum >= 0 && m->mtype == &MarkType && m->mdata) {
712                 Mark *M = m->mdata;
713                 m->mdata = NULL;
714                 m->mtype = NULL;
715                 M->mark = NULL;
716                 Py_DECREF(M);
717         }
718         return 1;
719 }
720
721 static int do_Pane_init(Pane *self safe, PyObject *args, PyObject *kwds,
722                        Pane **parentp safe,
723                        int *zp safe)
724 {
725         int ret;
726         static const char *keywords[] = {"parent", "z", NULL};
727
728         if (self->pane) {
729                 PyErr_SetString(PyExc_TypeError, "Pane already initialised");
730                 return -1;
731         }
732         if (in_pane_frompane)
733                 /* An internal Pane_Frompane call - it will set .pane,
734                  * and we don't want a .handler.
735                  */
736                 return 0;
737
738         /* Pane(parent=None, z=0) */
739         ret = PyArg_ParseTupleAndKeywords(args, kwds, "O!|i", (char**)keywords,
740                                           &PaneType, parentp, zp);
741         if (ret <= 0)
742                 return -1;
743
744         self->map = key_alloc();
745         key_add(self->map, "Close:mark", &python_close_mark);
746         self->cmd = python_pane_call;
747         self->cmd.closed_ok = 1;
748         self->cmd.free = python_pane_free;
749         if (self->ob_base.ob_type)
750                 self->cmd.name = self->ob_base.ob_type->tp_name;
751
752         return 1;
753 }
754
755 static int Pane_init(Pane *self safe, PyObject *args, PyObject *kwds)
756 {
757         Pane *parent = NULL;
758         int z = 0;
759         int ret = do_Pane_init(self, args, kwds, &parent, &z);
760
761         if (ret <= 0)
762                 return ret;
763         if (!parent || !parent->pane)
764                 return -1;
765
766         /* The pane holds a reference to the Pane through the ->handle
767          * function
768          */
769         Py_INCREF(self);
770         self->pane = pane_register(parent->pane, z, &self->cmd, self);
771         if (!self->pane)
772                 return -1;
773
774         pane_get(self->pane);
775         return 0;
776 }
777
778 static int Doc_init(Doc *self, PyObject *args, PyObject *kwds)
779 {
780         Pane *parent = NULL;
781         struct python_doc *pd;
782         int z = 0;
783         int ret = do_Pane_init((Pane*safe)self, args, kwds, &parent, &z);
784
785         if (ret <= 0)
786                 return ret;
787         if (!self || !parent || !parent->pane)
788                 return -1;
789
790         self->cmd.func = python_doc_call_func;
791         self->pane = doc_register(parent->pane, &self->cmd);
792         if (self->pane) {
793                 pane_get(self->pane);
794                 pd = self->pane->doc_data;
795                 pd->pdoc = self;
796                 pd->doc.refcnt = mark_refcnt;
797         }
798         return 0;
799 }
800
801 static inline void do_free(PyObject *ob safe)
802 {
803         if (ob->ob_type && ob->ob_type->tp_free)
804                 ob->ob_type->tp_free(ob);
805 }
806
807 DEF_CMD(python_null_call)
808 {
809         return 1;
810 }
811
812 static void python_pane_free_final(struct command *c safe)
813 {
814         Pane *p = container_of(c, Pane, cmd);
815
816         if (p->pane)
817                 pane_put(p->pane);
818         python_pane_free(c);
819         do_free((PyObject*safe)p);
820 }
821
822 static void pane_dealloc(Pane *self safe)
823 {
824         struct pane *p = self->pane;
825
826         /* if initialization failed, then dealloc happens before the
827          * pane gets closed.  In that case we need to modify the
828          * free sequence so do_free() gets called after the close.
829          */
830
831         if (p && p->handle && p->handle->func == python_pane_call.func) {
832                 p->handle = &python_null_call;
833                 p->handle->free = python_pane_free_final;
834                 pane_close(p);
835         } else if (p && p->handle && p->handle->func == python_doc_call.func) {
836                 p->handle = &python_null_call;
837                 p->handle->free = python_pane_free_final;
838                 pane_close(p);
839         } else {
840                 if (p)
841                         pane_put(p);
842                 do_free((PyObject*safe)self);
843         }
844 }
845
846 static PyObject *pane_children(Pane *self safe, PyObject *args)
847 {
848         PaneIter *ret;
849
850         if (!pane_valid(self))
851                 return NULL;
852         ret = (PaneIter*)PyObject_CallObject((PyObject*)&PaneIterType, NULL);
853         if (ret) {
854                 if (list_empty(&self->pane->children))
855                         ret->pane = NULL;
856                 else
857                         ret->pane = list_first_entry(&self->pane->children,
858                                                      struct pane, siblings);
859         }
860         return (PyObject*)ret;
861 }
862
863 static Pane *pane_iter_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
864 {
865         Pane *self;
866
867         self = (Pane *)type->tp_alloc(type, 0);
868         if (self)
869                 self->pane = NULL;
870         return self;
871 }
872
873 static void paneiter_dealloc(PaneIter *self safe)
874 {
875         do_free((PyObject*safe)self);
876 }
877
878 static PyObject *Pane_clone_children(Pane *self safe, PyObject *args)
879 {
880         Pane *other = NULL;
881         int ret;
882
883         if (!pane_valid(self))
884                 return NULL;
885
886         ret = PyArg_ParseTuple(args, "O!", &PaneType, &other);
887         if (ret <= 0 || !other)
888                 return NULL;
889         if (other->pane)
890                 pane_clone_children(self->pane, other->pane);
891         Py_INCREF(Py_None);
892         return Py_None;
893 }
894
895 static PyObject *Pane_take_focus(Pane *self safe, PyObject *args)
896 {
897         if (!pane_valid(self))
898                 return NULL;
899
900         pane_take_focus(self->pane);
901         Py_INCREF(Py_None);
902         return Py_None;
903 }
904
905 static PyObject *Pane_has_focus(Pane *self safe, PyObject *args)
906 {
907         Pane *other = NULL;
908         int ret;
909
910         if (!pane_valid(self))
911                 return NULL;
912
913         ret = PyArg_ParseTuple(args, "|O!", &PaneType, &other);
914         if (ret <= 0)
915                 return NULL;
916
917         if (pane_has_focus(self->pane, other ? other->pane : NULL)) {
918                 Py_INCREF(Py_True);
919                 return Py_True;
920         } else {
921                 Py_INCREF(Py_False);
922                 return Py_False;
923         }
924 }
925
926 static PaneIter *pane_this_iter(PaneIter *self safe)
927 {
928         Py_INCREF(self);
929         return self;
930 }
931
932 static PyObject *pane_iter_next(PaneIter *self safe)
933 {
934         PyObject *ret;
935         if (!self->pane)
936                 /* Reached the end */
937                 return NULL;
938         ret = Pane_Frompane(self->pane);
939         if (self->pane->siblings.next == &self->pane->parent->children)
940                 /* Reached the end of the list */
941                 self->pane = NULL;
942         else
943                 self->pane = list_next_entry(self->pane, siblings);
944         return ret;
945 }
946
947 struct pyret {
948         struct command comm;
949         PyObject *ret;
950         bool return_char;
951 };
952
953 DEF_CB(take_focus)
954 {
955         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
956         struct pane *p = ci->focus;
957
958         if (!p)
959                 return Enoarg;
960         if (pr->ret)
961                 return Efallthrough;
962         pr->ret = Pane_Frompane(ci->focus);
963         return 1;
964 }
965
966 DEF_CB(take_mark)
967 {
968         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
969
970         if (pr->ret)
971                 return Einval;
972         if (!mark_valid(ci->mark))
973                 return Efallthrough;
974         if (ci->mark->viewnum == MARK_UNGROUPED) {
975                 /* Cannot rely on this mark persisting, take a copy */
976                 struct mark *m = mark_dup(ci->mark);
977                 pr->ret = Mark_Frommark(m);
978                 m->mtype = (void*)pr->ret;
979         } else
980                 pr->ret = Mark_Frommark(ci->mark);
981         return 1;
982 }
983
984 DEF_CB(take_mark2)
985 {
986         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
987
988         if (pr->ret)
989                 return Einval;
990         if (!mark_valid(ci->mark2))
991                 return Efallthrough;
992         pr->ret = Mark_Frommark(ci->mark2);
993         return 1;
994 }
995
996 DEF_CB(take_2_marks)
997 {
998         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
999         PyObject *m1, *m2;
1000
1001         if (pr->ret)
1002                 return Einval;
1003         if (mark_valid(ci->mark))
1004                 m1 = Mark_Frommark(ci->mark);
1005         else
1006                 m1 = Py_None;
1007         if (mark_valid(ci->mark2))
1008                 m2 = Mark_Frommark(ci->mark2);
1009         else
1010                 m2 = Py_None;
1011
1012         pr->ret = Py_BuildValue("OO", m1, m2);
1013         if (mark_valid(ci->mark))
1014                 Py_DECREF(m1);
1015         if (mark_valid(ci->mark2))
1016                 Py_DECREF(m2);
1017         return 1;
1018 }
1019
1020 DEF_CB(take_str)
1021 {
1022         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1023
1024         if (pr->ret)
1025                 return Einval;
1026         if (!ci->str)
1027                 return Efallthrough;
1028         pr->ret = python_string(ci->str, -1);
1029         return 1;
1030 }
1031
1032 DEF_CB(take_bytes)
1033 {
1034         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1035
1036         if (pr->ret)
1037                 return Einval;
1038         if (!ci->str)
1039                 return Efallthrough;
1040         pr->ret = safe_cast PyBytes_FromStringAndSize(ci->str, ci->num);
1041         return 1;
1042 }
1043
1044 DEF_CB(take_comm)
1045 {
1046         struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1047
1048         if (pr->ret)
1049                 return Einval;
1050         if (!ci->comm2)
1051                 return Efallthrough;
1052         pr->ret = Comm_Fromcomm(ci->comm2);
1053         return 1;
1054 }
1055
1056 static struct command *map_ret(char *ret safe)
1057 {
1058         if (strcmp(ret, "pane") == 0)
1059                 return &take_focus;
1060         if (strcmp(ret, "mark") == 0)
1061                 return &take_mark;
1062         if (strcmp(ret, "mark2") == 0)
1063                 return &take_mark2;
1064         if (strcmp(ret, "marks") == 0)
1065                 return &take_2_marks;
1066         if (strcmp(ret, "str") == 0)
1067                 return &take_str;
1068         if (strcmp(ret, "bytes") == 0)
1069                 return &take_bytes;
1070         if (strcmp(ret, "comm") == 0)
1071                 return &take_comm;
1072         return NULL;
1073 }
1074
1075 static bool handle_ret(PyObject *kwds, struct cmd_info *ci safe,
1076                        struct pyret *pr safe)
1077 {
1078         char *rets;
1079         struct command *c;
1080         PyObject *ret, *s3 = NULL;
1081
1082         memset(pr, 0, sizeof(*pr));
1083
1084         ret = kwds ? PyDict_GetItemString(kwds, "ret") : NULL;
1085         if (!ret)
1086                 return True;
1087
1088         if (!PyUnicode_Check(ret) ||
1089             (rets = python_as_string(ret, &s3)) == NULL) {
1090                 PyErr_SetString(PyExc_TypeError, "ret= must be given a string");
1091                 return False;
1092         }
1093         if (strcmp(rets, "char") == 0) {
1094                 pr->return_char = 1;
1095                 ret = NULL;
1096         } else {
1097                 if (ci->comm2) {
1098                         PyErr_SetString(PyExc_TypeError, "ret= not permitted with comm2");
1099                         Py_XDECREF(s3);
1100                         return False;
1101                 }
1102                 c = map_ret(rets);
1103                 if (!c) {
1104                         PyErr_SetString(PyExc_TypeError, "ret= type not valid");
1105                         Py_XDECREF(s3);
1106                         return False;
1107                 }
1108                 pr->comm = *c;
1109                 ci->comm2 = &pr->comm;
1110         }
1111         Py_XDECREF(s3);
1112         return True;
1113 }
1114
1115 static void set_err(int rv)
1116 {
1117         switch(rv) {
1118         case Enoarg:
1119                 PyErr_SetObject(Edlib_CommandFailed,
1120                                 PyUnicode_FromFormat("Enoarg"));
1121                 break;
1122         case Einval:
1123                 PyErr_SetObject(Edlib_CommandFailed,
1124                                 PyUnicode_FromFormat("Einval"));
1125                 break;
1126         case Enosup:
1127                 PyErr_SetObject(Edlib_CommandFailed,
1128                                 PyUnicode_FromFormat("Enosup"));
1129                 break;
1130         case Efail:
1131                 PyErr_SetObject(Edlib_CommandFailed,
1132                                 PyUnicode_FromFormat("Efail"));
1133                 break;
1134         default:
1135                 PyErr_SetObject(Edlib_CommandFailed,
1136                                 PyUnicode_FromFormat("%d", rv));
1137         }
1138 }
1139
1140 static PyObject *choose_ret(int rv, struct pyret *pr safe)
1141 {
1142         if (pr->comm.func && rv >= Efalse) {
1143                 if (pr->ret)
1144                         return pr->ret;
1145                 Py_INCREF(Py_None);
1146                 return Py_None;
1147         }
1148         Py_XDECREF(pr->ret);
1149         if (rv < Efalse) {
1150                 set_err(rv);
1151                 return NULL;
1152         }
1153         if (pr->return_char) {
1154                 if (rv == 0) {
1155                         Py_INCREF(Py_False);
1156                         return Py_False;
1157                 }
1158                 if (rv == CHAR_RET(WEOF)) {
1159                         Py_INCREF(Py_None);
1160                         return Py_None;
1161                 }
1162                 return PyUnicode_FromFormat("%c", rv & 0x1FFFFF);
1163         }
1164         return PyLong_FromLong(rv);
1165 }
1166
1167 static PyObject *Pane_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1168 {
1169         struct cmd_info ci = SAFE_CI;
1170         int rv;
1171         PyObject *s1, *s2;
1172         struct pyret pr;
1173
1174         if (!pane_valid(self))
1175                 return NULL;
1176
1177         ci.home = self->pane;
1178
1179         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1180             !handle_ret(kwds, &ci, &pr)) {
1181                 Py_XDECREF(s1); Py_XDECREF(s2);
1182                 command_put(ci.comm2);
1183                 return NULL;
1184         }
1185
1186         python_running = False;
1187         rv = key_handle(&ci);
1188         python_running = True;
1189
1190         /* Just in case ... */
1191         PyErr_Clear();
1192
1193         Py_XDECREF(s1); Py_XDECREF(s2);
1194         command_put(ci.comm2);
1195
1196         return choose_ret(rv, &pr);
1197 }
1198
1199 static PyObject *pane_direct_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1200 {
1201         struct cmd_info ci = SAFE_CI;
1202         int rv;
1203         PyObject *s1, *s2;
1204         struct pyret pr;
1205
1206         if (!pane_valid(self))
1207                 return NULL;
1208
1209         ci.home = self->pane;
1210
1211         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1212             !handle_ret(kwds, &ci, &pr)) {
1213                 Py_XDECREF(s1); Py_XDECREF(s2);
1214                 command_put(ci.comm2);
1215                 return NULL;
1216         }
1217
1218         ci.comm = ci.home->handle;
1219         rv = ci.comm->func(&ci);
1220
1221         Py_XDECREF(s1); Py_XDECREF(s2);
1222         command_put(ci.comm2);
1223         return choose_ret(rv, &pr);
1224 }
1225
1226 static PyObject *Pane_notify(Pane *self safe, PyObject *args safe, PyObject *kwds)
1227 {
1228         struct cmd_info ci = SAFE_CI;
1229         int rv;
1230         PyObject *s1, *s2;
1231
1232         if (!pane_valid(self))
1233                 return NULL;
1234
1235         ci.home = self->pane;
1236
1237         if (!get_cmd_info(&ci, args, kwds, &s1, &s2)) {
1238                 Py_XDECREF(s1); Py_XDECREF(s2);
1239                 command_put(ci.comm2);
1240                 return NULL;
1241         }
1242
1243         rv = home_pane_notify(ci.home, ci.key, ci.focus, ci.num, ci.mark, ci.str,
1244                               ci.num2, ci.mark2, ci.str2,
1245                               ci.comm2);
1246
1247         Py_XDECREF(s1); Py_XDECREF(s2);
1248         command_put(ci.comm2);
1249         if (rv < Efalse) {
1250                 set_err(rv);
1251                 return NULL;
1252         }
1253         return PyLong_FromLong(rv);
1254 }
1255
1256 static PyObject *Pane_mapxy(Pane *self safe, PyObject *args)
1257 {
1258         short x,y;
1259         struct xy xy;
1260         Pane *other = NULL;
1261
1262         int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1263         if (ret <= 0 || !self->pane || !other || !other->pane)
1264                 return NULL;
1265
1266         xy = pane_mapxy(other->pane, self->pane, x, y, False);
1267         return Py_BuildValue("ii", xy.x, xy.y);
1268 }
1269
1270 static PyObject *Pane_clipxy(Pane *self safe, PyObject *args)
1271 {
1272         short x,y;
1273         struct xy xy;
1274         Pane *other = NULL;
1275
1276         int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1277         if (ret <= 0 || !self->pane || !other || !other->pane)
1278                 return NULL;
1279
1280         xy = pane_mapxy(other->pane, self->pane, x, y, True);
1281         return Py_BuildValue("ii", xy.x, xy.y);
1282 }
1283
1284 static PyObject *Pane_add_notify(Pane *self safe, PyObject *args)
1285 {
1286         Pane *other = NULL;
1287         char *event = NULL;
1288         int ret = PyArg_ParseTuple(args, "O!s", &PaneType, &other, &event);
1289         if (ret <= 0 || !other || !event)
1290                 return NULL;
1291         if (self->pane && other->pane)
1292                 pane_add_notify(self->pane, other->pane, event);
1293
1294         Py_INCREF(Py_None);
1295         return Py_None;
1296 }
1297
1298 static PyObject *Pane_drop_notify(Pane *self safe, PyObject *args)
1299 {
1300         char *event = NULL;
1301         int ret = PyArg_ParseTuple(args, "s", &event);
1302         if (ret <= 0 || !event)
1303                 return NULL;
1304         if (self->pane)
1305                 pane_drop_notifiers(self->pane, event);
1306
1307         Py_INCREF(Py_None);
1308         return Py_None;
1309 }
1310
1311 static PyObject *Pane_damaged(Pane *self safe, PyObject *args)
1312 {
1313         int damage = DAMAGED_REFRESH;
1314         int ret = PyArg_ParseTuple(args, "|i", &damage);
1315         if (ret <= 0)
1316                 return NULL;
1317         if (self->pane)
1318                 pane_damaged(self->pane, damage);
1319
1320         Py_INCREF(Py_None);
1321         return Py_None;
1322 }
1323
1324 static PyObject *Pane_close(Pane *self safe, PyObject *args)
1325 {
1326         struct pane *p = self->pane;
1327         if (p) {
1328                 pane_close(p);
1329                 self->pane = NULL;
1330         }
1331         Py_INCREF(Py_None);
1332         return Py_None;
1333 }
1334
1335 static PyObject *Pane_get_scale(Pane *self safe, PyObject *args)
1336 {
1337         struct pane *p = self->pane;
1338         struct xy xy = {1000, 1000};
1339
1340         if (p)
1341                 xy = pane_scale(p);
1342         return Py_BuildValue("ii", xy.x, xy.y);
1343 }
1344
1345 static PyObject *Pane_set_time(Pane *self safe, PyObject *args)
1346 {
1347         struct pane *p = self->pane;
1348         if (p)
1349                 pane_set_time(p);
1350         Py_INCREF(Py_None);
1351         return Py_None;
1352 }
1353
1354 static PyObject *Pane_too_long(Pane *self safe, PyObject *args)
1355 {
1356         struct pane *p = self->pane;
1357
1358         if (!p || pane_too_long(p, 0)) {
1359                 Py_INCREF(Py_True);
1360                 return Py_True;
1361         } else {
1362                 Py_INCREF(Py_False);
1363                 return Py_False;
1364         }
1365 }
1366
1367 static PyObject *Pane_mychild(Pane *self safe, PyObject *args)
1368 {
1369         Pane *child = NULL;
1370         int ret = PyArg_ParseTuple(args, "O!", &PaneType, &child);
1371         if (ret <= 0 || !child)
1372                 return NULL;
1373         if (self->pane && child->pane) {
1374                 struct pane *p = pane_my_child(self->pane, child->pane);
1375                 if (p)
1376                         return Pane_Frompane(p);
1377         }
1378         Py_INCREF(Py_None);
1379         return Py_None;
1380 }
1381
1382 static PyObject *Pane_clip(Pane *self safe, PyObject *args)
1383 {
1384         Mark *start = NULL, *end = NULL;
1385         int view = -1;
1386         int tostart = 0;
1387         int ret = PyArg_ParseTuple(args, "iO!O!|i", &view, &MarkType, &start,
1388                                    &MarkType, &end, &tostart);
1389
1390         if (ret > 0 && start && end && self->pane &&
1391             start->mark && end->mark && view >= 0)
1392                 marks_clip(self->pane, start->mark, end->mark, view, self->pane,
1393                            !!tostart);
1394         Py_INCREF(Py_None);
1395         return Py_None;
1396 }
1397
1398 static PyObject *Pane_reparent(Pane *self safe, PyObject *args)
1399 {
1400         Pane *newparent = NULL;
1401         int ret = PyArg_ParseTuple(args, "O!", &PaneType, &newparent);
1402
1403         if (ret > 0 && newparent && self->pane && newparent->pane) {
1404                 pane_reparent(self->pane, newparent->pane);
1405                 if (self->pane->parent != newparent->pane) {
1406                         PyErr_SetString(PyExc_TypeError, "reparent failed");
1407                         return NULL;
1408                 }
1409         }
1410         Py_INCREF(Py_None);
1411         return Py_None;
1412 }
1413
1414 static PyObject *Pane_move_after(Pane *self safe, PyObject *args)
1415 {
1416         Pane *peer = NULL;
1417         int ret = PyArg_ParseTuple(args, "O", &peer);
1418
1419         if (ret > 0 && peer && self->pane) {
1420                 if ((PyObject*)peer == Py_None)
1421                         pane_move_after(self->pane, NULL);
1422                 else if (PyObject_TypeCheck(peer, &PaneType) && peer->pane)
1423                         pane_move_after(self->pane, peer->pane);
1424         }
1425         Py_INCREF(Py_None);
1426         return Py_None;
1427 }
1428
1429 static PyObject *Pane_step(Pane *self safe, PyObject *args, int dir, int move)
1430 {
1431         Mark *m = NULL;
1432         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &m);
1433         wint_t wch;
1434
1435         if (!pane_valid(self))
1436                 return NULL;
1437         if (ret <= 0 || !m || !mark_valid(m->mark)) {
1438                 PyErr_SetString(PyExc_TypeError, "Arg must be a mark");
1439                 return NULL;
1440         }
1441
1442         if (move)
1443                 wch = doc_move(self->pane, m->mark, dir);
1444         else
1445                 wch = doc_pending(self->pane, m->mark, dir);
1446         if (wch == WEOF) {
1447                 Py_INCREF(Py_None);
1448                 return Py_None;
1449         }
1450         return PyUnicode_FromFormat("%c", wch);
1451 }
1452
1453 static PyObject *Pane_step_next(Pane *self safe, PyObject *args)
1454 {
1455         return Pane_step(self, args, 1, 1);
1456 }
1457
1458 static PyObject *Pane_step_prev(Pane *self safe, PyObject *args)
1459 {
1460         return Pane_step(self, args, -1, 1);
1461 }
1462
1463 static PyObject *Pane_step_following(Pane *self safe, PyObject *args)
1464 {
1465         return Pane_step(self, args, 1, 0);
1466 }
1467
1468 static PyObject *Pane_step_prior(Pane *self safe, PyObject *args)
1469 {
1470         return Pane_step(self, args, -1, 0);
1471 }
1472
1473 static PyObject *Pane_get_vmarks(Pane *self safe, PyObject *args)
1474 {
1475         struct pyret pr;
1476         Pane *owner = NULL;
1477         int view = -1;
1478         int ret;
1479
1480         if (!pane_valid(self))
1481                 return NULL;
1482         ret = PyArg_ParseTuple(args, "i|O!", &view, &PaneType, &owner);
1483         if (ret <= 0 || view < 0 || (owner && !pane_valid(owner))) {
1484                 Py_INCREF(Py_None);
1485                 return Py_None;
1486         }
1487         memset(&pr, 0, sizeof(pr));
1488         pr.comm = take_2_marks;
1489         home_call_comm(self->pane, "doc:vmark-get",
1490                        owner ? owner->pane : self->pane,
1491                        &pr.comm, view);
1492         if (pr.ret)
1493                 return pr.ret;
1494         Py_INCREF(Py_None);
1495         return Py_None;
1496 }
1497
1498 static PyObject *Pane_vmark_at_or_before(Pane *self safe, PyObject *args)
1499 {
1500         Mark *m = NULL;
1501         Pane *owner = NULL;
1502         struct pyret pr;
1503         int view = -1;
1504         int ret;
1505
1506         if (!pane_valid(self))
1507                 return NULL;
1508         ret = PyArg_ParseTuple(args, "iO!|O!", &view, &MarkType, &m,
1509                                &PaneType, &owner);
1510         if (ret <= 0 || view < 0 || !m || !mark_valid(m->mark) ||
1511             (owner && !pane_valid(owner))) {
1512                 Py_INCREF(Py_None);
1513                 return Py_None;
1514         }
1515         memset(&pr, 0, sizeof(pr));
1516         pr.comm = take_mark;
1517         home_call_comm(self->pane, "doc:vmark-prev",
1518                        owner ? owner->pane : self->pane,
1519                        &pr.comm, view, m->mark);
1520         if (pr.ret)
1521                 return pr.ret;
1522         Py_INCREF(Py_None);
1523         return Py_None;
1524 }
1525
1526 static const PyMethodDef pane_methods[] = {
1527         {"close", (PyCFunction)Pane_close, METH_NOARGS,
1528          "close the pane"},
1529         {"children", (PyCFunction)pane_children, METH_NOARGS,
1530          "provides an iterator which will iterate over all children"},
1531         {"clone_children", (PyCFunction)Pane_clone_children, METH_VARARGS,
1532          "Clone all children onto the target"},
1533         {"take_focus", (PyCFunction)Pane_take_focus, METH_NOARGS,
1534          "Claim the focus for this pane"},
1535         {"has_focus", (PyCFunction)Pane_has_focus, METH_VARARGS,
1536          "Check if pane is focus of display"},
1537         {"call", (void*)(PyCFunctionWithKeywords)Pane_call, METH_VARARGS|METH_KEYWORDS,
1538          "Call a command from a pane"},
1539         {"notify", (void*)(PyCFunctionWithKeywords)Pane_notify, METH_VARARGS|METH_KEYWORDS,
1540          "Send a notification from a pane"},
1541         {"mapxy", (PyCFunction)Pane_mapxy, METH_VARARGS,
1542          "Convert pane-relative co-ords between panes"},
1543         {"clipxy", (PyCFunction)Pane_clipxy, METH_VARARGS,
1544          "Convert pane-relative co-ords between panes, clipping to all panes"},
1545         {"add_notify", (PyCFunction)Pane_add_notify, METH_VARARGS,
1546          "Add notifier for an event on some other pane"},
1547         {"drop_notify", (PyCFunction)Pane_drop_notify, METH_VARARGS,
1548          "Drop notification to this pane for an event"},
1549         {"damaged", (PyCFunction)Pane_damaged, METH_VARARGS,
1550          "Mark pane as damaged"},
1551         {"scale", (PyCFunction)Pane_get_scale, METH_NOARGS,
1552          "Get the x,y scale numbers for this pane"},
1553         {"mychild", (PyCFunction)Pane_mychild, METH_VARARGS,
1554          "Get ancestor of pane which is my child, or None"},
1555         {"clip", (PyCFunction)Pane_clip, METH_VARARGS,
1556          "clip all 'type' marks in the given range"},
1557         {"reparent", (PyCFunction)Pane_reparent, METH_VARARGS,
1558          "Give a pane a new parent"},
1559         {"move_after", (PyCFunction)Pane_move_after, METH_VARARGS,
1560          "Move a pane after another in order of children"},
1561         {"next", (PyCFunction)Pane_step_next, METH_VARARGS,
1562          "Move mark forward returning the character"},
1563         {"prev", (PyCFunction)Pane_step_prev, METH_VARARGS,
1564          "Move mark back returning the character"},
1565         {"following", (PyCFunction)Pane_step_following, METH_VARARGS,
1566          "returning the character after mark"},
1567         {"prior", (PyCFunction)Pane_step_prior, METH_VARARGS,
1568          "returning the character before mark"},
1569         {"vmarks", (PyCFunction)Pane_get_vmarks, METH_VARARGS,
1570          "return first and last vmark given view number"},
1571         {"vmark_at_or_before", (PyCFunction)Pane_vmark_at_or_before, METH_VARARGS,
1572          "return vmark at-or-before given mark"},
1573         {"set_time", (PyCFunction)Pane_set_time, METH_NOARGS,
1574          "Set start time for long running operation"},
1575         {"too_long", (PyCFunction)Pane_too_long, METH_NOARGS,
1576          "Check if command in pane has been running for too long"},
1577         {NULL}
1578 };
1579
1580 static PyObject *pane_getnum(Pane *p safe, char *which safe)
1581 {
1582         long n = 0;
1583
1584         if (!pane_valid(p))
1585                 return NULL;
1586
1587         switch(*which) {
1588         case 'x': n = p->pane->x; break;
1589         case 'y': n = p->pane->y; break;
1590         case 'w': n = p->pane->w > 0 ? p->pane->w : 1; break;
1591         case 'h': n = p->pane->h > 0 ? p->pane->h : 1; break;
1592         case 'X': n = p->pane->cx; break;
1593         case 'Y': n = p->pane->cy; break;
1594         case 'z': n = p->pane->z; break;
1595         case 'Z': n = p->pane->abs_z; break;
1596         }
1597         return PyLong_FromLong(n);
1598 }
1599
1600 static int pane_setnum(Pane *p safe, PyObject *v, char *which safe)
1601 {
1602         int x,y,w,h;
1603         long val;
1604
1605         if (!pane_valid(p))
1606                 return -1;
1607
1608         if (*which == 'z') {
1609                 PyErr_SetString(PyExc_TypeError, "z cannot be set");
1610                 return -1;
1611         }
1612         if (*which == 'Z') {
1613                 PyErr_SetString(PyExc_TypeError, "abs_z cannot be set");
1614                 return -1;
1615         }
1616         val = PyLong_AsLong(v);
1617         if (val == -1 && PyErr_Occurred())
1618                 return -1;
1619
1620         x = p->pane->x; y = p->pane->y;
1621         w = p->pane->w; h = p->pane->h;
1622         switch(*which) {
1623         case 'x': x = val; break;
1624         case 'y': y = val; break;
1625         case 'w': w = val; break;
1626         case 'h': h = val; break;
1627         case 'X': p->pane->cx = val; return 0;
1628         case 'Y': p->pane->cy = val; return 0;
1629         }
1630         pane_resize(p->pane, x, y, w, h);
1631         return 0;
1632 }
1633
1634 static Pane *pane_getpane(Pane *p safe, char *which safe)
1635 {
1636         struct pane *new = NULL;
1637         Pane *newpane;
1638
1639         if (!pane_valid(p))
1640                 return NULL;
1641
1642         if (*which == 'p')
1643                 new = p->pane->parent;
1644         if (*which == 'f')
1645                 new = p->pane->focus;
1646         if (*which == 'r')
1647                 new = pane_root(p->pane);
1648         if (*which == 'F')
1649                 new = pane_focus(p->pane);
1650         if (*which == 'L')
1651                 new = pane_leaf(p->pane);
1652         if (new == NULL) {
1653                 Py_INCREF(Py_None);
1654                 newpane = (Pane*)Py_None;
1655         } else
1656                 newpane = (Pane *)Pane_Frompane(new);
1657
1658         return newpane;
1659 }
1660
1661 static int pane_nosetpane(Pane *p, PyObject *v, void *which)
1662 {
1663         PyErr_SetString(PyExc_TypeError, "Cannot set panes");
1664         return -1;
1665 }
1666
1667 static PyObject *pane_repr(Pane *self safe)
1668 {
1669         char *s = NULL;
1670         PyObject *ret;
1671         if (!pane_valid(self))
1672                 asprintf(&s, "<edlib.Pane FREED!!! %p>", self);
1673         else
1674                 asprintf(&s, "<edlib.Pane %p-%s>", self->pane, self->pane->name);
1675         ret = Py_BuildValue("s", s);
1676         free(s);
1677         return ret;
1678 }
1679
1680 static PyObject *doc_repr(Doc *self safe)
1681 {
1682         char *s = NULL;
1683         PyObject *ret;
1684         if (!doc_valid(self))
1685                 asprintf(&s, "<edlib.Doc FREED!!! %p>", self);
1686         else
1687                 asprintf(&s, "<edlib.Doc %p-%s>", self->pane, self->pane->name);
1688         ret = Py_BuildValue("s", s);
1689         free(s);
1690         return ret;
1691 }
1692
1693 static long pane_hash(Pane *p safe)
1694 {
1695         return (long)p->pane;
1696 }
1697
1698 static PyObject *pane_cmp(Pane *p1 safe, Pane *p2 safe, int op)
1699 {
1700         Py_RETURN_RICHCOMPARE(p1->pane, p2->pane, op);
1701 }
1702
1703 static const PyGetSetDef pane_getseters[] = {
1704         {"x",
1705          (getter)pane_getnum, (setter)pane_setnum,
1706          "X offset in parent", "x" },
1707         {"y",
1708          (getter)pane_getnum, (setter)pane_setnum,
1709          "Y offset in parent", "y" },
1710         {"z",
1711          (getter)pane_getnum, (setter)pane_setnum,
1712          "Z offset in parent", "z" },
1713         {"w",
1714          (getter)pane_getnum, (setter)pane_setnum,
1715          "width of pane", "w" },
1716         {"h",
1717          (getter)pane_getnum, (setter)pane_setnum,
1718          "heigth of pane", "h" },
1719         {"cx",
1720          (getter)pane_getnum, (setter)pane_setnum,
1721          "Cursor X offset in pane", "X" },
1722         {"cy",
1723          (getter)pane_getnum, (setter)pane_setnum,
1724          "Cursor Y offset in pane", "Y" },
1725         {"abs_z",
1726          (getter)pane_getnum, (setter)pane_setnum,
1727          "global Z offset", "Z" },
1728         {"parent",
1729          (getter)pane_getpane, (setter)pane_nosetpane,
1730          "Parent pane", "p"},
1731         {"focus",
1732          (getter)pane_getpane, (setter)pane_nosetpane,
1733          "Focal child", "f"},
1734         {"root",
1735          (getter)pane_getpane, (setter)pane_nosetpane,
1736          "Root pane", "r"},
1737         {"final_focus",
1738          (getter)pane_getpane, (setter)pane_nosetpane,
1739          "Final focus pane", "F"},
1740         {"leaf",
1741          (getter)pane_getpane, (setter)pane_nosetpane,
1742          "Leaf pane", "L"},
1743         {NULL}  /* Sentinel */
1744 };
1745
1746 static PyObject *Pane_get_item(Pane *self safe, PyObject *key safe)
1747 {
1748         char *k, *v;
1749         PyObject *t1 = NULL;
1750
1751         if (!pane_valid(self))
1752                 return NULL;
1753
1754         k = python_as_string(key, &t1);
1755         if (!k) {
1756                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1757                 return NULL;
1758         }
1759         v = pane_attr_get(self->pane, k);
1760         Py_XDECREF(t1);
1761         if (v)
1762                 return Py_BuildValue("s", v);
1763         Py_INCREF(Py_None);
1764         return Py_None;
1765 }
1766
1767 static int Pane_set_item(Pane *self safe, PyObject *key, PyObject *val)
1768 {
1769         char *k, *v;
1770         PyObject *t1 = NULL, *t2 = NULL;
1771
1772         if (!pane_valid(self))
1773                 return -1;
1774
1775         k = python_as_string(key, &t1);
1776         if (!k) {
1777                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1778                 return -1;
1779         }
1780         v = python_as_string(val, &t2);
1781         if (val != Py_None && !v) {
1782                 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
1783                 Py_XDECREF(t1);
1784                 return -1;
1785         }
1786         attr_set_str(&self->pane->attrs, k, v);
1787         Py_XDECREF(t1);
1788         Py_XDECREF(t2);
1789         return 0;
1790 }
1791
1792 static const PyMappingMethods pane_mapping = {
1793         .mp_length = NULL,
1794         .mp_subscript = (binaryfunc)Pane_get_item,
1795         .mp_ass_subscript = (objobjargproc)Pane_set_item,
1796 };
1797
1798 static PyTypeObject PaneType = {
1799         PyVarObject_HEAD_INIT(NULL, 0)
1800         .tp_name        = "edlib.Pane",
1801         .tp_basicsize   = sizeof(Pane),
1802         .tp_dealloc     = (destructor)pane_dealloc,
1803         .tp_richcompare = (richcmpfunc)pane_cmp,
1804         .tp_repr        = (reprfunc)pane_repr,
1805         .tp_as_mapping  = (PyMappingMethods*)&pane_mapping,
1806         .tp_hash        = (hashfunc)pane_hash,
1807         .tp_call        = (ternaryfunc)pane_direct_call,
1808         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1809         .tp_doc         = "edlib panes",
1810         .tp_methods     = (PyMethodDef*)pane_methods,
1811         .tp_getset      = (PyGetSetDef*)pane_getseters,
1812         .tp_init        = (initproc)Pane_init,
1813         .tp_new         = (newfunc)pane_new,
1814 };
1815
1816 static PyTypeObject PaneIterType = {
1817         PyVarObject_HEAD_INIT(NULL, 0)
1818         .tp_name        = "edlib.PaneIter",
1819         .tp_basicsize   = sizeof(PaneIter),
1820         .tp_dealloc     = (destructor)paneiter_dealloc,
1821         .tp_flags       = Py_TPFLAGS_DEFAULT,
1822         .tp_doc         = "edlib pane iterator",
1823         .tp_iter        = (getiterfunc)pane_this_iter,
1824         .tp_iternext    = (iternextfunc)pane_iter_next,
1825         .tp_new         = (newfunc)pane_iter_new,
1826 };
1827
1828 static PyObject *first_mark(Doc *self safe, PyObject *args)
1829 {
1830         struct mark *m;
1831
1832         if (!doc_valid(self))
1833                 return NULL;
1834
1835         m = mark_first(&self->pane->doc_data->doc);
1836         if (!m) {
1837                 Py_INCREF(Py_None);
1838                 return Py_None;
1839         }
1840         return Mark_Frommark(m);
1841 }
1842
1843 static PyObject *to_end(Doc *self safe, PyObject *args)
1844 {
1845         Mark *mark = NULL;
1846         int end = 0;
1847         int ret;
1848
1849         if (!doc_valid(self))
1850                 return NULL;
1851
1852         ret = PyArg_ParseTuple(args, "O!p", &MarkType, &mark, &end);
1853         if (ret <= 0 || !mark || !mark_valid(mark->mark)) {
1854                 PyErr_SetString(PyExc_TypeError, "Mark undefined or uninitialized");
1855                 return NULL;
1856         }
1857
1858         mark_to_end(self->pane, mark->mark, end);
1859         Py_INCREF(Py_None);
1860         return Py_None;
1861 }
1862
1863 static const PyMethodDef doc_methods[] = {
1864         {"first_mark", (PyCFunction)first_mark, METH_NOARGS,
1865          "first mark of document"},
1866         {"to_end", (PyCFunction)to_end, METH_VARARGS,
1867          "Move mark to one end of document"},
1868         {NULL}
1869 };
1870
1871 static PyTypeObject DocType = {
1872         PyVarObject_HEAD_INIT(NULL, 0)
1873         .tp_name        = "edlib.Doc",
1874         .tp_basicsize   = sizeof(Doc),
1875         .tp_dealloc     = (destructor)pane_dealloc,
1876         .tp_repr        = (reprfunc)doc_repr,
1877         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1878         .tp_doc         = "edlib document",
1879         .tp_methods     = (PyMethodDef*)doc_methods,
1880         .tp_base        = &PaneType,
1881         .tp_init        = (initproc)Doc_init,
1882         .tp_new         = (newfunc)Doc_new,
1883 };
1884
1885 static PyObject *mark_getoffset(Mark *m safe, void *x)
1886 {
1887         struct doc *d;
1888         if (!mark_valid(m->mark)) {
1889                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1890                 return NULL;
1891         }
1892         d = &m->mark->owner->doc;
1893         if (d->refcnt == mark_refcnt)
1894                 return PyLong_FromLong(m->mark->ref.o);
1895         return PyLong_FromLong(0);
1896 }
1897
1898 static int mark_setoffset(Mark *m safe, PyObject *v safe, void *x)
1899 {
1900         struct doc *d;
1901         long val;
1902
1903         if (!mark_valid(m->mark)) {
1904                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1905                 return -1;
1906         }
1907         val = PyLong_AsLong(v);
1908         if (val == -1 && PyErr_Occurred())
1909                 return -1;
1910         d = &m->mark->owner->doc;
1911         if (d->refcnt == mark_refcnt)
1912                 m->mark->ref.o = val;
1913         else {
1914                 PyErr_SetString(PyExc_TypeError, "Setting offset on non-local mark");
1915                 return -1;
1916         }
1917         return 0;
1918 }
1919
1920 static PyObject *mark_getseq(Mark *m safe, void *x)
1921 {
1922         if (!mark_valid(m->mark)) {
1923                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1924                 return NULL;
1925         }
1926         return PyLong_FromLong(m->mark->seq);
1927 }
1928
1929 static int mark_nosetseq(Mark *m, PyObject *v, void *which)
1930 {
1931         PyErr_SetString(PyExc_TypeError, "Cannot set mark seq number");
1932         return -1;
1933 }
1934
1935 static void mark_refcnt(struct mark *m safe, int inc)
1936 {
1937         if (!m->ref.c)
1938                 return;
1939         while (inc > 0) {
1940                 Py_INCREF(m->ref.c);
1941                 inc -= 1;
1942         }
1943         while (inc < 0) {
1944                 Py_DECREF(m->ref.c);
1945                 inc += 1;
1946         }
1947 }
1948
1949 static PyObject *mark_getpos(Mark *m safe, void *x)
1950 {
1951         struct doc *d;
1952         if (!mark_valid(m->mark)) {
1953                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1954                 return NULL;
1955         }
1956         d = &m->mark->owner->doc;
1957         if (d->refcnt == mark_refcnt && m->mark->ref.c) {
1958                 Py_INCREF(m->mark->ref.c);
1959                 return m->mark->ref.c;
1960         } else {
1961                 Py_INCREF(Py_None);
1962                 return Py_None;
1963         }
1964 }
1965
1966 static int mark_setpos(Mark *m safe, PyObject *v, void *x)
1967 {
1968         struct mark *m2;
1969         struct doc *d;
1970
1971         if (!mark_valid(m->mark)) {
1972                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1973                 return -1;
1974         }
1975         d = &m->mark->owner->doc;
1976         if (d->refcnt != mark_refcnt) {
1977                 PyErr_SetString(PyExc_TypeError, "Cannot set ref for non-local mark");
1978                 return -1;
1979         }
1980         d->refcnt(m->mark, -1);
1981         if (v == Py_None)
1982                 v = NULL;
1983         /* If an adjacent mark has a ref.c with a matching value
1984          * use that instead, so that mark_same() works.
1985          */
1986         if ((m2 = mark_next(m->mark)) != NULL &&
1987             m2->owner->doc.refcnt == mark_refcnt &&
1988             m2->ref.c != NULL && v != NULL &&
1989             PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1990                 m->mark->ref.c = m2->ref.c;
1991         else if ((m2 = mark_prev(m->mark)) != NULL &&
1992                  m2->owner->doc.refcnt == mark_refcnt &&
1993                  m2->ref.c != NULL && v != NULL &&
1994                  PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1995                 m->mark->ref.c = m2->ref.c;
1996         else
1997                 m->mark->ref.c = v;
1998         d->refcnt(m->mark, 1);
1999         return 0;
2000 }
2001
2002 static PyObject *mark_getview(Mark *m safe, void *x)
2003 {
2004         if (!mark_valid(m->mark)) {
2005                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2006                 return NULL;
2007         }
2008         return PyLong_FromLong(m->mark->viewnum);
2009 }
2010
2011 static int mark_nosetview(Mark *m, PyObject *v, void *which)
2012 {
2013         PyErr_SetString(PyExc_TypeError, "Cannot set mark viewnum");
2014         return -1;
2015 }
2016
2017 static PyObject *mark_compare(Mark *a safe, Mark *b safe, int op)
2018 {
2019         if ((PyObject*)a == Py_None)
2020                 Py_RETURN_RICHCOMPARE(0, 1, op);
2021         else if ((PyObject*)b == Py_None)
2022                 Py_RETURN_RICHCOMPARE(1, 0, op);
2023         else if (PyObject_TypeCheck(a, &MarkType) == 0 ||
2024                  PyObject_TypeCheck(b, &MarkType) == 0) {
2025                 PyErr_SetString(PyExc_TypeError, "Mark compared with non-Mark");
2026                 return NULL;
2027         } else if (!mark_valid(a->mark) || !mark_valid(b->mark))
2028                 return NULL;
2029         else {
2030                 int cmp = a->mark->seq - b->mark->seq;
2031                 if (mark_same(a->mark, b->mark))
2032                         cmp = 0;
2033                 Py_RETURN_RICHCOMPARE(cmp, 0, op);
2034         }
2035 }
2036
2037 static const PyGetSetDef mark_getseters[] = {
2038         {"pos",
2039          (getter)mark_getpos, (setter)mark_setpos,
2040          "Position ref", NULL},
2041         {"offset",
2042          (getter)mark_getoffset, (setter)mark_setoffset,
2043          "Position offset", NULL},
2044         {"viewnum",
2045          (getter)mark_getview, (setter)mark_nosetview,
2046          "Index for view list", NULL},
2047         {"seq",
2048          (getter)mark_getseq, (setter)mark_nosetseq,
2049          "Sequence number of mark", NULL},
2050         {NULL}  /* Sentinel */
2051 };
2052
2053 static Mark *Mark_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
2054 {
2055         Mark *self;
2056
2057         self = (Mark *)type->tp_alloc(type, 0);
2058         if (self) {
2059                 self->mark = NULL;
2060         }
2061         return self;
2062 }
2063
2064 static int Mark_init(Mark *self safe, PyObject *args safe, PyObject *kwds)
2065 {
2066         Pane *doc = NULL;
2067         Pane *owner = NULL;
2068         int view = MARK_UNGROUPED;
2069         Mark *orig = NULL;
2070         static const char *keywords[] = {"pane","view","orig", "owner", NULL};
2071         int ret;
2072
2073         if (!PyTuple_Check(args) ||
2074             (PyTuple_GET_SIZE(args) == 0 && kwds == NULL))
2075                 /* Internal Mark_Frommark call */
2076                 return 1;
2077
2078         ret = PyArg_ParseTupleAndKeywords(args, kwds, "|O!iO!O!", (char**)keywords,
2079                                           &PaneType, &doc,
2080                                           &view,
2081                                           &MarkType, &orig,
2082                                           &PaneType, &owner);
2083         if (ret <= 0)
2084                 return -1;
2085         if (doc && orig) {
2086                 PyErr_SetString(PyExc_TypeError,
2087                                 "Only one of 'pane' and 'orig' may be set");
2088                 return -1;
2089         }
2090         if (!doc && !orig) {
2091                 PyErr_SetString(PyExc_TypeError,
2092                                 "At least one of 'pane' and 'orig' must be set");
2093                 return -1;
2094         }
2095         if (doc && doc->pane) {
2096                 struct pane *p = doc->pane;
2097                 struct pane *op = owner ? owner->pane : NULL;
2098                 if (!op)
2099                         op = p;
2100                 self->mark = vmark_new(p, view, op);
2101         } else if (orig && mark_valid(orig->mark)) {
2102                 self->mark = mark_dup_view(orig->mark);
2103         }
2104         if (!self->mark) {
2105                 PyErr_SetString(PyExc_TypeError, "Mark creation failed");
2106                 return -1;
2107         }
2108         if (self->mark->viewnum >= 0) {
2109                 /* vmarks can use mdata and don't disappear until
2110                  * explicitly released.
2111                  */
2112                 self->mark->mtype = &MarkType;
2113                 self->mark->mdata = self;
2114                 Py_INCREF(self);
2115         } else {
2116                 /* Other marks cannot use mdata and get freed when
2117                  * the original PyObject is destroyed
2118                  */
2119                 self->mark->mtype = (void*)self;
2120         }
2121         return 1;
2122 }
2123
2124 static void mark_dealloc(Mark *self safe)
2125 {
2126         if (mark_valid(self->mark) && self->mark->mtype == (void*)self) {
2127                 /* Python allocated this mark, so can free it. */
2128                 struct mark *m = self->mark;
2129                 self->mark = NULL;
2130                 m->mtype = NULL;
2131                 m->mdata = NULL;
2132                 mark_free(m);
2133         }
2134         do_free((PyObject*safe)self);
2135 }
2136
2137 static PyObject *Mark_to_mark(Mark *self safe, PyObject *args)
2138 {
2139         Mark *other = NULL;
2140         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2141         if (ret <= 0 || !other ||
2142             !mark_valid(self->mark) || !mark_valid(other->mark))
2143                 return NULL;
2144         mark_to_mark(self->mark, other->mark);
2145
2146         Py_INCREF(Py_None);
2147         return Py_None;
2148 }
2149
2150 static PyObject *Mark_to_mark_noref(Mark *self safe, PyObject *args)
2151 {
2152         Mark *other = NULL;
2153         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2154         if (ret <= 0 || !other ||
2155             !mark_valid(self->mark) || !mark_valid(other->mark))
2156                 return NULL;
2157         mark_to_mark_noref(self->mark, other->mark);
2158
2159         Py_INCREF(Py_None);
2160         return Py_None;
2161 }
2162
2163 static PyObject *Mark_clip(Mark *self safe, PyObject *args)
2164 {
2165         Mark *start = NULL, *end = NULL;
2166         int tostart = 0;
2167         int ret = PyArg_ParseTuple(args, "O!O!|p", &MarkType, &start,
2168                                    &MarkType, &end, &tostart);
2169
2170         if (ret > 0 && start && end && mark_valid(self->mark) &&
2171             mark_valid(start->mark) && mark_valid(end->mark))
2172                 mark_clip(self->mark, start->mark, end->mark, tostart);
2173
2174         Py_INCREF(Py_None);
2175         return Py_None;
2176 }
2177
2178 static PyObject *Mark_step(Mark *self safe, PyObject *args)
2179 {
2180         /* Convenience function to help implement doc:char */
2181         int forward = 1;
2182         int ret = PyArg_ParseTuple(args, "i", &forward);
2183
2184         if (ret > 0 && self->mark)
2185                 mark_step(self->mark, forward);
2186
2187         Py_INCREF(Py_None);
2188         return Py_None;
2189 }
2190
2191 static PyObject *Mark_step_sharesref(Mark *self safe, PyObject *args)
2192 {
2193         /* Convenience function to help implement doc:char */
2194         int forward = 1;
2195         int ret = PyArg_ParseTuple(args, "i", &forward);
2196
2197         if (ret > 0 && self->mark)
2198                 mark_step_sharesref(self->mark, forward);
2199
2200         Py_INCREF(Py_None);
2201         return Py_None;
2202 }
2203
2204 static PyObject *Mark_next(Mark *self safe, PyObject *args)
2205 {
2206         struct mark *next;
2207         if (!mark_valid(self->mark)) {
2208                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2209                 return NULL;
2210         }
2211         if (self->mark->viewnum >= 0)
2212                 next = vmark_next(self->mark);
2213         else
2214                 next = NULL;
2215         if (next)
2216                 return Mark_Frommark(next);
2217         Py_INCREF(Py_None);
2218         return Py_None;
2219 }
2220
2221 static PyObject *Mark_prev(Mark *self safe, PyObject *args)
2222 {
2223         struct mark *prev;
2224         if (!mark_valid(self->mark)) {
2225                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2226                 return NULL;
2227         }
2228         if (self->mark->viewnum >= 0)
2229                 prev = vmark_prev(self->mark);
2230         else
2231                 prev = NULL;
2232         if (prev)
2233                 return Mark_Frommark(prev);
2234         Py_INCREF(Py_None);
2235         return Py_None;
2236 }
2237
2238 static PyObject *Mark_next_any(Mark *self safe, PyObject *args)
2239 {
2240         struct mark *next;
2241         if (!mark_valid(self->mark)) {
2242                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2243                 return NULL;
2244         }
2245         next = mark_next(self->mark);
2246         if (next)
2247                 return Mark_Frommark(next);
2248         Py_INCREF(Py_None);
2249         return Py_None;
2250 }
2251
2252 static PyObject *Mark_prev_any(Mark *self safe, PyObject *args)
2253 {
2254         struct mark *prev;
2255         if (!mark_valid(self->mark)) {
2256                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2257                 return NULL;
2258         }
2259         prev = mark_prev(self->mark);
2260         if (prev)
2261                 return Mark_Frommark(prev);
2262         Py_INCREF(Py_None);
2263         return Py_None;
2264 }
2265
2266 static PyObject *Mark_dup(Mark *self safe, PyObject *args)
2267 {
2268         struct mark *new;
2269         if (!mark_valid(self->mark)) {
2270                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2271                 return NULL;
2272         }
2273         new = mark_dup(self->mark);
2274         if (new) {
2275                 Mark *ret = (Mark*)Mark_Frommark(new);
2276                 /* We want this mark to be freed when the Mark
2277                  * dies
2278                  */
2279                 new->mtype = (void*)ret;
2280                 return (PyObject*)ret;
2281         }
2282
2283         Py_INCREF(Py_None);
2284         return Py_None;
2285 }
2286
2287 static PyObject *Mark_release(Mark *self safe, PyObject *args)
2288 {
2289         struct mark *m = self->mark;
2290
2291         if (!mark_valid(m)) {
2292                 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2293                 return NULL;
2294         }
2295         if (m->viewnum == MARK_UNGROUPED || m->viewnum == MARK_POINT) {
2296                 PyErr_SetString(PyExc_TypeError,
2297                                 "Cannot release ungrouped marks or points");
2298                 return NULL;
2299         }
2300         if (m->mtype != &MarkType) {
2301                 PyErr_SetString(PyExc_TypeError,
2302                                 "Mark is not managed by python, and cannot be released");
2303                 return NULL;
2304         }
2305
2306         /* We are dropping this mark - there cannot be any other ref */
2307         ASSERT(m->mdata == self);
2308         self->mark = NULL;
2309         Py_DECREF(self);
2310         m->mdata = NULL;
2311         m->mtype = NULL;
2312         mark_free(m);
2313
2314         Py_INCREF(Py_None);
2315         return Py_None;
2316 }
2317
2318 static PyObject *Mark_watch(Mark *self safe, PyObject *args)
2319 {
2320         struct mark *m = self->mark;
2321
2322         if (!mark_valid(m)) {
2323                 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2324                 return NULL;
2325         }
2326         mark_watch(m);
2327         Py_INCREF(Py_None);
2328         return Py_None;
2329 }
2330
2331 static const PyMethodDef mark_methods[] = {
2332         {"to_mark", (PyCFunction)Mark_to_mark, METH_VARARGS,
2333          "Move one mark to another"},
2334         {"to_mark_noref", (PyCFunction)Mark_to_mark_noref, METH_VARARGS,
2335          "Move one mark to another but don't update ref"},
2336         {"next", (PyCFunction)Mark_next, METH_NOARGS,
2337          "next vmark"},
2338         {"prev", (PyCFunction)Mark_prev, METH_NOARGS,
2339          "previous vmark"},
2340         {"next_any", (PyCFunction)Mark_next_any, METH_NOARGS,
2341          "next any_mark"},
2342         {"prev_any", (PyCFunction)Mark_prev_any, METH_NOARGS,
2343          "previous any_mark"},
2344         {"dup", (PyCFunction)Mark_dup, METH_NOARGS,
2345          "duplicate a mark, as ungrouped"},
2346         {"clip", (PyCFunction)Mark_clip, METH_VARARGS,
2347          "If this mark is in range, move to end"},
2348         {"release", (PyCFunction)Mark_release, METH_NOARGS,
2349          "release a vmark so it can disappear"},
2350         {"watch", (PyCFunction)Mark_watch, METH_NOARGS,
2351          "acknowledge movement of a point - allow further notifications"},
2352         {"step", (PyCFunction)Mark_step, METH_VARARGS,
2353          "Move mark over any adjacent marks with same reference"},
2354         {"step_sharesref", (PyCFunction)Mark_step_sharesref, METH_VARARGS,
2355          "Move mark over any adjacent marks with same reference"},
2356         {NULL}
2357 };
2358
2359 static PyObject *mark_get_item(Mark *self safe, PyObject *key safe)
2360 {
2361         char *k, *v;
2362         PyObject *t1 = NULL;
2363
2364         if (!mark_valid(self->mark)) {
2365                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2366                 return NULL;
2367         }
2368         k = python_as_string(key, &t1);
2369         if (!k) {
2370                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2371                 return NULL;
2372         }
2373         v = attr_find(self->mark->attrs, k);
2374         Py_XDECREF(t1);
2375         if (v)
2376                 return Py_BuildValue("s", v);
2377         Py_INCREF(Py_None);
2378         return Py_None;
2379 }
2380
2381 static int mark_set_item(Mark *self safe, PyObject *key safe, PyObject *val safe)
2382 {
2383         char *k, *v;
2384         PyObject *t1 = NULL, *t2 = NULL;
2385         if (!mark_valid(self->mark)) {
2386                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2387                 return -1;
2388         }
2389         k = python_as_string(key, &t1);
2390         if (!k) {
2391                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2392                 return -1;
2393         }
2394         v = python_as_string(val, &t2);
2395         if (val != Py_None && !v) {
2396                 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
2397                 Py_XDECREF(t1);
2398                 return -1;
2399         }
2400         attr_set_str(&self->mark->attrs, k, v);
2401         Py_XDECREF(t1);
2402         Py_XDECREF(t2);
2403         return 0;
2404 }
2405
2406 static PyObject *mark_repr(Mark *self safe)
2407 {
2408         char *s = NULL, *dm;
2409         PyObject *ret;
2410
2411         if (!self->mark)
2412                 asprintf(&s, "<edlib.Mark NULL %p>", self);
2413         else if (!mark_valid(self->mark))
2414                 asprintf(&s, "<edlib.Mark FREED %p>", self);
2415         else if ((dm = call_ret(str, "doc:debug:mark", self->mark->owner,
2416                                 0, self->mark))
2417                  != NULL)
2418                 asprintf(&s, "<edlib.Mark seq=%d v=%d %s>",
2419                          self->mark->seq, self->mark->viewnum, dm);
2420         else
2421                 asprintf(&s, "<edlib.Mark seq=%d v=%d i=%d %p>",
2422                          self->mark->seq, self->mark->viewnum,
2423                          self->mark->ref.o, self->mark);
2424
2425         ret = Py_BuildValue("s", s);
2426         free(s);
2427         return ret;
2428 }
2429
2430 static const PyMappingMethods mark_mapping = {
2431         .mp_length = NULL,
2432         .mp_subscript = (binaryfunc)mark_get_item,
2433         .mp_ass_subscript = (objobjargproc)mark_set_item,
2434 };
2435
2436 static int mark_bool(Mark *self safe)
2437 {
2438         return mark_valid(self->mark);
2439 }
2440
2441 static const PyNumberMethods mark_as_num = {
2442         .nb_bool        = (inquiry) mark_bool,
2443 };
2444
2445 static PyTypeObject MarkType = {
2446         PyVarObject_HEAD_INIT(NULL, 0)
2447         .tp_name        = "edlib.Mark",
2448         .tp_basicsize   = sizeof(Mark),
2449         .tp_dealloc     = (destructor)mark_dealloc,
2450         .tp_as_mapping  = (PyMappingMethods*)&mark_mapping,
2451         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2452         .tp_doc         = "edlib marks",
2453         .tp_richcompare = (richcmpfunc)mark_compare,
2454         .tp_methods     = (PyMethodDef*)mark_methods,
2455         .tp_getset      = (PyGetSetDef*)mark_getseters,
2456         .tp_init        = (initproc)Mark_init,
2457         .tp_new         = (newfunc)Mark_new,
2458         .tp_repr        = (reprfunc)mark_repr,
2459         .tp_as_number   = (PyNumberMethods*)&mark_as_num,
2460 };
2461
2462 static void comm_dealloc(Comm *self safe)
2463 {
2464         command_put(self->comm);
2465         do_free((PyObject*safe)self);
2466 }
2467
2468 static PyObject *comm_repr(Comm *self safe)
2469 {
2470         char *s = NULL;
2471         PyObject *ret;
2472
2473         if (self->comm)
2474                 asprintf(&s, "<edlib.Comm refcnt=%d %p>",
2475                          self->comm->refcnt, self->comm);
2476         else
2477                 asprintf(&s, "<edlib.Comm NULL %p>", self);
2478         ret = Py_BuildValue("s", s);
2479         free(s);
2480         return ret;
2481 }
2482
2483 static PyObject *Comm_call(Comm *c safe, PyObject *args safe, PyObject *kwds)
2484 {
2485         struct cmd_info ci = SAFE_CI;
2486         int rv;
2487         PyObject *s1, *s2;
2488         struct pyret pr;
2489
2490         if (!c->comm)
2491                 return NULL;
2492         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
2493             !handle_ret(kwds, &ci, &pr)) {
2494                 Py_XDECREF(s1); Py_XDECREF(s2);
2495                 command_put(ci.comm2);
2496                 return NULL;
2497         }
2498         ci.comm = c->comm;
2499         rv = c->comm->func(&ci);
2500         Py_XDECREF(s1); Py_XDECREF(s2);
2501         command_put(ci.comm2);
2502
2503         return choose_ret(rv, &pr);
2504 }
2505
2506 static PyObject *comm_cmp(Comm *c1 safe, Comm *c2 safe, int op)
2507 {
2508         Py_RETURN_RICHCOMPARE(c1->comm, c2->comm, op);
2509 }
2510
2511 static Comm *comm_new(PyTypeObject *type safe, PyObject *args safe, PyObject *kwds)
2512 {
2513         Comm *self;
2514
2515         self = (Comm *)type->tp_alloc(type, 0);
2516         if (self)
2517                 self->comm = NULL;
2518         return self;
2519 }
2520
2521 static PyTypeObject CommType = {
2522         PyVarObject_HEAD_INIT(NULL, 0)
2523         .tp_name        = "edlib.Comm",
2524         .tp_basicsize   = sizeof(Comm),
2525         .tp_dealloc     = (destructor)comm_dealloc,
2526         .tp_richcompare = (richcmpfunc)comm_cmp,
2527         .tp_repr        = (reprfunc)comm_repr,
2528         .tp_call        = (ternaryfunc)Comm_call,
2529         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2530         .tp_doc         = "edlib command",
2531         .tp_new         = (newfunc)comm_new,
2532 };
2533
2534 static void python_free_command(struct command *c safe)
2535 {
2536         struct python_command *pc = container_of(c, struct python_command, c);
2537
2538         if (pc->callable)
2539                 Py_DECREF(pc->callable);
2540         list_del(&pc->lst);
2541         free(pc);
2542 }
2543
2544 /* The 'call' function takes liberties with arg passing.
2545  * Positional args must start with the key, and then are handled based on
2546  * there type.  They can be panes, strigns, ints, pairs, marks, commands.
2547  * Panes are assigned to focus, then home.
2548  * Strings (after the key) are assigned to 'str' then 'str2'.
2549
2550  * Ints are assigned to num then num2
2551  * Pairs (must be of ints) are assigned to x,y then hx,hy.
2552  * Marks are assigned to mark then mark2
2553  * A command is assigned to comm2 (comm is set automatically)
2554  * kwd arguments can also be used, currently
2555  * key, home, focus, xy, hxy, str, str2, mark, mark2, comm2.
2556  * A 'None' arg is ignored - probably a mark or string or something. Just use NULL
2557  */
2558 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
2559                          PyObject **s1 safe, PyObject **s2 safe)
2560 {
2561         int argc;
2562         PyObject *a;
2563         int i;
2564         int num_set = 0, num2_set = 0;
2565         int xy_set = 0;
2566
2567         *s1 = *s2 = NULL;
2568
2569         if (!PyTuple_Check(args))
2570                 return False;
2571         argc = PyTuple_GET_SIZE(args);
2572         if (argc >= 1) {
2573                 /* First positional arg must be the key */
2574                 a = PyTuple_GetItem(args, 0);
2575                 if (!PyUnicode_Check(a)) {
2576                         PyErr_SetString(PyExc_TypeError, "First arg must be key");
2577                         return False;
2578                 }
2579                 ci->key = safe_cast PyUnicode_AsUTF8(a);
2580         }
2581         for (i = 1; i < argc; i++) {
2582                 a = PyTuple_GetItem(args, i);
2583                 if (!a || a == Py_None)
2584                         /* quietly ignore */;
2585                 else if (PyObject_TypeCheck(a, &PaneType)) {
2586                         if ((void*)ci->home == NULL)
2587                                 ci->home = safe_cast ((Pane*)a)->pane;
2588                         else if ((void*)ci->focus == NULL)
2589                                 ci->focus = safe_cast ((Pane*)a)->pane;
2590                         else {
2591                                 PyErr_SetString(PyExc_TypeError, "Only 2 Pane args permitted");
2592                                 return False;
2593                         }
2594                 } else if (PyObject_TypeCheck(a, &MarkType)) {
2595                         if (ci->mark == NULL)
2596                                 ci->mark = ((Mark*)a)->mark;
2597                         else if (ci->mark2 == NULL)
2598                                 ci->mark2 = ((Mark*)a)->mark;
2599                         else {
2600                                 PyErr_SetString(PyExc_TypeError, "Only 2 Mark args permitted");
2601                                 return False;
2602                         }
2603                 } else if (PyUnicode_Check(a)) {
2604                         char *str;
2605                         PyObject *s = NULL;
2606                         if (ci->str && ci->str2) {
2607                                 PyErr_SetString(PyExc_TypeError, "Only 3 String args permitted");
2608                                 return False;
2609                         }
2610                         str = python_as_string(a, &s);
2611                         if (!str)
2612                                 return False;
2613                         if (s) {
2614                                 *s2 = *s1;
2615                                 *s1 = s;
2616                         }
2617                         if (ci->str == NULL)
2618                                 ci->str = str;
2619                         else
2620                                 ci->str2 = str;
2621                 } else if (PyLong_Check(a)) {
2622                         if (!num_set) {
2623                                 ci->num = PyLong_AsLong(a);
2624                                 num_set = 1;
2625                         } else if (!num2_set) {
2626                                 ci->num2 = PyLong_AsLong(a);
2627                                 num2_set = 1;
2628                         } else {
2629                                 PyErr_SetString(PyExc_TypeError, "Only 2 Number args permitted");
2630                                 return False;
2631                         }
2632                 } else if (PyTuple_Check(a)) {
2633                         int n = PyTuple_GET_SIZE(a);
2634                         PyObject *n1, *n2;
2635                         if (n != 2) {
2636                                 PyErr_SetString(PyExc_TypeError, "Only 2-element tuples permitted");
2637                                 return False;
2638                         }
2639                         n1 = PyTuple_GetItem(a, 0);
2640                         n2 = PyTuple_GetItem(a, 1);
2641                         if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2642                                 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2643                                 return False;
2644                         }
2645                         if (!xy_set) {
2646                                 ci->x = PyLong_AsLong(n1);
2647                                 ci->y = PyLong_AsLong(n2);
2648                                 xy_set = 1;
2649                         } else {
2650                                 PyErr_SetString(PyExc_TypeError, "Only one tuple permitted");
2651                                 return False;
2652                         }
2653                 } else if (PyObject_TypeCheck(a, &CommType)) {
2654                         Comm *c = (Comm*)a;
2655                         if (ci->comm2 == NULL && c->comm) {
2656                                 ci->comm2 = command_get(c->comm);
2657                         } else {
2658                                 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2659                                 return False;
2660                         }
2661                 } else if (PyCallable_Check(a)) {
2662                         struct python_command *pc = export_callable(a, NULL);
2663
2664                         if (ci->comm2 == NULL)
2665                                 ci->comm2 = &pc->c;
2666                         else {
2667                                 command_put(&pc->c);
2668                                 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2669                                 return False;
2670                         }
2671                 } else {
2672                         PyErr_Format(PyExc_TypeError, "Unsupported arg type %d", i);
2673                         return False;
2674                 }
2675         }
2676         if (kwds && PyDict_Check(kwds)) {
2677                 a = PyDict_GetItemString(kwds, "str1");
2678                 if (!a || a == Py_None)
2679                         a = PyDict_GetItemString(kwds, "str");
2680                 if (a && a != Py_None) {
2681                         if (*s1 || ci->str) {
2682                                 PyErr_SetString(PyExc_TypeError,
2683                                                 "'str' given with other strings");
2684                                 return False;
2685                         }
2686                         if (!PyUnicode_Check(a)) {
2687                                 PyErr_SetString(PyExc_TypeError,
2688                                                 "'str' must be string or unicode");
2689                                 return False;
2690                         }
2691                         ci->str = python_as_string(a, s1);
2692                 }
2693                 a = PyDict_GetItemString(kwds, "str2");
2694                 if (a && a != Py_None) {
2695                         if (*s2 || ci->str2) {
2696                                 PyErr_SetString(PyExc_TypeError,
2697                                                 "'str2' given with 2 strings");
2698                                 return False;
2699                         }
2700                         if (!PyUnicode_Check(a)) {
2701                                 PyErr_SetString(PyExc_TypeError,
2702                                                 "'str2' must be string or unicode");
2703                                 return False;
2704                         }
2705                         ci->str2 = python_as_string(a, s2);
2706                 }
2707                 a = PyDict_GetItemString(kwds, "mark");
2708                 if (a && a != Py_None) {
2709                         if (ci->mark) {
2710                                 PyErr_SetString(PyExc_TypeError,
2711                                                 "'mark' given with other marks");
2712                                 return False;
2713                         }
2714                         if (!PyObject_TypeCheck(a, &MarkType)) {
2715                                 PyErr_SetString(PyExc_TypeError,
2716                                                 "'mark' must be an edlib.Mark");
2717                                 return False;
2718                         }
2719                         ci->mark = ((Mark*)a)->mark;
2720                 }
2721                 a = PyDict_GetItemString(kwds, "mark2");
2722                 if (a && a != Py_None) {
2723                         if (ci->mark2) {
2724                                 PyErr_SetString(PyExc_TypeError,
2725                                                 "'mark2' given with 2 other marks");
2726                                 return False;
2727                         }
2728                         if (!PyObject_TypeCheck(a, &MarkType)) {
2729                                 PyErr_SetString(PyExc_TypeError,
2730                                                 "'mark2' must be an edlib.Mark");
2731                                 return False;
2732                         }
2733                         ci->mark2 = ((Mark*)a)->mark;
2734                 }
2735                 a = PyDict_GetItemString(kwds, "num");
2736                 if (a) {
2737                         if (num_set) {
2738                                 PyErr_SetString(PyExc_TypeError,
2739                                                 "'num' given with other numbers");
2740                                 return False;
2741                         }
2742                         if (!PyLong_Check(a)) {
2743                                 PyErr_SetString(PyExc_TypeError,
2744                                                 "'num' must be an integer");
2745                                 return False;
2746                         }
2747                         ci->num = PyLong_AsLong(a);
2748                         num_set = 1;
2749                 }
2750                 a = PyDict_GetItemString(kwds, "num2");
2751                 if (a) {
2752                         if (num2_set) {
2753                                 PyErr_SetString(PyExc_TypeError,
2754                                                 "'num2' given with 2 other numbers");
2755                                 return False;
2756                         }
2757                         if (!PyLong_Check(a)) {
2758                                 PyErr_SetString(PyExc_TypeError,
2759                                                 "'num2' must be an integer");
2760                                 return False;
2761                         }
2762                         ci->num2 = PyLong_AsLong(a);
2763                         num2_set = 1;
2764                 }
2765                 a = PyDict_GetItemString(kwds, "focus");
2766                 if (a && a != Py_None) {
2767                         Pane *p;
2768                         if ((void*)ci->focus) {
2769                                 PyErr_SetString(PyExc_TypeError,
2770                                                 "'focus' given with other pane");
2771                                 return False;
2772                         }
2773                         if (!PyObject_TypeCheck(a, &PaneType)) {
2774                                 PyErr_SetString(PyExc_TypeError,
2775                                                 "'focus' must be a pane");
2776                                 return False;
2777                         }
2778                         p = (Pane*)a;
2779                         if (p->pane)
2780                                 ci->focus = p->pane;
2781                         else {
2782                                 PyErr_SetString(PyExc_TypeError, "focus value invalid");
2783                                 return False;
2784                         }
2785                 }
2786                 a = PyDict_GetItemString(kwds, "xy");
2787                 if (a && a != Py_None) {
2788                         PyObject *n1, *n2;
2789                         if (xy_set) {
2790                                 PyErr_SetString(PyExc_TypeError,
2791                                                 "'xy' given with other tuple");
2792                                 return False;
2793                         }
2794                         if (!PyTuple_Check(a) || PyTuple_GET_SIZE(a) != 2) {
2795                                 PyErr_SetString(PyExc_TypeError,
2796                                                 "'xy' must be a tuple of 2 integers");
2797                                 return False;
2798                         }
2799                         n1 = PyTuple_GetItem(a, 0);
2800                         n2 = PyTuple_GetItem(a, 1);
2801                         if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2802                                 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2803                                 return False;
2804                         }
2805                         ci->x = PyLong_AsLong(n1);
2806                         ci->y = PyLong_AsLong(n2);
2807                         xy_set = 1;
2808                 }
2809                 a = PyDict_GetItemString(kwds, "comm2");
2810                 if (a && a != Py_None) {
2811                         if (ci->comm2) {
2812                                 PyErr_SetString(PyExc_TypeError,
2813                                                 "'comm2' given with other command");
2814                                 return False;
2815                         }
2816                         if (PyObject_TypeCheck(a, &CommType)) {
2817                                 Comm *c = (Comm*)a;
2818                                 if (c->comm)
2819                                         ci->comm2 = command_get(c->comm);
2820                                 else {
2821                                         PyErr_SetString(PyExc_TypeError, "comm2 value invalid");
2822                                         return False;
2823                                 }
2824                         } else if (PyCallable_Check(a)) {
2825                                 struct python_command *pc = export_callable(a, NULL);
2826
2827                                 ci->comm2 = &pc->c;
2828                         } else {
2829                                 PyErr_SetString(PyExc_TypeError,
2830                                                 "'comm2' must be a callable");
2831                                 return False;
2832                         }
2833                 }
2834         }
2835         if (!(void*)ci->key) {
2836                 PyErr_SetString(PyExc_TypeError, "No key specified");
2837                 return False;
2838         }
2839         if (!(void*)ci->home) {
2840                 PyErr_SetString(PyExc_TypeError, "No pane specified");
2841                 return False;
2842         }
2843         if (!(void*)ci->focus)
2844                 ci->focus = ci->home;
2845
2846         return True;
2847 }
2848
2849 static PyObject *py_time_start(PyObject *self, PyObject *args)
2850 {
2851         int type;
2852         int ret = PyArg_ParseTuple(args, "i", &type);
2853
2854         if (ret <= 0)
2855                 return NULL;
2856         time_start(type);
2857
2858         Py_INCREF(Py_None);
2859         return Py_None;
2860 }
2861
2862 static PyObject *py_time_stop(PyObject *self, PyObject *args)
2863 {
2864         int type;
2865         int ret = PyArg_ParseTuple(args, "i", &type);
2866
2867         if (ret <= 0)
2868                 return NULL;
2869         time_stop(type);
2870
2871         Py_INCREF(Py_None);
2872         return Py_None;
2873 }
2874
2875 static PyObject *py_LOG(PyObject *self, PyObject *args)
2876 {
2877         int argc = PySequence_Length(args);
2878         int i;
2879         char buf[1024];
2880         int l = 0;
2881
2882         for (i = 0; i < argc && l < (int)sizeof(buf) - 2; i++) {
2883                 PyObject *o = PySequence_GetItem(args, i);
2884                 PyObject *s, *tofree = NULL;
2885                 char *str;
2886                 unsigned int slen;
2887
2888                 if (!o)
2889                         continue;
2890                 s = PyObject_Str(o);
2891                 Py_DECREF(o);
2892                 if (!s)
2893                         continue;
2894                 str = python_as_string(s, &tofree);
2895                 slen = str ? strlen(str) : 0;
2896                 if (slen + l + 2 > sizeof(buf))
2897                         slen = sizeof(buf) - l - 2;
2898                 if (str) {
2899                         if (l)
2900                                 buf[l++] = ' ';
2901                         strncpy(buf+l, str, slen);
2902                         l += slen;
2903                 }
2904                 Py_XDECREF(tofree);
2905         }
2906         buf[l] = 0;
2907         if (l)
2908                 LOG("%s", buf);
2909
2910         Py_INCREF(Py_None);
2911         return Py_None;
2912 }
2913
2914 static PyObject *py_LOG_BT(PyObject *self, PyObject *args)
2915 {
2916         LOG_BT();
2917         Py_INCREF(Py_None);
2918         return Py_None;
2919 }
2920
2921 static const PyMethodDef edlib_methods[] = {
2922         {"time_start", py_time_start, METH_VARARGS,
2923          "Record start time"},
2924         {"time_stop", py_time_stop, METH_VARARGS,
2925          "Record stop time"},
2926         {"LOG", py_LOG, METH_VARARGS,
2927          "Generate log message"},
2928         {"LOG_BT", py_LOG_BT, METH_NOARGS,
2929          "Generate backtrace message"},
2930         {NULL, NULL, 0, NULL}
2931 };
2932
2933 /* This must be visible when the module is loaded so it
2934  * cannot be static.  sparse doesn't like variables that are
2935  * neither extern nor static.  So mark it extern
2936  */
2937 extern char *edlib_module_path;
2938 char *edlib_module_path;
2939
2940 void edlib_init(struct pane *ed safe)
2941 {
2942         PyObject *m;
2943         PyConfig config;
2944         char *argv[2]= { "edlib", NULL };
2945         sighandler_t sigint;
2946
2947         if (edlib_module_path)
2948                 module_dir = strdup(edlib_module_path);
2949         else
2950                 module_dir = ".";
2951
2952         /* de-register SIGINT while we initialise python,
2953          * so that Python thinks that it's registration is
2954          * valid - so PyErr_SetInterrupt() don't think there
2955          * is a race.
2956          */
2957         sigint = signal(SIGINT, SIG_DFL);
2958         PyConfig_InitPythonConfig(&config);
2959         config.isolated = 1;
2960         PyConfig_SetBytesArgv(&config, 0, argv);
2961         Py_InitializeFromConfig(&config);
2962         PyConfig_Clear(&config);
2963         signal(SIGINT, sigint);
2964
2965         PaneType.tp_new = PyType_GenericNew;
2966         PaneIterType.tp_new = PyType_GenericNew;
2967         DocType.tp_new = PyType_GenericNew;
2968         MarkType.tp_new = PyType_GenericNew;
2969         CommType.tp_new = PyType_GenericNew;
2970         if (PyType_Ready(&PaneType) < 0 ||
2971             PyType_Ready(&PaneIterType) < 0 ||
2972             PyType_Ready(&DocType) < 0 ||
2973             PyType_Ready(&MarkType) < 0 ||
2974             PyType_Ready(&CommType) < 0)
2975                 return;
2976
2977         m = PyImport_AddModule("edlib");
2978         if (!m) {
2979                 PyErr_LOG();
2980                 return;
2981         }
2982
2983         PyModule_SetDocString(m , "edlib - one more editor is never enough");
2984
2985         PyModule_AddFunctions(m, (PyMethodDef*)edlib_methods);
2986         PyModule_AddObject(m, "editor", Pane_Frompane(ed));
2987         PyModule_AddObject(m, "Pane", (PyObject *)&PaneType);
2988         PyModule_AddObject(m, "PaneIter", (PyObject *)&PaneIterType);
2989         PyModule_AddObject(m, "Mark", (PyObject *)&MarkType);
2990         PyModule_AddObject(m, "Comm", (PyObject *)&CommType);
2991         PyModule_AddObject(m, "Doc", (PyObject *)&DocType);
2992         PyModule_AddIntMacro(m, DAMAGED_CHILD);
2993         PyModule_AddIntMacro(m, DAMAGED_SIZE);
2994         PyModule_AddIntMacro(m, DAMAGED_VIEW);
2995         PyModule_AddIntMacro(m, DAMAGED_REFRESH);
2996         PyModule_AddIntMacro(m, DAMAGED_POSTORDER);
2997         PyModule_AddIntMacro(m, DAMAGED_CLOSED);
2998         PyModule_AddIntMacro(m, Efallthrough);
2999         PyModule_AddIntMacro(m, Enoarg);
3000         PyModule_AddIntMacro(m, Einval);
3001         PyModule_AddIntMacro(m, Efalse);
3002         PyModule_AddIntMacro(m, Efail);
3003         PyModule_AddIntMacro(m, Enosup);
3004         PyModule_AddIntMacro(m, Efail);
3005         PyModule_AddIntMacro(m, NO_NUMERIC);
3006
3007         PyModule_AddIntMacro(m, TIME_KEY);
3008         PyModule_AddIntMacro(m, TIME_WINDOW);
3009         PyModule_AddIntMacro(m, TIME_READ);
3010         PyModule_AddIntMacro(m, TIME_SIG);
3011         PyModule_AddIntMacro(m, TIME_TIMER);
3012         PyModule_AddIntMacro(m, TIME_IDLE);
3013         PyModule_AddIntMacro(m, TIME_REFRESH);
3014         PyModule_AddIntMacro(m, TIME_MISC);
3015
3016         PyModule_AddIntMacro(m, RXLF_ANCHORED);
3017         PyModule_AddIntMacro(m, RXLF_BACKTRACK);
3018
3019         PyModule_AddIntMacro(m, MARK_UNGROUPED);
3020         PyModule_AddIntMacro(m, MARK_POINT);
3021
3022         PyModule_AddIntConstant(m, "WEOF", 0x3FFFFF);
3023
3024         PyModule_AddIntConstant(m, "testing", edlib_testing(ed));
3025
3026         Edlib_CommandFailed = PyErr_NewException("edlib.commandfailed", NULL, NULL);
3027         Py_INCREF(Edlib_CommandFailed);
3028         PyModule_AddObject(m, "commandfailed", Edlib_CommandFailed);
3029
3030         EdlibModule = m;
3031         ed_pane = ed;
3032
3033         call_comm("global-set-command", ed, &handle_alarm,
3034                   0, NULL, "fast-alarm-python");
3035
3036         call_comm("global-set-command", ed, &python_load_module,
3037                   0, NULL, "global-load-modules:python");
3038 }