mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-29 12:14:31 -06:00
f60b6354f8
glib headers should not be included with 'extern "C"'.
243 lines
6.7 KiB
C++
243 lines
6.7 KiB
C++
/********************************************************************
|
|
* qofevent.c -- QOF event handling implementation *
|
|
* Copyright 2000 Dave Peticolas <dave@krondo.com> *
|
|
* Copyright 2006 Neil Williams <linux@codehelp.co.uk> *
|
|
* *
|
|
* 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 "qof.h"
|
|
#include "qofevent-p.h"
|
|
|
|
/* Static Variables ************************************************/
|
|
static guint suspend_counter = 0;
|
|
static gint next_handler_id = 1;
|
|
static guint handler_run_level = 0;
|
|
static guint pending_deletes = 0;
|
|
static GList *handlers = NULL;
|
|
|
|
/* This static indicates the debugging module that this .o belongs to. */
|
|
static QofLogModule log_module = QOF_MOD_ENGINE;
|
|
|
|
/* Implementations *************************************************/
|
|
|
|
static gint
|
|
find_next_handler_id(void)
|
|
{
|
|
HandlerInfo *hi;
|
|
gint handler_id;
|
|
GList *node;
|
|
|
|
/* look for a free handler id */
|
|
handler_id = next_handler_id;
|
|
node = handlers;
|
|
|
|
while (node)
|
|
{
|
|
hi = static_cast<HandlerInfo*>(node->data);
|
|
|
|
if (hi->handler_id == handler_id)
|
|
{
|
|
handler_id++;
|
|
node = handlers;
|
|
continue;
|
|
}
|
|
|
|
node = node->next;
|
|
}
|
|
/* Update id for next registration */
|
|
next_handler_id = handler_id + 1;
|
|
return handler_id;
|
|
}
|
|
|
|
gint
|
|
qof_event_register_handler (QofEventHandler handler, gpointer user_data)
|
|
{
|
|
HandlerInfo *hi;
|
|
gint handler_id;
|
|
|
|
ENTER ("(handler=%p, data=%p)", handler, user_data);
|
|
|
|
/* sanity check */
|
|
if (!handler)
|
|
{
|
|
PERR ("no handler specified");
|
|
return 0;
|
|
}
|
|
|
|
/* look for a free handler id */
|
|
handler_id = find_next_handler_id();
|
|
|
|
/* Found one, add the handler */
|
|
hi = g_new0 (HandlerInfo, 1);
|
|
|
|
hi->handler = handler;
|
|
hi->user_data = user_data;
|
|
hi->handler_id = handler_id;
|
|
|
|
handlers = g_list_prepend (handlers, hi);
|
|
LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
|
|
return handler_id;
|
|
}
|
|
|
|
void
|
|
qof_event_unregister_handler (gint handler_id)
|
|
{
|
|
GList *node;
|
|
|
|
ENTER ("(handler_id=%d)", handler_id);
|
|
for (node = handlers; node; node = node->next)
|
|
{
|
|
HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
|
|
|
|
if (hi->handler_id != handler_id)
|
|
continue;
|
|
|
|
/* Normally, we could actually remove the handler's node from the
|
|
list, but we may be unregistering the event handler as a result
|
|
of a generated event, such as QOF_EVENT_DESTROY. In that case,
|
|
we're in the middle of walking the GList and it is wrong to
|
|
modify the list. So, instead, we just NULL the handler. */
|
|
if (hi->handler)
|
|
LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id,
|
|
hi->handler, hi->user_data);
|
|
|
|
/* safety -- clear the handler in case we're running events now */
|
|
hi->handler = NULL;
|
|
|
|
if (handler_run_level == 0)
|
|
{
|
|
handlers = g_list_remove_link (handlers, node);
|
|
g_list_free_1 (node);
|
|
g_free (hi);
|
|
}
|
|
else
|
|
{
|
|
pending_deletes++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
PERR ("no such handler: %d", handler_id);
|
|
}
|
|
|
|
void
|
|
qof_event_suspend (void)
|
|
{
|
|
suspend_counter++;
|
|
|
|
if (suspend_counter == 0)
|
|
{
|
|
PERR ("suspend counter overflow");
|
|
}
|
|
}
|
|
|
|
void
|
|
qof_event_resume (void)
|
|
{
|
|
if (suspend_counter == 0)
|
|
{
|
|
PERR ("suspend counter underflow");
|
|
return;
|
|
}
|
|
|
|
suspend_counter--;
|
|
}
|
|
|
|
static void
|
|
qof_event_generate_internal (QofInstance *entity, QofEventId event_id,
|
|
gpointer event_data)
|
|
{
|
|
GList *node;
|
|
GList *next_node = NULL;
|
|
|
|
g_return_if_fail(entity);
|
|
|
|
switch (event_id)
|
|
{
|
|
case QOF_EVENT_NONE:
|
|
{
|
|
/* if none, don't log, just return. */
|
|
return;
|
|
}
|
|
}
|
|
|
|
handler_run_level++;
|
|
for (node = handlers; node; node = next_node)
|
|
{
|
|
HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
|
|
|
|
next_node = node->next;
|
|
if (hi->handler)
|
|
{
|
|
PINFO("id=%d hi=%p han=%p data=%p", hi->handler_id, hi,
|
|
hi->handler, event_data);
|
|
hi->handler (entity, event_id, hi->user_data, event_data);
|
|
}
|
|
}
|
|
handler_run_level--;
|
|
|
|
/* If we're the outermost event runner and we have pending deletes
|
|
* then go delete the handlers now.
|
|
*/
|
|
if (handler_run_level == 0 && pending_deletes)
|
|
{
|
|
for (node = handlers; node; node = next_node)
|
|
{
|
|
HandlerInfo *hi = static_cast<HandlerInfo*>(node->data);
|
|
next_node = node->next;
|
|
if (hi->handler == NULL)
|
|
{
|
|
/* remove this node from the list, then free this node */
|
|
handlers = g_list_remove_link (handlers, node);
|
|
g_list_free_1 (node);
|
|
g_free (hi);
|
|
}
|
|
}
|
|
pending_deletes = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
qof_event_force (QofInstance *entity, QofEventId event_id, gpointer event_data)
|
|
{
|
|
if (!entity)
|
|
return;
|
|
|
|
qof_event_generate_internal (entity, event_id, event_data);
|
|
}
|
|
|
|
void
|
|
qof_event_gen (QofInstance *entity, QofEventId event_id, gpointer event_data)
|
|
{
|
|
if (!entity)
|
|
return;
|
|
|
|
if (suspend_counter)
|
|
return;
|
|
|
|
qof_event_generate_internal (entity, event_id, event_data);
|
|
}
|
|
|
|
/* =========================== END OF FILE ======================= */
|