diff options
| author | Dana Jansens <danakj@orodu.net> | 2003-03-16 21:11:39 +0000 |
|---|---|---|
| committer | Dana Jansens <danakj@orodu.net> | 2003-03-16 21:11:39 +0000 |
| commit | f8a47de5ec444c452093371e3db16857eb39a490 (patch) | |
| tree | 31db2567842d98232775f9980f7a8d2586c0ac71 /c/hooks.c | |
| parent | 8ba0586bcbdc7fe9648f1063812126d71a041670 (diff) | |
merge the C branch into HEAD
Diffstat (limited to 'c/hooks.c')
| -rw-r--r-- | c/hooks.c | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/c/hooks.c b/c/hooks.c new file mode 100644 index 00000000..6bf15d20 --- /dev/null +++ b/c/hooks.c @@ -0,0 +1,285 @@ +#include "hooks.h" +#include <Python.h> +#include <glib.h> + +/* the 'hooks' module and its dictionary */ +static PyObject *hooks = NULL, *hooksdict = NULL; + +/* + * + * Define the type 'Hook' + * + */ +#define IS_HOOK(v) ((v)->ob_type == &HookType) + +staticforward PyTypeObject HookType; + +typedef struct { + PyObject_HEAD + GSList *funcs; +} HookObject; + +static PyObject *create_Hook(PyObject *self, PyObject *args) +{ + HookObject *hook; + char *name; + int ret; + + (void) self; + + if (!PyArg_ParseTuple(args, "s:Hook", &name)) + return NULL; + + hook = PyObject_New(HookObject, &HookType); + hook->funcs = NULL; + + /* add it to the hooks module */ + ret = PyDict_SetItemString(hooksdict, name, (PyObject*) hook); + Py_DECREF(hook); + + if (ret == -1) { + char *s = g_strdup_printf( + "Failed to add the hook '%s' to the 'hooks' module", name); + PyErr_SetString(PyExc_RuntimeError, s); + g_free(s); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static void hook_dealloc(HookObject *self) +{ + GSList *it; + + for (it = self->funcs; it != NULL; it = it->next) + Py_DECREF((PyObject*) it->data); + + PyObject_Del((PyObject*) self); +} + +static PyObject *hook_fire(HookObject *self, PyObject *args) +{ + GSList *it; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'fire' requires a 'Hook' object"); + return NULL; + } + + for (it = self->funcs; it != NULL; it = it->next) { + PyObject *ret = PyObject_CallObject(it->data, args); + if (ret == NULL) + return NULL; + Py_DECREF(ret); + } + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *hook_add(HookObject *self, PyObject *args) +{ + PyObject *func; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'add' requires a 'Hook' object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "O:add", &func)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'add' requires a callable argument"); + return NULL; + } + self->funcs = g_slist_append(self->funcs, func); + Py_INCREF(func); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject *hook_remove(HookObject *self, PyObject *args) +{ + PyObject *func; + GSList *it; + + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'remove' requires a 'Hook' object"); + return NULL; + } + if (!PyArg_ParseTuple(args, "O:remove", &func)) + return NULL; + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'remove' requires a callable argument"); + return NULL; + } + it = g_slist_find(self->funcs, func); + if (it != NULL) { + self->funcs = g_slist_delete_link(self->funcs, it); + Py_DECREF(func); + + Py_INCREF(Py_None); + return Py_None; + } + PyErr_SetString(PyExc_TypeError, + "given callable object was not found in Hook"); + return NULL; +} + +static PyObject *hook_count(HookObject *self, PyObject *args) +{ + if (!IS_HOOK(self)) { + PyErr_SetString(PyExc_TypeError, + "descriptor 'fire' requires a 'Hook' object"); + return NULL; + } + if (!PyArg_ParseTuple(args, ":count")) + return NULL; + + return PyInt_FromLong(g_slist_length(self->funcs)); +} + +static PyTypeObject HookType = { + PyObject_HEAD_INIT(NULL) + 0, + "Hook", + sizeof(HookObject), + 0, + (destructor) hook_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ +}; + +static PyMethodDef HookMethods[] = { + {"fire", (PyCFunction)hook_fire, METH_VARARGS, + "hook.fire() -- Fire the added hook functions for the Hook."}, + {"add", (PyCFunction)hook_add, METH_VARARGS, + "hook.add(func) -- Add a function to the hook." }, + {"remove", (PyCFunction)hook_remove, METH_VARARGS, + "hook.remove(func) -- Remove a function from the hook." }, + {"count", (PyCFunction)hook_count, METH_VARARGS, + "hook.count() -- Return the number of functions in the hook." }, + + { NULL, NULL, 0, NULL } +}; + + +/* + * + * Module initialization/finalization + * + */ + +/* the "events" hook */ +static HookObject *events_hook = NULL, *keyboard_hook = NULL, + *pointer_hook = NULL; + +static PyMethodDef HooksMethods[] = { + {"create", create_Hook, METH_VARARGS, + "hooks.create('name') -- Add a hook called 'name' to the hooks module."}, + + { NULL, NULL, 0, NULL } +}; + +void hooks_startup() +{ + int ret; + + HookType.ob_type = &PyType_Type; + HookType.tp_methods = HookMethods; + PyType_Ready(&HookType); + + Py_InitModule("hooks", HooksMethods); + + /* get the hooks module/dict */ + hooks = PyImport_ImportModule("hooks"); /* new */ + g_assert(hooks != NULL); + hooksdict = PyModule_GetDict(hooks); /* borrowed */ + g_assert(hooksdict != NULL); + + /* create the "events" hook */ + events_hook = PyObject_New(HookObject, &HookType); + events_hook->funcs = NULL; + + /* add it to the hooks module */ + ret = PyDict_SetItemString(hooksdict, "events", (PyObject*) events_hook); + g_assert(ret == 0); + + /* create the "keyboard" hook */ + keyboard_hook = PyObject_New(HookObject, &HookType); + keyboard_hook->funcs = NULL; + + /* add it to the hooks module */ + ret = PyDict_SetItemString(hooksdict, "keyboard", + (PyObject*) keyboard_hook); + g_assert(ret == 0); + + /* create the "pointer" hook */ + pointer_hook = PyObject_New(HookObject, &HookType); + pointer_hook->funcs = NULL; + + /* add it to the hooks module */ + ret = PyDict_SetItemString(hooksdict, "pointer", (PyObject*) pointer_hook); + g_assert(ret == 0); +} + +void hooks_shutdown() +{ + Py_DECREF(pointer_hook); + Py_DECREF(keyboard_hook); + Py_DECREF(events_hook); + Py_DECREF(hooks); +} + +void hooks_fire(EventData *data) +{ + PyObject *ret, *args; + + g_assert(events_hook != NULL); + + args = Py_BuildValue("(O)", data); + ret = hook_fire(events_hook, args); + Py_DECREF(args); + if (ret == NULL) + PyErr_Print(); +} + +void hooks_fire_keyboard(EventData *data) +{ + PyObject *ret, *args; + + g_assert(events_hook != NULL); + + args = Py_BuildValue("(O)", data); + ret = hook_fire(keyboard_hook, args); + Py_DECREF(args); + if (ret == NULL) + PyErr_Print(); +} + +void hooks_fire_pointer(EventData *data) +{ + PyObject *ret, *args; + + g_assert(events_hook != NULL); + + args = Py_BuildValue("(O)", data); + ret = hook_fire(pointer_hook, args); + Py_DECREF(args); + if (ret == NULL) + PyErr_Print(); +} |
