Line data Source code
1 : /*
2 : * gnc-hooks.c -- helpers for using Glib hook functions
3 : * Copyright (C) 2005 David Hampton <hampton@employees.org>
4 : * Derek Atkins <derek@ihtfp.com>
5 : *
6 : * This program is free software; you can redistribute it and/or
7 : * modify it under the terms of the GNU General Public License as
8 : * published by the Free Software Foundation; either version 2 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU General Public License
17 : * along with this program; if not, contact:
18 : *
19 : * Free Software Foundation Voice: +1-617-542-5942
20 : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
21 : * Boston, MA 02110-1301, USA gnu@gnu.org
22 : */
23 :
24 : #include <config.h>
25 :
26 : #include <glib.h>
27 : #include <stdio.h>
28 : #include "gnc-hooks.h"
29 : #include "gnc-engine.h"
30 :
31 : static QofLogModule log_module = GNC_MOD_ENGINE;
32 :
33 : static GHashTable* gnc_hooks_list = NULL;
34 : static gboolean gnc_hooks_initialized = FALSE;
35 :
36 : typedef struct
37 : {
38 : gchar *desc;
39 : GHookList *danglers;
40 : gint num_args;
41 : } GncHook;
42 :
43 :
44 : gchar *
45 442 : gnc_hook_create (const gchar *name, gint num_args, const gchar *desc)
46 : {
47 : GncHook *hook_list;
48 :
49 442 : g_return_val_if_fail(name != NULL, NULL);
50 442 : g_return_val_if_fail(num_args <= 1, NULL);
51 442 : g_return_val_if_fail(desc != NULL, NULL);
52 :
53 442 : ENTER("name %s", name);
54 442 : if (gnc_hooks_list == NULL)
55 : {
56 34 : gnc_hooks_list = g_hash_table_new(g_str_hash, g_str_equal);
57 :
58 : /* If we're not initialized then initialize now */
59 34 : if (!gnc_hooks_initialized)
60 0 : gnc_hooks_init();
61 : }
62 :
63 442 : hook_list = g_hash_table_lookup(gnc_hooks_list, name);
64 442 : if (hook_list)
65 : {
66 0 : LEAVE("List %s(%p) already exists", name, hook_list);
67 0 : return((gchar*)name);
68 : }
69 :
70 442 : hook_list = g_new0(GncHook, 1);
71 442 : hook_list->desc = g_strdup(desc);
72 442 : hook_list->danglers = g_malloc(sizeof(GHookList));
73 442 : g_hook_list_init(hook_list->danglers, sizeof(GHook));
74 442 : hook_list->num_args = num_args;
75 442 : g_hash_table_insert(gnc_hooks_list, (gchar *)name, hook_list);
76 :
77 442 : LEAVE("created list %s(%p)", name, hook_list);
78 442 : return (gchar *)name;
79 : }
80 :
81 : static GncHook *
82 37 : gnc_hook_lookup (const gchar *name)
83 : {
84 : GncHook *hook;
85 :
86 37 : ENTER("name %s", name);
87 37 : if (gnc_hooks_list == NULL)
88 : {
89 3 : PINFO("no hook lists");
90 3 : gnc_hooks_init();
91 : }
92 :
93 37 : hook = g_hash_table_lookup(gnc_hooks_list, name);
94 37 : LEAVE("hook list %p", hook);
95 37 : return(hook);
96 : }
97 :
98 : int
99 31 : gnc_hook_num_args (const gchar *name)
100 : {
101 : GncHook *hook;
102 31 : int num_args = -1;
103 :
104 31 : ENTER("name %s", name);
105 31 : if (gnc_hooks_list == NULL)
106 : {
107 31 : PINFO("no hook lists");
108 31 : gnc_hooks_init();
109 : }
110 :
111 31 : hook = g_hash_table_lookup(gnc_hooks_list, name);
112 31 : if (hook)
113 31 : num_args = hook->num_args;
114 31 : LEAVE("hook list %p, num_args %i", hook, num_args);
115 31 : return(num_args);
116 : }
117 :
118 : void
119 34 : gnc_hook_add_dangler (const gchar *name, GFunc callback,
120 : GDestroyNotify destroy, gpointer cb_arg)
121 : {
122 : GncHook *gnc_hook;
123 : GHook *hook;
124 :
125 34 : ENTER("list %s, function %p, cbarg %p", name, callback, cb_arg);
126 34 : gnc_hook = gnc_hook_lookup(name);
127 34 : g_return_if_fail(gnc_hook != NULL);
128 34 : hook = g_hook_alloc(gnc_hook->danglers);
129 34 : hook->func = callback;
130 34 : hook->data = cb_arg;
131 34 : hook->destroy = destroy;
132 34 : g_hook_append(gnc_hook->danglers, hook);
133 34 : LEAVE("");
134 : }
135 :
136 : void
137 0 : gnc_hook_remove_dangler (const gchar *name, GFunc callback)
138 : {
139 : GncHook *gnc_hook;
140 : GHook *hook;
141 :
142 0 : ENTER("name %s, function %p", name, callback);
143 0 : gnc_hook = gnc_hook_lookup(name);
144 0 : if (gnc_hook == NULL)
145 : {
146 0 : LEAVE("Unknown hook list %s", name);
147 0 : return;
148 : }
149 :
150 0 : hook = g_hook_find_func(gnc_hook->danglers, TRUE, callback);
151 0 : if (hook == NULL)
152 : {
153 0 : LEAVE("Hook %p not found in %s", callback, name);
154 0 : return;
155 : }
156 :
157 0 : g_hook_destroy_link(gnc_hook->danglers, hook);
158 0 : LEAVE("Removed %p from %s", hook, name);
159 : }
160 :
161 : static void
162 0 : call_hook (GHook *hook, gpointer data)
163 : {
164 0 : ENTER("hook %p (func %p), data %p, cbarg %p", hook, hook->func, data,
165 : hook->data);
166 0 : ((GFunc)hook->func)(data, hook->data);
167 0 : LEAVE("");
168 0 : }
169 :
170 : void
171 3 : gnc_hook_run (const gchar *name, gpointer data)
172 : {
173 : GncHook *hook;
174 :
175 3 : ENTER("list %s, data %p", (name == NULL ? "(null)" : name), data);
176 3 : hook = gnc_hook_lookup(name);
177 3 : if (!hook)
178 : {
179 0 : LEAVE("No such hook list");
180 0 : return;
181 : }
182 3 : g_hook_list_marshal(hook->danglers, TRUE, call_hook, data);
183 3 : LEAVE("");
184 : }
185 :
186 : void
187 34 : gnc_hooks_init(void)
188 : {
189 34 : ENTER("");
190 :
191 34 : if (gnc_hooks_initialized)
192 : {
193 0 : LEAVE("Hooks already initialized");
194 0 : return;
195 : }
196 :
197 34 : gnc_hooks_initialized = TRUE;
198 :
199 34 : gnc_hook_create(HOOK_STARTUP, 0,
200 : "Functions to run at startup. Hook args: ()");
201 34 : gnc_hook_create(HOOK_SHUTDOWN, 0,
202 : "Functions to run at guile shutdown. Hook args: ()");
203 34 : gnc_hook_create(HOOK_UI_STARTUP, 0,
204 : "Functions to run when the ui comes up. Hook args: ()");
205 34 : gnc_hook_create(HOOK_UI_POST_STARTUP, 0,
206 : "Functions to run after the ui comes up. Hook args: ()");
207 34 : gnc_hook_create(HOOK_UI_SHUTDOWN, 0,
208 : "Functions to run at ui shutdown. Hook args: ()");
209 34 : gnc_hook_create(HOOK_NEW_BOOK, 0,
210 : "Run after a new (empty) book is opened, before the"
211 : " book-opened-hook. Hook args: ()");
212 34 : gnc_hook_create(HOOK_REPORT, 0,
213 : "Run just before the reports are pushed into the menus."
214 : " Hook args: ()");
215 34 : gnc_hook_create(HOOK_CURRENCY_CHANGED, 0,
216 : "Functions to run when the user changes currency settings. Hook args: ()");
217 34 : gnc_hook_create(HOOK_SAVE_OPTIONS, 0,
218 : "Functions to run when saving options. Hook args: ()");
219 34 : gnc_hook_create(HOOK_ADD_EXTENSION, 0,
220 : "Functions to run when the extensions menu is created."
221 : " Hook args: ()");
222 :
223 34 : gnc_hook_create(HOOK_BOOK_OPENED, 1,
224 : "Run after book open. Hook args: <gnc:Session*>.");
225 34 : gnc_hook_create(HOOK_BOOK_CLOSED, 1,
226 : "Run before file close. Hook args: <gnc:Session*>");
227 34 : gnc_hook_create(HOOK_BOOK_SAVED, 1,
228 : "Run after file saved. Hook args: <gnc:Session*>");
229 :
230 34 : LEAVE("");
231 : }
|