mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-25 18:30:23 -06:00
b1ba16c33b
This required the addition of an extra parameter to gnc_hook_add_dangler to allow the scm hooks to unprotect the scm data on hook destruction.
232 lines
6.4 KiB
C
232 lines
6.4 KiB
C
/*
|
|
* gnc-hooks.c -- helpers for using Glib hook functions
|
|
* Copyright (C) 2005 David Hampton <hampton@employees.org>
|
|
* Derek Atkins <derek@ihtfp.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, contact:
|
|
*
|
|
* Free Software Foundation Voice: +1-617-542-5942
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <glib.h>
|
|
#include <stdio.h>
|
|
#include "gnc-hooks.h"
|
|
#include "gnc-engine.h"
|
|
|
|
static QofLogModule log_module = GNC_MOD_ENGINE;
|
|
|
|
static GHashTable* gnc_hooks_list = NULL;
|
|
static gboolean gnc_hooks_initialized = FALSE;
|
|
|
|
typedef struct
|
|
{
|
|
gchar *desc;
|
|
GHookList *danglers;
|
|
gint num_args;
|
|
} GncHook;
|
|
|
|
|
|
gchar *
|
|
gnc_hook_create (const gchar *name, gint num_args, const gchar *desc)
|
|
{
|
|
GncHook *hook_list;
|
|
|
|
g_return_val_if_fail(name != NULL, NULL);
|
|
g_return_val_if_fail(num_args <= 1, NULL);
|
|
g_return_val_if_fail(desc != NULL, NULL);
|
|
|
|
ENTER("name %s", name);
|
|
if (gnc_hooks_list == NULL)
|
|
{
|
|
gnc_hooks_list = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
/* If we're not initialized then initialize now */
|
|
if (!gnc_hooks_initialized)
|
|
gnc_hooks_init();
|
|
}
|
|
|
|
hook_list = g_hash_table_lookup(gnc_hooks_list, name);
|
|
if (hook_list)
|
|
{
|
|
LEAVE("List %s(%p) already exists", name, hook_list);
|
|
return((gchar*)name);
|
|
}
|
|
|
|
hook_list = g_new0(GncHook, 1);
|
|
hook_list->desc = g_strdup(desc);
|
|
hook_list->danglers = g_malloc(sizeof(GHookList));
|
|
g_hook_list_init(hook_list->danglers, sizeof(GHook));
|
|
hook_list->num_args = num_args;
|
|
g_hash_table_insert(gnc_hooks_list, (gchar *)name, hook_list);
|
|
|
|
LEAVE("created list %s(%p)", name, hook_list);
|
|
return (gchar *)name;
|
|
}
|
|
|
|
static GncHook *
|
|
gnc_hook_lookup (const gchar *name)
|
|
{
|
|
GncHook *hook;
|
|
|
|
ENTER("name %s", name);
|
|
if (gnc_hooks_list == NULL)
|
|
{
|
|
PINFO("no hook lists");
|
|
gnc_hooks_init();
|
|
}
|
|
|
|
hook = g_hash_table_lookup(gnc_hooks_list, name);
|
|
LEAVE("hook list %p", hook);
|
|
return(hook);
|
|
}
|
|
|
|
int
|
|
gnc_hook_num_args (const gchar *name)
|
|
{
|
|
GncHook *hook;
|
|
int num_args = -1;
|
|
|
|
ENTER("name %s", name);
|
|
if (gnc_hooks_list == NULL)
|
|
{
|
|
PINFO("no hook lists");
|
|
gnc_hooks_init();
|
|
}
|
|
|
|
hook = g_hash_table_lookup(gnc_hooks_list, name);
|
|
if (hook)
|
|
num_args = hook->num_args;
|
|
LEAVE("hook list %p, num_args %i", hook, num_args);
|
|
return(num_args);
|
|
}
|
|
|
|
void
|
|
gnc_hook_add_dangler (const gchar *name, GFunc callback,
|
|
GDestroyNotify destroy, gpointer cb_arg)
|
|
{
|
|
GncHook *gnc_hook;
|
|
GHook *hook;
|
|
|
|
ENTER("list %s, function %p, cbarg %p", name, callback, cb_arg);
|
|
gnc_hook = gnc_hook_lookup(name);
|
|
g_return_if_fail(gnc_hook != NULL);
|
|
hook = g_hook_alloc(gnc_hook->danglers);
|
|
hook->func = callback;
|
|
hook->data = cb_arg;
|
|
hook->destroy = destroy;
|
|
g_hook_append(gnc_hook->danglers, hook);
|
|
LEAVE("");
|
|
}
|
|
|
|
void
|
|
gnc_hook_remove_dangler (const gchar *name, GFunc callback)
|
|
{
|
|
GncHook *gnc_hook;
|
|
GHook *hook;
|
|
|
|
ENTER("name %s, function %p", name, callback);
|
|
gnc_hook = gnc_hook_lookup(name);
|
|
if (gnc_hook == NULL)
|
|
{
|
|
LEAVE("Unknown hook list %s", name);
|
|
return;
|
|
}
|
|
|
|
hook = g_hook_find_func(gnc_hook->danglers, TRUE, callback);
|
|
if (hook == NULL)
|
|
{
|
|
LEAVE("Hook %p not found in %s", callback, name);
|
|
return;
|
|
}
|
|
|
|
g_hook_destroy_link(gnc_hook->danglers, hook);
|
|
LEAVE("Removed %p from %s", hook, name);
|
|
}
|
|
|
|
static void
|
|
call_hook (GHook *hook, gpointer data)
|
|
{
|
|
ENTER("hook %p (func %p), data %p, cbarg %p", hook, hook->func, data,
|
|
hook->data);
|
|
((GFunc)hook->func)(data, hook->data);
|
|
LEAVE("");
|
|
}
|
|
|
|
void
|
|
gnc_hook_run (const gchar *name, gpointer data)
|
|
{
|
|
GncHook *hook;
|
|
|
|
ENTER("list %s, data %p", (name == NULL ? "(null)" : name), data);
|
|
hook = gnc_hook_lookup(name);
|
|
if (!hook)
|
|
{
|
|
LEAVE("No such hook list");
|
|
return;
|
|
}
|
|
g_hook_list_marshal(hook->danglers, TRUE, call_hook, data);
|
|
LEAVE("");
|
|
}
|
|
|
|
void
|
|
gnc_hooks_init(void)
|
|
{
|
|
ENTER("");
|
|
|
|
if (gnc_hooks_initialized)
|
|
{
|
|
LEAVE("Hooks already initialized");
|
|
return;
|
|
}
|
|
|
|
gnc_hooks_initialized = TRUE;
|
|
|
|
gnc_hook_create(HOOK_STARTUP, 0,
|
|
"Functions to run at startup. Hook args: ()");
|
|
gnc_hook_create(HOOK_SHUTDOWN, 0,
|
|
"Functions to run at guile shutdown. Hook args: ()");
|
|
gnc_hook_create(HOOK_UI_STARTUP, 0,
|
|
"Functions to run when the ui comes up. Hook args: ()");
|
|
gnc_hook_create(HOOK_UI_POST_STARTUP, 0,
|
|
"Functions to run after the ui comes up. Hook args: ()");
|
|
gnc_hook_create(HOOK_UI_SHUTDOWN, 0,
|
|
"Functions to run at ui shutdown. Hook args: ()");
|
|
gnc_hook_create(HOOK_NEW_BOOK, 0,
|
|
"Run after a new (empty) book is opened, before the"
|
|
" book-opened-hook. Hook args: ()");
|
|
gnc_hook_create(HOOK_REPORT, 0,
|
|
"Run just before the reports are pushed into the menus."
|
|
" Hook args: ()");
|
|
gnc_hook_create(HOOK_CURRENCY_CHANGED, 0,
|
|
"Functions to run when the user changes currency settings. Hook args: ()");
|
|
gnc_hook_create(HOOK_SAVE_OPTIONS, 0,
|
|
"Functions to run when saving options. Hook args: ()");
|
|
gnc_hook_create(HOOK_ADD_EXTENSION, 0,
|
|
"Functions to run when the extensions menu is created."
|
|
" Hook args: ()");
|
|
|
|
gnc_hook_create(HOOK_BOOK_OPENED, 1,
|
|
"Run after book open. Hook args: <gnc:Session*>.");
|
|
gnc_hook_create(HOOK_BOOK_CLOSED, 1,
|
|
"Run before file close. Hook args: <gnc:Session*>");
|
|
gnc_hook_create(HOOK_BOOK_SAVED, 1,
|
|
"Run after file saved. Hook args: <gnc:Session*>");
|
|
|
|
LEAVE("");
|
|
}
|