about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2012-11-08 00:05:32 +0000
committerJames Booth <boothj5@gmail.com>2012-11-08 00:05:32 +0000
commit181669a8cb20d385e3635a7c1a23972a673db3fd (patch)
treeba98becc643270bf62b57a5d4f2d12fc2173969d /src
parentc4c5668779a26fa614b3511437454e6a2dcc027f (diff)
downloadprofani-tty-181669a8cb20d385e3635a7c1a23972a673db3fd.tar.gz
Basic chat room handling of presence
Diffstat (limited to 'src')
-rw-r--r--src/jabber.c31
-rw-r--r--src/profanity.c22
-rw-r--r--src/profanity.h4
-rw-r--r--src/room_chat.c26
-rw-r--r--src/room_chat.h3
-rw-r--r--src/ui.h2
-rw-r--r--src/windows.c35
7 files changed, 111 insertions, 12 deletions
diff --git a/src/jabber.c b/src/jabber.c
index 336c990b..24dd2915 100644
--- a/src/jabber.c
+++ b/src/jabber.c
@@ -645,7 +645,7 @@ _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata)
 }
 
 static int
-_room_presence_handler(const char * const jid)
+_room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza)
 {
     char *room = NULL;
     char *nick = NULL;
@@ -662,9 +662,36 @@ _room_presence_handler(const char * const jid)
     if (strcmp(room_get_nick_for_room(room), nick) == 0) {
         room_set_roster_received(room);
         prof_handle_room_roster_complete(room);
+
+    // handle presence from room members
     } else {
+        // roster not yet complete, just add to roster
         if (!room_get_roster_received(room)) {
             room_add_to_roster(room, nick);
+
+        // deal with presence information
+        } else {
+            char *type = xmpp_stanza_get_attribute(stanza, "type");
+            char *show_str, *status_str;
+
+            xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, "status");
+            if (status != NULL) {
+                status_str = xmpp_stanza_get_text(status);
+            } else {
+                status_str = NULL;
+            }
+
+            if ((type != NULL) && (strcmp(type, "unavailable") == 0)) {
+                prof_handle_room_member_offline(room, nick, "offline", status_str);
+            } else {
+                xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, "show");
+                if (show != NULL) {
+                    show_str = xmpp_stanza_get_text(show);
+                } else {
+                    show_str = "online";
+                    prof_handle_room_member_online(room, nick, show_str, status_str);
+                }
+            }
         }
     }
 
@@ -684,7 +711,7 @@ _presence_handler(xmpp_conn_t * const conn,
 
     // handle chat room presence
     if (room_is_active(from)) {
-        return _room_presence_handler(from);
+        return _room_presence_handler(from, stanza);
 
     // handle regular presence
     } else {
diff --git a/src/profanity.c b/src/profanity.c
index 7ef6a9a9..edb15bed 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -30,6 +30,7 @@
 #include "chat_log.h"
 #include "command.h"
 #include "common.h"
+#include "contact.h"
 #include "contact_list.h"
 #include "history.h"
 #include "log.h"
@@ -177,6 +178,7 @@ prof_handle_room_history(const char * const room_jid, const char * const nick,
     GTimeVal tv_stamp, const char * const message)
 {
     win_show_room_history(room_jid, nick, tv_stamp, message);
+    win_page_off();
 }
 
 void
@@ -184,12 +186,32 @@ prof_handle_room_message(const char * const room_jid, const char * const nick,
     const char * const message)
 {
     win_show_room_message(room_jid, nick, message);
+    win_page_off();
 }
 
 void
 prof_handle_room_roster_complete(const char * const room)
 {
     win_show_room_roster(room);
+    win_page_off();
+}
+
+void
+prof_handle_room_member_online(const char * const room, const char * const nick,
+    const char * const show, const char * const status)
+{
+    room_add_to_roster(room, nick);
+    win_show_room_member_online(room, nick);
+    win_page_off();
+}
+
+void
+prof_handle_room_member_offline(const char * const room, const char * const nick,
+    const char * const show, const char * const status)
+{
+    room_remove_from_roster(room, nick);
+    win_show_room_member_offline(room, nick);
+    win_page_off();
 }
 
 void
diff --git a/src/profanity.h b/src/profanity.h
index d7bbd37c..b7430ed9 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -40,5 +40,9 @@ void prof_handle_room_history(const char * const room_jid,
 void prof_handle_room_message(const char * const room_jid, const char * const nick,
     const char * const message);
 void prof_handle_room_roster_complete(const char * const room);
+void prof_handle_room_member_online(const char * const room,
+    const char * const nick, const char * const show, const char * const status);
+void prof_handle_room_member_offline(const char * const room,
+    const char * const nick, const char * const show, const char * const status);
 
 #endif
diff --git a/src/room_chat.c b/src/room_chat.c
index 82f997f7..6dc0f32c 100644
--- a/src/room_chat.c
+++ b/src/room_chat.c
@@ -25,10 +25,12 @@
 
 #include <glib.h>
 
+#include <contact.h>
+
 typedef struct _muc_room_t {
     char *jid;
     char *nick;
-    GSList *roster;
+    GHashTable *roster;
     gboolean roster_received;
 } muc_room;
 
@@ -47,7 +49,8 @@ room_join(const char * const jid, const char * const nick)
     muc_room *new_room = malloc(sizeof(muc_room));
     new_room->jid = strdup(jid);
     new_room->nick = strdup(nick);
-    new_room->roster = NULL;
+    new_room->roster = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+        (GDestroyNotify)p_contact_free);
     new_room->roster_received = FALSE;
 
     g_hash_table_insert(rooms, strdup(jid), new_room);
@@ -117,17 +120,28 @@ room_add_to_roster(const char * const jid, const char * const nick)
     muc_room *room = g_hash_table_lookup(rooms, jid);
 
     if (room != NULL) {
-        room->roster = g_slist_append(room->roster, strdup(nick));
+        PContact contact = p_contact_new(nick, NULL, "online", NULL, NULL);
+        g_hash_table_replace(room->roster, strdup(nick), contact);
+    }
+}
+
+void
+room_remove_from_roster(const char * const jid, const char * const nick)
+{
+    muc_room *room = g_hash_table_lookup(rooms, jid);
+
+    if (room != NULL) {
+        g_hash_table_remove(room->roster, nick);
     }
 }
 
-GSList *
+GList *
 room_get_roster(const char * const jid)
 {
     muc_room *room = g_hash_table_lookup(rooms, jid);
 
     if (room != NULL) {
-        return room->roster;
+        return g_hash_table_get_keys(room->roster);
     } else {
         return NULL;
     }
@@ -168,7 +182,7 @@ _room_free(muc_room *room)
             room->nick = NULL;
         }
         if (room->roster != NULL) {
-            g_slist_free_full(room->roster, g_free);
+            g_hash_table_remove_all(room->roster);
             room->roster = NULL;
         }
         g_free(room);
diff --git a/src/room_chat.h b/src/room_chat.h
index 77675fcd..d455e03c 100644
--- a/src/room_chat.h
+++ b/src/room_chat.h
@@ -29,6 +29,7 @@ char * room_get_nick_for_room(const char * const jid);
 gboolean room_parse_room_jid(const char * const room_jid, char **room,
     char **nick);
 void room_add_to_roster(const char * const jid, const char * const nick);
-GSList * room_get_roster(const char * const jid);
+GList * room_get_roster(const char * const jid);
 void room_set_roster_received(const char * const jid);
 gboolean room_get_roster_received(const char * const jid);
+void room_remove_from_roster(const char * const jid, const char * const nick);
diff --git a/src/ui.h b/src/ui.h
index 59128299..acdde2be 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -110,6 +110,8 @@ void win_show_room_history(const char * const room_jid, const char * const nick,
     GTimeVal tv_stamp, const char * const message);
 void win_show_room_message(const char * const room_jid, const char * const nick,
     const char * const message);
+void win_show_room_member_offline(const char * const room, const char * const nick);
+void win_show_room_member_online(const char * const room, const char * const nick);
 
 // console window actions
 void cons_about(void);
diff --git a/src/windows.c b/src/windows.c
index 91b6ee31..8f3bd19a 100644
--- a/src/windows.c
+++ b/src/windows.c
@@ -500,8 +500,7 @@ win_show_room_roster(const char * const room)
     int win_index = _find_prof_win_index(room);
     WINDOW *win = _wins[win_index].win;
 
-    GSList *roster = room_get_roster(room);
-
+    GList *roster = room_get_roster(room);
 
     if (roster != NULL) {
         wprintw(win, "Room occupants:\n");
@@ -514,7 +513,7 @@ win_show_room_roster(const char * const room)
         if (roster->next != NULL) {
             wprintw(win, ", ");
         }
-        roster = g_slist_next(roster);
+        roster = g_list_next(roster);
     }
     wprintw(win, "\n");
 
@@ -525,6 +524,36 @@ win_show_room_roster(const char * const room)
 }
 
 void
+win_show_room_member_offline(const char * const room, const char * const nick)
+{
+    int win_index = _find_prof_win_index(room);
+    WINDOW *win = _wins[win_index].win;
+
+    _win_show_time(win);
+    wattron(win, COLOUR_OFFLINE);
+    wprintw(win, "-- %s has left the room.\n", nick);
+    wattroff(win, COLOUR_OFFLINE);
+
+    if (win_index == _curr_prof_win)
+        dirty = TRUE;
+}
+
+void
+win_show_room_member_online(const char * const room, const char * const nick)
+{
+    int win_index = _find_prof_win_index(room);
+    WINDOW *win = _wins[win_index].win;
+
+    _win_show_time(win);
+    wattron(win, COLOUR_ONLINE);
+    wprintw(win, "++ %s has joined the room.\n", nick);
+    wattroff(win, COLOUR_ONLINE);
+
+    if (win_index == _curr_prof_win)
+        dirty = TRUE;
+}
+
+void
 win_show_room_history(const char * const room_jid, const char * const nick,
     GTimeVal tv_stamp, const char * const message)
 {