2 * Copyright Neil Brown ©2015-2023 <neil@brown.name>
3 * May be distributed under terms of GPLv2 - see file:COPYING
5 * Python3 bindings for edlib.
6 * An edlib command "global-load-modules:python" will read and execute
8 * It must "import edlib" and it can use "edlib.editor" to get the editor
11 * Types available are:
12 * edlib.pane - a generic pane. These form a tree of which edlib.editor
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.
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.
37 /* Need to define stuff that pyconfig needs */
42 //#define PyType_HasFeature __PyType_HasFeature
44 #undef PyType_HasFeature __PyType_HasFeature
45 int PyType_HasFeature(PyTypeObject *type, unsigned long feature);
48 #define Py_INCREF(op) (0)
50 #define Py_DECREF(op) (0)
52 #define Py_XDECREF(op) (0)
54 #define Py_IS_TYPE(ob, type) (ob == (void*)type)
59 #define MARK_DATA_PTR struct Mark
60 #define PRIVATE_DOC_REF
70 #define DOC_DATA_TYPE struct python_doc
71 #define PANE_DATA_PTR_TYPE struct Pane *
82 #include "core-pane.h"
84 #define SAFE_CI {.key=safe_cast NULL,\
85 .home=safe_cast NULL,\
86 .focus=safe_cast NULL,\
87 .comm=safe_cast NULL,\
90 static PyObject *Edlib_CommandFailed;
91 static PyObject *EdlibModule;
93 static struct pane *ed_pane;
95 static char *module_dir;
96 static char *python_as_string(PyObject *s, PyObject **tofree safe);
98 /* Python commands visible to edlib are wrapped in
99 * the python_command. There is only one per callback,
100 * so that edlib code can compare for equalty.
102 struct python_command {
105 struct list_head lst;
107 static LIST_HEAD(exported_commands);
109 DEF_CMD(python_call);
110 DEF_CMD(python_pane_call);
111 DEF_CMD(python_doc_call);
112 static void python_free_command(struct command *c safe);
114 static struct python_command *export_callable(PyObject *callable safe,
117 struct python_command *c;
118 const char *name = NULL;
121 if (nm && PyUnicode_Check(nm))
122 name = PyUnicode_AsUTF8(nm);
127 list_for_each_entry(c, &exported_commands, lst)
128 if (c->callable == callable) {
133 c = malloc(sizeof(*c));
135 c->c.free = python_free_command;
137 if (strcmp(name, "handle_close") == 0 ||
139 strcmp(name+len-10, "_closed_ok") == 0))
145 c->callable = callable;
146 list_add(&c->lst, &exported_commands);
150 typedef struct Pane {
157 static PyTypeObject PaneType;
163 static PyTypeObject PaneIterType;
165 typedef struct pydoc {
172 static PyTypeObject DocType;
174 typedef struct Mark {
178 static PyTypeObject MarkType;
179 static void mark_refcnt(struct mark *m safe, int inc);
183 struct command *comm;
185 static PyTypeObject CommType;
187 static inline bool pane_valid(Pane *p safe)
189 if (p->pane && p->pane->handle)
191 PyErr_SetString(PyExc_TypeError, "Pane has been freed");
195 static inline bool doc_valid(Doc *p safe)
197 if (p->pane && p->pane->handle)
199 PyErr_SetString(PyExc_TypeError, "Doc pane has been freed");
203 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
204 PyObject **s1 safe, PyObject **s2 safe);
206 static int in_pane_frompane = 0;
207 static inline PyObject *safe Pane_Frompane(struct pane *p)
210 if (p && p->handle && p->handle->func == python_pane_call.func) {
213 } else if (p && p->handle && p->handle->func == python_doc_call.func) {
214 struct python_doc *pd = p->doc_data;
215 Doc *pdoc = pd->pdoc;
219 in_pane_frompane = 1;
220 pane = (Pane *)PyObject_CallObject((PyObject*)&PaneType, NULL);
221 in_pane_frompane = 0;
225 pane->pane = pane_get(p);
229 return (PyObject*)pane;
232 static inline PyObject *safe Mark_Frommark(struct mark *m safe)
236 if (mark_valid(m) && m->mtype == &MarkType && m->mdata) {
237 /* This is a vmark, re-use the PyObject */
239 return (PyObject*)m->mdata;
241 mark = (Mark *)PyObject_CallObject((PyObject*)&MarkType, NULL);
242 if (mark && mark_valid(m))
244 return (PyObject*)mark;
247 static inline PyObject *safe Comm_Fromcomm(struct command *c safe)
249 Comm *comm = (Comm *)PyObject_CallObject((PyObject*)&CommType, NULL);
251 comm->comm = command_get(c);
252 return (PyObject*)comm;
255 static PyObject *py_LOG(PyObject *self, PyObject *args);
256 static void PyErr_LOG(void)
258 /* cribbed from https://groups.google.com/forum/#!topic/comp.lang.python/khLrxC6EOKc */
259 char *errorMsg = NULL;
260 PyObject *modIO = NULL;
261 PyObject *modTB = NULL;
262 PyObject *obFuncStringIO = NULL;
263 PyObject *obIO = NULL;
264 PyObject *obFuncTB = NULL;
265 PyObject *argsTB = NULL;
266 PyObject *obResult = NULL;
267 PyObject *tofree = NULL;
268 PyObject *exc_typ, *exc_val, *exc_tb;
270 if (!PyErr_Occurred())
273 PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
274 PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
276 PyException_SetTraceback(exc_val, exc_tb);
278 /* Import the modules we need - StringIO and traceback */
279 errorMsg = "Can't import io";
280 modIO = PyImport_ImportModule("io");
284 errorMsg = "Can't import traceback";
285 modTB = PyImport_ImportModule("traceback");
289 /* Construct a cStringIO object */
290 errorMsg = "Can't find io.StringIO";
291 obFuncStringIO = PyObject_GetAttrString(modIO, "StringIO");
294 errorMsg = "io.StringIO() failed";
295 obIO = PyObject_CallObject(obFuncStringIO, NULL);
299 /* Get the traceback.print_exception function, and call it. */
300 errorMsg = "Can't find traceback.print_exception";
301 obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
304 errorMsg = "can't make print_exception arguments";
305 argsTB = Py_BuildValue("OOOOO",
306 exc_typ ? exc_typ : Py_None,
307 exc_val ? exc_val : Py_None,
308 exc_tb ? exc_tb : Py_None,
314 errorMsg = "traceback.print_exception() failed";
315 obResult = PyObject_CallObject(obFuncTB, argsTB);
321 /* Now call the getvalue() method in the StringIO instance */
322 Py_DECREF(obFuncStringIO);
323 errorMsg = "cant find getvalue function";
324 obFuncStringIO = PyObject_GetAttrString(obIO, "getvalue");
327 Py_XDECREF(obResult);
328 errorMsg = "getvalue() failed.";
329 obResult = PyObject_CallObject(obFuncStringIO, NULL);
333 /* And it should be a string all ready to go - report it. */
334 errorMsg = python_as_string(obResult, &tofree);;
335 LOG("Python error:\n%s", errorMsg);
338 call("editor:notify:Message:broadcast",ed_pane, 0, NULL,
339 "Python Error - see log") <= 0))
340 /* Failed to alert anyone - write to stderr */
341 fwrite(errorMsg, 1, strlen(errorMsg), stderr);
349 Py_XDECREF(obFuncStringIO);
351 Py_XDECREF(obFuncTB);
353 Py_XDECREF(obResult);
360 DEF_CMD(python_load_module)
362 const char *name = ci->str;
368 PyObject *builtins, *compile, *args, *bytecode;
372 snprintf(buf, sizeof(buf), "%s/python/%s.py", module_dir, name);
373 fd = open(buf, O_RDONLY);
376 size = lseek(fd, 0, SEEK_END);
377 lseek(fd, 0, SEEK_SET);
378 code = malloc(size+1);
383 size = read(fd, code, size);
391 LOG("Loading python module %s from %s", name, buf);
393 builtins = PyEval_GetBuiltins();
394 compile = PyDict_GetItemString(builtins, "compile");
395 args = safe_cast Py_BuildValue("(sss)", code, buf, "exec");
396 bytecode = PyObject_Call(compile, args, NULL);
399 if (bytecode == NULL) {
404 snprintf(buf2, sizeof(buf2), "edlib.%s", name);
406 if (PyImport_ExecCodeModule(buf2, bytecode) == NULL)
412 static PyObject *safe python_string(const char *s safe, int len)
415 const char *e = NULL;
420 while ((!e || c < e) && *c && !(*c & 0x80))
422 while ((wch = get_utf8(&c, e)) != WEOF)
423 if (wch == WERR || wch > 0x10FFFF)
426 return safe_cast PyUnicode_DecodeUTF8(s, c - s, NULL);
429 static char *python_as_string(PyObject *s, PyObject **tofree safe)
431 if (s && PyUnicode_Check(s)) {
432 s = PyUnicode_AsUTF8String(s);
435 if (s && PyBytes_Check(s)) {
436 char *ret = PyBytes_AsString(s);
437 unsigned char *r = (unsigned char*)ret;
438 if (r && r[0] == 0xef && r[1] == 0xbb && r[2] == 0xbf)
439 /* UTF-8 Byte Order Mark */
447 static int dict_add(PyObject *kwds, char *name, PyObject *val)
451 PyDict_SetItemString(kwds, name, val);
456 static bool python_running;
460 PyErr_SetInterrupt();
464 REDEF_CB(python_call)
466 struct python_command *pc = container_of(ci->comm, struct python_command, c);
467 PyObject *ret = NULL, *args, *kwds, *str;
469 bool unterminated = False;
470 int klen = strlen(ci->key);
473 strcmp(ci->key + klen - 13, " unterminated") == 0)
476 args = safe_cast Py_BuildValue("(s)", ci->key);
478 rv = rv && dict_add(kwds, "home", Pane_Frompane(ci->home));
479 rv = rv && dict_add(kwds, "focus",
480 Pane_Frompane(ci->focus));
481 rv = rv && dict_add(kwds, "mark",
482 ci->mark ? Mark_Frommark(ci->mark):
483 (Py_INCREF(Py_None), Py_None));
484 rv = rv && dict_add(kwds, "mark2",
485 ci->mark2 ? Mark_Frommark(ci->mark2):
486 (Py_INCREF(Py_None), Py_None));
489 str = python_string(ci->str, unterminated ? ci->num2 : -1);
495 dict_add(kwds, "str", str);
496 dict_add(kwds, "str1", str);
502 rv = rv && dict_add(kwds, "str2",
503 ci->str2 ? python_string(ci->str2, -1):
504 (Py_INCREF(Py_None), safe_cast Py_None));
505 rv = rv && dict_add(kwds, "comm", Comm_Fromcomm(ci->comm));
506 rv = rv && dict_add(kwds, "comm2",
507 ci->comm2 ? Comm_Fromcomm(ci->comm2):
508 (Py_INCREF(Py_None), Py_None));
509 rv = rv && dict_add(kwds, "num",
510 Py_BuildValue("i", ci->num));
511 rv = rv && dict_add(kwds, "rpt_num",
512 Py_BuildValue("i", RPT_NUM(ci)));
513 rv = rv && dict_add(kwds, "num2",
514 Py_BuildValue("i", ci->num2));
515 rv = rv && dict_add(kwds, "xy",
516 Py_BuildValue("ii", ci->x, ci->y));
518 if (rv && pc->callable) {
519 python_running = True;
520 ret = PyObject_Call(pc->callable, args, kwds);
521 python_running = False;
528 /* FIXME cancel error?? */
533 else if (PyLong_Check(ret))
534 rv = PyLong_AsLong(ret);
535 else if (PyBool_Check(ret))
536 rv = (ret == Py_True) ? 1 : Efalse;
537 else if (PyUnicode_Check(ret) && PyUnicode_GET_LENGTH(ret) >= 1)
538 rv = CHAR_RET(PyUnicode_READ_CHAR(ret, 0));
545 REDEF_CMD(python_doc_call)
547 int rv = python_pane_call_func(ci);
548 if (rv == Efallthrough)
549 rv = key_lookup(doc_default_cmd, ci);
553 static void do_map_init(Pane *self safe)
556 PyObject *l = PyObject_Dir((PyObject*)self);
559 if (!self->map || !self->pane || !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);
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);
574 strstarts(docs, "handle-range") &&
577 char *s1 = strchr(docs+13, sep);
578 char *s2 = s1 ? strchr(s1+1, sep) : NULL;
580 char *a = strndup(docs+13, s1-(docs+13));
581 char *b = strndup(s1+1, s2-(s1+1));
583 struct python_command *comm =
584 export_callable(m, e);
585 key_add_range(self->map, a, b,
588 command_put(&comm->c);
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,
600 command_put(&comm->c);
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);
613 if (m && PyMethod_Check(m)) {
614 PyObject *doc = PyObject_GetAttrString(m, "__doc__");
616 PyObject *tofree = NULL;
617 if (doc && doc != Py_None &&
618 (docs = python_as_string(doc, &tofree)) != NULL) {
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);
626 if (strstarts(docs, "handle-list") &&
629 char *s1 = docs + 12;
630 while (s1 && *s1 && *s1 != sep) {
631 struct python_command *comm =
632 export_callable(m, e);
634 char *s2 = strchr(s1, sep);
636 a = strndup(s1, s2-s1);
642 key_add(self->map, a, &comm->c);
644 command_put(&comm->c);
657 REDEF_CB(python_pane_call)
659 Pane *home = container_of(ci->comm, Pane, cmd);
661 if (!home || !home->map)
666 return key_lookup(home->map, ci);
669 static Pane *pane_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
673 self = (Pane *)type->tp_alloc(type, 0);
680 static Doc *Doc_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
684 self = (Doc *)type->tp_alloc(type, 0);
691 static void python_pane_free(struct command *c safe)
693 Pane *p = container_of(c, Pane, cmd);
694 struct pane *pn = p->pane;
695 /* pane has been closed */
700 if (pn && PyObject_TypeCheck(p, &DocType))
701 doc_free(&pn->doc_data->doc, safe_cast pn);
707 DEF_CMD_CLOSED(python_close_mark)
709 struct mark *m = ci->mark;
711 if (m && m->viewnum >= 0 && m->mtype == &MarkType && m->mdata) {
721 static int do_Pane_init(Pane *self safe, PyObject *args, PyObject *kwds,
726 static const char *keywords[] = {"parent", "z", NULL};
729 PyErr_SetString(PyExc_TypeError, "Pane already initialised");
732 if (in_pane_frompane)
733 /* An internal Pane_Frompane call - it will set .pane,
734 * and we don't want a .handler.
738 /* Pane(parent=None, z=0) */
739 ret = PyArg_ParseTupleAndKeywords(args, kwds, "O!|i", (char**)keywords,
740 &PaneType, parentp, zp);
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;
755 static int Pane_init(Pane *self safe, PyObject *args, PyObject *kwds)
759 int ret = do_Pane_init(self, args, kwds, &parent, &z);
763 if (!parent || !parent->pane)
766 /* The pane holds a reference to the Pane through the ->handle
770 self->pane = pane_register(parent->pane, z, &self->cmd, self);
774 pane_get(self->pane);
778 static int Doc_init(Doc *self, PyObject *args, PyObject *kwds)
781 struct python_doc *pd;
783 int ret = do_Pane_init((Pane*safe)self, args, kwds, &parent, &z);
787 if (!self || !parent || !parent->pane)
790 self->cmd.func = python_doc_call_func;
791 self->pane = doc_register(parent->pane, &self->cmd);
793 pane_get(self->pane);
794 pd = self->pane->doc_data;
796 pd->doc.refcnt = mark_refcnt;
801 static inline void do_free(PyObject *ob safe)
803 if (ob->ob_type && ob->ob_type->tp_free)
804 ob->ob_type->tp_free(ob);
807 DEF_CMD(python_null_call)
812 static void python_pane_free_final(struct command *c safe)
814 Pane *p = container_of(c, Pane, cmd);
819 do_free((PyObject*safe)p);
822 static void pane_dealloc(Pane *self safe)
824 struct pane *p = self->pane;
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.
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;
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;
842 do_free((PyObject*safe)self);
846 static PyObject *pane_children(Pane *self safe, PyObject *args)
850 if (!pane_valid(self))
852 ret = (PaneIter*)PyObject_CallObject((PyObject*)&PaneIterType, NULL);
854 if (list_empty(&self->pane->children))
857 ret->pane = list_first_entry(&self->pane->children,
858 struct pane, siblings);
860 return (PyObject*)ret;
863 static Pane *pane_iter_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
867 self = (Pane *)type->tp_alloc(type, 0);
873 static void paneiter_dealloc(PaneIter *self safe)
875 do_free((PyObject*safe)self);
878 static PyObject *Pane_clone_children(Pane *self safe, PyObject *args)
883 if (!pane_valid(self))
886 ret = PyArg_ParseTuple(args, "O!", &PaneType, &other);
887 if (ret <= 0 || !other)
890 pane_clone_children(self->pane, other->pane);
895 static PyObject *Pane_take_focus(Pane *self safe, PyObject *args)
897 if (!pane_valid(self))
900 pane_take_focus(self->pane);
905 static PyObject *Pane_has_focus(Pane *self safe, PyObject *args)
910 if (!pane_valid(self))
913 ret = PyArg_ParseTuple(args, "|O!", &PaneType, &other);
917 if (pane_has_focus(self->pane, other ? other->pane : NULL)) {
926 static PaneIter *pane_this_iter(PaneIter *self safe)
932 static PyObject *pane_iter_next(PaneIter *self safe)
936 /* Reached the end */
938 ret = Pane_Frompane(self->pane);
939 if (self->pane->siblings.next == &self->pane->parent->children)
940 /* Reached the end of the list */
943 self->pane = list_next_entry(self->pane, siblings);
955 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
956 struct pane *p = ci->focus;
962 pr->ret = Pane_Frompane(ci->focus);
968 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
972 if (!mark_valid(ci->mark))
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;
980 pr->ret = Mark_Frommark(ci->mark);
986 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
990 if (!mark_valid(ci->mark2))
992 pr->ret = Mark_Frommark(ci->mark2);
998 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1003 if (mark_valid(ci->mark))
1004 m1 = Mark_Frommark(ci->mark);
1007 if (mark_valid(ci->mark2))
1008 m2 = Mark_Frommark(ci->mark2);
1012 pr->ret = Py_BuildValue("OO", m1, m2);
1013 if (mark_valid(ci->mark))
1015 if (mark_valid(ci->mark2))
1022 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1027 return Efallthrough;
1028 pr->ret = python_string(ci->str, -1);
1034 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1039 return Efallthrough;
1040 pr->ret = safe_cast PyBytes_FromStringAndSize(ci->str, ci->num);
1046 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1051 return Efallthrough;
1052 pr->ret = Comm_Fromcomm(ci->comm2);
1056 static struct command *map_ret(char *ret safe)
1058 if (strcmp(ret, "pane") == 0)
1060 if (strcmp(ret, "mark") == 0)
1062 if (strcmp(ret, "mark2") == 0)
1064 if (strcmp(ret, "marks") == 0)
1065 return &take_2_marks;
1066 if (strcmp(ret, "str") == 0)
1068 if (strcmp(ret, "bytes") == 0)
1070 if (strcmp(ret, "comm") == 0)
1075 static bool handle_ret(PyObject *kwds, struct cmd_info *ci safe,
1076 struct pyret *pr safe)
1080 PyObject *ret, *s3 = NULL;
1082 memset(pr, 0, sizeof(*pr));
1084 ret = kwds ? PyDict_GetItemString(kwds, "ret") : NULL;
1088 if (!PyUnicode_Check(ret) ||
1089 (rets = python_as_string(ret, &s3)) == NULL) {
1090 PyErr_SetString(PyExc_TypeError, "ret= must be given a string");
1093 if (strcmp(rets, "char") == 0) {
1094 pr->return_char = 1;
1098 PyErr_SetString(PyExc_TypeError, "ret= not permitted with comm2");
1104 PyErr_SetString(PyExc_TypeError, "ret= type not valid");
1109 ci->comm2 = &pr->comm;
1115 static void set_err(int rv)
1119 PyErr_SetObject(Edlib_CommandFailed,
1120 PyUnicode_FromFormat("Enoarg"));
1123 PyErr_SetObject(Edlib_CommandFailed,
1124 PyUnicode_FromFormat("Einval"));
1127 PyErr_SetObject(Edlib_CommandFailed,
1128 PyUnicode_FromFormat("Enosup"));
1131 PyErr_SetObject(Edlib_CommandFailed,
1132 PyUnicode_FromFormat("Efail"));
1135 PyErr_SetObject(Edlib_CommandFailed,
1136 PyUnicode_FromFormat("%d", rv));
1140 static PyObject *choose_ret(int rv, struct pyret *pr safe)
1142 if (pr->comm.func && rv >= Efalse) {
1148 Py_XDECREF(pr->ret);
1153 if (pr->return_char) {
1155 Py_INCREF(Py_False);
1158 if (rv == CHAR_RET(WEOF)) {
1162 return PyUnicode_FromFormat("%c", rv & 0x1FFFFF);
1164 return PyLong_FromLong(rv);
1167 static PyObject *Pane_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1169 struct cmd_info ci = SAFE_CI;
1174 if (!pane_valid(self))
1177 ci.home = self->pane;
1179 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1180 !handle_ret(kwds, &ci, &pr)) {
1181 Py_XDECREF(s1); Py_XDECREF(s2);
1182 command_put(ci.comm2);
1186 python_running = False;
1187 rv = key_handle(&ci);
1188 python_running = True;
1190 /* Just in case ... */
1193 Py_XDECREF(s1); Py_XDECREF(s2);
1194 command_put(ci.comm2);
1196 return choose_ret(rv, &pr);
1199 static PyObject *pane_direct_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1201 struct cmd_info ci = SAFE_CI;
1206 if (!pane_valid(self))
1209 ci.home = self->pane;
1211 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1212 !handle_ret(kwds, &ci, &pr)) {
1213 Py_XDECREF(s1); Py_XDECREF(s2);
1214 command_put(ci.comm2);
1218 ci.comm = ci.home->handle;
1219 rv = ci.comm->func(&ci);
1221 Py_XDECREF(s1); Py_XDECREF(s2);
1222 command_put(ci.comm2);
1223 return choose_ret(rv, &pr);
1226 static PyObject *Pane_notify(Pane *self safe, PyObject *args safe, PyObject *kwds)
1228 struct cmd_info ci = SAFE_CI;
1232 if (!pane_valid(self))
1235 ci.home = self->pane;
1237 if (!get_cmd_info(&ci, args, kwds, &s1, &s2)) {
1238 Py_XDECREF(s1); Py_XDECREF(s2);
1239 command_put(ci.comm2);
1243 rv = home_pane_notify(ci.home, ci.key, ci.focus, ci.num, ci.mark, ci.str,
1244 ci.num2, ci.mark2, ci.str2,
1247 Py_XDECREF(s1); Py_XDECREF(s2);
1248 command_put(ci.comm2);
1253 return PyLong_FromLong(rv);
1256 static PyObject *Pane_mapxy(Pane *self safe, PyObject *args)
1262 int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1263 if (ret <= 0 || !self->pane || !other || !other->pane)
1266 xy = pane_mapxy(other->pane, self->pane, x, y, False);
1267 return Py_BuildValue("ii", xy.x, xy.y);
1270 static PyObject *Pane_clipxy(Pane *self safe, PyObject *args)
1276 int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1277 if (ret <= 0 || !self->pane || !other || !other->pane)
1280 xy = pane_mapxy(other->pane, self->pane, x, y, True);
1281 return Py_BuildValue("ii", xy.x, xy.y);
1284 static PyObject *Pane_add_notify(Pane *self safe, PyObject *args)
1288 int ret = PyArg_ParseTuple(args, "O!s", &PaneType, &other, &event);
1289 if (ret <= 0 || !other || !event)
1291 if (self->pane && other->pane)
1292 pane_add_notify(self->pane, other->pane, event);
1298 static PyObject *Pane_drop_notify(Pane *self safe, PyObject *args)
1301 int ret = PyArg_ParseTuple(args, "s", &event);
1302 if (ret <= 0 || !event)
1305 pane_drop_notifiers(self->pane, event);
1311 static PyObject *Pane_damaged(Pane *self safe, PyObject *args)
1313 int damage = DAMAGED_REFRESH;
1314 int ret = PyArg_ParseTuple(args, "|i", &damage);
1318 pane_damaged(self->pane, damage);
1324 static PyObject *Pane_close(Pane *self safe, PyObject *args)
1326 struct pane *p = self->pane;
1335 static PyObject *Pane_get_scale(Pane *self safe, PyObject *args)
1337 struct pane *p = self->pane;
1338 struct xy xy = {1000, 1000};
1342 return Py_BuildValue("ii", xy.x, xy.y);
1345 static PyObject *Pane_set_time(Pane *self safe, PyObject *args)
1347 struct pane *p = self->pane;
1354 static PyObject *Pane_too_long(Pane *self safe, PyObject *args)
1356 struct pane *p = self->pane;
1358 if (!p || pane_too_long(p, 0)) {
1362 Py_INCREF(Py_False);
1367 static PyObject *Pane_mychild(Pane *self safe, PyObject *args)
1370 int ret = PyArg_ParseTuple(args, "O!", &PaneType, &child);
1371 if (ret <= 0 || !child)
1373 if (self->pane && child->pane) {
1374 struct pane *p = pane_my_child(self->pane, child->pane);
1376 return Pane_Frompane(p);
1382 static PyObject *Pane_clip(Pane *self safe, PyObject *args)
1384 Mark *start = NULL, *end = NULL;
1387 int ret = PyArg_ParseTuple(args, "iO!O!|i", &view, &MarkType, &start,
1388 &MarkType, &end, &tostart);
1390 if (ret > 0 && start && end && self->pane &&
1391 start->mark && end->mark && view >= 0)
1392 marks_clip(self->pane, start->mark, end->mark, view, self->pane,
1398 static PyObject *Pane_reparent(Pane *self safe, PyObject *args)
1400 Pane *newparent = NULL;
1401 int ret = PyArg_ParseTuple(args, "O!", &PaneType, &newparent);
1403 if (ret > 0 && newparent && self->pane && newparent->pane) {
1404 pane_reparent(self->pane, newparent->pane);
1405 if (self->pane->parent != newparent->pane) {
1406 PyErr_SetString(PyExc_TypeError, "reparent failed");
1414 static PyObject *Pane_move_after(Pane *self safe, PyObject *args)
1417 int ret = PyArg_ParseTuple(args, "O", &peer);
1419 if (ret > 0 && peer && self->pane) {
1420 if ((PyObject*)peer == Py_None)
1421 pane_move_after(self->pane, NULL);
1422 else if (PyObject_TypeCheck(peer, &PaneType) && peer->pane)
1423 pane_move_after(self->pane, peer->pane);
1429 static PyObject *Pane_step(Pane *self safe, PyObject *args, int dir, int move)
1432 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &m);
1435 if (!pane_valid(self))
1437 if (ret <= 0 || !m || !mark_valid(m->mark)) {
1438 PyErr_SetString(PyExc_TypeError, "Arg must be a mark");
1443 wch = doc_move(self->pane, m->mark, dir);
1445 wch = doc_pending(self->pane, m->mark, dir);
1450 return PyUnicode_FromFormat("%c", wch);
1453 static PyObject *Pane_step_next(Pane *self safe, PyObject *args)
1455 return Pane_step(self, args, 1, 1);
1458 static PyObject *Pane_step_prev(Pane *self safe, PyObject *args)
1460 return Pane_step(self, args, -1, 1);
1463 static PyObject *Pane_step_following(Pane *self safe, PyObject *args)
1465 return Pane_step(self, args, 1, 0);
1468 static PyObject *Pane_step_prior(Pane *self safe, PyObject *args)
1470 return Pane_step(self, args, -1, 0);
1473 static PyObject *Pane_get_vmarks(Pane *self safe, PyObject *args)
1480 if (!pane_valid(self))
1482 ret = PyArg_ParseTuple(args, "i|O!", &view, &PaneType, &owner);
1483 if (ret <= 0 || view < 0 || (owner && !pane_valid(owner))) {
1487 memset(&pr, 0, sizeof(pr));
1488 pr.comm = take_2_marks;
1489 home_call_comm(self->pane, "doc:vmark-get",
1490 owner ? owner->pane : self->pane,
1498 static PyObject *Pane_vmark_at_or_before(Pane *self safe, PyObject *args)
1506 if (!pane_valid(self))
1508 ret = PyArg_ParseTuple(args, "iO!|O!", &view, &MarkType, &m,
1510 if (ret <= 0 || view < 0 || !m || !mark_valid(m->mark) ||
1511 (owner && !pane_valid(owner))) {
1515 memset(&pr, 0, sizeof(pr));
1516 pr.comm = take_mark;
1517 home_call_comm(self->pane, "doc:vmark-prev",
1518 owner ? owner->pane : self->pane,
1519 &pr.comm, view, m->mark);
1526 static const PyMethodDef pane_methods[] = {
1527 {"close", (PyCFunction)Pane_close, METH_NOARGS,
1529 {"children", (PyCFunction)pane_children, METH_NOARGS,
1530 "provides an iterator which will iterate over all children"},
1531 {"clone_children", (PyCFunction)Pane_clone_children, METH_VARARGS,
1532 "Clone all children onto the target"},
1533 {"take_focus", (PyCFunction)Pane_take_focus, METH_NOARGS,
1534 "Claim the focus for this pane"},
1535 {"has_focus", (PyCFunction)Pane_has_focus, METH_VARARGS,
1536 "Check if pane is focus of display"},
1537 {"call", (void*)(PyCFunctionWithKeywords)Pane_call, METH_VARARGS|METH_KEYWORDS,
1538 "Call a command from a pane"},
1539 {"notify", (void*)(PyCFunctionWithKeywords)Pane_notify, METH_VARARGS|METH_KEYWORDS,
1540 "Send a notification from a pane"},
1541 {"mapxy", (PyCFunction)Pane_mapxy, METH_VARARGS,
1542 "Convert pane-relative co-ords between panes"},
1543 {"clipxy", (PyCFunction)Pane_clipxy, METH_VARARGS,
1544 "Convert pane-relative co-ords between panes, clipping to all panes"},
1545 {"add_notify", (PyCFunction)Pane_add_notify, METH_VARARGS,
1546 "Add notifier for an event on some other pane"},
1547 {"drop_notify", (PyCFunction)Pane_drop_notify, METH_VARARGS,
1548 "Drop notification to this pane for an event"},
1549 {"damaged", (PyCFunction)Pane_damaged, METH_VARARGS,
1550 "Mark pane as damaged"},
1551 {"scale", (PyCFunction)Pane_get_scale, METH_NOARGS,
1552 "Get the x,y scale numbers for this pane"},
1553 {"mychild", (PyCFunction)Pane_mychild, METH_VARARGS,
1554 "Get ancestor of pane which is my child, or None"},
1555 {"clip", (PyCFunction)Pane_clip, METH_VARARGS,
1556 "clip all 'type' marks in the given range"},
1557 {"reparent", (PyCFunction)Pane_reparent, METH_VARARGS,
1558 "Give a pane a new parent"},
1559 {"move_after", (PyCFunction)Pane_move_after, METH_VARARGS,
1560 "Move a pane after another in order of children"},
1561 {"next", (PyCFunction)Pane_step_next, METH_VARARGS,
1562 "Move mark forward returning the character"},
1563 {"prev", (PyCFunction)Pane_step_prev, METH_VARARGS,
1564 "Move mark back returning the character"},
1565 {"following", (PyCFunction)Pane_step_following, METH_VARARGS,
1566 "returning the character after mark"},
1567 {"prior", (PyCFunction)Pane_step_prior, METH_VARARGS,
1568 "returning the character before mark"},
1569 {"vmarks", (PyCFunction)Pane_get_vmarks, METH_VARARGS,
1570 "return first and last vmark given view number"},
1571 {"vmark_at_or_before", (PyCFunction)Pane_vmark_at_or_before, METH_VARARGS,
1572 "return vmark at-or-before given mark"},
1573 {"set_time", (PyCFunction)Pane_set_time, METH_NOARGS,
1574 "Set start time for long running operation"},
1575 {"too_long", (PyCFunction)Pane_too_long, METH_NOARGS,
1576 "Check if command in pane has been running for too long"},
1580 static PyObject *pane_getnum(Pane *p safe, char *which safe)
1588 case 'x': n = p->pane->x; break;
1589 case 'y': n = p->pane->y; break;
1590 case 'w': n = p->pane->w > 0 ? p->pane->w : 1; break;
1591 case 'h': n = p->pane->h > 0 ? p->pane->h : 1; break;
1592 case 'X': n = p->pane->cx; break;
1593 case 'Y': n = p->pane->cy; break;
1594 case 'z': n = p->pane->z; break;
1595 case 'Z': n = p->pane->abs_z; break;
1597 return PyLong_FromLong(n);
1600 static int pane_setnum(Pane *p safe, PyObject *v, char *which safe)
1608 if (*which == 'z') {
1609 PyErr_SetString(PyExc_TypeError, "z cannot be set");
1612 if (*which == 'Z') {
1613 PyErr_SetString(PyExc_TypeError, "abs_z cannot be set");
1616 val = PyLong_AsLong(v);
1617 if (val == -1 && PyErr_Occurred())
1620 x = p->pane->x; y = p->pane->y;
1621 w = p->pane->w; h = p->pane->h;
1623 case 'x': x = val; break;
1624 case 'y': y = val; break;
1625 case 'w': w = val; break;
1626 case 'h': h = val; break;
1627 case 'X': p->pane->cx = val; return 0;
1628 case 'Y': p->pane->cy = val; return 0;
1630 pane_resize(p->pane, x, y, w, h);
1634 static Pane *pane_getpane(Pane *p safe, char *which safe)
1636 struct pane *new = NULL;
1643 new = p->pane->parent;
1645 new = p->pane->focus;
1647 new = pane_root(p->pane);
1649 new = pane_focus(p->pane);
1651 new = pane_leaf(p->pane);
1654 newpane = (Pane*)Py_None;
1656 newpane = (Pane *)Pane_Frompane(new);
1661 static int pane_nosetpane(Pane *p, PyObject *v, void *which)
1663 PyErr_SetString(PyExc_TypeError, "Cannot set panes");
1667 static PyObject *pane_repr(Pane *self safe)
1671 if (!pane_valid(self))
1672 asprintf(&s, "<edlib.Pane FREED!!! %p>", self);
1674 asprintf(&s, "<edlib.Pane %p-%s>", self->pane, self->pane->name);
1675 ret = Py_BuildValue("s", s);
1680 static PyObject *doc_repr(Doc *self safe)
1684 if (!doc_valid(self))
1685 asprintf(&s, "<edlib.Doc FREED!!! %p>", self);
1687 asprintf(&s, "<edlib.Doc %p-%s>", self->pane, self->pane->name);
1688 ret = Py_BuildValue("s", s);
1693 static long pane_hash(Pane *p safe)
1695 return (long)p->pane;
1698 static PyObject *pane_cmp(Pane *p1 safe, Pane *p2 safe, int op)
1700 Py_RETURN_RICHCOMPARE(p1->pane, p2->pane, op);
1703 static const PyGetSetDef pane_getseters[] = {
1705 (getter)pane_getnum, (setter)pane_setnum,
1706 "X offset in parent", "x" },
1708 (getter)pane_getnum, (setter)pane_setnum,
1709 "Y offset in parent", "y" },
1711 (getter)pane_getnum, (setter)pane_setnum,
1712 "Z offset in parent", "z" },
1714 (getter)pane_getnum, (setter)pane_setnum,
1715 "width of pane", "w" },
1717 (getter)pane_getnum, (setter)pane_setnum,
1718 "heigth of pane", "h" },
1720 (getter)pane_getnum, (setter)pane_setnum,
1721 "Cursor X offset in pane", "X" },
1723 (getter)pane_getnum, (setter)pane_setnum,
1724 "Cursor Y offset in pane", "Y" },
1726 (getter)pane_getnum, (setter)pane_setnum,
1727 "global Z offset", "Z" },
1729 (getter)pane_getpane, (setter)pane_nosetpane,
1730 "Parent pane", "p"},
1732 (getter)pane_getpane, (setter)pane_nosetpane,
1733 "Focal child", "f"},
1735 (getter)pane_getpane, (setter)pane_nosetpane,
1738 (getter)pane_getpane, (setter)pane_nosetpane,
1739 "Final focus pane", "F"},
1741 (getter)pane_getpane, (setter)pane_nosetpane,
1743 {NULL} /* Sentinel */
1746 static PyObject *Pane_get_item(Pane *self safe, PyObject *key safe)
1749 PyObject *t1 = NULL;
1751 if (!pane_valid(self))
1754 k = python_as_string(key, &t1);
1756 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1759 v = pane_attr_get(self->pane, k);
1762 return Py_BuildValue("s", v);
1767 static int Pane_set_item(Pane *self safe, PyObject *key, PyObject *val)
1770 PyObject *t1 = NULL, *t2 = NULL;
1772 if (!pane_valid(self))
1775 k = python_as_string(key, &t1);
1777 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1780 v = python_as_string(val, &t2);
1781 if (val != Py_None && !v) {
1782 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
1786 attr_set_str(&self->pane->attrs, k, v);
1792 static const PyMappingMethods pane_mapping = {
1794 .mp_subscript = (binaryfunc)Pane_get_item,
1795 .mp_ass_subscript = (objobjargproc)Pane_set_item,
1798 static PyTypeObject PaneType = {
1799 PyVarObject_HEAD_INIT(NULL, 0)
1800 .tp_name = "edlib.Pane",
1801 .tp_basicsize = sizeof(Pane),
1802 .tp_dealloc = (destructor)pane_dealloc,
1803 .tp_richcompare = (richcmpfunc)pane_cmp,
1804 .tp_repr = (reprfunc)pane_repr,
1805 .tp_as_mapping = (PyMappingMethods*)&pane_mapping,
1806 .tp_hash = (hashfunc)pane_hash,
1807 .tp_call = (ternaryfunc)pane_direct_call,
1808 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1809 .tp_doc = "edlib panes",
1810 .tp_methods = (PyMethodDef*)pane_methods,
1811 .tp_getset = (PyGetSetDef*)pane_getseters,
1812 .tp_init = (initproc)Pane_init,
1813 .tp_new = (newfunc)pane_new,
1816 static PyTypeObject PaneIterType = {
1817 PyVarObject_HEAD_INIT(NULL, 0)
1818 .tp_name = "edlib.PaneIter",
1819 .tp_basicsize = sizeof(PaneIter),
1820 .tp_dealloc = (destructor)paneiter_dealloc,
1821 .tp_flags = Py_TPFLAGS_DEFAULT,
1822 .tp_doc = "edlib pane iterator",
1823 .tp_iter = (getiterfunc)pane_this_iter,
1824 .tp_iternext = (iternextfunc)pane_iter_next,
1825 .tp_new = (newfunc)pane_iter_new,
1828 static PyObject *first_mark(Doc *self safe, PyObject *args)
1832 if (!doc_valid(self))
1835 m = mark_first(&self->pane->doc_data->doc);
1840 return Mark_Frommark(m);
1843 static PyObject *to_end(Doc *self safe, PyObject *args)
1849 if (!doc_valid(self))
1852 ret = PyArg_ParseTuple(args, "O!p", &MarkType, &mark, &end);
1853 if (ret <= 0 || !mark || !mark_valid(mark->mark)) {
1854 PyErr_SetString(PyExc_TypeError, "Mark undefined or uninitialized");
1858 mark_to_end(self->pane, mark->mark, end);
1863 static const PyMethodDef doc_methods[] = {
1864 {"first_mark", (PyCFunction)first_mark, METH_NOARGS,
1865 "first mark of document"},
1866 {"to_end", (PyCFunction)to_end, METH_VARARGS,
1867 "Move mark to one end of document"},
1871 static PyTypeObject DocType = {
1872 PyVarObject_HEAD_INIT(NULL, 0)
1873 .tp_name = "edlib.Doc",
1874 .tp_basicsize = sizeof(Doc),
1875 .tp_dealloc = (destructor)pane_dealloc,
1876 .tp_repr = (reprfunc)doc_repr,
1877 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1878 .tp_doc = "edlib document",
1879 .tp_methods = (PyMethodDef*)doc_methods,
1880 .tp_base = &PaneType,
1881 .tp_init = (initproc)Doc_init,
1882 .tp_new = (newfunc)Doc_new,
1885 static PyObject *mark_getoffset(Mark *m safe, void *x)
1888 if (!mark_valid(m->mark)) {
1889 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1892 d = &m->mark->owner->doc;
1893 if (d->refcnt == mark_refcnt)
1894 return PyLong_FromLong(m->mark->ref.o);
1895 return PyLong_FromLong(0);
1898 static int mark_setoffset(Mark *m safe, PyObject *v safe, void *x)
1903 if (!mark_valid(m->mark)) {
1904 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1907 val = PyLong_AsLong(v);
1908 if (val == -1 && PyErr_Occurred())
1910 d = &m->mark->owner->doc;
1911 if (d->refcnt == mark_refcnt)
1912 m->mark->ref.o = val;
1914 PyErr_SetString(PyExc_TypeError, "Setting offset on non-local mark");
1920 static PyObject *mark_getseq(Mark *m safe, void *x)
1922 if (!mark_valid(m->mark)) {
1923 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1926 return PyLong_FromLong(m->mark->seq);
1929 static int mark_nosetseq(Mark *m, PyObject *v, void *which)
1931 PyErr_SetString(PyExc_TypeError, "Cannot set mark seq number");
1935 static void mark_refcnt(struct mark *m safe, int inc)
1940 Py_INCREF(m->ref.c);
1944 Py_DECREF(m->ref.c);
1949 static PyObject *mark_getpos(Mark *m safe, void *x)
1952 if (!mark_valid(m->mark)) {
1953 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1956 d = &m->mark->owner->doc;
1957 if (d->refcnt == mark_refcnt && m->mark->ref.c) {
1958 Py_INCREF(m->mark->ref.c);
1959 return m->mark->ref.c;
1966 static int mark_setpos(Mark *m safe, PyObject *v, void *x)
1971 if (!mark_valid(m->mark)) {
1972 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1975 d = &m->mark->owner->doc;
1976 if (d->refcnt != mark_refcnt) {
1977 PyErr_SetString(PyExc_TypeError, "Cannot set ref for non-local mark");
1980 d->refcnt(m->mark, -1);
1983 /* If an adjacent mark has a ref.c with a matching value
1984 * use that instead, so that mark_same() works.
1986 if ((m2 = mark_next(m->mark)) != NULL &&
1987 m2->owner->doc.refcnt == mark_refcnt &&
1988 m2->ref.c != NULL && v != NULL &&
1989 PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1990 m->mark->ref.c = m2->ref.c;
1991 else if ((m2 = mark_prev(m->mark)) != NULL &&
1992 m2->owner->doc.refcnt == mark_refcnt &&
1993 m2->ref.c != NULL && v != NULL &&
1994 PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1995 m->mark->ref.c = m2->ref.c;
1998 d->refcnt(m->mark, 1);
2002 static PyObject *mark_getview(Mark *m safe, void *x)
2004 if (!mark_valid(m->mark)) {
2005 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2008 return PyLong_FromLong(m->mark->viewnum);
2011 static int mark_nosetview(Mark *m, PyObject *v, void *which)
2013 PyErr_SetString(PyExc_TypeError, "Cannot set mark viewnum");
2017 static PyObject *mark_compare(Mark *a safe, Mark *b safe, int op)
2019 if ((PyObject*)a == Py_None)
2020 Py_RETURN_RICHCOMPARE(0, 1, op);
2021 else if ((PyObject*)b == Py_None)
2022 Py_RETURN_RICHCOMPARE(1, 0, op);
2023 else if (PyObject_TypeCheck(a, &MarkType) == 0 ||
2024 PyObject_TypeCheck(b, &MarkType) == 0) {
2025 PyErr_SetString(PyExc_TypeError, "Mark compared with non-Mark");
2027 } else if (!mark_valid(a->mark) || !mark_valid(b->mark))
2030 int cmp = a->mark->seq - b->mark->seq;
2031 if (mark_same(a->mark, b->mark))
2033 Py_RETURN_RICHCOMPARE(cmp, 0, op);
2037 static const PyGetSetDef mark_getseters[] = {
2039 (getter)mark_getpos, (setter)mark_setpos,
2040 "Position ref", NULL},
2042 (getter)mark_getoffset, (setter)mark_setoffset,
2043 "Position offset", NULL},
2045 (getter)mark_getview, (setter)mark_nosetview,
2046 "Index for view list", NULL},
2048 (getter)mark_getseq, (setter)mark_nosetseq,
2049 "Sequence number of mark", NULL},
2050 {NULL} /* Sentinel */
2053 static Mark *Mark_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
2057 self = (Mark *)type->tp_alloc(type, 0);
2064 static int Mark_init(Mark *self safe, PyObject *args safe, PyObject *kwds)
2068 int view = MARK_UNGROUPED;
2070 static const char *keywords[] = {"pane","view","orig", "owner", NULL};
2073 if (!PyTuple_Check(args) ||
2074 (PyTuple_GET_SIZE(args) == 0 && kwds == NULL))
2075 /* Internal Mark_Frommark call */
2078 ret = PyArg_ParseTupleAndKeywords(args, kwds, "|O!iO!O!", (char**)keywords,
2086 PyErr_SetString(PyExc_TypeError,
2087 "Only one of 'pane' and 'orig' may be set");
2090 if (!doc && !orig) {
2091 PyErr_SetString(PyExc_TypeError,
2092 "At least one of 'pane' and 'orig' must be set");
2095 if (doc && doc->pane) {
2096 struct pane *p = doc->pane;
2097 struct pane *op = owner ? owner->pane : NULL;
2100 self->mark = vmark_new(p, view, op);
2101 } else if (orig && mark_valid(orig->mark)) {
2102 self->mark = mark_dup_view(orig->mark);
2105 PyErr_SetString(PyExc_TypeError, "Mark creation failed");
2108 if (self->mark->viewnum >= 0) {
2109 /* vmarks can use mdata and don't disappear until
2110 * explicitly released.
2112 self->mark->mtype = &MarkType;
2113 self->mark->mdata = self;
2116 /* Other marks cannot use mdata and get freed when
2117 * the original PyObject is destroyed
2119 self->mark->mtype = (void*)self;
2124 static void mark_dealloc(Mark *self safe)
2126 if (mark_valid(self->mark) && self->mark->mtype == (void*)self) {
2127 /* Python allocated this mark, so can free it. */
2128 struct mark *m = self->mark;
2134 do_free((PyObject*safe)self);
2137 static PyObject *Mark_to_mark(Mark *self safe, PyObject *args)
2140 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2141 if (ret <= 0 || !other ||
2142 !mark_valid(self->mark) || !mark_valid(other->mark))
2144 mark_to_mark(self->mark, other->mark);
2150 static PyObject *Mark_to_mark_noref(Mark *self safe, PyObject *args)
2153 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2154 if (ret <= 0 || !other ||
2155 !mark_valid(self->mark) || !mark_valid(other->mark))
2157 mark_to_mark_noref(self->mark, other->mark);
2163 static PyObject *Mark_clip(Mark *self safe, PyObject *args)
2165 Mark *start = NULL, *end = NULL;
2167 int ret = PyArg_ParseTuple(args, "O!O!|p", &MarkType, &start,
2168 &MarkType, &end, &tostart);
2170 if (ret > 0 && start && end && mark_valid(self->mark) &&
2171 mark_valid(start->mark) && mark_valid(end->mark))
2172 mark_clip(self->mark, start->mark, end->mark, tostart);
2178 static PyObject *Mark_step(Mark *self safe, PyObject *args)
2180 /* Convenience function to help implement doc:char */
2182 int ret = PyArg_ParseTuple(args, "i", &forward);
2184 if (ret > 0 && self->mark)
2185 mark_step(self->mark, forward);
2191 static PyObject *Mark_step_sharesref(Mark *self safe, PyObject *args)
2193 /* Convenience function to help implement doc:char */
2195 int ret = PyArg_ParseTuple(args, "i", &forward);
2197 if (ret > 0 && self->mark)
2198 mark_step_sharesref(self->mark, forward);
2204 static PyObject *Mark_next(Mark *self safe, PyObject *args)
2207 if (!mark_valid(self->mark)) {
2208 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2211 if (self->mark->viewnum >= 0)
2212 next = vmark_next(self->mark);
2216 return Mark_Frommark(next);
2221 static PyObject *Mark_prev(Mark *self safe, PyObject *args)
2224 if (!mark_valid(self->mark)) {
2225 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2228 if (self->mark->viewnum >= 0)
2229 prev = vmark_prev(self->mark);
2233 return Mark_Frommark(prev);
2238 static PyObject *Mark_next_any(Mark *self safe, PyObject *args)
2241 if (!mark_valid(self->mark)) {
2242 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2245 next = mark_next(self->mark);
2247 return Mark_Frommark(next);
2252 static PyObject *Mark_prev_any(Mark *self safe, PyObject *args)
2255 if (!mark_valid(self->mark)) {
2256 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2259 prev = mark_prev(self->mark);
2261 return Mark_Frommark(prev);
2266 static PyObject *Mark_dup(Mark *self safe, PyObject *args)
2269 if (!mark_valid(self->mark)) {
2270 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2273 new = mark_dup(self->mark);
2275 Mark *ret = (Mark*)Mark_Frommark(new);
2276 /* We want this mark to be freed when the Mark
2279 new->mtype = (void*)ret;
2280 return (PyObject*)ret;
2287 static PyObject *Mark_release(Mark *self safe, PyObject *args)
2289 struct mark *m = self->mark;
2291 if (!mark_valid(m)) {
2292 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2295 if (m->viewnum == MARK_UNGROUPED || m->viewnum == MARK_POINT) {
2296 PyErr_SetString(PyExc_TypeError,
2297 "Cannot release ungrouped marks or points");
2300 if (m->mtype != &MarkType) {
2301 PyErr_SetString(PyExc_TypeError,
2302 "Mark is not managed by python, and cannot be released");
2306 /* We are dropping this mark - there cannot be any other ref */
2307 ASSERT(m->mdata == self);
2318 static PyObject *Mark_watch(Mark *self safe, PyObject *args)
2320 struct mark *m = self->mark;
2322 if (!mark_valid(m)) {
2323 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2331 static const PyMethodDef mark_methods[] = {
2332 {"to_mark", (PyCFunction)Mark_to_mark, METH_VARARGS,
2333 "Move one mark to another"},
2334 {"to_mark_noref", (PyCFunction)Mark_to_mark_noref, METH_VARARGS,
2335 "Move one mark to another but don't update ref"},
2336 {"next", (PyCFunction)Mark_next, METH_NOARGS,
2338 {"prev", (PyCFunction)Mark_prev, METH_NOARGS,
2340 {"next_any", (PyCFunction)Mark_next_any, METH_NOARGS,
2342 {"prev_any", (PyCFunction)Mark_prev_any, METH_NOARGS,
2343 "previous any_mark"},
2344 {"dup", (PyCFunction)Mark_dup, METH_NOARGS,
2345 "duplicate a mark, as ungrouped"},
2346 {"clip", (PyCFunction)Mark_clip, METH_VARARGS,
2347 "If this mark is in range, move to end"},
2348 {"release", (PyCFunction)Mark_release, METH_NOARGS,
2349 "release a vmark so it can disappear"},
2350 {"watch", (PyCFunction)Mark_watch, METH_NOARGS,
2351 "acknowledge movement of a point - allow further notifications"},
2352 {"step", (PyCFunction)Mark_step, METH_VARARGS,
2353 "Move mark over any adjacent marks with same reference"},
2354 {"step_sharesref", (PyCFunction)Mark_step_sharesref, METH_VARARGS,
2355 "Move mark over any adjacent marks with same reference"},
2359 static PyObject *mark_get_item(Mark *self safe, PyObject *key safe)
2362 PyObject *t1 = NULL;
2364 if (!mark_valid(self->mark)) {
2365 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2368 k = python_as_string(key, &t1);
2370 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2373 v = attr_find(self->mark->attrs, k);
2376 return Py_BuildValue("s", v);
2381 static int mark_set_item(Mark *self safe, PyObject *key safe, PyObject *val safe)
2384 PyObject *t1 = NULL, *t2 = NULL;
2385 if (!mark_valid(self->mark)) {
2386 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2389 k = python_as_string(key, &t1);
2391 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2394 v = python_as_string(val, &t2);
2395 if (val != Py_None && !v) {
2396 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
2400 attr_set_str(&self->mark->attrs, k, v);
2406 static PyObject *mark_repr(Mark *self safe)
2408 char *s = NULL, *dm;
2412 asprintf(&s, "<edlib.Mark NULL %p>", self);
2413 else if (!mark_valid(self->mark))
2414 asprintf(&s, "<edlib.Mark FREED %p>", self);
2415 else if ((dm = call_ret(str, "doc:debug:mark", self->mark->owner,
2418 asprintf(&s, "<edlib.Mark seq=%d v=%d %s>",
2419 self->mark->seq, self->mark->viewnum, dm);
2421 asprintf(&s, "<edlib.Mark seq=%d v=%d i=%d %p>",
2422 self->mark->seq, self->mark->viewnum,
2423 self->mark->ref.o, self->mark);
2425 ret = Py_BuildValue("s", s);
2430 static const PyMappingMethods mark_mapping = {
2432 .mp_subscript = (binaryfunc)mark_get_item,
2433 .mp_ass_subscript = (objobjargproc)mark_set_item,
2436 static int mark_bool(Mark *self safe)
2438 return mark_valid(self->mark);
2441 static const PyNumberMethods mark_as_num = {
2442 .nb_bool = (inquiry) mark_bool,
2445 static PyTypeObject MarkType = {
2446 PyVarObject_HEAD_INIT(NULL, 0)
2447 .tp_name = "edlib.Mark",
2448 .tp_basicsize = sizeof(Mark),
2449 .tp_dealloc = (destructor)mark_dealloc,
2450 .tp_as_mapping = (PyMappingMethods*)&mark_mapping,
2451 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2452 .tp_doc = "edlib marks",
2453 .tp_richcompare = (richcmpfunc)mark_compare,
2454 .tp_methods = (PyMethodDef*)mark_methods,
2455 .tp_getset = (PyGetSetDef*)mark_getseters,
2456 .tp_init = (initproc)Mark_init,
2457 .tp_new = (newfunc)Mark_new,
2458 .tp_repr = (reprfunc)mark_repr,
2459 .tp_as_number = (PyNumberMethods*)&mark_as_num,
2462 static void comm_dealloc(Comm *self safe)
2464 command_put(self->comm);
2465 do_free((PyObject*safe)self);
2468 static PyObject *comm_repr(Comm *self safe)
2474 asprintf(&s, "<edlib.Comm refcnt=%d %p>",
2475 self->comm->refcnt, self->comm);
2477 asprintf(&s, "<edlib.Comm NULL %p>", self);
2478 ret = Py_BuildValue("s", s);
2483 static PyObject *Comm_call(Comm *c safe, PyObject *args safe, PyObject *kwds)
2485 struct cmd_info ci = SAFE_CI;
2492 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
2493 !handle_ret(kwds, &ci, &pr)) {
2494 Py_XDECREF(s1); Py_XDECREF(s2);
2495 command_put(ci.comm2);
2499 rv = c->comm->func(&ci);
2500 Py_XDECREF(s1); Py_XDECREF(s2);
2501 command_put(ci.comm2);
2503 return choose_ret(rv, &pr);
2506 static PyObject *comm_cmp(Comm *c1 safe, Comm *c2 safe, int op)
2508 Py_RETURN_RICHCOMPARE(c1->comm, c2->comm, op);
2511 static Comm *comm_new(PyTypeObject *type safe, PyObject *args safe, PyObject *kwds)
2515 self = (Comm *)type->tp_alloc(type, 0);
2521 static PyTypeObject CommType = {
2522 PyVarObject_HEAD_INIT(NULL, 0)
2523 .tp_name = "edlib.Comm",
2524 .tp_basicsize = sizeof(Comm),
2525 .tp_dealloc = (destructor)comm_dealloc,
2526 .tp_richcompare = (richcmpfunc)comm_cmp,
2527 .tp_repr = (reprfunc)comm_repr,
2528 .tp_call = (ternaryfunc)Comm_call,
2529 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2530 .tp_doc = "edlib command",
2531 .tp_new = (newfunc)comm_new,
2534 static void python_free_command(struct command *c safe)
2536 struct python_command *pc = container_of(c, struct python_command, c);
2539 Py_DECREF(pc->callable);
2544 /* The 'call' function takes liberties with arg passing.
2545 * Positional args must start with the key, and then are handled based on
2546 * there type. They can be panes, strigns, ints, pairs, marks, commands.
2547 * Panes are assigned to focus, then home.
2548 * Strings (after the key) are assigned to 'str' then 'str2'.
2550 * Ints are assigned to num then num2
2551 * Pairs (must be of ints) are assigned to x,y then hx,hy.
2552 * Marks are assigned to mark then mark2
2553 * A command is assigned to comm2 (comm is set automatically)
2554 * kwd arguments can also be used, currently
2555 * key, home, focus, xy, hxy, str, str2, mark, mark2, comm2.
2556 * A 'None' arg is ignored - probably a mark or string or something. Just use NULL
2558 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
2559 PyObject **s1 safe, PyObject **s2 safe)
2564 int num_set = 0, num2_set = 0;
2569 if (!PyTuple_Check(args))
2571 argc = PyTuple_GET_SIZE(args);
2573 /* First positional arg must be the key */
2574 a = PyTuple_GetItem(args, 0);
2575 if (!PyUnicode_Check(a)) {
2576 PyErr_SetString(PyExc_TypeError, "First arg must be key");
2579 ci->key = safe_cast PyUnicode_AsUTF8(a);
2581 for (i = 1; i < argc; i++) {
2582 a = PyTuple_GetItem(args, i);
2583 if (!a || a == Py_None)
2584 /* quietly ignore */;
2585 else if (PyObject_TypeCheck(a, &PaneType)) {
2586 if ((void*)ci->home == NULL)
2587 ci->home = safe_cast ((Pane*)a)->pane;
2588 else if ((void*)ci->focus == NULL)
2589 ci->focus = safe_cast ((Pane*)a)->pane;
2591 PyErr_SetString(PyExc_TypeError, "Only 2 Pane args permitted");
2594 } else if (PyObject_TypeCheck(a, &MarkType)) {
2595 if (ci->mark == NULL)
2596 ci->mark = ((Mark*)a)->mark;
2597 else if (ci->mark2 == NULL)
2598 ci->mark2 = ((Mark*)a)->mark;
2600 PyErr_SetString(PyExc_TypeError, "Only 2 Mark args permitted");
2603 } else if (PyUnicode_Check(a)) {
2606 if (ci->str && ci->str2) {
2607 PyErr_SetString(PyExc_TypeError, "Only 3 String args permitted");
2610 str = python_as_string(a, &s);
2617 if (ci->str == NULL)
2621 } else if (PyLong_Check(a)) {
2623 ci->num = PyLong_AsLong(a);
2625 } else if (!num2_set) {
2626 ci->num2 = PyLong_AsLong(a);
2629 PyErr_SetString(PyExc_TypeError, "Only 2 Number args permitted");
2632 } else if (PyTuple_Check(a)) {
2633 int n = PyTuple_GET_SIZE(a);
2636 PyErr_SetString(PyExc_TypeError, "Only 2-element tuples permitted");
2639 n1 = PyTuple_GetItem(a, 0);
2640 n2 = PyTuple_GetItem(a, 1);
2641 if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2642 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2646 ci->x = PyLong_AsLong(n1);
2647 ci->y = PyLong_AsLong(n2);
2650 PyErr_SetString(PyExc_TypeError, "Only one tuple permitted");
2653 } else if (PyObject_TypeCheck(a, &CommType)) {
2655 if (ci->comm2 == NULL && c->comm) {
2656 ci->comm2 = command_get(c->comm);
2658 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2661 } else if (PyCallable_Check(a)) {
2662 struct python_command *pc = export_callable(a, NULL);
2664 if (ci->comm2 == NULL)
2667 command_put(&pc->c);
2668 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2672 PyErr_Format(PyExc_TypeError, "Unsupported arg type %d", i);
2676 if (kwds && PyDict_Check(kwds)) {
2677 a = PyDict_GetItemString(kwds, "str1");
2678 if (!a || a == Py_None)
2679 a = PyDict_GetItemString(kwds, "str");
2680 if (a && a != Py_None) {
2681 if (*s1 || ci->str) {
2682 PyErr_SetString(PyExc_TypeError,
2683 "'str' given with other strings");
2686 if (!PyUnicode_Check(a)) {
2687 PyErr_SetString(PyExc_TypeError,
2688 "'str' must be string or unicode");
2691 ci->str = python_as_string(a, s1);
2693 a = PyDict_GetItemString(kwds, "str2");
2694 if (a && a != Py_None) {
2695 if (*s2 || ci->str2) {
2696 PyErr_SetString(PyExc_TypeError,
2697 "'str2' given with 2 strings");
2700 if (!PyUnicode_Check(a)) {
2701 PyErr_SetString(PyExc_TypeError,
2702 "'str2' must be string or unicode");
2705 ci->str2 = python_as_string(a, s2);
2707 a = PyDict_GetItemString(kwds, "mark");
2708 if (a && a != Py_None) {
2710 PyErr_SetString(PyExc_TypeError,
2711 "'mark' given with other marks");
2714 if (!PyObject_TypeCheck(a, &MarkType)) {
2715 PyErr_SetString(PyExc_TypeError,
2716 "'mark' must be an edlib.Mark");
2719 ci->mark = ((Mark*)a)->mark;
2721 a = PyDict_GetItemString(kwds, "mark2");
2722 if (a && a != Py_None) {
2724 PyErr_SetString(PyExc_TypeError,
2725 "'mark2' given with 2 other marks");
2728 if (!PyObject_TypeCheck(a, &MarkType)) {
2729 PyErr_SetString(PyExc_TypeError,
2730 "'mark2' must be an edlib.Mark");
2733 ci->mark2 = ((Mark*)a)->mark;
2735 a = PyDict_GetItemString(kwds, "num");
2738 PyErr_SetString(PyExc_TypeError,
2739 "'num' given with other numbers");
2742 if (!PyLong_Check(a)) {
2743 PyErr_SetString(PyExc_TypeError,
2744 "'num' must be an integer");
2747 ci->num = PyLong_AsLong(a);
2750 a = PyDict_GetItemString(kwds, "num2");
2753 PyErr_SetString(PyExc_TypeError,
2754 "'num2' given with 2 other numbers");
2757 if (!PyLong_Check(a)) {
2758 PyErr_SetString(PyExc_TypeError,
2759 "'num2' must be an integer");
2762 ci->num2 = PyLong_AsLong(a);
2765 a = PyDict_GetItemString(kwds, "focus");
2766 if (a && a != Py_None) {
2768 if ((void*)ci->focus) {
2769 PyErr_SetString(PyExc_TypeError,
2770 "'focus' given with other pane");
2773 if (!PyObject_TypeCheck(a, &PaneType)) {
2774 PyErr_SetString(PyExc_TypeError,
2775 "'focus' must be a pane");
2780 ci->focus = p->pane;
2782 PyErr_SetString(PyExc_TypeError, "focus value invalid");
2786 a = PyDict_GetItemString(kwds, "xy");
2787 if (a && a != Py_None) {
2790 PyErr_SetString(PyExc_TypeError,
2791 "'xy' given with other tuple");
2794 if (!PyTuple_Check(a) || PyTuple_GET_SIZE(a) != 2) {
2795 PyErr_SetString(PyExc_TypeError,
2796 "'xy' must be a tuple of 2 integers");
2799 n1 = PyTuple_GetItem(a, 0);
2800 n2 = PyTuple_GetItem(a, 1);
2801 if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2802 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2805 ci->x = PyLong_AsLong(n1);
2806 ci->y = PyLong_AsLong(n2);
2809 a = PyDict_GetItemString(kwds, "comm2");
2810 if (a && a != Py_None) {
2812 PyErr_SetString(PyExc_TypeError,
2813 "'comm2' given with other command");
2816 if (PyObject_TypeCheck(a, &CommType)) {
2819 ci->comm2 = command_get(c->comm);
2821 PyErr_SetString(PyExc_TypeError, "comm2 value invalid");
2824 } else if (PyCallable_Check(a)) {
2825 struct python_command *pc = export_callable(a, NULL);
2829 PyErr_SetString(PyExc_TypeError,
2830 "'comm2' must be a callable");
2835 if (!(void*)ci->key) {
2836 PyErr_SetString(PyExc_TypeError, "No key specified");
2839 if (!(void*)ci->home) {
2840 PyErr_SetString(PyExc_TypeError, "No pane specified");
2843 if (!(void*)ci->focus)
2844 ci->focus = ci->home;
2849 static PyObject *py_time_start(PyObject *self, PyObject *args)
2852 int ret = PyArg_ParseTuple(args, "i", &type);
2862 static PyObject *py_time_stop(PyObject *self, PyObject *args)
2865 int ret = PyArg_ParseTuple(args, "i", &type);
2875 static PyObject *py_LOG(PyObject *self, PyObject *args)
2877 int argc = PySequence_Length(args);
2882 for (i = 0; i < argc && l < (int)sizeof(buf) - 2; i++) {
2883 PyObject *o = PySequence_GetItem(args, i);
2884 PyObject *s, *tofree = NULL;
2890 s = PyObject_Str(o);
2894 str = python_as_string(s, &tofree);
2895 slen = str ? strlen(str) : 0;
2896 if (slen + l + 2 > sizeof(buf))
2897 slen = sizeof(buf) - l - 2;
2901 strncpy(buf+l, str, slen);
2914 static PyObject *py_LOG_BT(PyObject *self, PyObject *args)
2921 static const PyMethodDef edlib_methods[] = {
2922 {"time_start", py_time_start, METH_VARARGS,
2923 "Record start time"},
2924 {"time_stop", py_time_stop, METH_VARARGS,
2925 "Record stop time"},
2926 {"LOG", py_LOG, METH_VARARGS,
2927 "Generate log message"},
2928 {"LOG_BT", py_LOG_BT, METH_NOARGS,
2929 "Generate backtrace message"},
2930 {NULL, NULL, 0, NULL}
2933 /* This must be visible when the module is loaded so it
2934 * cannot be static. sparse doesn't like variables that are
2935 * neither extern nor static. So mark it extern
2937 extern char *edlib_module_path;
2938 char *edlib_module_path;
2940 void edlib_init(struct pane *ed safe)
2944 char *argv[2]= { "edlib", NULL };
2945 sighandler_t sigint;
2947 if (edlib_module_path)
2948 module_dir = strdup(edlib_module_path);
2952 /* de-register SIGINT while we initialise python,
2953 * so that Python thinks that it's registration is
2954 * valid - so PyErr_SetInterrupt() don't think there
2957 sigint = signal(SIGINT, SIG_DFL);
2958 PyConfig_InitPythonConfig(&config);
2959 config.isolated = 1;
2960 PyConfig_SetBytesArgv(&config, 0, argv);
2961 Py_InitializeFromConfig(&config);
2962 PyConfig_Clear(&config);
2963 signal(SIGINT, sigint);
2965 PaneType.tp_new = PyType_GenericNew;
2966 PaneIterType.tp_new = PyType_GenericNew;
2967 DocType.tp_new = PyType_GenericNew;
2968 MarkType.tp_new = PyType_GenericNew;
2969 CommType.tp_new = PyType_GenericNew;
2970 if (PyType_Ready(&PaneType) < 0 ||
2971 PyType_Ready(&PaneIterType) < 0 ||
2972 PyType_Ready(&DocType) < 0 ||
2973 PyType_Ready(&MarkType) < 0 ||
2974 PyType_Ready(&CommType) < 0)
2977 m = PyImport_AddModule("edlib");
2983 PyModule_SetDocString(m , "edlib - one more editor is never enough");
2985 PyModule_AddFunctions(m, (PyMethodDef*)edlib_methods);
2986 PyModule_AddObject(m, "editor", Pane_Frompane(ed));
2987 PyModule_AddObject(m, "Pane", (PyObject *)&PaneType);
2988 PyModule_AddObject(m, "PaneIter", (PyObject *)&PaneIterType);
2989 PyModule_AddObject(m, "Mark", (PyObject *)&MarkType);
2990 PyModule_AddObject(m, "Comm", (PyObject *)&CommType);
2991 PyModule_AddObject(m, "Doc", (PyObject *)&DocType);
2992 PyModule_AddIntMacro(m, DAMAGED_CHILD);
2993 PyModule_AddIntMacro(m, DAMAGED_SIZE);
2994 PyModule_AddIntMacro(m, DAMAGED_VIEW);
2995 PyModule_AddIntMacro(m, DAMAGED_REFRESH);
2996 PyModule_AddIntMacro(m, DAMAGED_POSTORDER);
2997 PyModule_AddIntMacro(m, DAMAGED_CLOSED);
2998 PyModule_AddIntMacro(m, Efallthrough);
2999 PyModule_AddIntMacro(m, Enoarg);
3000 PyModule_AddIntMacro(m, Einval);
3001 PyModule_AddIntMacro(m, Efalse);
3002 PyModule_AddIntMacro(m, Efail);
3003 PyModule_AddIntMacro(m, Enosup);
3004 PyModule_AddIntMacro(m, Efail);
3005 PyModule_AddIntMacro(m, NO_NUMERIC);
3007 PyModule_AddIntMacro(m, TIME_KEY);
3008 PyModule_AddIntMacro(m, TIME_WINDOW);
3009 PyModule_AddIntMacro(m, TIME_READ);
3010 PyModule_AddIntMacro(m, TIME_SIG);
3011 PyModule_AddIntMacro(m, TIME_TIMER);
3012 PyModule_AddIntMacro(m, TIME_IDLE);
3013 PyModule_AddIntMacro(m, TIME_REFRESH);
3014 PyModule_AddIntMacro(m, TIME_MISC);
3016 PyModule_AddIntMacro(m, RXLF_ANCHORED);
3017 PyModule_AddIntMacro(m, RXLF_BACKTRACK);
3019 PyModule_AddIntMacro(m, MARK_UNGROUPED);
3020 PyModule_AddIntMacro(m, MARK_POINT);
3022 PyModule_AddIntConstant(m, "WEOF", 0x3FFFFF);
3024 PyModule_AddIntConstant(m, "testing", edlib_testing(ed));
3026 Edlib_CommandFailed = PyErr_NewException("edlib.commandfailed", NULL, NULL);
3027 Py_INCREF(Edlib_CommandFailed);
3028 PyModule_AddObject(m, "commandfailed", Edlib_CommandFailed);
3033 call_comm("global-set-command", ed, &handle_alarm,
3034 0, NULL, "fast-alarm-python");
3036 call_comm("global-set-command", ed, &python_load_module,
3037 0, NULL, "global-load-modules:python");