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.
--- 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();
--- 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);
--- 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)
--- 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,
--- 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 <x> 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:
--- 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__ */
--- 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));
--- 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);
--- 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;