Chat states receival (Alexis Hildebrandt)
Patch from Alexis Hildebrandt, slightly modified
(mostly coding style updates).
--- 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)) {