Add manpage for notionflux
[notion/jeffpc.git] / libmainloop / hooks.c
blob3d8a8feac1bddb80de4d71fd801a52e2f62e1ae1
1 /*
2 * ion/mainloop/hooks.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <libtu/types.h>
10 #include <libtu/misc.h>
11 #include <libtu/dlist.h>
12 #include <libtu/output.h>
13 #include <libtu/rb.h>
14 #include <libtu/objp.h>
15 #include <libtu/locale.h>
16 #include <libextl/extl.h>
17 #include "hooks.h"
20 EXTL_EXPORT
21 IMPLCLASS(WHook, Obj, hook_deinit, NULL);
23 static Rb_node named_hooks=NULL;
26 /*{{{ Named hooks */
29 /* If hk==NULL to register, new is attempted to be created. */
30 WHook *mainloop_register_hook(const char *name, WHook *hk)
32 bool created=FALSE;
33 char *nnm;
35 if(hk==NULL)
36 return NULL;
38 if(named_hooks==NULL){
39 named_hooks=make_rb();
40 if(named_hooks==NULL)
41 return NULL;
44 nnm=scopy(name);
46 if(nnm==NULL)
47 return NULL;
49 if(!rb_insert(named_hooks, nnm, hk)){
50 free(nnm);
51 destroy_obj((Obj*)hk);
54 return hk;
58 WHook *mainloop_unregister_hook(const char *name, WHook *hk)
60 bool found=FALSE;
61 Rb_node node;
63 if(named_hooks==NULL)
64 return NULL;
66 if(hk==NULL){
67 assert(name!=NULL);
68 node=rb_find_key_n(named_hooks, name, &found);
69 }else{
70 rb_traverse(node, named_hooks){
71 if((WHook*)rb_val(node)==hk){
72 found=TRUE;
73 break;
78 if(found){
79 hk=(WHook*)rb_val(node);
80 free((char*)node->k.key);
81 rb_delete_node(node);
84 return hk;
88 /*EXTL_DOC
89 * Find named hook \var{name}.
91 EXTL_SAFE
92 EXTL_EXPORT
93 WHook *mainloop_get_hook(const char *name)
95 if(name==NULL)
96 return NULL;
98 if(named_hooks!=NULL){
99 bool found=FALSE;
100 Rb_node node=rb_find_key_n(named_hooks, name, &found);
101 if(found)
102 return (WHook*)rb_val(node);
105 return NULL;
109 /*}}}*/
112 /*{{{ Init/deinit */
115 static void destroy_item(WHook *hk, WHookItem *item)
117 if(item->fn==NULL)
118 extl_unref_fn(item->efn);
119 UNLINK_ITEM(hk->items, item, next, prev);
120 free(item);
124 static WHookItem *create_item(WHook *hk)
126 WHookItem *item=ALLOC(WHookItem);
127 if(item!=NULL){
128 LINK_ITEM_FIRST(hk->items, item, next, prev);
129 item->fn=NULL;
130 item->efn=extl_fn_none();
133 return item;
137 bool hook_init(WHook *hk)
139 hk->items=NULL;
140 return TRUE;
144 WHook *create_hook()
146 CREATEOBJ_IMPL(WHook, hook, (p));
150 void hook_deinit(WHook *hk)
152 mainloop_unregister_hook(NULL, hk);
153 while(hk->items!=NULL)
154 destroy_item(hk, hk->items);
158 /*}}}*/
161 /*{{{ Find/add/remove */
164 WHookItem *hook_find(WHook *hk, WHookDummy *fn)
166 WHookItem *hi;
168 for(hi=hk->items; hi!=NULL; hi=hi->next){
169 if(hi->fn==fn)
170 return hi;
173 return NULL;
177 WHookItem *hook_find_extl(WHook *hk, ExtlFn efn)
179 WHookItem *hi;
181 for(hi=hk->items; hi!=NULL; hi=hi->next){
182 if(extl_fn_eq(hi->efn, efn))
183 return hi;
186 return NULL;
190 /*EXTL_DOC
191 * Is \var{fn} hooked to hook \var{hk}?
193 EXTL_SAFE
194 EXTL_EXPORT_MEMBER
195 bool hook_listed(WHook *hk, ExtlFn efn)
197 return hook_find_extl(hk, efn)!=NULL;
201 bool hook_add(WHook *hk, WHookDummy *fn)
203 WHookItem *item;
205 if(hook_find(hk, fn))
206 return FALSE;
208 item=create_item(hk);
209 if(item==NULL)
210 return FALSE;
211 item->fn=fn;
212 return TRUE;
216 /*EXTL_DOC
217 * Add \var{efn} to the list of functions to be called when the
218 * hook \var{hk} is triggered.
220 EXTL_EXPORT_AS(WHook, add)
221 bool hook_add_extl(WHook *hk, ExtlFn efn)
223 WHookItem *item;
225 if(efn==extl_fn_none()){
226 warn(TR("No function given."));
227 return FALSE;
230 if(hook_find_extl(hk, efn))
231 return FALSE;
233 item=create_item(hk);
235 if(item==NULL)
236 return FALSE;
238 item->efn=extl_ref_fn(efn);
240 return TRUE;
244 bool hook_remove(WHook *hk, WHookDummy *fn)
246 WHookItem *item=hook_find(hk, fn);
247 if(item!=NULL)
248 destroy_item(hk, item);
249 return (item!=NULL);
253 /*EXTL_DOC
254 * Remove \var{efn} from the list of functions to be called when the
255 * hook \var{hk} is triggered.
257 EXTL_EXPORT_AS(WHook, remove)
258 bool hook_remove_extl(WHook *hk, ExtlFn efn)
260 WHookItem *item=hook_find_extl(hk, efn);
261 if(item!=NULL)
262 destroy_item(hk, item);
263 return (item!=NULL);
267 /*}}}*/
270 /*{{{ Basic marshallers */
273 static bool marshall_v(WHookDummy *fn, void *param)
275 fn();
276 return TRUE;
280 static bool marshall_extl_v(ExtlFn fn, void *param)
282 extl_call(fn, NULL, NULL);
283 return TRUE;
287 static bool marshall_o(WHookDummy *fn, void *param)
289 fn((Obj*)param);
290 return TRUE;
294 static bool marshall_extl_o(ExtlFn fn, void *param)
296 return extl_call(fn, "o", NULL, (Obj*)param);
300 static bool marshall_p(WHookDummy *fn, void *param)
302 fn(param);
303 return TRUE;
307 static bool marshall_alt_v(bool (*fn)(), void *param)
309 return fn();
313 static bool marshall_extl_alt_v(ExtlFn fn, void *param)
315 bool ret=FALSE;
316 extl_call(fn, NULL, "b", &ret);
317 return ret;
321 static bool marshall_alt_o(bool (*fn)(), void *param)
323 return fn((Obj*)param);
327 static bool marshall_extl_alt_o(ExtlFn fn, void *param)
329 bool ret=FALSE;
330 extl_call(fn, "o", "b", (Obj*)param, &ret);
331 return ret;
335 static bool marshall_alt_p(bool (*fn)(), void *param)
337 return fn(param);
341 /*}}}*/
344 /*{{{ Call */
347 void hook_call(const WHook *hk, void *p,
348 WHookMarshall *m, WHookMarshallExtl *em)
350 WHookItem *hi, *next;
352 for(hi=hk->items; hi!=NULL; hi=next){
353 next=hi->next;
354 if(hi->fn!=NULL)
355 m(hi->fn, p);
356 else if(em!=NULL)
357 em(hi->efn, p);
362 bool hook_call_alt(const WHook *hk, void *p,
363 WHookMarshall *m, WHookMarshallExtl *em)
365 WHookItem *hi, *next;
366 bool ret=FALSE;
368 for(hi=hk->items; hi!=NULL; hi=next){
369 next=hi->next;
370 if(hi->fn!=NULL)
371 ret=m(hi->fn, p);
372 else if(em!=NULL)
373 ret=em(hi->efn, p);
374 if(ret)
375 break;
378 return ret;
382 void hook_call_v(const WHook *hk)
384 hook_call(hk, NULL, marshall_v, marshall_extl_v);
388 void hook_call_o(const WHook *hk, Obj *o)
390 hook_call(hk, o, marshall_o, marshall_extl_o);
394 void hook_call_p(const WHook *hk, void *p, WHookMarshallExtl *em)
396 hook_call(hk, p, marshall_p, em);
400 bool hook_call_alt_v(const WHook *hk)
402 return hook_call_alt(hk, NULL, (WHookMarshall*)marshall_alt_v,
403 (WHookMarshallExtl*)marshall_extl_alt_v);
407 bool hook_call_alt_o(const WHook *hk, Obj *o)
409 return hook_call_alt(hk, o, (WHookMarshall*)marshall_alt_o,
410 (WHookMarshallExtl*)marshall_extl_alt_o);
414 bool hook_call_alt_p(const WHook *hk, void *p, WHookMarshallExtl *em)
416 return hook_call_alt(hk, p, (WHookMarshall*)marshall_alt_p, em);
420 /*}}}*/