00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdio.h>
00021 #include <string.h>
00022
00023 #include <glib.h>
00024 #include "hook.h"
00025
00026 static GThread * hook_thread;
00027 static GSList *hook_list;
00028
00029 void hook_init (void)
00030 {
00031 hook_thread = g_thread_self ();
00032 }
00033
00034 static Hook *
00035 hook_find(const gchar *name)
00036 {
00037 GSList *list;
00038
00039 for (list = hook_list; list != NULL; list = g_slist_next(list))
00040 {
00041 Hook *hook = (Hook *) list->data;
00042
00043 if (!g_ascii_strcasecmp(hook->name, name))
00044 return hook;
00045 }
00046
00047 return NULL;
00048 }
00049
00050 void
00051 hook_register(const gchar *name)
00052 {
00053 Hook *hook;
00054
00055 g_return_if_fail(name != NULL);
00056
00057 if (hook_find(name) != NULL)
00058 return;
00059
00060 hook = g_new0(Hook, 1);
00061 hook->name = g_strdup(name);
00062 hook->items = NULL;
00063
00064 hook_list = g_slist_append(hook_list, hook);
00065 }
00066
00067 gint
00068 hook_associate(const gchar *name, HookFunction func, gpointer user_data)
00069 {
00070 Hook *hook;
00071 HookItem *hookitem;
00072
00073 g_return_val_if_fail(name != NULL, -1);
00074 g_return_val_if_fail(func != NULL, -1);
00075
00076 hook = hook_find(name);
00077
00078 if (hook == NULL)
00079 {
00080 hook_register(name);
00081 hook = hook_find(name);
00082 }
00083
00084
00085 g_return_val_if_fail(hook != NULL, -1);
00086
00087 hookitem = g_new0(HookItem, 1);
00088 hookitem->func = func;
00089 hookitem->user_data = user_data;
00090
00091 hook->items = g_slist_append(hook->items, hookitem);
00092 return 0;
00093 }
00094
00095 gint
00096 hook_dissociate(const gchar *name, HookFunction func)
00097 {
00098 Hook *hook;
00099 GSList *iter;
00100
00101 g_return_val_if_fail(name != NULL, -1);
00102 g_return_val_if_fail(func != NULL, -1);
00103
00104 hook = hook_find(name);
00105
00106 if (hook == NULL)
00107 return -1;
00108
00109 iter = hook->items;
00110 while (iter != NULL)
00111 {
00112 HookItem *hookitem = (HookItem*)iter->data;
00113 if (hookitem->func == func)
00114 {
00115 hook->items = g_slist_delete_link(hook->items, iter);
00116 g_free( hookitem );
00117 return 0;
00118 }
00119 iter = g_slist_next(iter);
00120 }
00121 return -1;
00122 }
00123
00124 gint
00125 hook_dissociate_full(const gchar *name, HookFunction func, gpointer user_data)
00126 {
00127 Hook *hook;
00128 GSList *iter;
00129
00130 g_return_val_if_fail(name != NULL, -1);
00131 g_return_val_if_fail(func != NULL, -1);
00132
00133 hook = hook_find(name);
00134
00135 if (hook == NULL)
00136 return -1;
00137
00138 iter = hook->items;
00139 while (iter != NULL)
00140 {
00141 HookItem *hookitem = (HookItem*)iter->data;
00142 if (hookitem->func == func && hookitem->user_data == user_data)
00143 {
00144 hook->items = g_slist_delete_link(hook->items, iter);
00145 g_free( hookitem );
00146 return 0;
00147 }
00148 iter = g_slist_next(iter);
00149 }
00150 return -1;
00151 }
00152
00153 void
00154 hook_call(const gchar *name, gpointer hook_data)
00155 {
00156 Hook *hook;
00157 GSList *iter;
00158
00159
00160
00161
00162 if (g_thread_self () != hook_thread)
00163 {
00164 fprintf (stderr, "Warning: Unsafe hook_call of \"%s\" from secondary "
00165 "thread. (Use event_queue instead.)\n", name);
00166 return;
00167 }
00168
00169 hook = hook_find(name);
00170
00171 if (hook == NULL)
00172 return;
00173
00174 for (iter = hook->items; iter != NULL; iter = g_slist_next(iter))
00175 {
00176 HookItem *hookitem = (HookItem*)iter->data;
00177
00178 g_return_if_fail(hookitem->func != NULL);
00179
00180 hookitem->func(hook_data, hookitem->user_data);
00181 }
00182 }