* Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA typedef struct _PurpleStatusPrivate PurpleStatusPrivate; PurpleStatusPrimitive primitive; struct _PurpleStatusAttribute * A PurpleStatus can be thought of as an "instance" of a PurpleStatusType. * If you're familiar with object-oriented programming languages * then this should be immediately clear. Say, for example, that * one of your AIM buddies has set himself as "away." You have a * PurpleBuddy node for this person in your buddy list. Purple wants * to mark this buddy as "away," so it creates a new PurpleStatus. * The PurpleStatus has its PurpleStatusType set to the "away" state * for the oscar protocol. The PurpleStatus also contains the buddy's * away message. PurpleStatuses are sometimes saved, depending on * the context. The current PurpleStatuses associated with each of * your accounts are saved so that the next time you start Purple, * your accounts will be set to their last known statuses. There * is also a list of saved statuses that are written to the * status.xml file. Also, each PurpleStatus has a "saveable" boolean. * If "saveable" is set to FALSE then the status is NEVER saved. * All PurpleStatuses should be inside a PurplePresence. * A PurpleStatus is either "independent" or "exclusive." * Independent statuses can be active or inactive and they don't * affect anything else. However, you can only have one exclusive * status per PurplePresence. If you activate one exclusive status, * then the previous exclusive status is automatically deactivated. * A PurplePresence is like a collection of PurpleStatuses (plus some * See <link linkend="libpurple-presence">Presence API</link> * Private data for PurpleStatus struct _PurpleStatusPrivate PurpleStatusType *status_type; PurplePresence *presence; * The current values of the attributes for this status. The * key is a string containing the name of the attribute. It is * a borrowed reference from the list of attrs in the * PurpleStatusType. The value is a GValue. /* GObject property enums */ static GParamSpec *properties[PROP_LAST]; G_DEFINE_TYPE_WITH_PRIVATE(PurpleStatus, purple_status, G_TYPE_OBJECT); static int primitive_scores[] = -200, /* extended away */ -10, /* idle, special case. */ -5, /* idle time, special case. */ 10 /* Offline messageable */ #define SCORE_IDLE_TIME 10 #define SCORE_OFFLINE_MESSAGE 11 /************************************************************************** * PurpleStatusPrimitive API **************************************************************************/ static struct PurpleStatusPrimitiveMap PurpleStatusPrimitive type; } const status_primitive_map[] = { PURPLE_STATUS_UNSET, "unset", N_("Unset") }, { PURPLE_STATUS_OFFLINE, "offline", N_("Offline") }, { PURPLE_STATUS_AVAILABLE, "available", N_("Available") }, { PURPLE_STATUS_UNAVAILABLE, "unavailable", N_("Do not disturb") }, { PURPLE_STATUS_INVISIBLE, "invisible", N_("Invisible") }, { PURPLE_STATUS_AWAY, "away", N_("Away") }, { PURPLE_STATUS_EXTENDED_AWAY, "extended_away", N_("Extended away") }, { PURPLE_STATUS_MOBILE, "mobile", N_("Mobile") }, { PURPLE_STATUS_TUNE, "tune", N_("Listening to music"), }, { PURPLE_STATUS_MOOD, "mood", N_("Feeling") }, _purple_statuses_get_primitive_scores(void) purple_primitive_get_id_from_type(PurpleStatusPrimitive type) for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++) if (type == status_primitive_map[i].type) return status_primitive_map[i].id; return status_primitive_map[0].id; purple_primitive_get_name_from_type(PurpleStatusPrimitive type) for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++) if (type == status_primitive_map[i].type) return _(status_primitive_map[i].name); return _(status_primitive_map[0].name); purple_primitive_get_type_from_id(const char *id) g_return_val_if_fail(id != NULL, PURPLE_STATUS_UNSET); for (i = 0; i < PURPLE_STATUS_NUM_PRIMITIVES; i++) if (purple_strequal(id, status_primitive_map[i].id)) return status_primitive_map[i].type; return status_primitive_map[0].type; /************************************************************************** **************************************************************************/ purple_status_type_new_full(PurpleStatusPrimitive primitive, const char *id, const char *name, gboolean saveable, gboolean user_settable, gboolean independent) PurpleStatusType *status_type; g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL); status_type = g_new0(PurpleStatusType, 1); status_type->primitive = primitive; status_type->saveable = saveable; status_type->user_settable = user_settable; status_type->independent = independent; status_type->id = g_strdup(id); status_type->id = g_strdup(purple_primitive_get_id_from_type(primitive)); status_type->name = g_strdup(name); status_type->name = g_strdup(purple_primitive_get_name_from_type(primitive)); purple_status_type_new(PurpleStatusPrimitive primitive, const char *id, const char *name, gboolean user_settable) g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, NULL); return purple_status_type_new_full(primitive, id, name, TRUE, status_type_add_attr(PurpleStatusType *status_type, const char *id, const char *name, GValue *value) PurpleStatusAttribute *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 = purple_status_attribute_new(id, name, value); status_type->attrs = g_list_append(status_type->attrs, attr); status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args) 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, GValue *); g_return_if_fail(value != NULL); status_type_add_attr(status_type, id, name, value); purple_status_type_new_with_attrs(PurpleStatusPrimitive primitive, const char *id, const char *name, gboolean saveable, gboolean user_settable, gboolean independent, const char *attr_id, const char *attr_name, GValue *attr_value, PurpleStatusType *status_type; g_return_val_if_fail(primitive != PURPLE_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 = purple_status_type_new_full(primitive, id, name, saveable, user_settable, independent); /* Add the first attribute */ status_type_add_attr(status_type, attr_id, attr_name, attr_value); va_start(args, attr_value); status_type_add_attrs_vargs(status_type, args); purple_status_type_destroy(PurpleStatusType *status_type) g_return_if_fail(status_type != NULL); g_free(status_type->name); g_list_free_full(status_type->attrs, (GDestroyNotify)purple_status_attribute_destroy); purple_status_type_get_primitive(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, PURPLE_STATUS_UNSET); return status_type->primitive; purple_status_type_get_id(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, NULL); purple_status_type_get_name(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, NULL); return status_type->name; purple_status_type_is_saveable(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, FALSE); return status_type->saveable; purple_status_type_is_user_settable(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, FALSE); return status_type->user_settable; purple_status_type_is_independent(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, FALSE); return status_type->independent; purple_status_type_is_exclusive(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, FALSE); return !status_type->independent; purple_status_type_is_available(const PurpleStatusType *status_type) PurpleStatusPrimitive primitive; g_return_val_if_fail(status_type != NULL, FALSE); primitive = purple_status_type_get_primitive(status_type); return (primitive == PURPLE_STATUS_AVAILABLE); purple_status_type_get_attr(const PurpleStatusType *status_type, const char *id) 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) PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data; if (purple_strequal(purple_status_attribute_get_id(attr), id)) purple_status_type_get_attrs(const PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, NULL); return status_type->attrs; purple_status_type_find_with_id(GList *status_types, const char *id) PurpleStatusType *status_type; g_return_val_if_fail(id != NULL, NULL); while (status_types != NULL) status_type = status_types->data; if (purple_strequal(id, status_type->id)) status_types = status_types->next; /************************************************************************** * PurpleStatusAttribute API **************************************************************************/ purple_status_attribute_new(const char *id, const char *name, GValue *value_type) PurpleStatusAttribute *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(PurpleStatusAttribute, 1); attr->name = g_strdup(name); attr->value_type = value_type; purple_status_attribute_destroy(PurpleStatusAttribute *attr) g_return_if_fail(attr != NULL); purple_value_free(attr->value_type); purple_status_attribute_get_id(const PurpleStatusAttribute *attr) g_return_val_if_fail(attr != NULL, NULL); purple_status_attribute_get_name(const PurpleStatusAttribute *attr) g_return_val_if_fail(attr != NULL, NULL); purple_status_attribute_get_value(const PurpleStatusAttribute *attr) g_return_val_if_fail(attr != NULL, NULL); /************************************************************************** **************************************************************************/ notify_buddy_status_update(PurpleBuddy *buddy, PurplePresence *presence, PurpleStatus *old_status, PurpleStatus *new_status) if (purple_prefs_get_bool("/purple/logging/log_system")) GDateTime *current_time = g_date_time_new_now_utc(); const char *buddy_alias = purple_buddy_get_alias(buddy); tmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, purple_buddy_get_name(buddy), purple_status_get_name(old_status), purple_status_get_name(new_status)); logtmp = g_markup_escape_text(tmp, -1); /* old_status == NULL when an independent status is toggled. */ if (purple_status_is_active(new_status)) tmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, purple_buddy_get_name(buddy), purple_status_get_name(new_status)); logtmp = g_markup_escape_text(tmp, -1); tmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, purple_buddy_get_name(buddy), purple_status_get_name(new_status)); logtmp = g_markup_escape_text(tmp, -1); log = purple_account_get_log(purple_buddy_get_account(buddy), FALSE); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, buddy_alias, g_date_time_unref(current_time); notify_status_update(PurplePresence *presence, PurpleStatus *old_status, PurpleStatus *new_status) if (PURPLE_IS_ACCOUNT_PRESENCE(presence)) PurpleAccount *account = purple_account_presence_get_account( PURPLE_ACCOUNT_PRESENCE(presence)); PurpleAccountUiOps *ops = purple_accounts_get_ui_ops(); if (purple_account_get_enabled(account, purple_core_get_ui())) purple_protocol_change_account_status(account, old_status, new_status); if (ops != NULL && ops->status_changed != NULL) ops->status_changed(account, new_status); else if (PURPLE_IS_BUDDY_PRESENCE(presence)) notify_buddy_status_update(purple_buddy_presence_get_buddy( PURPLE_BUDDY_PRESENCE(presence)), presence, old_status, status_has_changed(PurpleStatus *status) PurplePresence *presence; PurpleStatus *old_status; presence = purple_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 (purple_status_is_exclusive(status)) old_status = purple_presence_get_active_status(presence); if (old_status != NULL && (old_status != status)) { PurpleStatusPrivate *priv = purple_status_get_instance_private(old_status); g_object_notify_by_pspec(G_OBJECT(old_status), properties[PROP_ACTIVE]); g_object_set(presence, "active-status", status, NULL); g_object_notify_by_pspec(G_OBJECT(status), properties[PROP_ACTIVE]); notify_status_update(presence, old_status, status); status_set_attr_boolean(PurpleStatus *status, const char *id, g_return_if_fail(PURPLE_IS_STATUS(status)); g_return_if_fail(id != NULL); /* Make sure this attribute exists and is the correct type. */ attr_value = purple_status_get_attr_value(status, id); g_return_if_fail(attr_value != NULL); g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_BOOLEAN); g_value_set_boolean(attr_value, value); status_set_attr_int(PurpleStatus *status, const char *id, int value) g_return_if_fail(PURPLE_IS_STATUS(status)); g_return_if_fail(id != NULL); /* Make sure this attribute exists and is the correct type. */ attr_value = purple_status_get_attr_value(status, id); g_return_if_fail(attr_value != NULL); g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_INT); g_value_set_int(attr_value, value); status_set_attr_string(PurpleStatus *status, const char *id, g_return_if_fail(PURPLE_IS_STATUS(status)); g_return_if_fail(id != NULL); /* Make sure this attribute exists and is the correct type. */ attr_value = purple_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) { purple_debug_error("status", "Attempted to set status attribute '%s' for " "status '%s', which is not legal. Fix " purple_status_type_get_name(purple_status_get_status_type(status))); g_return_if_fail(G_VALUE_TYPE(attr_value) == G_TYPE_STRING); /* XXX: Check if the value has actually changed. If it has, and the status * is active, should this trigger 'status_has_changed'? */ g_value_set_string(attr_value, value); purple_status_set_active(PurpleStatus *status, gboolean active) purple_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 purple_status_set_active_with_attrs_list(). That * function was created because account.c needs to pass a GList of * attributes to the status API. purple_status_set_active_with_attrs(PurpleStatus *status, gboolean active, va_list args) 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); purple_status_set_active_with_attrs_list(status, active, attrs); purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active, PurpleStatusPrivate *priv = NULL; gboolean changed = FALSE; GList *specified_attr_ids = NULL; PurpleStatusType *status_type; g_return_if_fail(PURPLE_IS_STATUS(status)); priv = purple_status_get_instance_private(status); if (!active && purple_status_is_exclusive(status)) purple_debug_error("status", "Cannot deactivate an exclusive status (%s).\n", purple_status_get_id(status)); if (priv->active != active) value = purple_status_get_attr_value(status, id); purple_debug_warning("status", "The attribute \"%s\" on the status \"%s\" is " "not supported.\n", id, priv->status_type->name); /* Skip over the data and move on to the next attribute */ specified_attr_ids = g_list_prepend(specified_attr_ids, (gpointer)id); if (G_VALUE_TYPE(value) == G_TYPE_STRING) const gchar *string_data = l->data; if (purple_strequal(string_data, g_value_get_string(value))) status_set_attr_string(status, id, string_data); else if (G_VALUE_TYPE(value) == G_TYPE_INT) int int_data = GPOINTER_TO_INT(l->data); if (int_data == g_value_get_int(value)) status_set_attr_int(status, id, int_data); else if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN) gboolean boolean_data = GPOINTER_TO_INT(l->data); if (boolean_data == g_value_get_boolean(value)) status_set_attr_boolean(status, id, boolean_data); /* We don't know what the data is--skip over it */ /* Reset any unspecified attributes to their default value */ status_type = purple_status_get_status_type(status); l = purple_status_type_get_attrs(status_type); PurpleStatusAttribute *attr; if (!g_list_find_custom(specified_attr_ids, attr->id, (GCompareFunc)strcmp)) { default_value = purple_status_attribute_get_value(attr); if (G_VALUE_TYPE(default_value) == G_TYPE_STRING) { const char *cur = purple_status_get_attr_string(status, attr->id); const char *def = g_value_get_string(default_value); if (purple_strequal(cur, def)) { status_set_attr_string(status, attr->id, def); } else if (G_VALUE_TYPE(default_value) == G_TYPE_INT) { int cur = purple_status_get_attr_int(status, attr->id); int def = g_value_get_int(default_value); status_set_attr_int(status, attr->id, def); } else if (G_VALUE_TYPE(default_value) == G_TYPE_BOOLEAN) { gboolean cur = purple_status_get_attr_boolean(status, attr->id); gboolean def = g_value_get_boolean(default_value); status_set_attr_boolean(status, attr->id, def); g_list_free(specified_attr_ids); status_has_changed(status); purple_status_get_status_type(PurpleStatus *status) PurpleStatusPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); priv = purple_status_get_instance_private(status); return priv->status_type; purple_status_get_presence(PurpleStatus *status) PurpleStatusPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); priv = purple_status_get_instance_private(status); purple_status_get_id(PurpleStatus *status) g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); return purple_status_type_get_id(purple_status_get_status_type(status)); purple_status_get_name(PurpleStatus *status) g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); return purple_status_type_get_name(purple_status_get_status_type(status)); purple_status_is_independent(PurpleStatus *status) g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); return purple_status_type_is_independent(purple_status_get_status_type(status)); purple_status_is_exclusive(PurpleStatus *status) g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); return purple_status_type_is_exclusive(purple_status_get_status_type(status)); purple_status_is_available(PurpleStatus *status) g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); return purple_status_type_is_available(purple_status_get_status_type(status)); purple_status_is_active(PurpleStatus *status) PurpleStatusPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); priv = purple_status_get_instance_private(status); purple_status_is_online(PurpleStatus *status) PurpleStatusPrimitive primitive; g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); primitive = purple_status_type_get_primitive(purple_status_get_status_type(status)); return (primitive != PURPLE_STATUS_UNSET && primitive != PURPLE_STATUS_OFFLINE); purple_status_get_attr_value(PurpleStatus *status, const char *id) PurpleStatusPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); g_return_val_if_fail(id != NULL, NULL); priv = purple_status_get_instance_private(status); return (GValue *)g_hash_table_lookup(priv->attr_values, id); purple_status_get_attr_boolean(PurpleStatus *status, const char *id) g_return_val_if_fail(PURPLE_IS_STATUS(status), FALSE); g_return_val_if_fail(id != NULL, FALSE); if ((value = purple_status_get_attr_value(status, id)) == NULL) g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_BOOLEAN, FALSE); return g_value_get_boolean(value); purple_status_get_attr_int(PurpleStatus *status, const char *id) g_return_val_if_fail(PURPLE_IS_STATUS(status), 0); g_return_val_if_fail(id != NULL, 0); if ((value = purple_status_get_attr_value(status, id)) == NULL) g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_INT, 0); return g_value_get_int(value); purple_status_get_attr_string(PurpleStatus *status, const char *id) g_return_val_if_fail(PURPLE_IS_STATUS(status), NULL); g_return_val_if_fail(id != NULL, NULL); if ((value = purple_status_get_attr_value(status, id)) == NULL) g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_STRING, NULL); return g_value_get_string(value); purple_status_compare(PurpleStatus *status1, PurpleStatus *status2) PurpleStatusType *type1, *type2; int score1 = 0, score2 = 0; if ((status1 == NULL && status2 == NULL) || else if (status1 == NULL) else if (status2 == NULL) type1 = purple_status_get_status_type(status1); type2 = purple_status_get_status_type(status2); if (purple_status_is_active(status1)) score1 = primitive_scores[purple_status_type_get_primitive(type1)]; if (purple_status_is_active(status2)) score2 = primitive_scores[purple_status_type_get_primitive(type2)]; else if (score1 < score2) /************************************************************************** * GBoxed code for PurpleStatusType **************************************************************************/ static PurpleStatusType * purple_status_type_ref(PurpleStatusType *status_type) g_return_val_if_fail(status_type != NULL, NULL); status_type->box_count++; purple_status_type_unref(PurpleStatusType *status_type) g_return_if_fail(status_type != NULL); g_return_if_fail(status_type->box_count >= 0); if (!status_type->box_count--) purple_status_type_destroy(status_type); purple_status_type_get_type(void) type = g_boxed_type_register_static("PurpleStatusType", (GBoxedCopyFunc)purple_status_type_ref, (GBoxedFreeFunc)purple_status_type_unref); /************************************************************************** * GBoxed code for PurpleStatusAttribute **************************************************************************/ static PurpleStatusAttribute * purple_status_attribute_copy(PurpleStatusAttribute *status_attr) g_return_val_if_fail(status_attr != NULL, NULL); return purple_status_attribute_new(status_attr->id, purple_value_dup(status_attr->value_type)); purple_status_attribute_get_type(void) type = g_boxed_type_register_static("PurpleStatusAttribute", (GBoxedCopyFunc)purple_status_attribute_copy, (GBoxedFreeFunc)purple_status_attribute_destroy); /************************************************************************** * GBoxed code for PurpleMood **************************************************************************/ purple_mood_copy(PurpleMood *mood) g_return_val_if_fail(mood != NULL, NULL); mood_copy = g_new(PurpleMood, 1); mood_copy->mood = g_strdup(mood->mood); mood_copy->description = g_strdup(mood->description); purple_mood_free(PurpleMood *mood) g_free((gchar *)mood->mood); g_free((gchar *)mood->description); purple_mood_get_type(void) type = g_boxed_type_register_static("PurpleMood", (GBoxedCopyFunc)purple_mood_copy, (GBoxedFreeFunc)purple_mood_free); /************************************************************************** **************************************************************************/ /* Set method for GObject properties */ purple_status_set_property(GObject *obj, guint param_id, const GValue *value, PurpleStatus *status = PURPLE_STATUS(obj); PurpleStatusPrivate *priv = purple_status_get_instance_private(status); priv->status_type = g_value_get_pointer(value); priv->presence = g_value_get_object(value); purple_status_set_active(status, g_value_get_boolean(value)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); /* Get method for GObject properties */ purple_status_get_property(GObject *obj, guint param_id, GValue *value, PurpleStatus *status = PURPLE_STATUS(obj); g_value_set_pointer(value, purple_status_get_status_type(status)); g_value_set_object(value, purple_status_get_presence(status)); g_value_set_boolean(value, purple_status_is_active(status)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); /* GObject initialization function */ purple_status_init(PurpleStatus *status) PurpleStatusPrivate *priv = purple_status_get_instance_private(status); g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)purple_value_free); /* Called when done constructing */ purple_status_constructed(GObject *object) PurpleStatusPrivate *priv = purple_status_get_instance_private(PURPLE_STATUS(object)); G_OBJECT_CLASS(purple_status_parent_class)->constructed(object); for (l = purple_status_type_get_attrs(priv->status_type); l != NULL; l = l->next) PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data; GValue *value = purple_status_attribute_get_value(attr); GValue *new_value = purple_value_dup(value); g_hash_table_insert(priv->attr_values, (char *)purple_status_attribute_get_id(attr), * GObject finalize function * TODO: If the PurpleStatus is in a PurplePresence, then * remove it from the PurplePresence? purple_status_finalize(GObject *obj) PurpleStatusPrivate *priv = purple_status_get_instance_private(PURPLE_STATUS(obj)); g_hash_table_destroy(priv->attr_values); G_OBJECT_CLASS(purple_status_parent_class)->finalize(obj); /* Class initializer function */ purple_status_class_init(PurpleStatusClass *klass) GObjectClass *obj_class = G_OBJECT_CLASS(klass); obj_class->finalize = purple_status_finalize; obj_class->constructed = purple_status_constructed; obj_class->get_property = purple_status_get_property; obj_class->set_property = purple_status_set_property; properties[PROP_STATUS_TYPE] = g_param_spec_pointer("status-type", "The PurpleStatusType of the status.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | properties[PROP_PRESENCE] = g_param_spec_object("presence", "Presence", "The presence that the status belongs to.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | properties[PROP_ACTIVE] = g_param_spec_boolean("active", "Active", "Whether the status is active or not.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, PROP_LAST, properties); purple_status_new(PurpleStatusType *status_type, PurplePresence *presence) g_return_val_if_fail(status_type != NULL, NULL); g_return_val_if_fail(PURPLE_IS_PRESENCE(presence), NULL); return g_object_new(PURPLE_TYPE_STATUS, "status-type", status_type, /************************************************************************** **************************************************************************/ score_pref_changed_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) int index = GPOINTER_TO_INT(data); primitive_scores[index] = GPOINTER_TO_INT(value); purple_statuses_get_handle(void) { purple_statuses_init(void) void *handle = purple_statuses_get_handle(); purple_prefs_add_none("/purple/status"); purple_prefs_add_none("/purple/status/scores"); purple_prefs_add_int("/purple/status/scores/offline", primitive_scores[PURPLE_STATUS_OFFLINE]); purple_prefs_add_int("/purple/status/scores/available", primitive_scores[PURPLE_STATUS_AVAILABLE]); purple_prefs_add_int("/purple/status/scores/invisible", primitive_scores[PURPLE_STATUS_INVISIBLE]); purple_prefs_add_int("/purple/status/scores/away", primitive_scores[PURPLE_STATUS_AWAY]); purple_prefs_add_int("/purple/status/scores/extended_away", primitive_scores[PURPLE_STATUS_EXTENDED_AWAY]); purple_prefs_add_int("/purple/status/scores/idle", primitive_scores[SCORE_IDLE]); purple_prefs_add_int("/purple/status/scores/idle_time", primitive_scores[SCORE_IDLE_TIME]); purple_prefs_add_int("/purple/status/scores/offline_msg", primitive_scores[SCORE_OFFLINE_MESSAGE]); purple_prefs_connect_callback(handle, "/purple/status/scores/offline", GINT_TO_POINTER(PURPLE_STATUS_OFFLINE)); purple_prefs_connect_callback(handle, "/purple/status/scores/available", GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE)); purple_prefs_connect_callback(handle, "/purple/status/scores/invisible", GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE)); purple_prefs_connect_callback(handle, "/purple/status/scores/away", GINT_TO_POINTER(PURPLE_STATUS_AWAY)); purple_prefs_connect_callback(handle, "/purple/status/scores/extended_away", GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY)); purple_prefs_connect_callback(handle, "/purple/status/scores/idle", GINT_TO_POINTER(SCORE_IDLE)); purple_prefs_connect_callback(handle, "/purple/status/scores/idle_time", GINT_TO_POINTER(SCORE_IDLE_TIME)); purple_prefs_connect_callback(handle, "/purple/status/scores/offline_msg", GINT_TO_POINTER(SCORE_OFFLINE_MESSAGE)); purple_prefs_trigger_callback("/purple/status/scores/offline"); purple_prefs_trigger_callback("/purple/status/scores/available"); purple_prefs_trigger_callback("/purple/status/scores/invisible"); purple_prefs_trigger_callback("/purple/status/scores/away"); purple_prefs_trigger_callback("/purple/status/scores/extended_away"); purple_prefs_trigger_callback("/purple/status/scores/idle"); purple_prefs_trigger_callback("/purple/status/scores/idle_time"); purple_prefs_trigger_callback("/purple/status/scores/offline_msg"); purple_statuses_uninit(void) purple_prefs_disconnect_by_handle(purple_prefs_get_handle());