summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Lundblad <malu@pidgin.im>2010-02-18 21:38:43 +0000
committerMarcus Lundblad <malu@pidgin.im>2010-02-18 21:38:43 +0000
commit46e2a06ce2bdfd014e564e693422b0aa06ceedb9 (patch)
tree0211fd9c3f2720038935197af3ab46d52f492b9d
parentb551ca1f8ac096a1576d8e3c298f01a1bfdd48bd (diff)
parentc14672ee3571c4f2c09129326825a937ec1ac8b0 (diff)
downloadpidgin-cpw.rekkanoryo.icqxstatus.tar.gz
propagate from branch 'im.pidgin.pidgin' (head 770b86501b614dbcd9bd0d7ebbe55f21446d4dc1)cpw.rekkanoryo.icqxstatus
to branch 'im.pidgin.cpw.rekkanoryo.icqxstatus' (head ecd37aedbc80e0aa4ad96ee8bde1cf04997f2943)
-rw-r--r--COPYRIGHT4
-rw-r--r--ChangeLog.API1
-rw-r--r--finch/gntplugin.c2
-rw-r--r--finch/gntprefs.c2
-rw-r--r--finch/plugins/gnthistory.c2
-rw-r--r--libpurple/plugins/perl/common/Request.xs7
-rw-r--r--libpurple/protocols/gg/gg.c3
-rw-r--r--libpurple/protocols/jabber/jabber.c54
-rw-r--r--libpurple/protocols/jabber/libxmpp.c2
-rw-r--r--libpurple/protocols/jabber/presence.c10
-rw-r--r--libpurple/protocols/jabber/usermood.c256
-rw-r--r--libpurple/protocols/jabber/usermood.h2
-rw-r--r--libpurple/protocols/jabber/xdata.c2
-rw-r--r--libpurple/protocols/oscar/family_buddy.c12
-rw-r--r--libpurple/protocols/oscar/family_icbm.c241
-rw-r--r--libpurple/protocols/oscar/family_locate.c398
-rw-r--r--libpurple/protocols/oscar/libicq.c3
-rw-r--r--libpurple/protocols/oscar/oscar.c272
-rw-r--r--libpurple/protocols/oscar/oscar.h26
-rw-r--r--libpurple/protocols/oscar/oscarcommon.h2
-rw-r--r--libpurple/protocols/oscar/tlv.c8
-rw-r--r--libpurple/protocols/sametime/sametime.c8
-rw-r--r--libpurple/protocols/silc/buddy.c2
-rw-r--r--libpurple/protocols/silc/chat.c2
-rw-r--r--libpurple/protocols/silc10/buddy.c2
-rw-r--r--libpurple/protocols/silc10/chat.c2
-rw-r--r--libpurple/prpl.h6
-rw-r--r--libpurple/request.c38
-rw-r--r--libpurple/request.h26
-rw-r--r--libpurple/status.c20
-rw-r--r--libpurple/status.h13
-rw-r--r--pidgin/gtkblist.c178
-rw-r--r--pidgin/gtkrequest.c35
-rw-r--r--pidgin/gtksavedstatuses.c9
-rw-r--r--pidgin/pixmaps/Makefile.am5
-rw-r--r--pidgin/pixmaps/emotes/default/24/Makefile.am20
-rw-r--r--pidgin/pixmaps/emotes/default/24/afraid.png (renamed from pidgin/pixmaps/emotes/default/24/tremble.png)bin1493 -> 1493 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/amorous.png (renamed from pidgin/pixmaps/emotes/default/24/in-love.png)bin1636 -> 1636 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/default.theme.in267
-rw-r--r--pidgin/pixmaps/emotes/default/24/excited.png (renamed from pidgin/pixmaps/emotes/default/24/smile-big.png)bin1420 -> 1420 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/happy.png (renamed from pidgin/pixmaps/emotes/default/24/smile.png)bin1509 -> 1509 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/hot.png (renamed from pidgin/pixmaps/emotes/default/24/sweat.png)bin1513 -> 1513 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/hungry.png (renamed from pidgin/pixmaps/emotes/default/24/eat.png)bin1598 -> 1598 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/in_love.png (renamed from pidgin/pixmaps/emotes/default/24/love.png)bin1339 -> 1339 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/nervous.png (renamed from pidgin/pixmaps/emotes/default/24/nailbiting.png)bin1514 -> 1514 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/shocked.png (renamed from pidgin/pixmaps/emotes/default/24/shock.png)bin1507 -> 1507 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/sleeping.pngbin0 -> 1542 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/sleepy.pngbin1542 -> 1506 bytes
-rw-r--r--pidgin/pixmaps/emotes/default/24/yawn.pngbin1506 -> 0 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/Makefile.am36
-rw-r--r--pidgin/pixmaps/emotes/small/16/TODO13
-rw-r--r--pidgin/pixmaps/emotes/small/16/afraid.pngbin0 -> 909 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/amorous.pngbin0 -> 944 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/bathing.pngbin0 -> 816 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/cinema.pngbin0 -> 659 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/disappointed.pngbin0 -> 906 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/embarrassed.pngbin0 -> 917 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/excited.png (renamed from pidgin/pixmaps/emotes/small/16/smile-big.png)bin916 -> 916 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/happy.png (renamed from pidgin/pixmaps/emotes/small/16/smile.png)bin973 -> 973 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/hot.pngbin0 -> 919 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/hungry.pngbin0 -> 956 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/in_love.png (renamed from pidgin/pixmaps/emotes/small/16/love.png)bin847 -> 847 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/internet.pngbin0 -> 999 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/mean.pngbin0 -> 921 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/mobile.png (renamed from pidgin/pixmaps/emblems/16/mobile.png)bin535 -> 535 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/music.png (renamed from pidgin/pixmaps/emblems/16/music.png)bin571 -> 571 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/nervous.pngbin0 -> 937 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/restroom.pngbin0 -> 716 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/sarcastic.pngbin0 -> 904 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/scalable/mobile.svg (renamed from pidgin/pixmaps/emblems/scalable/mobile.svg)0
-rw-r--r--pidgin/pixmaps/emotes/small/16/scalable/music.svg (renamed from pidgin/pixmaps/emblems/scalable/music.svg)0
-rw-r--r--pidgin/pixmaps/emotes/small/16/shocked.png (renamed from pidgin/pixmaps/emotes/small/16/shock.png)bin952 -> 952 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/shopping.pngbin0 -> 645 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/sleeping.pngbin0 -> 912 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/sleepy.pngbin912 -> 935 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/small.theme.in132
-rw-r--r--pidgin/pixmaps/emotes/small/16/studying.pngbin0 -> 718 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/suit.pngbin0 -> 804 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/surfing.pngbin0 -> 919 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/typing.pngbin0 -> 725 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/working.pngbin0 -> 924 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/writing.pngbin0 -> 714 bytes
-rw-r--r--pidgin/pixmaps/emotes/small/16/yawn.pngbin935 -> 0 bytes
-rw-r--r--po/POTFILES.in1
84 files changed, 1672 insertions, 452 deletions
diff --git a/COPYRIGHT b/COPYRIGHT
index 1d3a4cfd4b..ae9afc633a 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -228,6 +228,7 @@ Thomas Huriaux
Instant Messaging Freedom, Inc.
Vitaliy Ischenko
Intel Corporation
+Andrew Ivanov
Scott Jackson
Hans Petter Jansson
David Jedelsky
@@ -237,7 +238,7 @@ Jan Kaluza
Yuriy Kaminskiy
Anders Kaseorg
Praveen Karadakal
-Jaromír Karmazín
+Tomáš Kebert
John Kelm
Jochen Kemnade
Yann Kerherve
@@ -541,6 +542,7 @@ Ma Xuan
Jared Yanovich
Timmy Yee
Li Yuan
+Yuriy Yevgrafov
Nickolai Zeldovich
Tom Zickel
Marco Ziech
diff --git a/ChangeLog.API b/ChangeLog.API
index 60a79e0b2f..5dc9206bd8 100644
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -146,6 +146,7 @@ version 2.6.0 (08/18/2009):
* xmlnode_from_file
* xmlnode_get_parent
* xmlnode_set_attrib_full
+ * PURPLE_STATUS_MOOD as a new PurpleStatusPrimitive
Changed:
* xmlnode_remove_attrib now removes all attributes with the
diff --git a/finch/gntplugin.c b/finch/gntplugin.c
index 332584ba27..642da2301b 100644
--- a/finch/gntplugin.c
+++ b/finch/gntplugin.c
@@ -498,7 +498,7 @@ process_pref_frame(PurplePluginPrefFrame *frame)
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;
diff --git a/finch/gntprefs.c b/finch/gntprefs.c
index 6d51da06eb..eb6c5eb376 100644
--- a/finch/gntprefs.c
+++ b/finch/gntprefs.c
@@ -171,7 +171,7 @@ get_pref_field(Prefs *prefs)
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);
}
diff --git a/finch/plugins/gnthistory.c b/finch/plugins/gnthistory.c
index 68303be145..b5514f0b26 100644
--- a/finch/plugins/gnthistory.c
+++ b/finch/plugins/gnthistory.c
@@ -158,7 +158,7 @@ history_prefs_check(PurplePlugin *plugin)
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);
diff --git a/libpurple/plugins/perl/common/Request.xs b/libpurple/plugins/perl/common/Request.xs
index 3ba745c2fc..499a6756a8 100644
--- a/libpurple/plugins/perl/common/Request.xs
+++ b/libpurple/plugins/perl/common/Request.xs
@@ -380,6 +380,13 @@ purple_request_field_list_add(field, item, data)
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
diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
index 67ee8a4863..21f2a136d3 100644
--- a/libpurple/protocols/gg/gg.c
+++ b/libpurple/protocols/gg/gg.c
@@ -2465,7 +2465,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* can_do_media */
+ NULL /* get_moods */
};
static PurplePluginInfo info = {
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
index 13791995d9..c22a89d550 100644
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -62,6 +62,7 @@
#include "roster.h"
#include "ping.h"
#include "si.h"
+#include "usermood.h"
#include "xdata.h"
#include "pep.h"
#include "adhoccommands.h"
@@ -2062,18 +2063,31 @@ void jabber_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboole
if (full) {
PurpleStatus *status;
- 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) {
- char *moodplustext = g_strdup_printf("%s (%s)", mood, moodtext);
+ /* find the mood */
+ PurpleMood *moods = jabber_get_moods(account);
+ const char *description = NULL;
+
+ for (; moods->mood ; moods++) {
+ if (purple_strequal(moods->mood, mood)) {
+ description = moods->description;
+ break;
+ }
+ }
+
+ moodtext = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
+ if(moodtext && *moodtext) {
+ char *moodplustext =
+ g_strdup_printf("%s (%s)", description ? _(description) : mood, moodtext);
purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext);
g_free(moodplustext);
} else
- purple_notify_user_info_add_pair(user_info, _("Mood"), mood);
+ purple_notify_user_info_add_pair(user_info, _("Mood"),
+ description ? _(description) : mood);
}
if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
PurpleStatus *tune = purple_presence_get_status(presence, "tune");
@@ -2134,7 +2148,15 @@ GList *jabber_status_types(PurpleAccount *account)
"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
"buzz", _("Allow Buzz"), buzz_enabled,
NULL);
- types = g_list_append(types, type);
+ types = g_list_prepend(types, type);
+
+
+ type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD,
+ "mood", NULL, TRUE, TRUE, TRUE,
+ PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING),
+ PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING),
+ NULL);
+ types = g_list_prepend(types, type);
priority_value = purple_value_new(PURPLE_TYPE_INT);
purple_value_set_int(priority_value, 1);
@@ -2150,7 +2172,7 @@ GList *jabber_status_types(PurpleAccount *account)
"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
"buzz", _("Allow Buzz"), buzz_enabled,
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);
@@ -2166,7 +2188,7 @@ GList *jabber_status_types(PurpleAccount *account)
"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
"buzz", _("Allow Buzz"), buzz_enabled,
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);
@@ -2182,7 +2204,7 @@ GList *jabber_status_types(PurpleAccount *account)
"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
"buzz", _("Allow Buzz"), buzz_enabled,
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);
@@ -2195,11 +2217,11 @@ GList *jabber_status_types(PurpleAccount *account)
"moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
"nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
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,
@@ -2207,7 +2229,7 @@ GList *jabber_status_types(PurpleAccount *account)
NULL, TRUE, 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,
@@ -2221,9 +2243,9 @@ GList *jabber_status_types(PurpleAccount *account)
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
diff --git a/libpurple/protocols/jabber/libxmpp.c b/libpurple/protocols/jabber/libxmpp.c
index 1c79766114..a10fa5499c 100644
--- a/libpurple/protocols/jabber/libxmpp.c
+++ b/libpurple/protocols/jabber/libxmpp.c
@@ -43,6 +43,7 @@
#include "presence.h"
#include "google.h"
#include "pep.h"
+#include "usermood.h"
#include "usertune.h"
#include "caps.h"
#include "data.h"
@@ -126,6 +127,7 @@ static PurplePluginProtocolInfo prpl_info =
NULL, /* get_account_text_table */
jabber_initiate_media, /* initiate_media */
jabber_get_media_caps, /* get_media_caps */
+ jabber_get_moods /* get_moods */
};
static gboolean load_plugin(PurplePlugin *plugin)
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
index 8e913a5e3b..8e77cd1b2f 100644
--- a/libpurple/protocols/jabber/presence.c
+++ b/libpurple/protocols/jabber/presence.c
@@ -40,6 +40,7 @@
#include "jutil.h"
#include "adhoccommands.h"
+#include "usermood.h"
#include "usertune.h"
@@ -131,6 +132,15 @@ void jabber_set_status(PurpleAccount *account, PurpleStatus *status)
gc = purple_account_get_connection(account);
js = purple_connection_get_protocol_data(gc);
+
+ /* it's a mood update */
+ if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+ const char *mood =
+ purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+ jabber_mood_set(js, mood, NULL);
+ return;
+ }
+
jabber_presence_send(js, FALSE);
}
diff --git a/libpurple/protocols/jabber/usermood.c b/libpurple/protocols/jabber/usermood.c
index 1fda1e4075..da5c1a0ccc 100644
--- a/libpurple/protocols/jabber/usermood.c
+++ b/libpurple/protocols/jabber/usermood.c
@@ -30,100 +30,106 @@
#include "request.h"
#include "debug.h"
-static const char * const moodstrings[] = {
- "afraid",
- "amazed",
- "amorous",
- "angry",
- "annoyed",
- "anxious",
- "aroused",
- "ashamed",
- "bored",
- "brave",
- "calm",
- "cautious",
- "cold",
- "confident",
- "confused",
- "contemplative",
- "contented",
- "cranky",
- "crazy",
- "creative",
- "curious",
- "dejected",
- "depressed",
- "disappointed",
- "disgusted",
- "dismayed",
- "distracted",
- "embarrassed",
- "envious",
- "excited",
- "flirtatious",
- "frustrated",
- "grumpy",
- "guilty",
- "happy",
- "hopeful",
- "hot",
- "humbled",
- "humiliated",
- "hungry",
- "hurt",
- "impressed",
- "in_awe",
- "in_love",
- "indignant",
- "interested",
- "intoxicated",
- "invincible",
- "jealous",
- "lonely",
- "lucky",
- "mean",
- "moody",
- "nervous",
- "neutral",
- "offended",
- "outraged",
- "playful",
- "proud",
- "relaxed",
- "relieved",
- "remorseful",
- "restless",
- "sad",
- "sarcastic",
- "serious",
- "shocked",
- "shy",
- "sick",
- "sleepy",
- "spontaneous",
- "stressed",
- "strong",
- "surprised",
- "thankful",
- "thirsty",
- "tired",
- "weak",
- "worried"
+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)
-{
- xmlnode *item;
- JabberBuddy *buddy = jabber_buddy_find(js, from, FALSE);
- const char *newmood = NULL;
- char *moodtext = NULL;
- xmlnode *child, *mood;
+static PurpleMood empty_moods[] = {
+ {NULL, NULL, NULL}
+};
+static void jabber_mood_cb(JabberStream *js, const char *from, xmlnode *items) {
/* it doesn't make sense to have more than one item here, so let's just pick the first one */
- item = xmlnode_get_child(items, "item");
-
+ xmlnode *item = xmlnode_get_child(items, "item");
+ const char *newmood = NULL;
+ char *moodtext = NULL;
+ JabberBuddy *buddy = jabber_buddy_find(js, from, FALSE);
+ xmlnode *moodinfo, *mood;
/* ignore the mood of people not on our buddy list */
if (!buddy || !item)
return;
@@ -131,39 +137,34 @@ jabber_mood_cb(JabberStream *js, const char *from, xmlnode *items)
mood = xmlnode_get_child_with_namespace(item, "mood", "http://jabber.org/protocol/mood");
if (!mood)
return;
- for (child = mood->child; child; child = child->next) {
- if (child->type != XMLNODE_TYPE_TAG)
- continue;
-
- if (g_str_equal("text", child->name) && moodtext == NULL)
- moodtext = xmlnode_get_data(child);
- else {
- int i;
- for (i = 0; i < G_N_ELEMENTS(moodstrings); ++i) {
- /* verify that the mood is known (valid) */
- if (g_str_equal(child->name, moodstrings[i])) {
- newmood = moodstrings[i];
- break;
+ for (moodinfo = mood->child; moodinfo; moodinfo = moodinfo->next) {
+ if (moodinfo->type == XMLNODE_TYPE_TAG) {
+ if (!strcmp(moodinfo->name, "text")) {
+ if (!moodtext) /* only pick the first one */
+ moodtext = xmlnode_get_data(moodinfo);
+ } else {
+ int i;
+ for (i = 0; moods[i].mood; ++i) {
+ /* verify that the mood is known (valid) */
+ if (!strcmp(moodinfo->name, moods[i].mood)) {
+ newmood = moods[i].mood;
+ break;
+ }
}
}
+ if (newmood != NULL && moodtext != NULL)
+ break;
}
if (newmood != NULL && moodtext != NULL)
break;
}
if (newmood != NULL) {
- PurpleAccount *account;
- 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);
-
- account = purple_connection_get_account(js->gc);
- purple_prpl_got_user_status(account, from, status_id, "mood",
- _(newmood), "moodtext",
- moodtext ? moodtext : "", NULL);
+ purple_prpl_got_user_status(js->gc->account, from, "mood",
+ PURPLE_MOOD_NAME, newmood,
+ PURPLE_MOOD_COMMENT, moodtext,
+ NULL);
+ } else {
+ purple_prpl_got_user_status_deactive(js->gc->account, from, "mood");
}
g_free(moodtext);
}
@@ -175,6 +176,7 @@ void jabber_mood_init(void) {
static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) {
JabberStream *js;
+ 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)) {
@@ -184,12 +186,12 @@ static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *f
js = gc->proto_data;
- if (selected_mood < 0 || selected_mood >= G_N_ELEMENTS(moodstrings)) {
+ if (selected_mood < 0 || selected_mood >= max_mood_idx) {
purple_debug_error("jabber", "Invalid mood index (%d) selected.\n", selected_mood);
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) {
@@ -207,8 +209,8 @@ static void do_mood_set_mood(PurplePluginAction *action) {
field = purple_request_field_choice_new("mood",
_("Mood"), 0);
- for(i = 0; i < G_N_ELEMENTS(moodstrings); ++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);
@@ -254,3 +256,17 @@ void jabber_mood_set(JabberStream *js, const char *mood, const char *text) {
/* publish is freed by jabber_pep_publish -> jabber_iq_send -> jabber_iq_free
(yay for well-defined memory management rules) */
}
+
+PurpleMood *jabber_get_moods(PurpleAccount *account)
+{
+ PurpleConnection *gc = purple_account_get_connection(account);
+ JabberStream *js = (JabberStream *) gc->proto_data;
+
+ if (js->pep) {
+ purple_debug_info("jabber", "get_moods: account supports PEP\n");
+ return moods;
+ } else {
+ purple_debug_info("jabber", "get_moods: account doesn't support PEP\n");
+ return empty_moods;
+ }
+} \ No newline at end of file
diff --git a/libpurple/protocols/jabber/usermood.h b/libpurple/protocols/jabber/usermood.h
index 4e27b2bb39..922da1667e 100644
--- a/libpurple/protocols/jabber/usermood.h
+++ b/libpurple/protocols/jabber/usermood.h
@@ -36,4 +36,6 @@ void jabber_mood_set(JabberStream *js,
const char *mood, /* must be one of the valid strings defined in the XEP */
const char *text /* might be NULL */);
+PurpleMood *jabber_get_moods(PurpleAccount *account);
+
#endif /* PURPLE_JABBER_USERMOOD_H_ */
diff --git a/libpurple/protocols/jabber/xdata.c b/libpurple/protocols/jabber/xdata.c
index aeda049af5..64ca60586e 100644
--- a/libpurple/protocols/jabber/xdata.c
+++ b/libpurple/protocols/jabber/xdata.c
@@ -305,7 +305,7 @@ void *jabber_x_data_request_with_actions(JabberStream *js, xmlnode *packet, GLis
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);
}
diff --git a/libpurple/protocols/oscar/family_buddy.c b/libpurple/protocols/oscar/family_buddy.c
index 9ca1dfae07..7efd60e520 100644
--- a/libpurple/protocols/oscar/family_buddy.c
+++ b/libpurple/protocols/oscar/family_buddy.c
@@ -221,6 +221,18 @@ buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *f
if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
ret = userfunc(od, conn, frame, &userinfo);
+ 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.bn);
+
+ 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.bn);
+ }
+ }
aim_info_free(&userinfo);
return ret;
diff --git a/libpurple/protocols/oscar/family_icbm.c b/libpurple/protocols/oscar/family_icbm.c
index d3bdc70e53..a01a6e56f1 100644
--- a/libpurple/protocols/oscar/family_icbm.c
+++ b/libpurple/protocols/oscar/family_icbm.c
@@ -2624,6 +2624,15 @@ static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod
char *bn;
guchar *cookie;
guint8 bnlen;
+ 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);
@@ -2633,14 +2642,54 @@ static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod
if (channel == 0x0002)
{
- if (reason == 0x0003) /* channel-specific */
- /* parse status note text */
- parse_status_note_text(od, cookie, bn, 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, bn, reason, cookie);
+ 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, bn);
+ presence = purple_buddy_get_presence(buddy);
+ status = purple_presence_get_active_status(presence);
+ purple_prpl_got_user_status(account, bn,
+ 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) {
@@ -2699,6 +2748,7 @@ static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod
g_free(cookie);
g_free(bn);
+ g_free(xml);
return ret;
}
@@ -2807,6 +2857,181 @@ int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event
}
/*
+ * 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,
diff --git a/libpurple/protocols/oscar/family_locate.c b/libpurple/protocols/oscar/family_locate.c
index 98d469413f..b3625d7a9e 100644
--- a/libpurple/protocols/oscar/family_locate.c
+++ b/libpurple/protocols/oscar/family_locate.c
@@ -45,7 +45,7 @@
* But, eh.
*/
static const struct {
- guint32 flag;
+ guint64 flag;
guint8 data[16];
} aim_caps[] = {
@@ -166,6 +166,16 @@ static const struct {
{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}},
@@ -240,6 +250,202 @@ static const struct {
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.
@@ -274,6 +480,7 @@ aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo)
cur->sessionlen = userinfo->sessionlen;
if (userinfo->capabilities != 0)
cur->capabilities = userinfo->capabilities;
+
cur->present |= userinfo->present;
if (userinfo->iconcsumlen > 0) {
@@ -398,13 +605,38 @@ aim_locate_getcaps(OscarData *od, ByteStream *bs, int len)
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)
{
@@ -495,6 +727,38 @@ aim_info_free(aim_userinfo_t *info)
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.
@@ -535,11 +799,12 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
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) {
/*
@@ -651,11 +916,23 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
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->bn, "mood",
+ PURPLE_MOOD_NAME, mood,
+ NULL);
+ else
+ purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
} else if (type == 0x000e) {
/*
@@ -791,6 +1068,37 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
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->bn, "mood",
+ PURPLE_MOOD_NAME, mood,
+ NULL);
+ else
+ purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
+ } break;
}
/* Save ourselves. */
@@ -857,6 +1165,10 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
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()
*/
@@ -892,8 +1204,9 @@ aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info)
}
#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);
@@ -904,6 +1217,7 @@ aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info)
return 0;
}
+#endif
/*
* Subtype 0x0001
@@ -1089,6 +1403,10 @@ int
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;
@@ -1096,7 +1414,7 @@ aim_locate_setcaps(OscarData *od, guint32 caps)
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));
@@ -1179,9 +1497,21 @@ userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *fram
/* 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->bn, "mood",
+ PURPLE_MOOD_NAME, mood,
+ NULL);
+ else
+ purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood");
}
aim_tlvlist_free(tlvlist);
@@ -1399,3 +1729,57 @@ locate_modfirst(OscarData *od, aim_module_t *mod)
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;
+}
diff --git a/libpurple/protocols/oscar/libicq.c b/libpurple/protocols/oscar/libicq.c
index 6c56f43572..def3c761e7 100644
--- a/libpurple/protocols/oscar/libicq.c
+++ b/libpurple/protocols/oscar/libicq.c
@@ -108,7 +108,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
icq_get_account_text_table, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* can_do_media */
+ oscar_get_purple_moods, /* get_moods */
};
static PurplePluginInfo info =
diff --git a/libpurple/protocols/oscar/oscar.c b/libpurple/protocols/oscar/oscar.c
index c4c59e4d39..9eb30bd942 100644
--- a/libpurple/protocols/oscar/oscar.c
+++ b/libpurple/protocols/oscar/oscar.c
@@ -61,6 +61,11 @@
#define OSCAR_STATUS_ID_FREE4CHAT "free4chat"
#define OSCAR_STATUS_ID_CUSTOM "custom"
#define OSCAR_STATUS_ID_MOBILE "mobile"
+#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 AIMHASHDATA "http://pidgin.im/aim_data.php3"
@@ -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_TYPING);
+ OSCAR_CAPABILITY_SHORTCAPS | OSCAR_CAPABILITY_TYPING | OSCAR_CAPABILITY_ICQSERVERRELAY | OSCAR_CAPABILITY_NEWCAPS | OSCAR_CAPABILITY_XTRAZ);
static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
static guint8 features_icq[] = {0x01, 0x06};
@@ -180,6 +185,7 @@ static int purple_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *,
static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_userinfo (OscarData *, FlapConnection *, FlapFrame *, ...);
+static int purple_got_infoblock (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -190,6 +196,7 @@ static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *,
static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...);
static int oscar_icon_req (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_msgack (OscarData *, FlapConnection *, FlapFrame *, ...);
+static int purple_parse_ratechange (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_evilnotify (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -672,7 +679,7 @@ static gchar *oscar_caps_to_string(OscarCapability caps)
{
GString *str;
const gchar *tmp;
- guint bit = 1;
+ guint64 bit = 1;
str = g_string_new("");
@@ -703,6 +710,10 @@ static gchar *oscar_caps_to_string(OscarCapability caps)
case OSCAR_CAPABILITY_GAMES2:
tmp = _("Games");
break;
+ case OSCAR_CAPABILITY_XTRAZ:
+ case OSCAR_CAPABILITY_NEWCAPS:
+ tmp = _("ICQ Xtraz");
+ break;
case OSCAR_CAPABILITY_ADDINS:
tmp = _("Add-Ins");
break;
@@ -784,6 +795,16 @@ static char *oscar_icqstatus(int state) {
return g_strdup(_("Web Aware"));
else if (state & AIM_ICQ_STATE_INVISIBLE)
return g_strdup(_("Invisible"));
+ else if (state & AIM_ICQ_STATE_EVIL)
+ return g_strdup(_("Evil"));
+ else if (state & AIM_ICQ_STATE_DEPRESSION)
+ return g_strdup(_("Depression"));
+ else if (state & AIM_ICQ_STATE_ATHOME)
+ return g_strdup(_("At home"));
+ else if (state & AIM_ICQ_STATE_ATWORK)
+ return g_strdup(_("At work"));
+ else if (state & AIM_ICQ_STATE_LUNCH)
+ return g_strdup(_("At lunch"));
else
return g_strdup(_("Online"));
}
@@ -961,6 +982,16 @@ static void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUser
}
}
+ 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);
}
@@ -2240,6 +2271,16 @@ static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame
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 {
@@ -2552,7 +2593,9 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
{
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);
@@ -2582,6 +2625,20 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
}
}
+ 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;
@@ -2667,10 +2724,28 @@ incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
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->bn, args->cookie);
+
+ if(args->info.rtfmsg.msgtype == 1)
+ {
+ if(rtfmsg)
+ {
+ serv_got_im(gc, userinfo->bn, rtfmsg, flags,
+ time(NULL));
+ }
+ else
+ {
+ serv_got_im(gc, userinfo->bn,
+ args->info.rtfmsg.rtfmsg, flags,
+ time(NULL));
+ }
+ }
+ }
else
{
purple_debug_error("oscar", "Unknown request class %hu\n",
@@ -3250,6 +3325,29 @@ static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason,
} 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. "
@@ -3497,6 +3595,55 @@ static int purple_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame
return 1;
}
+static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+{
+ PurpleConnection *gc = od->gc;
+ PurpleAccount *account = purple_connection_get_account(gc);
+ PurpleBuddy *b;
+ PurplePresence *presence;
+ PurpleStatus *status;
+ gchar *message = NULL;
+
+ va_list ap;
+ aim_userinfo_t *userinfo;
+
+ va_start(ap, fr);
+ userinfo = va_arg(ap, aim_userinfo_t *);
+ va_end(ap);
+
+ b = purple_find_buddy(account, userinfo->bn);
+ if (b == NULL)
+ return 1;
+
+ if (!oscar_util_valid_name_icq(userinfo->bn))
+ {
+ if (strcmp(purple_buddy_get_name(b), userinfo->bn) != 0)
+ serv_got_alias(gc, purple_buddy_get_name(b), userinfo->bn);
+ else
+ serv_got_alias(gc, purple_buddy_get_name(b), NULL);
+ }
+
+ presence = purple_buddy_get_presence(b);
+ status = purple_presence_get_active_status(presence);
+
+ if (purple_status_is_online(status) && !purple_status_is_available(status) &&
+ userinfo->flags & AIM_FLAG_AWAY && userinfo->away_len > 0 &&
+ userinfo->away != NULL && userinfo->away_encoding != NULL)
+ {
+ gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
+ message = oscar_encoding_to_utf8(account, charset,
+ userinfo->away,
+ userinfo->away_len);
+ g_free(charset);
+ purple_prpl_got_user_status(account, userinfo->bn,
+ purple_status_get_id(status),
+ "message", message, NULL);
+ g_free(message);
+ }
+
+ return 1;
+}
+
static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
{
char *msg;
@@ -4848,6 +4995,16 @@ oscar_set_extendedstatus(PurpleConnection *gc)
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;
@@ -5009,6 +5166,12 @@ oscar_set_status(PurpleAccount *account, PurpleStatus *status)
pc = purple_account_get_connection(account);
od = purple_connection_get_protocol_data(pc);
+ /* 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) {
+ aim_locate_setcaps(od, 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);
@@ -5961,6 +6124,11 @@ int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMes
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)
{
const char *name = b ? purple_buddy_get_name(b) : NULL;
@@ -6031,12 +6199,17 @@ const char *oscar_list_emblem(PurpleBuddy *b)
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;
}
@@ -6259,9 +6432,53 @@ oscar_status_types(PurpleAccount *account)
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,
@@ -6271,9 +6488,12 @@ oscar_status_types(PurpleAccount *account)
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);
@@ -6306,9 +6526,14 @@ oscar_status_types(PurpleAccount *account)
NULL, TRUE, TRUE, FALSE);
status_types = g_list_prepend(status_types, type);
- status_types = g_list_reverse(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 status_types;
+ return g_list_reverse(status_types);
}
static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
@@ -6480,6 +6705,23 @@ oscar_close_directim(gpointer object, gpointer ignored)
}
}
+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 void
oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore)
{
@@ -6529,15 +6771,13 @@ oscar_buddy_menu(PurpleBuddy *buddy) {
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 &&
oscar_util_name_compare(purple_account_get_username(account), bname) &&
diff --git a/libpurple/protocols/oscar/oscar.h b/libpurple/protocols/oscar/oscar.h
index 54756d5d80..561b98c0bc 100644
--- a/libpurple/protocols/oscar/oscar.h
+++ b/libpurple/protocols/oscar/oscar.h
@@ -375,8 +375,12 @@ typedef enum
OSCAR_CAPABILITY_CAMERA = 0x04000000,
OSCAR_CAPABILITY_ICHAT_SCREENSHARE = 0x08000000,
OSCAR_CAPABILITY_TYPING = 0x10000000,
- OSCAR_CAPABILITY_GENERICUNKNOWN = 0x20000000,
- OSCAR_CAPABILITY_LAST = 0x40000000
+ OSCAR_CAPABILITY_NEWCAPS = 0x20000000,
+ OSCAR_CAPABILITY_XTRAZ = 0x40000000,
+ OSCAR_CAPABILITY_GENERICUNKNOWN = 0x80000000,
+#warning Fix OSCAR_CAPABILITY_LAST situation
+ // TODO: We're out of bits. Rework things that depend on this or remove some capability. (Or, ensure this is a 64-bit type.)
+ OSCAR_CAPABILITY_LAST = 0x100000000
} OscarCapability;
/*
@@ -535,6 +539,7 @@ struct _OscarData
struct {
struct aim_userinfo_s *userinfo;
+ struct userinfo_node *requested;
} locate;
struct {
@@ -572,6 +577,12 @@ struct _OscarData
#define AIM_ICQ_STATE_BUSY 0x00000010
#define AIM_ICQ_STATE_CHAT 0x00000020
#define AIM_ICQ_STATE_INVISIBLE 0x00000100
+#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_WEBAWARE 0x00010000
#define AIM_ICQ_STATE_HIDEIP 0x00020000
#define AIM_ICQ_STATE_BIRTHDAY 0x00080000
@@ -1012,7 +1023,8 @@ struct aim_incomingim_ch4_args
/* 0x0008 */ int aim_im_warn(OscarData *od, FlapConnection *conn, const char *destbn, guint32 flags);
/* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code);
/* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
-/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event);
+/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, 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);
@@ -1144,8 +1156,10 @@ 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 *);
int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info);
-
-
+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 *);
@@ -1474,7 +1488,7 @@ int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value);
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);
diff --git a/libpurple/protocols/oscar/oscarcommon.h b/libpurple/protocols/oscar/oscarcommon.h
index a4467e7ef3..a7af4cb62f 100644
--- a/libpurple/protocols/oscar/oscarcommon.h
+++ b/libpurple/protocols/oscar/oscarcommon.h
@@ -30,6 +30,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
@@ -51,6 +52,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);
diff --git a/libpurple/protocols/oscar/tlv.c b/libpurple/protocols/oscar/tlv.c
index e139c06522..92e42a4ff4 100644
--- a/libpurple/protocols/oscar/tlv.c
+++ b/libpurple/protocols/oscar/tlv.c
@@ -407,10 +407,11 @@ int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
* @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 @@ int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps)
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);
}
diff --git a/libpurple/protocols/sametime/sametime.c b/libpurple/protocols/sametime/sametime.c
index 0092e137e4..be9382c938 100644
--- a/libpurple/protocols/sametime/sametime.c
+++ b/libpurple/protocols/sametime/sametime.c
@@ -3527,10 +3527,10 @@ static void blist_menu_conf_list(PurpleBuddy *buddy,
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);
@@ -5458,7 +5458,7 @@ static void remote_group_multi(struct mwResolveResult *result,
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);
diff --git a/libpurple/protocols/silc/buddy.c b/libpurple/protocols/silc/buddy.c
index 7c07da1f16..224c753366 100644
--- a/libpurple/protocols/silc/buddy.c
+++ b/libpurple/protocols/silc/buddy.c
@@ -1183,7 +1183,7 @@ silcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcDList clients)
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);
}
diff --git a/libpurple/protocols/silc/chat.c b/libpurple/protocols/silc/chat.c
index 477970849f..6ecbe5c314 100644
--- a/libpurple/protocols/silc/chat.c
+++ b/libpurple/protocols/silc/chat.c
@@ -475,7 +475,7 @@ void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
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);
diff --git a/libpurple/protocols/silc10/buddy.c b/libpurple/protocols/silc10/buddy.c
index 5939ef40a0..356e4edd43 100644
--- a/libpurple/protocols/silc10/buddy.c
+++ b/libpurple/protocols/silc10/buddy.c
@@ -1176,7 +1176,7 @@ silcpurple_add_buddy_select(SilcPurpleBuddyRes r,
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);
}
diff --git a/libpurple/protocols/silc10/chat.c b/libpurple/protocols/silc10/chat.c
index 0331fffeb4..b9c903ef51 100644
--- a/libpurple/protocols/silc10/chat.c
+++ b/libpurple/protocols/silc10/chat.c
@@ -449,7 +449,7 @@ void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
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);
diff --git a/libpurple/prpl.h b/libpurple/prpl.h
index 709dafb3d6..4ed0def2fc 100644
--- a/libpurple/prpl.h
+++ b/libpurple/prpl.h
@@ -569,6 +569,12 @@ struct _PurplePluginProtocolInfo
*/
PurpleMediaCaps (*get_media_caps)(PurpleAccount *account,
const char *who);
+
+ /**
+ * 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) \
diff --git a/libpurple/request.c b/libpurple/request.c
index 8ff0e3728e..fe7198c799 100644
--- a/libpurple/request.c
+++ b/libpurple/request.c
@@ -850,13 +850,40 @@ void
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);
- field->u.list.items = g_list_append(field->u.list.items, g_strdup(item));
+ 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);
}
@@ -962,6 +989,15 @@ purple_request_field_list_get_items(const PurpleRequestField *field)
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)
{
diff --git a/libpurple/request.h b/libpurple/request.h
index 08a18faaca..049b043b93 100644
--- a/libpurple/request.h
+++ b/libpurple/request.h
@@ -150,6 +150,7 @@ struct _PurpleRequestField
struct
{
GList *items;
+ GList *icons;
GHashTable *item_data;
GList *selected;
GHashTable *selected_table;
@@ -953,11 +954,24 @@ void *purple_request_field_list_get_data(const PurpleRequestField *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);
/**
+ * 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.
*
* @param field The field.
@@ -1015,6 +1029,18 @@ GList *purple_request_field_list_get_selected(
*/
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);
+
/*@}*/
/**************************************************************************/
diff --git a/libpurple/status.c b/libpurple/status.c
index 2040db1aff..9f7f80f151 100644
--- a/libpurple/status.c
+++ b/libpurple/status.c
@@ -137,6 +137,7 @@ static int primitive_scores[] =
-200, /* extended away */
-400, /* mobile */
0, /* tune */
+ 0, /* mood */
-10, /* idle, special case. */
-5, /* idle time, special case. */
10 /* Offline messageable */
@@ -157,15 +158,16 @@ static struct PurpleStatusPrimitiveMap
} 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 *
diff --git a/libpurple/status.h b/libpurple/status.h
index 743dd4dbb3..f47ce900bb 100644
--- a/libpurple/status.h
+++ b/libpurple/status.h
@@ -87,6 +87,12 @@ typedef struct _PurpleStatusAttr PurpleStatusAttr;
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.
*
@@ -106,8 +112,7 @@ typedef enum
*/
/*
* 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
{
@@ -120,6 +125,7 @@ typedef enum
PURPLE_STATUS_EXTENDED_AWAY,
PURPLE_STATUS_MOBILE,
PURPLE_STATUS_TUNE,
+ PURPLE_STATUS_MOOD,
PURPLE_STATUS_NUM_PRIMITIVES
} PurpleStatusPrimitive;
@@ -139,6 +145,9 @@ typedef enum
#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
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
index 340cb74163..3a31a66ec8 100644
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -3667,7 +3667,8 @@ static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full)
/* Offline? */
- /* FIXME: Why is this status special-cased by the core? -- rlaager */
+ /* FIXME: Why is this status special-cased by the core? --rlaager
+ * FIXME: Alternatively, why not have the core do all of them? --rlaager */
if (!PURPLE_BUDDY_IS_ONLINE(b)) {
purple_notify_user_info_add_pair(user_info, _("Status"), _("Offline"));
}
@@ -3762,6 +3763,24 @@ static GdkPixbuf * _pidgin_blist_get_cached_emblem(gchar *path) {
return pb;
}
+static char *get_mood_icon_path(const char *mood)
+{
+ char *path;
+
+ if (!strcmp(mood, "busy")) {
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin",
+ "status", "16", "busy.png", NULL);
+ } else if (!strcmp(mood, "hiptop")) {
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin",
+ "emblems", "16", "hiptop.png", NULL);
+ } else {
+ char *filename = g_strdup_printf("%s.png", mood);
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin",
+ "emotes", "small", filename, NULL);
+ g_free(filename);
+ }
+ return path;
+}
GdkPixbuf *
pidgin_blist_get_emblem(PurpleBlistNode *node)
@@ -3773,7 +3792,7 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
PurplePluginProtocolInfo *prpl_info;
const char *name = NULL;
char *filename, *path;
- PurplePresence *p;
+ PurplePresence *p = NULL;
PurpleStatus *tune;
if(PURPLE_BLIST_NODE_IS_CONTACT(node)) {
@@ -3786,14 +3805,17 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
gtkbuddynode = node->ui_data;
p = purple_buddy_get_presence(buddy);
if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
- path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems",
- "16", "mobile.png", NULL);
+ /* This emblem comes from the small emoticon set now,
+ * to reduce duplication. */
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes",
+ "small", "mobile.png", NULL);
return _pidgin_blist_get_cached_emblem(path);
}
if (((struct _pidgin_blist_node*)(node->parent->ui_data))->contact_expanded) {
- if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
- return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
+ if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"))
+ return NULL;
+ return pidgin_create_prpl_icon(((PurpleBuddy*)node)->account, PIDGIN_PRPL_ICON_SMALL);
}
} else {
return NULL;
@@ -3806,9 +3828,14 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
return _pidgin_blist_get_cached_emblem(path);
}
- p = purple_buddy_get_presence(buddy);
+ /* If we came through the contact code flow above, we didn't need
+ * to get the presence until now. */
+ if (p == NULL)
+ p = purple_buddy_get_presence(buddy);
+
if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
- path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "mobile.png", NULL);
+ /* This emblem comes from the small emoticon set now, to reduce duplication. */
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", "small", "mobile.png", NULL);
return _pidgin_blist_get_cached_emblem(path);
}
@@ -3827,7 +3854,8 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
return _pidgin_blist_get_cached_emblem(path);
}
/* Regular old "tune" is the only one in all protocols. */
- path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", "music.png", NULL);
+ /* This emblem comes from the small emoticon set now, to reduce duplication. */
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", "small", "music.png", NULL);
return _pidgin_blist_get_cached_emblem(path);
}
@@ -3839,13 +3867,24 @@ pidgin_blist_get_emblem(PurpleBlistNode *node)
if (prpl_info && prpl_info->list_emblem)
name = prpl_info->list_emblem(buddy);
- if (name == NULL)
- return NULL;
+ if (name == NULL) {
+ PurpleStatus *status;
- filename = g_strdup_printf("%s.png", name);
+ if (!purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOOD))
+ return NULL;
- path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", filename, NULL);
- g_free(filename);
+ status = purple_presence_get_status(p, "mood");
+ name = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+
+ if (!(name && *name))
+ return NULL;
+
+ path = get_mood_icon_path(name);
+ } else {
+ filename = g_strdup_printf("%s.png", name);
+ path = g_build_filename(DATADIR, "pixmaps", "pidgin", "emblems", "16", filename, NULL);
+ g_free(filename);
+ }
/* _pidgin_blist_get_cached_emblem() assumes ownership of path */
return _pidgin_blist_get_cached_emblem(path);
@@ -7785,6 +7824,88 @@ disable_account_cb(GtkCheckMenuItem *widget, gpointer data)
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 *path;
+
+ if (mood->mood == NULL || mood->description == NULL)
+ continue;
+
+ path = get_mood_icon_path(mood->mood);
+ purple_request_field_list_add_icon(f, _(mood->description),
+ path, (gpointer)mood->mood);
+ g_free(path);
+
+ 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)
{
@@ -7864,6 +7985,7 @@ pidgin_blist_update_accounts_menu(void)
PurpleAccount *account = NULL;
GdkPixbuf *pixbuf = NULL;
PurplePlugin *plugin = NULL;
+ PurplePluginProtocolInfo *prpl_info;
account = accounts->data;
@@ -7903,8 +8025,32 @@ pidgin_blist_update_accounts_menu(void)
gc = purple_account_get_connection(account);
plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
- if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
- build_plugin_actions(submenu, plugin, gc);
+ prpl_info = plugin ? PURPLE_PLUGIN_PROTOCOL_INFO(plugin) : NULL;
+
+ if (prpl_info &&
+ (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) ||
+ PURPLE_PLUGIN_HAS_ACTIONS(plugin))) {
+ if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods)) {
+ GList *types;
+ 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);
+
+ /* Be safe. It shouldn't match more than once anyway */
+ break;
+ }
+ }
+ if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
+ build_plugin_actions(submenu, plugin, gc);
+ }
} else {
menuitem = gtk_menu_item_new_with_label(_("No actions available"));
gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
diff --git a/pidgin/gtkrequest.c b/pidgin/gtkrequest.c
index 5f7e2e7333..092bd3ac90 100644
--- a/pidgin/gtkrequest.c
+++ b/pidgin/gtkrequest.c
@@ -1064,6 +1064,9 @@ create_list_field(PurpleRequestField *field)
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);
@@ -1075,7 +1078,10 @@ create_list_field(PurpleRequestField *field)
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));
@@ -1094,13 +1100,38 @@ create_list_field(PurpleRequestField *field)
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;
+ GdkPixbuf* pixbuf = NULL;
+
+ if (icon_path)
+ pixbuf = gdk_pixbuf_new_from_file(icon_path, NULL);
+
+ 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);
diff --git a/pidgin/gtksavedstatuses.c b/pidgin/gtksavedstatuses.c
index 2ce91ba603..2f24185b42 100644
--- a/pidgin/gtksavedstatuses.c
+++ b/pidgin/gtksavedstatuses.c
@@ -869,7 +869,14 @@ create_status_type_menu(PurpleStatusPrimitive type)
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.
diff --git a/pidgin/pixmaps/Makefile.am b/pidgin/pixmaps/Makefile.am
index 30f5682461..2ac9241d56 100644
--- a/pidgin/pixmaps/Makefile.am
+++ b/pidgin/pixmaps/Makefile.am
@@ -101,8 +101,6 @@ EMBLEMS_16 = \
emblems/16/half-operator.png \
emblems/16/hiptop.png \
emblems/16/male.png \
- emblems/16/mobile.png \
- emblems/16/music.png \
emblems/16/not-authorized.png \
emblems/16/operator.png \
emblems/16/qq-member.png \
@@ -120,8 +118,6 @@ EMBLEMS_SCALABLE = \
emblems/scalable/free-for-chat.svg \
emblems/scalable/game.svg \
emblems/scalable/male.svg \
- emblems/scalable/mobile.svg \
- emblems/scalable/music.svg \
emblems/scalable/not-authorized.svg \
emblems/scalable/qq-member.svg \
emblems/scalable/secure.svg \
@@ -207,6 +203,7 @@ EMOTES_DEFAULT_24_SCALABLE = \
emotes/default/24/scalable/yin-yang.svg
EMOTES_SMALL_16_SCALABLE = \
+ emotes/small/16/scalable/mobile.svg
emotes/small/16/scalable/pidgin-emotes.svg
PROTOCOLS_16_SCALABLE = \
diff --git a/pidgin/pixmaps/emotes/default/24/Makefile.am b/pidgin/pixmaps/emotes/default/24/Makefile.am
index 4bf3d69044..f4edbe83e6 100644
--- a/pidgin/pixmaps/emotes/default/24/Makefile.am
+++ b/pidgin/pixmaps/emotes/default/24/Makefile.am
@@ -2,6 +2,7 @@ SMILEYS = \
act-up.png \
airplane.png \
alien.png \
+ amorous.png \
angel.png \
angry.png \
arrogant.png \
@@ -56,8 +57,9 @@ SMILEYS = \
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 @@ SMILEYS = \
hug-left.png \
hug-right.png \
hypnotized.png \
- in-love.png \
+ in_love.png \
island.png \
jump.png \
kissed.png \
@@ -94,7 +96,6 @@ SMILEYS = \
liquor.png \
loser.png \
love-over.png \
- love.png \
lying.png \
mad-tongue.png \
mail.png \
@@ -114,7 +115,7 @@ SMILEYS = \
msn.png \
musical-note.png \
music.png \
- nailbiting.png \
+ nervous.png \
neutral.png \
on-the-phone.png \
party.png \
@@ -144,7 +145,7 @@ SMILEYS = \
secret.png \
shame.png \
sheep.png \
- shock.png \
+ shocked.png \
shout.png \
shut-mouth.png \
sick.png \
@@ -153,9 +154,9 @@ SMILEYS = \
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 @@ SMILEYS = \
stop.png \
struggle.png \
sun.png \
- sweat.png \
+ hot.png \
talktohand.png \
teeth.png \
terror.png \
@@ -175,7 +176,7 @@ SMILEYS = \
thunder.png \
time-out.png \
tongue.png \
- tremble.png \
+ afraid.png \
turtle.png \
tv.png \
umbrella.png \
@@ -188,7 +189,6 @@ SMILEYS = \
wilt.png \
wink.png \
worship.png \
- yawn.png \
yin-yang.png
diff --git a/pidgin/pixmaps/emotes/default/24/tremble.png b/pidgin/pixmaps/emotes/default/24/afraid.png
index 623a5d26e3..623a5d26e3 100644
--- a/pidgin/pixmaps/emotes/default/24/tremble.png
+++ b/pidgin/pixmaps/emotes/default/24/afraid.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/in-love.png b/pidgin/pixmaps/emotes/default/24/amorous.png
index e752acc976..e752acc976 100644
--- a/pidgin/pixmaps/emotes/default/24/in-love.png
+++ b/pidgin/pixmaps/emotes/default/24/amorous.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/default.theme.in b/pidgin/pixmaps/emotes/default/24/default.theme.in
index 8ddb77e61d..9fa98b13ba 100644
--- a/pidgin/pixmaps/emotes/default/24/default.theme.in
+++ b/pidgin/pixmaps/emotes/default/24/default.theme.in
@@ -6,37 +6,87 @@ Author=Hylke Bons
# 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
+tongue.png :P :p :-P :-p
+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
+moneymouth.png :-$
+foot-in-mouth.png :-!
+shout.png >:o >:O
+! skywalker.png C:-) c:-) C:) c:)
+! monkey.png :-(|) :(|) 8-|)
+! cyclops.png O-) o-)
+
+
+[XMPP]
+# Following XEP-0038 + GTalk + our default set, in default set order
+# The GTalk strings come from ticket #3307.
+happy.png :) :-) =)
+excited.png :-D :-d :D :d =D =d
+sad.png :-( :(
+wink.png ;-) ;) ;^)
+tongue.png :P :p :-P :-p
+shocked.png =-O =-o :-O :-o
+kiss.png :kiss: :-*
+glasses-cool.png 8-) B-)
+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 + GTalk
+angry.png >:-( >:( X-( x-(
+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: <3
+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:
+
+# Others
+neutral.png :| :-|
+victory.png \\m/
+
+# Hidden icons from the default set.
! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|) 8-|)
-! cyclops.png O-) o-)
+! 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
+tongue.png :P :p :-P :-p
+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 :-[
@@ -46,26 +96,27 @@ crying.png :'(
shut-mouth.png :-X
glasses-cool.png 8-)
! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|)
+! monkey.png :-(|) :(|) 8-|)
+! 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
-tongue.png :P :p :-P :-p
+shocked.png :-O :-o :O :o
+tongue.png :-P :P :-p :p
glasses-cool.png (H) (h)
angry.png :@ :-@
embarrassed.png :$ :-$
-confused.png :S :s :-S :-s
+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)
love-over.png (U) (u)
msn.png (M) (m)
cat.png (@)
@@ -125,10 +176,11 @@ thinking.png *-)
thunder.png (li)
party.png <:o)
eyeroll.png 8-)
-yawn.png |-)
+sleepy.png |-)
bunny.png ('.')
! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|)
+! monkey.png :-(|) :(|) 8-|)
+! cyclops.png O-) o-)
# Hidden MSN emotes
cigarette.png (ci) (CI)
@@ -139,7 +191,7 @@ fingers-crossed.png (yn) (YN)
# 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 +199,13 @@ party.png /8-) /dy /revel
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 +216,9 @@ cute.png /;-D /ka /cute
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 +232,8 @@ skeleton.png /!!! /kl /skeleton
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 +252,12 @@ soccerball.png /footb /zq /soccer
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
@@ -233,20 +285,21 @@ star.png /<*> /xixing /star
girl.png /<00> /nv /woman
boy.png /<11> /nan /man
! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|)
+! monkey.png :-(|) :(|) 8-|)
+! 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 +318,27 @@ thinking.png :-\\ :-/
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 :-(|) :(|)
+! monkey.png :-(|) :(|) 8-|)
+! 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 +355,11 @@ arrogant.png [-(
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,107 +375,16 @@ mad-tongue.png >:P >:p
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 :-(|) :(|)
-
-# Hidden Yahoo emotes
-alien.png =:) >-)
-beat-up.png b-( B-(
-chicken.png ~:>
-coffee.png ~o) ~O)
-cow.png 3:-O 3:-o
-dance.png \\:D/ \\:d/
-rose.png @};-
-dont-know.png :-L :-l
-skeleton.png 8-X 8-x
-lamp.png *-:)
-monkey.png :(|)
-coins.png $-)
-peace.png :)>-
-pig.png :@)
-pray.png [-o< [-O<
-pumpkin.png (~~)
-shame.png [-X [-x
-flag.png **==
-clover.png %%-
-musical-note.png :-"
-giggle.png ;))
-worship.png ^:)^
-star.png (*)
-waving.png >:/
-talktohand.png :-@
-
-# Only available after activating the Yahoo! Fighter IMVironment
-male-fighter1.png o-> O->
-male-fighter2.png o=> O=>
-female-fighter.png o-+ O-+
-yin-yang.png (%)
-
-# Following Yahoo! Messenger 8.1
-[Yahoo JAPAN]
-smile.png :) :-)
-question.png :-/ :-\\
-shock.png :-O :O :-o :o
-devil.png >:)
-angel.png O:-) o:-) 0:-)
-sick.png :-&
-yawn.png (:|
-hypnotized.png @-)
-on-the-phone.png :)]
-sad.png :( :-(
-in-love.png :x :-x :X :-X
-angry.png X-( x-( X( x(
-crying.png :((
-glasses-nerdy.png :-B :-b
-quiet.png :-$
-drool.png =P~ =p~
-lying.png :^O :^o
-call-me.png :-c
-wink.png ;) ;-)
-embarrassed.png :">
-mean.png :-> :>
-laugh.png :)) :-))
-bye.png =;
-arrogant.png [-(
-thinking.png :-?
-waiting.png :-w :-W
-at-wits-end.png ~x( ~X(
-smile-big.png :D :-D :d :-d
-tongue.png :-P :P :-p :p
-glasses-cool.png B-) b-)
-neutral.png :| :-|
-sleepy.png I-) i-) |-)
-clown.png :o) :O)
-doh.png #-o #-O
-weep.png :-<
-go-away.png :-h
-lashes.png ;;)
-kiss.png :-* :*
-confused.png :-S :-s
-sarcastic.png /:)
-eyeroll.png 8-|
-silly.png 8-}
-clap.png =D> =d>
-mad-tongue.png >:P >:p
-time-out.png :-t :-T
-hug-left.png >:D< >:d<
-love-over.png =((
-sweat.png #:-S #:-s
-rotfl.png =)) :-j :-J
-loser.png L-) l-)
-party.png <:-P <:-p
-nailbiting.png :-SS :-Ss :-sS :-ss
-cowboy.png <):)
-desire.png 8->
-! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|)
+! monkey.png :-(|) :(|) 8-|)
+! cyclops.png O-) o-)
# Hidden Yahoo emotes
alien.png =:) >-)
@@ -459,14 +422,14 @@ yin-yang.png (%)
# 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(
@@ -474,7 +437,7 @@ messed.png X)
glasses-nerdy.png Q)
doh.png :G
pirate.png P)
-shock.png :O
+shocked.png :O
sidefrown.png :{
sinister.png :B
smirk.png :,
@@ -484,23 +447,7 @@ pissed-off.png B|
wink.png ;-) ;)
sad.png :[
kiss.png :x
-
-[XMPP]
-# XMPP emoticons
-smile.png :) :-) =)
-smile-big.png :D :-D =D
-wink.png ;) ;-) ;^)
-shock.png :-o
-tongue.png :P :-P :-p :p
-glasses-cool.png B-)
-angry.png X-(
-sad.png :( :-( =(
-crying.png :'(
-neutral.png :-|
-thinking.png :-/
-love.png <3
-monkey.png :(|)
-victory.png \\m/
! skywalker.png C:-) c:-) C:) c:)
-! monkey.png :-(|) :(|) 8-|)
-! cyclops.png O-) o-)
+! monkey.png :-(|) :(|) 8-|)
+! cyclops.png O-) o-)
+
diff --git a/pidgin/pixmaps/emotes/default/24/smile-big.png b/pidgin/pixmaps/emotes/default/24/excited.png
index ce3f8664bc..ce3f8664bc 100644
--- a/pidgin/pixmaps/emotes/default/24/smile-big.png
+++ b/pidgin/pixmaps/emotes/default/24/excited.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/smile.png b/pidgin/pixmaps/emotes/default/24/happy.png
index 8a2ba4925c..8a2ba4925c 100644
--- a/pidgin/pixmaps/emotes/default/24/smile.png
+++ b/pidgin/pixmaps/emotes/default/24/happy.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/sweat.png b/pidgin/pixmaps/emotes/default/24/hot.png
index 1b7fbec14b..1b7fbec14b 100644
--- a/pidgin/pixmaps/emotes/default/24/sweat.png
+++ b/pidgin/pixmaps/emotes/default/24/hot.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/eat.png b/pidgin/pixmaps/emotes/default/24/hungry.png
index 393482f13e..393482f13e 100644
--- a/pidgin/pixmaps/emotes/default/24/eat.png
+++ b/pidgin/pixmaps/emotes/default/24/hungry.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/love.png b/pidgin/pixmaps/emotes/default/24/in_love.png
index 31aeea275e..31aeea275e 100644
--- a/pidgin/pixmaps/emotes/default/24/love.png
+++ b/pidgin/pixmaps/emotes/default/24/in_love.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/nailbiting.png b/pidgin/pixmaps/emotes/default/24/nervous.png
index 6888af8e0a..6888af8e0a 100644
--- a/pidgin/pixmaps/emotes/default/24/nailbiting.png
+++ b/pidgin/pixmaps/emotes/default/24/nervous.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/shock.png b/pidgin/pixmaps/emotes/default/24/shocked.png
index 0e7438e9ee..0e7438e9ee 100644
--- a/pidgin/pixmaps/emotes/default/24/shock.png
+++ b/pidgin/pixmaps/emotes/default/24/shocked.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/sleeping.png b/pidgin/pixmaps/emotes/default/24/sleeping.png
new file mode 100644
index 0000000000..e3bfe411b1
--- /dev/null
+++ b/pidgin/pixmaps/emotes/default/24/sleeping.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/sleepy.png b/pidgin/pixmaps/emotes/default/24/sleepy.png
index e3bfe411b1..2c3e78fd8d 100644
--- a/pidgin/pixmaps/emotes/default/24/sleepy.png
+++ b/pidgin/pixmaps/emotes/default/24/sleepy.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/default/24/yawn.png b/pidgin/pixmaps/emotes/default/24/yawn.png
deleted file mode 100644
index 2c3e78fd8d..0000000000
--- a/pidgin/pixmaps/emotes/default/24/yawn.png
+++ /dev/null
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/Makefile.am b/pidgin/pixmaps/emotes/small/16/Makefile.am
index 1980513a37..64ce3768db 100644
--- a/pidgin/pixmaps/emotes/small/16/Makefile.am
+++ b/pidgin/pixmaps/emotes/small/16/Makefile.am
@@ -1,4 +1,24 @@
+# These are mood images that are NOT also used in the smiley theme.
+MOODS = \
+ afraid.png \
+ bathing.png \
+ cinema.png \
+ disappointed.png \
+ embarrassed.png \
+ internet.png \
+ music.png \
+ restroom.png \
+ search.png \
+ shopping.png \
+ studying.png \
+ suit.png \
+ surfing.png \
+ typing.png \
+ working.png \
+ writing.png
+
SMILEYS = \
+ amorous.png \
angel.png \
angry.png \
beer.png \
@@ -12,12 +32,15 @@ SMILEYS = \
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 +50,16 @@ SMILEYS = \
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
@@ -46,6 +67,7 @@ pidginsmileypix_in_files = small.theme.in
if INSTALL_PIXMAPS
pidginsmileypixdir = $(datadir)/pixmaps/pidgin/emotes/small
pidginsmileypix_DATA = \
+ $(MOODS) \
$(SMILEYS) \
theme
@@ -56,4 +78,4 @@ theme: small.theme.in
$< > $@
endif
-EXTRA_DIST = $(SMILEYS) $(pidginsmileypix_in_files) theme
+EXTRA_DIST = $(MOODS) $(SMILEYS) $(pidginsmileypix_in_files) theme
diff --git a/pidgin/pixmaps/emotes/small/16/TODO b/pidgin/pixmaps/emotes/small/16/TODO
index 06046f86d6..e4d1008102 100644
--- a/pidgin/pixmaps/emotes/small/16/TODO
+++ b/pidgin/pixmaps/emotes/small/16/TODO
@@ -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 @@ our default icons:
cigarette.png
coffee.png
console.png
- love.png
+ in_love.png
musical-note.png
party.png
phone.png
diff --git a/pidgin/pixmaps/emotes/small/16/afraid.png b/pidgin/pixmaps/emotes/small/16/afraid.png
new file mode 100644
index 0000000000..b10a1a0abf
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/afraid.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/amorous.png b/pidgin/pixmaps/emotes/small/16/amorous.png
new file mode 100644
index 0000000000..41a520b194
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/amorous.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/bathing.png b/pidgin/pixmaps/emotes/small/16/bathing.png
new file mode 100644
index 0000000000..662eb2ac97
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/bathing.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/cinema.png b/pidgin/pixmaps/emotes/small/16/cinema.png
new file mode 100644
index 0000000000..e561cb0791
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/cinema.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/disappointed.png b/pidgin/pixmaps/emotes/small/16/disappointed.png
new file mode 100644
index 0000000000..3b3e2a12b8
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/disappointed.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/embarrassed.png b/pidgin/pixmaps/emotes/small/16/embarrassed.png
new file mode 100644
index 0000000000..404b38b494
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/embarrassed.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/smile-big.png b/pidgin/pixmaps/emotes/small/16/excited.png
index f03bc545ff..f03bc545ff 100644
--- a/pidgin/pixmaps/emotes/small/16/smile-big.png
+++ b/pidgin/pixmaps/emotes/small/16/excited.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/smile.png b/pidgin/pixmaps/emotes/small/16/happy.png
index cc6d3e2e89..cc6d3e2e89 100644
--- a/pidgin/pixmaps/emotes/small/16/smile.png
+++ b/pidgin/pixmaps/emotes/small/16/happy.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/hot.png b/pidgin/pixmaps/emotes/small/16/hot.png
new file mode 100644
index 0000000000..518ecc2274
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/hot.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/hungry.png b/pidgin/pixmaps/emotes/small/16/hungry.png
new file mode 100644
index 0000000000..bb53909c72
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/hungry.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/love.png b/pidgin/pixmaps/emotes/small/16/in_love.png
index 20e596b323..20e596b323 100644
--- a/pidgin/pixmaps/emotes/small/16/love.png
+++ b/pidgin/pixmaps/emotes/small/16/in_love.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/internet.png b/pidgin/pixmaps/emotes/small/16/internet.png
new file mode 100644
index 0000000000..9281221f98
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/internet.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/mean.png b/pidgin/pixmaps/emotes/small/16/mean.png
new file mode 100644
index 0000000000..be41d91e79
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/mean.png
Binary files differ
diff --git a/pidgin/pixmaps/emblems/16/mobile.png b/pidgin/pixmaps/emotes/small/16/mobile.png
index d368e64715..d368e64715 100644
--- a/pidgin/pixmaps/emblems/16/mobile.png
+++ b/pidgin/pixmaps/emotes/small/16/mobile.png
Binary files differ
diff --git a/pidgin/pixmaps/emblems/16/music.png b/pidgin/pixmaps/emotes/small/16/music.png
index 4b40b6eedf..4b40b6eedf 100644
--- a/pidgin/pixmaps/emblems/16/music.png
+++ b/pidgin/pixmaps/emotes/small/16/music.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/nervous.png b/pidgin/pixmaps/emotes/small/16/nervous.png
new file mode 100644
index 0000000000..dee32c7d4f
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/nervous.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/restroom.png b/pidgin/pixmaps/emotes/small/16/restroom.png
new file mode 100644
index 0000000000..a642e7d53c
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/restroom.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/sarcastic.png b/pidgin/pixmaps/emotes/small/16/sarcastic.png
new file mode 100644
index 0000000000..e18fb792d0
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/sarcastic.png
Binary files differ
diff --git a/pidgin/pixmaps/emblems/scalable/mobile.svg b/pidgin/pixmaps/emotes/small/16/scalable/mobile.svg
index 239d2c38f5..239d2c38f5 100644
--- a/pidgin/pixmaps/emblems/scalable/mobile.svg
+++ b/pidgin/pixmaps/emotes/small/16/scalable/mobile.svg
diff --git a/pidgin/pixmaps/emblems/scalable/music.svg b/pidgin/pixmaps/emotes/small/16/scalable/music.svg
index 29f0acfda6..29f0acfda6 100644
--- a/pidgin/pixmaps/emblems/scalable/music.svg
+++ b/pidgin/pixmaps/emotes/small/16/scalable/music.svg
diff --git a/pidgin/pixmaps/emotes/small/16/shock.png b/pidgin/pixmaps/emotes/small/16/shocked.png
index 0938170ee4..0938170ee4 100644
--- a/pidgin/pixmaps/emotes/small/16/shock.png
+++ b/pidgin/pixmaps/emotes/small/16/shocked.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/shopping.png b/pidgin/pixmaps/emotes/small/16/shopping.png
new file mode 100644
index 0000000000..291107ae64
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/shopping.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/sleeping.png b/pidgin/pixmaps/emotes/small/16/sleeping.png
new file mode 100644
index 0000000000..5fb313e620
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/sleeping.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/sleepy.png b/pidgin/pixmaps/emotes/small/16/sleepy.png
index 5fb313e620..9a86537f4f 100644
--- a/pidgin/pixmaps/emotes/small/16/sleepy.png
+++ b/pidgin/pixmaps/emotes/small/16/sleepy.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/small.theme.in b/pidgin/pixmaps/emotes/small/16/small.theme.in
index 64dc0e4f88..084c603ee0 100644
--- a/pidgin/pixmaps/emotes/small/16/small.theme.in
+++ b/pidgin/pixmaps/emotes/small/16/small.theme.in
@@ -6,27 +6,58 @@ Author=Hylke Bons
# 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
+tongue.png :P :p :-P :-p
+shocked.png =-O =-o
kiss.png :-*
-crying.png :'(
+embarrassed.png :-[
+crying.png :'( :'-(
+thinking.png :-/ :-\\
+angel.png O:-) o:-)
+
+
+[XMPP]
+# Following XEP-0038 + GTalk + our default set, in default set order
+# The GTalk strings come from ticket #3307.
+happy.png :) :-) =)
+excited.png :-D :-d :D :d =D =d
+sad.png :-( :(
+wink.png ;-) ;) ;^)
+tongue.png :P :p :-P :-p
+shocked.png =-O =-o :-O :-o
+kiss.png :kiss: :-*
+embarrassed.png :-[
+crying.png :'-( :'(
thinking.png :-/ :-\\
angel.png O:-) o:-)
+# Following XEP-0038 + GTalk
+angry.png >:-( >:( X-( x-(
+phone.png :telephone:
+in_love.png :heart: :love: <3
+musical-note.png :music:
+beer.png :beer:
+coffee.png :coffee:
+
+# Others
+neutral.png :| :-|
+
+# 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
+tongue.png :P :p :-P :-p
+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 +65,20 @@ crying.png :'(
# 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
-tongue.png :P :p :-P :-p
+shocked.png :-O :-o :O :o
+tongue.png :-P :P :-p :p
angry.png :@ :-@
-confused.png :S :s :-S :-s
+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 +87,14 @@ phone.png (T) (t)
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 +103,27 @@ console.png (xx) (XX)
# 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 +132,54 @@ angry.png /<O> /oh /angry
# 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*
+music.png [:-}
+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)
@@ -171,30 +219,14 @@ musical-note.png :-"
# Following MySpaceIM Beta 1.0.697.0
[MySpaceIM]
-smile-big.png :D :-D
+excited.png :D :-D
devil.png }:)
confused.png :Z
-smile.png :) :-)
-shock.png :O
+amorous.png :X
+shocked.png :O
neutral.png :|
tongue.png :P :p
wink.png ;-) ;)
sad.png :[
kiss.png :x
-[XMPP]
-# XMPP emoticons
-smile.png :) :-) =)
-smile-big.png :D :-D =D
-wink.png ;) ;-) ;^)
-shock.png :-o
-tongue.png :P :-P :-p :p
-glasses-cool.png B-)
-angry.png X-(
-sad.png :( :-( =(
-crying.png :'(
-neutral.png :-|
-thinking.png :-/
-love.png <3
-monkey.png :(|)
-victory.png \\m/
diff --git a/pidgin/pixmaps/emotes/small/16/studying.png b/pidgin/pixmaps/emotes/small/16/studying.png
new file mode 100644
index 0000000000..0a6053f86c
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/studying.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/suit.png b/pidgin/pixmaps/emotes/small/16/suit.png
new file mode 100644
index 0000000000..3c0080f0dd
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/suit.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/surfing.png b/pidgin/pixmaps/emotes/small/16/surfing.png
new file mode 100644
index 0000000000..727b352f72
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/surfing.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/typing.png b/pidgin/pixmaps/emotes/small/16/typing.png
new file mode 100644
index 0000000000..7f60b0a25e
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/typing.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/working.png b/pidgin/pixmaps/emotes/small/16/working.png
new file mode 100644
index 0000000000..cc90d637df
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/working.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/writing.png b/pidgin/pixmaps/emotes/small/16/writing.png
new file mode 100644
index 0000000000..e8b5d0d53e
--- /dev/null
+++ b/pidgin/pixmaps/emotes/small/16/writing.png
Binary files differ
diff --git a/pidgin/pixmaps/emotes/small/16/yawn.png b/pidgin/pixmaps/emotes/small/16/yawn.png
deleted file mode 100644
index 9a86537f4f..0000000000
--- a/pidgin/pixmaps/emotes/small/16/yawn.png
+++ /dev/null
Binary files differ
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0ed24d7cfb..3ffb4b1987 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -145,6 +145,7 @@ libpurple/protocols/novell/nmuser.c
libpurple/protocols/novell/novell.c
libpurple/protocols/oscar/clientlogin.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