diff --git a/src/command.c b/src/command.c index 62eea490..785b133c 100644 --- a/src/command.c +++ b/src/command.c @@ -1082,6 +1082,10 @@ _cmd_tiny(const char * const inp, struct cmd_help_t help) static gboolean _cmd_close(const char * const inp, struct cmd_help_t help) { + if (win_in_groupchat()) { + char *room_jid = win_get_recipient(); + jabber_leave_chat_room(room_jid); + } if (win_in_chat()) { if (prefs_get_states()) { diff --git a/src/jabber.c b/src/jabber.c index 3fe4a91e..d294ba0a 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -330,6 +330,25 @@ jabber_join(const char * const room_jid, const char * const nick) room_join(room_jid, nick); } +void +jabber_leave_chat_room(const char * const room_jid) +{ + char *nick = room_get_nick_for_room(room_jid); + GString *full_jid = g_string_new(room_jid); + g_string_append(full_jid, "/"); + g_string_append(full_jid, nick); + + xmpp_stanza_t *presence = xmpp_stanza_new(jabber_conn.ctx); + xmpp_stanza_set_name(presence, "presence"); + xmpp_stanza_set_type(presence, "unavailable"); + xmpp_send(jabber_conn.conn, presence); + xmpp_stanza_release(presence); + + g_string_free(full_jid, TRUE); + + room_leave(room_jid); +} + void jabber_update_presence(jabber_presence_t status, const char * const msg) { diff --git a/src/jabber.h b/src/jabber.h index ee9e49fc..7abb4631 100644 --- a/src/jabber.h +++ b/src/jabber.h @@ -47,6 +47,7 @@ void jabber_disconnect(void); void jabber_process_events(void); void jabber_subscribe(const char * const recipient); void jabber_join(const char * const room_jid, const char * const nick); +void jabber_leave_chat_room(const char * const room_jid); void jabber_send(const char * const msg, const char * const recipient); void jabber_send_groupchat(const char * const msg, const char * const recipient); void jabber_send_inactive(const char * const recipient); diff --git a/src/room_chat.c b/src/room_chat.c index 710cc8cb..a8125874 100644 --- a/src/room_chat.c +++ b/src/room_chat.c @@ -30,45 +30,79 @@ typedef struct _muc_room_t { char *nick; } muc_room; -GSList *rooms; +GHashTable *rooms = NULL; + +static void _room_free(muc_room *room); void room_join(const char * const jid, const char * const nick) { + if (rooms == NULL) { + rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, + (GDestroyNotify)_room_free); + } + muc_room *new_room = malloc(sizeof(muc_room)); new_room->jid = strdup(jid); new_room->nick = strdup(nick); - rooms = g_slist_append(rooms, new_room); + g_hash_table_insert(rooms, strdup(jid), new_room); +} + +void +room_leave(const char * const jid) +{ + g_hash_table_remove(rooms, jid); } gboolean room_jid_is_room_chat(const char * const jid) { - GSList *current = rooms; - while (current != NULL) { - muc_room *room = current->data; - if (g_str_has_prefix(jid, room->jid)) { + char **tokens = g_strsplit(jid, "/", 0); + char *jid_part = tokens[0]; + + if (rooms != NULL) { + muc_room *room = g_hash_table_lookup(rooms, jid_part); + + if (room != NULL) { return TRUE; + } else { + return FALSE; } - current = g_slist_next(current); + } else { + return FALSE; } - - return FALSE; - } char * room_get_nick_for_room(const char * const jid) { - GSList *current = rooms; - while (current != NULL) { - muc_room *room = current->data; - if (strcmp(jid, room->jid) == 0) { - return room->nick; - } - current = g_slist_next(current); - } + if (rooms != NULL) { + muc_room *room = g_hash_table_lookup(rooms, jid); - return NULL; + if (room != NULL) { + return room->nick; + } else { + return NULL; + } + } else { + return NULL; + } +} + +static void +_room_free(muc_room *room) +{ + if (room != NULL) { + if (room->jid != NULL) { + g_free(room->jid); + room->jid = NULL; + } + if (room->nick != NULL) { + g_free(room->nick); + room->nick = NULL; + } + g_free(room); + } + room = NULL; } diff --git a/src/room_chat.h b/src/room_chat.h index a6ceb4a0..c8be1f5b 100644 --- a/src/room_chat.h +++ b/src/room_chat.h @@ -23,5 +23,6 @@ #include void room_join(const char * const jid, const char * const nick); +void room_leave(const char * const jid); gboolean room_jid_is_room_chat(const char * const jid); char * room_get_nick_for_room(const char * const jid);