src/status.c

changeset 14253
b63ebf84c42b
parent 14252
d10dda2777a9
child 14254
77edc7a6191a
--- a/src/status.c	Sat Aug 19 00:24:14 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1766 +0,0 @@
-/**
- * @file status.c Status 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 "blist.h"
-#include "core.h"
-#include "dbus-maybe.h"
-#include "debug.h"
-#include "notify.h"
-#include "prefs.h"
-#include "status.h"
-
-/**
- * A type of status.
- */
-struct _GaimStatusType
-{
-	GaimStatusPrimitive primitive;
-
-	char *id;
-	char *name;
-	char *primary_attr_id;
-
-	gboolean saveable;
-	gboolean user_settable;
-	gboolean independent;
-
-	GList *attrs;
-};
-
-/**
- * A status attribute.
- */
-struct _GaimStatusAttr
-{
-	char *id;
-	char *name;
-	GaimValue *value_type;
-};
-
-/**
- * A list of statuses.
- */
-struct _GaimPresence
-{
-	GaimPresenceContext context;
-
-	gboolean idle;
-	time_t idle_time;
-	time_t login_time;
-
-	GList *statuses;
-	GHashTable *status_table;
-
-	GaimStatus *active_status;
-
-	union
-	{
-		GaimAccount *account;
-
-		struct
-		{
-			GaimConversation *conv;
-			char *user;
-
-		} chat;
-
-		struct
-		{
-			GaimAccount *account;
-			char *name;
-			size_t ref_count;
-			GList *buddies;
-
-		} buddy;
-
-	} u;
-};
-
-/**
- * An active status.
- */
-struct _GaimStatus
-{
-	GaimStatusType *type;
-	GaimPresence *presence;
-
-	const char *title;
-
-	gboolean active;
-
-	GHashTable *attr_values;
-};
-
-typedef struct
-{
-	GaimAccount *account;
-	char *name;
-} GaimStatusBuddyKey;
-
-static int primitive_scores[] =
-{
-	0,      /* unset                    */
-	-500,   /* offline                  */
-	100,    /* available                */
-	-75,    /* unavailable              */
-	-50,    /* invisible                */
-	-100,   /* away                     */
-	-200,   /* extended away            */
-	-400,   /* mobile                   */
-	-10,    /* idle, special case.      */
-	-5      /* idle time, special case. */
-};
-
-static GHashTable *buddy_presences = NULL;
-
-#define SCORE_IDLE      8
-#define SCORE_IDLE_TIME 9
-
-/**************************************************************************
- * GaimStatusPrimitive API
- **************************************************************************/
-static struct GaimStatusPrimitiveMap
-{
-	GaimStatusPrimitive type;
-	const char *id;
-	const char *name;
-
-} const status_primitive_map[] =
-{
-	{ GAIM_STATUS_UNSET,           "unset",           N_("Unset")           },
-	{ GAIM_STATUS_OFFLINE,         "offline",         N_("Offline")         },
-	{ GAIM_STATUS_AVAILABLE,       "available",       N_("Available")       },
-	{ GAIM_STATUS_UNAVAILABLE,     "unavailable",     N_("Unavailable")     },
-	{ GAIM_STATUS_INVISIBLE,       "invisible",       N_("Invisible")       },
-	{ GAIM_STATUS_AWAY,            "away",            N_("Away")            },
-	{ GAIM_STATUS_EXTENDED_AWAY,   "extended_away",   N_("Extended Away")   },
-	{ GAIM_STATUS_MOBILE,          "mobile",          N_("Mobile")          }
-};
-
-const char *
-gaim_primitive_get_id_from_type(GaimStatusPrimitive type)
-{
-    int i;
-
-    for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++)
-    {
-		if (type == status_primitive_map[i].type)
-			return status_primitive_map[i].id;
-    }
-
-    return status_primitive_map[0].id;
-}
-
-const char *
-gaim_primitive_get_name_from_type(GaimStatusPrimitive type)
-{
-    int i;
-
-    for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++)
-    {
-	if (type == status_primitive_map[i].type)
-		return _(status_primitive_map[i].name);
-    }
-
-    return _(status_primitive_map[0].name);
-}
-
-GaimStatusPrimitive
-gaim_primitive_get_type_from_id(const char *id)
-{
-    int i;
-
-    g_return_val_if_fail(id != NULL, GAIM_STATUS_UNSET);
-
-    for (i = 0; i < GAIM_STATUS_NUM_PRIMITIVES; i++)
-    {
-        if (!strcmp(id, status_primitive_map[i].id))
-            return status_primitive_map[i].type;
-    }
-
-    return status_primitive_map[0].type;
-}
-
-
-/**************************************************************************
- * GaimStatusType API
- **************************************************************************/
-GaimStatusType *
-gaim_status_type_new_full(GaimStatusPrimitive primitive, const char *id,
-						  const char *name, gboolean saveable,
-						  gboolean user_settable, gboolean independent)
-{
-	GaimStatusType *status_type;
-
-	g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL);
-
-	status_type = g_new0(GaimStatusType, 1);
-	GAIM_DBUS_REGISTER_POINTER(status_type, GaimStatusType);
-
-	status_type->primitive     = primitive;
-	status_type->saveable      = saveable;
-	status_type->user_settable = user_settable;
-	status_type->independent   = independent;
-
-	if (id != NULL)
-		status_type->id = g_strdup(id);
-	else
-		status_type->id = g_strdup(gaim_primitive_get_id_from_type(primitive));
-
-	if (name != NULL)
-		status_type->name = g_strdup(name);
-	else
-		status_type->name = g_strdup(gaim_primitive_get_name_from_type(primitive));
-
-	return status_type;
-}
-
-GaimStatusType *
-gaim_status_type_new(GaimStatusPrimitive primitive, const char *id,
-					 const char *name, gboolean user_settable)
-{
-	g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, NULL);
-
-	return gaim_status_type_new_full(primitive, id, name, FALSE,
-			user_settable, FALSE);
-}
-
-GaimStatusType *
-gaim_status_type_new_with_attrs(GaimStatusPrimitive primitive,
-		const char *id, const char *name,
-		gboolean saveable, gboolean user_settable,
-		gboolean independent, const char *attr_id,
-		const char *attr_name, GaimValue *attr_value,
-		...)
-{
-	GaimStatusType *status_type;
-	va_list args;
-
-	g_return_val_if_fail(primitive  != GAIM_STATUS_UNSET, NULL);
-	g_return_val_if_fail(attr_id    != NULL,              NULL);
-	g_return_val_if_fail(attr_name  != NULL,              NULL);
-	g_return_val_if_fail(attr_value != NULL,              NULL);
-
-	status_type = gaim_status_type_new_full(primitive, id, name, saveable,
-			user_settable, independent);
-
-	/* Add the first attribute */
-	gaim_status_type_add_attr(status_type, attr_id, attr_name, attr_value);
-
-	va_start(args, attr_value);
-	gaim_status_type_add_attrs_vargs(status_type, args);
-	va_end(args);
-
-	return status_type;
-}
-
-void
-gaim_status_type_destroy(GaimStatusType *status_type)
-{
-	g_return_if_fail(status_type != NULL);
-
-	g_free(status_type->id);
-	g_free(status_type->name);
-	g_free(status_type->primary_attr_id);
-
-	g_list_foreach(status_type->attrs, (GFunc)gaim_status_attr_destroy, NULL);
-	g_list_free(status_type->attrs);
-
-	GAIM_DBUS_UNREGISTER_POINTER(status_type);
-	g_free(status_type);
-}
-
-void
-gaim_status_type_set_primary_attr(GaimStatusType *status_type, const char *id)
-{
-	g_return_if_fail(status_type != NULL);
-
-	g_free(status_type->primary_attr_id);
-	status_type->primary_attr_id = g_strdup(id);
-}
-
-void
-gaim_status_type_add_attr(GaimStatusType *status_type, const char *id,
-		const char *name, GaimValue *value)
-{
-	GaimStatusAttr *attr;
-
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(id          != NULL);
-	g_return_if_fail(name        != NULL);
-	g_return_if_fail(value       != NULL);
-
-	attr = gaim_status_attr_new(id, name, value);
-
-	status_type->attrs = g_list_append(status_type->attrs, attr);
-}
-
-void
-gaim_status_type_add_attrs_vargs(GaimStatusType *status_type, va_list args)
-{
-	const char *id, *name;
-	GaimValue *value;
-
-	g_return_if_fail(status_type != NULL);
-
-	while ((id = va_arg(args, const char *)) != NULL)
-	{
-		name = va_arg(args, const char *);
-		g_return_if_fail(name != NULL);
-
-		value = va_arg(args, GaimValue *);
-		g_return_if_fail(value != NULL);
-
-		gaim_status_type_add_attr(status_type, id, name, value);
-	}
-}
-
-void
-gaim_status_type_add_attrs(GaimStatusType *status_type, const char *id,
-		const char *name, GaimValue *value, ...)
-{
-	va_list args;
-
-	g_return_if_fail(status_type != NULL);
-	g_return_if_fail(id          != NULL);
-	g_return_if_fail(name        != NULL);
-	g_return_if_fail(value       != NULL);
-
-	/* Add the first attribute */
-	gaim_status_type_add_attr(status_type, id, name, value);
-
-	va_start(args, value);
-	gaim_status_type_add_attrs_vargs(status_type, args);
-	va_end(args);
-}
-
-GaimStatusPrimitive
-gaim_status_type_get_primitive(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, GAIM_STATUS_UNSET);
-
-	return status_type->primitive;
-}
-
-const char *
-gaim_status_type_get_id(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->id;
-}
-
-const char *
-gaim_status_type_get_name(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->name;
-}
-
-gboolean
-gaim_status_type_is_saveable(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->saveable;
-}
-
-gboolean
-gaim_status_type_is_user_settable(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->user_settable;
-}
-
-gboolean
-gaim_status_type_is_independent(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return status_type->independent;
-}
-
-gboolean
-gaim_status_type_is_exclusive(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	return !status_type->independent;
-}
-
-gboolean
-gaim_status_type_is_available(const GaimStatusType *status_type)
-{
-	GaimStatusPrimitive primitive;
-
-	g_return_val_if_fail(status_type != NULL, FALSE);
-
-	primitive = gaim_status_type_get_primitive(status_type);
-
-	return (primitive == GAIM_STATUS_AVAILABLE);
-}
-
-const char *
-gaim_status_type_get_primary_attr(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->primary_attr_id;
-}
-
-GaimStatusAttr *
-gaim_status_type_get_attr(const GaimStatusType *status_type, const char *id)
-{
-	GList *l;
-
-	g_return_val_if_fail(status_type != NULL, NULL);
-	g_return_val_if_fail(id          != NULL, NULL);
-
-	for (l = status_type->attrs; l != NULL; l = l->next)
-	{
-		GaimStatusAttr *attr = (GaimStatusAttr *)l->data;
-
-		if (!strcmp(gaim_status_attr_get_id(attr), id))
-			return attr;
-	}
-
-	return NULL;
-}
-
-const GList *
-gaim_status_type_get_attrs(const GaimStatusType *status_type)
-{
-	g_return_val_if_fail(status_type != NULL, NULL);
-
-	return status_type->attrs;
-}
-
-const GaimStatusType *
-gaim_status_type_find_with_id(GList *status_types, const char *id)
-{
-	GaimStatusType *status_type;
-
-	g_return_val_if_fail(id != NULL, NULL);
-
-	while (status_types != NULL)
-	{
-		status_type = status_types->data;
-
-		if (!strcmp(id, status_type->id))
-			return status_type;
-
-		status_types = status_types->next;
-	}
-
-	return NULL;
-}
-
-
-/**************************************************************************
-* GaimStatusAttr API
-**************************************************************************/
-GaimStatusAttr *
-gaim_status_attr_new(const char *id, const char *name, GaimValue *value_type)
-{
-	GaimStatusAttr *attr;
-
-	g_return_val_if_fail(id         != NULL, NULL);
-	g_return_val_if_fail(name       != NULL, NULL);
-	g_return_val_if_fail(value_type != NULL, NULL);
-
-	attr = g_new0(GaimStatusAttr, 1);
-	GAIM_DBUS_REGISTER_POINTER(attr, GaimStatusAttr);
-
-	attr->id         = g_strdup(id);
-	attr->name       = g_strdup(name);
-	attr->value_type = value_type;
-
-	return attr;
-}
-
-void
-gaim_status_attr_destroy(GaimStatusAttr *attr)
-{
-	g_return_if_fail(attr != NULL);
-
-	g_free(attr->id);
-	g_free(attr->name);
-
-	gaim_value_destroy(attr->value_type);
-
-	GAIM_DBUS_UNREGISTER_POINTER(attr);
-	g_free(attr);
-}
-
-const char *
-gaim_status_attr_get_id(const GaimStatusAttr *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->id;
-}
-
-const char *
-gaim_status_attr_get_name(const GaimStatusAttr *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->name;
-}
-
-GaimValue *
-gaim_status_attr_get_value(const GaimStatusAttr *attr)
-{
-	g_return_val_if_fail(attr != NULL, NULL);
-
-	return attr->value_type;
-}
-
-
-/**************************************************************************
-* GaimStatus API
-**************************************************************************/
-GaimStatus *
-gaim_status_new(GaimStatusType *status_type, GaimPresence *presence)
-{
-	GaimStatus *status;
-	const GList *l;
-
-	g_return_val_if_fail(status_type != NULL, NULL);
-	g_return_val_if_fail(presence    != NULL, NULL);
-
-	status = g_new0(GaimStatus, 1);
-	GAIM_DBUS_REGISTER_POINTER(status, GaimStatus);
-
-	status->type     = status_type;
-	status->presence = presence;
-
-	status->attr_values =
-		g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-		(GDestroyNotify)gaim_value_destroy);
-
-	for (l = gaim_status_type_get_attrs(status_type); l != NULL; l = l->next)
-	{
-		GaimStatusAttr *attr = (GaimStatusAttr *)l->data;
-		GaimValue *value = gaim_status_attr_get_value(attr);
-		GaimValue *new_value = gaim_value_dup(value);
-
-		g_hash_table_insert(status->attr_values,
-							g_strdup(gaim_status_attr_get_id(attr)),
-							new_value);
-	}
-
-	return status;
-}
-
-/*
- * TODO: If the GaimStatus is in a GaimPresence, then
- *       remove it from the GaimPresence?
- */
-void
-gaim_status_destroy(GaimStatus *status)
-{
-	g_return_if_fail(status != NULL);
-
-	g_hash_table_destroy(status->attr_values);
-
-	GAIM_DBUS_UNREGISTER_POINTER(status);
-	g_free(status);
-}
-
-static void
-notify_buddy_status_update(GaimBuddy *buddy, GaimPresence *presence,
-		GaimStatus *old_status, GaimStatus *new_status)
-{
-	GaimBlistUiOps *ops = gaim_blist_get_ui_ops();
-
-	if (gaim_prefs_get_bool("/core/logging/log_system"))
-	{
-		time_t current_time = time(NULL);
-		const char *buddy_alias = gaim_buddy_get_alias(buddy);
-		char *tmp;
-		GaimLog *log;
-
-		if (old_status != NULL)
-		{
-			tmp = g_strdup_printf(_("%s changed status from %s to %s"), buddy_alias,
-			                      gaim_status_get_name(old_status),
-			                      gaim_status_get_name(new_status));
-		}
-		else
-		{
-			/* old_status == NULL when an independent status is toggled. */
-
-			if (gaim_status_is_active(new_status))
-			{
-				tmp = g_strdup_printf(_("%s is now %s"), buddy_alias,
-				                      gaim_status_get_name(new_status));
-			}
-			else
-			{
-				tmp = g_strdup_printf(_("%s is no longer %s"), buddy_alias,
-				                      gaim_status_get_name(new_status));
-			}
-		}
-
-		log = gaim_account_get_log(buddy->account, FALSE);
-		if (log != NULL)
-		{
-			gaim_log_write(log, GAIM_MESSAGE_SYSTEM, buddy_alias,
-			               current_time, tmp);
-		}
-
-		g_free(tmp);
-	}
-
-	if (ops != NULL && ops->update != NULL)
-		ops->update(gaim_get_blist(), (GaimBlistNode*)buddy);
-}
-
-static void
-notify_status_update(GaimPresence *presence, GaimStatus *old_status,
-					 GaimStatus *new_status)
-{
-	GaimPresenceContext context = gaim_presence_get_context(presence);
-
-	if (context == GAIM_PRESENCE_CONTEXT_ACCOUNT)
-	{
-		GaimAccount *account = gaim_presence_get_account(presence);
-		GaimAccountUiOps *ops = gaim_accounts_get_ui_ops();
-
-		if (gaim_account_get_enabled(account, gaim_core_get_ui()))
-			gaim_prpl_change_account_status(account, old_status, new_status);
-
-		if (ops != NULL && ops->status_changed != NULL)
-		{
-			ops->status_changed(account, new_status);
-		}
-	}
-	else if (context == GAIM_PRESENCE_CONTEXT_BUDDY)
-	{
-		const GList *l;
-
-		for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next)
-		{
-			notify_buddy_status_update((GaimBuddy *)l->data, presence,
-					old_status, new_status);
-		}
-	}
-}
-
-static void
-status_has_changed(GaimStatus *status)
-{
-	GaimPresence *presence;
-	GaimStatus *old_status;
-
-	presence   = gaim_status_get_presence(status);
-
-	/*
-	 * If this status is exclusive, then we must be setting it to "active."
-	 * Since we are setting it to active, we want to set the currently
-	 * active status to "inactive."
-	 */
-	if (gaim_status_is_exclusive(status))
-	{
-		old_status = gaim_presence_get_active_status(presence);
-		if (old_status != NULL && (old_status != status))
-			old_status->active = FALSE;
-		presence->active_status = status;
-	}
-	else
-		old_status = NULL;
-
-	notify_status_update(presence, old_status, status);
-}
-
-void
-gaim_status_set_active(GaimStatus *status, gboolean active)
-{
-	gaim_status_set_active_with_attrs_list(status, active, NULL);
-}
-
-/*
- * This used to parse the va_list directly, but now it creates a GList
- * and passes it to gaim_status_set_active_with_attrs_list().  That
- * function was created because accounts.c needs to pass a GList of
- * attributes to the status API.
- */
-void
-gaim_status_set_active_with_attrs(GaimStatus *status, gboolean active, va_list args)
-{
-	GList *attrs = NULL;
-	const gchar *id;
-	gpointer data;
-
-	if (args != NULL)
-	{
-		while ((id = va_arg(args, const char *)) != NULL)
-		{
-			attrs = g_list_append(attrs, (char *)id);
-			data = va_arg(args, void *);
-			attrs = g_list_append(attrs, data);
-		}
-	}
-	gaim_status_set_active_with_attrs_list(status, active, attrs);
-	g_list_free(attrs);
-}
-
-void
-gaim_status_set_active_with_attrs_list(GaimStatus *status, gboolean active,
-									   const GList *attrs)
-{
-	gboolean changed = FALSE;
-	const GList *l;
-	GList *specified_attr_ids = NULL;
-	GaimStatusType *status_type;
-
-	g_return_if_fail(status != NULL);
-
-	if (!active && gaim_status_is_exclusive(status))
-	{
-		gaim_debug_error("status",
-				   "Cannot deactivate an exclusive status (%s).\n",
-				   gaim_status_get_id(status));
-		return;
-	}
-
-	if (status->active != active)
-	{
-		changed = TRUE;
-	}
-
-	status->active = active;
-
-	/* Set any attributes */
-	l = attrs;
-	while (l != NULL)
-	{
-		const gchar *id;
-		GaimValue *value;
-
-		id = l->data;
-		l = l->next;
-		value = gaim_status_get_attr_value(status, id);
-		if (value == NULL)
-		{
-			gaim_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is "
-							   "not supported.\n", id, status->type->name);
-			/* Skip over the data and move on to the next attribute */
-			l = l->next;
-			continue;
-		}
-
-		specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id);
-
-		if (value->type == GAIM_TYPE_STRING)
-		{
-			const gchar *string_data = l->data;
-			l = l->next;
-			if (((string_data == NULL) && (value->data.string_data == NULL)) ||
-				((string_data != NULL) && (value->data.string_data != NULL) &&
-				!strcmp(string_data, value->data.string_data)))
-			{
-				continue;
-			}
-			gaim_status_set_attr_string(status, id, string_data);
-			changed = TRUE;
-		}
-		else if (value->type == GAIM_TYPE_INT)
-		{
-			int int_data = GPOINTER_TO_INT(l->data);
-			l = l->next;
-			if (int_data == value->data.int_data)
-				continue;
-			gaim_status_set_attr_int(status, id, int_data);
-			changed = TRUE;
-		}
-		else if (value->type == GAIM_TYPE_BOOLEAN)
-		{
-			gboolean boolean_data = GPOINTER_TO_INT(l->data);
-			l = l->next;
-			if (boolean_data == value->data.boolean_data)
-				continue;
-			gaim_status_set_attr_boolean(status, id, boolean_data);
-			changed = TRUE;
-		}
-		else
-		{
-			/* We don't know what the data is--skip over it */
-			l = l->next;
-		}
-	}
-
-	/* Reset any unspecified attributes to their default value */
-	status_type = gaim_status_get_type(status);
-	l = gaim_status_type_get_attrs(status_type);
-	while (l != NULL)
-	{
-		GaimStatusAttr *attr;
-
-		attr = l->data;
-		if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp))
-		{
-			GaimValue *default_value;
-			default_value = gaim_status_attr_get_value(attr);
-			if (default_value->type == GAIM_TYPE_STRING)
-				gaim_status_set_attr_string(status, attr->id,
-						gaim_value_get_string(default_value));
-			else if (default_value->type == GAIM_TYPE_INT)
-				gaim_status_set_attr_int(status, attr->id,
-						gaim_value_get_int(default_value));
-			else if (default_value->type == GAIM_TYPE_BOOLEAN)
-				gaim_status_set_attr_boolean(status, attr->id,
-						gaim_value_get_boolean(default_value));
-			changed = TRUE;
-		}
-
-		l = l->next;
-	}
-	g_list_free(specified_attr_ids);
-
-	if (!changed)
-		return;
-	status_has_changed(status);
-}
-
-void
-gaim_status_set_attr_boolean(GaimStatus *status, const char *id,
-		gboolean value)
-{
-	GaimValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = gaim_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_BOOLEAN);
-
-	gaim_value_set_boolean(attr_value, value);
-}
-
-void
-gaim_status_set_attr_int(GaimStatus *status, const char *id, int value)
-{
-	GaimValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = gaim_status_get_attr_value(status, id);
-	g_return_if_fail(attr_value != NULL);
-	g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_INT);
-
-	gaim_value_set_int(attr_value, value);
-}
-
-void
-gaim_status_set_attr_string(GaimStatus *status, const char *id,
-		const char *value)
-{
-	GaimValue *attr_value;
-
-	g_return_if_fail(status != NULL);
-	g_return_if_fail(id     != NULL);
-
-	/* Make sure this attribute exists and is the correct type. */
-	attr_value = gaim_status_get_attr_value(status, id);
-	/* This used to be g_return_if_fail, but it's failing a LOT, so
-	 * let's generate a log error for now. */
-	/* g_return_if_fail(attr_value != NULL); */
-	if (attr_value == NULL) {
-		gaim_debug_error("status",
-				 "Attempted to set status attribute '%s' for "
-				 "status '%s', which is not legal.  Fix "
-                                 "this!\n", id,
-				 gaim_status_type_get_name(gaim_status_get_type(status)));
-		return;
-	}
-	g_return_if_fail(gaim_value_get_type(attr_value) == GAIM_TYPE_STRING);
-
-	gaim_value_set_string(attr_value, value);
-}
-
-GaimStatusType *
-gaim_status_get_type(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, NULL);
-
-	return status->type;
-}
-
-GaimPresence *
-gaim_status_get_presence(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, NULL);
-
-	return status->presence;
-}
-
-const char *
-gaim_status_get_id(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, NULL);
-
-	return gaim_status_type_get_id(gaim_status_get_type(status));
-}
-
-const char *
-gaim_status_get_name(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, NULL);
-
-	return gaim_status_type_get_name(gaim_status_get_type(status));
-}
-
-gboolean
-gaim_status_is_independent(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, FALSE);
-
-	return gaim_status_type_is_independent(gaim_status_get_type(status));
-}
-
-gboolean
-gaim_status_is_exclusive(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, FALSE);
-
-	return gaim_status_type_is_exclusive(gaim_status_get_type(status));
-}
-
-gboolean
-gaim_status_is_available(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, FALSE);
-
-	return gaim_status_type_is_available(gaim_status_get_type(status));
-}
-
-gboolean
-gaim_status_is_active(const GaimStatus *status)
-{
-	g_return_val_if_fail(status != NULL, FALSE);
-
-	return status->active;
-}
-
-gboolean
-gaim_status_is_online(const GaimStatus *status)
-{
-	GaimStatusPrimitive primitive;
-
-	g_return_val_if_fail( status != NULL, FALSE);
-
-	primitive = gaim_status_type_get_primitive(gaim_status_get_type(status));
-
-	return (primitive != GAIM_STATUS_UNSET &&
-			primitive != GAIM_STATUS_OFFLINE);
-}
-
-GaimValue *
-gaim_status_get_attr_value(const GaimStatus *status, const char *id)
-{
-	g_return_val_if_fail(status != NULL, NULL);
-	g_return_val_if_fail(id     != NULL, NULL);
-
-	return (GaimValue *)g_hash_table_lookup(status->attr_values, id);
-}
-
-gboolean
-gaim_status_get_attr_boolean(const GaimStatus *status, const char *id)
-{
-	const GaimValue *value;
-
-	g_return_val_if_fail(status != NULL, FALSE);
-	g_return_val_if_fail(id     != NULL, FALSE);
-
-	if ((value = gaim_status_get_attr_value(status, id)) == NULL)
-		return FALSE;
-
-	g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_BOOLEAN, FALSE);
-
-	return gaim_value_get_boolean(value);
-}
-
-int
-gaim_status_get_attr_int(const GaimStatus *status, const char *id)
-{
-	const GaimValue *value;
-
-	g_return_val_if_fail(status != NULL, 0);
-	g_return_val_if_fail(id     != NULL, 0);
-
-	if ((value = gaim_status_get_attr_value(status, id)) == NULL)
-		return 0;
-
-	g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_INT, 0);
-
-	return gaim_value_get_int(value);
-}
-
-const char *
-gaim_status_get_attr_string(const GaimStatus *status, const char *id)
-{
-	const GaimValue *value;
-
-	g_return_val_if_fail(status != NULL, NULL);
-	g_return_val_if_fail(id     != NULL, NULL);
-
-	if ((value = gaim_status_get_attr_value(status, id)) == NULL)
-		return NULL;
-
-	g_return_val_if_fail(gaim_value_get_type(value) == GAIM_TYPE_STRING, NULL);
-
-	return gaim_value_get_string(value);
-}
-
-gint
-gaim_status_compare(const GaimStatus *status1, const GaimStatus *status2)
-{
-	GaimStatusType *type1, *type2;
-	int score1 = 0, score2 = 0;
-
-	if ((status1 == NULL && status2 == NULL) ||
-			(status1 == status2))
-	{
-		return 0;
-	}
-	else if (status1 == NULL)
-		return 1;
-	else if (status2 == NULL)
-		return -1;
-
-	type1 = gaim_status_get_type(status1);
-	type2 = gaim_status_get_type(status2);
-
-	if (gaim_status_is_active(status1))
-		score1 = primitive_scores[gaim_status_type_get_primitive(type1)];
-
-	if (gaim_status_is_active(status2))
-		score2 = primitive_scores[gaim_status_type_get_primitive(type2)];
-
-	if (score1 > score2)
-		return -1;
-	else if (score1 < score2)
-		return 1;
-
-	return 0;
-}
-
-
-/**************************************************************************
-* GaimPresence API
-**************************************************************************/
-GaimPresence *
-gaim_presence_new(GaimPresenceContext context)
-{
-	GaimPresence *presence;
-
-	g_return_val_if_fail(context != GAIM_PRESENCE_CONTEXT_UNSET, NULL);
-
-	presence = g_new0(GaimPresence, 1);
-	GAIM_DBUS_REGISTER_POINTER(presence, GaimPresence);
-
-	presence->context = context;
-
-	presence->status_table =
-		g_hash_table_new_full(g_str_hash, g_str_equal,
-							  g_free, NULL);
-
-	return presence;
-}
-
-GaimPresence *
-gaim_presence_new_for_account(GaimAccount *account)
-{
-	GaimPresence *presence = NULL;
-	g_return_val_if_fail(account != NULL, NULL);
-
-	presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_ACCOUNT);
-	presence->u.account = account;
-	presence->statuses = gaim_prpl_get_statuses(account, presence);
-
-	return presence;
-}
-
-GaimPresence *
-gaim_presence_new_for_conv(GaimConversation *conv)
-{
-	GaimPresence *presence;
-
-	g_return_val_if_fail(conv != NULL, NULL);
-
-	presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_CONV);
-	presence->u.chat.conv = conv;
-	/* presence->statuses = gaim_prpl_get_statuses(conv->account, presence); ? */
-
-	return presence;
-}
-
-GaimPresence *
-gaim_presence_new_for_buddy(GaimBuddy *buddy)
-{
-	GaimPresence *presence;
-	GaimStatusBuddyKey *key;
-	GaimAccount *account;
-
-	g_return_val_if_fail(buddy != NULL, NULL);
-	account = buddy->account;
-
-	key = g_new0(GaimStatusBuddyKey, 1);
-	key->account = buddy->account;
-	key->name    = g_strdup(buddy->name);
-
-	presence = g_hash_table_lookup(buddy_presences, key);
-	if (presence == NULL)
-	{
-		presence = gaim_presence_new(GAIM_PRESENCE_CONTEXT_BUDDY);
-
-		presence->u.buddy.name    = g_strdup(buddy->name);
-		presence->u.buddy.account = buddy->account;
-		presence->statuses = gaim_prpl_get_statuses(buddy->account, presence);
-
-		g_hash_table_insert(buddy_presences, key, presence);
-	}
-	else
-	{
-		g_free(key->name);
-		g_free(key);
-	}
-
-	presence->u.buddy.ref_count++;
-	presence->u.buddy.buddies = g_list_append(presence->u.buddy.buddies,
-			buddy);
-
-	return presence;
-}
-
-void
-gaim_presence_destroy(GaimPresence *presence)
-{
-	g_return_if_fail(presence != NULL);
-
-	if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY)
-	{
-		GaimStatusBuddyKey key;
-
-		if(presence->u.buddy.ref_count != 0)
-			return;
-
-		key.account = presence->u.buddy.account;
-		key.name    = presence->u.buddy.name;
-
-		g_hash_table_remove(buddy_presences, &key);
-
-		g_free(presence->u.buddy.name);
-	}
-	else if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_CONV)
-	{
-		g_free(presence->u.chat.user);
-	}
-
-	g_list_foreach(presence->statuses, (GFunc)gaim_status_destroy, NULL);
-	g_list_free(presence->statuses);
-
-	g_hash_table_destroy(presence->status_table);
-
-	GAIM_DBUS_UNREGISTER_POINTER(presence);
-	g_free(presence);
-}
-
-/*
- * TODO: Maybe we should cal gaim_presence_destroy() after we
- *       decrement the ref count?  I don't see why we should
- *       make other places do it manually when we can do it here.
- */
-void
-gaim_presence_remove_buddy(GaimPresence *presence, GaimBuddy *buddy)
-{
-	g_return_if_fail(presence != NULL);
-	g_return_if_fail(buddy    != NULL);
-	g_return_if_fail(gaim_presence_get_context(presence) ==
-			GAIM_PRESENCE_CONTEXT_BUDDY);
-
-	if (g_list_find(presence->u.buddy.buddies, buddy) != NULL)
-	{
-		presence->u.buddy.buddies = g_list_remove(presence->u.buddy.buddies,
-				buddy);
-		presence->u.buddy.ref_count--;
-	}
-}
-
-void
-gaim_presence_add_status(GaimPresence *presence, GaimStatus *status)
-{
-	g_return_if_fail(presence != NULL);
-	g_return_if_fail(status   != NULL);
-
-	presence->statuses = g_list_append(presence->statuses, status);
-
-	g_hash_table_insert(presence->status_table,
-	g_strdup(gaim_status_get_id(status)), status);
-}
-
-void
-gaim_presence_add_list(GaimPresence *presence, const GList *source_list)
-{
-	const GList *l;
-
-	g_return_if_fail(presence    != NULL);
-	g_return_if_fail(source_list != NULL);
-
-	for (l = source_list; l != NULL; l = l->next)
-		gaim_presence_add_status(presence, (GaimStatus *)l->data);
-}
-
-void
-gaim_presence_set_status_active(GaimPresence *presence, const char *status_id,
-		gboolean active)
-{
-	GaimStatus *status;
-
-	g_return_if_fail(presence  != NULL);
-	g_return_if_fail(status_id != NULL);
-
-	status = gaim_presence_get_status(presence, status_id);
-
-	g_return_if_fail(status != NULL);
-	/* TODO: Should we do the following? */
-	/* g_return_if_fail(active == status->active); */
-
-	if (gaim_status_is_exclusive(status))
-	{
-		if (!active)
-		{
-			gaim_debug_warning("status",
-					"Attempted to set a non-independent status "
-					"(%s) inactive. Only independent statuses "
-					"can be specifically marked inactive.",
-					status_id);
-			return;
-		}
-	}
-
-	gaim_status_set_active(status, active);
-}
-
-void
-gaim_presence_switch_status(GaimPresence *presence, const char *status_id)
-{
-	gaim_presence_set_status_active(presence, status_id, TRUE);
-}
-
-static void
-update_buddy_idle(GaimBuddy *buddy, GaimPresence *presence,
-		time_t current_time, gboolean old_idle, gboolean idle)
-{
-	GaimBlistUiOps *ops = gaim_blist_get_ui_ops();
-
-	if (!old_idle && idle)
-	{
-		if (gaim_prefs_get_bool("/core/logging/log_system"))
-		{
-			GaimLog *log = gaim_account_get_log(buddy->account, FALSE);
-
-			if (log != NULL)
-			{
-				char *tmp = g_strdup_printf(_("%s became idle"),
-				gaim_buddy_get_alias(buddy));
-
-				gaim_log_write(log, GAIM_MESSAGE_SYSTEM,
-				gaim_buddy_get_alias(buddy), current_time, tmp);
-				g_free(tmp);
-			}
-		}
-	}
-	else if (old_idle && !idle)
-	{
-		if (gaim_prefs_get_bool("/core/logging/log_system"))
-		{
-			GaimLog *log = gaim_account_get_log(buddy->account, FALSE);
-
-			if (log != NULL)
-			{
-				char *tmp = g_strdup_printf(_("%s became unidle"),
-				gaim_buddy_get_alias(buddy));
-
-				gaim_log_write(log, GAIM_MESSAGE_SYSTEM,
-				gaim_buddy_get_alias(buddy), current_time, tmp);
-				g_free(tmp);
-			}
-		}
-	}
-
-	if (old_idle != idle)
-		gaim_signal_emit(gaim_blist_get_handle(), "buddy-idle-changed", buddy,
-		                 old_idle, idle);
-
-	gaim_contact_invalidate_priority_buddy(gaim_buddy_get_contact(buddy));
-
-	/* Should this be done here? It'd perhaps make more sense to
-	 * connect to buddy-[un]idle signals and update from there
-	 */
-
-	if (ops != NULL && ops->update != NULL)
-		ops->update(gaim_get_blist(), (GaimBlistNode *)buddy);
-}
-
-void
-gaim_presence_set_idle(GaimPresence *presence, gboolean idle, time_t idle_time)
-{
-	gboolean old_idle;
-
-	g_return_if_fail(presence != NULL);
-
-	if (presence->idle == idle && presence->idle_time == idle_time)
-		return;
-
-	old_idle            = presence->idle;
-	presence->idle      = idle;
-	presence->idle_time = (idle ? idle_time : 0);
-
-	if (gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_BUDDY)
-	{
-		const GList *l;
-		time_t current_time = time(NULL);
-
-		for (l = gaim_presence_get_buddies(presence); l != NULL; l = l->next)
-		{
-			update_buddy_idle((GaimBuddy *)l->data, presence, current_time,
-			old_idle, idle);
-		}
-	}
-	else if(gaim_presence_get_context(presence) == GAIM_PRESENCE_CONTEXT_ACCOUNT)
-	{
-		GaimAccount *account;
-		GaimConnection *gc;
-		GaimPluginProtocolInfo *prpl_info = NULL;
-
-		account = gaim_presence_get_account(presence);
-
-		if (gaim_prefs_get_bool("/core/logging/log_system"))
-		{
-			GaimLog *log = gaim_account_get_log(account, FALSE);
-
-			if (log != NULL)
-			{
-				char *msg;
-
-				if (idle)
-					msg = g_strdup_printf(_("+++ %s became idle"), gaim_account_get_username(account));
-				else
-					msg = g_strdup_printf(_("+++ %s became unidle"), gaim_account_get_username(account));
-				gaim_log_write(log, GAIM_MESSAGE_SYSTEM,
-							   gaim_account_get_username(account),
-							   idle_time, msg);
-				g_free(msg);
-			}
-		}
-
-		gc = gaim_account_get_connection(account);
-
-		if (gc != NULL && gc->prpl != NULL)
-			prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
-		if (prpl_info && g_list_find(gaim_connections_get_all(), gc) &&
-				prpl_info->set_idle)
-			prpl_info->set_idle(gc, (idle ? (time(NULL) - idle_time) : 0));
-	}
-}
-
-void
-gaim_presence_set_login_time(GaimPresence *presence, time_t login_time)
-{
-	g_return_if_fail(presence != NULL);
-
-	if (presence->login_time == login_time)
-		return;
-
-	presence->login_time = login_time;
-}
-
-GaimPresenceContext
-gaim_presence_get_context(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, GAIM_PRESENCE_CONTEXT_UNSET);
-
-	return presence->context;
-}
-
-GaimAccount *
-gaim_presence_get_account(const GaimPresence *presence)
-{
-	GaimPresenceContext context;
-
-	g_return_val_if_fail(presence != NULL, NULL);
-
-	context = gaim_presence_get_context(presence);
-
-	g_return_val_if_fail(context == GAIM_PRESENCE_CONTEXT_ACCOUNT ||
-			context == GAIM_PRESENCE_CONTEXT_BUDDY, NULL);
-
-	return presence->u.account;
-}
-
-GaimConversation *
-gaim_presence_get_conversation(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, NULL);
-	g_return_val_if_fail(gaim_presence_get_context(presence) ==
-			GAIM_PRESENCE_CONTEXT_CONV, NULL);
-
-	return presence->u.chat.conv;
-}
-
-const char *
-gaim_presence_get_chat_user(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, NULL);
-	g_return_val_if_fail(gaim_presence_get_context(presence) ==
-			GAIM_PRESENCE_CONTEXT_CONV, NULL);
-
-	return presence->u.chat.user;
-}
-
-const GList *
-gaim_presence_get_buddies(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, NULL);
-	g_return_val_if_fail(gaim_presence_get_context(presence) ==
-			GAIM_PRESENCE_CONTEXT_BUDDY, NULL);
-
-	return presence->u.buddy.buddies;
-}
-
-const GList *
-gaim_presence_get_statuses(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, NULL);
-
-	return presence->statuses;
-}
-
-GaimStatus *
-gaim_presence_get_status(const GaimPresence *presence, const char *status_id)
-{
-	GaimStatus *status;
-	const GList *l = NULL;
-
-	g_return_val_if_fail(presence  != NULL, NULL);
-	g_return_val_if_fail(status_id != NULL, NULL);
-
-	/* What's the purpose of this hash table? */
-	status = (GaimStatus *)g_hash_table_lookup(presence->status_table,
-						   status_id);
-
-	if (status == NULL) {
-		for (l = gaim_presence_get_statuses(presence);
-			 l != NULL && status == NULL; l = l->next)
-		{
-			GaimStatus *temp_status = l->data;
-
-			if (!strcmp(status_id, gaim_status_get_id(temp_status)))
-				status = temp_status;
-		}
-
-		if (status != NULL)
-			g_hash_table_insert(presence->status_table,
-								g_strdup(gaim_status_get_id(status)), status);
-	}
-
-	return status;
-}
-
-GaimStatus *
-gaim_presence_get_active_status(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, NULL);
-
-	return presence->active_status;
-}
-
-gboolean
-gaim_presence_is_available(const GaimPresence *presence)
-{
-	GaimStatus *status;
-
-	g_return_val_if_fail(presence != NULL, FALSE);
-
-	status = gaim_presence_get_active_status(presence);
-
-	return ((status != NULL && gaim_status_is_available(status)) &&
-			!gaim_presence_is_idle(presence));
-}
-
-gboolean
-gaim_presence_is_online(const GaimPresence *presence)
-{
-	GaimStatus *status;
-
-	g_return_val_if_fail(presence != NULL, FALSE);
-
-	if ((status = gaim_presence_get_active_status(presence)) == NULL)
-		return FALSE;
-
-	return gaim_status_is_online(status);
-}
-
-gboolean
-gaim_presence_is_status_active(const GaimPresence *presence,
-		const char *status_id)
-{
-	GaimStatus *status;
-
-	g_return_val_if_fail(presence  != NULL, FALSE);
-	g_return_val_if_fail(status_id != NULL, FALSE);
-
-	status = gaim_presence_get_status(presence, status_id);
-
-	return (status != NULL && gaim_status_is_active(status));
-}
-
-gboolean
-gaim_presence_is_status_primitive_active(const GaimPresence *presence,
-		GaimStatusPrimitive primitive)
-{
-	GaimStatus *status;
-	GaimStatusType *status_type;
-
-	g_return_val_if_fail(presence  != NULL,              FALSE);
-	g_return_val_if_fail(primitive != GAIM_STATUS_UNSET, FALSE);
-
-	status      = gaim_presence_get_active_status(presence);
-	status_type = gaim_status_get_type(status);
-
-	if (gaim_status_type_get_primitive(status_type) == primitive)
-		return TRUE;
-
-	return FALSE;
-}
-
-gboolean
-gaim_presence_is_idle(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, FALSE);
-
-	return gaim_presence_is_online(presence) && presence->idle;
-}
-
-time_t
-gaim_presence_get_idle_time(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, 0);
-
-	return presence->idle_time;
-}
-
-time_t
-gaim_presence_get_login_time(const GaimPresence *presence)
-{
-	g_return_val_if_fail(presence != NULL, 0);
-
-	return gaim_presence_is_online(presence) ? presence->login_time : 0;
-}
-
-gint
-gaim_presence_compare(const GaimPresence *presence1,
-		const GaimPresence *presence2)
-{
-	gboolean idle1, idle2;
-	time_t idle_time_1, idle_time_2;
-	int score1 = 0, score2 = 0;
-	const GList *l;
-
-	if (presence1 == presence2)
-		return 0;
-	else if (presence1 == NULL)
-		return 1;
-	else if (presence2 == NULL)
-		return -1;
-
-	/* Compute the score of the first set of statuses. */
-	for (l = gaim_presence_get_statuses(presence1); l != NULL; l = l->next)
-	{
-		GaimStatus *status = (GaimStatus *)l->data;
-		GaimStatusType *type = gaim_status_get_type(status);
-
-		if (gaim_status_is_active(status))
-			score1 += primitive_scores[gaim_status_type_get_primitive(type)];
-	}
-	score1 += gaim_account_get_int(gaim_presence_get_account(presence1), "score", 0);
-
-	/* Compute the score of the second set of statuses. */
-	for (l = gaim_presence_get_statuses(presence2); l != NULL; l = l->next)
-	{
-		GaimStatus *status = (GaimStatus *)l->data;
-		GaimStatusType *type = gaim_status_get_type(status);
-
-		if (gaim_status_is_active(status))
-			score2 += primitive_scores[gaim_status_type_get_primitive(type)];
-	}
-	score2 += gaim_account_get_int(gaim_presence_get_account(presence2), "score", 0);
-
-	idle1 = gaim_presence_is_idle(presence1);
-	idle2 = gaim_presence_is_idle(presence2);
-
-	if (idle1)
-		score1 += primitive_scores[SCORE_IDLE];
-
-	if (idle2)
-		score2 += primitive_scores[SCORE_IDLE];
-
-	idle_time_1 = time(NULL) - gaim_presence_get_idle_time(presence1);
-	idle_time_2 = time(NULL) - gaim_presence_get_idle_time(presence2);
-
-	if (idle_time_1 > idle_time_2)
-		score1 += primitive_scores[SCORE_IDLE_TIME];
-	else if (idle_time_1 < idle_time_2)
-		score2 += primitive_scores[SCORE_IDLE_TIME];
-
-	if (score1 < score2)
-		return 1;
-	else if (score1 > score2)
-		return -1;
-
-	return 0;
-}
-
-
-/**************************************************************************
-* Status subsystem
-**************************************************************************/
-static void
-score_pref_changed_cb(const char *name, GaimPrefType type,
-					  gconstpointer value, gpointer data)
-{
-	int index = GPOINTER_TO_INT(data);
-
-	primitive_scores[index] = GPOINTER_TO_INT(value);
-}
-
-static guint
-gaim_buddy_presences_hash(gconstpointer key)
-{
-	const GaimStatusBuddyKey *me = key;
-	guint ret;
-	char *str;
-
-	str = g_strdup_printf("%p%s", me->account, me->name);
-	ret = g_str_hash(str);
-	g_free(str);
-
-	return ret;
-}
-
-static gboolean
-gaim_buddy_presences_equal(gconstpointer a, gconstpointer b)
-{
-	GaimStatusBuddyKey *key_a = (GaimStatusBuddyKey *)a;
-	GaimStatusBuddyKey *key_b = (GaimStatusBuddyKey *)b;
-
-	if(key_a->account == key_b->account &&
-			!strcmp(key_a->name, key_b->name))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-static void
-gaim_buddy_presences_key_free(gpointer a)
-{
-	GaimStatusBuddyKey *key = (GaimStatusBuddyKey *)a;
-	g_free(key->name);
-	g_free(key);
-}
-
-void *
-gaim_status_get_handle(void) {
-	static int handle;
-
-	return &handle;
-}
-
-void
-gaim_status_init(void)
-{
-	void *handle = gaim_status_get_handle;
-
-	gaim_prefs_add_none("/core/status");
-	gaim_prefs_add_none("/core/status/scores");
-
-	gaim_prefs_add_int("/core/status/scores/offline",
-			primitive_scores[GAIM_STATUS_OFFLINE]);
-	gaim_prefs_add_int("/core/status/scores/available",
-			primitive_scores[GAIM_STATUS_AVAILABLE]);
-	gaim_prefs_add_int("/core/status/scores/invisible",
-			primitive_scores[GAIM_STATUS_INVISIBLE]);
-	gaim_prefs_add_int("/core/status/scores/away",
-			primitive_scores[GAIM_STATUS_AWAY]);
-	gaim_prefs_add_int("/core/status/scores/extended_away",
-			primitive_scores[GAIM_STATUS_EXTENDED_AWAY]);
-	gaim_prefs_add_int("/core/status/scores/idle",
-			primitive_scores[SCORE_IDLE]);
-
-	gaim_prefs_connect_callback(handle, "/core/status/scores/offline",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(GAIM_STATUS_OFFLINE));
-	gaim_prefs_connect_callback(handle, "/core/status/scores/available",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(GAIM_STATUS_AVAILABLE));
-	gaim_prefs_connect_callback(handle, "/core/status/scores/invisible",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(GAIM_STATUS_INVISIBLE));
-	gaim_prefs_connect_callback(handle, "/core/status/scores/away",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(GAIM_STATUS_AWAY));
-	gaim_prefs_connect_callback(handle, "/core/status/scores/extended_away",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(GAIM_STATUS_EXTENDED_AWAY));
-	gaim_prefs_connect_callback(handle, "/core/status/scores/idle",
-			score_pref_changed_cb,
-			GINT_TO_POINTER(SCORE_IDLE));
-
-	buddy_presences = g_hash_table_new_full(gaim_buddy_presences_hash,
-											gaim_buddy_presences_equal,
-											gaim_buddy_presences_key_free, NULL);
-}
-
-void
-gaim_status_uninit(void)
-{
-	if (buddy_presences != NULL)
-	{
-		g_hash_table_destroy(buddy_presences);
-
-		buddy_presences = NULL;
-	}
-}

mercurial