changeset 29440:1fb503adb2ae

Move the mood UI for ICQ into Pidgin. It still uses the new request API stuff, which needs to be replaced. Then it needs to replace the XMPP UI.
author Richard Laager <rlaager@wiktel.com>
date Mon, 17 Nov 2008 07:30:43 +0000
parents cdd5c6929c52
children 086b26f60913
files libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/usermood.c libpurple/protocols/oscar/family_locate.c libpurple/protocols/oscar/libicq.c libpurple/protocols/oscar/oscar.c libpurple/protocols/oscar/oscar.h libpurple/protocols/oscar/oscarcommon.h libpurple/protocols/oscar/tlv.c libpurple/prpl.h libpurple/status.h pidgin/gtkblist.c
diffstat 11 files changed, 304 insertions(+), 195 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Nov 17 07:30:43 2008 +0000
@@ -1567,11 +1567,11 @@
 
 			purple_notify_user_info_add_pair(user_info, _("Subscription"), sub);
 
-			status = purple_presence_get_active_status(presence);
-			mood = purple_status_get_attr_string(status, "mood");
+			status = purple_presence_get_status(presence, "mood");
+			mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
 			if(mood && *mood) {
 				const char *moodtext;
-				moodtext = purple_status_get_attr_string(status, "moodtext");
+				moodtext = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
 				if(moodtext && *moodtext) {
 					char *moodplustext = g_strdup_printf("%s (%s)", mood, moodtext);
 
--- a/libpurple/protocols/jabber/usermood.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Mon Nov 17 07:30:43 2008 +0000
@@ -150,15 +150,12 @@
 		}
 	}
 	if (newmood != NULL) {
-		const char *status_id;
-		JabberBuddyResource *resource = jabber_buddy_find_resource(buddy, NULL);
-		if(!resource) { /* huh? */
-			g_free(moodtext);
-			return;
-		}
-		status_id = jabber_buddy_state_get_status_id(resource->state);
-
-		purple_prpl_got_user_status(js->gc->account, from, status_id, "mood", _(newmood), "moodtext", moodtext?moodtext:"", NULL);
+		purple_prpl_got_user_status(js->gc->account, from, "mood",
+				PURPLE_MOOD_NAME, mood,
+				PURPLE_MOOD_COMMENT, moodtext,
+				NULL);
+	} else {
+		purple_prpl_got_user_status_deactive(js->gc->account, from, "mood");
 	}
 	g_free(moodtext);
 }
--- a/libpurple/protocols/oscar/family_locate.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Mon Nov 17 07:30:43 2008 +0000
@@ -252,159 +252,202 @@
 	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
 };
 
+/* Keep this array synchronized with icq_purple_moods. */
 static const struct {
-	char *mood;
-	char *descriptivename;
+	const char *mood;
 	guint8 data[16];
-} aim_custom_icons[] = {
-	/* empty X-Status for the case when customicon == 0 */
-	{NULL, NULL,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+} icq_custom_icons[] = {
 
-	{"thinking", N_("Thinking"),
+	{"thinking",
 	 {0x3f, 0xb0, 0xbd, 0x36, 0xaf, 0x3b, 0x4a, 0x60,
 	  0x9e, 0xef, 0xcf, 0x19, 0x0f, 0x6a, 0x5a, 0x7f}},
 
-	{"busy", N_("Busy"),
+	{"busy",
 	 {0x48, 0x8e, 0x14, 0x89, 0x8a, 0xca, 0x4a, 0x08,
 	  0x82, 0xaa, 0x77, 0xce, 0x7a, 0x16, 0x52, 0x08}},
 
-	{"shopping", N_("Shopping"),
+	{"shopping",
 	 {0x63, 0x62, 0x73, 0x37, 0xa0, 0x3f, 0x49, 0xff,
 	  0x80, 0xe5, 0xf7, 0x09, 0xcd, 0xe0, 0xa4, 0xee}},
 
 	/* This was in the original patch, but isn't what the official client
 	 * (ICQ 6) sets when you choose its typewriter icon. */
-	{"typing", NULL,
+	{"typing",
 	 {0x63, 0x4f, 0x6b, 0xd8 ,0xad, 0xd2, 0x4a, 0xa1,
 	  0xaa, 0xb9, 0x11, 0x5b, 0xc2, 0x6d, 0x05, 0xa1}},
 
-	{"question", N_("Questioning"),
+	{"question",
 	 {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0,
 	  0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64}},
 
-	{"angry", N_("Angry"),
+	{"angry",
 	 {0x01, 0xd8, 0xd7, 0xee, 0xac, 0x3b, 0x49, 0x2a,
 	  0xa5, 0x8d, 0xd3, 0xd8, 0x77, 0xe6, 0x6b, 0x92}},
 
-	{"plate", N_("Eating"),
+	{"plate",
 	 {0xf8, 0xe8, 0xd7, 0xb2, 0x82, 0xc4, 0x41, 0x42,
 	  0x90, 0xf8, 0x10, 0xc6, 0xce, 0x0a, 0x89, 0xa6}},
 
-	{"cinema", N_("Watching a movie"),
+	{"cinema",
 	 {0x10, 0x7a, 0x9a, 0x18, 0x12, 0x32, 0x4d, 0xa4,
 	  0xb6, 0xcd, 0x08, 0x79, 0xdb, 0x78, 0x0f, 0x09}},
 
-	{"sick", N_("Sick"),
+	{"sick",
 	 {0x1f, 0x7a, 0x40, 0x71, 0xbf, 0x3b, 0x4e, 0x60,
 	  0xbc, 0x32, 0x4c, 0x57, 0x87, 0xb0, 0x4c, 0xf1}},
 
-	{"typing", N_("Typing"),
+	{"typing",
 	 {0x2c, 0xe0, 0xe4, 0xe5, 0x7c, 0x64, 0x43, 0x70,
 	  0x9c, 0x3a, 0x7a, 0x1c, 0xe8, 0x78, 0xa7, 0xdc}},
 
-	{"suit", N_("At the office"),
+	{"suit",
 	 {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27,
 	  0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97}},
 
-	{"bathing", N_("Taking a bath"),
+	{"bathing",
 	 {0x5a, 0x58, 0x1e, 0xa1, 0xe5, 0x80, 0x43, 0x0c,
 	  0xa0, 0x6f, 0x61, 0x22, 0x98, 0xb7, 0xe4, 0xc7}},
 
-	{"tv", N_("Watching TV"),
+	{"tv",
 	 {0x80, 0x53, 0x7d, 0xe2, 0xa4, 0x67, 0x4a, 0x76,
 	  0xb3, 0x54, 0x6d, 0xfd, 0x07, 0x5f, 0x5e, 0xc6}},
 
-	{"excited", N_("Having fun"),
+	{"excited",
 	 {0x6f, 0x49, 0x30, 0x98, 0x4f, 0x7c, 0x4a, 0xff,
 	  0xa2, 0x76, 0x34, 0xa0, 0x3b, 0xce, 0xae, 0xa7}},
 
-	{"sleeping", N_("Sleeping"),
+	{"sleeping",
 	 {0x78, 0x5e, 0x8c, 0x48, 0x40, 0xd3, 0x4c, 0x65,
 	  0x88, 0x6f, 0x04, 0xcf, 0x3f, 0x3f, 0x43, 0xdf}},
 
-	{"hiptop", N_("Using a PDA"),
+	{"hiptop",
 	 {0x10, 0x11, 0x17, 0xc9, 0xa3, 0xb0, 0x40, 0xf9,
 	  0x81, 0xac, 0x49, 0xe1, 0x59, 0xfb, 0xd5, 0xd4}},
 
-	{"in_love", N_("In love"),
+	{"in_love",
 	 {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48,
 	  0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80}},
 
-	/* Sleepy / Tired */
-	{"sleepy", N_("Sleepy"),
+	{"sleepy",
 	 {0x83, 0xc9, 0xb7, 0x8e, 0x77, 0xe7, 0x43, 0x78,
 	  0xb2, 0xc5, 0xfb, 0x6c, 0xfc, 0xc3, 0x5b, 0xec}},
 
-	{"meeting", N_("Meeting friends"),
+	{"meeting",
 	 {0xf1, 0x8a, 0xb5, 0x2e, 0xdc, 0x57, 0x49, 0x1d,
 	  0x99, 0xdc, 0x64, 0x44, 0x50, 0x24, 0x57, 0xaf}},
 
-	{"phone", N_("On the phone"),
+	{"phone",
 	 {0x12, 0x92, 0xe5, 0x50, 0x1b, 0x64, 0x4f, 0x66,
 	  0xb2, 0x06, 0xb2, 0x9a, 0xf3, 0x78, 0xe4, 0x8d}},
 
-	{"surfing", N_("Surfing"),
+	{"surfing",
 	 {0xa6, 0xed, 0x55, 0x7e, 0x6b, 0xf7, 0x44, 0xd4,
 	  0xa5, 0xd4, 0xd2, 0xe7, 0xd9, 0x5c, 0xe8, 0x1f}},
 
-	/* "I am mobile." / "John is mobile." */
-	{"mobile", N_("Mobile"),
+	{"mobile",
 	 {0x16, 0x0c, 0x60, 0xbb, 0xdd, 0x44, 0x43, 0xf3,
 	  0x91, 0x40, 0x05, 0x0f, 0x00, 0xe6, 0xc0, 0x09}},
 
-	{"search", N_("Searching the web"),
+	{"search",
 	 {0xd4, 0xe2, 0xb0, 0xba, 0x33, 0x4e, 0x4f, 0xa5,
 	  0x98, 0xd0, 0x11, 0x7d, 0xbf, 0x4d, 0x3c, 0xc8}},
 
-	{"party", N_("At a party"),
+	{"party",
 	 {0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1,
 	  0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x81}},
 
-	{"coffee", N_("Having Coffee"),
+	{"coffee",
 	 {0x1b, 0x78, 0xae, 0x31, 0xfa, 0x0b, 0x4d, 0x38,
 	  0x93, 0xd1, 0x99, 0x7e, 0xee, 0xaf, 0xb2, 0x18}},
 
-	/* Playing video games */
-	{"console", N_("Gaming"),
+	{"console",
 	 {0xd4, 0xa6, 0x11, 0xd0, 0x8f, 0x01, 0x4e, 0xc0,
 	  0x92, 0x23, 0xc5, 0xb6, 0xbe, 0xc6, 0xcc, 0xf0}},
 
-	{"internet", N_("Browsing the web"),
+	{"internet",
 	 {0x12, 0xd0, 0x7e, 0x3e, 0xf8, 0x85, 0x48, 0x9e,
 	  0x8e, 0x97, 0xa7, 0x2a, 0x65, 0x51, 0xe5, 0x8d}},
 
-	{"cigarette", N_("Smoking"),
+	{"cigarette",
 	 {0x64, 0x43, 0xc6, 0xaf, 0x22, 0x60, 0x45, 0x17,
 	  0xb5, 0x8c, 0xd7, 0xdf, 0x8e, 0x29, 0x03, 0x52}},
 
-	{"writing", N_("Writing"),
+	{"writing",
 	 {0x00, 0x72, 0xd9, 0x08, 0x4a, 0xd1, 0x43, 0xdd,
 	  0x91, 0x99, 0x6f, 0x02, 0x69, 0x66, 0x02, 0x6f}},
 
-	/* Drinking [Alcohol] */
-	{"beer", N_("Drinking"),
+	{"beer",
 	 {0x8c, 0x50, 0xdb, 0xae, 0x81, 0xed, 0x47, 0x86,
 	  0xac, 0xca, 0x16, 0xcc, 0x32, 0x13, 0xc7, 0xb7}},
 
-	{"music", N_("Listening to music"),
+	{"music",
 	 {0x61, 0xbe, 0xe0, 0xdd, 0x8b, 0xdd, 0x47, 0x5d,
 	  0x8d, 0xee, 0x5f, 0x4b, 0xaa, 0xcf, 0x19, 0xa7}},
 
-	{"studying", N_("Studying"),
+	{"studying",
 	 {0x60, 0x9d, 0x52, 0xf8, 0xa2, 0x9a, 0x49, 0xa6,
 	  0xb2, 0xa0, 0x25, 0x24, 0xc5, 0xe9, 0xd2, 0x60}},
 
-	{"working", N_("Working"),
+	{"working",
 	 {0xba, 0x74, 0xdb, 0x3e, 0x9e, 0x24, 0x43, 0x4b,
 	  0x87, 0xb6, 0x2f, 0x6b, 0x8d, 0xfe, 0xe5, 0x0f}},
 
-	{"restroom", N_("In the restroom"),
+	{"restroom",
 	 {0x16, 0xf5, 0xb7, 0x6f, 0xa9, 0xd2, 0x40, 0x35,
-	  0x8c, 0xc5, 0xc0, 0x84, 0x70, 0x3c, 0x98, 0xfa}}
+	  0x8c, 0xc5, 0xc0, 0x84, 0x70, 0x3c, 0x98, 0xfa}},
+
+	{NULL,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
 };
 
+/* Keep this array synchronized with icq_custom_icons. */
+static PurpleMood icq_purple_moods[] = {
+	{"thinking", N_("Thinking"), NULL},
+	{"busy", N_("Busy"), NULL},
+	{"shopping", N_("Shopping"), NULL},
+	/* This was in the original patch, but isn't what the official client
+	 * (ICQ 6) sets when you choose its typewriter icon. */
+	{"typing", NULL, NULL},
+	{"question", N_("Questioning"), NULL},
+	{"angry", N_("Angry"), NULL},
+	{"plate", N_("Eating"), NULL},
+	{"cinema", N_("Watching a movie"), NULL},
+	{"sick", N_("Sick"), NULL},
+	{"typing", N_("Typing"), NULL},
+	{"suit", N_("At the office"), NULL},
+	{"bathing", N_("Taking a bath"), NULL},
+	{"tv", N_("Watching TV"), NULL},
+	{"excited", N_("Having fun"), NULL},
+	{"sleeping", N_("Sleeping"), NULL},
+	{"hiptop", N_("Using a PDA"), NULL},
+	{"in_love", N_("In love"), NULL},
+	/* Sleepy / Tired */
+	{"sleepy", N_("Sleepy"), NULL},
+	{"meeting", N_("Meeting friends"), NULL},
+	{"phone", N_("On the phone"), NULL},
+	{"surfing", N_("Surfing"), NULL},
+	/* "I am mobile." / "John is mobile." */
+	{"mobile", N_("Mobile"), NULL},
+	{"search", N_("Searching the web"), NULL},
+	{"party", N_("At a party"), NULL},
+	{"coffee", N_("Having Coffee"), NULL},
+	/* Playing video games */
+	{"console", N_("Gaming"), NULL},
+	{"internet", N_("Browsing the web"), NULL},
+	{"cigarette", N_("Smoking"), NULL},
+	{"writing", N_("Writing"), NULL},
+	/* Drinking [Alcohol] */
+	{"beer", N_("Drinking"), NULL},
+	{"music", N_("Listening to music"), NULL},
+	{"studying", N_("Studying"), NULL},
+	{"working", N_("Working"), NULL},
+	{"restroom", N_("In the restroom"), NULL},
+	/* Mark the last record. */
+	{NULL, NULL, NULL},
+};
+
+
 /*
  * Add the userinfo to our linked list.  If we already have userinfo
  * for this buddy, then just overwrite parts of the old data.
@@ -652,10 +695,10 @@
 
 		cap = byte_stream_getraw(bs, 0x10);
 
-		for (i = 1; i < G_N_ELEMENTS(aim_custom_icons); i++) {
-			if (memcmp(&aim_custom_icons[i].data, cap, 0x10) == 0) {
-				purple_debug_misc("oscar", "Custom status icon: %s\n", aim_custom_icons[i].descriptivename);		
-				result = aim_custom_icons[i].mood;
+		for (i = 0; icq_custom_icons[i].mood; i++) {
+			if (memcmp(&icq_custom_icons[i].data, cap, 0x10) == 0) {
+				purple_debug_misc("oscar", "Custom status icon: %s\n", icq_purple_moods[i].description);		
+				result = icq_custom_icons[i].mood;
 				break; /* should only match once... */
 			}
 		}
@@ -1741,43 +1784,56 @@
 	return 0;
 }
 
-#if 1 //rlaager
-size_t aim_get_custom_icons_count(void)
-{
-	return G_N_ELEMENTS(aim_custom_icons);
-}
-
-char* aim_get_custom_icon_mood(gint32 no)
+#if 0 //rlaager
+const char* aim_get_custom_icon_mood(gint32 no)
 {
 	if (no >= G_N_ELEMENTS(aim_custom_icons) || no < 1)
 		return NULL;
-	return aim_custom_icons[no].mood;
-}
-
-char* aim_get_custom_icon_descriptivename(gint32 no)
-{
-	if (no >= G_N_ELEMENTS(aim_custom_icons) || no < 1)
-		return NULL;
-	return aim_custom_icons[no].descriptivename;
+	return aim_custom_icons[no].mood.mood;
 }
 #endif
 
-guint8*
-aim_get_custom_icon_data(const char *mood)
+const char*
+icq_get_custom_icon_description(const char *mood)
 {
 	int i;
 
 	if (!(mood && *mood))
 		return NULL;
 
-	for (i = 1; i < G_N_ELEMENTS(aim_custom_icons); i++) {
-		/* We check that descriptivename is not NULL to exclude
+	for (i = 0; icq_custom_icons[i].mood; i++) {
+		/* We check that description is not NULL to exclude
 		 * duplicates, like the typing duplicate. */
-		if (aim_custom_icons[i].descriptivename &&
-		    aim_custom_icons[i].mood &&
-		    !strcmp(mood, aim_custom_icons[i].mood)) {
-			return (guint8 *)aim_custom_icons[i].data;
+		if (icq_purple_moods[i].description &&
+		    !strcmp(mood, icq_custom_icons[i].mood)) {
+			return icq_purple_moods[i].description;
+		}
+	}
+
+	return NULL;
+}
+
+guint8*
+icq_get_custom_icon_data(const char *mood)
+{
+	int i;
+
+	if (!(mood && *mood))
+		return NULL;
+
+	for (i = 0; icq_custom_icons[i].mood; i++) {
+		/* We check that description is not NULL to exclude
+		 * duplicates, like the typing duplicate. */
+		if (icq_purple_moods[i].description &&
+		    !strcmp(mood, icq_custom_icons[i].mood)) {
+			return (guint8 *)icq_custom_icons[i].data;
 		}
 	}
 	return NULL;
 }
+
+PurpleMood*
+icq_get_purple_moods(PurpleAccount *account)
+{
+	return icq_purple_moods;
+}
--- a/libpurple/protocols/oscar/libicq.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Mon Nov 17 07:30:43 2008 +0000
@@ -107,6 +107,7 @@
 
 	sizeof(PurplePluginProtocolInfo),       /* struct_size */
 	icq_get_account_text_table, /* get_account_text_table */
+	oscar_get_purple_moods, /* get_moods */
 };
 
 static PurplePluginInfo info =
--- a/libpurple/protocols/oscar/oscar.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Nov 17 07:30:43 2008 +0000
@@ -934,6 +934,16 @@
 
 	}
 
+	if (presence) {
+		const char *mood;
+		const char *description;
+		status = purple_presence_get_status(presence, "mood");
+		mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+		description = icq_get_custom_icon_description(mood);
+		if (description && *description)
+			purple_notify_user_info_add_pair(user_info, _("Mood"), _(description));
+	}
+
 	purple_notify_user_info_add_pair(user_info, _("Status"), message);
 	g_free(message);
 }
@@ -4866,8 +4876,11 @@
 		return;
 
 	/* There's no need to do the stuff below for mood updates. */
-	if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD)
+	if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+		PurpleConnection *gc = purple_account_get_connection(account);
+		aim_locate_setcaps((OscarData *)gc->proto_data, purple_caps);
 		return;
+	}
 
 	/* Set the AIM-style away message for both AIM and ICQ accounts */
 	oscar_set_info_and_status(account, FALSE, NULL, TRUE, status);
@@ -5795,6 +5808,11 @@
 	return 0;
 }
 
+PurpleMood* oscar_get_purple_moods(PurpleAccount *account)
+{
+	return icq_get_purple_moods(account);
+}
+
 const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b)
 {
 	if ((b == NULL) || (b->name == NULL) || aim_snvalid_sms(b->name))
@@ -6762,99 +6780,6 @@
 		purple_xfer_request(xfer);
 }
 
-/* XXX: rlaager wants UI in the UI. */
-#if 1
-static void
-oscar_show_icq_moods_cb(PurpleConnection *gc, PurpleRequestFields *fields) {
-	OscarData *od = gc->proto_data;
-	PurpleRequestField *f;
-	GList *l;
-
-	f = purple_request_fields_get_field(fields, "mood");
-	l = purple_request_field_list_get_selected(f);
-	
-	if (l) {
-		const char *mood = purple_request_field_list_get_data(f, l->data);
-		PurpleAccount *account = purple_connection_get_account(gc);
-
-		if (mood != NULL) {
-			purple_account_set_status(account, "mood", TRUE,
-			                          PURPLE_MOOD_NAME, mood,
-			                          NULL);
-		} else {
-			purple_account_set_status(account, "mood", FALSE, NULL);
-		}
-	}
-
-	aim_locate_setcaps(od, purple_caps);
-}
-
-static void
-oscar_show_icq_moods(PurplePluginAction *action)
-{
-	PurpleConnection *gc = (PurpleConnection *) action->context;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurplePresence *presence = purple_account_get_presence(account);
-	PurpleStatus *status = purple_presence_get_status(presence, "mood");
-	const char *current_mood;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	guint32 i;
-	char* na_fn;
-
-	current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-
-	f = purple_request_field_list_new("mood", _("Please select your mood from the list."));
-
-	na_fn = g_build_filename("pixmaps", "pidgin", "emblems", "16", "not-authorized.png", NULL);
-
-	purple_request_field_list_add_icon(f, _("None"), na_fn, NULL);
-	if (current_mood == NULL)
-		purple_request_field_list_add_selected(f, _("None"));
-
-	g_free(na_fn);
-
-	/* TODO: rlaager wants this sorted. */
-	for (i = 1; i < aim_get_custom_icons_count(); i++) {
-		const char *mood = aim_get_custom_icon_mood(i);
-		const char *icon_desc = aim_get_custom_icon_descriptivename(i);
-		char *icon_path;
-		char *filename;
-
-		if (mood == NULL || icon_desc == NULL)
-			continue;
-
-		icon_path = g_strdup_printf("%s.png", mood);
-		filename = g_build_filename("pixmaps", "pidgin",
-		                            "emblems", "16",
-		                             icon_path, NULL);
-		g_free(icon_path);
-
-		purple_request_field_list_add_icon(f, _(icon_desc),
-				filename, (gpointer)mood);
-		g_free(filename);
-
-		if (current_mood && !strcmp(current_mood, mood))
-			purple_request_field_list_add_selected(f, _(icon_desc));
-	}
-	purple_request_field_group_add_field(g, f);
-	
-	purple_request_fields_add_group(fields, g);
-	
-	purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
-						NULL, fields,
-						_("OK"), G_CALLBACK(oscar_show_icq_moods_cb),
-						_("Cancel"), NULL,
-						purple_connection_get_account(gc), NULL, NULL,
-						gc);
-}
-#endif
-
 GList *
 oscar_actions(PurplePlugin *plugin, gpointer context)
 {
@@ -6897,13 +6822,6 @@
 		act = purple_plugin_action_new(_("Set Privacy Options..."),
 				oscar_show_icq_privacy_opts);
 		menu = g_list_prepend(menu, act);
-
-/* XXX: rlaager wants UI in the UI. */
-#if 1
-		act = purple_plugin_action_new(_("Set Mood..."),
-				oscar_show_icq_moods);
-		menu = g_list_prepend(menu, act);
-#endif
 	}
 	else
 	{
--- a/libpurple/protocols/oscar/oscar.h	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Nov 17 07:30:43 2008 +0000
@@ -1108,12 +1108,9 @@
 #if 0
 int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info);
 #endif
-#if 1
-size_t aim_get_custom_icons_count(void); //rlaager
-char* aim_get_custom_icon_mood(gint32 no);// rlaager
-char* aim_get_custom_icon_descriptivename(gint32 no); // rlaager
-#endif
-guint8* aim_get_custom_icon_data(const char *mood);
+PurpleMood* icq_get_purple_moods(PurpleAccount *account);
+const char* icq_get_custom_icon_description(const char *mood);
+guint8* icq_get_custom_icon_data(const char *mood);
 int icq_im_xstatus_request(OscarData *od, const char *sn);
 
 /* 0x0003 - family_buddy.c */
--- a/libpurple/protocols/oscar/oscarcommon.h	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/oscarcommon.h	Mon Nov 17 07:30:43 2008 +0000
@@ -29,6 +29,7 @@
 #include "prpl.h"
 #include "version.h"
 #include "notify.h"
+#include "status.h"
 
 #define OSCAR_DEFAULT_LOGIN_SERVER "login.messaging.aol.com"
 #define OSCAR_DEFAULT_LOGIN_PORT 5190
@@ -46,6 +47,7 @@
 #ifdef _WIN32
 const char *oscar_get_locale_charset(void);
 #endif
+PurpleMood* oscar_get_purple_moods(PurpleAccount *account);
 const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b);
 const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b);
 const char* oscar_list_emblem(PurpleBuddy *b);
--- a/libpurple/protocols/oscar/tlv.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/protocols/oscar/tlv.c	Mon Nov 17 07:30:43 2008 +0000
@@ -421,7 +421,7 @@
 	byte_stream_putcaps(&bs, caps);
 	
 	/* adding of custom icon GUID */
-	data = aim_get_custom_icon_data(mood);
+	data = icq_get_custom_icon_data(mood);
 	if (data != NULL)
 		byte_stream_putraw(&bs, data, 16);
 
--- a/libpurple/prpl.h	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/prpl.h	Mon Nov 17 07:30:43 2008 +0000
@@ -440,6 +440,12 @@
 	 *         destroyed by the caller when it's no longer needed.
 	 */
 	GHashTable *(*get_account_text_table)(PurpleAccount *account);
+
+	/**
+	 * Returns an array of "PurpleMood"s, with the last one having
+	 * "mood" set to @c NULL.
+	 */
+	PurpleMood *(*get_moods)(PurpleAccount *account);
 };
 
 #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
--- a/libpurple/status.h	Mon Nov 17 04:18:05 2008 +0000
+++ b/libpurple/status.h	Mon Nov 17 07:30:43 2008 +0000
@@ -77,6 +77,12 @@
 typedef struct _PurplePresence        PurplePresence;
 typedef struct _PurpleStatus          PurpleStatus;
 
+typedef struct _PurpleMood {
+	const char *mood;
+	const char *description;
+	gpointer *padding;
+} PurpleMood;
+
 /**
  * A context for a presence.
  *
--- a/pidgin/gtkblist.c	Mon Nov 17 04:18:05 2008 +0000
+++ b/pidgin/gtkblist.c	Mon Nov 17 07:30:43 2008 +0000
@@ -7624,6 +7624,95 @@
 	purple_account_set_enabled(account, PIDGIN_UI, FALSE);
 }
 
+static void
+edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields)
+{
+	PurpleRequestField *f;
+	GList *l;
+
+	f = purple_request_fields_get_field(fields, "mood");
+	l = purple_request_field_list_get_selected(f);
+
+	if (l) {
+		const char *mood = purple_request_field_list_get_data(f, l->data);
+		PurpleAccount *account = purple_connection_get_account(gc);
+
+		if (mood != NULL) {
+			purple_account_set_status(account, "mood", TRUE,
+			                          PURPLE_MOOD_NAME, mood,
+			                          NULL);
+		} else {
+			purple_account_set_status(account, "mood", FALSE, NULL);
+		}
+	}
+}
+
+static void
+set_mood_cb(GtkWidget *widget, PurpleAccount *account)
+{
+	PurplePresence *presence = purple_account_get_presence(account);
+	PurpleStatus *status = purple_presence_get_status(presence, "mood");
+	const char *current_mood;
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	char* na_fn;
+	PurpleConnection *gc = purple_account_get_connection(account);
+	PurplePluginProtocolInfo *prpl_info;
+	PurpleMood *mood;
+
+	g_return_if_fail(gc->prpl != NULL);
+	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+
+	current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+
+	fields = purple_request_fields_new();
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
+
+	na_fn = g_build_filename("pixmaps", "pidgin", "emblems", "16", "not-authorized.png", NULL);
+
+	purple_request_field_list_add_icon(f, _("None"), na_fn, NULL);
+	if (current_mood == NULL)
+		purple_request_field_list_add_selected(f, _("None"));
+
+	g_free(na_fn);
+
+	/* TODO: rlaager wants this sorted. */
+	for (mood = prpl_info->get_moods(account);
+	     mood->mood != NULL ; mood++)
+	{
+		char *icon_path;
+		char *filename;
+
+		if (mood->mood == NULL || mood->description == NULL)
+			continue;
+
+		icon_path = g_strdup_printf("%s.png", mood->mood);
+		filename = g_build_filename("pixmaps", "pidgin",
+		                            "emblems", "16",
+		                             icon_path, NULL);
+		g_free(icon_path);
+
+		purple_request_field_list_add_icon(f, _(mood->description),
+				filename, mood->mood);
+		g_free(filename);
+
+		if (current_mood && !strcmp(current_mood, mood->mood))
+			purple_request_field_list_add_selected(f, _(mood->description));
+	}
+	purple_request_field_group_add_field(g, f);
+	
+	purple_request_fields_add_group(fields, g);
+	
+	purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
+                              NULL, fields,
+                              _("OK"), G_CALLBACK(edit_mood_cb),
+                              _("Cancel"), NULL,
+                              purple_connection_get_account(gc),
+                              NULL, NULL, gc);
+}
+
 void
 pidgin_blist_update_accounts_menu(void)
 {
@@ -7697,6 +7786,8 @@
 		PurpleAccount *account = NULL;
 		GdkPixbuf *pixbuf = NULL;
 		PurplePlugin *plugin = NULL;
+		PurplePluginProtocolInfo *prpl_info;
+		GList *types;
 
 		account = accounts->data;
 		accel_group = gtk_menu_get_accel_group(GTK_MENU(accountmenu));
@@ -7735,10 +7826,45 @@
 			gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
 			gtk_widget_show(menuitem);
 
-			pidgin_separator(submenu);
-
 			gc = purple_account_get_connection(account);
 			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
+
+printf("HERE1\n");
+if (plugin){
+	printf("HERE1.1\n");
+	if (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)) {
+		printf("HERE1.2: %s\n", purple_account_get_username(account));
+		if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods)) {
+			printf("HERE1.3\n");
+		}
+	}
+}
+			if (plugin &&
+			    (prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin)) &&
+			    PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods))
+			{
+printf("HERE2\n");
+				for (types = purple_account_get_status_types(account);
+				     types != NULL ; types = types->next)
+				{
+					PurpleStatusType *type = types->data;
+printf("HERE3\n");
+					if (strcmp(purple_status_type_get_id(type), "mood") != 0)
+						continue;
+printf("HERE4\n");
+					menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood..."));
+					g_signal_connect(G_OBJECT(menuitem), "activate",
+						         G_CALLBACK(set_mood_cb), account);
+					gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
+					gtk_widget_show(menuitem);
+
+					/* Be safe.  It shouldn't match more than once anyway */
+					break;
+				}
+			}
+
+			pidgin_separator(submenu);
+
 			if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
 				build_plugin_actions(submenu, plugin, gc);
 			} else {