changeset 986:ed697234bd39

Chat states receival (Alexis Hildebrandt) Patch from Alexis Hildebrandt, slightly modified (mostly coding style updates).
author Mikael Berthe <mikael@lilotux.net>
date Sun, 29 Oct 2006 11:43:00 +0100
parents b33ca4e1c37d
children f47e312560af
files mcabber/src/jabglue.c mcabber/src/roster.c mcabber/src/roster.h mcabber/src/screen.c
diffstat 4 files changed, 127 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mcabber/src/jabglue.c	Sat Oct 28 18:14:22 2006 +0200
+++ b/mcabber/src/jabglue.c	Sun Oct 29 11:43:00 2006 +0100
@@ -51,6 +51,7 @@
 
 static void statehandler(jconn, int);
 static void packethandler(jconn, jpacket);
+void handle_state_events(char* from, xmlnode xmldata);
 
 static void logger(jconn j, int io, const char *buf)
 {
@@ -429,6 +430,22 @@
     y = xmlnode_insert_tag(x, "subject");
     xmlnode_insert_cdata(y, subject, (unsigned) -1);
   }
+
+  // TODO: insert event notifications request
+#undef USE_JEP_85
+#ifdef USE_JEP_85
+#define NS_CHAT_STATES    "http://jabber.org/features/chatstates"
+  // JEP-85
+  xmlnode event = xmlnode_insert_tag(x, "composing");
+  xmlnode_put_attrib(event, "xmlns", NS_CHAT_STATES);
+#else
+  // JEP-22
+  xmlnode event = xmlnode_insert_tag(x, "x");
+  xmlnode_put_attrib(event, "xmlns", NS_EVENT);
+  xmlnode_insert_tag(event, "composing");
+#endif
+
+
   jab_send(jc, x);
   xmlnode_free(x);
 
@@ -1422,6 +1439,8 @@
     }
   }
 
+  handle_state_events(from, xmldata);
+
   // Not used yet...
   x = xml_get_xmlns(xmldata, NS_ENCRYPTED);
   if (x && (p = xmlnode_get_data(x)) != NULL) {
@@ -1440,6 +1459,52 @@
   g_free(tmp);
 }
 
+void handle_state_events(char* from, xmlnode xmldata)
+{
+  xmlnode x   = NULL;
+  char *rname = strchr(from, JID_RESOURCE_SEPARATOR) + 1;
+  char *jid   = jidtodisp(from);
+  GSList *slist = roster_find(jid, jidsearch, ROSTER_TYPE_USER);
+  if (slist == NULL) return;
+  int jep85 = 0;
+
+  guint events  = buddy_resource_getevents(slist->data, rname);
+
+  x = xml_get_xmlns(xmldata, NS_EVENT);
+  if (x == NULL) {
+      x = xmldata;
+      jep85 = 1;
+  }
+
+  xmlnode tag = xmlnode_get_tag(x, "composing");
+  if (tag != NULL) {
+    events |= ROSTER_EVENT_COMPOSING;
+  } else if (!jep85) {
+    events &= ~ROSTER_EVENT_COMPOSING;
+  }
+
+  if (jep85) {
+      tag = xmlnode_get_tag(x, "paused");
+      if (tag != NULL) {
+        events &= ~ROSTER_EVENT_COMPOSING;
+      }
+  }
+
+  // clear composing and set new message event
+  // if message contains message body
+  if (xmlnode_get_tag_data(xmldata, "body") != NULL) {
+    events |= ROSTER_EVENT_MSG;
+    events &= ~ROSTER_EVENT_COMPOSING;
+  }
+
+  buddy_resource_setevents(slist->data, rname, events);
+
+  scr_UpdateBuddyWindow();
+  scr_DrawRoster();
+
+  g_free(jid);
+}
+
 static void evscallback_subscription(eviqs *evp, guint evcontext)
 {
   char *barejid;
--- a/mcabber/src/roster.c	Sat Oct 28 18:14:22 2006 +0200
+++ b/mcabber/src/roster.c	Sun Oct 29 11:43:00 2006 +0100
@@ -51,6 +51,7 @@
   enum imrole role;
   enum imaffiliation affil;
   gchar *realjid;       /* for chatrooms, if buddy's real jid is known */
+  guint events;
 } res;
 
 /* This is a private structure type for the roster */
@@ -1062,6 +1063,32 @@
   return 0;
 }
 
+guint buddy_resource_getevents(gpointer rosterdata, const char *resname)
+{
+  roster *roster_usr = rosterdata;
+  res *p_res = get_resource(roster_usr, resname);
+  if (p_res)
+    return p_res->events;
+  return ROSTER_EVENT_NONE;
+}
+
+void buddy_resource_setevents(gpointer rosterdata, const char *resname,
+                              guint events)
+{
+  roster *roster_usr = rosterdata;
+  res *p_res = get_resource(roster_usr, resname);
+  if (p_res)
+    p_res->events = events;
+
+  /*
+  // update group
+  roster_usr = roster_usr->list->data;
+  p_res = get_resource(roster_usr, "");
+  if (p_res)
+    p_res->events = events;
+  */
+}
+
 enum imrole buddy_getrole(gpointer rosterdata, const char *resname)
 {
   roster *roster_usr = rosterdata;
--- a/mcabber/src/roster.h	Sat Oct 28 18:14:22 2006 +0200
+++ b/mcabber/src/roster.h	Sun Oct 29 11:43:00 2006 +0100
@@ -74,6 +74,22 @@
 #define ROSTER_FLAG_USRLOCK (1U<<3) // Node should not be removed from buddylist
 // ROSTER_FLAG_LOCAL   (1U<<4) // Buddy not on server's roster  (??)
 
+
+/* Message event and chat state flags */
+#define ROSTER_EVENT_NONE      0U
+#define ROSTER_EVENT_MSG       1U
+/* JEP-22 Message Events */
+#define ROSTER_EVENT_OFFLINE   (1U<<1)
+#define ROSTER_EVENT_DELIVERED (1U<<2)
+#define ROSTER_EVENT_DISPLAYED (1U<<3)
+/* JEP-22 & JEP-85 */
+#define ROSTER_EVENT_COMPOSING (1U<<4)
+/* JEP-85 Chat State Notifications */
+#define ROSTER_EVENT_ACTIVE    (1U<<5)
+#define ROSTER_EVENT_PAUSED    (1U<<6)
+#define ROSTER_EVENT_INACTIVE  (1U<<7)
+#define ROSTER_EVENT_GONE      (1U<<8)
+
 extern GList *buddylist;
 extern GList *current_buddy;
 extern GList *alternate_buddy;
@@ -135,6 +151,9 @@
 GSList *buddy_getresources_locale(gpointer rosterdata);
 void    buddy_resource_setname(gpointer rosterdata, const char *resname,
                                const char *newname);
+void    buddy_resource_setevents(gpointer rosterdata, const char *resname,
+                                 guint event);
+guint   buddy_resource_getevents(gpointer rosterdata, const char *resname);
 enum imrole buddy_getrole(gpointer rosterdata, const char *resname);
 enum imaffiliation buddy_getaffil(gpointer rosterdata, const char *resname);
 const char *buddy_getrjid(gpointer rosterdata, const char *resname);
--- a/mcabber/src/screen.c	Sat Oct 28 18:14:22 2006 +0200
+++ b/mcabber/src/screen.c	Sun Oct 29 11:43:00 2006 +0100
@@ -1168,6 +1168,7 @@
   for (i=0; i<maxy && buddy; buddy = g_list_next(buddy)) {
     unsigned short bflags, btype, ismsg, isgrp, ismuc, ishid, isspe;
     gchar *rline_locale;
+    GSList *resources;
 
     bflags = buddy_getflags(BUDDATA(buddy));
     btype = buddy_gettype(BUDDATA(buddy));
@@ -1186,6 +1187,21 @@
     status = '?';
     pending = ' ';
 
+    resources = buddy_getresources(BUDDATA(buddy));
+    for ( ; resources ; resources = g_slist_next(resources) ) {
+      guint events = buddy_resource_getevents(BUDDATA(buddy),
+                                              resources ? resources->data : "");
+      if (events) {
+        if (events & ROSTER_EVENT_MSG && false) { // FIXME: not yet.
+          pending = '#';
+          break;
+        } else if (events & ROSTER_EVENT_COMPOSING) {
+          pending = '+';
+          break;
+        }
+      }
+    }
+
     // Display message notice if there is a message flag, but not
     // for unfolded groups.
     if (ismsg && (!isgrp || ishid)) {