]> git.neil.brown.name Git - edlib.git/blob - lang-python.c
Remove doc->self link.
[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 #include "core.h"
72 #include "misc.h"
73 #include "rexel.h"
74
75 struct python_doc {
76         struct doc      doc;
77         struct pydoc    *pdoc;
78 };
79
80 #include "core-pane.h"
81
82 #define SAFE_CI {.key=safe_cast NULL,\
83                  .home=safe_cast NULL,\
84                  .focus=safe_cast NULL,\
85                  .comm=safe_cast NULL,\
86         }
87
88 static PyObject *Edlib_CommandFailed;
89 static PyObject *EdlibModule;
90
91 static struct pane *ed_pane;
92
93 static char *module_dir;
94 static char *python_as_string(PyObject *s, PyObject **tofree safe);
95
96 /* Python commands visible to edlib are wrapped in
97  * the python_command.  There is only one per callback,
98  * so that edlib code can compare for equalty.
99  */
100 struct python_command {
101         struct command  c;
102         PyObject        *callable;
103         struct list_head lst;
104 };
105 static LIST_HEAD(exported_commands);
106
107 DEF_CMD(python_call);
108 DEF_CMD(python_pane_call);
109 DEF_CMD(python_doc_call);
110 static void python_free_command(struct command *c safe);
111
112 static struct python_command *export_callable(PyObject *callable safe,
113                                               PyObject *nm)
114 {
115         struct python_command *c;
116         const char *name = NULL;
117         int len;
118
119         if (nm && PyUnicode_Check(nm))
120                 name = PyUnicode_AsUTF8(nm);
121         if (!name)
122                 name = "";
123         len = strlen(name);
124
125         list_for_each_entry(c, &exported_commands, lst)
126                 if (c->callable == callable) {
127                         command_get(&c->c);
128                         return c;
129                 }
130
131         c = malloc(sizeof(*c));
132         c->c = python_call;
133         c->c.free = python_free_command;
134         c->c.refcnt = 0;
135         if (strcmp(name, "handle_close") == 0 ||
136             (len > 10 &&
137              strcmp(name+len-10, "_closed_ok") == 0))
138                 c->c.closed_ok = 1;
139         else
140                 c->c.closed_ok = 0;
141         command_get(&c->c);
142         Py_INCREF(callable);
143         c->callable = callable;
144         list_add(&c->lst, &exported_commands);
145         return c;
146 }
147
148 typedef struct {
149         PyObject_HEAD;
150         struct pane     *pane;
151         struct command  cmd;
152         struct map      *map;
153         int             map_init;
154 } Pane;
155 static PyTypeObject PaneType;
156
157 typedef struct {
158         PyObject_HEAD;
159         struct pane     *pane;
160 } PaneIter;
161 static PyTypeObject PaneIterType;
162
163 typedef struct pydoc {
164         PyObject_HEAD;
165         struct pane     *pane;
166         struct command  cmd;
167         struct map      *map;
168         int             map_init;
169 } Doc;
170 static PyTypeObject DocType;
171
172 typedef struct Mark {
173         PyObject_HEAD;
174         struct mark     *mark;
175 } Mark;
176 static PyTypeObject MarkType;
177 static void mark_refcnt(struct mark *m safe, int inc);
178
179 typedef struct {
180         PyObject_HEAD;
181         struct command  *comm;
182 } Comm;
183 static PyTypeObject CommType;
184
185 static inline bool pane_valid(Pane *p safe)
186 {
187         if (p->pane && p->pane->handle)
188                 return True;
189         PyErr_SetString(PyExc_TypeError, "Pane has been freed");
190         return False;
191 }
192
193 static inline bool doc_valid(Doc *p safe)
194 {
195         if (p->pane && p->pane->handle)
196                 return True;
197         PyErr_SetString(PyExc_TypeError, "Doc pane has been freed");
198         return False;
199 }
200
201 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
202                          PyObject **s1 safe, PyObject **s2 safe);
203
204 static int in_pane_frompane = 0;
205 static inline PyObject *safe Pane_Frompane(struct pane *p)
206 {
207         Pane *pane;
208         if (p && p->handle && p->handle->func == python_pane_call.func) {
209                 pane = p->data;
210                 Py_INCREF(pane);
211         } else if (p && p->handle && p->handle->func == python_doc_call.func) {
212                 struct python_doc *pd = p->doc_data;
213                 Doc *pdoc = pd->pdoc;
214                 pane = (Pane*)pdoc;
215                 Py_INCREF(pane);
216         } else {
217                 in_pane_frompane = 1;
218                 pane = (Pane *)PyObject_CallObject((PyObject*)&PaneType, NULL);
219                 in_pane_frompane = 0;
220                 if (!pane)
221                         ;
222                 else if (p)
223                         pane->pane = pane_get(p);
224                 else
225                         pane->pane = p;
226         }
227         return (PyObject*)pane;
228 }
229
230 static inline PyObject *safe Mark_Frommark(struct mark *m safe)
231 {
232         Mark *mark;
233
234         if (mark_valid(m) && m->mtype == &MarkType && m->mdata) {
235                 /* This is a vmark, re-use the PyObject */
236                 Py_INCREF(m->mdata);
237                 return (PyObject*)m->mdata;
238         }
239         mark = (Mark *)PyObject_CallObject((PyObject*)&MarkType, NULL);
240         if (mark && mark_valid(m))
241                 mark->mark = m;
242         return (PyObject*)mark;
243 }
244
245 static inline PyObject *safe Comm_Fromcomm(struct command *c safe)
246 {
247         Comm *comm = (Comm *)PyObject_CallObject((PyObject*)&CommType, NULL);
248         if (comm)
249                 comm->comm = command_get(c);
250         return (PyObject*)comm;
251 }
252
253 static PyObject *py_LOG(PyObject *self, PyObject *args);
254 static void PyErr_LOG(void)
255 {
256         /* cribbed from https://groups.google.com/forum/#!topic/comp.lang.python/khLrxC6EOKc */
257         char *errorMsg = NULL;
258         PyObject *modIO = NULL;
259         PyObject *modTB = NULL;
260         PyObject *obFuncStringIO = NULL;
261         PyObject *obIO = NULL;
262         PyObject *obFuncTB = NULL;
263         PyObject *argsTB = NULL;
264         PyObject *obResult = NULL;
265         PyObject *tofree = NULL;
266         PyObject *exc_typ, *exc_val, *exc_tb;
267
268         if (!PyErr_Occurred())
269                 return;
270
271         PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
272         PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
273         if (exc_tb)
274                 PyException_SetTraceback(exc_val, exc_tb);
275
276         /* Import the modules we need - StringIO and traceback */
277         errorMsg = "Can't import io";
278         modIO = PyImport_ImportModule("io");
279         if (!modIO)
280                 goto out;
281
282         errorMsg = "Can't import traceback";
283         modTB = PyImport_ImportModule("traceback");
284         if (!modTB)
285                 goto out;
286
287         /* Construct a cStringIO object */
288         errorMsg = "Can't find io.StringIO";
289         obFuncStringIO = PyObject_GetAttrString(modIO, "StringIO");
290         if (!obFuncStringIO)
291                 goto out;
292         errorMsg = "io.StringIO() failed";
293         obIO = PyObject_CallObject(obFuncStringIO, NULL);
294         if (!obIO)
295                 goto out;
296
297         /* Get the traceback.print_exception function, and call it. */
298         errorMsg = "Can't find traceback.print_exception";
299         obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
300         if (!obFuncTB)
301                 goto out;
302         errorMsg = "can't make print_exception arguments";
303         argsTB = Py_BuildValue("OOOOO",
304                                exc_typ ? exc_typ : Py_None,
305                                exc_val ? exc_val : Py_None,
306                                exc_tb  ? exc_tb  : Py_None,
307                                Py_None,
308                                obIO);
309         if (!argsTB)
310                 goto out;
311
312         errorMsg = "traceback.print_exception() failed";
313         obResult = PyObject_CallObject(obFuncTB, argsTB);
314         if (!obResult) {
315                 PyErr_Print();
316                 goto out;
317         }
318
319         /* Now call the getvalue() method in the StringIO instance */
320         Py_DECREF(obFuncStringIO);
321         errorMsg = "cant find getvalue function";
322         obFuncStringIO = PyObject_GetAttrString(obIO, "getvalue");
323         if (!obFuncStringIO)
324                 goto out;
325         Py_XDECREF(obResult);
326         errorMsg = "getvalue() failed.";
327         obResult = PyObject_CallObject(obFuncStringIO, NULL);
328         if (!obResult)
329                 goto out;
330
331         /* And it should be a string all ready to go - report it. */
332         errorMsg = python_as_string(obResult, &tofree);;
333         LOG("Python error:\n%s", errorMsg);
334         if (errorMsg &&
335             (!ed_pane ||
336              call("editor:notify:Message:broadcast",ed_pane, 0, NULL,
337                   "Python Error - see log") <= 0))
338                 /* Failed to alert anyone - write to stderr */
339                 fwrite(errorMsg, 1, strlen(errorMsg), stderr);
340         Py_XDECREF(tofree);
341         errorMsg = NULL;
342 out:
343         if (errorMsg)
344                 LOG(errorMsg);
345         Py_XDECREF(modIO);
346         Py_XDECREF(modTB);
347         Py_XDECREF(obFuncStringIO);
348         Py_XDECREF(obIO);
349         Py_XDECREF(obFuncTB);
350         Py_XDECREF(argsTB);
351         Py_XDECREF(obResult);
352
353         Py_XDECREF(exc_typ);
354         Py_XDECREF(exc_val);
355         Py_XDECREF(exc_tb);
356 }
357
358 DEF_CMD(python_load_module)
359 {
360         const char *name = ci->str;
361         int fd;
362         long long size;
363         char *code;
364         char buf[PATH_MAX];
365         char buf2[PATH_MAX];
366         PyObject *builtins, *compile, *args, *bytecode;
367
368         if (!name)
369                 return Enoarg;
370         snprintf(buf, sizeof(buf), "%s/python/%s.py", module_dir, name);
371         fd = open(buf, O_RDONLY);
372         if (fd < 0)
373                 return Efail;
374         size = lseek(fd, 0, SEEK_END);
375         lseek(fd, 0, SEEK_SET);
376         code = malloc(size+1);
377         if (!code) {
378                 close(fd);
379                 return Efail;
380         }
381         size = read(fd, code, size);
382         close(fd);
383         if (size <= 0) {
384                 free(code);
385                 return Efail;
386         }
387         code[size] = 0;
388
389         LOG("Loading python module %s from %s", name, buf);
390
391         builtins = PyEval_GetBuiltins();
392         compile = PyDict_GetItemString(builtins, "compile");
393         args = safe_cast Py_BuildValue("(sss)", code, buf, "exec");
394         bytecode = PyObject_Call(compile, args, NULL);
395         Py_DECREF(args);
396         free(code);
397         if (bytecode == NULL) {
398                 PyErr_LOG();
399                 return Efail;
400         }
401
402         snprintf(buf2, sizeof(buf2), "edlib.%s", name);
403
404         if (PyImport_ExecCodeModule(buf2, bytecode) == NULL)
405                 PyErr_LOG();
406         Py_DECREF(bytecode);
407         return 1;
408 }
409
410 static PyObject *safe python_string(const char *s safe, int len)
411 {
412         const char *c = s;
413         const char *e = NULL;
414         wint_t wch;
415
416         if (len >= 0)
417                 e = s + len;
418         while ((!e || c < e) && *c && !(*c & 0x80))
419                 c++;
420         while ((wch = get_utf8(&c, e)) != WEOF)
421                 if (wch == WERR || wch > 0x10FFFF)
422                         break;
423
424         return safe_cast PyUnicode_DecodeUTF8(s, c - s, NULL);
425 }
426
427 static char *python_as_string(PyObject *s, PyObject **tofree safe)
428 {
429         if (s && PyUnicode_Check(s)) {
430                 s = PyUnicode_AsUTF8String(s);
431                 *tofree = s;
432         }
433         if (s && PyBytes_Check(s)) {
434                 char *ret = PyBytes_AsString(s);
435                 unsigned char *r = (unsigned char*)ret;
436                 if (r && r[0] == 0xef && r[1] == 0xbb && r[2] == 0xbf)
437                         /* UTF-8 Byte Order Mark */
438                         return ret+3;
439                 else
440                         return ret;
441         }
442         return NULL;
443 }
444
445 static int dict_add(PyObject *kwds, char *name, PyObject *val)
446 {
447         if (!val)
448                 return 0;
449         PyDict_SetItemString(kwds, name, val);
450         Py_DECREF(val);
451         return 1;
452 }
453
454 static void python_interrupt(int sig)
455 {
456         /* Python code has been running for too long,
457          * interrupt it.
458          */
459         kill(getpid(), 2);
460 }
461
462 REDEF_CB(python_call)
463 {
464         struct python_command *pc = container_of(ci->comm, struct python_command, c);
465         PyObject *ret = NULL, *args, *kwds, *str;
466         int rv = 1;
467         bool unterminated = False;
468         int klen = strlen(ci->key);
469
470         if (klen > 13 &&
471             strcmp(ci->key + klen - 13, " unterminated") == 0)
472                 unterminated = True;
473
474         args = safe_cast Py_BuildValue("(s)", ci->key);
475         kwds = PyDict_New();
476         rv = rv && dict_add(kwds, "home", Pane_Frompane(ci->home));
477         rv = rv && dict_add(kwds, "focus",
478                             Pane_Frompane(ci->focus));
479         rv = rv && dict_add(kwds, "mark",
480                             ci->mark ? Mark_Frommark(ci->mark):
481                             (Py_INCREF(Py_None), Py_None));
482         rv = rv && dict_add(kwds, "mark2",
483                             ci->mark2 ? Mark_Frommark(ci->mark2):
484                             (Py_INCREF(Py_None), Py_None));
485
486         if (ci->str)
487                 str = python_string(ci->str, unterminated ? ci->num2 : -1);
488         else {
489                 str = Py_None;
490                 Py_INCREF(Py_None);
491         }
492         if (str) {
493                 dict_add(kwds, "str", str);
494                 dict_add(kwds, "str1", str);
495                 Py_INCREF(str);
496         } else {
497                 rv = 0;
498         }
499
500         rv = rv && dict_add(kwds, "str2",
501                             ci->str2 ? python_string(ci->str2, -1):
502                             (Py_INCREF(Py_None), safe_cast Py_None));
503         rv = rv && dict_add(kwds, "comm", Comm_Fromcomm(ci->comm));
504         rv = rv && dict_add(kwds, "comm2",
505                             ci->comm2 ? Comm_Fromcomm(ci->comm2):
506                             (Py_INCREF(Py_None), Py_None));
507         rv = rv && dict_add(kwds, "num",
508                             Py_BuildValue("i", ci->num));
509         rv = rv && dict_add(kwds, "rpt_num",
510                             Py_BuildValue("i", RPT_NUM(ci)));
511         rv = rv && dict_add(kwds, "num2",
512                             Py_BuildValue("i", ci->num2));
513         rv = rv && dict_add(kwds, "xy",
514                             Py_BuildValue("ii", ci->x, ci->y));
515
516         if (rv && pc->callable) {
517                 signal(SIGALRM, python_interrupt);
518                 alarm(10);
519                 ret = PyObject_Call(pc->callable, args, kwds);
520                 alarm(0);
521                 signal(SIGALRM, SIG_DFL);
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);
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         int remain;
1174         sighandler_t oldhan;
1175
1176         if (!pane_valid(self))
1177                 return NULL;
1178
1179         ci.home = self->pane;
1180
1181         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1182             !handle_ret(kwds, &ci, &pr)) {
1183                 Py_XDECREF(s1); Py_XDECREF(s2);
1184                 command_put(ci.comm2);
1185                 return NULL;
1186         }
1187
1188         remain = alarm(0);
1189         oldhan = signal(SIGALRM, SIG_DFL);
1190         rv = key_handle(&ci);
1191         if (oldhan != SIG_DFL) {
1192                 signal(SIGALRM, oldhan);
1193                 alarm(remain);
1194         }
1195
1196         /* Just in case ... */
1197         PyErr_Clear();
1198
1199         Py_XDECREF(s1); Py_XDECREF(s2);
1200         command_put(ci.comm2);
1201
1202         return choose_ret(rv, &pr);
1203 }
1204
1205 static PyObject *pane_direct_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1206 {
1207         struct cmd_info ci = SAFE_CI;
1208         int rv;
1209         PyObject *s1, *s2;
1210         struct pyret pr;
1211
1212         if (!pane_valid(self))
1213                 return NULL;
1214
1215         ci.home = self->pane;
1216
1217         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1218             !handle_ret(kwds, &ci, &pr)) {
1219                 Py_XDECREF(s1); Py_XDECREF(s2);
1220                 command_put(ci.comm2);
1221                 return NULL;
1222         }
1223
1224         ci.comm = ci.home->handle;
1225         rv = ci.comm->func(&ci);
1226
1227         Py_XDECREF(s1); Py_XDECREF(s2);
1228         command_put(ci.comm2);
1229         return choose_ret(rv, &pr);
1230 }
1231
1232 static PyObject *Pane_notify(Pane *self safe, PyObject *args safe, PyObject *kwds)
1233 {
1234         struct cmd_info ci = SAFE_CI;
1235         int rv;
1236         PyObject *s1, *s2;
1237
1238         if (!pane_valid(self))
1239                 return NULL;
1240
1241         ci.home = self->pane;
1242
1243         if (!get_cmd_info(&ci, args, kwds, &s1, &s2)) {
1244                 Py_XDECREF(s1); Py_XDECREF(s2);
1245                 command_put(ci.comm2);
1246                 return NULL;
1247         }
1248
1249         rv = home_pane_notify(ci.home, ci.key, ci.focus, ci.num, ci.mark, ci.str,
1250                               ci.num2, ci.mark2, ci.str2,
1251                               ci.comm2);
1252
1253         Py_XDECREF(s1); Py_XDECREF(s2);
1254         command_put(ci.comm2);
1255         if (rv < Efalse) {
1256                 set_err(rv);
1257                 return NULL;
1258         }
1259         return PyLong_FromLong(rv);
1260 }
1261
1262 static PyObject *Pane_mapxy(Pane *self safe, PyObject *args)
1263 {
1264         short x,y;
1265         struct xy xy;
1266         Pane *other = NULL;
1267
1268         int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1269         if (ret <= 0 || !self->pane || !other || !other->pane)
1270                 return NULL;
1271
1272         xy = pane_mapxy(other->pane, self->pane, x, y, False);
1273         return Py_BuildValue("ii", xy.x, xy.y);
1274 }
1275
1276 static PyObject *Pane_clipxy(Pane *self safe, PyObject *args)
1277 {
1278         short x,y;
1279         struct xy xy;
1280         Pane *other = NULL;
1281
1282         int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1283         if (ret <= 0 || !self->pane || !other || !other->pane)
1284                 return NULL;
1285
1286         xy = pane_mapxy(other->pane, self->pane, x, y, True);
1287         return Py_BuildValue("ii", xy.x, xy.y);
1288 }
1289
1290 static PyObject *Pane_add_notify(Pane *self safe, PyObject *args)
1291 {
1292         Pane *other = NULL;
1293         char *event = NULL;
1294         int ret = PyArg_ParseTuple(args, "O!s", &PaneType, &other, &event);
1295         if (ret <= 0 || !other || !event)
1296                 return NULL;
1297         if (self->pane && other->pane)
1298                 pane_add_notify(self->pane, other->pane, event);
1299
1300         Py_INCREF(Py_None);
1301         return Py_None;
1302 }
1303
1304 static PyObject *Pane_drop_notify(Pane *self safe, PyObject *args)
1305 {
1306         char *event = NULL;
1307         int ret = PyArg_ParseTuple(args, "s", &event);
1308         if (ret <= 0 || !event)
1309                 return NULL;
1310         if (self->pane)
1311                 pane_drop_notifiers(self->pane, event);
1312
1313         Py_INCREF(Py_None);
1314         return Py_None;
1315 }
1316
1317 static PyObject *Pane_damaged(Pane *self safe, PyObject *args)
1318 {
1319         int damage = DAMAGED_REFRESH;
1320         int ret = PyArg_ParseTuple(args, "|i", &damage);
1321         if (ret <= 0)
1322                 return NULL;
1323         if (self->pane)
1324                 pane_damaged(self->pane, damage);
1325
1326         Py_INCREF(Py_None);
1327         return Py_None;
1328 }
1329
1330 static PyObject *Pane_close(Pane *self safe, PyObject *args)
1331 {
1332         struct pane *p = self->pane;
1333         if (p) {
1334                 pane_close(p);
1335                 self->pane = NULL;
1336         }
1337         Py_INCREF(Py_None);
1338         return Py_None;
1339 }
1340
1341 static PyObject *Pane_get_scale(Pane *self safe, PyObject *args)
1342 {
1343         struct pane *p = self->pane;
1344         struct xy xy = {1000, 1000};
1345
1346         if (p)
1347                 xy = pane_scale(p);
1348         return Py_BuildValue("ii", xy.x, xy.y);
1349 }
1350
1351 static PyObject *Pane_set_time(Pane *self safe, PyObject *args)
1352 {
1353         struct pane *p = self->pane;
1354         if (p)
1355                 pane_set_time(p);
1356         Py_INCREF(Py_None);
1357         return Py_None;
1358 }
1359
1360 static PyObject *Pane_too_long(Pane *self safe, PyObject *args)
1361 {
1362         struct pane *p = self->pane;
1363
1364         if (!p || pane_too_long(p, 0)) {
1365                 Py_INCREF(Py_True);
1366                 return Py_True;
1367         } else {
1368                 Py_INCREF(Py_False);
1369                 return Py_False;
1370         }
1371 }
1372
1373 static PyObject *Pane_mychild(Pane *self safe, PyObject *args)
1374 {
1375         Pane *child = NULL;
1376         int ret = PyArg_ParseTuple(args, "O!", &PaneType, &child);
1377         if (ret <= 0 || !child)
1378                 return NULL;
1379         if (self->pane && child->pane) {
1380                 struct pane *p = pane_my_child(self->pane, child->pane);
1381                 if (p)
1382                         return Pane_Frompane(p);
1383         }
1384         Py_INCREF(Py_None);
1385         return Py_None;
1386 }
1387
1388 static PyObject *Pane_clip(Pane *self safe, PyObject *args)
1389 {
1390         Mark *start = NULL, *end = NULL;
1391         int view = -1;
1392         int tostart = 0;
1393         int ret = PyArg_ParseTuple(args, "iO!O!|i", &view, &MarkType, &start,
1394                                    &MarkType, &end, &tostart);
1395
1396         if (ret > 0 && start && end && self->pane &&
1397             start->mark && end->mark && view >= 0)
1398                 marks_clip(self->pane, start->mark, end->mark, view, self->pane,
1399                            !!tostart);
1400         Py_INCREF(Py_None);
1401         return Py_None;
1402 }
1403
1404 static PyObject *Pane_reparent(Pane *self safe, PyObject *args)
1405 {
1406         Pane *newparent = NULL;
1407         int ret = PyArg_ParseTuple(args, "O!", &PaneType, &newparent);
1408
1409         if (ret > 0 && newparent && self->pane && newparent->pane) {
1410                 pane_reparent(self->pane, newparent->pane);
1411                 if (self->pane->parent != newparent->pane) {
1412                         PyErr_SetString(PyExc_TypeError, "reparent failed");
1413                         return NULL;
1414                 }
1415         }
1416         Py_INCREF(Py_None);
1417         return Py_None;
1418 }
1419
1420 static PyObject *Pane_move_after(Pane *self safe, PyObject *args)
1421 {
1422         Pane *peer = NULL;
1423         int ret = PyArg_ParseTuple(args, "O", &peer);
1424
1425         if (ret > 0 && peer && self->pane) {
1426                 if ((PyObject*)peer == Py_None)
1427                         pane_move_after(self->pane, NULL);
1428                 else if (PyObject_TypeCheck(peer, &PaneType) && peer->pane)
1429                         pane_move_after(self->pane, peer->pane);
1430         }
1431         Py_INCREF(Py_None);
1432         return Py_None;
1433 }
1434
1435 static PyObject *Pane_step(Pane *self safe, PyObject *args, int dir, int move)
1436 {
1437         Mark *m = NULL;
1438         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &m);
1439         wint_t wch;
1440
1441         if (!pane_valid(self))
1442                 return NULL;
1443         if (ret <= 0 || !m || !mark_valid(m->mark)) {
1444                 PyErr_SetString(PyExc_TypeError, "Arg must be a mark");
1445                 return NULL;
1446         }
1447
1448         if (move)
1449                 wch = doc_move(self->pane, m->mark, dir);
1450         else
1451                 wch = doc_pending(self->pane, m->mark, dir);
1452         if (wch == WEOF) {
1453                 Py_INCREF(Py_None);
1454                 return Py_None;
1455         }
1456         return PyUnicode_FromFormat("%c", wch);
1457 }
1458
1459 static PyObject *Pane_step_next(Pane *self safe, PyObject *args)
1460 {
1461         return Pane_step(self, args, 1, 1);
1462 }
1463
1464 static PyObject *Pane_step_prev(Pane *self safe, PyObject *args)
1465 {
1466         return Pane_step(self, args, -1, 1);
1467 }
1468
1469 static PyObject *Pane_step_following(Pane *self safe, PyObject *args)
1470 {
1471         return Pane_step(self, args, 1, 0);
1472 }
1473
1474 static PyObject *Pane_step_prior(Pane *self safe, PyObject *args)
1475 {
1476         return Pane_step(self, args, -1, 0);
1477 }
1478
1479 static PyObject *Pane_get_vmarks(Pane *self safe, PyObject *args)
1480 {
1481         struct pyret pr;
1482         Pane *owner = NULL;
1483         int view = -1;
1484         int ret;
1485
1486         if (!pane_valid(self))
1487                 return NULL;
1488         ret = PyArg_ParseTuple(args, "i|O!", &view, &PaneType, &owner);
1489         if (ret <= 0 || view < 0 || (owner && !pane_valid(owner))) {
1490                 Py_INCREF(Py_None);
1491                 return Py_None;
1492         }
1493         memset(&pr, 0, sizeof(pr));
1494         pr.comm = take_2_marks;
1495         home_call_comm(self->pane, "doc:vmark-get",
1496                        owner ? owner->pane : self->pane,
1497                        &pr.comm, view);
1498         if (pr.ret)
1499                 return pr.ret;
1500         Py_INCREF(Py_None);
1501         return Py_None;
1502 }
1503
1504 static PyObject *Pane_vmark_at_or_before(Pane *self safe, PyObject *args)
1505 {
1506         Mark *m = NULL;
1507         Pane *owner = NULL;
1508         struct pyret pr;
1509         int view = -1;
1510         int ret;
1511
1512         if (!pane_valid(self))
1513                 return NULL;
1514         ret = PyArg_ParseTuple(args, "iO!|O!", &view, &MarkType, &m,
1515                                &PaneType, &owner);
1516         if (ret <= 0 || view < 0 || !m || !mark_valid(m->mark) ||
1517             (owner && !pane_valid(owner))) {
1518                 Py_INCREF(Py_None);
1519                 return Py_None;
1520         }
1521         memset(&pr, 0, sizeof(pr));
1522         pr.comm = take_mark;
1523         home_call_comm(self->pane, "doc:vmark-prev",
1524                        owner ? owner->pane : self->pane,
1525                        &pr.comm, view, m->mark);
1526         if (pr.ret)
1527                 return pr.ret;
1528         Py_INCREF(Py_None);
1529         return Py_None;
1530 }
1531
1532 static const PyMethodDef pane_methods[] = {
1533         {"close", (PyCFunction)Pane_close, METH_NOARGS,
1534          "close the pane"},
1535         {"children", (PyCFunction)pane_children, METH_NOARGS,
1536          "provides an iterator which will iterate over all children"},
1537         {"clone_children", (PyCFunction)Pane_clone_children, METH_VARARGS,
1538          "Clone all children onto the target"},
1539         {"take_focus", (PyCFunction)Pane_take_focus, METH_NOARGS,
1540          "Claim the focus for this pane"},
1541         {"has_focus", (PyCFunction)Pane_has_focus, METH_VARARGS,
1542          "Check if pane is focus of display"},
1543         {"call", (void*)(PyCFunctionWithKeywords)Pane_call, METH_VARARGS|METH_KEYWORDS,
1544          "Call a command from a pane"},
1545         {"notify", (void*)(PyCFunctionWithKeywords)Pane_notify, METH_VARARGS|METH_KEYWORDS,
1546          "Send a notification from a pane"},
1547         {"mapxy", (PyCFunction)Pane_mapxy, METH_VARARGS,
1548          "Convert pane-relative co-ords between panes"},
1549         {"clipxy", (PyCFunction)Pane_clipxy, METH_VARARGS,
1550          "Convert pane-relative co-ords between panes, clipping to all panes"},
1551         {"add_notify", (PyCFunction)Pane_add_notify, METH_VARARGS,
1552          "Add notifier for an event on some other pane"},
1553         {"drop_notify", (PyCFunction)Pane_drop_notify, METH_VARARGS,
1554          "Drop notification to this pane for an event"},
1555         {"damaged", (PyCFunction)Pane_damaged, METH_VARARGS,
1556          "Mark pane as damaged"},
1557         {"scale", (PyCFunction)Pane_get_scale, METH_NOARGS,
1558          "Get the x,y scale numbers for this pane"},
1559         {"mychild", (PyCFunction)Pane_mychild, METH_VARARGS,
1560          "Get ancestor of pane which is my child, or None"},
1561         {"clip", (PyCFunction)Pane_clip, METH_VARARGS,
1562          "clip all 'type' marks in the given range"},
1563         {"reparent", (PyCFunction)Pane_reparent, METH_VARARGS,
1564          "Give a pane a new parent"},
1565         {"move_after", (PyCFunction)Pane_move_after, METH_VARARGS,
1566          "Move a pane after another in order of children"},
1567         {"next", (PyCFunction)Pane_step_next, METH_VARARGS,
1568          "Move mark forward returning the character"},
1569         {"prev", (PyCFunction)Pane_step_prev, METH_VARARGS,
1570          "Move mark back returning the character"},
1571         {"following", (PyCFunction)Pane_step_following, METH_VARARGS,
1572          "returning the character after mark"},
1573         {"prior", (PyCFunction)Pane_step_prior, METH_VARARGS,
1574          "returning the character before mark"},
1575         {"vmarks", (PyCFunction)Pane_get_vmarks, METH_VARARGS,
1576          "return first and last vmark given view number"},
1577         {"vmark_at_or_before", (PyCFunction)Pane_vmark_at_or_before, METH_VARARGS,
1578          "return vmark at-or-before given mark"},
1579         {"set_time", (PyCFunction)Pane_set_time, METH_NOARGS,
1580          "Set start time for long running operation"},
1581         {"too_long", (PyCFunction)Pane_too_long, METH_NOARGS,
1582          "Check if command in pane has been running for too long"},
1583         {NULL}
1584 };
1585
1586 static PyObject *pane_getnum(Pane *p safe, char *which safe)
1587 {
1588         long n = 0;
1589
1590         if (!pane_valid(p))
1591                 return NULL;
1592
1593         switch(*which) {
1594         case 'x': n = p->pane->x; break;
1595         case 'y': n = p->pane->y; break;
1596         case 'w': n = p->pane->w > 0 ? p->pane->w : 1; break;
1597         case 'h': n = p->pane->h > 0 ? p->pane->h : 1; break;
1598         case 'X': n = p->pane->cx; break;
1599         case 'Y': n = p->pane->cy; break;
1600         case 'z': n = p->pane->z; break;
1601         case 'Z': n = p->pane->abs_z; break;
1602         }
1603         return PyLong_FromLong(n);
1604 }
1605
1606 static int pane_setnum(Pane *p safe, PyObject *v, char *which safe)
1607 {
1608         int x,y,w,h;
1609         long val;
1610
1611         if (!pane_valid(p))
1612                 return -1;
1613
1614         if (*which == 'z') {
1615                 PyErr_SetString(PyExc_TypeError, "z cannot be set");
1616                 return -1;
1617         }
1618         if (*which == 'Z') {
1619                 PyErr_SetString(PyExc_TypeError, "abs_z cannot be set");
1620                 return -1;
1621         }
1622         val = PyLong_AsLong(v);
1623         if (val == -1 && PyErr_Occurred())
1624                 return -1;
1625
1626         x = p->pane->x; y = p->pane->y;
1627         w = p->pane->w; h = p->pane->h;
1628         switch(*which) {
1629         case 'x': x = val; break;
1630         case 'y': y = val; break;
1631         case 'w': w = val; break;
1632         case 'h': h = val; break;
1633         case 'X': p->pane->cx = val; return 0;
1634         case 'Y': p->pane->cy = val; return 0;
1635         }
1636         pane_resize(p->pane, x, y, w, h);
1637         return 0;
1638 }
1639
1640 static Pane *pane_getpane(Pane *p safe, char *which safe)
1641 {
1642         struct pane *new = NULL;
1643         Pane *newpane;
1644
1645         if (!pane_valid(p))
1646                 return NULL;
1647
1648         if (*which == 'p')
1649                 new = p->pane->parent;
1650         if (*which == 'f')
1651                 new = p->pane->focus;
1652         if (*which == 'r')
1653                 new = pane_root(p->pane);
1654         if (*which == 'F')
1655                 new = pane_focus(p->pane);
1656         if (*which == 'L')
1657                 new = pane_leaf(p->pane);
1658         if (new == NULL) {
1659                 Py_INCREF(Py_None);
1660                 newpane = (Pane*)Py_None;
1661         } else
1662                 newpane = (Pane *)Pane_Frompane(new);
1663
1664         return newpane;
1665 }
1666
1667 static int pane_nosetpane(Pane *p, PyObject *v, void *which)
1668 {
1669         PyErr_SetString(PyExc_TypeError, "Cannot set panes");
1670         return -1;
1671 }
1672
1673 static PyObject *pane_repr(Pane *self safe)
1674 {
1675         char *s = NULL;
1676         PyObject *ret;
1677         if (!pane_valid(self))
1678                 asprintf(&s, "<edlib.Pane FREED!!! %p>", self);
1679         else
1680                 asprintf(&s, "<edlib.Pane %p-%s>", self->pane, self->pane->name);
1681         ret = Py_BuildValue("s", s);
1682         free(s);
1683         return ret;
1684 }
1685
1686 static PyObject *doc_repr(Doc *self safe)
1687 {
1688         char *s = NULL;
1689         PyObject *ret;
1690         if (!doc_valid(self))
1691                 asprintf(&s, "<edlib.Doc FREED!!! %p>", self);
1692         else
1693                 asprintf(&s, "<edlib.Doc %p-%s>", self->pane, self->pane->name);
1694         ret = Py_BuildValue("s", s);
1695         free(s);
1696         return ret;
1697 }
1698
1699 static long pane_hash(Pane *p safe)
1700 {
1701         return (long)p->pane;
1702 }
1703
1704 static PyObject *pane_cmp(Pane *p1 safe, Pane *p2 safe, int op)
1705 {
1706         Py_RETURN_RICHCOMPARE(p1->pane, p2->pane, op);
1707 }
1708
1709 static const PyGetSetDef pane_getseters[] = {
1710         {"x",
1711          (getter)pane_getnum, (setter)pane_setnum,
1712          "X offset in parent", "x" },
1713         {"y",
1714          (getter)pane_getnum, (setter)pane_setnum,
1715          "Y offset in parent", "y" },
1716         {"z",
1717          (getter)pane_getnum, (setter)pane_setnum,
1718          "Z offset in parent", "z" },
1719         {"w",
1720          (getter)pane_getnum, (setter)pane_setnum,
1721          "width of pane", "w" },
1722         {"h",
1723          (getter)pane_getnum, (setter)pane_setnum,
1724          "heigth of pane", "h" },
1725         {"cx",
1726          (getter)pane_getnum, (setter)pane_setnum,
1727          "Cursor X offset in pane", "X" },
1728         {"cy",
1729          (getter)pane_getnum, (setter)pane_setnum,
1730          "Cursor Y offset in pane", "Y" },
1731         {"abs_z",
1732          (getter)pane_getnum, (setter)pane_setnum,
1733          "global Z offset", "Z" },
1734         {"parent",
1735          (getter)pane_getpane, (setter)pane_nosetpane,
1736          "Parent pane", "p"},
1737         {"focus",
1738          (getter)pane_getpane, (setter)pane_nosetpane,
1739          "Focal child", "f"},
1740         {"root",
1741          (getter)pane_getpane, (setter)pane_nosetpane,
1742          "Root pane", "r"},
1743         {"final_focus",
1744          (getter)pane_getpane, (setter)pane_nosetpane,
1745          "Final focus pane", "F"},
1746         {"leaf",
1747          (getter)pane_getpane, (setter)pane_nosetpane,
1748          "Leaf pane", "L"},
1749         {NULL}  /* Sentinel */
1750 };
1751
1752 static PyObject *Pane_get_item(Pane *self safe, PyObject *key safe)
1753 {
1754         char *k, *v;
1755         PyObject *t1 = NULL;
1756
1757         if (!pane_valid(self))
1758                 return NULL;
1759
1760         k = python_as_string(key, &t1);
1761         if (!k) {
1762                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1763                 return NULL;
1764         }
1765         v = pane_attr_get(self->pane, k);
1766         Py_XDECREF(t1);
1767         if (v)
1768                 return Py_BuildValue("s", v);
1769         Py_INCREF(Py_None);
1770         return Py_None;
1771 }
1772
1773 static int Pane_set_item(Pane *self safe, PyObject *key, PyObject *val)
1774 {
1775         char *k, *v;
1776         PyObject *t1 = NULL, *t2 = NULL;
1777
1778         if (!pane_valid(self))
1779                 return -1;
1780
1781         k = python_as_string(key, &t1);
1782         if (!k) {
1783                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1784                 return -1;
1785         }
1786         v = python_as_string(val, &t2);
1787         if (val != Py_None && !v) {
1788                 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
1789                 Py_XDECREF(t1);
1790                 return -1;
1791         }
1792         attr_set_str(&self->pane->attrs, k, v);
1793         Py_XDECREF(t1);
1794         Py_XDECREF(t2);
1795         return 0;
1796 }
1797
1798 static const PyMappingMethods pane_mapping = {
1799         .mp_length = NULL,
1800         .mp_subscript = (binaryfunc)Pane_get_item,
1801         .mp_ass_subscript = (objobjargproc)Pane_set_item,
1802 };
1803
1804 static PyTypeObject PaneType = {
1805         PyVarObject_HEAD_INIT(NULL, 0)
1806         .tp_name        = "edlib.Pane",
1807         .tp_basicsize   = sizeof(Pane),
1808         .tp_dealloc     = (destructor)pane_dealloc,
1809         .tp_richcompare = (richcmpfunc)pane_cmp,
1810         .tp_repr        = (reprfunc)pane_repr,
1811         .tp_as_mapping  = (PyMappingMethods*)&pane_mapping,
1812         .tp_hash        = (hashfunc)pane_hash,
1813         .tp_call        = (ternaryfunc)pane_direct_call,
1814         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1815         .tp_doc         = "edlib panes",
1816         .tp_methods     = (PyMethodDef*)pane_methods,
1817         .tp_getset      = (PyGetSetDef*)pane_getseters,
1818         .tp_init        = (initproc)Pane_init,
1819         .tp_new         = (newfunc)pane_new,
1820 };
1821
1822 static PyTypeObject PaneIterType = {
1823         PyVarObject_HEAD_INIT(NULL, 0)
1824         .tp_name        = "edlib.PaneIter",
1825         .tp_basicsize   = sizeof(PaneIter),
1826         .tp_dealloc     = (destructor)paneiter_dealloc,
1827         .tp_flags       = Py_TPFLAGS_DEFAULT,
1828         .tp_doc         = "edlib pane iterator",
1829         .tp_iter        = (getiterfunc)pane_this_iter,
1830         .tp_iternext    = (iternextfunc)pane_iter_next,
1831         .tp_new         = (newfunc)pane_iter_new,
1832 };
1833
1834 static PyObject *first_mark(Doc *self safe, PyObject *args)
1835 {
1836         struct mark *m;
1837
1838         if (!doc_valid(self))
1839                 return NULL;
1840
1841         m = mark_first(&self->pane->doc_data->doc);
1842         if (!m) {
1843                 Py_INCREF(Py_None);
1844                 return Py_None;
1845         }
1846         return Mark_Frommark(m);
1847 }
1848
1849 static PyObject *to_end(Doc *self safe, PyObject *args)
1850 {
1851         Mark *mark = NULL;
1852         int end = 0;
1853         int ret;
1854
1855         if (!doc_valid(self))
1856                 return NULL;
1857
1858         ret = PyArg_ParseTuple(args, "O!p", &MarkType, &mark, &end);
1859         if (ret <= 0 || !mark || !mark_valid(mark->mark)) {
1860                 PyErr_SetString(PyExc_TypeError, "Mark undefined or uninitialized");
1861                 return NULL;
1862         }
1863
1864         mark_to_end(self->pane, mark->mark, end);
1865         Py_INCREF(Py_None);
1866         return Py_None;
1867 }
1868
1869 static const PyMethodDef doc_methods[] = {
1870         {"first_mark", (PyCFunction)first_mark, METH_NOARGS,
1871          "first mark of document"},
1872         {"to_end", (PyCFunction)to_end, METH_VARARGS,
1873          "Move mark to one end of document"},
1874         {NULL}
1875 };
1876
1877 static PyTypeObject DocType = {
1878         PyVarObject_HEAD_INIT(NULL, 0)
1879         .tp_name        = "edlib.Doc",
1880         .tp_basicsize   = sizeof(Doc),
1881         .tp_dealloc     = (destructor)pane_dealloc,
1882         .tp_repr        = (reprfunc)doc_repr,
1883         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1884         .tp_doc         = "edlib document",
1885         .tp_methods     = (PyMethodDef*)doc_methods,
1886         .tp_base        = &PaneType,
1887         .tp_init        = (initproc)Doc_init,
1888         .tp_new         = (newfunc)Doc_new,
1889 };
1890
1891 static PyObject *mark_getoffset(Mark *m safe, void *x)
1892 {
1893         struct doc *d;
1894         if (!mark_valid(m->mark)) {
1895                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1896                 return NULL;
1897         }
1898         d = &m->mark->owner->doc;
1899         if (d->refcnt == mark_refcnt)
1900                 return PyLong_FromLong(m->mark->ref.o);
1901         return PyLong_FromLong(0);
1902 }
1903
1904 static int mark_setoffset(Mark *m safe, PyObject *v safe, void *x)
1905 {
1906         struct doc *d;
1907         long val;
1908
1909         if (!mark_valid(m->mark)) {
1910                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1911                 return -1;
1912         }
1913         val = PyLong_AsLong(v);
1914         if (val == -1 && PyErr_Occurred())
1915                 return -1;
1916         d = &m->mark->owner->doc;
1917         if (d->refcnt == mark_refcnt)
1918                 m->mark->ref.o = val;
1919         else {
1920                 PyErr_SetString(PyExc_TypeError, "Setting offset on non-local mark");
1921                 return -1;
1922         }
1923         return 0;
1924 }
1925
1926 static PyObject *mark_getseq(Mark *m safe, void *x)
1927 {
1928         if (!mark_valid(m->mark)) {
1929                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1930                 return NULL;
1931         }
1932         return PyLong_FromLong(m->mark->seq);
1933 }
1934
1935 static int mark_nosetseq(Mark *m, PyObject *v, void *which)
1936 {
1937         PyErr_SetString(PyExc_TypeError, "Cannot set mark seq number");
1938         return -1;
1939 }
1940
1941 static void mark_refcnt(struct mark *m safe, int inc)
1942 {
1943         if (!m->ref.c)
1944                 return;
1945         while (inc > 0) {
1946                 Py_INCREF(m->ref.c);
1947                 inc -= 1;
1948         }
1949         while (inc < 0) {
1950                 Py_DECREF(m->ref.c);
1951                 inc += 1;
1952         }
1953 }
1954
1955 static PyObject *mark_getpos(Mark *m safe, void *x)
1956 {
1957         struct doc *d;
1958         if (!mark_valid(m->mark)) {
1959                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1960                 return NULL;
1961         }
1962         d = &m->mark->owner->doc;
1963         if (d->refcnt == mark_refcnt && m->mark->ref.c) {
1964                 Py_INCREF(m->mark->ref.c);
1965                 return m->mark->ref.c;
1966         } else {
1967                 Py_INCREF(Py_None);
1968                 return Py_None;
1969         }
1970 }
1971
1972 static int mark_setpos(Mark *m safe, PyObject *v, void *x)
1973 {
1974         struct mark *m2;
1975         struct doc *d;
1976
1977         if (!mark_valid(m->mark)) {
1978                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1979                 return -1;
1980         }
1981         d = &m->mark->owner->doc;
1982         if (d->refcnt != mark_refcnt) {
1983                 PyErr_SetString(PyExc_TypeError, "Cannot set ref for non-local mark");
1984                 return -1;
1985         }
1986         d->refcnt(m->mark, -1);
1987         if (v == Py_None)
1988                 v = NULL;
1989         /* If an adjacent mark has a ref.c with a matching value
1990          * use that instead, so that mark_same() works.
1991          */
1992         if ((m2 = mark_next(m->mark)) != NULL &&
1993             m2->owner->doc.refcnt == mark_refcnt &&
1994             m2->ref.c != NULL && v != NULL &&
1995             PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1996                 m->mark->ref.c = m2->ref.c;
1997         else if ((m2 = mark_prev(m->mark)) != NULL &&
1998                  m2->owner->doc.refcnt == mark_refcnt &&
1999                  m2->ref.c != NULL && v != NULL &&
2000                  PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
2001                 m->mark->ref.c = m2->ref.c;
2002         else
2003                 m->mark->ref.c = v;
2004         d->refcnt(m->mark, 1);
2005         return 0;
2006 }
2007
2008 static PyObject *mark_getview(Mark *m safe, void *x)
2009 {
2010         if (!mark_valid(m->mark)) {
2011                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2012                 return NULL;
2013         }
2014         return PyLong_FromLong(m->mark->viewnum);
2015 }
2016
2017 static int mark_nosetview(Mark *m, PyObject *v, void *which)
2018 {
2019         PyErr_SetString(PyExc_TypeError, "Cannot set mark viewnum");
2020         return -1;
2021 }
2022
2023 static PyObject *mark_compare(Mark *a safe, Mark *b safe, int op)
2024 {
2025         if ((PyObject*)a == Py_None)
2026                 Py_RETURN_RICHCOMPARE(0, 1, op);
2027         else if ((PyObject*)b == Py_None)
2028                 Py_RETURN_RICHCOMPARE(1, 0, op);
2029         else if (PyObject_TypeCheck(a, &MarkType) == 0 ||
2030                  PyObject_TypeCheck(b, &MarkType) == 0) {
2031                 PyErr_SetString(PyExc_TypeError, "Mark compared with non-Mark");
2032                 return NULL;
2033         } else if (!mark_valid(a->mark) || !mark_valid(b->mark))
2034                 return NULL;
2035         else {
2036                 int cmp = a->mark->seq - b->mark->seq;
2037                 if (mark_same(a->mark, b->mark))
2038                         cmp = 0;
2039                 Py_RETURN_RICHCOMPARE(cmp, 0, op);
2040         }
2041 }
2042
2043 static const PyGetSetDef mark_getseters[] = {
2044         {"pos",
2045          (getter)mark_getpos, (setter)mark_setpos,
2046          "Position ref", NULL},
2047         {"offset",
2048          (getter)mark_getoffset, (setter)mark_setoffset,
2049          "Position offset", NULL},
2050         {"viewnum",
2051          (getter)mark_getview, (setter)mark_nosetview,
2052          "Index for view list", NULL},
2053         {"seq",
2054          (getter)mark_getseq, (setter)mark_nosetseq,
2055          "Sequence number of mark", NULL},
2056         {NULL}  /* Sentinel */
2057 };
2058
2059 static Mark *Mark_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
2060 {
2061         Mark *self;
2062
2063         self = (Mark *)type->tp_alloc(type, 0);
2064         if (self) {
2065                 self->mark = NULL;
2066         }
2067         return self;
2068 }
2069
2070 static int Mark_init(Mark *self safe, PyObject *args safe, PyObject *kwds)
2071 {
2072         Pane *doc = NULL;
2073         Pane *owner = NULL;
2074         int view = MARK_UNGROUPED;
2075         Mark *orig = NULL;
2076         static const char *keywords[] = {"pane","view","orig", "owner", NULL};
2077         int ret;
2078
2079         if (!PyTuple_Check(args) ||
2080             (PyTuple_GET_SIZE(args) == 0 && kwds == NULL))
2081                 /* Internal Mark_Frommark call */
2082                 return 1;
2083
2084         ret = PyArg_ParseTupleAndKeywords(args, kwds, "|O!iO!O!", (char**)keywords,
2085                                           &PaneType, &doc,
2086                                           &view,
2087                                           &MarkType, &orig,
2088                                           &PaneType, &owner);
2089         if (ret <= 0)
2090                 return -1;
2091         if (doc && orig) {
2092                 PyErr_SetString(PyExc_TypeError,
2093                                 "Only one of 'pane' and 'orig' may be set");
2094                 return -1;
2095         }
2096         if (!doc && !orig) {
2097                 PyErr_SetString(PyExc_TypeError,
2098                                 "At least one of 'pane' and 'orig' must be set");
2099                 return -1;
2100         }
2101         if (doc && doc->pane) {
2102                 struct pane *p = doc->pane;
2103                 struct pane *op = owner ? owner->pane : NULL;
2104                 if (!op)
2105                         op = p;
2106                 self->mark = vmark_new(p, view, op);
2107         } else if (orig && mark_valid(orig->mark)) {
2108                 self->mark = mark_dup_view(orig->mark);
2109         }
2110         if (!self->mark) {
2111                 PyErr_SetString(PyExc_TypeError, "Mark creation failed");
2112                 return -1;
2113         }
2114         if (self->mark->viewnum >= 0) {
2115                 /* vmarks can use mdata and don't disappear until
2116                  * explicitly released.
2117                  */
2118                 self->mark->mtype = &MarkType;
2119                 self->mark->mdata = self;
2120                 Py_INCREF(self);
2121         } else {
2122                 /* Other marks cannot use mdata and get freed when
2123                  * the original PyObject is destroyed
2124                  */
2125                 self->mark->mtype = (void*)self;
2126         }
2127         return 1;
2128 }
2129
2130 static void mark_dealloc(Mark *self safe)
2131 {
2132         if (mark_valid(self->mark) && self->mark->mtype == (void*)self) {
2133                 /* Python allocated this mark, so can free it. */
2134                 struct mark *m = self->mark;
2135                 self->mark = NULL;
2136                 m->mtype = NULL;
2137                 m->mdata = NULL;
2138                 mark_free(m);
2139         }
2140         do_free((PyObject*safe)self);
2141 }
2142
2143 static PyObject *Mark_to_mark(Mark *self safe, PyObject *args)
2144 {
2145         Mark *other = NULL;
2146         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2147         if (ret <= 0 || !other ||
2148             !mark_valid(self->mark) || !mark_valid(other->mark))
2149                 return NULL;
2150         mark_to_mark(self->mark, other->mark);
2151
2152         Py_INCREF(Py_None);
2153         return Py_None;
2154 }
2155
2156 static PyObject *Mark_to_mark_noref(Mark *self safe, PyObject *args)
2157 {
2158         Mark *other = NULL;
2159         int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2160         if (ret <= 0 || !other ||
2161             !mark_valid(self->mark) || !mark_valid(other->mark))
2162                 return NULL;
2163         mark_to_mark_noref(self->mark, other->mark);
2164
2165         Py_INCREF(Py_None);
2166         return Py_None;
2167 }
2168
2169 static PyObject *Mark_clip(Mark *self safe, PyObject *args)
2170 {
2171         Mark *start = NULL, *end = NULL;
2172         int tostart = 0;
2173         int ret = PyArg_ParseTuple(args, "O!O!|p", &MarkType, &start,
2174                                    &MarkType, &end, &tostart);
2175
2176         if (ret > 0 && start && end && mark_valid(self->mark) &&
2177             mark_valid(start->mark) && mark_valid(end->mark))
2178                 mark_clip(self->mark, start->mark, end->mark, tostart);
2179
2180         Py_INCREF(Py_None);
2181         return Py_None;
2182 }
2183
2184 static PyObject *Mark_step(Mark *self safe, PyObject *args)
2185 {
2186         /* Convenience function to help implement doc:char */
2187         int forward = 1;
2188         int ret = PyArg_ParseTuple(args, "i", &forward);
2189
2190         if (ret > 0 && self->mark)
2191                 mark_step(self->mark, forward);
2192
2193         Py_INCREF(Py_None);
2194         return Py_None;
2195 }
2196
2197 static PyObject *Mark_step_sharesref(Mark *self safe, PyObject *args)
2198 {
2199         /* Convenience function to help implement doc:char */
2200         int forward = 1;
2201         int ret = PyArg_ParseTuple(args, "i", &forward);
2202
2203         if (ret > 0 && self->mark)
2204                 mark_step_sharesref(self->mark, forward);
2205
2206         Py_INCREF(Py_None);
2207         return Py_None;
2208 }
2209
2210 static PyObject *Mark_next(Mark *self safe, PyObject *args)
2211 {
2212         struct mark *next;
2213         if (!mark_valid(self->mark)) {
2214                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2215                 return NULL;
2216         }
2217         if (self->mark->viewnum >= 0)
2218                 next = vmark_next(self->mark);
2219         else
2220                 next = NULL;
2221         if (next)
2222                 return Mark_Frommark(next);
2223         Py_INCREF(Py_None);
2224         return Py_None;
2225 }
2226
2227 static PyObject *Mark_prev(Mark *self safe, PyObject *args)
2228 {
2229         struct mark *prev;
2230         if (!mark_valid(self->mark)) {
2231                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2232                 return NULL;
2233         }
2234         if (self->mark->viewnum >= 0)
2235                 prev = vmark_prev(self->mark);
2236         else
2237                 prev = NULL;
2238         if (prev)
2239                 return Mark_Frommark(prev);
2240         Py_INCREF(Py_None);
2241         return Py_None;
2242 }
2243
2244 static PyObject *Mark_next_any(Mark *self safe, PyObject *args)
2245 {
2246         struct mark *next;
2247         if (!mark_valid(self->mark)) {
2248                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2249                 return NULL;
2250         }
2251         next = mark_next(self->mark);
2252         if (next)
2253                 return Mark_Frommark(next);
2254         Py_INCREF(Py_None);
2255         return Py_None;
2256 }
2257
2258 static PyObject *Mark_prev_any(Mark *self safe, PyObject *args)
2259 {
2260         struct mark *prev;
2261         if (!mark_valid(self->mark)) {
2262                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2263                 return NULL;
2264         }
2265         prev = mark_prev(self->mark);
2266         if (prev)
2267                 return Mark_Frommark(prev);
2268         Py_INCREF(Py_None);
2269         return Py_None;
2270 }
2271
2272 static PyObject *Mark_dup(Mark *self safe, PyObject *args)
2273 {
2274         struct mark *new;
2275         if (!mark_valid(self->mark)) {
2276                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2277                 return NULL;
2278         }
2279         new = mark_dup(self->mark);
2280         if (new) {
2281                 Mark *ret = (Mark*)Mark_Frommark(new);
2282                 /* We want this mark to be freed when the Mark
2283                  * dies
2284                  */
2285                 new->mtype = (void*)ret;
2286                 return (PyObject*)ret;
2287         }
2288
2289         Py_INCREF(Py_None);
2290         return Py_None;
2291 }
2292
2293 static PyObject *Mark_release(Mark *self safe, PyObject *args)
2294 {
2295         struct mark *m = self->mark;
2296
2297         if (!mark_valid(m)) {
2298                 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2299                 return NULL;
2300         }
2301         if (m->viewnum == MARK_UNGROUPED || m->viewnum == MARK_POINT) {
2302                 PyErr_SetString(PyExc_TypeError,
2303                                 "Cannot release ungrouped marks or points");
2304                 return NULL;
2305         }
2306         if (m->mtype != &MarkType) {
2307                 PyErr_SetString(PyExc_TypeError,
2308                                 "Mark is not managed by python, and cannot be released");
2309                 return NULL;
2310         }
2311
2312         /* We are dropping this mark - there cannot be any other ref */
2313         ASSERT(m->mdata == self);
2314         self->mark = NULL;
2315         Py_DECREF(self);
2316         m->mdata = NULL;
2317         m->mtype = NULL;
2318         mark_free(m);
2319
2320         Py_INCREF(Py_None);
2321         return Py_None;
2322 }
2323
2324 static PyObject *Mark_watch(Mark *self safe, PyObject *args)
2325 {
2326         struct mark *m = self->mark;
2327
2328         if (!mark_valid(m)) {
2329                 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2330                 return NULL;
2331         }
2332         mark_watch(m);
2333         Py_INCREF(Py_None);
2334         return Py_None;
2335 }
2336
2337 static const PyMethodDef mark_methods[] = {
2338         {"to_mark", (PyCFunction)Mark_to_mark, METH_VARARGS,
2339          "Move one mark to another"},
2340         {"to_mark_noref", (PyCFunction)Mark_to_mark_noref, METH_VARARGS,
2341          "Move one mark to another but don't update ref"},
2342         {"next", (PyCFunction)Mark_next, METH_NOARGS,
2343          "next vmark"},
2344         {"prev", (PyCFunction)Mark_prev, METH_NOARGS,
2345          "previous vmark"},
2346         {"next_any", (PyCFunction)Mark_next_any, METH_NOARGS,
2347          "next any_mark"},
2348         {"prev_any", (PyCFunction)Mark_prev_any, METH_NOARGS,
2349          "previous any_mark"},
2350         {"dup", (PyCFunction)Mark_dup, METH_NOARGS,
2351          "duplicate a mark, as ungrouped"},
2352         {"clip", (PyCFunction)Mark_clip, METH_VARARGS,
2353          "If this mark is in range, move to end"},
2354         {"release", (PyCFunction)Mark_release, METH_NOARGS,
2355          "release a vmark so it can disappear"},
2356         {"watch", (PyCFunction)Mark_watch, METH_NOARGS,
2357          "acknowledge movement of a point - allow further notifications"},
2358         {"step", (PyCFunction)Mark_step, METH_VARARGS,
2359          "Move mark over any adjacent marks with same reference"},
2360         {"step_sharesref", (PyCFunction)Mark_step_sharesref, METH_VARARGS,
2361          "Move mark over any adjacent marks with same reference"},
2362         {NULL}
2363 };
2364
2365 static PyObject *mark_get_item(Mark *self safe, PyObject *key safe)
2366 {
2367         char *k, *v;
2368         PyObject *t1 = NULL;
2369
2370         if (!mark_valid(self->mark)) {
2371                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2372                 return NULL;
2373         }
2374         k = python_as_string(key, &t1);
2375         if (!k) {
2376                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2377                 return NULL;
2378         }
2379         v = attr_find(self->mark->attrs, k);
2380         Py_XDECREF(t1);
2381         if (v)
2382                 return Py_BuildValue("s", v);
2383         Py_INCREF(Py_None);
2384         return Py_None;
2385 }
2386
2387 static int mark_set_item(Mark *self safe, PyObject *key safe, PyObject *val safe)
2388 {
2389         char *k, *v;
2390         PyObject *t1 = NULL, *t2 = NULL;
2391         if (!mark_valid(self->mark)) {
2392                 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2393                 return -1;
2394         }
2395         k = python_as_string(key, &t1);
2396         if (!k) {
2397                 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2398                 return -1;
2399         }
2400         v = python_as_string(val, &t2);
2401         if (val != Py_None && !v) {
2402                 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
2403                 Py_XDECREF(t1);
2404                 return -1;
2405         }
2406         attr_set_str(&self->mark->attrs, k, v);
2407         Py_XDECREF(t1);
2408         Py_XDECREF(t2);
2409         return 0;
2410 }
2411
2412 static PyObject *mark_repr(Mark *self safe)
2413 {
2414         char *s = NULL, *dm;
2415         PyObject *ret;
2416
2417         if (!self->mark)
2418                 asprintf(&s, "<edlib.Mark NULL %p>", self);
2419         else if (!mark_valid(self->mark))
2420                 asprintf(&s, "<edlib.Mark FREED %p>", self);
2421         else if ((dm = call_ret(str, "doc:debug:mark", self->mark->owner,
2422                                 0, self->mark))
2423                  != NULL)
2424                 asprintf(&s, "<edlib.Mark seq=%d v=%d %s>",
2425                          self->mark->seq, self->mark->viewnum, dm);
2426         else
2427                 asprintf(&s, "<edlib.Mark seq=%d v=%d i=%d %p>",
2428                          self->mark->seq, self->mark->viewnum,
2429                          self->mark->ref.o, self->mark);
2430
2431         ret = Py_BuildValue("s", s);
2432         free(s);
2433         return ret;
2434 }
2435
2436 static const PyMappingMethods mark_mapping = {
2437         .mp_length = NULL,
2438         .mp_subscript = (binaryfunc)mark_get_item,
2439         .mp_ass_subscript = (objobjargproc)mark_set_item,
2440 };
2441
2442 static int mark_bool(Mark *self safe)
2443 {
2444         return mark_valid(self->mark);
2445 }
2446
2447 static const PyNumberMethods mark_as_num = {
2448         .nb_bool        = (inquiry) mark_bool,
2449 };
2450
2451 static PyTypeObject MarkType = {
2452         PyVarObject_HEAD_INIT(NULL, 0)
2453         .tp_name        = "edlib.Mark",
2454         .tp_basicsize   = sizeof(Mark),
2455         .tp_dealloc     = (destructor)mark_dealloc,
2456         .tp_as_mapping  = (PyMappingMethods*)&mark_mapping,
2457         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2458         .tp_doc         = "edlib marks",
2459         .tp_richcompare = (richcmpfunc)mark_compare,
2460         .tp_methods     = (PyMethodDef*)mark_methods,
2461         .tp_getset      = (PyGetSetDef*)mark_getseters,
2462         .tp_init        = (initproc)Mark_init,
2463         .tp_new         = (newfunc)Mark_new,
2464         .tp_repr        = (reprfunc)mark_repr,
2465         .tp_as_number   = (PyNumberMethods*)&mark_as_num,
2466 };
2467
2468 static void comm_dealloc(Comm *self safe)
2469 {
2470         command_put(self->comm);
2471         do_free((PyObject*safe)self);
2472 }
2473
2474 static PyObject *comm_repr(Comm *self safe)
2475 {
2476         char *s = NULL;
2477         PyObject *ret;
2478
2479         if (self->comm)
2480                 asprintf(&s, "<edlib.Comm refcnt=%d %p>",
2481                          self->comm->refcnt, self->comm);
2482         else
2483                 asprintf(&s, "<edlib.Comm NULL %p>", self);
2484         ret = Py_BuildValue("s", s);
2485         free(s);
2486         return ret;
2487 }
2488
2489 static PyObject *Comm_call(Comm *c safe, PyObject *args safe, PyObject *kwds)
2490 {
2491         struct cmd_info ci = SAFE_CI;
2492         int rv;
2493         PyObject *s1, *s2;
2494         struct pyret pr;
2495
2496         if (!c->comm)
2497                 return NULL;
2498         if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
2499             !handle_ret(kwds, &ci, &pr)) {
2500                 Py_XDECREF(s1); Py_XDECREF(s2);
2501                 command_put(ci.comm2);
2502                 return NULL;
2503         }
2504         ci.comm = c->comm;
2505         rv = c->comm->func(&ci);
2506         Py_XDECREF(s1); Py_XDECREF(s2);
2507         command_put(ci.comm2);
2508
2509         return choose_ret(rv, &pr);
2510 }
2511
2512 static PyObject *comm_cmp(Comm *c1 safe, Comm *c2 safe, int op)
2513 {
2514         Py_RETURN_RICHCOMPARE(c1->comm, c2->comm, op);
2515 }
2516
2517 static Comm *comm_new(PyTypeObject *type safe, PyObject *args safe, PyObject *kwds)
2518 {
2519         Comm *self;
2520
2521         self = (Comm *)type->tp_alloc(type, 0);
2522         if (self)
2523                 self->comm = NULL;
2524         return self;
2525 }
2526
2527 static PyTypeObject CommType = {
2528         PyVarObject_HEAD_INIT(NULL, 0)
2529         .tp_name        = "edlib.Comm",
2530         .tp_basicsize   = sizeof(Comm),
2531         .tp_dealloc     = (destructor)comm_dealloc,
2532         .tp_richcompare = (richcmpfunc)comm_cmp,
2533         .tp_repr        = (reprfunc)comm_repr,
2534         .tp_call        = (ternaryfunc)Comm_call,
2535         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2536         .tp_doc         = "edlib command",
2537         .tp_new         = (newfunc)comm_new,
2538 };
2539
2540 static void python_free_command(struct command *c safe)
2541 {
2542         struct python_command *pc = container_of(c, struct python_command, c);
2543
2544         if (pc->callable)
2545                 Py_DECREF(pc->callable);
2546         list_del(&pc->lst);
2547         free(pc);
2548 }
2549
2550 /* The 'call' function takes liberties with arg passing.
2551  * Positional args must start with the key, and then are handled based on
2552  * there type.  They can be panes, strigns, ints, pairs, marks, commands.
2553  * Panes are assigned to focus, then home.
2554  * Strings (after the key) are assigned to 'str' then 'str2'.
2555
2556  * Ints are assigned to num then num2
2557  * Pairs (must be of ints) are assigned to x,y then hx,hy.
2558  * Marks are assigned to mark then mark2
2559  * A command is assigned to comm2 (comm is set automatically)
2560  * kwd arguments can also be used, currently
2561  * key, home, focus, xy, hxy, str, str2, mark, mark2, comm2.
2562  * A 'None' arg is ignored - probably a mark or string or something. Just use NULL
2563  */
2564 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
2565                          PyObject **s1 safe, PyObject **s2 safe)
2566 {
2567         int argc;
2568         PyObject *a;
2569         int i;
2570         int num_set = 0, num2_set = 0;
2571         int xy_set = 0;
2572
2573         *s1 = *s2 = NULL;
2574
2575         if (!PyTuple_Check(args))
2576                 return False;
2577         argc = PyTuple_GET_SIZE(args);
2578         if (argc >= 1) {
2579                 /* First positional arg must be the key */
2580                 a = PyTuple_GetItem(args, 0);
2581                 if (!PyUnicode_Check(a)) {
2582                         PyErr_SetString(PyExc_TypeError, "First arg must be key");
2583                         return False;
2584                 }
2585                 ci->key = safe_cast PyUnicode_AsUTF8(a);
2586         }
2587         for (i = 1; i < argc; i++) {
2588                 a = PyTuple_GetItem(args, i);
2589                 if (!a || a == Py_None)
2590                         /* quietly ignore */;
2591                 else if (PyObject_TypeCheck(a, &PaneType)) {
2592                         if ((void*)ci->home == NULL)
2593                                 ci->home = safe_cast ((Pane*)a)->pane;
2594                         else if ((void*)ci->focus == NULL)
2595                                 ci->focus = safe_cast ((Pane*)a)->pane;
2596                         else {
2597                                 PyErr_SetString(PyExc_TypeError, "Only 2 Pane args permitted");
2598                                 return False;
2599                         }
2600                 } else if (PyObject_TypeCheck(a, &MarkType)) {
2601                         if (ci->mark == NULL)
2602                                 ci->mark = ((Mark*)a)->mark;
2603                         else if (ci->mark2 == NULL)
2604                                 ci->mark2 = ((Mark*)a)->mark;
2605                         else {
2606                                 PyErr_SetString(PyExc_TypeError, "Only 2 Mark args permitted");
2607                                 return False;
2608                         }
2609                 } else if (PyUnicode_Check(a)) {
2610                         char *str;
2611                         PyObject *s = NULL;
2612                         if (ci->str && ci->str2) {
2613                                 PyErr_SetString(PyExc_TypeError, "Only 3 String args permitted");
2614                                 return False;
2615                         }
2616                         str = python_as_string(a, &s);
2617                         if (!str)
2618                                 return False;
2619                         if (s) {
2620                                 *s2 = *s1;
2621                                 *s1 = s;
2622                         }
2623                         if (ci->str == NULL)
2624                                 ci->str = str;
2625                         else
2626                                 ci->str2 = str;
2627                 } else if (PyLong_Check(a)) {
2628                         if (!num_set) {
2629                                 ci->num = PyLong_AsLong(a);
2630                                 num_set = 1;
2631                         } else if (!num2_set) {
2632                                 ci->num2 = PyLong_AsLong(a);
2633                                 num2_set = 1;
2634                         } else {
2635                                 PyErr_SetString(PyExc_TypeError, "Only 2 Number args permitted");
2636                                 return False;
2637                         }
2638                 } else if (PyTuple_Check(a)) {
2639                         int n = PyTuple_GET_SIZE(a);
2640                         PyObject *n1, *n2;
2641                         if (n != 2) {
2642                                 PyErr_SetString(PyExc_TypeError, "Only 2-element tuples permitted");
2643                                 return False;
2644                         }
2645                         n1 = PyTuple_GetItem(a, 0);
2646                         n2 = PyTuple_GetItem(a, 1);
2647                         if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2648                                 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2649                                 return False;
2650                         }
2651                         if (!xy_set) {
2652                                 ci->x = PyLong_AsLong(n1);
2653                                 ci->y = PyLong_AsLong(n2);
2654                                 xy_set = 1;
2655                         } else {
2656                                 PyErr_SetString(PyExc_TypeError, "Only one tuple permitted");
2657                                 return False;
2658                         }
2659                 } else if (PyObject_TypeCheck(a, &CommType)) {
2660                         Comm *c = (Comm*)a;
2661                         if (ci->comm2 == NULL && c->comm) {
2662                                 ci->comm2 = command_get(c->comm);
2663                         } else {
2664                                 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2665                                 return False;
2666                         }
2667                 } else if (PyCallable_Check(a)) {
2668                         struct python_command *pc = export_callable(a, NULL);
2669
2670                         if (ci->comm2 == NULL)
2671                                 ci->comm2 = &pc->c;
2672                         else {
2673                                 command_put(&pc->c);
2674                                 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2675                                 return False;
2676                         }
2677                 } else {
2678                         PyErr_Format(PyExc_TypeError, "Unsupported arg type %d", i);
2679                         return False;
2680                 }
2681         }
2682         if (kwds && PyDict_Check(kwds)) {
2683                 a = PyDict_GetItemString(kwds, "str1");
2684                 if (!a || a == Py_None)
2685                         a = PyDict_GetItemString(kwds, "str");
2686                 if (a && a != Py_None) {
2687                         if (*s1 || ci->str) {
2688                                 PyErr_SetString(PyExc_TypeError,
2689                                                 "'str' given with other strings");
2690                                 return False;
2691                         }
2692                         if (!PyUnicode_Check(a)) {
2693                                 PyErr_SetString(PyExc_TypeError,
2694                                                 "'str' must be string or unicode");
2695                                 return False;
2696                         }
2697                         ci->str = python_as_string(a, s1);
2698                 }
2699                 a = PyDict_GetItemString(kwds, "str2");
2700                 if (a && a != Py_None) {
2701                         if (*s2 || ci->str2) {
2702                                 PyErr_SetString(PyExc_TypeError,
2703                                                 "'str2' given with 2 strings");
2704                                 return False;
2705                         }
2706                         if (!PyUnicode_Check(a)) {
2707                                 PyErr_SetString(PyExc_TypeError,
2708                                                 "'str2' must be string or unicode");
2709                                 return False;
2710                         }
2711                         ci->str2 = python_as_string(a, s2);
2712                 }
2713                 a = PyDict_GetItemString(kwds, "mark");
2714                 if (a && a != Py_None) {
2715                         if (ci->mark) {
2716                                 PyErr_SetString(PyExc_TypeError,
2717                                                 "'mark' given with other marks");
2718                                 return False;
2719                         }
2720                         if (!PyObject_TypeCheck(a, &MarkType)) {
2721                                 PyErr_SetString(PyExc_TypeError,
2722                                                 "'mark' must be an edlib.Mark");
2723                                 return False;
2724                         }
2725                         ci->mark = ((Mark*)a)->mark;
2726                 }
2727                 a = PyDict_GetItemString(kwds, "mark2");
2728                 if (a && a != Py_None) {
2729                         if (ci->mark2) {
2730                                 PyErr_SetString(PyExc_TypeError,
2731                                                 "'mark2' given with 2 other marks");
2732                                 return False;
2733                         }
2734                         if (!PyObject_TypeCheck(a, &MarkType)) {
2735                                 PyErr_SetString(PyExc_TypeError,
2736                                                 "'mark2' must be an edlib.Mark");
2737                                 return False;
2738                         }
2739                         ci->mark2 = ((Mark*)a)->mark;
2740                 }
2741                 a = PyDict_GetItemString(kwds, "num");
2742                 if (a) {
2743                         if (num_set) {
2744                                 PyErr_SetString(PyExc_TypeError,
2745                                                 "'num' given with other numbers");
2746                                 return False;
2747                         }
2748                         if (!PyLong_Check(a)) {
2749                                 PyErr_SetString(PyExc_TypeError,
2750                                                 "'num' must be an integer");
2751                                 return False;
2752                         }
2753                         ci->num = PyLong_AsLong(a);
2754                         num_set = 1;
2755                 }
2756                 a = PyDict_GetItemString(kwds, "num2");
2757                 if (a) {
2758                         if (num2_set) {
2759                                 PyErr_SetString(PyExc_TypeError,
2760                                                 "'num2' given with 2 other numbers");
2761                                 return False;
2762                         }
2763                         if (!PyLong_Check(a)) {
2764                                 PyErr_SetString(PyExc_TypeError,
2765                                                 "'num2' must be an integer");
2766                                 return False;
2767                         }
2768                         ci->num2 = PyLong_AsLong(a);
2769                         num2_set = 1;
2770                 }
2771                 a = PyDict_GetItemString(kwds, "focus");
2772                 if (a && a != Py_None) {
2773                         Pane *p;
2774                         if ((void*)ci->focus) {
2775                                 PyErr_SetString(PyExc_TypeError,
2776                                                 "'focus' given with other pane");
2777                                 return False;
2778                         }
2779                         if (!PyObject_TypeCheck(a, &PaneType)) {
2780                                 PyErr_SetString(PyExc_TypeError,
2781                                                 "'focus' must be a pane");
2782                                 return False;
2783                         }
2784                         p = (Pane*)a;
2785                         if (p->pane)
2786                                 ci->focus = p->pane;
2787                         else {
2788                                 PyErr_SetString(PyExc_TypeError, "focus value invalid");
2789                                 return False;
2790                         }
2791                 }
2792                 a = PyDict_GetItemString(kwds, "xy");
2793                 if (a && a != Py_None) {
2794                         PyObject *n1, *n2;
2795                         if (xy_set) {
2796                                 PyErr_SetString(PyExc_TypeError,
2797                                                 "'xy' given with other tuple");
2798                                 return False;
2799                         }
2800                         if (!PyTuple_Check(a) || PyTuple_GET_SIZE(a) != 2) {
2801                                 PyErr_SetString(PyExc_TypeError,
2802                                                 "'xy' must be a tuple of 2 integers");
2803                                 return False;
2804                         }
2805                         n1 = PyTuple_GetItem(a, 0);
2806                         n2 = PyTuple_GetItem(a, 1);
2807                         if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2808                                 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2809                                 return False;
2810                         }
2811                         ci->x = PyLong_AsLong(n1);
2812                         ci->y = PyLong_AsLong(n2);
2813                         xy_set = 1;
2814                 }
2815                 a = PyDict_GetItemString(kwds, "comm2");
2816                 if (a && a != Py_None) {
2817                         if (ci->comm2) {
2818                                 PyErr_SetString(PyExc_TypeError,
2819                                                 "'comm2' given with other command");
2820                                 return False;
2821                         }
2822                         if (PyObject_TypeCheck(a, &CommType)) {
2823                                 Comm *c = (Comm*)a;
2824                                 if (c->comm)
2825                                         ci->comm2 = command_get(c->comm);
2826                                 else {
2827                                         PyErr_SetString(PyExc_TypeError, "comm2 value invalid");
2828                                         return False;
2829                                 }
2830                         } else if (PyCallable_Check(a)) {
2831                                 struct python_command *pc = export_callable(a, NULL);
2832
2833                                 ci->comm2 = &pc->c;
2834                         } else {
2835                                 PyErr_SetString(PyExc_TypeError,
2836                                                 "'comm2' must be a callable");
2837                                 return False;
2838                         }
2839                 }
2840         }
2841         if (!(void*)ci->key) {
2842                 PyErr_SetString(PyExc_TypeError, "No key specified");
2843                 return False;
2844         }
2845         if (!(void*)ci->home) {
2846                 PyErr_SetString(PyExc_TypeError, "No pane specified");
2847                 return False;
2848         }
2849         if (!(void*)ci->focus)
2850                 ci->focus = ci->home;
2851
2852         return True;
2853 }
2854
2855 static PyObject *py_time_start(PyObject *self, PyObject *args)
2856 {
2857         int type;
2858         int ret = PyArg_ParseTuple(args, "i", &type);
2859
2860         if (ret <= 0)
2861                 return NULL;
2862         time_start(type);
2863
2864         Py_INCREF(Py_None);
2865         return Py_None;
2866 }
2867
2868 static PyObject *py_time_stop(PyObject *self, PyObject *args)
2869 {
2870         int type;
2871         int ret = PyArg_ParseTuple(args, "i", &type);
2872
2873         if (ret <= 0)
2874                 return NULL;
2875         time_stop(type);
2876
2877         Py_INCREF(Py_None);
2878         return Py_None;
2879 }
2880
2881 static PyObject *py_LOG(PyObject *self, PyObject *args)
2882 {
2883         int argc = PySequence_Length(args);
2884         int i;
2885         char buf[1024];
2886         int l = 0;
2887
2888         for (i = 0; i < argc && l < (int)sizeof(buf) - 2; i++) {
2889                 PyObject *o = PySequence_GetItem(args, i);
2890                 PyObject *s, *tofree = NULL;
2891                 char *str;
2892                 unsigned int slen;
2893
2894                 if (!o)
2895                         continue;
2896                 s = PyObject_Str(o);
2897                 Py_DECREF(o);
2898                 if (!s)
2899                         continue;
2900                 str = python_as_string(s, &tofree);
2901                 slen = str ? strlen(str) : 0;
2902                 if (slen + l + 2 > sizeof(buf))
2903                         slen = sizeof(buf) - l - 2;
2904                 if (str) {
2905                         if (l)
2906                                 buf[l++] = ' ';
2907                         strncpy(buf+l, str, slen);
2908                         l += slen;
2909                 }
2910                 Py_XDECREF(tofree);
2911         }
2912         buf[l] = 0;
2913         if (l)
2914                 LOG("%s", buf);
2915
2916         Py_INCREF(Py_None);
2917         return Py_None;
2918 }
2919
2920 static PyObject *py_LOG_BT(PyObject *self, PyObject *args)
2921 {
2922         LOG_BT();
2923         Py_INCREF(Py_None);
2924         return Py_None;
2925 }
2926
2927 static const PyMethodDef edlib_methods[] = {
2928         {"time_start", py_time_start, METH_VARARGS,
2929          "Record start time"},
2930         {"time_stop", py_time_stop, METH_VARARGS,
2931          "Record stop time"},
2932         {"LOG", py_LOG, METH_VARARGS,
2933          "Generate log message"},
2934         {"LOG_BT", py_LOG_BT, METH_NOARGS,
2935          "Generate backtrace message"},
2936         {NULL, NULL, 0, NULL}
2937 };
2938
2939 /* This must be visible when the module is loaded so it
2940  * cannot be static.  sparse doesn't like variables that are
2941  * neither extern nor static.  So mark it extern
2942  */
2943 extern char *edlib_module_path;
2944 char *edlib_module_path;
2945
2946 void edlib_init(struct pane *ed safe)
2947 {
2948         PyObject *m;
2949         PyConfig config;
2950         char *argv[2]= { "edlib", NULL };
2951
2952         if (edlib_module_path)
2953                 module_dir = strdup(edlib_module_path);
2954         else
2955                 module_dir = ".";
2956
2957         PyConfig_InitPythonConfig(&config);
2958         config.isolated = 1;
2959         PyConfig_SetBytesArgv(&config, 0, argv);
2960         Py_InitializeFromConfig(&config);
2961         PyConfig_Clear(&config);
2962
2963         PaneType.tp_new = PyType_GenericNew;
2964         PaneIterType.tp_new = PyType_GenericNew;
2965         DocType.tp_new = PyType_GenericNew;
2966         MarkType.tp_new = PyType_GenericNew;
2967         CommType.tp_new = PyType_GenericNew;
2968         if (PyType_Ready(&PaneType) < 0 ||
2969             PyType_Ready(&PaneIterType) < 0 ||
2970             PyType_Ready(&DocType) < 0 ||
2971             PyType_Ready(&MarkType) < 0 ||
2972             PyType_Ready(&CommType) < 0)
2973                 return;
2974
2975         m = PyImport_AddModule("edlib");
2976         if (!m) {
2977                 PyErr_LOG();
2978                 return;
2979         }
2980
2981         PyModule_SetDocString(m , "edlib - one more editor is never enough");
2982
2983         PyModule_AddFunctions(m, (PyMethodDef*)edlib_methods);
2984         PyModule_AddObject(m, "editor", Pane_Frompane(ed));
2985         PyModule_AddObject(m, "Pane", (PyObject *)&PaneType);
2986         PyModule_AddObject(m, "PaneIter", (PyObject *)&PaneIterType);
2987         PyModule_AddObject(m, "Mark", (PyObject *)&MarkType);
2988         PyModule_AddObject(m, "Comm", (PyObject *)&CommType);
2989         PyModule_AddObject(m, "Doc", (PyObject *)&DocType);
2990         PyModule_AddIntMacro(m, DAMAGED_CHILD);
2991         PyModule_AddIntMacro(m, DAMAGED_SIZE);
2992         PyModule_AddIntMacro(m, DAMAGED_VIEW);
2993         PyModule_AddIntMacro(m, DAMAGED_REFRESH);
2994         PyModule_AddIntMacro(m, DAMAGED_POSTORDER);
2995         PyModule_AddIntMacro(m, DAMAGED_CLOSED);
2996         PyModule_AddIntMacro(m, Efallthrough);
2997         PyModule_AddIntMacro(m, Enoarg);
2998         PyModule_AddIntMacro(m, Einval);
2999         PyModule_AddIntMacro(m, Efalse);
3000         PyModule_AddIntMacro(m, Efail);
3001         PyModule_AddIntMacro(m, Enosup);
3002         PyModule_AddIntMacro(m, Efail);
3003         PyModule_AddIntMacro(m, NO_NUMERIC);
3004
3005         PyModule_AddIntMacro(m, TIME_KEY);
3006         PyModule_AddIntMacro(m, TIME_WINDOW);
3007         PyModule_AddIntMacro(m, TIME_READ);
3008         PyModule_AddIntMacro(m, TIME_SIG);
3009         PyModule_AddIntMacro(m, TIME_TIMER);
3010         PyModule_AddIntMacro(m, TIME_IDLE);
3011         PyModule_AddIntMacro(m, TIME_REFRESH);
3012         PyModule_AddIntMacro(m, TIME_MISC);
3013
3014         PyModule_AddIntMacro(m, RXLF_ANCHORED);
3015         PyModule_AddIntMacro(m, RXLF_BACKTRACK);
3016
3017         PyModule_AddIntMacro(m, MARK_UNGROUPED);
3018         PyModule_AddIntMacro(m, MARK_POINT);
3019
3020         PyModule_AddIntConstant(m, "WEOF", 0x3FFFFF);
3021
3022         PyModule_AddIntConstant(m, "testing", edlib_testing(ed));
3023
3024         Edlib_CommandFailed = PyErr_NewException("edlib.commandfailed", NULL, NULL);
3025         Py_INCREF(Edlib_CommandFailed);
3026         PyModule_AddObject(m, "commandfailed", Edlib_CommandFailed);
3027
3028         EdlibModule = m;
3029         ed_pane = ed;
3030
3031         call_comm("global-set-command", ed, &python_load_module,
3032                   0, NULL, "global-load-modules:python");
3033 }