src/pounce.c

branch
cpw.khc.msnp14
changeset 20472
6a6d2ef151e6
parent 13912
463b4fa9f067
parent 20469
b2836a24d81e
child 20473
91e1b3a49d10
--- a/src/pounce.c	Wed Oct 18 16:28:51 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1138 +0,0 @@
-/**
- * @file pounce.c Buddy Pounce API
- * @ingroup core
- *
- * gaim
- *
- * Gaim is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "internal.h"
-#include "conversation.h"
-#include "debug.h"
-#include "pounce.h"
-
-#include "debug.h"
-#include "pounce.h"
-#include "util.h"
-
-typedef struct
-{
-	GString *buffer;
-
-	GaimPounce *pounce;
-	GaimPounceEvent events;
-	GaimPounceOption options;
-
-	char *ui_name;
-	char *pouncee;
-	char *protocol_id;
-	char *event_type;
-	char *option_type;
-	char *action_name;
-	char *param_name;
-	char *account_name;
-
-} PounceParserData;
-
-typedef struct
-{
-	char *name;
-
-	gboolean enabled;
-
-	GHashTable *atts;
-
-} GaimPounceActionData;
-
-typedef struct
-{
-	char *ui;
-	GaimPounceCb cb;
-	void (*new_pounce)(GaimPounce *);
-	void (*free_pounce)(GaimPounce *);
-
-} GaimPounceHandler;
-
-
-static GHashTable *pounce_handlers = NULL;
-static GList      *pounces = NULL;
-static guint       save_timer = 0;
-static gboolean    pounces_loaded = FALSE;
-
-
-/*********************************************************************
- * Private utility functions                                         *
- *********************************************************************/
-
-static GaimPounceActionData *
-find_action_data(const GaimPounce *pounce, const char *name)
-{
-	GaimPounceActionData *action;
-
-	g_return_val_if_fail(pounce != NULL, NULL);
-	g_return_val_if_fail(name   != NULL, NULL);
-
-	action = g_hash_table_lookup(pounce->actions, name);
-
-	return action;
-}
-
-static void
-free_action_data(gpointer data)
-{
-	GaimPounceActionData *action_data = data;
-
-	g_free(action_data->name);
-
-	g_hash_table_destroy(action_data->atts);
-
-	g_free(action_data);
-}
-
-
-/*********************************************************************
- * Writing to disk                                                   *
- *********************************************************************/
-
-static void
-action_parameter_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
-{
-	const char *name, *param_value;
-	xmlnode *node, *child;
-
-	name        = (const char *)key;
-	param_value = (const char *)value;
-	node        = (xmlnode *)user_data;
-
-	child = xmlnode_new_child(node, "param");
-	xmlnode_set_attrib(child, "name", name);
-	xmlnode_insert_data(child, param_value, -1);
-}
-
-static void
-action_parameter_list_to_xmlnode(gpointer key, gpointer value, gpointer user_data)
-{
-	const char *action;
-	GaimPounceActionData *action_data;
-	xmlnode *node, *child;
-
-	action      = (const char *)key;
-	action_data = (GaimPounceActionData *)value;
-	node        = (xmlnode *)user_data;
-
-	if (!action_data->enabled)
-		return;
-
-	child = xmlnode_new_child(node, "action");
-	xmlnode_set_attrib(child, "type", action);
-
-	g_hash_table_foreach(action_data->atts, action_parameter_to_xmlnode, child);
-}
-
-static void
-add_event_to_xmlnode(xmlnode *node, const char *type)
-{
-	xmlnode *child;
-
-	child = xmlnode_new_child(node, "event");
-	xmlnode_set_attrib(child, "type", type);
-}
-
-static void
-add_option_to_xmlnode(xmlnode *node, const char *type)
-{
-	xmlnode *child;
-
-	child = xmlnode_new_child(node, "option");
-	xmlnode_set_attrib(child, "type", type);
-}
-
-static xmlnode *
-pounce_to_xmlnode(GaimPounce *pounce)
-{
-	xmlnode *node, *child;
-	GaimAccount *pouncer;
-	GaimPounceEvent events;
-	GaimPounceOption options;
-
-	pouncer = gaim_pounce_get_pouncer(pounce);
-	events  = gaim_pounce_get_events(pounce);
-	options = gaim_pounce_get_options(pounce);
-
-	node = xmlnode_new("pounce");
-	xmlnode_set_attrib(node, "ui", pounce->ui_type);
-
-	child = xmlnode_new_child(node, "account");
-	xmlnode_set_attrib(child, "protocol", pouncer->protocol_id);
-	xmlnode_insert_data(child, gaim_account_get_username(pouncer), -1);
-
-	child = xmlnode_new_child(node, "pouncee");
-	xmlnode_insert_data(child, gaim_pounce_get_pouncee(pounce), -1);
-
-	/* Write pounce options */
-	child = xmlnode_new_child(node, "options");
-	if (options & GAIM_POUNCE_OPTION_AWAY)
-		add_option_to_xmlnode(child, "on-away");
-
-	/* Write pounce events */
-	child = xmlnode_new_child(node, "events");
-	if (events & GAIM_POUNCE_SIGNON)
-		add_event_to_xmlnode(child, "sign-on");
-	if (events & GAIM_POUNCE_SIGNOFF)
-		add_event_to_xmlnode(child, "sign-off");
-	if (events & GAIM_POUNCE_AWAY)
-		add_event_to_xmlnode(child, "away");
-	if (events & GAIM_POUNCE_AWAY_RETURN)
-		add_event_to_xmlnode(child, "return-from-away");
-	if (events & GAIM_POUNCE_IDLE)
-		add_event_to_xmlnode(child, "idle");
-	if (events & GAIM_POUNCE_IDLE_RETURN)
-		add_event_to_xmlnode(child, "return-from-idle");
-	if (events & GAIM_POUNCE_TYPING)
-		add_event_to_xmlnode(child, "start-typing");
-	if (events & GAIM_POUNCE_TYPED)
-		add_event_to_xmlnode(child, "typed");
-	if (events & GAIM_POUNCE_TYPING_STOPPED)
-		add_event_to_xmlnode(child, "stop-typing");
-	if (events & GAIM_POUNCE_MESSAGE_RECEIVED)
-		add_event_to_xmlnode(child, "message-received");
-
-	/* Write pounce actions */
-	child = xmlnode_new_child(node, "actions");
-	g_hash_table_foreach(pounce->actions, action_parameter_list_to_xmlnode, child);
-
-	if (gaim_pounce_get_save(pounce))
-		child = xmlnode_new_child(node, "save");
-
-	return node;
-}
-
-static xmlnode *
-pounces_to_xmlnode(void)
-{
-	xmlnode *node, *child;
-	GList *cur;
-
-	node = xmlnode_new("pounces");
-	xmlnode_set_attrib(node, "version", "1.0");
-
-	for (cur = gaim_pounces_get_all(); cur != NULL; cur = cur->next)
-	{
-		child = pounce_to_xmlnode(cur->data);
-		xmlnode_insert_child(node, child);
-	}
-
-	return node;
-}
-
-static void
-sync_pounces(void)
-{
-	xmlnode *node;
-	char *data;
-
-	if (!pounces_loaded)
-	{
-		gaim_debug_error("pounce", "Attempted to save buddy pounces before "
-						 "they were read!\n");
-		return;
-	}
-
-	node = pounces_to_xmlnode();
-	data = xmlnode_to_formatted_str(node, NULL);
-	gaim_util_write_data_to_file("pounces.xml", data, -1);
-	g_free(data);
-	xmlnode_free(node);
-}
-
-static gboolean
-save_cb(gpointer data)
-{
-	sync_pounces();
-	save_timer = 0;
-	return FALSE;
-}
-
-static void
-schedule_pounces_save(void)
-{
-	if (save_timer == 0)
-		save_timer = gaim_timeout_add(5000, save_cb, NULL);
-}
-
-
-/*********************************************************************
- * Reading from disk                                                 *
- *********************************************************************/
-
-static void
-free_parser_data(gpointer user_data)
-{
-	PounceParserData *data = user_data;
-
-	if (data->buffer != NULL)
-		g_string_free(data->buffer, TRUE);
-
-	g_free(data->ui_name);
-	g_free(data->pouncee);
-	g_free(data->protocol_id);
-	g_free(data->event_type);
-	g_free(data->option_type);
-	g_free(data->action_name);
-	g_free(data->param_name);
-	g_free(data->account_name);
-
-	g_free(data);
-}
-
-static void
-start_element_handler(GMarkupParseContext *context,
-					  const gchar *element_name,
-					  const gchar **attribute_names,
-					  const gchar **attribute_values,
-					  gpointer user_data, GError **error)
-{
-	PounceParserData *data = user_data;
-	GHashTable *atts;
-	int i;
-
-	atts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-	for (i = 0; attribute_names[i] != NULL; i++) {
-		g_hash_table_insert(atts, g_strdup(attribute_names[i]),
-							g_strdup(attribute_values[i]));
-	}
-
-	if (data->buffer != NULL) {
-		g_string_free(data->buffer, TRUE);
-		data->buffer = NULL;
-	}
-
-	if (!strcmp(element_name, "pounce")) {
-		const char *ui = g_hash_table_lookup(atts, "ui");
-
-		if (ui == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'ui' parameter for pounce!\n");
-		}
-		else
-			data->ui_name = g_strdup(ui);
-
-		data->events = 0;
-	}
-	else if (!strcmp(element_name, "account")) {
-		const char *protocol_id = g_hash_table_lookup(atts, "protocol");
-
-		if (protocol_id == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'protocol' parameter for account!\n");
-		}
-		else
-			data->protocol_id = g_strdup(protocol_id);
-	}
-	else if (!strcmp(element_name, "option")) {
-		const char *type = g_hash_table_lookup(atts, "type");
-
-		if (type == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'type' parameter for option!\n");
-		}
-		else
-			data->option_type = g_strdup(type);
-	}
-	else if (!strcmp(element_name, "event")) {
-		const char *type = g_hash_table_lookup(atts, "type");
-
-		if (type == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'type' parameter for event!\n");
-		}
-		else
-			data->event_type = g_strdup(type);
-	}
-	else if (!strcmp(element_name, "action")) {
-		const char *type = g_hash_table_lookup(atts, "type");
-
-		if (type == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'type' parameter for action!\n");
-		}
-		else
-			data->action_name = g_strdup(type);
-	}
-	else if (!strcmp(element_name, "param")) {
-		const char *param_name = g_hash_table_lookup(atts, "name");
-
-		if (param_name == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Unset 'name' parameter for param!\n");
-		}
-		else
-			data->param_name = g_strdup(param_name);
-	}
-
-	g_hash_table_destroy(atts);
-}
-
-static void
-end_element_handler(GMarkupParseContext *context, const gchar *element_name,
-					gpointer user_data,  GError **error)
-{
-	PounceParserData *data = user_data;
-	gchar *buffer = NULL;
-
-	if (data->buffer != NULL) {
-		buffer = g_string_free(data->buffer, FALSE);
-		data->buffer = NULL;
-	}
-
-	if (!strcmp(element_name, "account")) {
-		g_free(data->account_name);
-		data->account_name = g_strdup(buffer);
-	}
-	else if (!strcmp(element_name, "pouncee")) {
-		g_free(data->pouncee);
-		data->pouncee = g_strdup(buffer);
-	}
-	else if (!strcmp(element_name, "option")) {
-		if (!strcmp(data->option_type, "on-away"))
-			data->options |= GAIM_POUNCE_OPTION_AWAY;
-
-		g_free(data->option_type);
-		data->option_type = NULL;
-	}
-	else if (!strcmp(element_name, "event")) {
-		if (!strcmp(data->event_type, "sign-on"))
-			data->events |= GAIM_POUNCE_SIGNON;
-		else if (!strcmp(data->event_type, "sign-off"))
-			data->events |= GAIM_POUNCE_SIGNOFF;
-		else if (!strcmp(data->event_type, "away"))
-			data->events |= GAIM_POUNCE_AWAY;
-		else if (!strcmp(data->event_type, "return-from-away"))
-			data->events |= GAIM_POUNCE_AWAY_RETURN;
-		else if (!strcmp(data->event_type, "idle"))
-			data->events |= GAIM_POUNCE_IDLE;
-		else if (!strcmp(data->event_type, "return-from-idle"))
-			data->events |= GAIM_POUNCE_IDLE_RETURN;
-		else if (!strcmp(data->event_type, "start-typing"))
-			data->events |= GAIM_POUNCE_TYPING;
-		else if (!strcmp(data->event_type, "typed"))
-			data->events |= GAIM_POUNCE_TYPED;
-		else if (!strcmp(data->event_type, "stop-typing"))
-			data->events |= GAIM_POUNCE_TYPING_STOPPED;
-		else if (!strcmp(data->event_type, "message-received"))
-			data->events |= GAIM_POUNCE_MESSAGE_RECEIVED;
-
-		g_free(data->event_type);
-		data->event_type = NULL;
-	}
-	else if (!strcmp(element_name, "action")) {
-		if (data->pounce != NULL) {
-			gaim_pounce_action_register(data->pounce, data->action_name);
-			gaim_pounce_action_set_enabled(data->pounce, data->action_name, TRUE);
-		}
-
-		g_free(data->action_name);
-		data->action_name = NULL;
-	}
-	else if (!strcmp(element_name, "param")) {
-		if (data->pounce != NULL) {
-			gaim_pounce_action_set_attribute(data->pounce, data->action_name,
-											 data->param_name, buffer);
-		}
-
-		g_free(data->param_name);
-		data->param_name = NULL;
-	}
-	else if (!strcmp(element_name, "events")) {
-		GaimAccount *account;
-
-		account = gaim_accounts_find(data->account_name, data->protocol_id);
-
-		g_free(data->account_name);
-		g_free(data->protocol_id);
-
-		data->account_name = NULL;
-		data->protocol_id  = NULL;
-
-		if (account == NULL) {
-			gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-					   "Account for pounce not found!\n");
-			/*
-			 * This pounce has effectively been removed, so make
-			 * sure that we save the changes to pounces.xml
-			 */
-			schedule_pounces_save();
-		}
-		else {
-			gaim_debug(GAIM_DEBUG_INFO, "pounce",
-					   "Creating pounce: %s, %s\n", data->ui_name,
-					   data->pouncee);
-
-			data->pounce = gaim_pounce_new(data->ui_name, account,
-										   data->pouncee, data->events,
-										   data->options);
-		}
-
-		g_free(data->pouncee);
-		data->pouncee = NULL;
-	}
-	else if (!strcmp(element_name, "save")) {
-		if (data->pounce != NULL)
-			gaim_pounce_set_save(data->pounce, TRUE);
-	}
-	else if (!strcmp(element_name, "pounce")) {
-		data->pounce  = NULL;
-		data->events  = 0;
-		data->options = 0;
-
-		g_free(data->ui_name);
-		g_free(data->pouncee);
-		g_free(data->protocol_id);
-		g_free(data->event_type);
-		g_free(data->option_type);
-		g_free(data->action_name);
-		g_free(data->param_name);
-		g_free(data->account_name);
-
-		data->ui_name      = NULL;
-		data->pounce       = NULL;
-		data->protocol_id  = NULL;
-		data->event_type   = NULL;
-		data->option_type  = NULL;
-		data->action_name  = NULL;
-		data->param_name   = NULL;
-		data->account_name = NULL;
-	}
-
-	if (buffer != NULL)
-		g_free(buffer);
-}
-
-static void
-text_handler(GMarkupParseContext *context, const gchar *text,
-			 gsize text_len, gpointer user_data, GError **error)
-{
-	PounceParserData *data = user_data;
-
-	if (data->buffer == NULL)
-		data->buffer = g_string_new_len(text, text_len);
-	else
-		g_string_append_len(data->buffer, text, text_len);
-}
-
-static GMarkupParser pounces_parser =
-{
-	start_element_handler,
-	end_element_handler,
-	text_handler,
-	NULL,
-	NULL
-};
-
-gboolean
-gaim_pounces_load(void)
-{
-	gchar *filename = g_build_filename(gaim_user_dir(), "pounces.xml", NULL);
-	gchar *contents = NULL;
-	gsize length;
-	GMarkupParseContext *context;
-	GError *error = NULL;
-	PounceParserData *parser_data;
-
-	if (filename == NULL) {
-		pounces_loaded = TRUE;
-		return FALSE;
-	}
-
-	if (!g_file_get_contents(filename, &contents, &length, &error)) {
-		gaim_debug(GAIM_DEBUG_ERROR, "pounce",
-				   "Error reading pounces: %s\n", error->message);
-
-		g_free(filename);
-		g_error_free(error);
-
-		pounces_loaded = TRUE;
-		return FALSE;
-	}
-
-	parser_data = g_new0(PounceParserData, 1);
-
-	context = g_markup_parse_context_new(&pounces_parser, 0,
-										 parser_data, free_parser_data);
-
-	if (!g_markup_parse_context_parse(context, contents, length, NULL)) {
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-
-		pounces_loaded = TRUE;
-
-		return FALSE;
-	}
-
-	if (!g_markup_parse_context_end_parse(context, NULL)) {
-		gaim_debug(GAIM_DEBUG_ERROR, "pounce", "Error parsing %s\n",
-				   filename);
-
-		g_markup_parse_context_free(context);
-		g_free(contents);
-		g_free(filename);
-		pounces_loaded = TRUE;
-
-		return FALSE;
-	}
-
-	g_markup_parse_context_free(context);
-	g_free(contents);
-	g_free(filename);
-
-	pounces_loaded = TRUE;
-
-	return TRUE;
-}
-
-
-GaimPounce *
-gaim_pounce_new(const char *ui_type, GaimAccount *pouncer,
-				const char *pouncee, GaimPounceEvent event,
-				GaimPounceOption option)
-{
-	GaimPounce *pounce;
-	GaimPounceHandler *handler;
-
-	g_return_val_if_fail(ui_type != NULL, NULL);
-	g_return_val_if_fail(pouncer != NULL, NULL);
-	g_return_val_if_fail(pouncee != NULL, NULL);
-	g_return_val_if_fail(event   != 0,    NULL);
-
-	pounce = g_new0(GaimPounce, 1);
-
-	pounce->ui_type  = g_strdup(ui_type);
-	pounce->pouncer  = pouncer;
-	pounce->pouncee  = g_strdup(pouncee);
-	pounce->events   = event;
-	pounce->options  = option;
-
-	pounce->actions  = g_hash_table_new_full(g_str_hash, g_str_equal,
-											 g_free, free_action_data);
-
-	handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
-
-	if (handler != NULL && handler->new_pounce != NULL)
-		handler->new_pounce(pounce);
-
-	pounces = g_list_append(pounces, pounce);
-
-	schedule_pounces_save();
-
-	return pounce;
-}
-
-void
-gaim_pounce_destroy(GaimPounce *pounce)
-{
-	GaimPounceHandler *handler;
-
-	g_return_if_fail(pounce != NULL);
-
-	handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
-
-	pounces = g_list_remove(pounces, pounce);
-
-	g_free(pounce->ui_type);
-	g_free(pounce->pouncee);
-
-	g_hash_table_destroy(pounce->actions);
-
-	if (handler != NULL && handler->free_pounce != NULL)
-		handler->free_pounce(pounce);
-
-	g_free(pounce);
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_destroy_all_by_account(GaimAccount *account)
-{
-	GaimAccount *pouncer;
-	GaimPounce *pounce;
-	GList *l, *l_next;
-
-	g_return_if_fail(account != NULL);
-
-	for (l = gaim_pounces_get_all(); l != NULL; l = l_next)
-	{
-		pounce = (GaimPounce *)l->data;
-		l_next = l->next;
-
-		pouncer = gaim_pounce_get_pouncer(pounce);
-		if (pouncer == account)
-			gaim_pounce_destroy(pounce);
-	}
-}
-
-void
-gaim_pounce_set_events(GaimPounce *pounce, GaimPounceEvent events)
-{
-	g_return_if_fail(pounce != NULL);
-	g_return_if_fail(events != GAIM_POUNCE_NONE);
-
-	pounce->events = events;
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_set_options(GaimPounce *pounce, GaimPounceOption options)
-{
-	g_return_if_fail(pounce  != NULL);
-
-	pounce->options = options;
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_set_pouncer(GaimPounce *pounce, GaimAccount *pouncer)
-{
-	g_return_if_fail(pounce  != NULL);
-	g_return_if_fail(pouncer != NULL);
-
-	pounce->pouncer = pouncer;
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_set_pouncee(GaimPounce *pounce, const char *pouncee)
-{
-	g_return_if_fail(pounce  != NULL);
-	g_return_if_fail(pouncee != NULL);
-
-	g_free(pounce->pouncee);
-
-	pounce->pouncee = (pouncee == NULL ? NULL : g_strdup(pouncee));
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_set_save(GaimPounce *pounce, gboolean save)
-{
-	g_return_if_fail(pounce != NULL);
-
-	pounce->save = save;
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_action_register(GaimPounce *pounce, const char *name)
-{
-	GaimPounceActionData *action_data;
-
-	g_return_if_fail(pounce != NULL);
-	g_return_if_fail(name   != NULL);
-
-	if (g_hash_table_lookup(pounce->actions, name) != NULL)
-		return;
-
-	action_data = g_new0(GaimPounceActionData, 1);
-
-	action_data->name    = g_strdup(name);
-	action_data->enabled = FALSE;
-	action_data->atts    = g_hash_table_new_full(g_str_hash, g_str_equal,
-												 g_free, g_free);
-
-	g_hash_table_insert(pounce->actions, g_strdup(name), action_data);
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_action_set_enabled(GaimPounce *pounce, const char *action,
-							   gboolean enabled)
-{
-	GaimPounceActionData *action_data;
-
-	g_return_if_fail(pounce != NULL);
-	g_return_if_fail(action != NULL);
-
-	action_data = find_action_data(pounce, action);
-
-	g_return_if_fail(action_data != NULL);
-
-	action_data->enabled = enabled;
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_action_set_attribute(GaimPounce *pounce, const char *action,
-								 const char *attr, const char *value)
-{
-	GaimPounceActionData *action_data;
-
-	g_return_if_fail(pounce != NULL);
-	g_return_if_fail(action != NULL);
-	g_return_if_fail(attr   != NULL);
-
-	action_data = find_action_data(pounce, action);
-
-	g_return_if_fail(action_data != NULL);
-
-	if (value == NULL)
-		g_hash_table_remove(action_data->atts, attr);
-	else
-		g_hash_table_insert(action_data->atts, g_strdup(attr),
-							g_strdup(value));
-
-	schedule_pounces_save();
-}
-
-void
-gaim_pounce_set_data(GaimPounce *pounce, void *data)
-{
-	g_return_if_fail(pounce != NULL);
-
-	pounce->data = data;
-
-	schedule_pounces_save();
-}
-
-GaimPounceEvent
-gaim_pounce_get_events(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, GAIM_POUNCE_NONE);
-
-	return pounce->events;
-}
-
-GaimPounceOption
-gaim_pounce_get_options(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, GAIM_POUNCE_OPTION_NONE);
-
-	return pounce->options;
-}
-
-GaimAccount *
-gaim_pounce_get_pouncer(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, NULL);
-
-	return pounce->pouncer;
-}
-
-const char *
-gaim_pounce_get_pouncee(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, NULL);
-
-	return pounce->pouncee;
-}
-
-gboolean
-gaim_pounce_get_save(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, FALSE);
-
-	return pounce->save;
-}
-
-gboolean
-gaim_pounce_action_is_enabled(const GaimPounce *pounce, const char *action)
-{
-	GaimPounceActionData *action_data;
-
-	g_return_val_if_fail(pounce != NULL, FALSE);
-	g_return_val_if_fail(action != NULL, FALSE);
-
-	action_data = find_action_data(pounce, action);
-
-	g_return_val_if_fail(action_data != NULL, FALSE);
-
-	return action_data->enabled;
-}
-
-const char *
-gaim_pounce_action_get_attribute(const GaimPounce *pounce,
-								 const char *action, const char *attr)
-{
-	GaimPounceActionData *action_data;
-
-	g_return_val_if_fail(pounce != NULL, NULL);
-	g_return_val_if_fail(action != NULL, NULL);
-	g_return_val_if_fail(attr   != NULL, NULL);
-
-	action_data = find_action_data(pounce, action);
-
-	g_return_val_if_fail(action_data != NULL, NULL);
-
-	return g_hash_table_lookup(action_data->atts, attr);
-}
-
-void *
-gaim_pounce_get_data(const GaimPounce *pounce)
-{
-	g_return_val_if_fail(pounce != NULL, NULL);
-
-	return pounce->data;
-}
-
-void
-gaim_pounce_execute(const GaimAccount *pouncer, const char *pouncee,
-					GaimPounceEvent events)
-{
-	GaimPounce *pounce;
-	GaimPounceHandler *handler;
-	GaimPresence *presence;
-	GList *l, *l_next;
-	char *norm_pouncee;
-
-	g_return_if_fail(pouncer != NULL);
-	g_return_if_fail(pouncee != NULL);
-	g_return_if_fail(events  != GAIM_POUNCE_NONE);
-
-	norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
-
-	for (l = gaim_pounces_get_all(); l != NULL; l = l_next)
-	{
-		pounce = (GaimPounce *)l->data;
-		l_next = l->next;
-
-		presence = gaim_account_get_presence(pouncer);
-
-		if ((gaim_pounce_get_events(pounce) & events) &&
-			(gaim_pounce_get_pouncer(pounce) == pouncer) &&
-			!gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
-								  norm_pouncee) &&
-			(pounce->options == GAIM_POUNCE_OPTION_NONE ||
-			 (pounce->options & GAIM_POUNCE_OPTION_AWAY && 
-			  !gaim_presence_is_available(presence))))
-		{
-			handler = g_hash_table_lookup(pounce_handlers, pounce->ui_type);
-
-			if (handler != NULL && handler->cb != NULL)
-			{
-				handler->cb(pounce, events, gaim_pounce_get_data(pounce));
-
-				if (!gaim_pounce_get_save(pounce))
-					gaim_pounce_destroy(pounce);
-			}
-		}
-	}
-
-	g_free(norm_pouncee);
-}
-
-GaimPounce *
-gaim_find_pounce(const GaimAccount *pouncer, const char *pouncee,
-				 GaimPounceEvent events)
-{
-	GaimPounce *pounce = NULL;
-	GList *l;
-	char *norm_pouncee;
-
-	g_return_val_if_fail(pouncer != NULL, NULL);
-	g_return_val_if_fail(pouncee != NULL, NULL);
-	g_return_val_if_fail(events  != GAIM_POUNCE_NONE, NULL);
-
-	norm_pouncee = g_strdup(gaim_normalize(pouncer, pouncee));
-
-	for (l = gaim_pounces_get_all(); l != NULL; l = l->next)
-	{
-		pounce = (GaimPounce *)l->data;
-
-		if ((gaim_pounce_get_events(pounce) & events) &&
-			(gaim_pounce_get_pouncer(pounce) == pouncer) &&
-			!gaim_utf8_strcasecmp(gaim_normalize(pouncer, gaim_pounce_get_pouncee(pounce)),
-								  norm_pouncee))
-		{
-			break;
-		}
-
-		pounce = NULL;
-	}
-
-	g_free(norm_pouncee);
-
-	return pounce;
-}
-
-void
-gaim_pounces_register_handler(const char *ui, GaimPounceCb cb,
-							  void (*new_pounce)(GaimPounce *pounce),
-							  void (*free_pounce)(GaimPounce *pounce))
-{
-	GaimPounceHandler *handler;
-
-	g_return_if_fail(ui != NULL);
-	g_return_if_fail(cb != NULL);
-
-	handler = g_new0(GaimPounceHandler, 1);
-
-	handler->ui          = g_strdup(ui);
-	handler->cb          = cb;
-	handler->new_pounce  = new_pounce;
-	handler->free_pounce = free_pounce;
-
-	g_hash_table_insert(pounce_handlers, g_strdup(ui), handler);
-}
-
-void
-gaim_pounces_unregister_handler(const char *ui)
-{
-	g_return_if_fail(ui != NULL);
-
-	g_hash_table_remove(pounce_handlers, ui);
-}
-
-GList *
-gaim_pounces_get_all(void)
-{
-	return pounces;
-}
-
-static void
-free_pounce_handler(gpointer user_data)
-{
-	GaimPounceHandler *handler = (GaimPounceHandler *)user_data;
-
-	g_free(handler->ui);
-	g_free(handler);
-}
-
-static void
-buddy_state_cb(GaimBuddy *buddy, GaimPounceEvent event)
-{
-	gaim_pounce_execute(buddy->account, buddy->name, event);
-}
-
-static void
-buddy_status_changed_cb(GaimBuddy *buddy, GaimStatus *old_status,
-                        GaimStatus *status)
-{
-	gboolean old_available, available;
-
-	available = gaim_status_is_available(status);
-	old_available = gaim_status_is_available(old_status);
-
-	if (available && !old_available)
-		gaim_pounce_execute(buddy->account, buddy->name,
-		                    GAIM_POUNCE_AWAY_RETURN);
-	else if (!available && old_available)
-		gaim_pounce_execute(buddy->account, buddy->name,
-		                    GAIM_POUNCE_AWAY);
-}
-
-static void
-buddy_idle_changed_cb(GaimBuddy *buddy, gboolean old_idle, gboolean idle)
-{
-	if (idle && !old_idle)
-		gaim_pounce_execute(buddy->account, buddy->name,
-		                    GAIM_POUNCE_IDLE);
-	else if (!idle && old_idle)
-		gaim_pounce_execute(buddy->account, buddy->name,
-		                    GAIM_POUNCE_IDLE_RETURN);
-}
-
-static void
-buddy_typing_cb(GaimAccount *account, const char *name, void *data)
-{
-	GaimConversation *conv;
-
-	conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, name, account);
-	if (conv != NULL)
-	{
-		GaimTypingState state;
-		GaimPounceEvent event;
-
-		state = gaim_conv_im_get_typing_state(GAIM_CONV_IM(conv));
-		if (state == GAIM_TYPED)
-			event = GAIM_POUNCE_TYPED;
-		else if (state == GAIM_NOT_TYPING)
-			event = GAIM_POUNCE_TYPING_STOPPED;
-		else
-			event = GAIM_POUNCE_TYPING;
-
-		gaim_pounce_execute(account, name, event);
-	}
-}
-
-static void
-received_message_cb(GaimAccount *account, const char *name, void *data)
-{
-	gaim_pounce_execute(account, name, GAIM_POUNCE_MESSAGE_RECEIVED);
-}
-
-void *
-gaim_pounces_get_handle(void)
-{
-	static int pounce_handle;
-
-	return &pounce_handle;
-}
-
-void
-gaim_pounces_init(void)
-{
-	void *handle       = gaim_pounces_get_handle();
-	void *blist_handle = gaim_blist_get_handle();
-	void *conv_handle  = gaim_conversations_get_handle();
-
-	pounce_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
-											g_free, free_pounce_handler);
-
-	gaim_signal_connect(blist_handle, "buddy-idle-changed",
-	                    handle, GAIM_CALLBACK(buddy_idle_changed_cb), NULL);
-	gaim_signal_connect(blist_handle, "buddy-status-changed",
-	                    handle, GAIM_CALLBACK(buddy_status_changed_cb), NULL);
-	gaim_signal_connect(blist_handle, "buddy-signed-on",
-						handle, GAIM_CALLBACK(buddy_state_cb),
-						GINT_TO_POINTER(GAIM_POUNCE_SIGNON));
-	gaim_signal_connect(blist_handle, "buddy-signed-off",
-						handle, GAIM_CALLBACK(buddy_state_cb),
-						GINT_TO_POINTER(GAIM_POUNCE_SIGNOFF));
-
-	gaim_signal_connect(conv_handle, "buddy-typing",
-						handle, GAIM_CALLBACK(buddy_typing_cb), NULL);
-	gaim_signal_connect(conv_handle, "buddy-typed",
-						handle, GAIM_CALLBACK(buddy_typing_cb), NULL);
-	gaim_signal_connect(conv_handle, "buddy-typing-stopped",
-						handle, GAIM_CALLBACK(buddy_typing_cb), NULL);
-
-	gaim_signal_connect(conv_handle, "received-im-msg",
-						handle, GAIM_CALLBACK(received_message_cb), NULL);
-}
-
-void
-gaim_pounces_uninit()
-{
-	if (save_timer != 0)
-	{
-		gaim_timeout_remove(save_timer);
-		save_timer = 0;
-		sync_pounces();
-	}
-
-	gaim_signals_disconnect_by_handle(gaim_pounces_get_handle());
-}

mercurial