# HG changeset patch # User Mikael Berthe # Date 1127602904 -7200 # Node ID 03bb57383cea7ada6c442a313df3efea9532c44d # Parent 9f4e9e9aaf085dde2b4f6a4f81ceb17c42d738b7 Initial Multi-User Chat support This patch adds basic MUC support. We now can: - join an existing room; - create and unlock a room using the /rawxml command; - set our nickname; - send/receive chatgroup messages; - see the members of the room; - leave the room. Chatroom logging is currently disabled, as it could do some unexpected things. diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/commands.c --- a/mcabber/src/commands.c Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/commands.c Sun Sep 25 01:01:44 2005 +0200 @@ -51,6 +51,7 @@ static void do_connect(char *arg); static void do_disconnect(char *arg); static void do_rawxml(char *arg); +static void do_room(char *arg); // Global variable for the commands list static GSList *Commands; @@ -92,7 +93,7 @@ 0, &do_move); cmd_add("msay", "Send a multi-lines message to the selected buddy", COMPL_MULTILINE, 0, &do_msay); - //cmd_add("nick"); + cmd_add("room", "MUC actions command", COMPL_ROOM, 0, &do_room); cmd_add("quit", "Exit the software", 0, 0, NULL); cmd_add("rawxml", "Send a raw XML string", 0, 0, &do_rawxml); cmd_add("rename", "Rename the current buddy", 0, 0, &do_rename); @@ -146,6 +147,11 @@ compl_add_category_word(COMPL_MULTILINE, "begin"); compl_add_category_word(COMPL_MULTILINE, "send"); compl_add_category_word(COMPL_MULTILINE, "verbatim"); + + // Room category + compl_add_category_word(COMPL_ROOM, "join"); + compl_add_category_word(COMPL_ROOM, "leave"); + compl_add_category_word(COMPL_ROOM, "names"); } // expandalias(line) @@ -231,11 +237,13 @@ return; } - // local part (UI, logging, etc.) - hk_message_out(jid, 0, msg); + if (buddy_gettype(BUDDATA(current_buddy)) != ROSTER_TYPE_ROOM) { + // local part (UI, logging, etc.) + hk_message_out(jid, 0, msg); + } // Network part - jb_send_msg(jid, msg); + jb_send_msg(jid, msg, buddy_gettype(BUDDATA(current_buddy))); } // process_command(line) @@ -547,7 +555,7 @@ } bud = BUDDATA(current_buddy); - if (!(buddy_gettype(bud) & ROSTER_TYPE_USER)) { + if (!(buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_ROOM))) { scr_LogPrint(LPRINT_NORMAL, "This is not a user"); return; } @@ -603,7 +611,7 @@ } bud = BUDDATA(current_buddy); - if (!(buddy_gettype(bud) & ROSTER_TYPE_USER)) { + if (!(buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_ROOM))) { scr_LogPrint(LPRINT_NORMAL, "This is not a user"); return; } @@ -683,6 +691,7 @@ } if (type == ROSTER_TYPE_USER) typestr = "user"; + else if (type == ROSTER_TYPE_ROOM) typestr = "chatroom"; else if (type == ROSTER_TYPE_AGENT) typestr = "agent"; snprintf(buffer, 127, "Type: %s", typestr); scr_WriteIncomingMessage(jid, buffer, 0, HBB_PREFIX_INFO); @@ -892,6 +901,83 @@ } } +static void do_room(char *arg) +{ + gpointer bud; + + if (!arg || (!*arg)) { + scr_LogPrint(LPRINT_NORMAL, "Missing parameter"); + return; + } + + bud = BUDDATA(current_buddy); + + if (!strncasecmp(arg, "join", 4)) { + GSList *roster_usr; + char *roomname, *nick, *roomid; + + arg += 4; + if (*arg++ != ' ') { + scr_LogPrint(LPRINT_NORMAL, "Wrong or missing parameter"); + return; + } + for (; *arg && *arg == ' '; arg++) + ; + + roomname = g_strdup(arg); + nick = strchr(roomname, ' '); + if (!nick) { + scr_LogPrint(LPRINT_NORMAL, "Missing parameter (nickname)"); + g_free(roomname); + return; + } + + *nick++ = 0; + while (*nick && *nick == ' ') + nick++; + if (!*nick) { + scr_LogPrint(LPRINT_NORMAL, "Missing parameter (nickname)"); + g_free(roomname); + return; + } + // room syntax: "room@server/nick" + // FIXME: check roomid is a jid + roomid = g_strdup_printf("%s/%s", roomname, nick); + jb_room_join(roomid); + roster_usr = roster_add_user(roomname, NULL, NULL, ROSTER_TYPE_ROOM); + if (roster_usr) + buddy_setnickname(roster_usr->data, nick); + g_free(roomname); + g_free(roomid); + buddylist_build(); + update_roster = TRUE; + } else if (!strncasecmp(arg, "leave", 5)) { + char *roomid; + arg += 5; + for (; *arg && *arg == ' '; arg++) + ; + if (!(buddy_gettype(bud) & ROSTER_TYPE_ROOM)) { + scr_LogPrint(LPRINT_NORMAL, "This isn't a chatroom"); + return; + } + roomid = g_strdup_printf("%s/%s", buddy_getjid(bud), + buddy_getnickname(bud)); + jb_setstatus(offline, roomid, arg); + g_free(roomid); + buddy_setnickname(bud, NULL); + buddy_del_all_resources(bud); + scr_LogPrint(LPRINT_NORMAL, "You have left %s", buddy_getjid(bud)); + } else if (!strcasecmp(arg, "names")) { + if (!(buddy_gettype(bud) & ROSTER_TYPE_ROOM)) { + scr_LogPrint(LPRINT_NORMAL, "This isn't a chatroom"); + return; + } + do_info(NULL); + } else { + scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!"); + } +} + static void do_connect(char *arg) { mcabber_connect(); diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/compl.h --- a/mcabber/src/compl.h Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/compl.h Sun Sep 25 01:01:44 2005 +0200 @@ -14,6 +14,7 @@ #define COMPL_GROUP (1<<9) #define COMPL_GROUPNAME (1<<10) #define COMPL_MULTILINE (1<<11) +#define COMPL_ROOM (1<<12) void compl_add_category_word(guint, const char *command); void compl_del_category_word(guint categ, const char *word); diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/hooks.c --- a/mcabber/src/hooks.c Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/hooks.c Sun Sep 25 01:01:44 2005 +0200 @@ -30,33 +30,59 @@ static char *extcmd; -inline void hk_message_in(const char *jid, time_t timestamp, const char *msg, - const char *type) +inline void hk_message_in(const char *jid, const char *resname, + time_t timestamp, const char *msg, const char *type) { int new_guy = FALSE; - int message_flags; + int is_groupchat = FALSE; + int message_flags = 0; + guint rtype = ROSTER_TYPE_USER; + char *wmsg; + GSList *roster_usr; + + if (type && !strcmp(type, "groupchat")) { + rtype = ROSTER_TYPE_ROOM; + is_groupchat = TRUE; + if (!resname) { + message_flags = HBB_PREFIX_INFO; + resname = ""; + } + wmsg = g_strdup_printf("<%s> %s", resname, msg); + } else { + wmsg = (char*) msg; + } // If this user isn't in the roster, we add it - if (!roster_exists(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) { - roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER); + roster_usr = roster_find(jid, jidsearch, + rtype|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM); + if (!roster_usr) { + roster_add_user(jid, NULL, NULL, rtype); new_guy = TRUE; + } else { + if (buddy_gettype(roster_usr->data) == ROSTER_TYPE_ROOM) + is_groupchat = TRUE; } if (type && !strcmp(type, "error")) { message_flags = HBB_PREFIX_ERR | HBB_PREFIX_IN; scr_LogPrint(LPRINT_LOGNORM, "Error message received from <%s>", jid); - } else - message_flags = 0; + } // Note: the hlog_write should not be called first, because in some // cases scr_WriteIncomingMessage() will load the history and we'd // have the message twice... - scr_WriteIncomingMessage(jid, msg, timestamp, message_flags); + scr_WriteIncomingMessage(jid, wmsg, timestamp, message_flags); + // We don't log the message if it is an error message - if (!(message_flags & HBB_PREFIX_ERR)) - hlog_write_message(jid, timestamp, FALSE, msg); + // or if it is a groupchat message + // XXX We could use an option here to know if we should write GC messages... + if (!is_groupchat && !(message_flags & HBB_PREFIX_ERR)) + hlog_write_message(jid, timestamp, FALSE, wmsg); + // External command - hk_ext_cmd(jid, 'M', 'R', NULL); + if (!is_groupchat) + hk_ext_cmd(jid, 'M', 'R', NULL); + // We need to rebuild the list if the sender is unknown or // if the sender is offline/invisible and hide_offline_buddies is set if (new_guy || @@ -66,6 +92,8 @@ buddylist_build(); update_roster = TRUE; } + + if (rtype == ROSTER_TYPE_ROOM) g_free(wmsg); } inline void hk_message_out(const char *jid, time_t timestamp, const char *msg) diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/hooks.h --- a/mcabber/src/hooks.h Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/hooks.h Sun Sep 25 01:01:44 2005 +0200 @@ -5,8 +5,8 @@ #include "jabglue.h" -inline void hk_message_in(const char *jid, time_t timestamp, const char *msg, - const char *type); +inline void hk_message_in(const char *jid, const char *resname, + time_t timestamp, const char *msg, const char *type); inline void hk_message_out(const char *jid, time_t timestamp, const char *msg); inline void hk_statuschange(const char *jid, const char *resname, gchar prio, time_t timestamp, enum imstatus status, diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/jabglue.c Sun Sep 25 01:01:44 2005 +0200 @@ -333,10 +333,17 @@ mystatus = st; } -void jb_send_msg(const char *jid, const char *text) +void jb_send_msg(const char *jid, const char *text, int type) { + gchar *strtype; gchar *buffer = to_utf8(text); - xmlnode x = jutil_msgnew(TMSG_CHAT, (char*)jid, 0, (char*)buffer); + + if (type == ROSTER_TYPE_ROOM) + strtype = TMSG_GROUPCHAT; + else + strtype = TMSG_CHAT; + + xmlnode x = jutil_msgnew(strtype, (char*)jid, 0, (char*)buffer); jab_send(jc, x); xmlnode_free(x); g_free(buffer); @@ -462,6 +469,26 @@ g_free(cleanjid); } +// Join a MUC room +// room syntax: "room@server/nick" +void jb_room_join(const char *room) +{ + xmlnode x, y; + + if (!online) return; + if (!room) return; + + x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); + xmlnode_put_attrib(x, "from", jid_full(jc->user)); + xmlnode_put_attrib(x, "to", room); + y = xmlnode_insert_tag(x, "x"); + xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc"); + + jab_send(jc, x); + xmlnode_free(x); + jb_reset_keepalive(); +} + void postlogin() { //int i; @@ -571,6 +598,7 @@ const char *enc, time_t timestamp) { char *jid; + const char *rname; gchar *buffer = from_utf8(body); jid = jidtodisp(from); @@ -585,18 +613,9 @@ return; } - /* - //char *u, *h, *r; - //jidsplit(from, &u, &h, &r); - // Maybe we should remember the resource? - if (r) - scr_LogPrint(LPRINT_NORMAL, - "There is an extra part in message (resource?): %s", r); - //scr_LogPrint(LPRINT_NORMAL, "Msg from <%s>, type=%s", - // jidtodisp(from), type); - */ - - hk_message_in(jid, timestamp, buffer, type); + rname = strchr(from, '/'); + if (rname) rname++; + hk_message_in(jid, rname, timestamp, buffer, type); g_free(jid); g_free(buffer); } @@ -727,7 +746,7 @@ void packethandler(jconn conn, jpacket packet) { - char *p, *r; + char *p, *r, *s; const char *m, *rname; xmlnode x, y; char *from=NULL, *type=NULL, *body=NULL, *enc=NULL; @@ -906,7 +925,28 @@ } } + } else if (!strcmp(type, "get")) { + p = xmlnode_get_attrib(packet->x, "id"); + if (p) { + xmlnode z; + + id = p; + x = xmlnode_new_tag("iq"); + xmlnode_put_attrib(x, "type", "result"); + xmlnode_put_attrib(x, "to", from); + xmlnode_put_attrib(x, "id", id); + xmlnode_put_attrib(x, "type", "error"); + y = xmlnode_insert_tag(x, "error"); + xmlnode_put_attrib(y, "code", "503"); + xmlnode_put_attrib(y, "type", "cancel"); + z = xmlnode_insert_tag(y, "feature-not-implemented"); + xmlnode_put_attrib(z, "xmlns", + "urn:ietf:params:xml:ns:xmpp-stanzas"); + jab_send(conn, x); + xmlnode_free(x); + } } else if (!strcmp(type, "set")) { + /* FIXME: send error */ } else if (!strcmp(type, "error")) { if ((x = xmlnode_get_tag(packet->x, "error")) != NULL) display_server_error(x); @@ -940,19 +980,43 @@ ust = offline; if ((x = xmlnode_get_tag(packet->x, "status")) != NULL) - p = from_utf8(xmlnode_get_data(x)); + s = from_utf8(xmlnode_get_data(x)); else - p = NULL; + s = NULL; // Call hk_statuschange() if status has changed or if the // status message is different rname = strchr(from, '/'); if (rname) rname++; + + // Check for MUC presence packet + // There can be multiple tags!! + x = xmlnode_get_firstchild(packet->x); + for ( ; x; x = xmlnode_get_nextsibling(x)) { + if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) + if ((p = xmlnode_get_attrib(x, "xmlns")) && + !strncasecmp(p, "http://jabber.org/protocol/muc", 30)) + break; + } + if (x) { // This is a MUC presence message + roster_add_user(r, NULL, NULL, ROSTER_TYPE_ROOM); + + if (rname) + roster_setstatus(r, rname, bpprio, ust, NULL); + else + scr_LogPrint(LPRINT_LOGNORM, "MUC DBG: no rname!"); /* DBG */ + + buddylist_build(); + scr_DrawRoster(); + break; + } + + // Not a MUC message, so this is a regular buddy... m = roster_getstatusmsg(r, rname); - if ((ust != roster_getstatus(r, rname)) || (p && (!m || strcmp(p, m)))) - hk_statuschange(r, rname, bpprio, 0, ust, p); + if ((ust != roster_getstatus(r, rname)) || (s && (!m || strcmp(s, m)))) + hk_statuschange(r, rname, bpprio, 0, ust, s); g_free(r); - if (p) g_free(p); + if (s) g_free(s); break; case JPACKET_S10N: diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/jabglue.h --- a/mcabber/src/jabglue.h Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/jabglue.h Sun Sep 25 01:01:44 2005 +0200 @@ -47,11 +47,12 @@ void jb_updatebuddy(const char *jid, const char *name, const char *group); inline enum imstatus jb_getstatus(); void jb_setstatus(enum imstatus st, const char *recipient, const char *msg); -void jb_send_msg(const char *, const char *); +void jb_send_msg(const char *jid, const char *text, int type); void jb_send_raw(const char *str); void jb_keepalive(); inline void jb_reset_keepalive(); void jb_set_keepalive_delay(unsigned int delay); inline void jb_set_priority(unsigned int priority); +void jb_room_join(const char *room); #endif /* __JABGLUE_H__ */ diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/roster.c --- a/mcabber/src/roster.c Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/roster.c Sun Sep 25 01:01:44 2005 +0200 @@ -44,7 +44,7 @@ guint type; enum subscr subscription; GSList *resource; - res *cur_res; + gchar *nickname; // For groupchats guint flags; // list: user -> points to his group; group -> points to its users list GSList *list; @@ -197,7 +197,8 @@ if (!jidname) return NULL; if (!roster_type) - roster_type = ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP; + roster_type = ROSTER_TYPE_USER | ROSTER_TYPE_ROOM | + ROSTER_TYPE_AGENT | ROSTER_TYPE_GROUP; sample.type = roster_type; if (type == jidsearch) { @@ -249,7 +250,9 @@ roster *my_group; GSList *slist; - if ((type != ROSTER_TYPE_USER) && (type != ROSTER_TYPE_AGENT)) { + if ((type != ROSTER_TYPE_USER) && + (type != ROSTER_TYPE_ROOM) && + (type != ROSTER_TYPE_AGENT)) { // XXX Error message? return NULL; } @@ -258,7 +261,7 @@ if (!group) group = ""; // #1 Check this user doesn't already exist - slist = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); + slist = roster_find(jid, jidsearch, type|ROSTER_TYPE_AGENT); if (slist) return slist; // #2 add group if necessary slist = roster_add_group(group); @@ -276,7 +279,7 @@ roster_usr->name = g_strdup(str); g_free(str); } - roster_usr->type = type; //ROSTER_TYPE_USER; + roster_usr->type = type; roster_usr->list = slist; // (my_group SList element) // #4 Insert node (sorted) my_group->list = g_slist_insert_sorted(my_group->list, roster_usr, @@ -292,7 +295,8 @@ roster *roster_usr; GSList *node; - sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); + sl_user = roster_find(jid, jidsearch, + ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM); if (sl_user == NULL) return; roster_usr = (roster*)sl_user->data; @@ -304,6 +308,7 @@ // Let's free memory (jid, name, status message) if (roster_usr->jid) g_free((gchar*)roster_usr->jid); if (roster_usr->name) g_free((gchar*)roster_usr->name); + if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname); free_all_resources(&roster_usr->resource); g_free(roster_usr); @@ -341,6 +346,7 @@ // Free name and jid if (roster_usr->jid) g_free((gchar*)roster_usr->jid); if (roster_usr->name) g_free((gchar*)roster_usr->name); + if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname); free_all_resources(&roster_usr->resource); g_free(roster_usr); sl_usr = g_slist_next(sl_usr); @@ -371,7 +377,8 @@ roster *roster_usr; res *p_res; - sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); + sl_user = roster_find(jid, jidsearch, + ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT); // If we can't find it, we add it if (sl_user == NULL) sl_user = roster_add_user(jid, NULL, NULL, ROSTER_TYPE_USER); @@ -405,7 +412,8 @@ GSList *sl_user; roster *roster_usr; - sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); + sl_user = roster_find(jid, jidsearch, + ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT); if (sl_user == NULL) return; @@ -425,7 +433,8 @@ GSList *sl_user; roster *roster_usr, *roster_grp; - sl_user = roster_find(jid, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); + sl_user = roster_find(jid, jidsearch, + ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT); if (sl_user == NULL) return; @@ -527,14 +536,6 @@ return roster_usr->type; } -inline guint roster_exists(const char *jidname, enum findwhat type, - guint roster_type) -{ - if (roster_find(jidname, type, roster_type)) - return TRUE; - return FALSE; -} - /* ### BuddyList functions ### */ @@ -693,6 +694,7 @@ // Free old buddy if (roster_usr->jid) g_free((gchar*)roster_usr->jid); if (roster_usr->name) g_free((gchar*)roster_usr->name); + if (roster_usr->nickname) g_free((gchar*)roster_usr->nickname); free_all_resources(&roster_usr->resource); g_free(roster_usr); @@ -740,6 +742,26 @@ return roster_usr->name; } +void buddy_setnickname(gpointer rosterdata, char *newname) +{ + roster *roster_usr = rosterdata; + + if (!roster_usr->type & ROSTER_TYPE_ROOM) return; + + if (roster_usr->nickname) { + g_free((gchar*)roster_usr->nickname); + roster_usr->nickname = NULL; + } + if (newname) + roster_usr->nickname = g_strdup(newname); +} + +const char *buddy_getnickname(gpointer rosterdata) +{ + roster *roster_usr = rosterdata; + return roster_usr->nickname; +} + // buddy_getgroupname() // Returns a pointer on buddy's group name. const char *buddy_getgroupname(gpointer rosterdata) @@ -813,6 +835,18 @@ return reslist; } +// buddy_del_all_resources() +// Remove all resources from the specified buddy +void buddy_del_all_resources(gpointer rosterdata) +{ + roster *roster_usr = rosterdata; + + while (roster_usr->resource) { + res *r = roster_usr->resource->data; + del_resource(roster_usr, r->name); + } +} + // buddy_setflags() // Set one or several flags to value (TRUE/FALSE) void buddy_setflags(gpointer rosterdata, guint flags, guint value) @@ -873,7 +907,7 @@ if ((bname) && (*bname)) list = g_slist_append(list, g_strdup(bname)); } - } else { // ROSTER_TYPE_USER (jid) + } else { // ROSTER_TYPE_USER (jid) (or agent, or chatroom...) const char *bjid = buddy_getjid(BUDDATA(buddy)); if (bjid) list = g_slist_append(list, g_strdup(bjid)); diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/roster.h --- a/mcabber/src/roster.h Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/roster.h Sun Sep 25 01:01:44 2005 +0200 @@ -28,6 +28,7 @@ #define ROSTER_TYPE_USER 1 #define ROSTER_TYPE_GROUP 2 #define ROSTER_TYPE_AGENT 4 +#define ROSTER_TYPE_ROOM 8 // Flags: #define ROSTER_FLAG_MSG 1 // Message not read @@ -48,6 +49,7 @@ GSList *roster_add_group(const char *name); GSList *roster_add_user(const char *jid, const char *name, const char *group, guint type); +GSList *roster_find(const char *jidname, enum findwhat type, guint roster_type); void roster_del_user(const char *jid); void roster_free(void); void roster_setstatus(const char *jid, const char *resname, gchar prio, @@ -58,8 +60,6 @@ enum imstatus roster_getstatus(const char *jid, const char *resname); const char *roster_getstatusmsg(const char *jid, const char *resname); guint roster_gettype(const char *jid); -inline guint roster_exists(const char *jidname, enum findwhat type, - guint roster_type); void buddylist_build(void); void buddy_hide_group(gpointer rosterdata, int hide); @@ -68,6 +68,8 @@ const char *buddy_getjid(gpointer rosterdata); void buddy_setname(gpointer rosterdata, char *newname); const char *buddy_getname(gpointer rosterdata); +void buddy_setnickname(gpointer rosterdata, char *newname); +const char *buddy_getnickname(gpointer rosterdata); guint buddy_gettype(gpointer rosterdata); void buddy_setgroup(gpointer rosterdata, char *newgroupname); const char *buddy_getgroupname(gpointer rosterdata); @@ -76,6 +78,7 @@ const char *buddy_getstatusmsg(gpointer rosterdata, const char *resname); gchar buddy_getresourceprio(gpointer rosterdata, const char *resname); GSList *buddy_getresources(gpointer rosterdata); +void buddy_del_all_resources(gpointer rosterdata); void buddy_setflags(gpointer rosterdata, guint flags, guint value); guint buddy_getflags(gpointer rosterdata); GList *buddy_search(char *string); diff -r 9f4e9e9aaf08 -r 03bb57383cea mcabber/src/screen.c --- a/mcabber/src/screen.c Sun Sep 25 00:44:11 2005 +0200 +++ b/mcabber/src/screen.c Sun Sep 25 01:01:44 2005 +0200 @@ -720,6 +720,7 @@ enum imstatus budstate; unsigned short ismsg = buddy_getflags(BUDDATA(buddy)) & ROSTER_FLAG_MSG; unsigned short isgrp = buddy_gettype(BUDDATA(buddy)) & ROSTER_TYPE_GROUP; + unsigned short ismuc = buddy_gettype(BUDDATA(buddy)) & ROSTER_TYPE_ROOM; unsigned short ishid = buddy_getflags(BUDDATA(buddy)) & ROSTER_FLAG_HIDE; if (rOffset > 0) { @@ -749,6 +750,8 @@ wattrset(rosterWnd, COLOR_PAIR(COLOR_BD_DES)); } + if (ismuc) status = 'C'; + strncpy(name, buddy_getname(BUDDATA(buddy)), ROSTER_WIDTH-7); if (isgrp) { char *sep;