pidgin/pidgin

Merged in default (pull request #652)

2020-04-09, Gary Kramlich
c38a56bd5536
Merged in default (pull request #652)

Use structs instead of adjacent name-value GList elements

Approved-by: Elliott Sales de Andrade
Approved-by: Gary Kramlich
--- a/ChangeLog.API Wed Apr 01 18:07:49 2020 +0000
+++ b/ChangeLog.API Thu Apr 09 08:47:36 2020 +0000
@@ -125,6 +125,8 @@
details.
* purple_account_get_alias renamed to purple_account_get_private_alias
* purple_account_set_alias renamed to purple_account_set_private_alias
+ * purple_account_set_status_list renamed to
+ purple_account_set_status_attrs
* purple_account_option_get_type renamed to
purple_account_option_get_pref_type
* PurplePrivacyType renamed to PurpleAccountPrivacyType
@@ -261,6 +263,8 @@
* PurpleStatus is now a GObject. Please see the documentation for
details.
* purple_status_attr_* functions are now purple_status_attribute_*
+ * purple_status_set_active_with_attrs_list renamed to
+ purple_status_set_active_with_attrs_dict
* PurpleStatusAttr renamed to PurpleStatusAttribute
* PurplePresence is now an abstract type, and is a GObject. Please see
the documentation for details.
--- a/finch/gntplugin.c Wed Apr 01 18:07:49 2020 +0000
+++ b/finch/gntplugin.c Thu Apr 09 08:47:36 2020 +0000
@@ -567,7 +567,6 @@
field = NULL;
type = purple_prefs_get_pref_type(name);
if(purple_plugin_pref_get_pref_type(pref) == PURPLE_PLUGIN_PREF_CHOICE) {
- GList *list = purple_plugin_pref_get_choices(pref);
gpointer current_value = NULL;
switch(type) {
@@ -586,27 +585,26 @@
field = purple_request_field_list_new(name, label);
purple_request_field_list_set_multi_select(field, FALSE);
- while (list && list->next) {
- const char *label = list->data;
+ for (GList *list = purple_plugin_pref_get_choices(pref); list != NULL; list = list->next) {
+ const PurpleKeyValuePair *choice = list->data;
char *value = NULL;
switch(type) {
case PURPLE_PREF_BOOLEAN:
- value = g_strdup_printf("%d", GPOINTER_TO_INT(list->next->data));
+ value = g_strdup_printf("%d", GPOINTER_TO_INT(choice->value));
break;
case PURPLE_PREF_INT:
- value = g_strdup_printf("%d", GPOINTER_TO_INT(list->next->data));
+ value = g_strdup_printf("%d", GPOINTER_TO_INT(choice->value));
break;
case PURPLE_PREF_STRING:
- value = g_strdup(list->next->data);
+ value = g_strdup(choice->value);
break;
default:
break;
}
stringlist = g_list_prepend(stringlist, value);
- purple_request_field_list_add_icon(field, label, NULL, value);
+ purple_request_field_list_add_icon(field, choice->key, NULL, value);
if (purple_strequal(value, current_value))
- purple_request_field_list_add_selected(field, label);
- list = list->next->next;
+ purple_request_field_list_add_selected(field, choice->key);
}
g_free(current_value);
} else {
--- a/finch/gntrequest.c Wed Apr 01 18:07:49 2020 +0000
+++ b/finch/gntrequest.c Thu Apr 09 08:47:36 2020 +0000
@@ -471,22 +471,13 @@
static GntWidget*
create_choice_field(PurpleRequestField *field)
{
- GList *it;
GntWidget *combo = gnt_combo_box_new();
- it = purple_request_field_choice_get_elements(field);
- while (it != NULL)
+ for (GList *it = purple_request_field_choice_get_elements(field); it != NULL; it = g_list_next(it))
{
- const gchar *text;
- gpointer value;
+ PurpleKeyValuePair *choice = it->data;
- text = it->data;
- it = g_list_next(it);
- g_assert(it != NULL);
- value = it->data;
- it = g_list_next(it);
-
- gnt_combo_box_add_data(GNT_COMBO_BOX(combo), value, text);
+ gnt_combo_box_add_data(GNT_COMBO_BOX(combo), choice->value, choice->key);
}
gnt_combo_box_set_selected(GNT_COMBO_BOX(combo),
purple_request_field_choice_get_default_value(field));
@@ -604,7 +595,7 @@
GntWidget *username = NULL, *accountlist = NULL;
PurpleRequestHelpCb help_cb;
gpointer help_data;
- GSList *extra_actions, *it;
+ GSList *extra_actions;
window = setup_request_window(title, primary, secondary, PURPLE_REQUEST_FIELDS);
@@ -690,14 +681,13 @@
ok, ok_cb, cancel, cancel_cb, NULL);
extra_actions = purple_request_cpar_get_extra_actions(cpar);
- for (it = extra_actions; it; it = it->next->next) {
- const gchar *label = it->data;
- PurpleRequestFieldsCb *cb = it->next->data;
+ for (GSList *it = extra_actions; it; it = it->next) {
+ PurpleKeyValuePair *extra_action = it->data;
- GntWidget *button = gnt_button_new(label);
+ GntWidget *button = gnt_button_new(extra_action->key);
gnt_box_add_widget_in_front(GNT_BOX(box), button);
g_object_set_data(G_OBJECT(button), "ui-handle", window);
- g_object_set_data(G_OBJECT(button), "extra-cb", cb);
+ g_object_set_data(G_OBJECT(button), "extra-cb", extra_action->value);
g_object_set_data(G_OBJECT(button), "extra-cb-data", userdata);
g_signal_connect(G_OBJECT(button), "activate",
G_CALLBACK(multifield_extra_cb), allfields);
--- a/libpurple/account.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/account.c Thu Apr 09 08:47:36 2020 +0000
@@ -1792,26 +1792,19 @@
purple_account_set_status(PurpleAccount *account, const char *status_id,
gboolean active, ...)
{
- GList *attrs = NULL;
- const gchar *id;
- gpointer data;
+ GHashTable *attrs;
va_list args;
va_start(args, active);
- 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_account_set_status_list(account, status_id, active, attrs);
- g_list_free(attrs);
+ attrs = purple_attrs_from_vargs(args);
+ purple_account_set_status_attrs(account, status_id, active, attrs);
+ g_hash_table_destroy(attrs);
va_end(args);
}
void
-purple_account_set_status_list(PurpleAccount *account, const char *status_id,
- gboolean active, GList *attrs)
+purple_account_set_status_attrs(PurpleAccount *account, const char *status_id,
+ gboolean active, GHashTable *attrs)
{
PurpleStatus *status;
@@ -1829,7 +1822,7 @@
}
if (active || purple_status_is_independent(status))
- purple_status_set_active_with_attrs_list(status, active, attrs);
+ purple_status_set_active_with_attrs_dict(status, active, attrs);
/*
* Our current statuses are saved to accounts.xml (so that when we
--- a/libpurple/account.h Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/account.h Thu Apr 09 08:47:36 2020 +0000
@@ -444,8 +444,9 @@
* @status_id: The ID of the status.
* @active: Whether @a status_id is to be activated (%TRUE) or
* deactivated (%FALSE).
- * @attrs: (element-type utf8): A list of <type>const char *</type> attribute names followed by
- * <type>const char *</type> attribute values for the status.
+ * @attrs: (element-type utf8 gpointer): A hash table of
+ * <type>const char *</type> attribute names followed by
+ * <type>gpointer</type> attribute values for the status.
* (For example, one pair might be <literal>"message"</literal>
* followed by <literal>"hello, talk to me!"</literal>.)
*
@@ -455,9 +456,11 @@
* You can only deactivate an exclusive status by activating another exclusive
* status. So, if @a status_id is an exclusive status and @a active is @c
* FALSE, this function does nothing.
+ *
+ * Since: 3.0.0
*/
-void purple_account_set_status_list(PurpleAccount *account,
- const char *status_id, gboolean active, GList *attrs);
+void purple_account_set_status_attrs(PurpleAccount *account,
+ const char *status_id, gboolean active, GHashTable *attrs);
/**
* purple_account_set_public_alias:
--- a/libpurple/accounts.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/accounts.c Thu Apr 09 08:47:36 2020 +0000
@@ -200,10 +200,10 @@
migrate_xmpp_encryption(account);
}
-static GList *
+static GHashTable *
parse_status_attrs(PurpleXmlNode *node, PurpleStatus *status)
{
- GList *list = NULL;
+ GHashTable *attrs = g_hash_table_new(g_str_hash, g_str_equal);
PurpleXmlNode *child;
GValue *attr_value;
@@ -220,21 +220,18 @@
if (!attr_value)
continue;
- list = g_list_append(list, (char *)id);
-
switch (G_VALUE_TYPE(attr_value))
{
case G_TYPE_STRING:
- list = g_list_append(list, (char *)value);
+ g_hash_table_insert(attrs, id, (char *)value);
break;
case G_TYPE_INT:
case G_TYPE_BOOLEAN:
{
int v;
- if (sscanf(value, "%d", &v) == 1)
- list = g_list_append(list, GINT_TO_POINTER(v));
- else
- list = g_list_remove(list, id);
+ if (sscanf(value, "%d", &v) == 1) {
+ g_hash_table_insert(attrs, id, GINT_TO_POINTER(v));
+ }
break;
}
default:
@@ -242,7 +239,7 @@
}
}
- return list;
+ return attrs;
}
static void
@@ -252,7 +249,7 @@
const char *data;
const char *type;
PurpleXmlNode *child;
- GList *attrs = NULL;
+ GHashTable *attrs = NULL;
/* Get the active/inactive state */
data = purple_xmlnode_get_attrib(node, "active");
@@ -278,9 +275,9 @@
purple_account_get_status(account, type));
}
- purple_account_set_status_list(account, type, active, attrs);
+ purple_account_set_status_attrs(account, type, active, attrs);
- g_list_free(attrs);
+ g_hash_table_destroy(attrs);
}
static void
--- a/libpurple/media/codec.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/media/codec.c Thu Apr 09 08:47:36 2020 +0000
@@ -267,9 +267,7 @@
priv = purple_media_codec_get_instance_private(codec);
- new_param = g_new0(PurpleKeyValuePair, 1);
- new_param->key = g_strdup(name);
- new_param->value = g_strdup(value);
+ new_param = purple_key_value_pair_new_full(name, g_strdup(value), g_free);
priv->optional_params = g_list_append(
priv->optional_params, new_param);
@@ -286,12 +284,9 @@
priv = purple_media_codec_get_instance_private(codec);
- g_free(param->key);
- g_free(param->value);
-
priv->optional_params =
g_list_remove(priv->optional_params, param);
- g_free(param);
+ purple_key_value_pair_free(param);
g_object_notify_by_pspec(G_OBJECT(codec), properties[PROP_OPTIONAL_PARAMS]);
}
--- a/libpurple/pluginpref.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/pluginpref.c Thu Apr 09 08:47:36 2020 +0000
@@ -141,18 +141,11 @@
void
purple_plugin_pref_destroy(PurplePluginPref *pref)
{
- GList *tmp;
g_return_if_fail(pref != NULL);
g_free(pref->name);
g_free(pref->label);
- tmp = pref->choices;
- while(tmp) {
- g_free(tmp->data);
- /* Remove the string, and the data entries */
- tmp = g_list_delete_link(tmp, tmp);
- tmp = g_list_delete_link(tmp, tmp);
- }
+ g_list_free_full(pref->choices, (GDestroyNotify)purple_key_value_pair_free);
g_free(pref);
}
@@ -255,12 +248,15 @@
void
purple_plugin_pref_add_choice(PurplePluginPref *pref, const char *label, gpointer choice)
{
+ PurpleKeyValuePair *pref_choice;
+
g_return_if_fail(pref != NULL);
g_return_if_fail(label != NULL);
g_return_if_fail(choice || purple_prefs_get_pref_type(pref->name) == PURPLE_PREF_INT);
- pref->choices = g_list_append(pref->choices, g_strdup(label));
- pref->choices = g_list_append(pref->choices, choice);
+ pref_choice = purple_key_value_pair_new(label, choice);
+
+ pref->choices = g_list_append(pref->choices, pref_choice);
}
GList *
--- a/libpurple/pluginpref.h Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/pluginpref.h Thu Apr 09 08:47:36 2020 +0000
@@ -30,7 +30,7 @@
*/
typedef struct _PurplePluginPrefFrame PurplePluginPrefFrame;
-typedef struct _PurplePluginPref PurplePluginPref;
+typedef struct _PurplePluginPref PurplePluginPref;
/**
* PurpleStringFormatType:
@@ -245,7 +245,7 @@
*
* Get the choices for a choices plugin pref
*
- * Returns: (element-type void) (transfer none): GList of the choices
+ * Returns: (element-type PurpleKeyValuePair) (transfer none): GList of the choices
*/
GList *purple_plugin_pref_get_choices(PurplePluginPref *pref);
--- a/libpurple/protocols/bonjour/mdns_common.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c Thu Apr 09 08:47:36 2020 +0000
@@ -73,9 +73,8 @@
static inline GSList *
_add_txt_record(GSList *list, const gchar *key, const gchar *value)
{
- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1);
- kvp->key = g_strdup(key);
- kvp->value = g_strdup(get_max_txt_record_value(key, value));
+ const char *max_value = get_max_txt_record_value(key, value);
+ PurpleKeyValuePair *kvp = purple_key_value_pair_new_full(key, g_strdup(max_value), g_free);
return g_slist_prepend(list, kvp);
}
--- a/libpurple/protocols/gg/gg.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/gg/gg.c Thu Apr 09 08:47:36 2020 +0000
@@ -1040,9 +1040,7 @@
ggp_server_option = option;
#define ADD_VALUE(list, desc, v) { \
- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
- kvp->key = g_strdup((desc)); \
- kvp->value = g_strdup((v)); \
+ PurpleKeyValuePair *kvp = purple_key_value_pair_new_full((desc), g_strdup((v)), g_free); \
list = g_list_append(list, kvp); \
}
--- a/libpurple/protocols/jabber/gtalk.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/jabber/gtalk.c Thu Apr 09 08:47:36 2020 +0000
@@ -55,9 +55,7 @@
protocol->user_splits = g_list_append(protocol->user_splits, split);
#define ADD_VALUE(list, desc, v) { \
- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
- kvp->key = g_strdup((desc)); \
- kvp->value = g_strdup((v)); \
+ PurpleKeyValuePair *kvp = purple_key_value_pair_new_full((desc), g_strdup((v)), g_free); \
list = g_list_prepend(list, kvp); \
}
--- a/libpurple/protocols/jabber/jabber.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/jabber/jabber.c Thu Apr 09 08:47:36 2020 +0000
@@ -3387,7 +3387,7 @@
}
if (g_list_length(purple_request_field_choice_get_elements(
- field)) <= 2) {
+ field)) <= 1) {
gchar *name;
gboolean result;
purple_request_field_destroy(field);
--- a/libpurple/protocols/jabber/xmpp.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/jabber/xmpp.c Thu Apr 09 08:47:36 2020 +0000
@@ -46,9 +46,7 @@
protocol->user_splits = g_list_append(protocol->user_splits, split);
#define ADD_VALUE(list, desc, v) { \
- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
- kvp->key = g_strdup((desc)); \
- kvp->value = g_strdup((v)); \
+ PurpleKeyValuePair *kvp = purple_key_value_pair_new_full((desc), g_strdup((v)), g_free); \
list = g_list_prepend(list, kvp); \
}
--- a/libpurple/protocols/silc/silc.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/protocols/silc/silc.c Thu Apr 09 08:47:36 2020 +0000
@@ -2171,9 +2171,7 @@
protocol->account_options = g_list_append(protocol->account_options, option);
for (i = 0; silc_default_ciphers[i].name; i++) {
- kvp = g_new0(PurpleKeyValuePair, 1);
- kvp->key = g_strdup(silc_default_ciphers[i].name);
- kvp->value = g_strdup(silc_default_ciphers[i].name);
+ kvp = purple_key_value_pair_new_full(silc_default_ciphers[i].name, g_strdup(silc_default_ciphers[i].name), g_free);
list = g_list_append(list, kvp);
}
option = purple_account_option_list_new(_("Cipher"), "cipher", list);
@@ -2181,9 +2179,7 @@
list = NULL;
for (i = 0; silc_default_hmacs[i].name; i++) {
- kvp = g_new0(PurpleKeyValuePair, 1);
- kvp->key = g_strdup(silc_default_hmacs[i].name);
- kvp->value = g_strdup(silc_default_hmacs[i].name);
+ kvp = purple_key_value_pair_new_full(silc_default_hmacs[i].name, g_strdup(silc_default_hmacs[i].name), g_free);
list = g_list_append(list, kvp);
}
option = purple_account_option_list_new(_("HMAC"), "hmac", list);
--- a/libpurple/purpleaccountoption.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/purpleaccountoption.c Thu Apr 09 08:47:36 2020 +0000
@@ -185,7 +185,7 @@
else if (option->type == PURPLE_PREF_STRING_LIST)
{
g_list_free_full(option->default_value.list,
- (GDestroyNotify)purple_key_value_pair_free);
+ (GDestroyNotify)purple_key_value_pair_free);
}
g_free(option);
@@ -247,7 +247,7 @@
g_return_if_fail(option->type == PURPLE_PREF_STRING_LIST);
g_list_free_full(option->default_value.list,
- (GDestroyNotify)purple_key_value_pair_free);
+ (GDestroyNotify)purple_key_value_pair_free);
option->default_value.list = values;
}
@@ -263,9 +263,7 @@
g_return_if_fail(value != NULL);
g_return_if_fail(option->type == PURPLE_PREF_STRING_LIST);
- kvp = g_new0(PurpleKeyValuePair, 1);
- kvp->key = g_strdup(key);
- kvp->value = g_strdup(value);
+ kvp = purple_key_value_pair_new_full(key, g_strdup(value), g_free);
option->default_value.list = g_list_append(option->default_value.list,
kvp);
--- a/libpurple/request.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/request.c Thu Apr 09 08:47:36 2020 +0000
@@ -395,32 +395,25 @@
purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...)
{
va_list args;
- GSList *extra = NULL, *it;
-
- it = cpar->extra_actions;
- while (it != NULL) {
- gchar *label = it->data;
-
- g_free(label);
- it = g_slist_next(it);
- if (it == NULL)
- break;
- it = g_slist_next(it);
- }
+ GSList *extra = NULL;
+
+ g_slist_free_full(cpar->extra_actions, (GDestroyNotify)purple_key_value_pair_free);
va_start(args, cpar);
while (TRUE) {
const gchar *label;
PurpleRequestFieldsCb cb;
+ PurpleKeyValuePair *extra_action;
label = va_arg(args, const gchar*);
if (label == NULL)
break;
cb = va_arg(args, PurpleRequestFieldsCb);
- extra = g_slist_append(extra, g_strdup(label));
- extra = g_slist_append(extra, cb);
+ extra_action = purple_key_value_pair_new(label, cb);
+
+ extra = g_slist_append(extra, extra_action);
}
va_end(args);
@@ -946,22 +939,14 @@
}
else if (field->type == PURPLE_REQUEST_FIELD_CHOICE)
{
- if (field->u.choice.elements != NULL)
- {
- GList *it = field->u.choice.elements;
- while (it != NULL) {
- g_free(it->data);
- it = g_list_next(it); /* value */
- if (it == NULL) {
- g_warn_if_reached();
- break;
- }
- if (it->data && field->u.choice.data_destroy)
- field->u.choice.data_destroy(it->data);
- it = g_list_next(it); /* next label */
- }
- g_list_free(field->u.choice.elements);
+ for (GList *it = field->u.choice.elements; it != NULL; it = g_list_next(it)) {
+ PurpleKeyValuePair *choice = it->data;
+
+ if (choice->value && field->u.choice.data_destroy)
+ field->u.choice.data_destroy(choice->value);
+ purple_key_value_pair_free(choice);
}
+ g_list_free(field->u.choice.elements);
}
else if (field->type == PURPLE_REQUEST_FIELD_LIST)
{
@@ -1477,14 +1462,16 @@
purple_request_field_choice_add(PurpleRequestField *field, const char *label,
gpointer value)
{
+ PurpleKeyValuePair *choice;
+
g_return_if_fail(field != NULL);
g_return_if_fail(label != NULL);
g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_CHOICE);
+ choice = purple_key_value_pair_new(label, value);
+
field->u.choice.elements = g_list_append(field->u.choice.elements,
- g_strdup(label));
- field->u.choice.elements = g_list_append(field->u.choice.elements,
- value);
+ choice);
}
void
--- a/libpurple/request.h Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/request.h Thu Apr 09 08:47:36 2020 +0000
@@ -528,7 +528,7 @@
*
* Gets extra actions for the PurpleRequestFields dialog.
*
- * Returns: (element-type void) (transfer none): A list of actions (pairs of arguments, as in
+ * Returns: (element-type PurpleKeyValuePair) (transfer none): A list of actions (pairs of arguments, as in
* setter).
*/
GSList *
@@ -1472,7 +1472,7 @@
*
* Returns a list of elements in a choice field.
*
- * Returns: (element-type void) (transfer none): The list of pairs of {label, value}.
+ * Returns: (element-type PurpleKeyValuePair) (transfer none): The list of pairs of {label, value}.
*/
GList *
purple_request_field_choice_get_elements(const PurpleRequestField *field);
--- a/libpurple/status.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/status.c Thu Apr 09 08:47:36 2020 +0000
@@ -702,7 +702,7 @@
void
purple_status_set_active(PurpleStatus *status, gboolean active)
{
- purple_status_set_active_with_attrs_list(status, active, NULL);
+ purple_status_set_active_with_attrs_dict(status, active, NULL);
}
/*
@@ -714,31 +714,27 @@
void
purple_status_set_active_with_attrs(PurpleStatus *status, gboolean active, va_list args)
{
- GList *attrs = NULL;
- const gchar *id;
- gpointer data;
+ GHashTable *attrs = purple_attrs_from_vargs(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);
- g_list_free(attrs);
+ purple_status_set_active_with_attrs_dict(status, active, attrs);
+ g_hash_table_destroy(attrs);
}
void
-purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
- GList *attrs)
+purple_status_set_active_with_attrs_dict(PurpleStatus *status, gboolean active,
+ GHashTable *attrs)
{
PurpleStatusPrivate *priv = NULL;
gboolean changed = FALSE;
+ GHashTableIter iter;
+ gchar *id;
+ gpointer data;
GList *l;
GList *specified_attr_ids = NULL;
PurpleStatusType *status_type;
g_return_if_fail(PURPLE_IS_STATUS(status));
+ g_return_if_fail(attrs != NULL);
priv = purple_status_get_instance_private(status);
@@ -758,21 +754,16 @@
priv->active = active;
/* Set any attributes */
- l = attrs;
- while (l != NULL)
- {
- const gchar *id;
+ g_hash_table_iter_init(&iter, attrs);
+ while (g_hash_table_iter_next(&iter, (gpointer *)&id, (gpointer *)&data)) {
GValue *value;
- id = l->data;
- l = l->next;
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.\n", id, priv->status_type->name);
/* Skip over the data and move on to the next attribute */
- l = l->next;
continue;
}
@@ -780,8 +771,7 @@
if (G_VALUE_TYPE(value) == G_TYPE_STRING)
{
- const gchar *string_data = l->data;
- l = l->next;
+ const gchar *string_data = data;
if (purple_strequal(string_data, g_value_get_string(value)))
continue;
status_set_attr_string(status, id, string_data);
@@ -789,8 +779,7 @@
}
else if (G_VALUE_TYPE(value) == G_TYPE_INT)
{
- int int_data = GPOINTER_TO_INT(l->data);
- l = l->next;
+ int int_data = GPOINTER_TO_INT(data);
if (int_data == g_value_get_int(value))
continue;
status_set_attr_int(status, id, int_data);
@@ -798,18 +787,12 @@
}
else if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN)
{
- gboolean boolean_data = GPOINTER_TO_INT(l->data);
- l = l->next;
+ 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;
}
- else
- {
- /* We don't know what the data is--skip over it */
- l = l->next;
- }
}
/* Reset any unspecified attributes to their default value */
@@ -1369,3 +1352,22 @@
{
purple_prefs_disconnect_by_handle(purple_prefs_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;
+}
--- a/libpurple/status.h Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/status.h Thu Apr 09 08:47:36 2020 +0000
@@ -495,17 +495,18 @@
* purple_status_set_active_with_attrs_list:
* @status: The status.
* @active: The active state.
- * @attrs: (element-type void): A list of attributes to set on the status. This list is
- * composed of key/value pairs, where each key is a valid
- * attribute name for this PurpleStatusType. The list is
- * not modified or freed by this function.
+ * @attrs: (element-type utf8 gpointer): A hash table of attributes to set on the status.
+ * This hash table's keys are valid attribute names for this PurpleStatusType.
+ * The hash table is not modified or freed by this function.
*
* Sets whether or not a status is active.
*
* This should only be called by the account, conversation, and buddy APIs.
+ *
+ * Since: 3.0.0
*/
-void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
- GList *attrs);
+void purple_status_set_active_with_attrs_dict(PurpleStatus *status, gboolean active,
+ GHashTable *attrs);
/**
* purple_status_get_status_type:
@@ -700,6 +701,25 @@
*/
void purple_statuses_uninit(void);
+/**************************************************************************/
+/* Helpers */
+/**************************************************************************/
+
+/**
+ * purple_attrs_from_vargs:
+ * @args: A list of attributes to parse. This list is
+ * composed of key/value pairs, where each key is a valid
+ * attribute name for this PurpleStatusType. The list should
+ * be NULL terminated.
+ *
+ * Returns a hash table of attributes constructed from args.
+ *
+ * Returns: (element-type utf8 gpointer) (transfer container): The hash table of attributes.
+ *
+ * Since: 3.0.0
+ */
+GHashTable *purple_attrs_from_vargs(va_list args);
+
G_END_DECLS
#endif /* PURPLE_STATUS_H */
--- a/libpurple/util.c Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/util.c Thu Apr 09 08:47:36 2020 +0000
@@ -3782,12 +3782,40 @@
return g_string_free(string, FALSE);
}
-void purple_key_value_pair_free(PurpleKeyValuePair *kvp)
+PurpleKeyValuePair *
+purple_key_value_pair_new(const char *key, gpointer value)
+{
+ PurpleKeyValuePair *kvp;
+
+ kvp = g_new0(PurpleKeyValuePair, 1);
+ kvp->key = g_strdup(key);
+ kvp->value = value;
+ kvp->value_destroy_func = NULL;
+
+ return kvp;
+}
+
+PurpleKeyValuePair *
+purple_key_value_pair_new_full(const char *key, gpointer value, GDestroyNotify value_destroy_func)
+{
+ PurpleKeyValuePair *kvp = purple_key_value_pair_new(key, value);
+
+ kvp->value_destroy_func = value_destroy_func;
+
+ return kvp;
+}
+
+void
+purple_key_value_pair_free(PurpleKeyValuePair *kvp)
{
g_return_if_fail(kvp != NULL);
- g_free(kvp->value);
g_free(kvp->key);
+
+ if (kvp->value_destroy_func) {
+ kvp->value_destroy_func(kvp->value);
+ }
+
g_free(kvp);
}
--- a/libpurple/util.h Wed Apr 01 18:07:49 2020 +0000
+++ b/libpurple/util.h Thu Apr 09 08:47:36 2020 +0000
@@ -58,7 +58,7 @@
{
gchar *key;
void *value;
-
+ GDestroyNotify value_destroy_func;
};
G_BEGIN_DECLS
@@ -89,10 +89,41 @@
const char *album, gpointer unused);
/**
+ * purple_key_value_pair_new:
+ * @key: The key part of PurpleKeyValuePair
+ * @value: The value part of PurpleKeyValuePair
+ *
+ * Creates a new PurpleKeyValuePair allocating memory for @key,
+ * free value function is NULL.
+ *
+ * Returns: The created PurpleKeyValuePair
+ *
+ * Since: 3.0.0
+ */
+PurpleKeyValuePair *purple_key_value_pair_new(const char *key, gpointer value);
+
+/**
+ * purple_key_value_pair_new_full:
+ * @key: The key part of PurpleKeyValuePair
+ * @value: The value part of PurpleKeyValuePair
+ * @value_destroy_func: a function to free the memory for the @value
+ *
+ * Creates a new PurpleKeyValuePair allocating memory for @key,
+ * set free value function to @value_destroy_func.
+ *
+ * Returns: The created PurpleKeyValuePair
+ *
+ * Since: 3.0.0
+ */
+PurpleKeyValuePair *purple_key_value_pair_new_full(const char *key, gpointer value, GDestroyNotify value_destroy_func);
+
+/**
* purple_key_value_pair_free:
* @kvp: The PurpleKeyValuePair to free.
*
- * Frees a PurpleKeyValuePair.
+ * Frees @kvp.
+ *
+ * Since: 3.0.0
*/
void purple_key_value_pair_free(PurpleKeyValuePair *kvp);
--- a/pidgin/gtkprefs.c Wed Apr 01 18:07:49 2020 +0000
+++ b/pidgin/gtkprefs.c Thu Apr 09 08:47:36 2020 +0000
@@ -481,7 +481,6 @@
{
GtkWidget *dropdown;
GtkWidget *label = NULL;
- gchar *text;
GtkListStore *store = NULL;
GtkTreeIter iter;
GtkTreeIter active;
@@ -506,33 +505,35 @@
*dropdown_out = GTK_COMBO_BOX(dropdown);
g_object_set_data(G_OBJECT(dropdown), "type", GINT_TO_POINTER(initial.type));
- while (menuitems != NULL && (text = (char *)menuitems->data) != NULL) {
+ for (; menuitems != NULL; menuitems = g_list_next(menuitems)) {
+ const PurpleKeyValuePair *menu_item = menuitems->data;
int int_value = 0;
const char *str_value = NULL;
gboolean bool_value = FALSE;
- menuitems = g_list_next(menuitems);
- g_return_val_if_fail(menuitems != NULL, NULL);
+ if (menu_item->key == NULL) {
+ break;
+ }
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
- PREF_DROPDOWN_TEXT, text,
+ PREF_DROPDOWN_TEXT, menu_item->key,
-1);
if (initial.type == PURPLE_PREF_INT) {
- int_value = GPOINTER_TO_INT(menuitems->data);
+ int_value = GPOINTER_TO_INT(menu_item->value);
gtk_list_store_set(store, &iter,
PREF_DROPDOWN_VALUE, int_value,
-1);
}
else if (initial.type == PURPLE_PREF_STRING) {
- str_value = (const char *)menuitems->data;
+ str_value = (const char *)menu_item->value;
gtk_list_store_set(store, &iter,
PREF_DROPDOWN_VALUE, str_value,
-1);
}
else if (initial.type == PURPLE_PREF_BOOLEAN) {
- bool_value = (gboolean)GPOINTER_TO_INT(menuitems->data);
+ bool_value = (gboolean)GPOINTER_TO_INT(menu_item->value);
gtk_list_store_set(store, &iter,
PREF_DROPDOWN_VALUE, bool_value,
-1);
@@ -547,8 +548,6 @@
active = iter;
}
-
- menuitems = g_list_next(menuitems);
}
renderer = gtk_cell_renderer_text_new();
--- a/pidgin/gtkprefs.h Wed Apr 01 18:07:49 2020 +0000
+++ b/pidgin/gtkprefs.h Thu Apr 09 08:47:36 2020 +0000
@@ -136,7 +136,7 @@
* @title: The text to be displayed as the dropdown label
* @type: The type of preference to be stored in the dropdown
* @key: The key of the pref that will be represented by the dropdown
- * @menuitems: (element-type void): The choices to be added to the dropdown, choices should
+ * @menuitems: (element-type PurpleKeyValuePair): The choices to be added to the dropdown, choices should
* be paired as label/value
*
* Add a new dropdown representing a preference of the specified type
--- a/pidgin/gtkrequest.c Wed Apr 01 18:07:49 2020 +0000
+++ b/pidgin/gtkrequest.c Thu Apr 09 08:47:36 2020 +0000
@@ -1221,8 +1221,7 @@
{
GtkWidget *widget;
GList *elements = purple_request_field_choice_get_elements(field);
- int num_labels = g_list_length(elements) / 2;
- GList *l;
+ guint num_labels = g_list_length(elements);
gpointer *values = g_new(gpointer, num_labels);
gpointer default_value;
gboolean default_found = FALSE;
@@ -1235,23 +1234,16 @@
widget = gtk_combo_box_text_new();
i = 0;
- l = elements;
- while (l != NULL)
+ for (GList *l = elements; l != NULL; l = g_list_next(l))
{
- const char *text;
- gpointer *value;
-
- text = l->data;
- l = g_list_next(l);
- value = l->data;
- l = g_list_next(l);
-
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget), text);
- if (value == default_value) {
+ PurpleKeyValuePair *choice = l->data;
+
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(widget), choice->key);
+ if (choice->value == default_value) {
default_index = i;
default_found = TRUE;
}
- values[i++] = value;
+ values[i++] = choice->value;
}
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), default_index);
@@ -1277,29 +1269,22 @@
gtk_widget_set_tooltip_text(widget, purple_request_field_get_tooltip(field));
i = 0;
- l = elements;
- while (l != NULL)
+ for (GList *l = elements; l != NULL; l = g_list_next(l))
{
- const char *text;
- gpointer *value;
-
- text = l->data;
- l = g_list_next(l);
- value = l->data;
- l = g_list_next(l);
+ PurpleKeyValuePair *choice = l->data;
radio = gtk_radio_button_new_with_label_from_widget(
- GTK_RADIO_BUTTON(first_radio), text);
+ GTK_RADIO_BUTTON(first_radio), choice->key);
g_object_set_data(G_OBJECT(radio), "box", box);
if (first_radio == NULL)
first_radio = radio;
- if (value == default_value) {
+ if (choice->value == default_value) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
default_found = TRUE;
}
- values[i++] = value;
+ values[i++] = choice->value;
gtk_box_pack_start(GTK_BOX(box), radio, TRUE, TRUE, 0);
gtk_widget_show(radio);
@@ -1884,8 +1869,8 @@
char *label_text;
char *primary_esc, *secondary_esc;
const gboolean compact = purple_request_cpar_is_compact(cpar);
- GSList *extra_actions, *it;
- size_t extra_actions_count, i;
+ GSList *extra_actions;
+ size_t i;
const gchar **tab_names;
guint tab_count;
gboolean ok_btn = (ok_text != NULL);
@@ -1898,7 +1883,6 @@
purple_request_fields_set_ui_data(fields, data);
extra_actions = purple_request_cpar_get_extra_actions(cpar);
- extra_actions_count = g_slist_length(extra_actions) / 2;
data->cb_count = 2;
data->cbs = g_new0(GCallback, 2);
@@ -1929,14 +1913,12 @@
pidgin_request_add_help(GTK_DIALOG(win), cpar);
- it = extra_actions;
- for (i = 0; i < extra_actions_count; i++, it = it->next->next) {
- const gchar *label = it->data;
- PurpleRequestFieldsCb *cb = it->next->data;
-
- button = pidgin_dialog_add_button(GTK_DIALOG(win), label,
+ for (GSList *it = extra_actions; it != NULL; it = it->next) {
+ PurpleKeyValuePair *extra_action = it->data;
+
+ button = pidgin_dialog_add_button(GTK_DIALOG(win), extra_action->key,
G_CALLBACK(multifield_extra_cb), data);
- g_object_set_data(G_OBJECT(button), "extra-cb", cb);
+ g_object_set_data(G_OBJECT(button), "extra-cb", extra_action->value);
}
/* Cancel button */