hooks.c (3291B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2024 the Claws Mail team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <glib.h> 20 21 #include "utils.h" 22 #include "hooks.h" 23 24 static GHashTable *hooklist_table; 25 26 static GHookList *hooks_get_hooklist(const gchar *hooklist_name) 27 { 28 GHookList *hooklist; 29 30 if (hooklist_table == NULL) 31 hooklist_table = g_hash_table_new(g_str_hash, g_str_equal); 32 33 hooklist = (GHookList *) g_hash_table_lookup(hooklist_table, hooklist_name); 34 if (hooklist != NULL) 35 return hooklist; 36 37 hooklist = g_new0(GHookList, 1); 38 g_hook_list_init(hooklist, sizeof(GHook)); 39 g_hash_table_insert(hooklist_table, g_strdup(hooklist_name), hooklist); 40 41 return hooklist; 42 } 43 44 gulong hooks_register_hook(const gchar *hooklist_name, 45 ClawsMailHookFunction hook_func, 46 gpointer userdata) 47 { 48 GHookList *hooklist; 49 GHook *hook; 50 51 cm_return_val_if_fail(hooklist_name != NULL, HOOK_NONE); 52 cm_return_val_if_fail(hook_func != NULL, HOOK_NONE); 53 54 hooklist = hooks_get_hooklist(hooklist_name); 55 cm_return_val_if_fail(hooklist != NULL, HOOK_NONE); 56 57 hook = g_hook_alloc(hooklist); 58 cm_return_val_if_fail(hook != NULL, HOOK_NONE); 59 60 hook->func = hook_func; 61 hook->data = userdata; 62 63 g_hook_append(hooklist, hook); 64 65 debug_print("registered new hook for '%s' as id %lu\n", hooklist_name, hook->hook_id); 66 if (hook->hook_id == HOOK_NONE) 67 g_error("unexpected hook ID 0"); 68 69 return hook->hook_id; 70 } 71 72 void hooks_unregister_hook(const gchar *hooklist_name, 73 gulong hook_id) 74 { 75 GHookList *hooklist; 76 GHook *hook; 77 78 cm_return_if_fail(hooklist_name != NULL); 79 80 hooklist = hooks_get_hooklist(hooklist_name); 81 cm_return_if_fail(hooklist != NULL); 82 83 hook = g_hook_get(hooklist, hook_id); 84 cm_return_if_fail(hook != NULL); 85 86 debug_print("unregistered hook %lu in '%s'\n", hook->hook_id, hooklist_name); 87 88 g_hook_destroy(hooklist, hook_id); 89 } 90 91 struct MarshalData 92 { 93 gpointer source; 94 gboolean abort; 95 }; 96 97 static void hooks_marshal(GHook *hook, gpointer data) 98 { 99 gboolean (*func) (gpointer source, gpointer data); 100 struct MarshalData *marshal_data = (struct MarshalData *)data; 101 102 if (!marshal_data->abort) { 103 func = hook->func; 104 marshal_data->abort = func(marshal_data->source, hook->data); 105 } 106 } 107 108 gboolean hooks_invoke(const gchar *hooklist_name, 109 gpointer source) 110 { 111 GHookList *hooklist; 112 struct MarshalData marshal_data; 113 114 cm_return_val_if_fail(hooklist_name != NULL, FALSE); 115 116 hooklist = hooks_get_hooklist(hooklist_name); 117 cm_return_val_if_fail(hooklist != NULL, FALSE); 118 119 marshal_data.source = source; 120 marshal_data.abort = FALSE; 121 122 g_hook_list_marshal(hooklist, TRUE, hooks_marshal, &marshal_data); 123 124 return marshal_data.abort; 125 }