pidgin/pidgin

Use Meson summary() function.

2021-07-27, Elliott Sales de Andrade
cb640ea0f315
Use Meson summary() function.

Now that we require at least 0.52, we can use Meson's builtin summary printing to display the results of configuration.

Testing Done:
Configured with defaults, and with pixmaps disabled to trigger the warning: https://asciinema.org/a/mV2oxOoVCJNdmrPwgqqUJ3mkU?t=17

Reviewed at https://reviews.imfreedom.org/r/848/
/* purple
*
* 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
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <glib/gi18n-lib.h>
#include "internal.h"
#include "purpleprivate.h"
#include "buddylist.h"
#include "core.h"
#include "debug.h"
#include "notify.h"
#include "prefs.h"
#include "purpleaccountpresence.h"
#include "purplebuddypresence.h"
#include "status.h"
typedef struct _PurpleStatusPrivate PurpleStatusPrivate;
/*
* A type of status.
*/
struct _PurpleStatusType
{
int box_count;
PurpleStatusPrimitive primitive;
char *id;
char *name;
gboolean saveable;
gboolean user_settable;
gboolean independent;
GList *attrs;
};
/*
* A status attribute.
*/
struct _PurpleStatusAttribute
{
char *id;
char *name;
GValue *value_type;
};
struct _PurpleStatus
{
GObject parent;
};
/*
* Private data for PurpleStatus
*/
struct _PurpleStatusPrivate
{
PurpleStatusType *status_type;
PurplePresence *presence;
gboolean active;
/*
* 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.
*/
GHashTable *attr_values;
};
/* GObject property enums */
enum
{
PROP_0,
PROP_STATUS_TYPE,
PROP_PRESENCE,
PROP_ACTIVE,
PROP_LAST
};
typedef struct
{
PurpleAccount *account;
char *name;
} PurpleStatusBuddyKey;
static GParamSpec *properties[PROP_LAST];
G_DEFINE_TYPE_WITH_PRIVATE(PurpleStatus, purple_status, G_TYPE_OBJECT);
static int primitive_scores[] =
{
0, /* unset */
-500, /* offline */
100, /* available */
-75, /* unavailable */
-50, /* invisible */
-100, /* away */
-200, /* extended away */
-400, /* mobile */
0, /* tune */
0, /* mood */
-10, /* idle, special case. */
-5, /* idle time, special case. */
10 /* Offline messageable */
};
#define SCORE_IDLE 9
#define SCORE_IDLE_TIME 10
#define SCORE_OFFLINE_MESSAGE 11
/**************************************************************************
* PurpleStatusPrimitive API
**************************************************************************/
static struct PurpleStatusPrimitiveMap
{
PurpleStatusPrimitive type;
const char *id;
const char *name;
} 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") },
};
int *
_purple_statuses_get_primitive_scores(void)
{
return primitive_scores;
}
const char *
purple_primitive_get_id_from_type(PurpleStatusPrimitive type)
{
int i;
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;
}
const char *
purple_primitive_get_name_from_type(PurpleStatusPrimitive type)
{
int i;
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);
}
PurpleStatusPrimitive
purple_primitive_get_type_from_id(const char *id)
{
int i;
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;
}
/**************************************************************************
* PurpleStatusType API
**************************************************************************/
PurpleStatusType *
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;
if (id != NULL)
status_type->id = g_strdup(id);
else
status_type->id = g_strdup(purple_primitive_get_id_from_type(primitive));
if (name != NULL)
status_type->name = g_strdup(name);
else
status_type->name = g_strdup(purple_primitive_get_name_from_type(primitive));
return status_type;
}
PurpleStatusType *
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,
user_settable, FALSE);
}
static void
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);
}
static void
status_type_add_attrs_vargs(PurpleStatusType *status_type, va_list args)
{
const char *id, *name;
GValue *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, GValue *);
g_return_if_fail(value != NULL);
status_type_add_attr(status_type, id, name, value);
}
}
PurpleStatusType *
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;
va_list args;
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);
va_end(args);
return status_type;
}
void
purple_status_type_destroy(PurpleStatusType *status_type)
{
g_return_if_fail(status_type != NULL);
g_free(status_type->id);
g_free(status_type->name);
g_list_free_full(status_type->attrs,
(GDestroyNotify)purple_status_attribute_destroy);
g_free(status_type);
}
PurpleStatusPrimitive
purple_status_type_get_primitive(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, PURPLE_STATUS_UNSET);
return status_type->primitive;
}
const char *
purple_status_type_get_id(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, NULL);
return status_type->id;
}
const char *
purple_status_type_get_name(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, NULL);
return status_type->name;
}
gboolean
purple_status_type_is_saveable(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, FALSE);
return status_type->saveable;
}
gboolean
purple_status_type_is_user_settable(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, FALSE);
return status_type->user_settable;
}
gboolean
purple_status_type_is_independent(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, FALSE);
return status_type->independent;
}
gboolean
purple_status_type_is_exclusive(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, FALSE);
return !status_type->independent;
}
gboolean
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);
}
PurpleStatusAttribute *
purple_status_type_get_attr(const PurpleStatusType *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)
{
PurpleStatusAttribute *attr = (PurpleStatusAttribute *)l->data;
if (purple_strequal(purple_status_attribute_get_id(attr), id))
return attr;
}
return NULL;
}
GList *
purple_status_type_get_attrs(const PurpleStatusType *status_type)
{
g_return_val_if_fail(status_type != NULL, NULL);
return status_type->attrs;
}
const PurpleStatusType *
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))
return status_type;
status_types = status_types->next;
}
return NULL;
}
/**************************************************************************
* PurpleStatusAttribute API
**************************************************************************/
PurpleStatusAttribute *
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->id = g_strdup(id);
attr->name = g_strdup(name);
attr->value_type = value_type;
return attr;
}
void
purple_status_attribute_destroy(PurpleStatusAttribute *attr)
{
g_return_if_fail(attr != NULL);
g_free(attr->id);
g_free(attr->name);
purple_value_free(attr->value_type);
g_free(attr);
}
const char *
purple_status_attribute_get_id(const PurpleStatusAttribute *attr)
{
g_return_val_if_fail(attr != NULL, NULL);
return attr->id;
}
const char *
purple_status_attribute_get_name(const PurpleStatusAttribute *attr)
{
g_return_val_if_fail(attr != NULL, NULL);
return attr->name;
}
GValue *
purple_status_attribute_get_value(const PurpleStatusAttribute *attr)
{
g_return_val_if_fail(attr != NULL, NULL);
return attr->value_type;
}
/**************************************************************************
* PurpleStatus API
**************************************************************************/
static void
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);
char *tmp, *logtmp;
PurpleLog *log;
if (old_status != NULL)
{
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);
}
else
{
/* 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);
}
else
{
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);
if (log != NULL)
{
purple_log_write(log, PURPLE_MESSAGE_SYSTEM, buddy_alias,
current_time, logtmp);
}
g_date_time_unref(current_time);
g_free(tmp);
g_free(logtmp);
}
}
static void
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,
new_status);
}
}
static void
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);
priv->active = FALSE;
g_object_notify_by_pspec(G_OBJECT(old_status),
properties[PROP_ACTIVE]);
}
}
else
old_status = NULL;
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);
}
static void
status_set_attr_boolean(PurpleStatus *status, const char *id,
gboolean value)
{
GValue *attr_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_BOOLEAN);
g_value_set_boolean(attr_value, value);
}
static void
status_set_attr_int(PurpleStatus *status, const char *id, int value)
{
GValue *attr_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);
}
static void
status_set_attr_string(PurpleStatus *status, const char *id,
const char *value)
{
GValue *attr_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);
/* 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 "
"this!\n", id,
purple_status_type_get_name(purple_status_get_status_type(status)));
return;
}
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);
}
void
purple_status_set_active(PurpleStatus *status, gboolean active)
{
purple_status_set_active_with_attrs_dict(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.
*/
void
purple_status_set_active_with_attrs(PurpleStatus *status, gboolean active, va_list args)
{
GHashTable *attrs = purple_attrs_from_vargs(args);
purple_status_set_active_with_attrs_dict(status, active, attrs);
g_hash_table_destroy(attrs);
}
void
purple_status_set_active_with_attrs_dict(PurpleStatus *status, gboolean active,
GHashTable *attrs)
{
PurpleStatusPrivate *priv = NULL;
gboolean changed = FALSE;
GList *l;
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).",
purple_status_get_id(status));
return;
}
if(priv->active != active) {
changed = TRUE;
}
priv->active = active;
if(attrs != NULL) {
GHashTableIter iter;
gpointer key, data;
/* Set any attributes */
g_hash_table_iter_init(&iter, attrs);
while(g_hash_table_iter_next(&iter, &key, &data)) {
gchar *id = (gchar *)key;
GValue *value = purple_status_get_attr_value(status, id);
if(value == NULL) {
purple_debug_warning("status",
"The attribute \"%s\" on the status "
"\"%s\" is not supported.",
id, priv->status_type->name);
/* Skip over the data and move on to the next attribute */
continue;
}
specified_attr_ids = g_list_prepend(specified_attr_ids, id);
if(G_VALUE_HOLDS_STRING(value)) {
const gchar *string_data = (const gchar *)data;
if(purple_strequal(string_data, g_value_get_string(value))) {
continue;
}
status_set_attr_string(status, id, string_data);
changed = TRUE;
} else if(G_VALUE_HOLDS_INT(value)) {
gint int_data = GPOINTER_TO_INT(data);
if(int_data == g_value_get_int(value)) {
continue;
}
status_set_attr_int(status, id, int_data);
changed = TRUE;
} else if(G_VALUE_HOLDS_BOOLEAN(value)) {
gboolean boolean_data = GPOINTER_TO_INT(data);
if(boolean_data == g_value_get_boolean(value)) {
continue;
}
status_set_attr_boolean(status, id, boolean_data);
changed = TRUE;
}
}
}
/* Reset any unspecified attributes to their default value */
status_type = purple_status_get_status_type(status);
l = purple_status_type_get_attrs(status_type);
while(l != NULL) {
PurpleStatusAttribute *attr;
GList *found = NULL;
GValue *default_value = NULL;
default_value = NULL;
attr = l->data;
l = l->next;
found = g_list_find_custom(specified_attr_ids, attr->id,
(GCompareFunc)g_strcmp0);
if(found != NULL) {
continue;
}
default_value = purple_status_attribute_get_value(attr);
if(G_VALUE_HOLDS_STRING(default_value)) {
const gchar *cur = purple_status_get_attr_string(status,
attr->id);
const gchar *def = g_value_get_string(default_value);
if (purple_strequal(cur, def)) {
continue;
}
status_set_attr_string(status, attr->id, def);
} else if(G_VALUE_HOLDS_INT(default_value)) {
gint cur = purple_status_get_attr_int(status, attr->id);
gint def = g_value_get_int(default_value);
if(cur == def) {
continue;
}
status_set_attr_int(status, attr->id, def);
} else if(G_VALUE_HOLDS_BOOLEAN(default_value)) {
gboolean cur = purple_status_get_attr_boolean(status, attr->id);
gboolean def = g_value_get_boolean(default_value);
if(cur == def) {
continue;
}
status_set_attr_boolean(status, attr->id, def);
}
changed = TRUE;
}
g_list_free(specified_attr_ids);
if(changed) {
status_has_changed(status);
}
}
PurpleStatusType *
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;
}
PurplePresence *
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);
return priv->presence;
}
const char *
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));
}
const char *
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));
}
gboolean
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));
}
gboolean
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));
}
gboolean
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));
}
gboolean
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);
return priv->active;
}
gboolean
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);
}
GValue *
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);
}
gboolean
purple_status_get_attr_boolean(PurpleStatus *status, const char *id)
{
const GValue *value;
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)
return FALSE;
g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_BOOLEAN, FALSE);
return g_value_get_boolean(value);
}
int
purple_status_get_attr_int(PurpleStatus *status, const char *id)
{
const GValue *value;
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)
return 0;
g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_INT, 0);
return g_value_get_int(value);
}
const char *
purple_status_get_attr_string(PurpleStatus *status, const char *id)
{
const GValue *value;
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)
return NULL;
g_return_val_if_fail(G_VALUE_TYPE(value) == G_TYPE_STRING, NULL);
return g_value_get_string(value);
}
gint
purple_status_compare(PurpleStatus *status1, PurpleStatus *status2)
{
PurpleStatusType *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 = 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)];
if (score1 > score2)
return -1;
else if (score1 < score2)
return 1;
return 0;
}
/**************************************************************************
* 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++;
return status_type;
}
static void
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);
}
GType
purple_status_type_get_type(void)
{
static GType type = 0;
if (type == 0) {
type = g_boxed_type_register_static("PurpleStatusType",
(GBoxedCopyFunc)purple_status_type_ref,
(GBoxedFreeFunc)purple_status_type_unref);
}
return type;
}
/**************************************************************************
* 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,
status_attr->name,
purple_value_dup(status_attr->value_type));
}
GType
purple_status_attribute_get_type(void)
{
static GType type = 0;
if (type == 0) {
type = g_boxed_type_register_static("PurpleStatusAttribute",
(GBoxedCopyFunc)purple_status_attribute_copy,
(GBoxedFreeFunc)purple_status_attribute_destroy);
}
return type;
}
/**************************************************************************
* GBoxed code for PurpleMood
**************************************************************************/
static PurpleMood *
purple_mood_copy(PurpleMood *mood)
{
PurpleMood *mood_copy;
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);
return mood_copy;
}
static void
purple_mood_free(PurpleMood *mood)
{
g_free((gchar *)mood->mood);
g_free((gchar *)mood->description);
g_free(mood);
}
GType
purple_mood_get_type(void)
{
static GType type = 0;
if (type == 0) {
type = g_boxed_type_register_static("PurpleMood",
(GBoxedCopyFunc)purple_mood_copy,
(GBoxedFreeFunc)purple_mood_free);
}
return type;
}
/**************************************************************************
* GObject code
**************************************************************************/
/* Set method for GObject properties */
static void
purple_status_set_property(GObject *obj, guint param_id, const GValue *value,
GParamSpec *pspec)
{
PurpleStatus *status = PURPLE_STATUS(obj);
PurpleStatusPrivate *priv = purple_status_get_instance_private(status);
switch (param_id) {
case PROP_STATUS_TYPE:
priv->status_type = g_value_get_pointer(value);
break;
case PROP_PRESENCE:
priv->presence = g_value_get_object(value);
break;
case PROP_ACTIVE:
purple_status_set_active(status, g_value_get_boolean(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
/* Get method for GObject properties */
static void
purple_status_get_property(GObject *obj, guint param_id, GValue *value,
GParamSpec *pspec)
{
PurpleStatus *status = PURPLE_STATUS(obj);
switch (param_id) {
case PROP_STATUS_TYPE:
g_value_set_pointer(value, purple_status_get_status_type(status));
break;
case PROP_PRESENCE:
g_value_set_object(value, purple_status_get_presence(status));
break;
case PROP_ACTIVE:
g_value_set_boolean(value, purple_status_is_active(status));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
}
}
/* GObject initialization function */
static void
purple_status_init(PurpleStatus *status)
{
PurpleStatusPrivate *priv = purple_status_get_instance_private(status);
priv->attr_values =
g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
(GDestroyNotify)purple_value_free);
}
/* Called when done constructing */
static void
purple_status_constructed(GObject *object)
{
GList *l;
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),
new_value);
}
}
/*
* GObject finalize function
* TODO: If the PurpleStatus is in a PurplePresence, then
* remove it from the PurplePresence?
*/
static void
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 */
static void
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;
/* Setup properties */
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",
"Status type",
"The PurpleStatusType of the status.",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
properties[PROP_PRESENCE] = g_param_spec_object("presence", "Presence",
"The presence that the status belongs to.",
PURPLE_TYPE_PRESENCE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
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);
}
PurpleStatus *
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,
"presence", presence,
NULL);
}
/**************************************************************************
* Status subsystem
**************************************************************************/
static void
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);
}
void *
purple_statuses_get_handle(void) {
static int handle;
return &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",
score_pref_changed_cb,
GINT_TO_POINTER(PURPLE_STATUS_OFFLINE));
purple_prefs_connect_callback(handle, "/purple/status/scores/available",
score_pref_changed_cb,
GINT_TO_POINTER(PURPLE_STATUS_AVAILABLE));
purple_prefs_connect_callback(handle, "/purple/status/scores/invisible",
score_pref_changed_cb,
GINT_TO_POINTER(PURPLE_STATUS_INVISIBLE));
purple_prefs_connect_callback(handle, "/purple/status/scores/away",
score_pref_changed_cb,
GINT_TO_POINTER(PURPLE_STATUS_AWAY));
purple_prefs_connect_callback(handle, "/purple/status/scores/extended_away",
score_pref_changed_cb,
GINT_TO_POINTER(PURPLE_STATUS_EXTENDED_AWAY));
purple_prefs_connect_callback(handle, "/purple/status/scores/idle",
score_pref_changed_cb,
GINT_TO_POINTER(SCORE_IDLE));
purple_prefs_connect_callback(handle, "/purple/status/scores/idle_time",
score_pref_changed_cb,
GINT_TO_POINTER(SCORE_IDLE_TIME));
purple_prefs_connect_callback(handle, "/purple/status/scores/offline_msg",
score_pref_changed_cb,
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");
}
void
purple_statuses_uninit(void)
{
purple_prefs_disconnect_by_handle(purple_statuses_get_handle());
}
/**************************************************************************/
/* Helpers */
/**************************************************************************/
GHashTable *
purple_attrs_from_vargs(va_list args)
{
GHashTable *attrs = g_hash_table_new(g_str_hash, g_str_equal);
gchar *id;
while ((id = va_arg(args, gchar *)) != NULL)
{
gpointer data = va_arg(args, gpointer);
g_hash_table_insert(attrs, id, data);
}
return attrs;
}