changeset 29453:05c84351338b

propagate from branch 'im.pidgin.pidgin' (head 71b6fbd59f6ae249e6d1e8ed75dc04c9206c41a5) to branch 'im.pidgin.cpw.rekkanoryo.icqxstatus' (head 8819fcd02c7479beb2775cc5e5f87cfdbaac7351)
author Richard Laager <rlaager@wiktel.com>
date Wed, 26 Nov 2008 22:17:03 +0000
parents 8050ea54a83e (current diff) 414886d7a51c (diff)
children f3b62076fa32
files pidgin/pixmaps/emblems/16/mobile.png pidgin/pixmaps/emotes/default/24/eat.png pidgin/pixmaps/emotes/default/24/in-love.png pidgin/pixmaps/emotes/default/24/love.png pidgin/pixmaps/emotes/default/24/nailbiting.png pidgin/pixmaps/emotes/default/24/shock.png pidgin/pixmaps/emotes/default/24/smile-big.png pidgin/pixmaps/emotes/default/24/smile.png pidgin/pixmaps/emotes/default/24/sweat.png pidgin/pixmaps/emotes/default/24/tremble.png pidgin/pixmaps/emotes/default/24/yawn.png pidgin/pixmaps/emotes/small/16/love.png pidgin/pixmaps/emotes/small/16/shock.png pidgin/pixmaps/emotes/small/16/smile-big.png pidgin/pixmaps/emotes/small/16/smile.png pidgin/pixmaps/emotes/small/16/yawn.png
diffstat 94 files changed, 1599 insertions(+), 269 deletions(-) [+]
line wrap: on
line diff
--- a/.mtn-ignore	Wed Nov 26 22:16:58 2008 +0000
+++ b/.mtn-ignore	Wed Nov 26 22:17:03 2008 +0000
@@ -37,6 +37,41 @@
 pidgin-.*.tar.bz2
 pidgin-*.*.*-win32bin$
 pidgin/pidgin$
+pidgin/pixmaps/emblems/16/afraid.png
+pidgin/pixmaps/emblems/16/amorous.png
+pidgin/pixmaps/emblems/16/angry.png
+pidgin/pixmaps/emblems/16/beer.png
+pidgin/pixmaps/emblems/16/busy.png
+pidgin/pixmaps/emblems/16/cigarette.png
+pidgin/pixmaps/emblems/16/coffee.png
+pidgin/pixmaps/emblems/16/confused.png
+pidgin/pixmaps/emblems/16/console.png
+pidgin/pixmaps/emblems/16/disappointed.png
+pidgin/pixmaps/emblems/16/embarrassed.png
+pidgin/pixmaps/emblems/16/excited.png
+pidgin/pixmaps/emblems/16/happy.png
+pidgin/pixmaps/emblems/16/hot.png
+pidgin/pixmaps/emblems/16/hungry.png
+pidgin/pixmaps/emblems/16/in_love.png
+pidgin/pixmaps/emblems/16/mean.png
+pidgin/pixmaps/emblems/16/meeting.png
+pidgin/pixmaps/emblems/16/mobile.png
+pidgin/pixmaps/emblems/16/musical-note.png
+pidgin/pixmaps/emblems/16/nervous.png
+pidgin/pixmaps/emblems/16/neutral.png
+pidgin/pixmaps/emblems/16/party.png
+pidgin/pixmaps/emblems/16/phone.png
+pidgin/pixmaps/emblems/16/plate.png
+pidgin/pixmaps/emblems/16/question.png
+pidgin/pixmaps/emblems/16/sad.png
+pidgin/pixmaps/emblems/16/sarcastic.png
+pidgin/pixmaps/emblems/16/search.png
+pidgin/pixmaps/emblems/16/shocked.png
+pidgin/pixmaps/emblems/16/sick.png
+pidgin/pixmaps/emblems/16/sleeping.png
+pidgin/pixmaps/emblems/16/sleepy.png
+pidgin/pixmaps/emblems/16/thinking.png
+pidgin/pixmaps/emblems/16/tv.png
 pidgin/pixmaps/emotes/default/24/theme
 pidgin/pixmaps/emotes/none/theme
 pidgin/pixmaps/emotes/small/16/theme
--- a/COPYRIGHT	Wed Nov 26 22:16:58 2008 +0000
+++ b/COPYRIGHT	Wed Nov 26 22:17:03 2008 +0000
@@ -201,12 +201,14 @@
 Instant Messaging Freedom, Inc.
 Vitaliy Ischenko
 Intel Corporation
+Andrew Ivanov
 Scott Jackson
 Hans Petter Jansson
 Henry Jen
 Benjamin Kahn
 Anders Kaseorg
 Praveen Karadakal
+Tomáš Kebert
 John Kelm
 Jochen Kemnade
 Akuke Kok
@@ -477,6 +479,7 @@
 Ma Xuan
 Jared Yanovich
 Timmy Yee
+Yuriy Yevgrafov
 Nickolai Zeldovich
 Tom Zickel
 Marco Ziech
--- a/ChangeLog.API	Wed Nov 26 22:16:58 2008 +0000
+++ b/ChangeLog.API	Wed Nov 26 22:17:03 2008 +0000
@@ -1,5 +1,10 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.6.0 (??/??/????):
+	libpurple:
+		Added:
+		* PURPLE_STATUS_MOOD as a new PurpleStatusPrimitive
+
 version 2.5.0 (08/18/2008):
 	libpurple:
 		Added:
--- a/finch/gntplugin.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/finch/gntplugin.c	Wed Nov 26 22:17:03 2008 +0000
@@ -496,7 +496,7 @@
 						break;
 				}
 				stringlist = g_list_prepend(stringlist, value);
-				purple_request_field_list_add(field, label, value);
+				purple_request_field_list_add_icon(field, label, NULL, value);
 				if (strcmp(value, current_value) == 0)
 					purple_request_field_list_add_selected(field, label);
 				list = list->next->next;
--- a/finch/gntprefs.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/finch/gntprefs.c	Wed Nov 26 22:17:03 2008 +0000
@@ -170,7 +170,7 @@
 				default:
 					break;
 			}
-			purple_request_field_list_add(field, data, iter->data);
+			purple_request_field_list_add_icon(field, data, NULL, iter->data);
 			if (select)
 				purple_request_field_list_add_selected(field, data);
 		}
--- a/finch/plugins/gnthistory.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/finch/plugins/gnthistory.c	Wed Nov 26 22:17:03 2008 +0000
@@ -154,7 +154,7 @@
 		while (list) {
 			const char *label = _(list->data);
 			list = g_list_delete_link(list, list);
-			purple_request_field_list_add(field, label, list->data);
+			purple_request_field_list_add_icon(field, label, NULL, list->data);
 			if (system && strcmp(system, list->data) == 0)
 				purple_request_field_list_add_selected(field, label);
 			list = g_list_delete_link(list, list);
--- a/libpurple/plugins/perl/common/Request.xs	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/plugins/perl/common/Request.xs	Wed Nov 26 22:17:03 2008 +0000
@@ -374,6 +374,13 @@
 	void * data
 
 void
+purple_request_field_list_add_icon(field, item, icon_path, data)
+	Purple::Request::Field field
+	const char *item
+	const char *icon_path
+	void * data
+
+void
 purple_request_field_list_add_selected(field, item)
 	Purple::Request::Field field
 	const char *item
--- a/libpurple/protocols/gg/gg.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/gg/gg.c	Wed Nov 26 22:17:03 2008 +0000
@@ -757,16 +757,16 @@
 
 static void ggp_callback_add_to_chat_ok(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	GGPInfo *info = gc->proto_data;
 	PurpleRequestField *field;
-	/* TODO: sel may be null. */
 	GList *sel;
 
 	field = purple_request_fields_get_field(fields, "name");
 	sel = purple_request_field_list_get_selected(field);
+	if (sel == NULL || sel->data == NULL)
+		return;
 
-	ggp_confer_participants_add_uin(gc, sel->data, info->tmp_buddy);
-	info->tmp_buddy = 0;
+	ggp_confer_participants_add_uin(gc, sel->data,
+		GPOINTER_TO_INT(purple_request_field_list_get_data(field, sel->data)));
 }
 
 static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
@@ -786,9 +786,6 @@
 	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
 	info = gc->proto_data;
 
-	/* TODO: It tmp_buddy != 0 then stop! */
-	info->tmp_buddy = ggp_str_to_uin(purple_buddy_get_name(buddy));
-
 	fields = purple_request_fields_new();
 	group = purple_request_field_group_new(NULL);
 	purple_request_fields_add_group(fields, group);
@@ -796,8 +793,8 @@
 	field = purple_request_field_list_new("name", "Chat name");
 	for (l = info->chats; l != NULL; l = l->next) {
 		GGPChat *chat = l->data;
-		purple_request_field_list_add(field, g_strdup(chat->name),
-					    g_strdup(chat->name));
+		purple_request_field_list_add_icon(field, chat->name, NULL,
+			GINT_TO_POINTER(ggp_str_to_uin(purple_buddy_get_name(buddy))));
 	}
 	purple_request_field_group_add_field(group, field);
 
--- a/libpurple/protocols/gg/gg.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/gg/gg.h	Wed Nov 26 22:17:03 2008 +0000
@@ -62,7 +62,6 @@
 	GList *chats;
 	GGPSearches *searches;
 
-	uin_t tmp_buddy;
 	int chats_count;
 
 	GList *pending_richtext_messages;
--- a/libpurple/protocols/jabber/jabber.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Nov 26 22:17:03 2008 +0000
@@ -1567,12 +1567,12 @@
 
 			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");
-			if(mood != NULL) {
+			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");
-				if(moodtext != NULL) {
+				moodtext = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
+				if(moodtext && *moodtext) {
 					char *moodplustext = g_strdup_printf("%s (%s)", mood, moodtext);
 
 					purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext);
@@ -1658,7 +1658,7 @@
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 1);
@@ -1672,7 +1672,7 @@
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 0);
@@ -1686,7 +1686,7 @@
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 0);
@@ -1700,7 +1700,7 @@
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	priority_value = purple_value_new(PURPLE_TYPE_INT);
 	purple_value_set_int(priority_value, 0);
@@ -1714,11 +1714,11 @@
 			"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
 			"buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	/*
 	if(js->protocol_version == JABBER_PROTO_0_9)
-		m = g_list_append(m, _("Invisible"));
+		"Invisible"
 	*/
 
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE,
@@ -1726,7 +1726,7 @@
 			NULL, FALSE, TRUE, FALSE,
 			"message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
 			"tune", NULL, FALSE, TRUE, TRUE,
@@ -1740,9 +1740,9 @@
 			PURPLE_TUNE_YEAR, _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
 			PURPLE_TUNE_URL, _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
 			NULL);
-	types = g_list_append(types, type);
+	types = g_list_prepend(types, type);
 
-	return types;
+	return g_list_reverse(types);
 }
 
 static void
--- a/libpurple/protocols/jabber/usermood.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Wed Nov 26 22:17:03 2008 +0000
@@ -28,69 +28,93 @@
 #include "request.h"
 #include "debug.h"
 
-static const char * const moodstrings[] = {
-	"afraid",
-	"amazed",
-	"angry",
-	"annoyed",
-	"anxious",
-	"aroused",
-	"ashamed",
-	"bored",
-	"brave",
-	"calm",
-	"cold",
-	"confused",
-	"contented",
-	"cranky",
-	"curious",
-	"depressed",
-	"disappointed",
-	"disgusted",
-	"distracted",
-	"embarrassed",
-	"excited",
-	"flirtatious",
-	"frustrated",
-	"grumpy",
-	"guilty",
-	"happy",
-	"hot",
-	"humbled",
-	"humiliated",
-	"hungry",
-	"hurt",
-	"impressed",
-	"in_awe",
-	"in_love",
-	"indignant",
-	"interested",
-	"intoxicated",
-	"invincible",
-	"jealous",
-	"lonely",
-	"mean",
-	"moody",
-	"nervous",
-	"neutral",
-	"offended",
-	"playful",
-	"proud",
-	"relieved",
-	"remorseful",
-	"restless",
-	"sad",
-	"sarcastic",
-	"serious",
-	"shocked",
-	"shy",
-	"sick",
-	"sleepy",
-	"stressed",
-	"surprised",
-	"thirsty",
-	"worried",
-	NULL
+static PurpleMood moods[] = {
+	{"afraid", N_("Afraid"), NULL},
+	{"amazed", N_("Amazed"), NULL},
+	{"amorous", N_("Amorous"), NULL},
+	{"angry", N_("Angry"), NULL},
+	{"annoyed", N_("Annoyed"), NULL},
+	{"anxious", N_("Anxious"), NULL},
+	{"aroused", N_("Aroused"), NULL},
+	{"ashamed", N_("Ashamed"), NULL},
+	{"bored", N_("Bored"), NULL},
+	{"brave", N_("Brave"), NULL},
+	{"calm", N_("Calm"), NULL},
+	{"cautious", N_("Cautious"), NULL},
+	{"cold", N_("Cold"), NULL},
+	{"confident", N_("Confident"), NULL},
+	{"confused", N_("Confused"), NULL},
+	{"contemplative", N_("Contemplative"), NULL},
+	{"contented", N_("Contented"), NULL},
+	{"cranky", N_("Cranky"), NULL},
+	{"crazy", N_("Crazy"), NULL},
+	{"creative", N_("Creative"), NULL},
+	{"curious", N_("Curious"), NULL},
+	{"dejected", N_("Dejected"), NULL},
+	{"depressed", N_("Depressed"), NULL},
+	{"disappointed", N_("Disappointed"), NULL},
+	{"disgusted", N_("Disgusted"), NULL},
+	{"dismayed", N_("Dismayed"), NULL},
+	{"distracted", N_("Distracted"), NULL},
+	{"embarrassed", N_("Embarrassed"), NULL},
+	{"envious", N_("Envious"), NULL},
+	{"excited", N_("Excited"), NULL},
+	{"flirtatious", N_("Flirtatious"), NULL},
+	{"frustrated", N_("Frustrated"), NULL},
+	{"grateful", N_("Grateful"), NULL},
+	{"grieving", N_("Grieving"), NULL},
+	{"grumpy", N_("Grumpy"), NULL},
+	{"guilty", N_("Guilty"), NULL},
+	{"happy", N_("Happy"), NULL},
+	{"hopeful", N_("Hopeful"), NULL},
+	{"hot", N_("Hot"), NULL},
+	{"humbled", N_("Humbled"), NULL},
+	{"humiliated", N_("Humiliated"), NULL},
+	{"hungry", N_("Hungry"), NULL},
+	{"hurt", N_("Hurt"), NULL},
+	{"impressed", N_("Impressed"), NULL},
+	{"in_awe", N_("In_awe"), NULL},
+	{"in_love", N_("In_love"), NULL},
+	{"indignant", N_("Indignant"), NULL},
+	{"interested", N_("Interested"), NULL},
+	{"intoxicated", N_("Intoxicated"), NULL},
+	{"invincible", N_("Invincible"), NULL},
+	{"jealous", N_("Jealous"), NULL},
+	{"lonely", N_("Lonely"), NULL},
+	{"lost", N_("Lost"), NULL},
+	{"lucky", N_("Lucky"), NULL},
+	{"mean", N_("Mean"), NULL},
+	{"moody", N_("Moody"), NULL},
+	{"nervous", N_("Nervous"), NULL},
+	{"neutral", N_("Neutral"), NULL},
+	{"offended", N_("Offended"), NULL},
+	{"outraged", N_("Outraged"), NULL},
+	{"playful", N_("Playful"), NULL},
+	{"proud", N_("Proud"), NULL},
+	{"relaxed", N_("Relaxed"), NULL},
+	{"relieved", N_("Relieved"), NULL},
+	{"remorseful", N_("Remorseful"), NULL},
+	{"restless", N_("Restless"), NULL},
+	{"sad", N_("Sad"), NULL},
+	{"sarcastic", N_("Sarcastic"), NULL},
+	{"satisfied", N_("Satisfied"), NULL},
+	{"serious", N_("Serious"), NULL},
+	{"shocked", N_("Shocked"), NULL},
+	{"shy", N_("Shy"), NULL},
+	{"sick", N_("Sick"), NULL},
+	{"sleepy", N_("Sleepy"), NULL},
+	{"spontaneous", N_("Spontaneous"), NULL},
+	{"stressed", N_("Stressed"), NULL},
+	{"strong", N_("Strong"), NULL},
+	{"surprised", N_("Surprised"), NULL},
+	{"thankful", N_("Thankful"), NULL},
+	{"thirsty", N_("Thirsty"), NULL},
+	{"tired", N_("Tired"), NULL},
+	{"undefined", N_("Undefined"), NULL},
+	{"weak", N_("Weak"), NULL},
+	{"worried", N_("Worried"), NULL},
+	/* Mark the last record. */
+	{NULL, NULL, NULL}
 };
 
 static void jabber_mood_cb(JabberStream *js, const char *from, xmlnode *items) {
@@ -114,10 +138,10 @@
 					moodtext = xmlnode_get_data(moodinfo);
 			} else {
 				int i;
-				for (i = 0; moodstrings[i]; ++i) {
+				for (i = 0; moods[i].mood; ++i) {
 					/* verify that the mood is known (valid) */
-					if (!strcmp(moodinfo->name, moodstrings[i])) {
-						newmood = moodstrings[i];
+					if (!strcmp(moodinfo->name, moods[i].mood)) {
+						newmood = moods[i].mood;
 						break;
 					}
 				}
@@ -127,15 +151,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);
 }
@@ -147,7 +168,7 @@
 
 static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) {
 	JabberStream *js;
-	const int max_mood_idx = sizeof(moodstrings) / sizeof(moodstrings[0]) - 1;
+	const int max_mood_idx = sizeof(moods) / sizeof(moods[0]) - 1;
 	int selected_mood = purple_request_fields_get_choice(fields, "mood");
 
 	if (!PURPLE_CONNECTION_IS_VALID(gc)) {
@@ -162,7 +183,7 @@
 		return;
 	}
 
-	jabber_mood_set(js, moodstrings[selected_mood], purple_request_fields_get_string(fields, "text"));
+	jabber_mood_set(js, moods[selected_mood].mood, purple_request_fields_get_string(fields, "text"));
 }
 
 static void do_mood_set_mood(PurplePluginAction *action) {
@@ -180,8 +201,8 @@
 	field = purple_request_field_choice_new("mood",
 											_("Mood"), 0);
 	
-	for(i = 0; moodstrings[i]; ++i)
-		purple_request_field_choice_add(field, _(moodstrings[i]));
+	for(i = 0; moods[i].mood; ++i)
+		purple_request_field_choice_add(field, _(moods[i].description));
 	
 	purple_request_field_set_required(field, TRUE);
 	purple_request_field_group_add_field(group, field);
--- a/libpurple/protocols/jabber/xdata.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/jabber/xdata.c	Wed Nov 26 22:17:03 2008 +0000
@@ -302,7 +302,7 @@
 
 				data->values = g_slist_prepend(data->values, value);
 
-				purple_request_field_list_add(field, lbl, value);
+				purple_request_field_list_add_icon(field, lbl, NULL, value);
 				if(g_list_find_custom(selected, value, (GCompareFunc)strcmp))
 					purple_request_field_list_add_selected(field, lbl);
 			}
--- a/libpurple/protocols/oscar/family_buddy.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/family_buddy.c	Wed Nov 26 22:17:03 2008 +0000
@@ -224,6 +224,18 @@
 	if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING && userinfo.flags & AIM_FLAG_AWAY)
 		aim_locate_autofetch_away_message(od, userinfo.sn);
 
+	if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING &&
+	    userinfo.capabilities & OSCAR_CAPABILITY_XTRAZ) {
+		PurpleAccount *account = purple_connection_get_account(od->gc);
+		PurpleBuddy *buddy = purple_find_buddy(account, userinfo.sn);
+
+		if (buddy) {
+			PurplePresence *presence = purple_buddy_get_presence(buddy);
+
+			if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+				icq_im_xstatus_request(od, userinfo.sn);
+		}
+	}
 	aim_info_free(&userinfo);
 
 	return ret;
--- a/libpurple/protocols/oscar/family_icbm.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Wed Nov 26 22:17:03 2008 +0000
@@ -2533,6 +2533,15 @@
 	char *sn;
 	guchar *cookie;
 	guint8 snlen;
+	char *xml = NULL;
+	int hdrlen;
+	int curpos;
+	int num1,num2;
+	char *desc, *title, *temp;
+	PurpleAccount *account;
+	PurpleBuddy *buddy;
+	PurplePresence *presence;
+	PurpleStatus *status;
 
 	cookie = byte_stream_getraw(bs, 8);
 	channel = byte_stream_get16(bs);
@@ -2540,16 +2549,56 @@
 	sn = byte_stream_getstr(bs, snlen);
 	reason = byte_stream_get16(bs);
 
-	if (channel == 0x0002)
-	{
-		if (reason == 0x0003) /* channel-specific */
-			/* parse status note text */
-			parse_status_note_text(od, cookie, sn, bs);
-
-		byte_stream_get16(bs); /* Unknown */
-		byte_stream_get16(bs); /* Unknown */
-		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-			ret = userfunc(od, conn, frame, channel, sn, reason, cookie);
+	if (channel == 0x0002) {
+
+	 	hdrlen = byte_stream_getle16(bs);
+	 	if ( ((hdrlen == 27 ) && (bs->len > (27 + 51)))) {
+	 		byte_stream_advance(bs, 51);
+	 		num1 = byte_stream_getle16(bs); 
+	 		num2 = byte_stream_getle16(bs);
+	 		purple_debug_misc("oscar", "X-Status: Num1 %i, num2 %i\n",num1, num2);
+	 		
+	 		if(((num1 == 0x4f00)&&(num2 == 0x3b00))) {
+		 		byte_stream_advance(bs, 86);	
+		 		curpos = byte_stream_curpos(bs);
+		 		xml = byte_stream_getstr(bs, bs->len - curpos);
+		 		purple_debug_misc("oscar", "X-Status: Received XML reply\n");
+		 		if(xml) {
+ 				/* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", (const char*) xml); */
+ 					if ((desc=strstr(xml,"&lt;desc&gt;")) != NULL) {
+ 						temp=strstr(xml,"&lt;/desc&gt;");
+ 						temp[0]=0;
+ 						desc=desc+12;
+ 					}
+ 					if ((title=strstr(xml,"&lt;title&gt;")) != NULL) {
+ 						temp=strstr(xml,"&lt;/title&gt;");
+ 						temp[0]=0;
+ 						title=title+13;
+ 					} else {
+ 						title="";
+ 					}
+ 					strcpy(xml,title);
+					if (desc) {
+ 						strcat(xml, " - ");
+ 						strcat(xml, desc);
+					}
+ 					purple_debug_misc("oscar", "X-Status reply: %s\n", (const char*)xml);
+ 					account = purple_connection_get_account(od->gc);
+ 					buddy = purple_find_buddy(account, sn);
+ 					presence = purple_buddy_get_presence(buddy);
+ 					status = purple_presence_get_active_status(presence);
+ 					purple_prpl_got_user_status(account, sn,
+  					    purple_status_get_id(status), "message", xml, NULL);
+		   		} else {
+			 		purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n");
+				}
+	 		} else {
+		 		purple_debug_misc("oscar", "X-Status: 0x0004, 0x000b not an xstatus reply\n" );
+		 /*		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+		 		ret = userfunc(od, conn, frame, channel, sn, reason); */
+			}
+		
+	 	}
 
 	} else if (channel == 0x0004) { /* ICQ message */
 		switch (reason) {
@@ -2608,6 +2657,7 @@
 
 	g_free(cookie);
 	g_free(sn);
+	if (xml) g_free(xml);
 
 	return ret;
 }
@@ -2721,6 +2771,181 @@
 }
 
 /*
+ * Subtype 0x0006 - Send eXtra Status request
+ */
+int icq_im_xstatus_request(OscarData *od, const char *sn)
+{
+	FlapConnection *conn;
+	aim_snacid_t snacid;
+	guchar cookie[8];
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+	ByteStream bs, header, plugindata;
+	PurpleAccount *account;
+	const char *fmt;
+	char *statxml;
+	int xmllen;
+
+	static const guint8 pluginid[] = 
+	{
+	0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1, 
+	0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+	};
+	
+	static const guint8 c_plugindata[] =
+	{
+	0x1B, 0x00, 0x0A,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00,
+	0x01, 0x00, 0x00, 0x4F, 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0, 0x9C,
+	0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x53, 0x63, 0x72, 0x69, 0x70,
+	0x74, 0x20, 0x50, 0x6C, 0x75, 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
+	0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
+	0x72, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00
+	};
+	
+	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+		return -EINVAL;
+
+	if (!sn)
+		return -EINVAL;
+
+	fmt =  "<N><QUERY>&lt;Q&gt;&lt;PluginID&gt;srvMng&lt;/PluginID&gt;&lt;/Q&gt;</QUERY><NOTIFY>&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;req&gt;&lt;id&gt;AwayStat&lt;/id&gt;&lt;trans&gt;2&lt;/trans&gt;&lt;senderId&gt;%s&lt;/senderId&gt;&lt;/req&gt;&lt;/srv&gt;</NOTIFY></N>\r\n";	
+
+	account = purple_connection_get_account(od->gc);
+	xmllen = strlen(fmt) - 2 + strlen(account->username);
+
+	statxml = (char*) g_malloc(xmllen);
+	snprintf(statxml, xmllen, fmt, account->username);
+
+	aim_icbm_makecookie(cookie);
+
+	byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2
+					  + 2 + 2 + 8 + 16 + 2 + 2 + 2 + 2 + 2
+					  + 2 + 2 + sizeof(c_plugindata) + xmllen
+					  + 2 + 2);
+ 
+	snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+	aim_im_puticbm(&bs, cookie, 0x0002, sn);
+
+	byte_stream_new(&header, (7*2) + 16 + 8 + 2 + sizeof(c_plugindata) + xmllen); /* TLV 0x0005 Stream + Size */
+	byte_stream_new(&plugindata, (sizeof(c_plugindata) + xmllen));
+
+	byte_stream_put16(&header, 0x0000); /* Message Type: Request */
+	byte_stream_putraw(&header, cookie, sizeof(cookie)); /* Message ID */
+	byte_stream_putraw(&header, pluginid, sizeof(pluginid)); /* Plugin ID */
+	
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	
+	/* Add Plugin Specific Data */
+	byte_stream_putraw(&plugindata, c_plugindata, sizeof(c_plugindata)); /* Content of TLV 0x2711 */
+	byte_stream_putstr(&plugindata, statxml);
+
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, (sizeof(c_plugindata) + xmllen), plugindata.data);
+	
+	aim_tlvlist_write(&header, &inner_tlvlist);
+	
+	
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&header), header.data);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);		/* Empty TLV 0x0003 */
+	
+	aim_tlvlist_write(&bs, &outer_tlvlist);
+	
+	purple_debug_misc("oscar", "X-Status Request\n");
+	flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, 0x0000, snacid, &bs, TRUE);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
+	byte_stream_destroy(&header);
+	byte_stream_destroy(&plugindata);
+	byte_stream_destroy(&bs);
+	g_free(statxml);
+
+	return 0;
+}
+
+int icq_relay_xstatus(OscarData *od, const char *sn, const guchar *cookie)
+{
+	FlapConnection *conn;
+	ByteStream bs;
+	aim_snacid_t snacid;
+	PurpleAccount *account;
+	PurpleStatus *status;
+   const char *fmt;
+   const char *formatted_msg;
+   char *msg;
+   char *statxml;
+	const char *title;
+	int len;
+	
+	static const guint8 plugindata[] = {
+	0x1B, 0x00,
+	0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+	0x01, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4F, 
+	0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0, 
+	0x9C, 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00, 
+	0x00, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x50, 0x6C, 0x75, 
+	0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74, 
+	0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+	0x69, 0x6F, 0x6E, 0x20, 0x41, 0x72, 0x72, 0x69, 0x76, 0x65, 0x00,
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0xF3, 0x01, 0x00, 0x00, 0xEF, 0x01, 0x00, 0x00
+	};	
+
+	fmt = "<NR><RES>&lt;ret event='OnRemoteNotification'&gt;&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;val srv_id='cAwaySrv'&gt;&lt;Root&gt;&lt;CASXtraSetAwayMessage&gt;&lt;/CASXtraSetAwayMessage&gt;&l t;uin&gt;%s&lt;/uin&gt;&lt;index&gt;1&lt;/index&gt;&lt;title&gt;%s&lt;/title&gt;&lt;desc&gt;%s&lt;/desc&gt;&lt;/Root&gt;&lt;/val&gt;&lt;/srv&gt;&lt;srv&gt;&lt;id&gt;cRandomizerSrv&lt;/id&gt;&lt;val srv_id='cRandomizerSrv'&gt;undefined&lt;/val&gt;&lt;/srv&gt;&lt;/ret&gt;</RES></NR>\r\n";
+	
+	
+	if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
+		return -EINVAL;
+
+	if (!sn)
+		return -EINVAL;
+		
+	account = purple_connection_get_account(od->gc);
+	if(!account) return -EINVAL;
+	
+/*	if (!strcmp(account->username, sn))
+		icq_im_xstatus_request(od, sn); */
+	
+	status  = purple_presence_get_active_status(account->presence);
+	if (!status) return -EINVAL;
+   title = purple_status_get_name(status);
+   if (!title) return -EINVAL;
+	formatted_msg = purple_status_get_attr_string(status, "message");
+	if (!formatted_msg) return -EINVAL;
+   msg = purple_markup_strip_html(formatted_msg);
+	if (!msg) return -EINVAL;
+	len = strlen(fmt)-6+strlen(account->username)+strlen(title)+strlen(msg);
+	statxml = (char*) g_malloc(len);
+
+	snprintf(statxml, len, fmt, 
+		account->username, title, msg);
+
+	purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg);
+
+	byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2 + sizeof(plugindata) + strlen(statxml)); /* 16 extra */
+
+	snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0);
+	aim_im_puticbm(&bs, cookie, 0x0002, sn);
+	byte_stream_put16(&bs, 0x0003);
+	byte_stream_putraw(&bs, plugindata, sizeof(plugindata));
+	byte_stream_putraw(&bs, (const guint8*)statxml, strlen(statxml));
+	
+	flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x000b, 0x0000, snacid, &bs, TRUE);
+
+	g_free(statxml);
+	g_free(msg);
+	byte_stream_destroy(&bs);
+
+	return 0;
+}
+
+/*
  * Subtype 0x0014 - Receive a mini typing notification (mtn) packet.
  *
  * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
--- a/libpurple/protocols/oscar/family_locate.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Wed Nov 26 22:17:03 2008 +0000
@@ -166,6 +166,16 @@
 	 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
 
+	/* New format of caps (xtraz icons) */
+	{OSCAR_CAPABILITY_NEWCAPS,
+	 {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
+	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+
+	/* Support xtraz statuses */
+	{OSCAR_CAPABILITY_XTRAZ,
+	 {0x1a, 0x09, 0x3c, 0x6c, 0xd7, 0xFD, 0x4e, 0xc5, 
+	  0x9d, 0x51, 0xa6, 0x47, 0x4e, 0x34, 0xf5, 0xa0}},
+
 	{OSCAR_CAPABILITY_SENDBUDDYLIST,
 	 {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
 	  0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
@@ -242,6 +252,202 @@
 	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
 };
 
+/* Keep this array synchronized with icq_purple_moods. */
+static const struct {
+	const char *mood;
+	guint8 data[16];
+} icq_custom_icons[] = {
+
+	{"thinking",
+	 {0x3f, 0xb0, 0xbd, 0x36, 0xaf, 0x3b, 0x4a, 0x60,
+	  0x9e, 0xef, 0xcf, 0x19, 0x0f, 0x6a, 0x5a, 0x7f}},
+
+	{"busy",
+	 {0x48, 0x8e, 0x14, 0x89, 0x8a, 0xca, 0x4a, 0x08,
+	  0x82, 0xaa, 0x77, 0xce, 0x7a, 0x16, 0x52, 0x08}},
+
+	{"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",
+	 {0x63, 0x4f, 0x6b, 0xd8 ,0xad, 0xd2, 0x4a, 0xa1,
+	  0xaa, 0xb9, 0x11, 0x5b, 0xc2, 0x6d, 0x05, 0xa1}},
+
+	{"question",
+	 {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0,
+	  0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64}},
+
+	{"angry",
+	 {0x01, 0xd8, 0xd7, 0xee, 0xac, 0x3b, 0x49, 0x2a,
+	  0xa5, 0x8d, 0xd3, 0xd8, 0x77, 0xe6, 0x6b, 0x92}},
+
+	{"plate",
+	 {0xf8, 0xe8, 0xd7, 0xb2, 0x82, 0xc4, 0x41, 0x42,
+	  0x90, 0xf8, 0x10, 0xc6, 0xce, 0x0a, 0x89, 0xa6}},
+
+	{"cinema",
+	 {0x10, 0x7a, 0x9a, 0x18, 0x12, 0x32, 0x4d, 0xa4,
+	  0xb6, 0xcd, 0x08, 0x79, 0xdb, 0x78, 0x0f, 0x09}},
+
+	{"sick",
+	 {0x1f, 0x7a, 0x40, 0x71, 0xbf, 0x3b, 0x4e, 0x60,
+	  0xbc, 0x32, 0x4c, 0x57, 0x87, 0xb0, 0x4c, 0xf1}},
+
+	{"typing",
+	 {0x2c, 0xe0, 0xe4, 0xe5, 0x7c, 0x64, 0x43, 0x70,
+	  0x9c, 0x3a, 0x7a, 0x1c, 0xe8, 0x78, 0xa7, 0xdc}},
+
+	{"suit",
+	 {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27,
+	  0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97}},
+
+	{"bathing",
+	 {0x5a, 0x58, 0x1e, 0xa1, 0xe5, 0x80, 0x43, 0x0c,
+	  0xa0, 0x6f, 0x61, 0x22, 0x98, 0xb7, 0xe4, 0xc7}},
+
+	{"tv",
+	 {0x80, 0x53, 0x7d, 0xe2, 0xa4, 0x67, 0x4a, 0x76,
+	  0xb3, 0x54, 0x6d, 0xfd, 0x07, 0x5f, 0x5e, 0xc6}},
+
+	{"excited",
+	 {0x6f, 0x49, 0x30, 0x98, 0x4f, 0x7c, 0x4a, 0xff,
+	  0xa2, 0x76, 0x34, 0xa0, 0x3b, 0xce, 0xae, 0xa7}},
+
+	{"sleeping",
+	 {0x78, 0x5e, 0x8c, 0x48, 0x40, 0xd3, 0x4c, 0x65,
+	  0x88, 0x6f, 0x04, 0xcf, 0x3f, 0x3f, 0x43, 0xdf}},
+
+	{"hiptop",
+	 {0x10, 0x11, 0x17, 0xc9, 0xa3, 0xb0, 0x40, 0xf9,
+	  0x81, 0xac, 0x49, 0xe1, 0x59, 0xfb, 0xd5, 0xd4}},
+
+	{"in_love",
+	 {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48,
+	  0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80}},
+
+	{"sleepy",
+	 {0x83, 0xc9, 0xb7, 0x8e, 0x77, 0xe7, 0x43, 0x78,
+	  0xb2, 0xc5, 0xfb, 0x6c, 0xfc, 0xc3, 0x5b, 0xec}},
+
+	{"meeting",
+	 {0xf1, 0x8a, 0xb5, 0x2e, 0xdc, 0x57, 0x49, 0x1d,
+	  0x99, 0xdc, 0x64, 0x44, 0x50, 0x24, 0x57, 0xaf}},
+
+	{"phone",
+	 {0x12, 0x92, 0xe5, 0x50, 0x1b, 0x64, 0x4f, 0x66,
+	  0xb2, 0x06, 0xb2, 0x9a, 0xf3, 0x78, 0xe4, 0x8d}},
+
+	{"surfing",
+	 {0xa6, 0xed, 0x55, 0x7e, 0x6b, 0xf7, 0x44, 0xd4,
+	  0xa5, 0xd4, 0xd2, 0xe7, 0xd9, 0x5c, 0xe8, 0x1f}},
+
+	{"mobile",
+	 {0x16, 0x0c, 0x60, 0xbb, 0xdd, 0x44, 0x43, 0xf3,
+	  0x91, 0x40, 0x05, 0x0f, 0x00, 0xe6, 0xc0, 0x09}},
+
+	{"search",
+	 {0xd4, 0xe2, 0xb0, 0xba, 0x33, 0x4e, 0x4f, 0xa5,
+	  0x98, 0xd0, 0x11, 0x7d, 0xbf, 0x4d, 0x3c, 0xc8}},
+
+	{"party",
+	 {0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1,
+	  0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x81}},
+
+	{"coffee",
+	 {0x1b, 0x78, 0xae, 0x31, 0xfa, 0x0b, 0x4d, 0x38,
+	  0x93, 0xd1, 0x99, 0x7e, 0xee, 0xaf, 0xb2, 0x18}},
+
+	{"console",
+	 {0xd4, 0xa6, 0x11, 0xd0, 0x8f, 0x01, 0x4e, 0xc0,
+	  0x92, 0x23, 0xc5, 0xb6, 0xbe, 0xc6, 0xcc, 0xf0}},
+
+	{"internet",
+	 {0x12, 0xd0, 0x7e, 0x3e, 0xf8, 0x85, 0x48, 0x9e,
+	  0x8e, 0x97, 0xa7, 0x2a, 0x65, 0x51, 0xe5, 0x8d}},
+
+	{"cigarette",
+	 {0x64, 0x43, 0xc6, 0xaf, 0x22, 0x60, 0x45, 0x17,
+	  0xb5, 0x8c, 0xd7, 0xdf, 0x8e, 0x29, 0x03, 0x52}},
+
+	{"writing",
+	 {0x00, 0x72, 0xd9, 0x08, 0x4a, 0xd1, 0x43, 0xdd,
+	  0x91, 0x99, 0x6f, 0x02, 0x69, 0x66, 0x02, 0x6f}},
+
+	{"beer",
+	 {0x8c, 0x50, 0xdb, 0xae, 0x81, 0xed, 0x47, 0x86,
+	  0xac, 0xca, 0x16, 0xcc, 0x32, 0x13, 0xc7, 0xb7}},
+
+	{"music",
+	 {0x61, 0xbe, 0xe0, 0xdd, 0x8b, 0xdd, 0x47, 0x5d,
+	  0x8d, 0xee, 0x5f, 0x4b, 0xaa, 0xcf, 0x19, 0xa7}},
+
+	{"studying",
+	 {0x60, 0x9d, 0x52, 0xf8, 0xa2, 0x9a, 0x49, 0xa6,
+	  0xb2, 0xa0, 0x25, 0x24, 0xc5, 0xe9, 0xd2, 0x60}},
+
+	{"working",
+	 {0xba, 0x74, 0xdb, 0x3e, 0x9e, 0x24, 0x43, 0x4b,
+	  0x87, 0xb6, 0x2f, 0x6b, 0x8d, 0xfe, 0xe5, 0x0f}},
+
+	{"restroom",
+	 {0x16, 0xf5, 0xb7, 0x6f, 0xa9, 0xd2, 0x40, 0x35,
+	  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.
@@ -278,6 +484,7 @@
 		cur->sessionlen = userinfo->sessionlen;
 	if (userinfo->capabilities != 0)
 		cur->capabilities = userinfo->capabilities;
+
 	cur->present |= userinfo->present;
 
 	if (userinfo->iconcsumlen > 0) {
@@ -469,13 +676,38 @@
 					cap[8], cap[9],
 					cap[10], cap[11], cap[12], cap[13],
 					cap[14], cap[15]);
-
 		g_free(cap);
 	}
 
 	return flags;
 }
 
+static const char *
+aim_receive_custom_icon(OscarData *od, ByteStream *bs, int len)
+{
+	int offset;
+	const char *result = NULL;
+
+	for (offset = 0; byte_stream_empty(bs) && (offset < len); offset += 0x10) {
+		/* check wheather this capability is a custom user icon */
+		guint8 *cap;
+		int i;
+
+		cap = byte_stream_getraw(bs, 0x10);
+
+		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... */
+			}
+		}
+		g_free(cap);
+	}
+
+	return result;
+}
+
 guint32
 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len)
 {
@@ -566,6 +798,38 @@
 	g_free(info->away_encoding);
 }
 
+static const struct {
+	char *icqmood;
+	const char *mood;
+} icqmoods[] = {
+	{"icqmood0",  "shopping"},
+	{"icqmood1",  "bathing"},
+	{"icqmood2",  "sleepy"},
+	{"icqmood3",  "party"},
+	{"icqmood4",  "beer"},
+	{"icqmood5",  "thinking"},
+	{"icqmood6",  "plate"},
+	{"icqmood7",  "tv"},
+	{"icqmood8",  "meeting"},
+	{"icqmood9",  "coffee"},
+	{"icqmood10", "music"},
+	{"icqmood11", "suit"},
+	{"icqmood12", "cinema"},
+	{"icqmood13", "smile-big"},
+	{"icqmood14", "phone"},
+	{"icqmood15", "console"},
+	{"icqmood16", "studying"},
+	{"icqmood17", "sick"},
+	{"icqmood18", "sleeping"},
+	{"icqmood19", "surfing"},
+	{"icqmood20", "internet"},
+	{"icqmood21", "working"},
+	{"icqmood22", "typing"},
+	{"icqmood23", "angry"},
+	{NULL, 0}
+
+};
+
 /*
  * AIM is fairly regular about providing user info.  This is a generic
  * routine to extract it in its standard form.
@@ -606,11 +870,12 @@
 	for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
 		guint16 type, length;
 		int endpos;
+		int curpos;
 
 		type = byte_stream_get16(bs);
 		length = byte_stream_get16(bs);
-
-		endpos = byte_stream_curpos(bs) + MIN(length, byte_stream_empty(bs));
+		curpos = byte_stream_curpos(bs);
+		endpos = curpos + MIN(length, byte_stream_empty(bs));
 
 		if (type == 0x0001) {
 			/*
@@ -720,11 +985,23 @@
 			outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA;
 
 		} else if (type == 0x000d) {
+			PurpleAccount *account = purple_connection_get_account(od->gc);
+			const char *mood;
+
 			/*
 			 * OSCAR Capability information
 			 */
 			outinfo->capabilities |= aim_locate_getcaps(od, bs, length);
 			outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
+			byte_stream_setpos(bs, curpos);
+
+			mood = aim_receive_custom_icon(od, bs, length);
+			if (mood)
+				purple_prpl_got_user_status(account, outinfo->sn, "mood",
+						PURPLE_MOOD_NAME, mood,
+						NULL);
+			else
+				purple_prpl_got_user_status_deactive(account, outinfo->sn, "mood");
 
 		} else if (type == 0x000e) {
 			/*
@@ -853,6 +1130,37 @@
 							outinfo->itmsurl_encoding = NULL;
 						}
 					} break;
+
+					case 0x000e: { /* ICQ mood */
+						PurpleAccount *account = purple_connection_get_account(od->gc);
+						char *icqmood;
+						gint32 i;
+						const char *mood = NULL;
+
+						icqmood = byte_stream_getstr(bs, length2);
+
+						/* icqmood = "" means X-Status
+						 * with no mood icon. */
+						if (*icqmood) {
+							for (i = 0; icqmoods[i].icqmood; i++) {
+								if (!strcmp(icqmood, icqmoods[i].icqmood)) {
+									mood = icqmoods[i].mood;
+									break; /* should only match once... */
+								}
+							}
+
+							if (!mood)
+								purple_debug_warning("oscar", "Unknown icqmood: %s\n", icqmood);
+						}
+						g_free(icqmood);
+
+						if (mood)
+							purple_prpl_got_user_status(account, outinfo->sn, "mood",
+									PURPLE_MOOD_NAME, mood,
+									NULL);
+						else
+							purple_prpl_got_user_status_deactive(account, outinfo->sn, "mood");
+					} break;
 				}
 
 				/* Save ourselves. */
@@ -897,6 +1205,10 @@
 	return 0;
 }
 
+/* Apparently, this is never called.
+ * If you activate it, figure out a way to know what mood to pass to
+ * aim_tlvlist_add_caps() below. --rlaager */
+#if 0
 /*
  * Inverse of aim_info_extract()
  */
@@ -932,8 +1244,9 @@
 	}
 #endif
 
-	if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES)
-		aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities);
+	if (info->present & AIM_USERINFO_PRESENT_CAPABILITIES) {
+		aim_tlvlist_add_caps(&tlvlist, 0x000d, info->capabilities, NULL);
+	}
 
 	if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
 		aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen);
@@ -944,6 +1257,7 @@
 
 	return 0;
 }
+#endif
 
 /*
  * Subtype 0x0001
@@ -1133,6 +1447,10 @@
 aim_locate_setcaps(OscarData *od, guint32 caps)
 {
 	FlapConnection *conn;
+	PurpleAccount *account = purple_connection_get_account(od->gc);
+	PurplePresence *presence = purple_account_get_presence(account);
+	PurpleStatus *status = purple_presence_get_status(presence, "mood");
+	const char *mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
 	ByteStream bs;
 	aim_snacid_t snacid;
 	GSList *tlvlist = NULL;
@@ -1140,7 +1458,7 @@
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
-	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);
+	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps, mood);
 
 	byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
 
@@ -1224,9 +1542,21 @@
 	/* Caps will be 5 */
 	if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
 		ByteStream cbs;
+		PurpleAccount *account = purple_connection_get_account(od->gc);
+		const char *mood;
+
 		byte_stream_init(&cbs, tlv->value, tlv->length);
 		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
+		byte_stream_rewind(&cbs);
 		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
+
+		mood = aim_receive_custom_icon(od, &cbs, tlv->length);
+		if (mood)
+			purple_prpl_got_user_status(account, userinfo->sn, "mood",
+					PURPLE_MOOD_NAME, mood,
+					NULL);
+		else
+			purple_prpl_got_user_status_deactive(account, userinfo->sn, "mood");
 	}
 	aim_tlvlist_free(tlvlist);
 
@@ -1453,3 +1783,57 @@
 
 	return 0;
 }
+
+#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.mood;
+}
+#endif
+
+const char*
+icq_get_custom_icon_description(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 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	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/libicq.c	Wed Nov 26 22:17:03 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	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Wed Nov 26 22:17:03 2008 +0000
@@ -59,6 +59,11 @@
 #define OSCAR_STATUS_ID_NA          "na"
 #define OSCAR_STATUS_ID_OCCUPIED    "occupied"
 #define OSCAR_STATUS_ID_FREE4CHAT   "free4chat"
+#define OSCAR_STATUS_ID_EVIL        "evil"
+#define OSCAR_STATUS_ID_DEPRESSION	 "depression"
+#define OSCAR_STATUS_ID_ATHOME      "athome"
+#define OSCAR_STATUS_ID_ATWORK      "atwork"
+#define OSCAR_STATUS_ID_LUNCH       "lunch"
 #define OSCAR_STATUS_ID_CUSTOM      "custom"
 #define OSCAR_STATUS_ID_MOBILE	    "mobile"
 
@@ -68,7 +73,7 @@
 
 static OscarCapability purple_caps = (OSCAR_CAPABILITY_CHAT | OSCAR_CAPABILITY_BUDDYICON | OSCAR_CAPABILITY_DIRECTIM |
 									  OSCAR_CAPABILITY_SENDFILE | OSCAR_CAPABILITY_UNICODE | OSCAR_CAPABILITY_INTEROPERATE |
-									  OSCAR_CAPABILITY_SHORTCAPS);
+									  OSCAR_CAPABILITY_SHORTCAPS |  OSCAR_CAPABILITY_ICQSERVERRELAY | OSCAR_CAPABILITY_NEWCAPS | OSCAR_CAPABILITY_XTRAZ);
 
 static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
 static guint8 features_icq[] = {0x01, 0x06};
@@ -670,6 +675,9 @@
 			case OSCAR_CAPABILITY_GAMES:
 			case OSCAR_CAPABILITY_GAMES2:
 				tmp = _("Games");
+			case OSCAR_CAPABILITY_XTRAZ:
+			case OSCAR_CAPABILITY_NEWCAPS:
+				tmp = _("ICQ Xtraz");
 				break;
 			case OSCAR_CAPABILITY_ADDINS:
 				tmp = _("Add-Ins");
@@ -750,9 +758,17 @@
 		return g_strdup_printf(_("Away"));
 	else if (state & AIM_ICQ_STATE_WEBAWARE)
 		return g_strdup_printf(_("Web Aware"));
-	else if (state & AIM_ICQ_STATE_INVISIBLE)
-		return g_strdup_printf(_("Invisible"));
-	else
+	else if (state & AIM_ICQ_STATE_EVIL)
+		return g_strdup_printf(_("Evil"));
+	else if (state & AIM_ICQ_STATE_DEPRESSION)
+		return g_strdup_printf(_("Depression"));
+	else if (state & AIM_ICQ_STATE_ATHOME)
+		return g_strdup_printf(_("At home"));
+	else if (state & AIM_ICQ_STATE_ATWORK)
+		return g_strdup_printf(_("At work"));
+	else if (state & AIM_ICQ_STATE_LUNCH)
+		return g_strdup_printf(_("At lunch"));
+	else 
 		return g_strdup_printf(_("Online"));
 }
 
@@ -918,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);
 }
@@ -1984,6 +2010,16 @@
 			status_id = OSCAR_STATUS_ID_AWAY;
 		else if (type & AIM_ICQ_STATE_INVISIBLE)
 			status_id = OSCAR_STATUS_ID_INVISIBLE;
+		else if (type & AIM_ICQ_STATE_EVIL)
+			status_id = OSCAR_STATUS_ID_EVIL;
+		else if (type & AIM_ICQ_STATE_DEPRESSION)
+			status_id = OSCAR_STATUS_ID_DEPRESSION;
+		else if (type & AIM_ICQ_STATE_ATHOME)
+			status_id = OSCAR_STATUS_ID_ATHOME;
+		else if (type & AIM_ICQ_STATE_ATWORK)
+			status_id = OSCAR_STATUS_ID_ATWORK;
+		else if (type & AIM_ICQ_STATE_LUNCH)
+			status_id = OSCAR_STATUS_ID_LUNCH;
 		else
 			status_id = OSCAR_STATUS_ID_AVAILABLE;
 	} else {
@@ -2300,7 +2336,9 @@
 {
 	PurpleConnection *gc;
 	PurpleAccount *account;
+	PurpleMessageFlags flags = 0;
 	char *message = NULL;
+	char *rtfmsg = NULL;
 
 	g_return_val_if_fail(od != NULL, 0);
 	g_return_val_if_fail(od->gc != NULL, 0);
@@ -2330,6 +2368,21 @@
 		}
 	}
 
+
+	if (args->info.rtfmsg.rtfmsg != NULL)
+	{
+		if (args->encoding != NULL)
+		{
+			char *encoding = NULL;
+			encoding = oscar_encoding_extract(args->encoding);
+			rtfmsg = oscar_encoding_to_utf8(account, encoding, args->info.rtfmsg.rtfmsg,
+			                                 strlen(args->info.rtfmsg.rtfmsg));
+			g_free(encoding);
+		} else {
+			if (g_utf8_validate(args->info.rtfmsg.rtfmsg, strlen(args->info.rtfmsg.rtfmsg), NULL))
+				rtfmsg = g_strdup(args->info.rtfmsg.rtfmsg);
+		}
+	}
 	if (args->type & OSCAR_CAPABILITY_CHAT)
 	{
 		char *encoding, *utf8name, *tmp;
@@ -2415,10 +2468,28 @@
 
 	else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY)
 	{
-		purple_debug_error("oscar", "Got an ICQ Server Relay message of "
+		purple_debug_info("oscar", "Got an ICQ Server Relay message of "
 				"type %d\n", args->info.rtfmsg.msgtype);
-	}
-
+		purple_debug_info("oscar", "Sending X-Status Reply\n");
+
+		if(args->info.rtfmsg.msgtype == 26)
+		icq_relay_xstatus(od, userinfo->sn, args->cookie);
+		
+		if(args->info.rtfmsg.msgtype == 1)
+		{
+			if(rtfmsg)
+			{
+				serv_got_im(gc, userinfo->sn, rtfmsg, flags,
+				            time(NULL));
+			}
+			else
+			{
+				serv_got_im(gc, userinfo->sn,
+				            args->info.rtfmsg.rtfmsg, flags,
+				            time(NULL));
+			}
+		}
+	}
 	else
 	{
 		purple_debug_error("oscar", "Unknown request class %hu\n",
@@ -2820,7 +2891,6 @@
 			args = va_arg(ap, struct aim_incomingim_ch4_args *);
 			ret = incomingim_chan4(od, conn, userinfo, args, 0);
 		} break;
-
 		default: {
 			purple_debug_warning("oscar",
 					   "ICBM received on unsupported channel (channel "
@@ -2968,6 +3038,28 @@
 
 		} break;
 
+		case 0x0006: { /* Reply from an ICQ status message request */
+			char *statusmsg, **splitmsg;
+			PurpleNotifyUserInfo *user_info;
+
+			/* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
+			statusmsg = oscar_icqstatus(state);
+			splitmsg = g_strsplit(msg, "\r\n", 0);
+			
+			user_info = purple_notify_user_info_new();
+				
+			purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+			purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+			purple_notify_user_info_add_section_break(user_info);
+			purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+
+			g_free(statusmsg);
+			g_strfreev(splitmsg);
+
+			purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+			purple_notify_user_info_destroy(user_info);
+
+		} break;
 		default: {
 			purple_debug_warning("oscar",
 					   "Received an unknown client auto-response from %s.  "
@@ -4621,10 +4713,22 @@
 		data |= AIM_ICQ_STATE_CHAT;
 	else if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE))
 		data |= AIM_ICQ_STATE_INVISIBLE;
+	else if (!strcmp(status_id, OSCAR_STATUS_ID_EVIL))
+		data |= AIM_ICQ_STATE_EVIL;
+	else if (!strcmp(status_id, OSCAR_STATUS_ID_DEPRESSION))
+		data |= AIM_ICQ_STATE_DEPRESSION;
+	else if (!strcmp(status_id, OSCAR_STATUS_ID_ATWORK))
+		data |= AIM_ICQ_STATE_ATWORK;
+	else if (!strcmp(status_id, OSCAR_STATUS_ID_ATHOME))
+		data |= AIM_ICQ_STATE_ATHOME;
+	else if (!strcmp(status_id, OSCAR_STATUS_ID_LUNCH))
+		data |= AIM_ICQ_STATE_LUNCH;
 	else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM))
 		data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
 
+	
 	aim_srv_setextrainfo(od, TRUE, data, FALSE, NULL, NULL);
+	
 }
 
 static void
@@ -4771,6 +4875,13 @@
 	if (!purple_account_is_connected(account))
 		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) {
+		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);
 
@@ -5697,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))
@@ -5763,12 +5879,17 @@
 			return "admin";
 		if (userinfo->flags & AIM_FLAG_ACTIVEBUDDY)
 			return "bot";
-		if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
-			return "hiptop";
 		if (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)
 			return "secure";
 		if (userinfo->icqinfo.status & AIM_ICQ_STATE_BIRTHDAY)
 			return "birthday";
+
+		/* Make the mood icon override anything below this. */
+		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+			return NULL;
+
+		if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
+			return "hiptop";
 	}
 	return NULL;
 }
@@ -5990,9 +6111,53 @@
 										   purple_value_new(PURPLE_TYPE_STRING), NULL);
 	status_types = g_list_prepend(status_types, type);
 
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE,
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
 									 OSCAR_STATUS_ID_FREE4CHAT,
-									 _("Free For Chat"), TRUE, is_icq, FALSE);
+									 _("Free For Chat"), TRUE, is_icq, FALSE,
+									 "message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+
+	status_types = g_list_prepend(status_types, type);
+	
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+									 OSCAR_STATUS_ID_EVIL,
+									 _("Evil"), TRUE, is_icq, FALSE,
+				 "message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+	status_types = g_list_prepend(status_types, type);
+
+
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+									 OSCAR_STATUS_ID_DEPRESSION,
+									 _("Depression"), TRUE, is_icq, FALSE,
+				 "message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+	status_types = g_list_prepend(status_types, type);
+
+
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+									 OSCAR_STATUS_ID_ATHOME,
+									 _("At home"), TRUE, is_icq, FALSE,
+				"message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+	status_types = g_list_prepend(status_types, type);
+
+
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+									 OSCAR_STATUS_ID_ATWORK,
+									 _("At work"), TRUE, is_icq, FALSE,
+				"message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+
+	status_types = g_list_prepend(status_types, type);
+
+
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+									 OSCAR_STATUS_ID_LUNCH,
+									 _("Lunch"), TRUE, is_icq, FALSE,
+				"message", _("Message"),
+				purple_value_new(PURPLE_TYPE_STRING), NULL);
+
 	status_types = g_list_prepend(status_types, type);
 
 	type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
@@ -6002,9 +6167,12 @@
 										   purple_value_new(PURPLE_TYPE_STRING), NULL);
 	status_types = g_list_prepend(status_types, type);
 
-	type = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
 									 OSCAR_STATUS_ID_INVISIBLE,
-									 NULL, TRUE, TRUE, FALSE);
+									 NULL, TRUE, TRUE, FALSE,
+									 "message", _("Message"),
+									  purple_value_new(PURPLE_TYPE_STRING), NULL);
+
 	status_types = g_list_prepend(status_types, type);
 
 	type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, OSCAR_STATUS_ID_MOBILE, NULL, FALSE, FALSE, TRUE);
@@ -6037,9 +6205,14 @@
 									 NULL, TRUE, TRUE, FALSE);
 	status_types = g_list_prepend(status_types, type);
 
-	status_types = g_list_reverse(status_types);
-
-	return status_types;
+	type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD,
+			"mood", NULL, TRUE, is_icq, TRUE,
+			PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING),
+			PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING),
+			NULL);
+	status_types = g_list_prepend(status_types, type);
+
+	return g_list_reverse(status_types);
 }
 
 static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
@@ -6172,6 +6345,23 @@
 	aim_locate_getinfoshort(gc->proto_data, purple_buddy_get_name(buddy), 0x00000003);
 }
 
+static void oscar_get_icqxstatusmsg (PurpleBlistNode *node, gpointer ignore)
+{
+	PurpleBuddy *buddy;
+	PurpleConnection *gc;
+	PurpleAccount *account;
+	
+	
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	buddy = (PurpleBuddy *)node;
+	gc = purple_account_get_connection(buddy->account);
+	account = purple_connection_get_account(gc);
+	purple_debug_info("oscar",   "Manual X-Status Get From %s to %s:\n", purple_buddy_get_name(buddy), account->username);
+
+	icq_im_xstatus_request(gc->proto_data, purple_buddy_get_name(buddy));
+}
+
 static GList *
 oscar_buddy_menu(PurpleBuddy *buddy) {
 
@@ -6199,15 +6389,14 @@
 	                           NULL, NULL);
 	menu = g_list_prepend(menu, act);
 
-#if 0
 	if (od->icq)
 	{
-		act = purple_menu_action_new(_("Get Status Msg"),
-		                           PURPLE_CALLBACK(oscar_get_icqstatusmsg),
+		act = purple_menu_action_new(_("Get X-Status Msg"),
+		                           PURPLE_CALLBACK(oscar_get_icqxstatusmsg),
 		                           NULL, NULL);
 		menu = g_list_prepend(menu, act);
 	}
-#endif
+	
 
 	if (userinfo &&
 		aim_sncmp(purple_account_get_username(buddy->account), buddy->name) &&
--- a/libpurple/protocols/oscar/oscar.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Wed Nov 26 22:17:03 2008 +0000
@@ -362,8 +362,10 @@
 	OSCAR_CAPABILITY_LIVEVIDEO            = 0x02000000,
 	OSCAR_CAPABILITY_CAMERA               = 0x04000000,
 	OSCAR_CAPABILITY_ICHAT_SCREENSHARE    = 0x08000000,
-	OSCAR_CAPABILITY_GENERICUNKNOWN       = 0x10000000,
-	OSCAR_CAPABILITY_LAST                 = 0x20000000
+	OSCAR_CAPABILITY_NEWCAPS              = 0x10000000,
+	OSCAR_CAPABILITY_XTRAZ                = 0x20000000,
+	OSCAR_CAPABILITY_GENERICUNKNOWN       = 0x40000000,
+	OSCAR_CAPABILITY_LAST                 = 0x80000000
 } OscarCapability;
 
 /*
@@ -557,6 +559,12 @@
 #define AIM_ICQ_STATE_OUT               0x00000004
 #define AIM_ICQ_STATE_BUSY              0x00000010
 #define AIM_ICQ_STATE_CHAT              0x00000020
+#define AIM_ICQ_STATE_EVIL              0x00003000
+#define AIM_ICQ_STATE_DEPRESSION        0x00004000
+#define AIM_ICQ_STATE_ATHOME            0x00005000
+#define AIM_ICQ_STATE_ATWORK            0x00006000
+#define AIM_ICQ_STATE_LUNCH             0x00002001
+#define AIM_ICQ_STATE_EVIL              0x00003000
 #define AIM_ICQ_STATE_INVISIBLE         0x00000100
 #define AIM_ICQ_STATE_WEBAWARE          0x00010000
 #define AIM_ICQ_STATE_HIDEIP            0x00020000
@@ -966,6 +974,7 @@
 /* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *sn, const guchar *cookie, guint16 code);
 /* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
 /* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2);
+/* 0x000b */ int icq_relay_xstatus (OscarData *od, const char *sn, const guchar* cookie);
 void aim_icbm_makecookie(guchar* cookie);
 gchar *oscar_encoding_extract(const char *encoding);
 gchar *oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen);
@@ -1096,9 +1105,13 @@
 guint32 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len);
 void aim_info_free(aim_userinfo_t *);
 int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *);
+#if 0
 int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info);
-
-
+#endif
+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 */
 /* 0x0002 */ void aim_buddylist_reqrights(OscarData *, FlapConnection *);
@@ -1428,7 +1441,7 @@
 int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value);
 int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value);
 int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value);
-int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps);
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps, const char *mood);
 int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo);
 int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
 int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tl);
--- a/libpurple/protocols/oscar/oscarcommon.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/oscarcommon.h	Wed Nov 26 22:17:03 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	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/oscar/tlv.c	Wed Nov 26 22:17:03 2008 +0000
@@ -407,10 +407,11 @@
  * @param caps Bitfield of capability flags to send
  * @return The size of the value added.
  */
-int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps)
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps, const char *mood)
 {
 	guint8 buf[256]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
+	guint8 *data;
 
 	if (caps == 0)
 		return 0; /* nothing there anyway */
@@ -418,6 +419,11 @@
 	byte_stream_init(&bs, buf, sizeof(buf));
 
 	byte_stream_putcaps(&bs, caps);
+	
+	/* adding of custom icon GUID */
+	data = icq_get_custom_icon_data(mood);
+	if (data != NULL)
+		byte_stream_putraw(&bs, data, 16);
 
 	return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf);
 }
--- a/libpurple/protocols/sametime/sametime.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Wed Nov 26 22:17:03 2008 +0000
@@ -3505,10 +3505,10 @@
   purple_request_field_list_set_multi_select(f, FALSE);
   for(; confs; confs = confs->next) {
     struct mwConference *c = confs->data;
-    purple_request_field_list_add(f, mwConference_getTitle(c), c);
+    purple_request_field_list_add_icon(f, mwConference_getTitle(c), NULL, c);
   }
-  purple_request_field_list_add(f, _("Create New Conference..."),
-			      GINT_TO_POINTER(0x01));
+  purple_request_field_list_add_icon(f, _("Create New Conference..."),
+			      NULL, GINT_TO_POINTER(0x01));
   purple_request_field_group_add_field(g, f);
   
   f = purple_request_field_string_new(CHAT_KEY_INVITE, "Message", NULL, FALSE);
@@ -5434,7 +5434,7 @@
     res->id = g_strdup(match->id);
     res->name = g_strdup(match->name);
 
-    purple_request_field_list_add(f, res->name, res);
+    purple_request_field_list_add_icon(f, res->name, NULL, res);
   }
 
   purple_request_field_group_add_field(g, f);
--- a/libpurple/protocols/silc/buddy.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/silc/buddy.c	Wed Nov 26 22:17:03 2008 +0000
@@ -1178,7 +1178,7 @@
 			   client_entry->username, *client_entry->hostname ?
 			   client_entry->hostname : "",
 			   fingerprint ? tmp2 : "");
-		purple_request_field_list_add(f, tmp, client_entry);
+		purple_request_field_list_add_icon(f, tmp, NULL, client_entry);
 		silc_free(fingerprint);
 	}
 
--- a/libpurple/protocols/silc/chat.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/silc/chat.c	Wed Nov 26 22:17:03 2008 +0000
@@ -472,7 +472,7 @@
 		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
 			   ident->realname ? ident->realname : ident->username ?
 			   ident->username : "", fingerprint, babbleprint);
-		purple_request_field_list_add(f, tmp2, public_key);
+		purple_request_field_list_add_icon(f, tmp2, NULL, public_key);
 
 		silc_free(fingerprint);
 		silc_free(babbleprint);
--- a/libpurple/protocols/silc10/buddy.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Wed Nov 26 22:17:03 2008 +0000
@@ -1176,7 +1176,7 @@
 			   clients[i]->username, clients[i]->hostname ?
 			   clients[i]->hostname : "",
 			   fingerprint ? tmp2 : "");
-		purple_request_field_list_add(f, tmp, clients[i]);
+		purple_request_field_list_add_icon(f, tmp, NULL, clients[i]);
 		silc_free(fingerprint);
 	}
 
--- a/libpurple/protocols/silc10/chat.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/protocols/silc10/chat.c	Wed Nov 26 22:17:03 2008 +0000
@@ -449,7 +449,7 @@
 		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
 			   ident->realname ? ident->realname : ident->username ?
 			   ident->username : "", fingerprint, babbleprint);
-		purple_request_field_list_add(f, tmp2, pubkey);
+		purple_request_field_list_add_icon(f, tmp2, NULL, pubkey);
 
 		silc_free(fingerprint);
 		silc_free(babbleprint);
--- a/libpurple/prpl.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/prpl.h	Wed Nov 26 22:17:03 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/request.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/request.c	Wed Nov 26 22:17:03 2008 +0000
@@ -23,6 +23,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
+#define _PURPLE_REQUEST_C_
+
 #include "internal.h"
 
 #include "notify.h"
@@ -823,13 +825,40 @@
 purple_request_field_list_add(PurpleRequestField *field, const char *item,
 							void *data)
 {
+	purple_request_field_list_add_icon(field, item, NULL, data);
+}
+
+void
+purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path,
+							void *data)
+{
 	g_return_if_fail(field != NULL);
 	g_return_if_fail(item  != NULL);
 	g_return_if_fail(data  != NULL);
 	g_return_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST);
 
+	if (icon_path)
+	{
+		if (field->u.list.icons == NULL)
+		{
+			GList *l;
+			for (l = field->u.list.items ; l != NULL ; l = l->next)
+			{
+				/* Order doesn't matter, because we're just
+				 * filing in blank items.  So, we use
+				 * g_list_prepend() because it's faster. */
+				field->u.list.icons = g_list_prepend(field->u.list.icons, NULL);
+			}
+		}
+		field->u.list.icons = g_list_append(field->u.list.icons, g_strdup(icon_path));
+	}
+	else if (field->u.list.icons)
+	{
+		/* Keep this even with the items list. */
+		field->u.list.icons = g_list_append(field->u.list.icons, NULL);
+	}
+
 	field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
-
 	g_hash_table_insert(field->u.list.item_data, g_strdup(item), data);
 }
 
@@ -935,6 +964,15 @@
 	return field->u.list.items;
 }
 
+GList *
+purple_request_field_list_get_icons(const PurpleRequestField *field)
+{
+	g_return_val_if_fail(field != NULL, NULL);
+	g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_LIST, NULL);
+
+	return field->u.list.icons;
+}
+
 PurpleRequestField *
 purple_request_field_label_new(const char *id, const char *text)
 {
--- a/libpurple/request.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/request.h	Wed Nov 26 22:17:03 2008 +0000
@@ -146,6 +146,7 @@
 		struct
 		{
 			GList *items;
+			GList *icons;
 			GHashTable *item_data;
 			GList *selected;
 			GHashTable *selected_table;
@@ -907,15 +908,30 @@
 void *purple_request_field_list_get_data(const PurpleRequestField *field,
 									   const char *text);
 
+#if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_REQUEST_C_)
 /**
  * Adds an item to a list field.
  *
  * @param field The list field.
  * @param item  The list item.
  * @param data  The associated data.
+ *
+ * @deprecated Use purple_request_field_list_add_icon() instead.
  */
 void purple_request_field_list_add(PurpleRequestField *field,
 								 const char *item, void *data);
+#endif
+
+/**
+ * Adds an item to a list field.
+ *
+ * @param field The list field.
+ * @param item  The list item.
+ * @param icon_path The path to icon file, or @c NULL for no icon.
+ * @param data  The associated data.
+ */
+void purple_request_field_list_add_icon(PurpleRequestField *field,
+								 const char *item, const char* icon_path, void* data);
 
 /**
  * Adds a selected item to the list field.
@@ -975,6 +991,18 @@
  */
 GList *purple_request_field_list_get_items(const PurpleRequestField *field);
 
+/**
+ * Returns a list of icons in a list field.
+ *
+ * The icons will correspond with the items, in order.
+ *
+ * @param field The field.
+ *
+ * @constreturn The list of icons or @c NULL (i.e. the empty GList) if no
+ *              items have icons.
+ */
+GList *purple_request_field_list_get_icons(const PurpleRequestField *field);
+
 /*@}*/
 
 /**************************************************************************/
--- a/libpurple/status.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/status.c	Wed Nov 26 22:17:03 2008 +0000
@@ -135,6 +135,7 @@
 	-200,   /* extended away            */
 	-400,   /* mobile                   */
 	0,      /* tune                     */
+	0,      /* mood                     */
 	-10,    /* idle, special case.      */
 	-5,     /* idle time, special case. */
 	10      /* Offline messageable      */
@@ -155,15 +156,16 @@
 
 } const status_primitive_map[] =
 {
-	{ PURPLE_STATUS_UNSET,           "unset",           N_("Unset")           },
-	{ PURPLE_STATUS_OFFLINE,         "offline",         N_("Offline")         },
-	{ PURPLE_STATUS_AVAILABLE,       "available",       N_("Available")       },
-	{ PURPLE_STATUS_UNAVAILABLE,     "unavailable",     N_("Do not disturb")     },
-	{ PURPLE_STATUS_INVISIBLE,       "invisible",       N_("Invisible")       },
-	{ PURPLE_STATUS_AWAY,            "away",            N_("Away")            },
-	{ PURPLE_STATUS_EXTENDED_AWAY,   "extended_away",   N_("Extended away")   },
-	{ PURPLE_STATUS_MOBILE,          "mobile",          N_("Mobile")          },
-	{ PURPLE_STATUS_TUNE,            "tune",            N_("Listening to music") }
+	{ PURPLE_STATUS_UNSET,           "unset",           N_("Unset")               },
+	{ PURPLE_STATUS_OFFLINE,         "offline",         N_("Offline")             },
+	{ PURPLE_STATUS_AVAILABLE,       "available",       N_("Available")           },
+	{ PURPLE_STATUS_UNAVAILABLE,     "unavailable",     N_("Do not disturb")      },
+	{ PURPLE_STATUS_INVISIBLE,       "invisible",       N_("Invisible")           },
+	{ PURPLE_STATUS_AWAY,            "away",            N_("Away")                },
+	{ PURPLE_STATUS_EXTENDED_AWAY,   "extended_away",   N_("Extended away")       },
+	{ PURPLE_STATUS_MOBILE,          "mobile",          N_("Mobile")              },
+	{ PURPLE_STATUS_TUNE,            "tune",            N_("Listening to music"), },
+	{ PURPLE_STATUS_MOOD,            "mood",            N_("Feeling")             },
 };
 
 const char *
--- a/libpurple/status.h	Wed Nov 26 22:16:58 2008 +0000
+++ b/libpurple/status.h	Wed Nov 26 22:17:03 2008 +0000
@@ -50,8 +50,8 @@
  * your accounts are saved so that the next time you start Purple,
  * your accounts will be set to their last known statuses.  There
  * is also a list of saved statuses that are written to the
- * status.xml file.  Also, each PurpleStatus has a "savable" boolean.
- * If "savable" is set to FALSE then the status is NEVER saved.
+ * status.xml file.  Also, each PurpleStatus has a "saveable" boolean.
+ * If "saveable" is set to FALSE then the status is NEVER saved.
  * All PurpleStatuses should be inside a PurplePresence.
  *
  *
@@ -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.
  *
@@ -96,8 +102,7 @@
  */
 /*
  * If you add a value to this enum, make sure you update
- * the status_primitive_map array in status.c and the special-cases for idle
- * and offline-messagable just below it.
+ * the status_primitive_map and primitive_scores arrays in status.c.
  */
 typedef enum
 {
@@ -110,6 +115,7 @@
 	PURPLE_STATUS_EXTENDED_AWAY,
 	PURPLE_STATUS_MOBILE,
 	PURPLE_STATUS_TUNE,
+	PURPLE_STATUS_MOOD,
 	PURPLE_STATUS_NUM_PRIMITIVES
 } PurpleStatusPrimitive;
 
@@ -129,6 +135,9 @@
 #define PURPLE_TUNE_URL		"tune_url"
 #define PURPLE_TUNE_FULL	"tune_full"
 
+#define PURPLE_MOOD_NAME	"mood"
+#define PURPLE_MOOD_COMMENT	"moodtext"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -200,7 +209,7 @@
 
 /**
  * Creates a new status type with some default values (not
- * savable and not independent).
+ * saveable and not independent).
  *
  * @param primitive     The primitive status type.
  * @param id            The ID of the status type, or @c NULL to use the id of
--- a/pidgin/gtkblist.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/gtkblist.c	Wed Nov 26 22:17:03 2008 +0000
@@ -3625,7 +3625,7 @@
 	PurplePluginProtocolInfo *prpl_info;
 	const char *name = NULL;
 	char *filename, *path;
-	PurplePresence *p;
+	PurplePresence *presence = NULL;
 
 	if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
 		if(!gtknode->contact_expanded) {
@@ -3635,8 +3635,8 @@
 	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		buddy = (PurpleBuddy*)node;
 		gtkbuddynode = node->ui_data;
-		p = purple_buddy_get_presence(buddy);
-		if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
+		presence = purple_buddy_get_presence(buddy);
+		if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE)) {
 			path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems",
 						"16", "mobile.png", NULL);
 			return _pidgin_blist_get_cached_emblem(path);
@@ -3658,13 +3658,17 @@
 		return _pidgin_blist_get_cached_emblem(path);
 	}
 
-	p = purple_buddy_get_presence(buddy);
-	if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
+	/* If we came through the contact code flow above, we didn't need
+	 * to get the presence until now. */
+	if (presence == NULL)
+		presence = purple_buddy_get_presence(buddy);
+
+	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE)) {
 		path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "mobile.png", NULL);
 		return _pidgin_blist_get_cached_emblem(path);
 	}
 
-	if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) {
+	if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
 		path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL);
 		return _pidgin_blist_get_cached_emblem(path);
 	}
@@ -3677,8 +3681,18 @@
 	if (prpl_info && prpl_info->list_emblem)
 		name = prpl_info->list_emblem(buddy);
 
-	if (name == NULL)
-		return NULL;
+	if (name == NULL) {
+		PurpleStatus *status;
+
+		if (!purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+			return NULL;
+
+		status = purple_presence_get_status(presence, "mood");
+		name = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+		
+		if (!(name && *name))
+			return NULL;
+	}
 
 	filename = g_strdup_printf("%s.png", name);
 
@@ -7629,6 +7643,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)
 {
@@ -7702,6 +7805,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));
@@ -7740,10 +7845,34 @@
 			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;
+
+			if (plugin &&
+			    (prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin)) &&
+			    PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods))
+			{
+				for (types = purple_account_get_status_types(account);
+				     types != NULL ; types = types->next)
+				{
+					PurpleStatusType *type = types->data;
+
+					if (strcmp(purple_status_type_get_id(type), "mood") != 0)
+						continue;
+
+					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 {
--- a/pidgin/gtkrequest.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/gtkrequest.c	Wed Nov 26 22:17:03 2008 +0000
@@ -996,6 +996,9 @@
 	GtkTreeViewColumn *column;
 	GtkTreeIter iter;
 	GList *l;
+	GList *icons = NULL;
+
+	icons = purple_request_field_list_get_icons(field);
 
 	/* Create the scrolled window */
 	sw = gtk_scrolled_window_new(NULL, NULL);
@@ -1007,7 +1010,10 @@
 	gtk_widget_show(sw);
 
 	/* Create the list store */
-	store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING);
+	if (icons)
+		store = gtk_list_store_new(3, G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+	else
+		store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING);
 
 	/* Create the tree view */
 	treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
@@ -1026,13 +1032,43 @@
 	gtk_tree_view_column_pack_start(column, renderer, TRUE);
 	gtk_tree_view_column_add_attribute(column, renderer, "text", 1);
 
+	if (icons)
+	{
+		renderer = gtk_cell_renderer_pixbuf_new();
+		gtk_tree_view_column_pack_start(column, renderer, TRUE);
+		gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 2);
+
+		gtk_widget_set_size_request(treeview, 200, 400);
+	}
+
 	for (l = purple_request_field_list_get_items(field); l != NULL; l = l->next)
 	{
 		const char *text = (const char *)l->data;
 
 		gtk_list_store_append(store, &iter);
 
-		gtk_list_store_set(store, &iter,
+		if (icons)
+		{
+			const char *icon_path = (const char *)icons->data;
+			char* filename;
+			GdkPixbuf* pixbuf = NULL;
+
+			if (icon_path)
+			{
+				filename = g_build_filename(DATADIR, icon_path, NULL);
+				pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+				g_free(filename);
+			}
+
+			gtk_list_store_set(store, &iter,
+						   0, purple_request_field_list_get_data(field, text),
+						   1, text,
+						   2, pixbuf,
+						   -1);
+			icons = icons->next;
+		}
+		else
+			gtk_list_store_set(store, &iter,
 						   0, purple_request_field_list_get_data(field, text),
 						   1, text,
 						   -1);
--- a/pidgin/gtksavedstatuses.c	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Wed Nov 26 22:17:03 2008 +0000
@@ -921,7 +921,14 @@
 
 	for (i = PURPLE_STATUS_UNSET + 1; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
 	{
-		if (i == PURPLE_STATUS_MOBILE || i == PURPLE_STATUS_TUNE)
+		/* Someone should fix this for 3.0.0.  The independent boolean
+		 * should probably be set on the status type, not the status.
+		 * I guess that would prevent third party plugins from creating
+		 * independent statuses?
+		 */
+		if (i == PURPLE_STATUS_MOBILE ||
+		    i == PURPLE_STATUS_MOOD ||
+		    i == PURPLE_STATUS_TUNE)
 			/*
 			 * Special-case these.  They're intended to be independent
 			 * status types, so don't show them in the list.
--- a/pidgin/pixmaps/Makefile.am	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/Makefile.am	Wed Nov 26 22:17:03 2008 +0000
@@ -106,7 +106,58 @@
 		emblems/16/scalable/video.svg \
 		emblems/16/scalable/voice.svg
 
+
+# Magic to copy files from emotes/small/16 to emblems/16.
+# This is necessary because UIs expect emblems in one place and
+# smiley themes in another, but we don't want to duplicate these
+# images in the source.
+emblems/16/%.png: emotes/small/16/%.png
+	rm -f $@
+	cp -f $< $@
+
+emblems/16/busy.png: status/16/busy.png
+	rm -f $@
+	cp -f $< $@
+
+# The copied emblems.
+# Ensure these are in .mtn-ignore.
+EMBLEMS_16_COPIED = \
+		emblems/16/amorous.png \
+		emblems/16/angry.png \
+		emblems/16/busy.png \
+		emblems/16/beer.png \
+		emblems/16/cigarette.png \
+		emblems/16/coffee.png \
+		emblems/16/confused.png \
+		emblems/16/console.png \
+		emblems/16/disappointed.png \
+		emblems/16/embarrassed.png \
+		emblems/16/excited.png \
+		emblems/16/in_love.png \
+		emblems/16/mean.png \
+		emblems/16/meeting.png \
+		emblems/16/mobile.png \
+		emblems/16/musical-note.png \
+		emblems/16/neutral.png \
+		emblems/16/party.png \
+		emblems/16/phone.png \
+		emblems/16/plate.png \
+		emblems/16/question.png \
+		emblems/16/sad.png \
+		emblems/16/sarcastic.png \
+		emblems/16/search.png \
+		emblems/16/sick.png \
+		emblems/16/sleeping.png \
+		emblems/16/sleepy.png \
+		emblems/16/thinking.png \
+		emblems/16/tv.png
+
+
+# Non-copied emblems.
+# Ensure these filenames don't clash with files in emotes/small/16 or
+# bad things will happen!
 EMBLEMS_16 = \
+		$(EMBLEMS_16_COPIED) \
 		emblems/16/aol-client.png \
 		emblems/16/birthday.png \
 		emblems/16/blocked.png \
@@ -127,7 +178,19 @@
 		emblems/16/secure.png \
 		emblems/16/unavailable.png \
 		emblems/16/video.png \
-		emblems/16/voice.png
+		emblems/16/voice.png \
+		emblems/16/bathing.png \
+		emblems/16/cinema.png \
+		emblems/16/internet.png \
+		emblems/16/restroom.png \
+		emblems/16/shopping.png \
+		emblems/16/studying.png \
+		emblems/16/suit.png \
+		emblems/16/surfing.png \
+		emblems/16/typing.png \
+		emblems/16/working.png \
+		emblems/16/writing.png
+
 
 EMOTES_DEFAULT_24_SCALABLE = \
 		emotes/default/24/scalable/airplane.svg \
Binary file pidgin/pixmaps/emblems/16/bathing.png has changed
Binary file pidgin/pixmaps/emblems/16/cinema.png has changed
Binary file pidgin/pixmaps/emblems/16/internet.png has changed
Binary file pidgin/pixmaps/emblems/16/mobile.png has changed
Binary file pidgin/pixmaps/emblems/16/restroom.png has changed
Binary file pidgin/pixmaps/emblems/16/shopping.png has changed
Binary file pidgin/pixmaps/emblems/16/studying.png has changed
Binary file pidgin/pixmaps/emblems/16/suit.png has changed
Binary file pidgin/pixmaps/emblems/16/surfing.png has changed
Binary file pidgin/pixmaps/emblems/16/typing.png has changed
Binary file pidgin/pixmaps/emblems/16/working.png has changed
Binary file pidgin/pixmaps/emblems/16/writing.png has changed
--- a/pidgin/pixmaps/emotes/default/24/Makefile.am	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/emotes/default/24/Makefile.am	Wed Nov 26 22:17:03 2008 +0000
@@ -2,6 +2,7 @@
     act-up.png \
     airplane.png \
     alien.png \
+    amorous.png \
     angel.png \
     angry.png \
     arrogant.png \
@@ -56,8 +57,9 @@
     dont-know.png \
     drink.png \
     drool.png \
-    eat.png \
+    hungry.png \
     embarrassed.png \
+    excited.png \
     excruciating.png \
     eyeroll.png \
     female-fighter.png \
@@ -81,7 +83,7 @@
     hug-left.png \
     hug-right.png \
     hypnotized.png \
-    in-love.png \
+    in_love.png \
     island.png \
     jump.png \
     kissed.png \
@@ -94,7 +96,6 @@
     liquor.png \
     loser.png \
     love-over.png \
-    love.png \
     lying.png \
     mad-tongue.png \
     mail.png \
@@ -114,7 +115,7 @@
     msn.png \
     musical-note.png \
     music.png \
-    nailbiting.png \
+    nervous.png \
     neutral.png \
     on-the-phone.png \
     party.png \
@@ -144,7 +145,7 @@
     secret.png \
     shame.png \
     sheep.png \
-    shock.png \
+    shocked.png \
     shout.png \
     shut-mouth.png \
     sick.png \
@@ -153,9 +154,9 @@
     sinister.png \
     skeleton.png \
     skywalker.png \
+    sleeping.png \
     sleepy.png \
-    smile-big.png \
-    smile.png \
+    happy.png \
     smirk.png \
     snail.png \
     snicker.png \
@@ -167,7 +168,7 @@
     stop.png \
     struggle.png \
     sun.png \
-    sweat.png \
+    hot.png \
     talktohand.png \
     teeth.png \
     terror.png \
@@ -175,7 +176,7 @@
     thunder.png \
     time-out.png \
     tongue.png \
-    tremble.png \
+    afraid.png \
     turtle.png \
     tv.png \
     umbrella.png \
@@ -188,7 +189,6 @@
     wilt.png \
     wink.png \
     worship.png \
-    yawn.png \
     yin-yang.png
 
 
Binary file pidgin/pixmaps/emotes/default/24/afraid.png has changed
Binary file pidgin/pixmaps/emotes/default/24/amorous.png has changed
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in	Wed Nov 26 22:17:03 2008 +0000
@@ -6,16 +6,16 @@
 
 # Default smileys
 [default]
-smile.png           :)      :-)
-smile-big.png       :-D     :-d     :D      :d
+happy.png           :)      :-)
+excited.png         :-D     :-d     :D      :d
 sad.png             :-(     :(
 wink.png            ;-)     ;)
 tongue.png          :P      :-P     :-p     :p
-shock.png           =-O     =-o
+shocked.png         =-O     =-o
 kiss.png            :-*
 glasses-cool.png    8-)
 embarrassed.png     :-[
-crying.png          :'(
+crying.png          :'(     :'-(
 thinking.png        :-/     :-\\
 angel.png           O:-)    o:-)
 shut-mouth.png      :-X
@@ -27,16 +27,61 @@
 ! cyclops.png       O-) o-)
 
 
+[XMPP]
+# Following XEP-0038 + our default set, in default set order
+happy.png           :)      :-)
+excited.png         :-D     :-d     :D      :d
+sad.png             :-(     :(
+wink.png            ;-)     ;)
+tongue.png          :P      :-P     :-p     :p
+shocked.png         =-O     =-o
+kiss.png            :kiss:  :-*
+glasses-cool.png    8-)
+embarrassed.png     :-[
+crying.png          :'-(    :'(
+thinking.png        :-/     :-\\
+angel.png           O:-)    o:-)
+shut-mouth.png      :-X
+moneymouth.png      :-$
+foot-in-mouth.png   :-!
+shout.png           >:o     >:O
+
+# Following XEP-0038
+angry.png           >:-(    >:(
+good.png            :yes:
+bad.png             :no:
+stop.png            :wait:
+rose.png            @->--   :rose:
+phone.png           :telephone:
+mail.png            :email:
+lamp.png            :jabber:
+cake.png            :cake:
+in_love.png         :heart: :love:
+love-over.png       :brokenheart:
+musical-note.png    :music:
+beer.png            :beer:
+coffee.png          :coffee:
+coins.png           :money:
+moon.png            :moon:
+sun.png             :sun:
+star.png            :star:
+
+# Hidden icons from the default set.
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)  :(|)     8-|)
+! cyclops.png       O-) o-)
+
+
 # Following AIM 6.1
 [AIM]
-smile.png           :-)     :)
+happy.png           :-)     :)
 wink.png            ;-)     ;)
 sad.png             :-(     :(
 tongue.png          :-P     :P      :-p    :p
-shock.png           =-O
+shocked.png         =-O
 kiss.png            :-*
 shout.png           >:o
-smile-big.png       :-D     :D
+excited.png         :-D     :D
 moneymouth.png      :-$
 foot-in-mouth.png   :-!
 embarrassed.png     :-[
@@ -47,14 +92,15 @@
 glasses-cool.png    8-)
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
 
 
 # Following Windows Live Messenger 8.1
 [MSN]
-smile.png           :)      :-)
-smile-big.png       :D      :d :-D :-d
+happy.png           :)      :-)
+excited.png         :D      :d :-D :-d
 wink.png            ;)      ;-)
-shock.png           :-O     :-o :O :o
+shocked.png         :-O     :-o :O :o
 tongue.png          :P      :p :-P :-p
 glasses-cool.png    (H)     (h)
 angry.png           :@      :-@
@@ -65,7 +111,7 @@
 neutral.png         :|      :-|
 devil.png           (6)
 angel.png           (A)     (a)
-love.png            (L)     (l)
+in_love.png         (L)     (l)
 love-over.png       (U)     (u)
 msn.png             (M)     (m)
 cat.png             (@)
@@ -125,10 +171,11 @@
 thunder.png         (li)
 party.png           <:o)
 eyeroll.png         8-)
-yawn.png            |-) 
+sleepy.png          |-) 
 bunny.png           ('.')
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
 
 # Hidden MSN emotes
 cigarette.png      	(ci)    (CI)
@@ -139,7 +186,7 @@
 
 # Following QQ 2006
 [QQ]
-shock.png           /:O      /jy       /surprised
+shocked.png         /:O      /jy       /surprised
 curl-lip.png        /:~      /pz       /curl_lip
 desire.png          /:*      /se       /desire
 dazed.png           /:|      /dazed
@@ -147,13 +194,13 @@
 crying.png          /:<      /ll       /cry
 bashful.png         /:$      /hx       /bashful
 shut-mouth.png      /:X      /bz       /shut_mouth
-sleepy.png          /:Z      /shui     /sleep
+sleeping.png        /:Z      /shui     /sleep
 weep.png            /:'(     /dk       /weep
 embarrassed.png     /:-|     /gg       /embarassed
 pissed-off.png      /:@      /fn       /pissed_off
 act-up.png          /:P      /tp       /act_up
-smile-big.png       /:D      /cy       /toothy_smile
-smile.png           /:)      /wx       /small_smile
+excited.png         /:D      /cy       /toothy_smile
+happy.png           /:)      /wx       /small_smile
 sad.png             /:(      /ng       /sad
 glasses-cool.png    /:+      /kuk      /cool
 doctor.png          /:#      /feid     /SARS
@@ -164,9 +211,9 @@
 disdain.png         /;d      /by       /disdain
 arrogant.png        /;o      /am       /arrogant
 starving.png        /:g      /jie      /starving
-yawn.png            /|-)     /kun      /sleepy
+sleepy.png          /|-)     /kun      /sleepy
 terror.png          /:!      /jk       /terror
-sweat.png           /:L      /sweat
+hot.png             /:L      /sweat
 smirk.png           /:>      /hanx     /smirk
 soldier.png         /:;      /db       /soldier
 struggle.png        /;f      /fendou   /struggle
@@ -180,8 +227,8 @@
 hammer.png          /xx      /qiao     /hammer
 bye.png             /bye     /zj       /bye
 go-away.png         /go      /shan     /go
-tremble.png         /shake   /fad      /shake
-in-love.png         /love    /aiq      /love
+afraid.png          /shake   /fad      /shake
+amorous.png         /love    /aiq      /love
 jump.png            /jump    /tiao     /jump
 search.png          /find    /zhao     /search
 lashes.png          /&       /mm       /beautiful_eyebrows
@@ -200,12 +247,12 @@
 musical-note.png    /music   /yy       /music
 poop.png            /shit    /bb       /shit
 coffee.png          /coffee  /kf       /coffee
-eat.png             /eat     /fan      /eat
+hungry.png          /eat     /fan      /eat
 pill.png            /pill    /yw       /pill
 rose.png            /rose    /mg       /rose
 wilt.png            /fade    /dx       /wilt
 kiss.png            /kiss    /wen      /kiss
-love.png            /heart   /xin      /heart
+in_love.png         /heart   /xin      /heart
 love-over.png       /break   /xs       /broken_heart
 meeting.png         /meeting /hy       /meeting
 present.png         /gift    /lw       /gift
@@ -234,19 +281,20 @@
 boy.png             /<11>    /nan      /man
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
 
 
 # Following ICQ 6.0
 [ICQ]
-smile.png           :-)     :)
+happy.png           :-)     :)
 neutral.png         :-$
 sad.png             :-(     :(
-shock.png           =-O
+shocked.png         =-O
 wink.png            ;-)     ;)
 tongue.png          :-P     :P      :-p     :p
 music.png           [:-}
 laugh.png           *JOKINGLY*
-sleepy.png          *TIRED*
+sleeping.png        *TIRED*
 crying.png          :'(    :'-(
 sick.png            :-!
 kissed.png          *KISSED*
@@ -265,26 +313,27 @@
 good.png            *THUMBS\ UP*
 shout.png           >:o     >:O     :-@
 beer.png            *DRINK*
-smile-big.png       :-D     :D
+excited.png         :-D     :D
 glasses-cool.png    8-)
-in-love.png         *IN\ LOVE*
+amorous.png         *IN\ LOVE*
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
 
 
 # Following Yahoo! Messenger 8.1
 [Yahoo]
-smile.png           :)      :-)
+happy.png           :)      :-)
 question.png        :-/     :-\\
-shock.png           :-O     :O      :-o     :o 
+shocked.png         :-O     :O      :-o     :o 
 devil.png           >:)
 angel.png           O:-)    o:-)    0:-)
 sick.png            :-&
-yawn.png            (:|
+sleepy.png          (:|
 hypnotized.png      @-)
 on-the-phone.png    :)]
 sad.png             :(      :-(
-in-love.png         :x      :-x     :X      :-X
+amorous.png         :x      :-x     :X      :-X
 angry.png           X-(     x-(     X(      x(
 crying.png          :((
 glasses-nerdy.png   :-B     :-b
@@ -301,11 +350,11 @@
 thinking.png        :-?
 waiting.png         :-w     :-W
 at-wits-end.png     ~x(     ~X(
-smile-big.png       :D      :-D     :d      :-d
+excited.png         :D      :-D     :d      :-d
 tongue.png          :-P     :P      :-p     :p
 glasses-cool.png    B-)     b-)
 neutral.png         :|      :-|
-sleepy.png          I-)     i-)     |-)
+sleeping.png        I-)     i-)     |-)
 clown.png           :o)     :O)
 doh.png             #-o     #-O
 weep.png            :-<
@@ -321,15 +370,16 @@
 time-out.png        :-t     :-T
 hug-left.png        >:D<    >:d<
 love-over.png       =((
-sweat.png           #:-S    #:-s
+hot.png             #:-S    #:-s
 rotfl.png           =)) :-j :-J 
 loser.png           L-)     l-)
 party.png           <:-P    <:-p
-nailbiting.png      :-SS	:-Ss	:-sS	:-ss
+nervous.png         :-SS	:-Ss	:-sS	:-ss
 cowboy.png          <):)
 desire.png          8->
 ! skywalker.png     C:-)    c:-)    C:)     c:)
 ! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
 
 # Hidden Yahoo emotes
 alien.png           =:)     >-)
@@ -367,14 +417,14 @@
 
 # Following MySpaceIM Beta 1.0.697.0
 [MySpaceIM]
-smile-big.png	    :D      :-D
+excited.png  	    :D      :-D
 devil.png	    }:)
 confused.png	    :Z
 glasses-nerdy.png   B)
 bulgy-eyes.png	    %)
 freaked-out.png	    :E
 smile.png	    :)      :-)
-in-love.png	    :X
+amorous.png	    :X
 laugh.png	    :))
 mohawk.png	    -:
 mad-tongue.png	    X(
@@ -392,3 +442,7 @@
 wink.png	    ;-)     ;)
 sad.png		    :[
 kiss.png            :x
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)  :(|)
+! cyclops.png       O-) o-)
+
Binary file pidgin/pixmaps/emotes/default/24/eat.png has changed
Binary file pidgin/pixmaps/emotes/default/24/excited.png has changed
Binary file pidgin/pixmaps/emotes/default/24/happy.png has changed
Binary file pidgin/pixmaps/emotes/default/24/hot.png has changed
Binary file pidgin/pixmaps/emotes/default/24/hungry.png has changed
Binary file pidgin/pixmaps/emotes/default/24/in-love.png has changed
Binary file pidgin/pixmaps/emotes/default/24/in_love.png has changed
Binary file pidgin/pixmaps/emotes/default/24/love.png has changed
Binary file pidgin/pixmaps/emotes/default/24/nailbiting.png has changed
Binary file pidgin/pixmaps/emotes/default/24/nervous.png has changed
Binary file pidgin/pixmaps/emotes/default/24/shock.png has changed
Binary file pidgin/pixmaps/emotes/default/24/shocked.png has changed
Binary file pidgin/pixmaps/emotes/default/24/sleeping.png has changed
Binary file pidgin/pixmaps/emotes/default/24/sleepy.png has changed
Binary file pidgin/pixmaps/emotes/default/24/smile-big.png has changed
Binary file pidgin/pixmaps/emotes/default/24/smile.png has changed
Binary file pidgin/pixmaps/emotes/default/24/sweat.png has changed
Binary file pidgin/pixmaps/emotes/default/24/tremble.png has changed
Binary file pidgin/pixmaps/emotes/default/24/yawn.png has changed
--- a/pidgin/pixmaps/emotes/small/16/Makefile.am	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/emotes/small/16/Makefile.am	Wed Nov 26 22:17:03 2008 +0000
@@ -1,4 +1,5 @@
 SMILEYS = \
+    amorous.png \
     angel.png \
     angry.png \
     beer.png \
@@ -12,12 +13,15 @@
     crying.png \
     devil.png \
     dont-know.png \
+    excited.png \
     grin.png \
+    happy.png \
     hug-left.png \
     hug-right.png \
+    in_love.png \
     kiss.png \
-    love.png \
     meeting.png \
+    mobile.png \
     musical-note.png \
     nerdy.png \
     neutral.png \
@@ -27,18 +31,16 @@
     question.png \
     sad.png \
     shame.png \
-    shock.png \
+    shocked.png \
     sick.png \
     silent.png \
+    sleeping.png \
     sleepy.png \
-    smile-big.png \
-    smile.png \
     thinking.png \
     tongue.png \
     tv.png \
     uhm-yeah.png \
-    wink.png \
-    yawn.png
+    wink.png
 
 
 pidginsmileypix_in_files = small.theme.in
--- a/pidgin/pixmaps/emotes/small/16/TODO	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/emotes/small/16/TODO	Wed Nov 26 22:17:03 2008 +0000
@@ -1,7 +1,18 @@
 The following icons where just scaled down from the 24x24 and may need work:
+	afraid.png
+	amorous.png
+	disappointed.png
+	embarrassed.png
+	happy.png
+	hot.png
+	hungry.png
+	mean.png
 	meeting.png
+	nervous.png
 	question.png
+	sarcastic.png
 	search.png
+	shocked.png
 	sleepy.png
 	smile-big.png
 	tv.png
@@ -13,7 +24,7 @@
 	cigarette.png
 	coffee.png
 	console.png
-	love.png
+	in_love.png
 	musical-note.png
 	party.png
 	phone.png
Binary file pidgin/pixmaps/emotes/small/16/afraid.png has changed
Binary file pidgin/pixmaps/emotes/small/16/amorous.png has changed
Binary file pidgin/pixmaps/emotes/small/16/disappointed.png has changed
Binary file pidgin/pixmaps/emotes/small/16/embarrassed.png has changed
Binary file pidgin/pixmaps/emotes/small/16/excited.png has changed
Binary file pidgin/pixmaps/emotes/small/16/happy.png has changed
Binary file pidgin/pixmaps/emotes/small/16/hot.png has changed
Binary file pidgin/pixmaps/emotes/small/16/hungry.png has changed
Binary file pidgin/pixmaps/emotes/small/16/in_love.png has changed
Binary file pidgin/pixmaps/emotes/small/16/love.png has changed
Binary file pidgin/pixmaps/emotes/small/16/mean.png has changed
Binary file pidgin/pixmaps/emotes/small/16/mobile.png has changed
Binary file pidgin/pixmaps/emotes/small/16/nervous.png has changed
Binary file pidgin/pixmaps/emotes/small/16/sarcastic.png has changed
Binary file pidgin/pixmaps/emotes/small/16/shock.png has changed
Binary file pidgin/pixmaps/emotes/small/16/shocked.png has changed
Binary file pidgin/pixmaps/emotes/small/16/sleeping.png has changed
Binary file pidgin/pixmaps/emotes/small/16/sleepy.png has changed
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in	Wed Nov 26 22:16:58 2008 +0000
+++ b/pidgin/pixmaps/emotes/small/16/small.theme.in	Wed Nov 26 22:17:03 2008 +0000
@@ -6,27 +6,54 @@
 
 # Default smileys
 [default]
-smile.png           :)      :-)
-smile-big.png       :-D     :-d     :D      :d
+happy.png           :)      :-)
+excited.png         :-D     :-d     :D      :d
 sad.png             :-(     :(
 wink.png            ;-)     ;)
 tongue.png          :P      :-P     :-p     :p
-shock.png           =-O     =-o
+shocked.png         =-O     =-o
 kiss.png            :-*
-crying.png          :'(
+embarrassed.png     :-[
+crying.png          :'(     :'-(
 thinking.png        :-/     :-\\
 angel.png           O:-)    o:-)
 
 
+[XMPP]
+# Following XEP-0038 + our default set, in default set order
+happy.png           :)      :-)
+excited.png         :-D     :-d     :D      :d
+sad.png             :-(     :(
+wink.png            ;-)     ;)
+tongue.png          :P      :-P     :-p     :p
+shocked.png         =-O     =-o
+kiss.png            :kiss:  :-*
+embarrassed.png     :-[
+crying.png          :'-(    :'(
+thinking.png        :-/     :-\\
+angel.png           O:-)    o:-)
+
+# Following XEP-0038
+angry.png           >:-(    >:(
+phone.png           :telephone:
+in_love.png         :heart: :love:
+musical-note.png    :music:
+beer.png            :beer:
+coffee.png          :coffee:
+
+# Hidden icons from the default set.
+
+
 # Following AIM 6.1
 [AIM]
-smile.png           :-)     :)
+happy.png           :-)     :)
 wink.png            ;-)     ;)
 sad.png             :-(     :(
 tongue.png          :-P     :P      :-p    :p
-shock.png           =-O
+shocked.png         =-O
 kiss.png            :-*
-smile-big.png       :-D     :D
+excited.png         :-D     :D
+embarrassed.png     :-[
 angel.png           O:-)
 thinking.png        :-\\    :-/
 crying.png          :'(
@@ -34,19 +61,20 @@
 
 # Following Windows Live Messenger 8.1
 [MSN]
-smile.png           :)      :-)
-smile-big.png       :D      :d :-D :-d
+happy.png           :)      :-)
+excited.png         :D      :d :-D :-d
 wink.png            ;)      ;-)
-shock.png           :-O     :-o :O :o
+shocked.png         :-O     :-o :O :o
 tongue.png          :P      :p :-P :-p
 angry.png           :@      :-@
+embarrassed.png     :$      :-$
 confused.png        :S      :s :-S :-s
 sad.png             :(      :-(
 crying.png          :'(
 neutral.png         :|      :-|
 devil.png           (6)
 angel.png           (A)     (a)
-love.png            (L)     (l)
+in_love.png         (L)     (l)
 musical-note.png    (8)
 kiss.png            (K)     (k)
 camera.png          (P)     (p)
@@ -55,12 +83,14 @@
 hug-left.png        ({)
 hug-right.png       (})
 beer.png            (B)     (b)
+sarcastic.png       ^o)
 sick.png            +o(
 plate.png           (pl)
+mobile.png          (mp)
 dont-know.png       :^)
 thinking.png        *-)
 party.png           <:o)
-yawn.png            |-) 
+sleepy.png          |-) 
 
 # Hidden MSN emotes
 cigarette.png      	(ci)    (CI)
@@ -69,22 +99,27 @@
 
 # Following QQ 2006
 [QQ]
-shock.png           /:O      /jy       /surprised
+shocked.png         /:O      /jy       /surprised
 party.png           /8-)     /dy       /revel
 crying.png          /:<      /ll       /cry
-sleepy.png          /:Z      /shui     /sleep
-smile-big.png       /:D      /cy       /toothy_smile
-smile.png           /:)      /wx       /small_smile
+sleeping.png        /:Z      /shui     /sleep
+embarrassed.png     /:-|     /gg       /embarassed
+excited.png         /:D      /cy       /toothy_smile
+happy.png           /:)      /wx       /small_smile
 sad.png             /:(      /ng       /sad
 sick.png            /:T      /tu       /vomit
-yawn.png            /|-)     /kun      /sleepy
+sleepy.png          /|-)     /kun      /sleepy
+hot.png             /:L      /sweat
 question.png        /?       /yiw      /question
+afraid.png          /shake   /fad      /shake
+amorous.png         /love    /aiq      /love
 search.png          /find    /zhao     /search
 hug-left.png        /hug     /yb       /hug
 musical-note.png    /music   /yy       /music
 coffee.png          /coffee  /kf       /coffee
+hungry.png          /eat     /fan      /eat
 kiss.png            /kiss    /wen      /kiss
-love.png            /heart   /xin      /heart
+in_love.png         /heart   /xin      /heart
 meeting.png         /meeting /hy       /meeting
 phone.png           /phone   /dh       /phone
 tv.png              /TV      /ds       /TV
@@ -93,45 +128,53 @@
 
 # Following ICQ 6.0
 [ICQ]
-smile.png           :-)     :)
+happy.png           :-)     :)
 neutral.png         :-$
 sad.png             :-(     :(
-shock.png           =-O
+shocked.png         =-O
 wink.png            ;-)     ;)
 tongue.png          :-P     :P      :-p     :p
-sleepy.png          *TIRED*
+sleeping.png        *TIRED*
 crying.png          :'(    :'-(
 sick.png            :-!
 kiss.png            :-{} :-*
+embarrassed.png     :-[
 devil.png           ]:->
 angel.png           O:-)
 thinking.png        :-\\    :-/
 beer.png            *DRINK*
-smile-big.png       :-D     :D
+excited.png         :-D     :D
+amorous.png         *IN\ LOVE*
 
 
 # Following Yahoo! Messenger 8.1
 [Yahoo]
-smile.png           :)      :-)
+happy.png           :)      :-)
 question.png        :-/     :-\\
-shock.png           :-O     :O      :-o     :o 
+shocked.png         :-O     :O      :-o     :o 
 devil.png           >:)
 angel.png           O:-)    o:-)    0:-)
 sick.png            :-&
-yawn.png            (:|
+sleepy.png          (:|
 sad.png             :(      :-(
+amorous.png         :x      :-x     :X      :-X
 angry.png           X-(     x-(     X(      x(
 crying.png          :((
 wink.png            ;)      ;-)
+embarrassed.png     :">
+mean.png            :->     :>
 thinking.png        :-?
-smile-big.png       :D      :-D     :d      :-d
+excited.png         :D      :-D     :d      :-d
 tongue.png          :-P     :P      :-p     :p
 neutral.png         :|      :-|
-sleepy.png          I-)     i-)     |-)
+sleeping.png        I-)     i-)     |-)
 kiss.png            :-*     :*
 confused.png        :-S     :-s
+sarcastic.png       /:)
 hug-left.png        >:D<    >:d<
+hot.png             #:-S    #:-s
 party.png           <:-P    <:-p
+nervous.png         :-SS	:-Ss	:-sS	:-ss
 
 # Hidden Yahoo emotes
 coffee.png          ~o)     ~O)
@@ -144,13 +187,15 @@
 
 # Following MySpaceIM Beta 1.0.697.0
 [MySpaceIM]
-smile-big.png	    :D      :-D
+excited.png  	    :D      :-D
 devil.png	    }:)
 confused.png	    :Z
 smile.png	    :)      :-)
+amorous.png	    :X
 shock.png	    :O
 neutral.png	    :|
 tongue.png	    :P      :p
 wink.png	    ;-)     ;)
 sad.png		    :[
 kiss.png            :x
+
Binary file pidgin/pixmaps/emotes/small/16/smile-big.png has changed
Binary file pidgin/pixmaps/emotes/small/16/smile.png has changed
Binary file pidgin/pixmaps/emotes/small/16/yawn.png has changed
--- a/po/POTFILES.in	Wed Nov 26 22:16:58 2008 +0000
+++ b/po/POTFILES.in	Wed Nov 26 22:17:03 2008 +0000
@@ -124,6 +124,7 @@
 libpurple/protocols/novell/nmuser.c
 libpurple/protocols/novell/novell.c
 libpurple/protocols/oscar/family_chatnav.c
+libpurple/protocols/oscar/family_locate.c
 libpurple/protocols/oscar/flap_connection.c
 libpurple/protocols/oscar/libaim.c
 libpurple/protocols/oscar/libicq.c