# HG changeset patch # User Mikael Berthe # Date 1163843098 -3600 # Node ID 4c8d7b558e8309beedb550ab0d19985e015477d7 # Parent 97f862e44d5d240c9db5b8656e2816bdd90c080a Annotations listing (/roster note in the status buffer) diff -r 97f862e44d5d -r 4c8d7b558e83 mcabber/src/commands.c --- a/mcabber/src/commands.c Wed Nov 15 22:47:35 2006 +0100 +++ b/mcabber/src/commands.c Sat Nov 18 10:44:58 2006 +0100 @@ -467,10 +467,70 @@ } } +// display_and_free_note(note, winId) +// Display the note information in the winId buffer, and free note +// (winId is a bare jid or NULL for the status window, in which case we +// display the note jid too) +static void display_and_free_note(struct annotation *note, const char *winId) +{ + gchar tbuf[128]; + GString *sbuf; + guint msg_flag = HBB_PREFIX_INFO; + /* We use the flag prefix_info for the first line, and prefix_none + for the other lines, for better readability */ + + if (!note) + return; + + sbuf = g_string_new(""); + + if (!winId) { + // We're writing to the status window, so let's show the jid too. + g_string_printf(sbuf, "Annotation on <%s>", note->jid); + scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag); + msg_flag = HBB_PREFIX_NONE; + } + + // If we have the creation date, display it + if (note->cdate) { + strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", + localtime(¬e->cdate)); + g_string_printf(sbuf, "Note created %s", tbuf); + scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag); + msg_flag = HBB_PREFIX_NONE; + } + // If we have the modification date, display it + // unless it's the same as the creation date + if (note->mdate && note->mdate != note->cdate) { + strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", + localtime(¬e->mdate)); + g_string_printf(sbuf, "Note modified %s", tbuf); + scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag); + msg_flag = HBB_PREFIX_NONE; + } + // Note text + g_string_printf(sbuf, "Note: %s", note->text); + scr_WriteIncomingMessage(winId, sbuf->str, 0, msg_flag); + + g_string_free(sbuf, TRUE); + g_free(note->text); + g_free(note->jid); + g_free(note); +} + +static void display_all_annotations() +{ + GSList *notes; + notes = jb_get_all_storage_rosternotes(); + // Call display_and_free_note() for each note, + // with winId = NULL (special window) + g_slist_foreach(notes, (GFunc)&display_and_free_note, NULL); + g_slist_free(notes); +} + static void roster_note(char *arg) { const char *jid; - gchar *msg, *notetxt; guint type; if (!current_buddy) @@ -479,6 +539,13 @@ jid = buddy_getjid(BUDDATA(current_buddy)); type = buddy_gettype(BUDDATA(current_buddy)); + if (!jid && type == ROSTER_TYPE_SPECIAL && !arg) { + // We're in the status window (the only special buffer currently) + // Let's display all server notes + display_all_annotations(); + return; + } + if (!jid || (type != ROSTER_TYPE_USER && type != ROSTER_TYPE_ROOM && type != ROSTER_TYPE_AGENT)) { @@ -486,12 +553,9 @@ return; } - if (arg && *arg) + if (arg && *arg) { // Set a note + gchar *msg, *notetxt; msg = to_utf8(arg); - else - msg = NULL; - - if (msg) { // Set a note if (!strcmp(msg, "-")) notetxt = NULL; // delete note else @@ -501,36 +565,7 @@ } else { // Display a note struct annotation *note = jb_get_storage_rosternotes(jid); if (note) { - char tbuf[128]; - guint msg_flag = HBB_PREFIX_INFO; - /* We use the flag prefix_info for the first line, and prefix_none - for the other lines, for better readability */ - - // If we have the creation date, display it - if (note->cdate) { - strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", - localtime(¬e->cdate)); - msg = g_strdup_printf("Note created %s", tbuf); - scr_WriteIncomingMessage(jid, msg, 0, msg_flag); - g_free(msg); - msg_flag = HBB_PREFIX_NONE; - } - // If we have the modification date, display it - // unless it's the same as the creation date - if (note->mdate && note->mdate != note->cdate) { - strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", - localtime(¬e->mdate)); - msg = g_strdup_printf("Note modified %s", tbuf); - scr_WriteIncomingMessage(jid, msg, 0, msg_flag); - g_free(msg); - msg_flag = HBB_PREFIX_NONE; - } - // Note text - msg = g_strdup_printf("Note: %s", note->text); - scr_WriteIncomingMessage(jid, msg, 0, msg_flag); - g_free(note->text); - g_free(note); - g_free(msg); + display_and_free_note(note, jid); } else { scr_WriteIncomingMessage(jid, "This item doesn't have a note.", 0, HBB_PREFIX_INFO); @@ -1300,6 +1335,7 @@ if (note) { // We do not display the note, we just tell the user. g_free(note->text); + g_free(note->jid); g_free(note); scr_WriteIncomingMessage(jid, "(This item has an annotation)", 0, HBB_PREFIX_INFO); diff -r 97f862e44d5d -r 4c8d7b558e83 mcabber/src/jabglue.c --- a/mcabber/src/jabglue.c Wed Nov 15 22:47:35 2006 +0100 +++ b/mcabber/src/jabglue.c Sat Nov 18 10:44:58 2006 +0100 @@ -1238,6 +1238,53 @@ "Warning: you're not connected to the server."); } +static struct annotation *parse_storage_rosternote(xmlnode notenode) +{ + const char *p; + struct annotation *note = g_new0(struct annotation, 1); + p = xmlnode_get_attrib(notenode, "cdate"); + if (p) + note->cdate = from_iso8601(p, 1); + p = xmlnode_get_attrib(notenode, "mdate"); + if (p) + note->mdate = from_iso8601(p, 1); + note->text = g_strdup(xmlnode_get_data(notenode)); + note->jid = g_strdup(xmlnode_get_attrib(notenode, "jid")); + return note; +} + +// jb_get_all_storage_rosternotes() +// Return a GSList with all storage annotations. +// The caller should g_free the list and its contents. +GSList *jb_get_all_storage_rosternotes(void) +{ + xmlnode x; + GSList *sl_notes = NULL; + + // If we have no rosternotes, probably the server doesn't support them. + if (!rosternotes) + return NULL; + + // Walk through the storage rosternotes tags + x = xmlnode_get_firstchild(rosternotes); + for ( ; x; x = xmlnode_get_nextsibling(x)) { + const char *p; + struct annotation *note; + p = xmlnode_get_name(x); + + // We want a note item + if (!p || strcmp(p, "note")) + continue; + // Just in case, check the jid... + if (!xmlnode_get_attrib(x, "jid")) + continue; + // Ok, let's add the note to our list + note = parse_storage_rosternote(x); + sl_notes = g_slist_append(sl_notes, note); + } + return sl_notes; +} + // jb_get_storage_rosternotes(barejid) // Return the annotation associated with this jid. // The caller should g_free the string and structure after use. @@ -1255,30 +1302,19 @@ return NULL; } - // Walk through the storage tags + // Walk through the storage rosternotes tags x = xmlnode_get_firstchild(rosternotes); for ( ; x; x = xmlnode_get_nextsibling(x)) { const char *jid; const char *p; p = xmlnode_get_name(x); - // If the current node is a conference item, see if we have to replace it. - if (p && !strcmp(p, "note")) { - jid = xmlnode_get_attrib(x, "jid"); - if (!jid) - continue; - if (!strcmp(jid, barejid)) { - // We've found a note for this contact. - struct annotation *note = g_new0(struct annotation, 1); - p = xmlnode_get_attrib(x, "cdate"); - if (p) - note->cdate = from_iso8601(p, 1); - p = xmlnode_get_attrib(x, "mdate"); - if (p) - note->mdate = from_iso8601(p, 1); - note->text = g_strdup(xmlnode_get_data(x)); - return note; - } - } + // We want a note item + if (!p || strcmp(p, "note")) + continue; + // Just in case, check the jid... + jid = xmlnode_get_attrib(x, "jid"); + if (jid && !strcmp(jid, barejid)) // We've found a note for this contact. + return parse_storage_rosternote(x); } return NULL; // No note found } diff -r 97f862e44d5d -r 4c8d7b558e83 mcabber/src/jabglue.h --- a/mcabber/src/jabglue.h Wed Nov 15 22:47:35 2006 +0100 +++ b/mcabber/src/jabglue.h Sat Nov 18 10:44:58 2006 +0100 @@ -38,6 +38,7 @@ struct annotation { time_t cdate; time_t mdate; + gchar *jid; gchar *text; }; @@ -78,6 +79,7 @@ const char *nick, const char *passwd, int autojoin); struct annotation *jb_get_storage_rosternotes(const char *barejid); +GSList *jb_get_all_storage_rosternotes(void); void jb_set_storage_rosternotes(const char *barejid, const char *note); #endif /* __JABGLUE_H__ */