# HG changeset patch # User Christian Hammond # Date 1053903079 0 # Node ID bf2a7a7b739d43379d68a239abe57fbe34a92e5b # Parent e9b9fbf89c426728792dc3aed6e9815679525c82 [gaim-migrate @ 5918] Reworked the group support. You should now be able to delete groups by dragging a user into them and then back out. I stress _should_. This will likely have bugs. I cleaned up the ones I found, I think, but I'm not 100% confident here :) Please test! Preferably on test accounts, but it won't kill things, just reorder stuff. committer: Tailor Script diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/Makefile.am --- a/src/protocols/msn/Makefile.am Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/Makefile.am Sun May 25 22:51:19 2003 +0000 @@ -9,6 +9,8 @@ dispatch.h \ error.c \ error.h \ + group.c \ + group.h \ md5.h \ msg.c \ msg.h \ diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/group.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/msn/group.c Sun May 25 22:51:19 2003 +0000 @@ -0,0 +1,274 @@ +/** + * @file group.c Group functions + * + * gaim + * + * Copyright (C) 2003 Christian Hammond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "msn.h" +#include "group.h" + +MsnGroup * +msn_group_new(MsnSession *session, int id, const char *name) +{ + MsnGroup *group; + + g_return_val_if_fail(session != NULL, NULL); + g_return_val_if_fail(id >= 0, NULL); + g_return_val_if_fail(name != NULL, NULL); + + group = msn_groups_find_with_id(session->groups, id); + + if (group == NULL) { + group = g_new0(MsnGroup, 1); + + group->session = session; + group->id = id; + group->name = g_strdup(name); + group->users = msn_users_new(); + } + + msn_group_ref(group); + + return group; +} + +void +msn_group_destroy(MsnGroup *group) +{ + g_return_if_fail(group != NULL); + + if (group->ref_count > 0) { + msn_group_unref(group); + + return; + } + + if (group->session != NULL && group->session->groups != NULL) + msn_groups_remove(group->session->groups, group); + + msn_users_destroy(group->users); + + g_free(group->name); + g_free(group); +} + +MsnGroup * +msn_group_ref(MsnGroup *group) +{ + g_return_val_if_fail(group != NULL, NULL); + + group->ref_count++; + + return group; +} + +MsnGroup * +msn_group_unref(MsnGroup *group) +{ + g_return_val_if_fail(group != NULL, NULL); + + if (group->ref_count <= 0) + return NULL; + + group->ref_count--; + + if (group->ref_count == 0) { + msn_group_destroy(group); + + return NULL; + } + + return group; +} + +void +msn_group_set_id(MsnGroup *group, int id) +{ + g_return_if_fail(group != NULL); + g_return_if_fail(id >= 0); + + group->id = id; +} + +void +msn_group_set_name(MsnGroup *group, const char *name) +{ + g_return_if_fail(group != NULL); + g_return_if_fail(name != NULL); + + if (group->name != NULL) + g_free(group->name); + + group->name = g_strdup(name); +} + +int +msn_group_get_id(const MsnGroup *group) +{ + g_return_val_if_fail(group != NULL, -1); + + return group->id; +} + +const char * +msn_group_get_name(const MsnGroup *group) +{ + g_return_val_if_fail(group != NULL, NULL); + + return group->name; +} + +void +msn_group_add_user(MsnGroup *group, MsnUser *user) +{ + g_return_if_fail(group != NULL); + g_return_if_fail(user != NULL); + + msn_users_add(group->users, user); + + msn_user_ref(user); + + gaim_debug(GAIM_DEBUG_INFO, "msn", "Adding user %s to group %s (%d)\n", + msn_user_get_passport(user), msn_group_get_name(group), + msn_group_get_id(group)); +} + +void +msn_group_remove_user(MsnGroup *group, MsnUser *user) +{ + g_return_if_fail(group != NULL); + g_return_if_fail(user != NULL); + + msn_users_remove(group->users, user); + + msn_user_unref(user); +} + +MsnUsers * +msn_group_get_users(const MsnGroup *group) +{ + g_return_val_if_fail(group != NULL, NULL); + + return group->users; +} + + +MsnGroups * +msn_groups_new(void) +{ + return g_new0(MsnGroups, 1); +} + +void +msn_groups_destroy(MsnGroups *groups) +{ + g_return_if_fail(groups != NULL); + + while (groups->groups != NULL) + msn_group_destroy(groups->groups->data); + + /* See if we've leaked anybody. */ + while (groups->groups != NULL) { + gaim_debug(GAIM_DEBUG_WARNING, "msn", + "Leaking group %s (id %d)\n", + msn_group_get_name(groups->groups->data), + msn_group_get_id(groups->groups->data)); + } + + g_free(groups); +} + +void +msn_groups_add(MsnGroups *groups, MsnGroup *group) +{ + g_return_if_fail(groups != NULL); + g_return_if_fail(group != NULL); + + groups->groups = g_list_append(groups->groups, group); + + groups->count++; + + gaim_debug(GAIM_DEBUG_INFO, "msn", "Adding group %s (%d)\n", + msn_group_get_name(group), msn_group_get_id(group)); +} + +void +msn_groups_remove(MsnGroups *groups, MsnGroup *group) +{ + g_return_if_fail(groups != NULL); + g_return_if_fail(group != NULL); + + gaim_debug(GAIM_DEBUG_INFO, "msn", "Removing group %s (%d)\n", + msn_group_get_name(group), msn_group_get_id(group)); + + groups->groups = g_list_remove(groups->groups, group); + + groups->count--; +} + +size_t +msn_groups_get_count(const MsnGroups *groups) +{ + g_return_val_if_fail(groups != NULL, 0); + + return groups->count; +} + +GList * +msn_groups_get_list(const MsnGroups *groups) +{ + g_return_val_if_fail(groups != NULL, NULL); + + return groups->groups; +} + +MsnGroup * +msn_groups_find_with_id(MsnGroups *groups, int id) +{ + GList *l; + + g_return_val_if_fail(groups != NULL, NULL); + g_return_val_if_fail(id >= 0, NULL); + + for (l = groups->groups; l != NULL; l = l->next) { + MsnGroup *group = l->data; + + if (group->id == id) + return group; + } + + return NULL; +} + +MsnGroup * +msn_groups_find_with_name(MsnGroups *groups, const char *name) +{ + GList *l; + + g_return_val_if_fail(groups != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + + for (l = groups->groups; l != NULL; l = l->next) { + MsnGroup *group = l->data; + + if (group->name != NULL && !g_ascii_strcasecmp(name, group->name)) + return group; + } + + return NULL; +} diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/group.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/msn/group.h Sun May 25 22:51:19 2003 +0000 @@ -0,0 +1,233 @@ +/** + * @file group.h Group functions + * + * gaim + * + * Copyright (C) 2003 Christian Hammond + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _MSN_GROUP_H_ +#define _MSN_GROUP_H_ + +typedef struct _MsnGroup MsnGroup; +typedef struct _MsnGroups MsnGroups; + +#include "session.h" +#include "user.h" + +/** + * A group. + */ +struct _MsnGroup +{ + size_t ref_count; /**< The reference count. */ + + MsnSession *session; /**< The MSN session. */ + + int id; /**< The group ID. */ + char *name; /**< The name of the group. */ + + MsnUsers *users; /**< The users in the group. */ +}; + +/** + * A list of groups. + */ +struct _MsnGroups +{ + size_t count; /**< The number of groups. */ + + GList *groups; /**< The list of groups. */ +}; + +/**************************************************************************/ +/** @name Group API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a new group structure. + * + * @param session The MSN session. + * @param id The group ID. + * @param name The name of the group. + * + * @return A new group structure. + */ +MsnGroup *msn_group_new(MsnSession *session, int id, const char *name); + +/** + * Destroys a group structure. + * + * @param group The group to destroy. + */ +void msn_group_destroy(MsnGroup *group); + +/** + * Increments the reference count on a group. + * + * @param group The group. + * + * @return @a group + */ +MsnGroup *msn_group_ref(MsnGroup *group); + +/** + * Decrements the reference count on a group. + * + * This will destroy the structure if the count hits 0. + * + * @param group The group. + * + * @return @a group, or @c NULL if the new count is 0. + */ +MsnGroup *msn_group_unref(MsnGroup *group); + +/** + * Sets the ID for a group. + * + * @param group The group. + * @param id The ID. + */ +void msn_group_set_id(MsnGroup *group, int id); + +/** + * Sets the name for a group. + * + * @param group The group. + * @param name The name. + */ +void msn_group_set_name(MsnGroup *group, const char *name); + +/** + * Returns the ID for a group. + * + * @param group The group. + * + * @return The ID. + */ +int msn_group_get_id(const MsnGroup *group); + +/** + * Returns the name for a group. + * + * @param group The group. + * + * @return The name. + */ +const char *msn_group_get_name(const MsnGroup *group); + +/** + * Adds a user to the group. + * + * @param group The group. + * @param user The user. + */ +void msn_group_add_user(MsnGroup *group, MsnUser *user); + +/** + * Removes a user from the group. + * + * @param group The group. + * @param user The user. + */ +void msn_group_remove_user(MsnGroup *group, MsnUser *user); + +/** + * Returns the users in a group. + * + * @param group The group. + * + * @return The list of users. + */ +MsnUsers *msn_group_get_users(const MsnGroup *group); + +/*@}*/ + +/**************************************************************************/ +/** @name Group List API */ +/**************************************************************************/ +/*@{*/ + +/** + * Creates a new MsnGroups structure. + * + * @return A new MsnGroups structure. + */ +MsnGroups *msn_groups_new(void); + +/** + * Destroys a groups list. + * + * @param groups The groups list. + */ +void msn_groups_destroy(MsnGroups *groups); + +/** + * Adds a group to a groups list. + * + * @param groups The groups list. + * @param group The group. + */ +void msn_groups_add(MsnGroups *groups, MsnGroup *group); + +/** + * Removes a group from a groups list. + * + * @param groups The groups list. + * @param group The group. + */ +void msn_groups_remove(MsnGroups *groups, MsnGroup *group); + +/** + * Returns the number of groups in a groups list. + * + * @param groups The groups list. + * + * @return The number of groups. + */ +size_t msn_groups_get_count(const MsnGroups *groups); + +/** + * Finds a group with the specified ID. + * + * @param groups A list of groups. + * @param id The group ID. + * + * @return The group if found, or @c NULL otherwise. + */ +MsnGroup *msn_groups_find_with_id(MsnGroups *groups, int id); + +/** + * Returns a GList of all groups. + * + * @param groups The list of groups. + * + * @return A GList of all groups. + */ +GList *msn_groups_get_list(const MsnGroups *groups); + +/** + * Finds a group with the specified name. + * + * @param groups A list of groups. + * @param name The group name. + * + * @return The group if found, or @c NULL otherwise. + */ +MsnGroup *msn_groups_find_with_name(MsnGroups *groups, const char *name); + +#endif /* _MSN_GROUP_H_ */ diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/msn.c --- a/src/protocols/msn/msn.c Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/msn.c Sun May 25 22:51:19 2003 +0000 @@ -989,18 +989,20 @@ static void msn_group_buddy(struct gaim_connection *gc, const char *who, - const char *old_group, const char *new_group) + const char *old_group_name, const char *new_group_name) { MsnSession *session = gc->proto_data; char outparams[MSN_BUF_LEN]; - gint *old_group_id, *new_group_id; + MsnGroup *old_group, *new_group; + + old_group = msn_groups_find_with_name(session->groups, old_group_name); + new_group = msn_groups_find_with_name(session->groups, new_group_name); - old_group_id = g_hash_table_lookup(session->group_ids, old_group); - new_group_id = g_hash_table_lookup(session->group_ids, new_group); + gaim_debug(GAIM_DEBUG_MISC, "msn", "new_group = %p\n", new_group); - if (new_group_id == NULL) { + if (new_group == NULL) { g_snprintf(outparams, sizeof(outparams), "%s 0", - msn_url_encode(new_group)); + msn_url_encode(new_group_name)); if (!msn_servconn_send_command(session->notification_conn, "ADG", outparams)) { @@ -1010,12 +1012,18 @@ } /* I hate this. So much. */ - session->moving_buddy = TRUE; - session->dest_group_name = g_strdup(new_group); + session->moving_buddy = TRUE; + session->dest_group_name = g_strdup(new_group_name); + session->old_group = old_group; + + session->moving_user = + msn_users_find_with_passport(session->users, who); + + msn_user_ref(session->moving_user); } else { g_snprintf(outparams, sizeof(outparams), "FL %s %s %d", - who, who, *new_group_id); + who, who, msn_group_get_id(new_group)); if (!msn_servconn_send_command(session->notification_conn, "ADD", outparams)) { @@ -1025,9 +1033,9 @@ } } - if (old_group_id != NULL) { + if (old_group != NULL) { g_snprintf(outparams, sizeof(outparams), "FL %s %d", - who, *old_group_id); + who, msn_group_get_id(old_group)); if (!msn_servconn_send_command(session->notification_conn, "REM", outparams)) { @@ -1035,36 +1043,55 @@ signoff(gc); return; } + + if (msn_users_get_count(msn_group_get_users(old_group)) <= 0) { + g_snprintf(outparams, sizeof(outparams), "%d", + msn_group_get_id(old_group)); + + if (!msn_servconn_send_command(session->notification_conn, + "RMG", outparams)) { + + hide_login_progress(gc, _("Write error")); + signoff(gc); + return; + } + } } } static void -msn_rename_group(struct gaim_connection *gc, const char *old_group, - const char *new_group, GList *members) +msn_rename_group(struct gaim_connection *gc, const char *old_group_name, + const char *new_group_name, GList *members) { MsnSession *session = gc->proto_data; char outparams[MSN_BUF_LEN]; - int *group_id; + MsnGroup *old_group; - if (g_hash_table_lookup_extended(session->group_ids, old_group, - NULL, (gpointer)&group_id)) { + if ((old_group = msn_groups_find_with_name(session->groups, + old_group_name)) != NULL) { + g_snprintf(outparams, sizeof(outparams), "%d %s 0", - *group_id, msn_url_encode(new_group)); + msn_group_get_id(old_group), + msn_url_encode(new_group_name)); if (!msn_servconn_send_command(session->notification_conn, "REG", outparams)) { hide_login_progress(gc, _("Write error")); signoff(gc); + return; } + + msn_group_set_name(old_group, new_group_name); } else { g_snprintf(outparams, sizeof(outparams), "%s 0", - msn_url_encode(new_group)); + msn_url_encode(new_group_name)); if (!msn_servconn_send_command(session->notification_conn, "ADG", outparams)) { hide_login_progress(gc, _("Write error")); signoff(gc); + return; } } } diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/notification.c --- a/src/protocols/msn/notification.c Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/notification.c Sun May 25 22:51:19 2003 +0000 @@ -45,40 +45,55 @@ MsnSession *session = servconn->session; struct gaim_connection *gc = session->account->gc; struct buddy *b; + MsnGroup *group = NULL; + struct group *g = NULL; + int group_id; + + group_id = msn_user_get_group_id(user); + + if (group_id > -1) + group = msn_groups_find_with_id(session->groups, group_id); + + if (group == NULL) { + GList *l; + gaim_debug(GAIM_DEBUG_WARNING, "msn", + "Group ID %d for user %s was not defined.\n", + group_id, msn_user_get_passport(user)); + + /* Find a group that we can stick this guy into. Lamer. */ + l = msn_groups_get_list(session->groups); + + if (l != NULL) { + group = l->data; + + msn_user_set_group_id(user, msn_group_get_id(group)); + } + } + + if (group == NULL || + (g = gaim_find_group(msn_group_get_name(group))) == NULL) { + + gaim_debug(GAIM_DEBUG_ERROR, "msn", + "Group '%s' appears in server-side " + "buddy list, but not here!", + msn_group_get_name(group)); + } + + if (group != NULL) + msn_group_add_user(group, user); + + if (g == NULL) { + /* Should never happen. */ + + if ((g = gaim_find_group(_("Buddies"))) == NULL) { + g = gaim_group_new(_("Buddies")); + gaim_blist_add_group(g, NULL); + } + } b = gaim_find_buddy(gc->account, msn_user_get_passport(user)); if (b == NULL) { - struct group *g = NULL; - const char *group_name = NULL; - int group_id; - - group_id = msn_user_get_group_id(user); - - if (group_id > -1) { - group_name = g_hash_table_lookup(session->group_names, - &group_id); - } - - if (group_name == NULL) { - gaim_debug(GAIM_DEBUG_WARNING, "msn", - "Group ID %d for user %s was not defined.\n", - group_id, msn_user_get_passport(user)); - } - else if ((g = gaim_find_group(group_name)) == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "msn", - "Group '%s' appears in server-side " - "buddy list, but not here!", - group_name); - } - - if (g == NULL) { - if ((g = gaim_find_group(_("Buddies"))) == NULL) { - g = gaim_group_new(_("Buddies")); - gaim_blist_add_group(g, NULL); - } - } - b = gaim_buddy_new(gc->account, msn_user_get_passport(user), NULL); @@ -420,7 +435,9 @@ friend = msn_url_decode(params[4]); if (!g_ascii_strcasecmp(list, "FL")) { - user = msn_user_new(session, passport, friend); + user = msn_user_new(session, passport, NULL); + + msn_user_set_group_id(user, atoi(params[5])); __add_buddy(servconn, user); @@ -455,20 +472,18 @@ __adg_cmd(MsnServConn *servconn, const char *command, const char **params, size_t param_count) { + MsnGroup *group; MsnSession *session = servconn->session; - gint *group_id; + gint group_id; char *group_name; - group_id = g_new(gint, 1); - *group_id = atoi(params[3]); + group_id = atoi(params[3]); group_name = msn_url_decode(params[2]); - gaim_debug(GAIM_DEBUG_INFO, "msn", "Added group %s (id %d)\n", - group_name, group_id); + group = msn_group_new(session, group_id, group_name); - g_hash_table_insert(session->group_ids, group_name, group_id); - g_hash_table_insert(session->group_names, group_id, g_strdup(group_name)); + msn_groups_add(session->groups, group); return TRUE; } @@ -592,10 +607,10 @@ size_t param_count) { MsnSession *session = servconn->session; + MsnGroup *group; struct group *g; const char *name; int group_num, num_groups, group_id; - gint *group_id_1, *group_id_2; group_num = atoi(params[2]); num_groups = atoi(params[3]); @@ -605,24 +620,12 @@ if (num_groups == 0) return TRUE; - if (group_num == 1) { - session->group_names = g_hash_table_new_full(g_int_hash, g_int_equal, - g_free, g_free); - session->group_ids = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - } - - group_id_1 = g_new(gint, 1); - group_id_2 = g_new(gint, 1); - - *group_id_1 = group_id; - *group_id_2 = group_id; - if (!strcmp(name, "~")) name = _("Buddies"); - g_hash_table_insert(session->group_names, group_id_1, g_strdup(name)); - g_hash_table_insert(session->group_ids, g_strdup(name), group_id_2); + group = msn_group_new(session, group_id, name); + + msn_groups_add(session->groups, group); if ((g = gaim_find_group(name)) == NULL) { g = gaim_group_new(name); @@ -837,8 +840,6 @@ friend = msn_url_decode(params[3]); - gaim_debug(GAIM_DEBUG_INFO, "msn", "Setting friendly name to %s\n", - friend); g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", friend); return TRUE; @@ -849,22 +850,21 @@ size_t param_count) { MsnSession *session = servconn->session; - gint *group_id; + MsnGroup *group; + int group_id; char *group_name; - group_id = g_new(gint, 1); - *group_id = atoi(params[2]); + group_id = atoi(params[2]); group_name = msn_url_decode(params[3]); - gaim_debug(GAIM_DEBUG_INFO, "msn", "Renamed group %s to %s\n", - g_hash_table_lookup(session->group_names, group_id), - group_name); + group = msn_groups_find_with_id(session->groups, group_id); - g_hash_table_replace(session->group_names, group_id, g_strdup(group_name)); + gaim_debug(GAIM_DEBUG_INFO, "msn", "Renamed group %s to %s\n", + msn_group_get_name(group), group_name); - g_hash_table_remove(session->group_ids, group_name); - g_hash_table_insert(session->group_ids, group_name, group_id); + if (group != NULL) + msn_group_set_name(group, group_name); return TRUE; } @@ -877,38 +877,84 @@ /* I hate this. */ if (session->moving_buddy) { + MsnGroup *group, *old_group; struct gaim_connection *gc = session->account->gc; const char *passport = params[3]; char outparams[MSN_BUF_LEN]; - int *group_id; + + group = msn_groups_find_with_name(session->groups, + session->dest_group_name); + + old_group = session->old_group; + + session->moving_buddy = FALSE; + session->old_group = NULL; - group_id = g_hash_table_lookup(session->group_ids, - session->dest_group_name); + if (group == NULL) { + gaim_debug(GAIM_DEBUG_ERROR, "msn", + "Still don't have a group ID for %s while moving %s!\n", + session->dest_group_name, passport); + + g_free(session->dest_group_name); + session->dest_group_name = NULL; + + return TRUE; + } g_free(session->dest_group_name); session->dest_group_name = NULL; - session->moving_buddy = FALSE; - - if (group_id == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "msn", - "Still don't have a group ID for %s while moving %s!\n", - session->dest_group_name, passport); - return TRUE; - } g_snprintf(outparams, sizeof(outparams), "FL %s %s %d", - passport, passport, *group_id); + passport, passport, msn_group_get_id(group)); if (!msn_servconn_send_command(session->notification_conn, "ADD", outparams)) { hide_login_progress(gc, _("Write error")); signoff(gc); + return FALSE; + } + + if (old_group != NULL) + msn_group_remove_user(old_group, session->moving_user); + + msn_user_unref(session->moving_user); + + session->moving_user = NULL; + + if (old_group != NULL && + msn_users_get_count(msn_group_get_users(old_group)) <= 0) { + + g_snprintf(outparams, sizeof(outparams), "%d", + msn_group_get_id(old_group)); + + if (!msn_servconn_send_command(session->notification_conn, + "RMG", outparams)) { + + hide_login_progress(gc, _("Write error")); + signoff(gc); + return FALSE; + } } } return TRUE; } +static gboolean +__rmg_cmd(MsnServConn *servconn, const char *command, const char **params, + size_t param_count) +{ + MsnSession *session = servconn->session; + MsnGroup *group; + + group = msn_groups_find_with_id(session->groups, atoi(params[2])); + + if (group != NULL) + msn_groups_remove(session->groups, group); + + return TRUE; +} + /************************************************************************** * Misc commands **************************************************************************/ @@ -1354,7 +1400,7 @@ msn_servconn_register_command(notification, "REA", __rea_cmd); msn_servconn_register_command(notification, "REG", __reg_cmd); msn_servconn_register_command(notification, "REM", __rem_cmd); - msn_servconn_register_command(notification, "RMG", __blank_cmd); + msn_servconn_register_command(notification, "RMG", __rmg_cmd); msn_servconn_register_command(notification, "RNG", __rng_cmd); msn_servconn_register_command(notification, "SYN", __blank_cmd); msn_servconn_register_command(notification, "URL", __url_cmd); diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/session.c --- a/src/protocols/msn/session.c Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/session.c Sun May 25 22:51:19 2003 +0000 @@ -36,7 +36,8 @@ session->dispatch_server = g_strdup(server); session->dispatch_port = port; - session->users = msn_users_new(); + session->users = msn_users_new(); + session->groups = msn_groups_new(); return session; } @@ -58,12 +59,10 @@ while (session->lists.forward) msn_user_destroy(session->lists.forward->data); - if (session->group_ids) g_hash_table_destroy(session->group_ids); - if (session->group_names) g_hash_table_destroy(session->group_names); - g_slist_free(session->lists.allow); g_slist_free(session->lists.block); + msn_groups_destroy(session->groups); msn_users_destroy(session->users); g_free(session->passport_info.kv); diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/session.h --- a/src/protocols/msn/session.h Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/session.h Sun May 25 22:51:19 2003 +0000 @@ -27,6 +27,7 @@ #include "servconn.h" #include "switchboard.h" #include "user.h" +#include "group.h" struct _MsnSession { @@ -44,10 +45,9 @@ unsigned int trId; MsnUsers *users; + MsnGroups *groups; GList *switches; - GHashTable *group_names; /* ID -> name */ - GHashTable *group_ids; /* Name -> ID */ struct { @@ -77,6 +77,8 @@ /* For moving buddies from one group to another. Ugh. */ gboolean moving_buddy; char *dest_group_name; + MsnUser *moving_user; + MsnGroup *old_group; }; /** diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/user.c --- a/src/protocols/msn/user.c Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/user.c Sun May 25 22:51:19 2003 +0000 @@ -29,27 +29,20 @@ user = msn_users_find_with_passport(session->users, passport); - if (user != NULL) { - if (name != NULL) - msn_user_set_name(user, name); + if (user == NULL) { + user = g_new0(MsnUser, 1); - msn_user_ref(user); + user->session = session; - return user; - } + msn_user_set_passport(user, passport); + msn_user_set_group_id(user, -1); - user = g_new0(MsnUser, 1); - - user->session = session; + msn_users_add(session->users, user); + } if (name != NULL) msn_user_set_name(user, name); - msn_user_set_passport(user, passport); - msn_user_set_group_id(user, -1); - - msn_users_add(session->users, user); - msn_user_ref(user); return user; @@ -254,10 +247,17 @@ void msn_users_destroy(MsnUsers *users) { + GList *l, *l_next = NULL; + g_return_if_fail(users != NULL); - while (users->users != NULL) - msn_user_destroy(users->users->data); + for (l = users->users; l != NULL; l = l_next) { + l_next = l->next; + + msn_user_destroy(l->data); + + users->users = g_list_remove(users->users, l->data); + } /* See if we've leaked anybody. */ while (users->users != NULL) { @@ -276,15 +276,27 @@ g_return_if_fail(user != NULL); users->users = g_list_append(users->users, user); + + users->count++; } void msn_users_remove(MsnUsers *users, MsnUser *user) { g_return_if_fail(users != NULL); - g_return_if_fail(user != NULL); + g_return_if_fail(user != NULL); users->users = g_list_remove(users->users, user); + + users->count--; +} + +size_t +msn_users_get_count(const MsnUsers *users) +{ + g_return_val_if_fail(users != NULL, 0); + + return users->count; } MsnUser * diff -r e9b9fbf89c42 -r bf2a7a7b739d src/protocols/msn/user.h --- a/src/protocols/msn/user.h Sun May 25 19:47:13 2003 +0000 +++ b/src/protocols/msn/user.h Sun May 25 22:51:19 2003 +0000 @@ -59,9 +59,16 @@ */ struct _MsnUsers { - GList *users; /** The list of users. */ + size_t count; /**< The number of users. */ + + GList *users; /**< The list of users. */ }; +/**************************************************************************/ +/** @name User API */ +/**************************************************************************/ +/*@{*/ + /** * Creates a new user structure. * @@ -220,6 +227,13 @@ */ GHashTable *msn_user_get_client_caps(const MsnUser *user); +/*@}*/ + +/**************************************************************************/ +/** @name User List API */ +/**************************************************************************/ +/*@{*/ + /** * Creates a new MsnUsers structure. * @@ -251,6 +265,15 @@ void msn_users_remove(MsnUsers *users, MsnUser *user); /** + * Returns the number of users in a users list. + * + * @param users The users list. + * + * @return The number of users. + */ +size_t msn_users_get_count(const MsnUsers *users); + +/** * Finds a user with the specified passport. * * @param users A list of users. @@ -260,4 +283,6 @@ */ MsnUser *msn_users_find_with_passport(MsnUsers *users, const char *passport); +/*@}*/ + #endif /* _MSN_USER_H_ */