summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Sales de Andrade <qulogic@pidgin.im>2010-02-28 04:07:39 +0000
committerElliott Sales de Andrade <qulogic@pidgin.im>2010-02-28 04:07:39 +0000
commit034e387678b1d1b87570743e9ebc05153fb7cdb9 (patch)
tree0852787504f6571d8f879b4297722f06500f533b
parent8c1111b9139955facdd6aad51bf5e14e007f05b7 (diff)
parentd9d015d4bb28b8d0c14c31a65776ca1239f37d93 (diff)
downloadpidgin-034e387678b1d1b87570743e9ebc05153fb7cdb9.tar.gz
propagate from branch 'im.pidgin.pidgin' (head 61c80aebc63d4ecf48f854206f228de4dd4b9b6e)
to branch 'im.pidgin.cpw.malu.ft_thumbnails' (head 8a8fef36b57ac9a3c86a4a9fa8058c37a2c2fdad)
-rw-r--r--COPYRIGHT4
-rw-r--r--ChangeLog3
-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/Makefile.mingw4
-rw-r--r--libpurple/example/nullclient.c10
-rw-r--r--libpurple/plugins/log_reader.c2
-rw-r--r--libpurple/plugins/perl/common/Request.xs7
-rw-r--r--libpurple/protocols/bonjour/Makefile.mingw2
-rw-r--r--libpurple/protocols/bonjour/bonjour.c5
-rw-r--r--libpurple/protocols/bonjour/bonjour_ft.c20
-rw-r--r--libpurple/protocols/bonjour/jabber.c260
-rw-r--r--libpurple/protocols/bonjour/jabber.h4
-rw-r--r--libpurple/protocols/bonjour/mdns_avahi.c20
-rw-r--r--libpurple/protocols/gg/gg.c3
-rw-r--r--libpurple/protocols/irc/irc.c3
-rw-r--r--libpurple/protocols/jabber/Makefile.mingw2
-rw-r--r--libpurple/protocols/jabber/jabber.c63
-rw-r--r--libpurple/protocols/jabber/jabber.h5
-rw-r--r--libpurple/protocols/jabber/libxmpp.c2
-rw-r--r--libpurple/protocols/jabber/presence.c10
-rw-r--r--libpurple/protocols/jabber/usermood.c263
-rw-r--r--libpurple/protocols/jabber/usermood.h2
-rw-r--r--libpurple/protocols/jabber/xdata.c2
-rw-r--r--libpurple/protocols/msn/msn.c3
-rw-r--r--libpurple/protocols/msn/slp.c21
-rw-r--r--libpurple/protocols/msn/slp.h19
-rw-r--r--libpurple/protocols/msn/slplink.c57
-rw-r--r--libpurple/protocols/mxit/mxit.c5
-rw-r--r--libpurple/protocols/myspace/myspace.c3
-rw-r--r--libpurple/protocols/novell/novell.c3
-rw-r--r--libpurple/protocols/oscar/clientlogin.c31
-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/flap_connection.c6
-rw-r--r--libpurple/protocols/oscar/libaim.c3
-rw-r--r--libpurple/protocols/oscar/libicq.c3
-rw-r--r--libpurple/protocols/oscar/oscar.c221
-rw-r--r--libpurple/protocols/oscar/oscar.h25
-rw-r--r--libpurple/protocols/oscar/oscarcommon.h2
-rw-r--r--libpurple/protocols/oscar/tlv.c8
-rw-r--r--libpurple/protocols/qq/qq.c3
-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/silc/silc.c3
-rw-r--r--libpurple/protocols/silc10/buddy.c2
-rw-r--r--libpurple/protocols/silc10/chat.c2
-rw-r--r--libpurple/protocols/simple/simple.c3
-rw-r--r--libpurple/protocols/yahoo/libyahoo.c3
-rw-r--r--libpurple/protocols/yahoo/libyahoojp.c3
-rw-r--r--libpurple/protocols/zephyr/zephyr.c3
-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--libpurple/win32/global.mak2
-rw-r--r--libpurple/win32/libc_interface.c24
-rw-r--r--libpurple/win32/libc_interface.h9
-rw-r--r--pidgin/Makefile.am1
-rw-r--r--pidgin/gtkblist.c222
-rw-r--r--pidgin/gtkdebug.c155
-rw-r--r--pidgin/gtkdocklet-gtk.c5
-rw-r--r--pidgin/gtkdocklet-x11.c359
-rw-r--r--pidgin/gtkft.c8
-rw-r--r--pidgin/gtkprefs.c2
-rw-r--r--pidgin/gtkprivacy.c22
-rw-r--r--pidgin/gtkrequest.c56
-rw-r--r--pidgin/gtksavedstatuses.c100
-rw-r--r--pidgin/gtkutils.c4
-rw-r--r--pidgin/pidginstock.c39
-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--pidgin/plugins/gestures/gestures.c26
-rw-r--r--pidgin/plugins/gevolution/assoc-buddy.c1
-rw-r--r--pidgin/plugins/gtkbuddynote.c8
-rw-r--r--pidgin/plugins/win32/transparency/win2ktrans.c52
-rw-r--r--pidgin/win32/gtkwin32dep.c77
-rw-r--r--pidgin/win32/nsis/langmacros.nsh6
-rw-r--r--pidgin/win32/nsis/pidgin-installer.nsi22
-rw-r--r--pidgin/win32/nsis/translations/english.nsh8
-rw-r--r--pidgin/win32/nsis/translations/norwegian_nynorsk.nsh9
-rw-r--r--pidgin/win32/nsis/translations/polish.nsh10
-rw-r--r--po/POTFILES.in4
135 files changed, 2285 insertions, 1320 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 b/ChangeLog
index bee9238bab..4177c8e7ac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,6 +18,9 @@ version 2.7.0 (??/??/????):
* Make the search dialog unobtrusive in the conversation window (by making
it look and behave like the search dialog in Firefox)
+ Bonjour:
+ * Added support for IPv6. (Thanks to T_X for testing)
+
version 2.6.6 (02/18/2010):
libpurple:
* Fix 'make check' on OS X. (David Fang)
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/Makefile.mingw b/libpurple/Makefile.mingw
index 1f55790f3d..29d3c9ee96 100644
--- a/libpurple/Makefile.mingw
+++ b/libpurple/Makefile.mingw
@@ -8,7 +8,7 @@ PIDGIN_TREE_TOP := ..
include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
TARGET = libpurple
-NEEDED_DLLS = $(LIBXML2_TOP)/bin/libxml2.dll
+NEEDED_DLLS = $(LIBXML2_TOP)/bin/libxml2-2.dll
##
## INCLUDE PATHS
@@ -20,7 +20,7 @@ INCLUDE_PATHS += \
-I$(GTK_TOP)/include \
-I$(GTK_TOP)/include/glib-2.0 \
-I$(GTK_TOP)/lib/glib-2.0/include \
- -I$(LIBXML2_TOP)/include
+ -I$(LIBXML2_TOP)/include/libxml2
LIB_PATHS += -L$(GTK_TOP)/lib \
-L$(LIBXML2_TOP)/lib
diff --git a/libpurple/example/nullclient.c b/libpurple/example/nullclient.c
index 4783bda61b..b311ee8cbf 100644
--- a/libpurple/example/nullclient.c
+++ b/libpurple/example/nullclient.c
@@ -27,7 +27,11 @@
#include <signal.h>
#include <string.h>
+#ifndef _WIN32
#include <unistd.h>
+#else
+#include "win32/win32dep.h"
+#endif
#include "defines.h"
@@ -80,7 +84,11 @@ static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInput
if (condition & PURPLE_INPUT_WRITE)
cond |= PURPLE_GLIB_WRITE_COND;
+#if defined _WIN32 && !defined WINPIDGIN_USE_GLIB_IO_CHANNEL
+ channel = wpurple_g_io_channel_win32_new_socket(fd);
+#else
channel = g_io_channel_unix_new(fd);
+#endif
closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
purple_glib_io_invoke, closure, purple_glib_io_destroy);
@@ -253,12 +261,14 @@ int main(int argc, char *argv[])
PurpleSavedStatus *status;
char *res;
+#ifndef _WIN32
/* libpurple's built-in DNS resolution forks processes to perform
* blocking lookups without blocking the main process. It does not
* handle SIGCHLD itself, so if the UI does not you quickly get an army
* of zombie subprocesses marching around.
*/
signal(SIGCHLD, SIG_IGN);
+#endif
init_libpurple();
diff --git a/libpurple/plugins/log_reader.c b/libpurple/plugins/log_reader.c
index 9da6ee1c2d..d7090a015d 100644
--- a/libpurple/plugins/log_reader.c
+++ b/libpurple/plugins/log_reader.c
@@ -2644,7 +2644,7 @@ static void log_reader_init_prefs(void) {
g_free(contents);
}
g_free(path);
-#endif /* !GTK_CHECK_VERSION(2,6,0) */
+#endif /* !GLIB_CHECK_VERSION(2,6,0) */
} /* path */
if (!found) {
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/bonjour/Makefile.mingw b/libpurple/protocols/bonjour/Makefile.mingw
index 8e3d6dd8c2..f0f3138f71 100644
--- a/libpurple/protocols/bonjour/Makefile.mingw
+++ b/libpurple/protocols/bonjour/Makefile.mingw
@@ -30,7 +30,7 @@ INCLUDE_PATHS += -I. \
-I$(GTK_TOP)/include/glib-2.0 \
-I$(GTK_TOP)/lib/glib-2.0/include \
-I$(BONJOUR_TOP)/Include \
- -I$(LIBXML2_TOP)/include \
+ -I$(LIBXML2_TOP)/include/libxml2 \
-I$(PURPLE_TOP) \
-I$(PURPLE_TOP)/win32 \
-I$(PIDGIN_TREE_TOP)
diff --git a/libpurple/protocols/bonjour/bonjour.c b/libpurple/protocols/bonjour/bonjour.c
index f1e26b20ea..eb72a1141d 100644
--- a/libpurple/protocols/bonjour/bonjour.c
+++ b/libpurple/protocols/bonjour/bonjour.c
@@ -101,6 +101,8 @@ bonjour_login(PurpleAccount *account)
/* Start waiting for jabber connections (iChat style) */
bd->jabber_data = g_new0(BonjourJabber, 1);
+ bd->jabber_data->socket = -1;
+ bd->jabber_data->socket6 = -1;
bd->jabber_data->port = purple_account_get_int(account, "port", BONJOUR_DEFAULT_PORT);
bd->jabber_data->account = account;
@@ -525,7 +527,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
diff --git a/libpurple/protocols/bonjour/bonjour_ft.c b/libpurple/protocols/bonjour/bonjour_ft.c
index 6fd68fce7c..d045cc62d6 100644
--- a/libpurple/protocols/bonjour/bonjour_ft.c
+++ b/libpurple/protocols/bonjour/bonjour_ft.c
@@ -747,8 +747,7 @@ bonjour_bytestreams_listen(int sock, gpointer data)
XepIq *iq;
xmlnode *query, *streamhost;
gchar *port;
- const char *next_ip, *local_ip;
- const char token [] = ";";
+ GSList *local_ips;
BonjourData *bd;
purple_debug_info("bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock);
@@ -773,17 +772,16 @@ bonjour_bytestreams_listen(int sock, gpointer data)
xfer->local_port = purple_network_get_port_from_fd(sock);
- local_ip = purple_network_get_my_ip_ext2(sock);
- /* cheat a little here - the intent of the "const" attribute is to make it clear that the string doesn't need to be freed */
- next_ip = strtok((char *)local_ip, token);
+ local_ips = bonjour_jabber_get_local_ips(sock);
port = g_strdup_printf("%hu", xfer->local_port);
- while(next_ip != NULL) {
+ while(local_ips) {
streamhost = xmlnode_new_child(query, "streamhost");
xmlnode_set_attrib(streamhost, "jid", xf->sid);
- xmlnode_set_attrib(streamhost, "host", next_ip);
+ xmlnode_set_attrib(streamhost, "host", local_ips->data);
xmlnode_set_attrib(streamhost, "port", port);
- next_ip = strtok(NULL, token);
+ g_free(local_ips->data);
+ local_ips = g_slist_delete_link(local_ips, local_ips);
}
g_free(port);
@@ -796,15 +794,17 @@ bonjour_bytestreams_init(PurpleXfer *xfer)
XepXfer *xf;
if(xfer == NULL)
return;
+
purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n");
xf = xfer->data;
+
purple_network_listen_map_external(FALSE);
xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
bonjour_bytestreams_listen, xfer);
purple_network_listen_map_external(TRUE);
- if (xf->listen_data == NULL) {
+ if (xf->listen_data == NULL)
purple_xfer_cancel_local(xfer);
- }
+
return;
}
diff --git a/libpurple/protocols/bonjour/jabber.c b/libpurple/protocols/bonjour/jabber.c
index e07a95f960..ee150c6ac8 100644
--- a/libpurple/protocols/bonjour/jabber.c
+++ b/libpurple/protocols/bonjour/jabber.c
@@ -44,6 +44,11 @@
#endif
#include <fcntl.h>
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+
#include "network.h"
#include "eventloop.h"
#include "connection.h"
@@ -623,15 +628,22 @@ void bonjour_jabber_stream_started(BonjourJabberConversation *bconv) {
}
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
static void
_server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition)
{
BonjourJabber *jdata = data;
- struct sockaddr_in their_addr; /* connector's address information */
- socklen_t sin_size = sizeof(struct sockaddr);
+ struct sockaddr_storage their_addr; /* connector's address information */
+ socklen_t sin_size = sizeof(struct sockaddr_storage);
int client_socket;
int flags;
- char *address_text = NULL;
+#ifdef HAVE_INET_NTOP
+ char addrstr[INET6_ADDRSTRLEN];
+#endif
+ const char *address_text;
struct _match_buddies_by_address_t *mbba;
BonjourJabberConversation *bconv;
GSList *buddies;
@@ -640,7 +652,9 @@ _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition co
if (condition != PURPLE_INPUT_READ)
return;
- if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1)
+ memset(&their_addr, 0, sin_size);
+
+ if ((client_socket = accept(server_socket, (struct sockaddr*)&their_addr, &sin_size)) == -1)
return;
flags = fcntl(client_socket, F_GETFL);
@@ -650,7 +664,16 @@ _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition co
#endif
/* Look for the buddy that has opened the conversation and fill information */
- address_text = inet_ntoa(their_addr.sin_addr);
+#ifdef HAVE_INET_NTOP
+ if (their_addr.ss_family == AF_INET6)
+ address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in6 *)&their_addr)->sin6_addr,
+ addrstr, sizeof(addrstr));
+ else
+ address_text = inet_ntop(their_addr.ss_family, &((struct sockaddr_in *)&their_addr)->sin_addr,
+ addrstr, sizeof(addrstr));
+#else
+ address_text = inet_ntoa(((struct sockaddr_in *)&their_addr)->sin_addr);
+#endif
purple_debug_info("bonjour", "Received incoming connection from %s.\n", address_text);
mbba = g_new0(struct _match_buddies_by_address_t, 1);
mbba->address = address_text;
@@ -680,52 +703,42 @@ _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition co
}
-gint
-bonjour_jabber_start(BonjourJabber *jdata)
+static int
+start_serversocket_listening(int port, int socket, struct sockaddr *addr, size_t addr_size, gboolean ip6, gboolean allow_port_fallback)
{
- struct sockaddr_in my_addr;
-
- /* Open a listening socket for incoming conversations */
- jdata->socket = socket(PF_INET, SOCK_STREAM, 0);
- if (jdata->socket < 0) {
- gchar *buf = g_strdup_printf(_("Unable to create socket: %s"),
- g_strerror(errno));
- purple_connection_error_reason(jdata->account->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
- g_free(buf);
- return -1;
- }
+ int ret_port = port;
- memset(&my_addr, 0, sizeof(struct sockaddr_in));
- my_addr.sin_family = AF_INET;
+ purple_debug_info("bonjour", "Attempting to bind IPv%d socket to port %d.\n", ip6 ? 6 : 4, port);
/* Try to use the specified port - if it isn't available, use a random port */
- my_addr.sin_port = htons(jdata->port);
- if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0)
- {
+ if (bind(socket, addr, addr_size) != 0) {
+
purple_debug_info("bonjour", "Unable to bind to specified "
- "port %i: %s\n", jdata->port, g_strerror(errno));
- my_addr.sin_port = 0;
- if (bind(jdata->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0)
- {
- gchar *buf = g_strdup_printf(_("Unable to bind socket "
- "to port: %s"), g_strerror(errno));
- purple_connection_error_reason(jdata->account->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
- g_free(buf);
+ "port %i: %s\n", port, g_strerror(errno));
+
+ if (!allow_port_fallback) {
+ purple_debug_warning("bonjour", "Not attempting random port assignment.\n");
return -1;
}
- jdata->port = purple_network_get_port_from_fd(jdata->socket);
+#ifdef PF_INET6
+ if (ip6)
+ ((struct sockaddr_in6 *) addr)->sin6_port = 0;
+ else
+#endif
+ ((struct sockaddr_in *) addr)->sin_port = 0;
+
+ if (bind(socket, addr, addr_size) != 0) {
+ purple_debug_error("bonjour", "Unable to bind IPv%d socket to port: %s\n", ip6 ? 6 : 4, g_strerror(errno));
+ return -1;
+ }
+ ret_port = purple_network_get_port_from_fd(socket);
}
+ purple_debug_info("bonjour", "Bound IPv%d socket to port %d.\n", ip6 ? 6 : 4, ret_port);
+
/* Attempt to listen on the bound socket */
- if (listen(jdata->socket, 10) != 0)
- {
- gchar *buf = g_strdup_printf(_("Unable to listen on socket: %s"),
- g_strerror(errno));
- purple_connection_error_reason(jdata->account->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, buf);
- g_free(buf);
+ if (listen(socket, 10) != 0) {
+ purple_debug_error("bonjour", "Unable to listen on IPv%d socket: %s\n", ip6 ? 6 : 4, g_strerror(errno));
return -1;
}
@@ -739,8 +752,66 @@ bonjour_jabber_start(BonjourJabber *jdata)
}
#endif
- /* Open a watcher in the socket we have just opened */
- jdata->watcher_id = purple_input_add(jdata->socket, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+ return ret_port;
+}
+
+gint
+bonjour_jabber_start(BonjourJabber *jdata)
+{
+ int ipv6_port = -1, ipv4_port = -1;
+
+ /* Open a listening socket for incoming conversations */
+#ifdef PF_INET6
+ jdata->socket6 = socket(PF_INET6, SOCK_STREAM, 0);
+#endif
+ jdata->socket = socket(PF_INET, SOCK_STREAM, 0);
+ if (jdata->socket == -1 && jdata->socket6 == -1) {
+ purple_debug_error("bonjour", "Unable to create socket: %s",
+ g_strerror(errno));
+ return -1;
+ }
+
+#ifdef PF_INET6
+ if (jdata->socket6 != -1) {
+ struct sockaddr_in6 addr6;
+ memset(&addr6, 0, sizeof(addr6));
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = htons(jdata->port);
+ addr6.sin6_addr = in6addr_any;
+ ipv6_port = start_serversocket_listening(jdata->port, jdata->socket6, (struct sockaddr *) &addr6, sizeof(addr6), TRUE, TRUE);
+ /* Open a watcher in the socket we have just opened */
+ if (ipv6_port > 0) {
+ jdata->watcher_id6 = purple_input_add(jdata->socket6, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+ jdata->port = ipv6_port;
+ } else {
+ purple_debug_error("bonjour", "Failed to start listening on IPv6 socket.\n");
+ close(jdata->socket6);
+ jdata->socket6 = -1;
+ }
+ }
+#endif
+ if (jdata->socket != -1) {
+ struct sockaddr_in addr4;
+ memset(&addr4, 0, sizeof(addr4));
+ addr4.sin_family = AF_INET;
+ addr4.sin_port = htons(jdata->port);
+ ipv4_port = start_serversocket_listening(jdata->port, jdata->socket, (struct sockaddr *) &addr4, sizeof(addr4), FALSE, ipv6_port != -1);
+ /* Open a watcher in the socket we have just opened */
+ if (ipv4_port > 0) {
+ jdata->watcher_id = purple_input_add(jdata->socket, PURPLE_INPUT_READ, _server_socket_handler, jdata);
+ jdata->port = ipv4_port;
+ } else {
+ purple_debug_error("bonjour", "Failed to start listening on IPv4 socket.\n");
+ close(jdata->socket);
+ jdata->socket = -1;
+ }
+ }
+
+ if (!(ipv6_port > 0 || ipv4_port > 0)) {
+ purple_debug_error("bonjour", "Unable to listen on socket: %s",
+ g_strerror(errno));
+ return -1;
+ }
return jdata->port;
}
@@ -1101,6 +1172,10 @@ bonjour_jabber_stop(BonjourJabber *jdata)
close(jdata->socket);
if (jdata->watcher_id > 0)
purple_input_remove(jdata->watcher_id);
+ if (jdata->socket6 >= 0)
+ close(jdata->socket6);
+ if (jdata->watcher_id6 > 0)
+ purple_input_remove(jdata->watcher_id6);
/* Close all the conversation sockets and remove all the watchers after sending end streams */
if (jdata->account->gc != NULL) {
@@ -1234,58 +1309,97 @@ xep_iq_send_and_free(XepIq *iq)
return (ret >= 0) ? 0 : -1;
}
-/* This returns a ';' delimited string containing all non-localhost IPs */
-const char *
-purple_network_get_my_ip_ext2(int fd)
+/* This returns a list containing all non-localhost IPs */
+GSList *
+bonjour_jabber_get_local_ips(int fd)
{
- char buffer[1024];
- static char ip_ext[17 * 10];
+ GSList *ips = NULL;
+ const char *address_text;
+ int ret;
+
+#ifdef HAVE_GETIFADDRS /* This is required for IPv6 */
+ {
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr *addr;
+ char addrstr[INET6_ADDRSTRLEN];
+
+ ret = getifaddrs(&ifap);
+ if (ret != 0) {
+ const char *error = g_strerror(errno);
+ purple_debug_error("bonjour", "getifaddrs() error: %s\n", error ? error : "(null)");
+ return NULL;
+ }
+
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (!(ifa->ifa_flags & IFF_RUNNING) || (ifa->ifa_flags & IFF_LOOPBACK) || ifa->ifa_addr == NULL)
+ continue;
+
+ addr = ifa->ifa_addr;
+ address_text = NULL;
+ switch (addr->sa_family) {
+ case AF_INET:
+ address_text = inet_ntop(addr->sa_family, &((struct sockaddr_in *)addr)->sin_addr,
+ addrstr, sizeof(addrstr));
+ break;
+#ifdef PF_INET6
+ case AF_INET6:
+ address_text = inet_ntop(addr->sa_family, &((struct sockaddr_in6 *)addr)->sin6_addr,
+ addrstr, sizeof(addrstr));
+ break;
+#endif
+ }
+
+ if (address_text != NULL) {
+ if (addr->sa_family == AF_INET)
+ ips = g_slist_append(ips, g_strdup(address_text));
+ else
+ ips = g_slist_prepend(ips, g_strdup(address_text));
+ }
+ }
+
+ freeifaddrs(ifap);
+
+ }
+#else
+ {
char *tmp;
- char *tip;
struct ifconf ifc;
struct ifreq *ifr;
+ char buffer[1024];
struct sockaddr_in *sinptr;
- guint32 lhost = htonl(127 * 256 * 256 * 256 + 1);
- long unsigned int add;
int source = fd;
- int len, count = 0;
if (fd < 0)
source = socket(PF_INET, SOCK_STREAM, 0);
ifc.ifc_len = sizeof(buffer);
ifc.ifc_req = (struct ifreq *)buffer;
- ioctl(source, SIOCGIFCONF, &ifc);
+ ret = ioctl(source, SIOCGIFCONF, &ifc);
if (fd < 0)
close(source);
- memset(ip_ext, 0, sizeof(ip_ext));
- memcpy(ip_ext, "0.0.0.0", 7);
+ if (ret < 0) {
+ const char *error = g_strerror(errno);
+ purple_debug_error("bonjour", "ioctl(SIOCGIFCONF) error: %s\n", error ? error : "(null)");
+ return NULL;
+ }
+
tmp = buffer;
- tip = ip_ext;
- while (tmp < buffer + ifc.ifc_len && count < 10)
- {
+ while (tmp < buffer + ifc.ifc_len) {
ifr = (struct ifreq *)tmp;
tmp += HX_SIZE_OF_IFREQ(*ifr);
- if (ifr->ifr_addr.sa_family == AF_INET)
- {
+ if (ifr->ifr_addr.sa_family == AF_INET) {
sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
- if (sinptr->sin_addr.s_addr != lhost)
- {
- add = ntohl(sinptr->sin_addr.s_addr);
- len = g_snprintf(tip, 17, "%lu.%lu.%lu.%lu;",
- ((add >> 24) & 255),
- ((add >> 16) & 255),
- ((add >> 8) & 255),
- add & 255);
- tip = &tip[len];
- count++;
- continue;
+ if ((ntohl(sinptr->sin_addr.s_addr) >> 24) != 127) {
+ address_text = inet_ntoa(sinptr->sin_addr);
+ ips = g_slist_prepend(ips, g_strdup(address_text));
}
- }
+ }
}
+ }
+#endif
- return ip_ext;
+ return ips;
}
diff --git a/libpurple/protocols/bonjour/jabber.h b/libpurple/protocols/bonjour/jabber.h
index b92f7f654f..c4db2068c3 100644
--- a/libpurple/protocols/bonjour/jabber.h
+++ b/libpurple/protocols/bonjour/jabber.h
@@ -37,7 +37,9 @@ typedef struct _BonjourJabber
{
gint port;
gint socket;
+ gint socket6;
gint watcher_id;
+ gint watcher_id6;
PurpleAccount *account;
GSList *pending_conversations;
} BonjourJabber;
@@ -105,6 +107,6 @@ typedef struct _XepIq {
XepIq *xep_iq_new(void *data, XepIqType type, const char *to, const char *from, const char *id);
int xep_iq_send_and_free(XepIq *iq);
-const char *purple_network_get_my_ip_ext2(int fd);
+GSList * bonjour_jabber_get_local_ips(int fd);
#endif /* _BONJOUR_JABBER_H_ */
diff --git a/libpurple/protocols/bonjour/mdns_avahi.c b/libpurple/protocols/bonjour/mdns_avahi.c
index 6297f156b7..7ef358cbea 100644
--- a/libpurple/protocols/bonjour/mdns_avahi.c
+++ b/libpurple/protocols/bonjour/mdns_avahi.c
@@ -189,8 +189,12 @@ _resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtoco
bb->ips = g_slist_remove(bb->ips, rd->ip);
g_free((gchar *) rd->ip);
}
- bb->ips = g_slist_prepend(bb->ips, g_strdup(ip));
- rd->ip = bb->ips->data;
+ rd->ip = g_strdup(ip);
+ /* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */
+ if (protocol == AVAHI_PROTO_INET6)
+ bb->ips = g_slist_prepend(bb->ips, (gchar *) rd->ip);
+ else
+ bb->ips = g_slist_append(bb->ips, (gchar *) rd->ip);
}
bb->port_p2pj = port;
@@ -249,7 +253,7 @@ _browser_callback(AvahiServiceBrowser *b, AvahiIfIndex interface,
/* Make sure it isn't us */
if (purple_utf8_strcasecmp(name, account->username) != 0) {
if (!avahi_service_resolver_new(avahi_service_browser_get_client(b),
- interface, protocol, name, type, domain, AVAHI_PROTO_INET,
+ interface, protocol, name, type, domain, protocol,
0, _resolver_callback, account)) {
purple_debug_warning("bonjour", "_browser_callback -- Error initiating resolver: %s\n",
avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
@@ -448,14 +452,14 @@ gboolean _mdns_publish(BonjourDnsSd *data, PublishType type, GSList *records) {
case PUBLISH_START:
publish_result = avahi_entry_group_add_service_strlst(
idata->group, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_INET, 0,
+ AVAHI_PROTO_UNSPEC, 0,
purple_account_get_username(data->account),
LINK_LOCAL_RECORD_NAME, NULL, NULL, data->port_p2pj, lst);
break;
case PUBLISH_UPDATE:
publish_result = avahi_entry_group_update_service_txt_strlst(
idata->group, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_INET, 0,
+ AVAHI_PROTO_UNSPEC, 0,
purple_account_get_username(data->account),
LINK_LOCAL_RECORD_NAME, NULL, lst);
break;
@@ -487,7 +491,7 @@ gboolean _mdns_browse(BonjourDnsSd *data) {
g_return_val_if_fail(idata != NULL, FALSE);
- idata->sb = avahi_service_browser_new(idata->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, LINK_LOCAL_RECORD_NAME, NULL, 0, _browser_callback, data->account);
+ idata->sb = avahi_service_browser_new(idata->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, LINK_LOCAL_RECORD_NAME, NULL, 0, _browser_callback, data->account);
if (!idata->sb) {
purple_debug_error("bonjour",
@@ -533,7 +537,7 @@ gboolean _mdns_set_buddy_icon_data(BonjourDnsSd *data, gconstpointer avatar_data
purple_account_get_username(data->account));
ret = avahi_entry_group_add_record(idata->buddy_icon_group, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_INET, flags, svc_name,
+ AVAHI_PROTO_UNSPEC, flags, svc_name,
AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 120, avatar_data, avatar_len);
g_free(svc_name);
@@ -622,7 +626,7 @@ void _mdns_retrieve_buddy_icon(BonjourBuddy* buddy) {
name = g_strdup_printf("%s." LINK_LOCAL_RECORD_NAME "local", buddy->name);
idata->buddy_icon_rec_browser = avahi_record_browser_new(session_idata->client, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_INET, name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 0,
+ AVAHI_PROTO_UNSPEC, name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_NULL, 0,
_buddy_icon_record_cb, buddy);
g_free(name);
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/irc/irc.c b/libpurple/protocols/irc/irc.c
index b60b2dd5ca..95ce70f601 100644
--- a/libpurple/protocols/irc/irc.c
+++ b/libpurple/protocols/irc/irc.c
@@ -944,7 +944,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static gboolean load_plugin (PurplePlugin *plugin) {
diff --git a/libpurple/protocols/jabber/Makefile.mingw b/libpurple/protocols/jabber/Makefile.mingw
index c0f5c62e81..c648d42fd4 100644
--- a/libpurple/protocols/jabber/Makefile.mingw
+++ b/libpurple/protocols/jabber/Makefile.mingw
@@ -29,7 +29,7 @@ INCLUDE_PATHS += -I. \
-I$(GTK_TOP)/include \
-I$(GTK_TOP)/include/glib-2.0 \
-I$(GTK_TOP)/lib/glib-2.0/include \
- -I$(LIBXML2_TOP)/include \
+ -I$(LIBXML2_TOP)/include/libxml2 \
-I$(PURPLE_TOP) \
-I$(PURPLE_TOP)/win32 \
-I$(PIDGIN_TREE_TOP)
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
index 13791995d9..0bdf8dd6bb 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"
@@ -69,6 +70,8 @@
#include "jingle/jingle.h"
#include "jingle/rtp.h"
+#define PING_TIMEOUT 60
+
GList *jabber_features = NULL;
GList *jabber_identities = NULL;
static GSList *jabber_cmds = NULL;
@@ -520,9 +523,12 @@ static gboolean jabber_keepalive_timeout(PurpleConnection *gc)
void jabber_keepalive(PurpleConnection *gc)
{
- JabberStream *js = gc->proto_data;
+ JabberStream *js = purple_connection_get_protocol_data(gc);
+ time_t now = time(NULL);
+
+ if (js->keepalive_timeout == 0 && (now - js->last_ping) >= PING_TIMEOUT) {
+ js->last_ping = now;
- if (js->keepalive_timeout == 0) {
jabber_keepalive_ping(js);
js->keepalive_timeout = purple_timeout_add_seconds(120,
(GSourceFunc)(jabber_keepalive_timeout), gc);
@@ -2062,18 +2068,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 +2153,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 +2177,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 +2193,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 +2209,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 +2222,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 +2234,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 +2248,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/jabber.h b/libpurple/protocols/jabber/jabber.h
index 75d0f2107d..882cf02438 100644
--- a/libpurple/protocols/jabber/jabber.h
+++ b/libpurple/protocols/jabber/jabber.h
@@ -166,6 +166,11 @@ struct _JabberStream
time_t idle;
time_t old_idle;
+ /** When we last pinged the server, so we don't ping more
+ * often than once every minute.
+ */
+ time_t last_ping;
+
JabberID *user;
JabberBuddy *user_jb;
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..b3dd448e1e 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);
@@ -237,13 +239,14 @@ void jabber_mood_init_action(GList **m) {
void jabber_mood_set(JabberStream *js, const char *mood, const char *text) {
xmlnode *publish, *moodnode;
- g_return_if_fail(mood != NULL);
-
publish = xmlnode_new("publish");
xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/mood");
moodnode = xmlnode_new_child(xmlnode_new_child(publish, "item"), "mood");
xmlnode_set_namespace(moodnode, "http://jabber.org/protocol/mood");
- xmlnode_new_child(moodnode, mood);
+ if (mood) {
+ /* if mood is NULL, set an empty mood node, meaning: unset mood */
+ xmlnode_new_child(moodnode, mood);
+ }
if (text && text[0] != '\0') {
xmlnode *textnode = xmlnode_new_child(moodnode, "text");
@@ -254,3 +257,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/msn/msn.c b/libpurple/protocols/msn/msn.c
index d9f547f471..0d34e0c298 100644
--- a/libpurple/protocols/msn/msn.c
+++ b/libpurple/protocols/msn/msn.c
@@ -2732,7 +2732,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
msn_get_account_text_table, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
diff --git a/libpurple/protocols/msn/slp.c b/libpurple/protocols/msn/slp.c
index 37061ceac0..b55e48b8e1 100644
--- a/libpurple/protocols/msn/slp.c
+++ b/libpurple/protocols/msn/slp.c
@@ -308,8 +308,6 @@ find_valid_emoticon(PurpleAccount *account, const char *path)
return NULL;
}
-#define MAX_FILE_NAME_LEN 0x226
-
static void
got_sessionreq(MsnSlpCall *slpcall, const char *branch,
const char *euf_guid, const char *context)
@@ -382,7 +380,7 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
/* File Transfer */
PurpleAccount *account;
PurpleXfer *xfer;
- char *bin;
+ MsnFileContext *header;
gsize bin_len;
guint32 file_size;
char *file_name;
@@ -396,15 +394,17 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
slpcall->slplink->remote_user);
- if (xfer)
- {
- bin = (char *)purple_base64_decode(context, &bin_len);
- file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8));
- file_name = g_convert(bin + 20, MAX_FILE_NAME_LEN, "UTF-8", "UTF-16LE",
- NULL, NULL, NULL);
+ header = (MsnFileContext *)purple_base64_decode(context, &bin_len);
+ if (bin_len >= sizeof(MsnFileContext) - 1 &&
+ (header->version == 2 ||
+ (header->version == 3 && header->length == sizeof(MsnFileContext) + 63))) {
+ file_size = GUINT64_FROM_LE(header->file_size);
- g_free(bin);
+ file_name = g_convert((const gchar *)&header->file_name,
+ MAX_FILE_NAME_LEN * 2,
+ "UTF-8", "UTF-16LE",
+ NULL, NULL, NULL);
purple_xfer_set_filename(xfer, file_name ? file_name : "");
g_free(file_name);
@@ -424,6 +424,7 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
purple_xfer_request(xfer);
}
+ g_free(header);
accepted = TRUE;
diff --git a/libpurple/protocols/msn/slp.h b/libpurple/protocols/msn/slp.h
index 2b7ef672e8..a340fbe6c7 100644
--- a/libpurple/protocols/msn/slp.h
+++ b/libpurple/protocols/msn/slp.h
@@ -30,6 +30,25 @@
#include "session.h"
#include "slpcall.h"
+#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
+
+/**
+ * The context data for a file transfer request
+ */
+#pragma pack(push,1) /* Couldn't they have made it the right size? */
+typedef struct
+{
+ guint32 length; /*< Length of header */
+ guint32 version; /*< MSN version */
+ guint64 file_size; /*< Size of file */
+ guint32 type; /*< Transfer type */
+ gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
+ gchar unknown1[30]; /*< Used somehow for background sharing */
+ guint32 unknown2; /*< Possibly for background sharing as well */
+ gchar preview[1]; /*< File preview data, 96x96 PNG */
+} MsnFileContext;
+#pragma pack(pop)
+
MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink,
const char *body);
diff --git a/libpurple/protocols/msn/slplink.c b/libpurple/protocols/msn/slplink.c
index 640943fb91..c00db15d0d 100644
--- a/libpurple/protocols/msn/slplink.c
+++ b/libpurple/protocols/msn/slplink.c
@@ -658,74 +658,51 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
}
}
-typedef struct
-{
- guint32 length;
- guint32 unk1;
- guint32 file_size;
- guint32 unk2;
- guint32 unk3;
-} MsnContextHeader;
-
-#define MAX_FILE_NAME_LEN 0x226
-
static gchar *
gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
{
gsize size = 0;
- MsnContextHeader header;
+ MsnFileContext header;
gchar *u8 = NULL;
- guchar *base;
- guchar *n;
gchar *ret;
gunichar2 *uni = NULL;
glong currentChar = 0;
- glong uni_len = 0;
- gsize len;
+ glong len = 0;
size = purple_xfer_get_size(xfer);
- if(!file_name) {
+ if (!file_name) {
gchar *basename = g_path_get_basename(file_path);
u8 = purple_utf8_try_convert(basename);
g_free(basename);
file_name = u8;
}
- uni = g_utf8_to_utf16(file_name, -1, NULL, &uni_len, NULL);
+ uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL);
- if(u8) {
+ if (u8) {
g_free(u8);
file_name = NULL;
u8 = NULL;
}
- len = sizeof(MsnContextHeader) + MAX_FILE_NAME_LEN + 4;
-
- header.length = GUINT32_TO_LE(len);
- header.unk1 = GUINT32_TO_LE(2);
- header.file_size = GUINT32_TO_LE(size);
- header.unk2 = GUINT32_TO_LE(0);
- header.unk3 = GUINT32_TO_LE(0);
-
- base = g_malloc(len + 1);
- n = base;
-
- memcpy(n, &header, sizeof(MsnContextHeader));
- n += sizeof(MsnContextHeader);
+ header.length = GUINT32_TO_LE(sizeof(MsnFileContext) - 1);
+ header.version = GUINT32_TO_LE(2); /* V.3 contains additional unnecessary data */
+ header.file_size = GUINT64_TO_LE(size);
+ header.type = GUINT32_TO_LE(1); /* No file preview */
- memset(n, 0x00, MAX_FILE_NAME_LEN);
- for(currentChar = 0; currentChar < uni_len; currentChar++) {
- *((gunichar2 *)n + currentChar) = GUINT16_TO_LE(uni[currentChar]);
+ len = MIN(len, MAX_FILE_NAME_LEN);
+ for (currentChar = 0; currentChar < len; currentChar++) {
+ header.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
}
- n += MAX_FILE_NAME_LEN;
+ memset(&header.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
- memset(n, 0xFF, 4);
- n += 4;
+ memset(&header.unknown1, 0, sizeof(header.unknown1));
+ header.unknown2 = GUINT32_TO_LE(0xffffffff);
+ header.preview[0] = '\0';
g_free(uni);
- ret = purple_base64_encode(base, len);
- g_free(base);
+ ret = purple_base64_encode((const guchar *)&header, sizeof(MsnFileContext));
return ret;
}
diff --git a/libpurple/protocols/mxit/mxit.c b/libpurple/protocols/mxit/mxit.c
index 67df55fe61..ee8eb8a9d2 100644
--- a/libpurple/protocols/mxit/mxit.c
+++ b/libpurple/protocols/mxit/mxit.c
@@ -633,8 +633,9 @@ static PurplePluginProtocolInfo proto_info = {
NULL, /* attention_types */
sizeof( PurplePluginProtocolInfo ), /* struct_size */
mxit_get_text_table, /* get_account_text_table */
- NULL,
- NULL
+ NULL, /* initiate_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
diff --git a/libpurple/protocols/myspace/myspace.c b/libpurple/protocols/myspace/myspace.c
index 943614d1ad..de136be226 100644
--- a/libpurple/protocols/myspace/myspace.c
+++ b/libpurple/protocols/myspace/myspace.c
@@ -3093,7 +3093,8 @@ static PurplePluginProtocolInfo prpl_info = {
sizeof(PurplePluginProtocolInfo), /* struct_size */
msim_get_account_text_table, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
/**
diff --git a/libpurple/protocols/novell/novell.c b/libpurple/protocols/novell/novell.c
index d6090ccc66..5cbb667bdb 100644
--- a/libpurple/protocols/novell/novell.c
+++ b/libpurple/protocols/novell/novell.c
@@ -3529,7 +3529,8 @@ static PurplePluginProtocolInfo prpl_info = {
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info = {
diff --git a/libpurple/protocols/oscar/clientlogin.c b/libpurple/protocols/oscar/clientlogin.c
index cd3a7c39e2..1ae6bc686a 100644
--- a/libpurple/protocols/oscar/clientlogin.c
+++ b/libpurple/protocols/oscar/clientlogin.c
@@ -43,7 +43,7 @@
#include "core.h"
#define URL_CLIENT_LOGIN "https://api.screenname.aol.com/auth/clientLogin"
-#define URL_START_OSCAR_SESSION "http://api.oscar.aol.com/aim/startOSCARSession"
+#define URL_START_OSCAR_SESSION "https://api.oscar.aol.com/aim/startOSCARSession"
/*
* Using clientLogin requires a developer ID. This key is for libpurple.
@@ -177,10 +177,23 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
code = atoi(tmp);
if (code != 200)
{
+ xmlnode *status_detail_node;
+ guint status_detail = 0;
+
+ status_detail_node = xmlnode_get_child(response_node,
+ "statusDetailCode");
+ if (status_detail_node) {
+ gchar *data = xmlnode_get_data(status_detail_node);
+ if (data) {
+ status_detail = atoi(data);
+ g_free(data);
+ }
+ }
+
purple_debug_error("oscar", "startOSCARSession response statusCode "
"was %s: %s\n", tmp, response);
- if (code == 401 || code == 607)
+ if ((code == 401 && status_detail != 1014) || code == 607)
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("You have been connecting and disconnecting too "
@@ -293,7 +306,11 @@ static void start_oscar_session_cb(PurpleUtilFetchUrlData *url_data, gpointer us
static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
{
char *query_string, *signature, *url;
- gboolean use_tls = purple_account_get_bool(purple_connection_get_account(od->gc), "use_ssl", OSCAR_DEFAULT_USE_SSL);
+ PurpleAccount *account;
+ gboolean use_tls;
+
+ account = purple_connection_get_account(od->gc);
+ use_tls = purple_account_get_bool(account, "use_ssl", OSCAR_DEFAULT_USE_SSL);
/*
* Construct the GET parameters. 0x00000611 is the distid given to
@@ -317,7 +334,8 @@ static void send_start_oscar_session(OscarData *od, const char *token, const cha
g_free(signature);
/* Make the request */
- od->url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE,
+ od->url_data = purple_util_fetch_url_request_len_with_account(account,
+ url, TRUE, NULL, FALSE, NULL, FALSE, -1,
start_oscar_session_cb, od);
g_free(url);
}
@@ -573,8 +591,9 @@ void send_client_login(OscarData *od, const char *username)
g_string_free(body, TRUE);
/* Send the POST request */
- od->url_data = purple_util_fetch_url_request(URL_CLIENT_LOGIN,
- TRUE, NULL, FALSE, request->str, FALSE,
+ od->url_data = purple_util_fetch_url_request_len_with_account(
+ purple_connection_get_account(gc), URL_CLIENT_LOGIN,
+ TRUE, NULL, FALSE, request->str, FALSE, -1,
client_login_cb, od);
g_string_free(request, TRUE);
}
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/flap_connection.c b/libpurple/protocols/oscar/flap_connection.c
index cf52edc4c5..3255e0f37a 100644
--- a/libpurple/protocols/oscar/flap_connection.c
+++ b/libpurple/protocols/oscar/flap_connection.c
@@ -364,6 +364,12 @@ flap_connection_close(OscarData *od, FlapConnection *conn)
conn->connect_data = NULL;
}
+ if (conn->gsc != NULL && conn->gsc->connect_data != NULL)
+ {
+ purple_ssl_close(conn->gsc);
+ conn->gsc = NULL;
+ }
+
if (conn->new_conn_data != NULL)
{
if (conn->type == SNAC_FAMILY_CHAT)
diff --git a/libpurple/protocols/oscar/libaim.c b/libpurple/protocols/oscar/libaim.c
index 6364a325be..7d62d94549 100644
--- a/libpurple/protocols/oscar/libaim.c
+++ b/libpurple/protocols/oscar/libaim.c
@@ -97,7 +97,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
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..d72c4d408f 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};
@@ -672,7 +677,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 +708,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 +793,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 +980,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 +2269,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 +2591,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 +2623,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 +2722,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 +3323,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. "
@@ -4848,6 +4944,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 +5115,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 +6073,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 +6148,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 +6381,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 +6437,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 +6475,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 +6654,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 +6720,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..7328ea1e08 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;
/*
@@ -572,6 +576,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 +1022,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 +1155,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 +1487,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/qq/qq.c b/libpurple/protocols/qq/qq.c
index 72d28a0e82..87e88d9329 100644
--- a/libpurple/protocols/qq/qq.c
+++ b/libpurple/protocols/qq/qq.c
@@ -1037,7 +1037,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info = {
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/silc/silc.c b/libpurple/protocols/silc/silc.c
index fe75fe3a02..2262106040 100644
--- a/libpurple/protocols/silc/silc.c
+++ b/libpurple/protocols/silc/silc.c
@@ -2116,7 +2116,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
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/protocols/simple/simple.c b/libpurple/protocols/simple/simple.c
index b3dabdd452..34e72854e4 100644
--- a/libpurple/protocols/simple/simple.c
+++ b/libpurple/protocols/simple/simple.c
@@ -2086,7 +2086,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
diff --git a/libpurple/protocols/yahoo/libyahoo.c b/libpurple/protocols/yahoo/libyahoo.c
index bd580eea4f..bf6c6861d5 100644
--- a/libpurple/protocols/yahoo/libyahoo.c
+++ b/libpurple/protocols/yahoo/libyahoo.c
@@ -264,7 +264,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
yahoo_get_account_text_table, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
diff --git a/libpurple/protocols/yahoo/libyahoojp.c b/libpurple/protocols/yahoo/libyahoojp.c
index d15001ea32..1f45e43b1b 100644
--- a/libpurple/protocols/yahoo/libyahoojp.c
+++ b/libpurple/protocols/yahoo/libyahoojp.c
@@ -160,7 +160,8 @@ static PurplePluginProtocolInfo prpl_info =
sizeof(PurplePluginProtocolInfo), /* struct_size */
yahoojp_get_account_text_table, /* get_account_text_table */
NULL, /* initiate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info =
diff --git a/libpurple/protocols/zephyr/zephyr.c b/libpurple/protocols/zephyr/zephyr.c
index b3089625ba..2168191b1b 100644
--- a/libpurple/protocols/zephyr/zephyr.c
+++ b/libpurple/protocols/zephyr/zephyr.c
@@ -2908,7 +2908,8 @@ static PurplePluginProtocolInfo prpl_info = {
sizeof(PurplePluginProtocolInfo), /* struct_size */
NULL, /* get_account_text_table */
NULL, /* initate_media */
- NULL /* can_do_media */
+ NULL, /* get_media_caps */
+ NULL /* get_moods */
};
static PurplePluginInfo info = {
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 48a641f168..2559110537 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 a06f3ec85b..ea6fa932b1 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;
@@ -961,11 +962,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.
@@ -1023,6 +1037,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/libpurple/win32/global.mak b/libpurple/win32/global.mak
index 66e33423d5..ef2505948c 100644
--- a/libpurple/win32/global.mak
+++ b/libpurple/win32/global.mak
@@ -15,7 +15,7 @@ GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.11-daa1
GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0-2.14
GTK_BIN ?= $(GTK_TOP)/bin
BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
-LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.6.30
+LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.7.4
MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa2
NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4
NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.11.4
diff --git a/libpurple/win32/libc_interface.c b/libpurple/win32/libc_interface.c
index 5307a42613..fb3809afcb 100644
--- a/libpurple/win32/libc_interface.c
+++ b/libpurple/win32/libc_interface.c
@@ -33,6 +33,7 @@
#include "libc_internal.h"
#include <glib/gstdio.h>
+/** This is redefined here because we can't include internal.h */
#ifdef ENABLE_NLS
# include <locale.h>
# include <libintl.h>
@@ -1047,29 +1048,12 @@ wpurple_get_timezone_abbreviation(const struct tm *tm)
return "";
}
+int wpurple_g_access (const gchar *filename, int mode);
/**
- * g_access:
- * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
- * @mode: as in access()
- *
- * A wrapper for the POSIX access() function. This function is used to
- * test a pathname for one or several of read, write or execute
- * permissions, or just existence. On Windows, the underlying access()
- * function in the C library only checks the READONLY attribute, and
- * does not look at the ACL at all. Software that needs to handle file
- * permissions on Windows more exactly should use the Win32 API.
- *
- * See the C library manual for more details about access().
- *
- * Returns: zero if the pathname refers to an existing file system
- * object that has all the tested permissions, or -1 otherwise or on
- * error.
- *
- * Since: 2.8
+ * @deprecated - remove for 3.0.0
*/
int
-wpurple_g_access (const gchar *filename,
- int mode)
+wpurple_g_access (const gchar *filename, int mode)
{
return g_access(filename, mode);
}
diff --git a/libpurple/win32/libc_interface.h b/libpurple/win32/libc_interface.h
index de9811a8c4..cc7acc1d72 100644
--- a/libpurple/win32/libc_interface.h
+++ b/libpurple/win32/libc_interface.h
@@ -129,19 +129,14 @@ wpurple_gethostname( name, size )
wpurple_gettimeofday( timeval, timezone )
/* stdio.h */
+#undef snprintf
#define snprintf _snprintf
+#undef vsnprintf
#define vsnprintf _vsnprintf
#define rename( oldname, newname ) \
wpurple_rename( oldname, newname )
-#ifdef g_rename
-# undef g_rename
-#endif
-/* This is necessary because we want rename on win32 to be able to overwrite an existing file, it is done in internal.h if GLib < 2.6*/
-#define g_rename(oldname, newname) \
-wpurple_rename(oldname, newname)
-
/* sys/stat.h */
#define fchmod(a,b)
diff --git a/pidgin/Makefile.am b/pidgin/Makefile.am
index 3c0289bad9..f6c938a64d 100644
--- a/pidgin/Makefile.am
+++ b/pidgin/Makefile.am
@@ -89,7 +89,6 @@ pidgin_SOURCES = \
gtkdnd-hints.c \
gtkdocklet.c \
gtkdocklet-gtk.c \
- gtkdocklet-x11.c \
gtkeventloop.c \
gtkft.c \
gtkicon-theme.c \
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
index 340cb74163..9e9f89380b 100644
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -2660,39 +2660,30 @@ static void pidgin_blist_drag_data_rcv_cb(GtkWidget *widget, GdkDragContext *dc,
/* Altered from do_colorshift in gnome-panel */
static void
-do_alphashift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
+do_alphashift(GdkPixbuf *pixbuf, int shift)
{
gint i, j;
- gint width, height, has_alpha, srcrowstride, destrowstride;
- guchar *target_pixels;
- guchar *original_pixels;
- guchar *pixsrc;
- guchar *pixdest;
+ gint width, height, padding;
+ guchar *pixels;
int val;
- guchar a;
- has_alpha = gdk_pixbuf_get_has_alpha (src);
- if (!has_alpha)
+ if (!gdk_pixbuf_get_has_alpha(pixbuf))
return;
- width = gdk_pixbuf_get_width (src);
- height = gdk_pixbuf_get_height (src);
- srcrowstride = gdk_pixbuf_get_rowstride (src);
- destrowstride = gdk_pixbuf_get_rowstride (dest);
- target_pixels = gdk_pixbuf_get_pixels (dest);
- original_pixels = gdk_pixbuf_get_pixels (src);
+ width = gdk_pixbuf_get_width(pixbuf);
+ height = gdk_pixbuf_get_height(pixbuf);
+ padding = gdk_pixbuf_get_rowstride(pixbuf) - width * 4;
+ pixels = gdk_pixbuf_get_pixels(pixbuf);
for (i = 0; i < height; i++) {
- pixdest = target_pixels + i*destrowstride;
- pixsrc = original_pixels + i*srcrowstride;
for (j = 0; j < width; j++) {
- *(pixdest++) = *(pixsrc++);
- *(pixdest++) = *(pixsrc++);
- *(pixdest++) = *(pixsrc++);
- a = *(pixsrc++);
- val = a - shift;
- *(pixdest++) = CLAMP(val, 0, 255);
+ pixels++;
+ pixels++;
+ pixels++;
+ val = *pixels - shift;
+ *(pixels++) = CLAMP(val, 0, 255);
}
+ pixels += padding;
}
}
@@ -3667,7 +3658,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 +3754,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 +3783,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 +3796,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 +3819,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 +3845,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 +3858,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);
@@ -6328,7 +6358,7 @@ static void buddy_node(PurpleBuddy *buddy, GtkTreeIter *iter, PurpleBlistNode *n
g_object_ref(G_OBJECT(gtkblist->empty_avatar));
avatar = gtkblist->empty_avatar;
} else if ((!PURPLE_BUDDY_IS_ONLINE(buddy) || purple_presence_is_idle(presence))) {
- do_alphashift(avatar, avatar, 77);
+ do_alphashift(avatar, 77);
}
emblem = pidgin_blist_get_emblem((PurpleBlistNode*) buddy);
@@ -7785,6 +7815,93 @@ 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_strequal(mood, "")) {
+ 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);
+
+ /* first item is an empty one for unsetting the mood */
+ purple_request_field_list_add(f, "", "");
+ if (purple_strequal(current_mood, ""))
+ purple_request_field_list_add_selected(f, "");
+
+ /* 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 +7981,7 @@ pidgin_blist_update_accounts_menu(void)
PurpleAccount *account = NULL;
GdkPixbuf *pixbuf = NULL;
PurplePlugin *plugin = NULL;
+ PurplePluginProtocolInfo *prpl_info;
account = accounts->data;
@@ -7903,8 +8021,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/gtkdebug.c b/pidgin/gtkdebug.c
index a8ef98bd82..075dfb48b3 100644
--- a/pidgin/gtkdebug.c
+++ b/pidgin/gtkdebug.c
@@ -250,11 +250,11 @@ clear_cb(GtkWidget *w, DebugWindow *win)
static void
pause_cb(GtkWidget *w, DebugWindow *win)
{
- win->paused = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+ win->paused = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w));
#ifdef HAVE_REGEX_H
if(!win->paused) {
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
regex_filter_all(win);
else
regex_show_all(win);
@@ -445,7 +445,7 @@ regex_compile(DebugWindow *win) {
/* we check if the filter is on in case it was only of the options that
* got changed, and not the expression.
*/
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
regex_filter_all(win);
}
@@ -459,9 +459,9 @@ regex_pref_filter_cb(const gchar *name, PurplePrefType type,
if(!win || !win->window)
return;
- current = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter));
+ current = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter));
if(active != current)
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), active);
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), active);
}
static void
@@ -483,7 +483,7 @@ regex_pref_invert_cb(const gchar *name, PurplePrefType type,
win->invert = active;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
regex_filter_all(win);
}
@@ -496,7 +496,7 @@ regex_pref_highlight_cb(const gchar *name, PurplePrefType type,
win->highlight = active;
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
regex_filter_all(win);
}
@@ -522,7 +522,7 @@ regex_row_changed_cb(GtkTreeModel *model, GtkTreePath *path,
gtk_tree_model_get(model, iter, 0, &text, 1, &level, -1);
if (level >= purple_prefs_get_int(PIDGIN_PREFS_ROOT "/debug/filterlevel")) {
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) {
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) {
regex_match(win, text);
} else {
gtk_imhtml_append_text(GTK_IMHTML(win->text), text, 0);
@@ -546,8 +546,8 @@ regex_timer_cb(DebugWindow *win) {
static void
regex_changed_cb(GtkWidget *w, DebugWindow *win) {
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter))) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter),
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter))) {
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter),
FALSE);
}
@@ -561,9 +561,9 @@ static void
regex_key_release_cb(GtkWidget *w, GdkEventKey *e, DebugWindow *win) {
if(e->keyval == GDK_Return &&
GTK_WIDGET_IS_SENSITIVE(win->filter) &&
- !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ !gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
{
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter), TRUE);
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter), TRUE);
}
}
@@ -588,10 +588,10 @@ regex_popup_cb(GtkEntry *entry, GtkWidget *menu, DebugWindow *win) {
}
static void
-regex_filter_toggled_cb(GtkToggleButton *button, DebugWindow *win) {
+regex_filter_toggled_cb(GtkToggleToolButton *button, DebugWindow *win) {
gboolean active;
- active = gtk_toggle_button_get_active(button);
+ active = gtk_toggle_tool_button_get_active(button);
purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/debug/filter", active);
@@ -611,7 +611,7 @@ filter_level_pref_changed(const char *name, PurplePrefType type, gconstpointer v
if (GPOINTER_TO_INT(value) != gtk_combo_box_get_active(GTK_COMBO_BOX(win->filterlevel)))
gtk_combo_box_set_active(GTK_COMBO_BOX(win->filterlevel), GPOINTER_TO_INT(value));
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win->filter)))
+ if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win->filter)))
regex_filter_all(win);
else
regex_show_all(win);
@@ -677,9 +677,12 @@ debug_window_new(void)
GtkWidget *vbox;
GtkWidget *toolbar;
GtkWidget *frame;
- GtkWidget *image;
gint width, height;
void *handle;
+ GtkToolItem *item;
+#if !GTK_CHECK_VERSION(2,12,0)
+ GtkTooltips *tooltips;
+#endif
win = g_new0(DebugWindow, 1);
@@ -720,7 +723,12 @@ debug_window_new(void)
if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/toolbar")) {
/* Setup our top button bar thingie. */
toolbar = gtk_toolbar_new();
+#if !GTK_CHECK_VERSION(2,12,0)
+ tooltips = gtk_tooltips_new();
+#endif
+#if !GTK_CHECK_VERSION(2,14,0)
gtk_toolbar_set_tooltips(GTK_TOOLBAR(toolbar), TRUE);
+#endif
gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), TRUE);
g_signal_connect(G_OBJECT(toolbar), "button-press-event", G_CALLBACK(toolbar_context), win);
@@ -735,61 +743,93 @@ debug_window_new(void)
#ifndef HAVE_REGEX_H
/* Find button */
- gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND,
- _("Find"), NULL, G_CALLBACK(find_cb),
- win, -1);
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_FIND);
+ gtk_tool_item_set_is_important(item, TRUE);
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_tool_item_set_tooltip_text(item, _("Find"));
+#else
+ gtk_tool_item_set_tooltip(item, tooltips, _("Find"), NULL);
+#endif
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(find_cb), win);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
#endif /* HAVE_REGEX_H */
/* Save */
- gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE,
- _("Save"), NULL, G_CALLBACK(save_cb),
- win, -1);
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
+ gtk_tool_item_set_is_important(item, TRUE);
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_tool_item_set_tooltip_text(item, _("Save"));
+#else
+ gtk_tool_item_set_tooltip(item, tooltips, _("Save"), NULL);
+#endif
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(save_cb), win);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
/* Clear button */
- gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR,
- _("Clear"), NULL, G_CALLBACK(clear_cb),
- win, -1);
+ item = gtk_tool_button_new_from_stock(GTK_STOCK_CLEAR);
+ gtk_tool_item_set_is_important(item, TRUE);
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_tool_item_set_tooltip_text(item, _("Clear"));
+#else
+ gtk_tool_item_set_tooltip(item, tooltips, _("Clear"), NULL);
+#endif
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(clear_cb), win);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
- gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+ item = gtk_separator_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
/* Pause */
- image = gtk_image_new_from_stock(PIDGIN_STOCK_PAUSE, GTK_ICON_SIZE_MENU);
- gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
- GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
- NULL, _("Pause"), _("Pause"),
- NULL, image,
- G_CALLBACK(pause_cb), win);
+ item = gtk_toggle_tool_button_new_from_stock(PIDGIN_STOCK_PAUSE);
+ gtk_tool_item_set_is_important(item, TRUE);
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_tool_item_set_tooltip_text(item, _("Pause"));
+#else
+ gtk_tool_item_set_tooltip(item, tooltips, _("Pause"), NULL);
+#endif
+ g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(pause_cb), win);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
#ifdef HAVE_REGEX_H
/* regex stuff */
- gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+ item = gtk_separator_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
/* regex toggle button */
- image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
- win->filter =
- gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
- GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
- NULL, _("Filter"), _("Filter"),
- NULL, image,
- G_CALLBACK(regex_filter_toggled_cb),
- win);
+ item = gtk_toggle_tool_button_new_from_stock(GTK_STOCK_FIND);
+ gtk_tool_item_set_is_important(item, TRUE);
+ win->filter = GTK_WIDGET(item);
+ gtk_tool_button_set_label(GTK_TOOL_BUTTON(win->filter), _("Filter"));
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(win->filter), _("Filter"));
+#else
+ gtk_tooltips_set_tip(tooltips, win->filter, _("Filter"), NULL);
+#endif
+ g_signal_connect(G_OBJECT(win->filter), "clicked", G_CALLBACK(regex_filter_toggled_cb), win);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(win->filter));
+
/* we purposely disable the toggle button here in case
* /purple/gtk/debug/expression has an empty string. If it does not have
* an empty string, the change signal will get called and make the
* toggle button sensitive.
*/
gtk_widget_set_sensitive(win->filter, FALSE);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->filter),
+ gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win->filter),
purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/filter"));
purple_prefs_connect_callback(handle, PIDGIN_PREFS_ROOT "/debug/filter",
regex_pref_filter_cb, win);
/* regex entry */
win->expression = gtk_entry_new();
- gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
- GTK_TOOLBAR_CHILD_WIDGET, win->expression,
- NULL, _("Right click for more options."),
- NULL, NULL, NULL, NULL);
+ item = gtk_tool_item_new();
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_widget_set_tooltip_text(win->expression, _("Right click for more options."));
+#else
+ gtk_tooltips_set_tip(tooltips, win->expression, _("Right click for more options."), NULL);
+#endif
+ gtk_container_add(GTK_CONTAINER(item), GTK_WIDGET(win->expression));
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+
/* this needs to be before the text is set from the pref if we want it
* to colorize a stored expression.
*/
@@ -815,18 +855,23 @@ debug_window_new(void)
#endif /* HAVE_REGEX_H */
- gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+ item = gtk_separator_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
- gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
- GTK_TOOLBAR_CHILD_WIDGET, gtk_label_new(_("Level ")),
- NULL, _("Select the debug filter level."),
- NULL, NULL, NULL, NULL);
+ item = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level ")));
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
win->filterlevel = gtk_combo_box_new_text();
- gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
- GTK_TOOLBAR_CHILD_WIDGET, win->filterlevel,
- NULL, _("Select the debug filter level."),
- NULL, NULL, NULL, NULL);
+ item = gtk_tool_item_new();
+#if GTK_CHECK_VERSION(2,12,0)
+ gtk_widget_set_tooltip_text(win->filterlevel, _("Select the debug filter level."));
+#else
+ gtk_tooltips_set_tip(tooltips, win->filterlevel, _("Select the debug filter level."), NULL);
+#endif
+ gtk_container_add(GTK_CONTAINER(item), win->filterlevel);
+ gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+
gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("All"));
gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Misc"));
gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Info"));
diff --git a/pidgin/gtkdocklet-gtk.c b/pidgin/gtkdocklet-gtk.c
index 0acf5b49f1..98beb64387 100644
--- a/pidgin/gtkdocklet-gtk.c
+++ b/pidgin/gtkdocklet-gtk.c
@@ -26,8 +26,6 @@
#include "pidginstock.h"
#include "gtkdocklet.h"
-#if GTK_CHECK_VERSION(2,10,0)
-
/* globals */
GtkStatusIcon *docklet = NULL;
@@ -155,6 +153,3 @@ docklet_ui_init(void)
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(),
DATADIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S "pidgin" G_DIR_SEPARATOR_S "tray");
}
-
-#endif /* GTK_CHECK_VERSION(2,10,0) */
-
diff --git a/pidgin/gtkdocklet-x11.c b/pidgin/gtkdocklet-x11.c
deleted file mode 100644
index 37660aca3f..0000000000
--- a/pidgin/gtkdocklet-x11.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * System tray icon (aka docklet) plugin for Purple
- *
- * Copyright (C) 2002-3 Robert McQueen <robot101@debian.org>
- * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com>
- * Inspired by a similar plugin by:
- * John (J5) Palmieri <johnp@martianrock.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02111-1301, USA.
- */
-
-#include "internal.h"
-#include "pidgin.h"
-#include "debug.h"
-#include "prefs.h"
-#include "pidginstock.h"
-
-#include "gtkdialogs.h"
-
-#include "eggtrayicon.h"
-#include "gtkdocklet.h"
-#include <gdk/gdkkeysyms.h>
-
-#if !GTK_CHECK_VERSION(2,10,0)
-
-#define SHORT_EMBED_TIMEOUT 5000
-#define LONG_EMBED_TIMEOUT 15000
-
-/* globals */
-static EggTrayIcon *docklet = NULL;
-static GtkWidget *image = NULL;
-static GtkTooltips *tooltips = NULL;
-static GdkPixbuf *blank_icon = NULL;
-static int embed_timeout = 0;
-static int docklet_height = 0;
-
-/* protos */
-static void docklet_x11_create(gboolean);
-
-static gboolean
-docklet_x11_recreate_cb(gpointer data)
-{
- docklet_x11_create(TRUE);
-
- return FALSE; /* for when we're called by the glib idle handler */
-}
-
-static void
-docklet_x11_embedded_cb(GtkWidget *widget, void *data)
-{
- purple_debug(PURPLE_DEBUG_INFO, "docklet", "X11 embedded\n");
-
- g_source_remove(embed_timeout);
- embed_timeout = 0;
- pidgin_docklet_embedded();
- purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded", FALSE);
-}
-
-static void
-docklet_x11_destroyed_cb(GtkWidget *widget, void *data)
-{
- purple_debug(PURPLE_DEBUG_INFO, "docklet", "X11 destroyed\n");
-
- pidgin_docklet_remove();
-
- g_object_unref(G_OBJECT(docklet));
- docklet = NULL;
-
- g_idle_add(docklet_x11_recreate_cb, NULL);
-}
-
-static gboolean
-docklet_x11_clicked_cb(GtkWidget *button, GdkEventButton *event, void *data)
-{
- if (event->type != GDK_BUTTON_PRESS)
- return FALSE;
-
- pidgin_docklet_clicked(event->button);
- return TRUE;
-}
-
-static gboolean
-docklet_x11_pressed_cb(GtkWidget *button, GdkEventKey *event)
-{
- guint state, keyval;
-
- state = event->state & gtk_accelerator_get_default_mod_mask();
- keyval = event->keyval;
- if (state == 0 &&
- (keyval == GDK_Return ||
- keyval == GDK_KP_Enter ||
- keyval == GDK_ISO_Enter ||
- keyval == GDK_space ||
- keyval == GDK_KP_Space))
- {
- pidgin_docklet_clicked(1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-docklet_x11_popup_cb(GtkWidget *button)
-{
- pidgin_docklet_clicked(3);
-}
-
-static void
-docklet_x11_update_icon(PurpleStatusPrimitive status, gboolean connecting, gboolean pending)
-{
- const gchar *icon_name = NULL;
-
- g_return_if_fail(image != NULL);
-
- switch (status) {
- case PURPLE_STATUS_OFFLINE:
- icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
- break;
- case PURPLE_STATUS_AWAY:
- icon_name = PIDGIN_STOCK_TRAY_AWAY;
- break;
- case PURPLE_STATUS_UNAVAILABLE:
- icon_name = PIDGIN_STOCK_TRAY_BUSY;
- break;
- case PURPLE_STATUS_EXTENDED_AWAY:
- icon_name = PIDGIN_STOCK_TRAY_XA;
- break;
- case PURPLE_STATUS_INVISIBLE:
- icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
- break;
- default:
- icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
- break;
- }
-
- if (pending)
- icon_name = PIDGIN_STOCK_TRAY_PENDING;
- if (connecting)
- icon_name = PIDGIN_STOCK_TRAY_CONNECT;
-
- if(icon_name) {
- int icon_size;
- if (docklet_height < 22)
- icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
- else if (docklet_height < 32)
- icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL);
- else if (docklet_height < 48)
- icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM);
- else
- icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE);
-
- gtk_image_set_from_stock(GTK_IMAGE(image), icon_name, icon_size);
- }
-}
-
-static void
-docklet_x11_resize_icon(GtkWidget *widget)
-{
- if (docklet_height == MIN(widget->allocation.height, widget->allocation.width))
- return;
- docklet_height = MIN(widget->allocation.height, widget->allocation.width);
- pidgin_docklet_update_icon();
-}
-
-static void
-docklet_x11_blank_icon(void)
-{
- if (!blank_icon) {
- GtkIconSize size = GTK_ICON_SIZE_LARGE_TOOLBAR;
- gint width, height;
- g_object_get(G_OBJECT(image), "icon-size", &size, NULL);
- gtk_icon_size_lookup(size, &width, &height);
- blank_icon = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
- gdk_pixbuf_fill(blank_icon, 0);
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(image), blank_icon);
-}
-
-static void
-docklet_x11_set_tooltip(gchar *tooltip)
-{
- if (!tooltips)
- tooltips = gtk_tooltips_new();
-
- /* image->parent is a GtkEventBox */
- if (tooltip) {
- gtk_tooltips_enable(tooltips);
- gtk_tooltips_set_tip(tooltips, image->parent, tooltip, NULL);
- } else {
- gtk_tooltips_set_tip(tooltips, image->parent, "", NULL);
- gtk_tooltips_disable(tooltips);
- }
-}
-
-static void
-docklet_x11_position_menu(GtkMenu *menu, int *x, int *y, gboolean *push_in,
- gpointer user_data)
-{
- GtkWidget *widget = GTK_WIDGET(docklet);
- GtkRequisition req;
- gint menu_xpos, menu_ypos;
-
- gtk_widget_size_request(GTK_WIDGET(menu), &req);
- gdk_window_get_origin(widget->window, &menu_xpos, &menu_ypos);
-
- menu_xpos += widget->allocation.x;
- menu_ypos += widget->allocation.y;
-
- if (menu_ypos > gdk_screen_get_height(gtk_widget_get_screen(widget)) / 2)
- menu_ypos -= req.height;
- else
- menu_ypos += widget->allocation.height;
-
- *x = menu_xpos;
- *y = menu_ypos;
-
- *push_in = TRUE;
-}
-
-static void
-docklet_x11_destroy(void)
-{
- g_return_if_fail(docklet != NULL);
-
- if (embed_timeout)
- g_source_remove(embed_timeout);
-
- pidgin_docklet_remove();
-
- g_signal_handlers_disconnect_by_func(G_OBJECT(docklet), G_CALLBACK(docklet_x11_destroyed_cb), NULL);
- gtk_widget_destroy(GTK_WIDGET(docklet));
-
- g_object_unref(G_OBJECT(docklet));
- docklet = NULL;
-
- if (blank_icon)
- g_object_unref(G_OBJECT(blank_icon));
- blank_icon = NULL;
-
- image = NULL;
-
- purple_debug(PURPLE_DEBUG_INFO, "docklet", "X11 destroyed\n");
-}
-
-static gboolean
-docklet_x11_embed_timeout_cb(gpointer data)
-{
- /* The docklet was not embedded within the timeout.
- * Remove it as a visibility manager, but leave the plugin
- * loaded so that it can embed automatically if/when a notification
- * area becomes available.
- */
- purple_debug_info("docklet", "X11 failed to embed within timeout\n");
- pidgin_docklet_remove();
-
- return FALSE;
-}
-
-static void
-docklet_x11_create(gboolean recreate)
-{
- GtkWidget *box;
-
- if (docklet) {
- /* if this is being called when a tray icon exists, it's because
- something messed up. try destroying it before we proceed,
- although docklet_refcount may be all hosed. hopefully won't happen. */
- purple_debug(PURPLE_DEBUG_WARNING, "docklet", "trying to create icon but it already exists?\n");
- docklet_x11_destroy();
- }
-
- docklet = egg_tray_icon_new(PIDGIN_NAME);
- box = gtk_event_box_new();
- image = gtk_image_new();
- GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS);
-
- g_signal_connect(G_OBJECT(docklet), "embedded", G_CALLBACK(docklet_x11_embedded_cb), NULL);
- g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(docklet_x11_destroyed_cb), NULL);
- g_signal_connect(G_OBJECT(docklet), "size-allocate", G_CALLBACK(docklet_x11_resize_icon), NULL);
- g_signal_connect(G_OBJECT(box), "button-press-event", G_CALLBACK(docklet_x11_clicked_cb), NULL);
- g_signal_connect(G_OBJECT(box), "key-press-event", G_CALLBACK(docklet_x11_pressed_cb), NULL);
- g_signal_connect(G_OBJECT(box), "popup-menu", G_CALLBACK(docklet_x11_popup_cb), NULL);
- gtk_container_add(GTK_CONTAINER(box), image);
- gtk_container_add(GTK_CONTAINER(docklet), box);
-
- if (!gtk_check_version(2,4,0))
- g_object_set(G_OBJECT(box), "visible-window", FALSE, NULL);
-
- gtk_widget_show_all(GTK_WIDGET(docklet));
-
- /* ref the docklet before we bandy it about the place */
- g_object_ref(G_OBJECT(docklet));
-
- /* This is a hack to avoid a race condition between the docklet getting
- * embedded in the notification area and the gtkblist restoring its
- * previous visibility state. If the docklet does not get embedded within
- * the timeout, it will be removed as a visibility manager until it does
- * get embedded. Ideally, we would only call docklet_embedded() when the
- * icon was actually embedded. This only happens when the docklet is first
- * created, not when being recreated.
- *
- * The x11 docklet tracks whether it successfully embedded in a pref and
- * allows for a longer timeout period if it successfully embedded the last
- * time it was run. This should hopefully solve problems with the buddy
- * list not properly starting hidden when Pidgin is started on login.
- */
- if(!recreate) {
- pidgin_docklet_embedded();
- if(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded")) {
- embed_timeout = g_timeout_add(LONG_EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL);
- } else {
- embed_timeout = g_timeout_add(SHORT_EMBED_TIMEOUT, docklet_x11_embed_timeout_cb, NULL);
- }
- }
-
- purple_debug(PURPLE_DEBUG_INFO, "docklet", "X11 created\n");
-}
-
-static void
-docklet_x11_create_ui_op(void)
-{
- docklet_x11_create(FALSE);
-}
-
-static struct docklet_ui_ops ui_ops =
-{
- docklet_x11_create_ui_op,
- docklet_x11_destroy,
- docklet_x11_update_icon,
- docklet_x11_blank_icon,
- docklet_x11_set_tooltip,
- docklet_x11_position_menu
-};
-
-void
-docklet_ui_init()
-{
- pidgin_docklet_set_ui_ops(&ui_ops);
- purple_prefs_add_none(PIDGIN_PREFS_ROOT "/docklet/x11");
- purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/docklet/x11/embedded", FALSE);
-}
-
-#endif /* !GTK_CHECK_VERSION(2,10,0) */
-
diff --git a/pidgin/gtkft.c b/pidgin/gtkft.c
index dc50a3c08c..5eb37600c4 100644
--- a/pidgin/gtkft.c
+++ b/pidgin/gtkft.c
@@ -578,7 +578,7 @@ setup_tree(PidginXferDialog *dialog)
/* Build the tree model */
/* Transfer type, Progress Bar, Filename, Size, Remaining */
- model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_DOUBLE,
+ model = gtk_list_store_new(NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_INT,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_POINTER);
dialog->model = model;
@@ -612,7 +612,7 @@ setup_tree(PidginXferDialog *dialog)
/* Progress bar column */
renderer = gtk_cell_renderer_progress_new();
column = gtk_tree_view_column_new_with_attributes(_("Progress"), renderer,
- "percentage", COLUMN_PROGRESS, NULL);
+ "value", COLUMN_PROGRESS, NULL);
gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
@@ -909,7 +909,7 @@ pidgin_xfer_dialog_add_xfer(PidginXferDialog *dialog, PurpleXfer *xfer)
lfilename = utf8;
gtk_list_store_set(dialog->model, &data->iter,
COLUMN_STATUS, pixbuf,
- COLUMN_PROGRESS, 0.0,
+ COLUMN_PROGRESS, 0,
COLUMN_FILENAME, (type == PURPLE_XFER_RECEIVE)
? purple_xfer_get_filename(xfer)
: lfilename,
@@ -1042,7 +1042,7 @@ pidgin_xfer_dialog_update_xfer(PidginXferDialog *dialog,
remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));
gtk_list_store_set(xfer_dialog->model, &data->iter,
- COLUMN_PROGRESS, purple_xfer_get_progress(xfer),
+ COLUMN_PROGRESS, (gint)(purple_xfer_get_progress(xfer) * 100),
COLUMN_SIZE, size_str,
COLUMN_REMAINING, remaining_str,
-1);
diff --git a/pidgin/gtkprefs.c b/pidgin/gtkprefs.c
index c2d3498426..bee1ee062a 100644
--- a/pidgin/gtkprefs.c
+++ b/pidgin/gtkprefs.c
@@ -902,9 +902,7 @@ prefs_build_theme_combo_box(GtkListStore *store, const char *current_theme, cons
cell_rend = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combo_box), cell_rend, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo_box), cell_rend, "markup", 1, NULL);
-#if GTK_CHECK_VERSION(2,6,0)
g_object_set(cell_rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-#endif
gtk_drag_dest_set(combo_box, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te,
sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE);
diff --git a/pidgin/gtkprivacy.c b/pidgin/gtkprivacy.c
index 518b03d508..369863f0dd 100644
--- a/pidgin/gtkprivacy.c
+++ b/pidgin/gtkprivacy.c
@@ -220,7 +220,7 @@ select_account_cb(GtkWidget *dropdown, PurpleAccount *account,
for (i = 0; i < menu_entry_count; i++) {
if (menu_entries[i].num == account->perm_deny) {
- gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), i);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), i);
break;
}
}
@@ -234,9 +234,9 @@ select_account_cb(GtkWidget *dropdown, PurpleAccount *account,
* Even better: the privacy API needs to not suck.
*/
static void
-type_changed_cb(GtkOptionMenu *optmenu, PidginPrivacyDialog *dialog)
+type_changed_cb(GtkComboBox *combo, PidginPrivacyDialog *dialog)
{
- int new_type = menu_entries[gtk_option_menu_get_history(optmenu)].num;
+ int new_type = menu_entries[gtk_combo_box_get_active(combo)].num;
dialog->account->perm_deny = new_type;
serv_set_permit_deny(purple_account_get_connection(dialog->account));
@@ -343,8 +343,7 @@ privacy_dialog_new(void)
GtkWidget *button;
GtkWidget *dropdown;
GtkWidget *label;
- GtkWidget *menu;
- int selected = 0;
+ int selected = -1;
int i;
dialog = g_new0(PidginPrivacyDialog, 1);
@@ -372,22 +371,19 @@ privacy_dialog_new(void)
dialog->account = pidgin_account_option_menu_get_selected(dropdown);
/* Add the drop-down list with the allow/block types. */
- dialog->type_menu = gtk_option_menu_new();
+ dialog->type_menu = gtk_combo_box_new_text();
gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0);
gtk_widget_show(dialog->type_menu);
- /* Build the menu for that. */
- menu = gtk_menu_new();
-
for (i = 0; i < menu_entry_count; i++) {
- pidgin_new_item(menu, _(menu_entries[i].text));
+ gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->type_menu),
+ _(menu_entries[i].text));
if (menu_entries[i].num == dialog->account->perm_deny)
selected = i;
}
- gtk_option_menu_set_menu(GTK_OPTION_MENU(dialog->type_menu), menu);
- gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), selected);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), selected);
g_signal_connect(G_OBJECT(dialog->type_menu), "changed",
G_CALLBACK(type_changed_cb), dialog);
@@ -421,7 +417,7 @@ privacy_dialog_new(void)
button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_CLOSE, G_CALLBACK(close_cb), dialog);
dialog->close_button = button;
- type_changed_cb(GTK_OPTION_MENU(dialog->type_menu), dialog);
+ type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog);
#if 0
if (dialog->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) {
gtk_widget_show(dialog->allow_widget);
diff --git a/pidgin/gtkrequest.c b/pidgin/gtkrequest.c
index e650d81d09..9848d7dc4b 100644
--- a/pidgin/gtkrequest.c
+++ b/pidgin/gtkrequest.c
@@ -231,10 +231,10 @@ field_bool_cb(GtkToggleButton *button, PurpleRequestField *field)
}
static void
-field_choice_menu_cb(GtkOptionMenu *menu, PurpleRequestField *field)
+field_choice_menu_cb(GtkComboBox *menu, PurpleRequestField *field)
{
purple_request_field_choice_set_value(field,
- gtk_option_menu_get_history(menu));
+ gtk_combo_box_get_active(menu));
}
static void
@@ -958,26 +958,15 @@ create_choice_field(PurpleRequestField *field)
if (num_labels > 5)
{
- GtkWidget *menu;
- GtkWidget *item;
-
- widget = gtk_option_menu_new();
-
- menu = gtk_menu_new();
+ widget = gtk_combo_box_new_text();
for (l = labels; l != NULL; l = l->next)
{
const char *text = l->data;
-
- item = gtk_menu_item_new_with_label(text);
- gtk_widget_show(item);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(widget), text);
}
- gtk_widget_show(menu);
- gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu);
- gtk_option_menu_set_history(GTK_OPTION_MENU(widget),
+ gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
purple_request_field_choice_get_default_value(field));
g_signal_connect(G_OBJECT(widget), "changed",
@@ -1094,6 +1083,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);
@@ -1105,7 +1097,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));
@@ -1124,13 +1119,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..6601748a05 100644
--- a/pidgin/gtksavedstatuses.c
+++ b/pidgin/gtksavedstatuses.c
@@ -85,17 +85,16 @@ enum
};
/**
- * These are used in the GtkComboBox to select the specific
- * PurpleStatusType when setting a substatus for a particular saved
- * status.
+ * These are used in the GtkComboBox to select the specific PurpleStatusType
+ * when setting a (sub)status for a particular saved status.
*/
enum
{
- SUBSTATUS_COLUMN_ICON,
+ STATUS_COLUMN_ICON,
/** A hidden column containing the ID of this PurpleStatusType. */
- SUBSTATUS_COLUMN_STATUS_ID,
- SUBSTATUS_COLUMN_STATUS_NAME,
- SUBSTATUS_NUM_COLUMNS
+ STATUS_COLUMN_STATUS_ID,
+ STATUS_COLUMN_STATUS_NAME,
+ STATUS_NUM_COLUMNS
};
typedef struct
@@ -118,7 +117,7 @@ typedef struct
gchar *original_title;
GtkEntry *title;
- GtkOptionMenu *type;
+ GtkComboBox *type;
GtkIMHtml *message;
} StatusEditor;
@@ -742,7 +741,7 @@ status_editor_ok_cb(GtkButton *button, gpointer user_data)
return;
}
- type = gtk_option_menu_get_history(dialog->type) + (PURPLE_STATUS_UNSET + 1);
+ type = gtk_combo_box_get_active(dialog->type) + (PURPLE_STATUS_UNSET + 1);
message = gtk_imhtml_get_markup(dialog->message);
unformatted = purple_markup_strip_html(message);
@@ -837,53 +836,56 @@ editor_title_changed_cb(GtkWidget *widget, gpointer user_data)
}
static GtkWidget *
-create_stock_item(const gchar *str, const gchar *icon)
-{
- GtkWidget *menuitem = gtk_menu_item_new();
- GtkWidget *label = gtk_label_new_with_mnemonic(str);
- GtkWidget *hbox = gtk_hbox_new(FALSE, 4);
- GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
- GtkWidget *image = gtk_image_new_from_stock(icon, icon_size);;
-
- gtk_widget_show(label);
- gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-
- gtk_container_add(GTK_CONTAINER(menuitem), hbox);
-
- return menuitem;
-}
-
-static GtkWidget *
create_status_type_menu(PurpleStatusPrimitive type)
{
int i;
GtkWidget *dropdown;
- GtkWidget *menu;
- GtkWidget *item;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
- dropdown = gtk_option_menu_new();
- menu = gtk_menu_new();
+ store = gtk_list_store_new(STATUS_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
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.
*/
continue;
- item = create_stock_item(purple_primitive_get_name_from_type(i),
- get_stock_icon_from_primitive(i));
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+ gtk_list_store_append(store, &iter);
+ gtk_list_store_set(store, &iter,
+ STATUS_COLUMN_ICON, get_stock_icon_from_primitive(i),
+ STATUS_COLUMN_STATUS_ID, purple_primitive_get_id_from_type(i),
+ STATUS_COLUMN_STATUS_NAME, purple_primitive_get_name_from_type(i),
+ -1);
}
- gtk_menu_set_active(GTK_MENU(menu), type - (PURPLE_STATUS_UNSET + 1));
- gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu);
- gtk_widget_show_all(menu);
+ dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, FALSE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
+ "stock-id", STATUS_COLUMN_ICON,
+ NULL);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
+ gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
+ "text", STATUS_COLUMN_STATUS_NAME,
+ NULL);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown),
+ type - (PURPLE_STATUS_UNSET + 1));
return dropdown;
}
@@ -1153,7 +1155,7 @@ pidgin_status_editor_show(gboolean edit, PurpleSavedStatus *saved_status)
dropdown = create_status_type_menu(purple_savedstatus_get_type(saved_status));
else
dropdown = create_status_type_menu(PURPLE_STATUS_AWAY);
- dialog->type = GTK_OPTION_MENU(dropdown);
+ dialog->type = GTK_COMBO_BOX(dropdown);
pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL);
/* Status message */
@@ -1268,7 +1270,7 @@ substatus_selection_changed_cb(GtkComboBox *box, gpointer user_data)
if (!gtk_combo_box_get_active_iter(box, &iter))
return;
gtk_tree_model_get(GTK_TREE_MODEL(select->model), &iter,
- SUBSTATUS_COLUMN_STATUS_ID, &id,
+ STATUS_COLUMN_STATUS_ID, &id,
-1);
type = purple_account_get_status_type(select->account, id);
g_free(id);
@@ -1359,7 +1361,7 @@ substatus_editor_ok_cb(GtkButton *button, gpointer user_data)
}
gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
- SUBSTATUS_COLUMN_STATUS_ID, &id,
+ STATUS_COLUMN_STATUS_ID, &id,
-1);
type = purple_account_get_status_type(dialog->account, id);
if (purple_status_type_get_attr(type, "message") != NULL)
@@ -1449,7 +1451,7 @@ edit_substatus(StatusEditor *status_editor, PurpleAccount *account)
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget(sg, label);
- dialog->model = gtk_list_store_new(SUBSTATUS_NUM_COLUMNS,
+ dialog->model = gtk_list_store_new(STATUS_NUM_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
@@ -1462,12 +1464,12 @@ edit_substatus(StatusEditor *status_editor, PurpleAccount *account)
NULL);
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, FALSE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend,
- "stock-id", SUBSTATUS_COLUMN_ICON, NULL);
+ "stock-id", STATUS_COLUMN_ICON, NULL);
rend = GTK_CELL_RENDERER(gtk_cell_renderer_text_new());
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), rend, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), rend,
- "text", SUBSTATUS_COLUMN_STATUS_NAME, NULL);
+ "text", STATUS_COLUMN_STATUS_NAME, NULL);
g_signal_connect(G_OBJECT(combo), "changed",
G_CALLBACK(substatus_selection_changed_cb), dialog);
@@ -1543,9 +1545,9 @@ edit_substatus(StatusEditor *status_editor, PurpleAccount *account)
gtk_list_store_append(dialog->model, &iter);
gtk_list_store_set(dialog->model, &iter,
- SUBSTATUS_COLUMN_ICON, pidgin_stock_id_from_status_primitive(prim),
- SUBSTATUS_COLUMN_STATUS_ID, id,
- SUBSTATUS_COLUMN_STATUS_NAME, name,
+ STATUS_COLUMN_ICON, pidgin_stock_id_from_status_primitive(prim),
+ STATUS_COLUMN_STATUS_ID, id,
+ STATUS_COLUMN_STATUS_NAME, name,
-1);
if ((status_id != NULL) && !strcmp(status_id, id))
{
diff --git a/pidgin/gtkutils.c b/pidgin/gtkutils.c
index fedb3e1b4a..a7744243ca 100644
--- a/pidgin/gtkutils.c
+++ b/pidgin/gtkutils.c
@@ -406,13 +406,13 @@ pidgin_pixbuf_button_from_stock(const char *text, const char *icon,
gtk_container_add(GTK_CONTAINER(button), bbox);
if (icon) {
- gtk_box_pack_start_defaults(GTK_BOX(bbox), ibox);
+ gtk_box_pack_start(GTK_BOX(bbox), ibox, TRUE, TRUE, 0);
image = gtk_image_new_from_stock(icon, GTK_ICON_SIZE_BUTTON);
gtk_box_pack_end(GTK_BOX(ibox), image, FALSE, TRUE, 0);
}
if (text) {
- gtk_box_pack_start_defaults(GTK_BOX(bbox), lbox);
+ gtk_box_pack_start(GTK_BOX(bbox), lbox, TRUE, TRUE, 0);
label = gtk_label_new(NULL);
gtk_label_set_text_with_mnemonic(GTK_LABEL(label), text);
gtk_label_set_mnemonic_widget(GTK_LABEL(label), button);
diff --git a/pidgin/pidginstock.c b/pidgin/pidginstock.c
index 8eddd473f5..38d402fc15 100644
--- a/pidgin/pidginstock.c
+++ b/pidgin/pidginstock.c
@@ -270,37 +270,30 @@ find_file(const char *dir, const char *base)
/* Altered from do_colorshift in gnome-panel */
static void
-do_alphashift(GdkPixbuf *dest, GdkPixbuf *src)
+do_alphashift(GdkPixbuf *pixbuf)
{
gint i, j;
- gint width, height, has_alpha, srcrowstride, destrowstride;
- guchar *target_pixels;
- guchar *original_pixels;
- guchar *pixsrc;
- guchar *pixdest;
+ gint width, height, padding;
+ guchar *pixels;
guchar a;
- has_alpha = gdk_pixbuf_get_has_alpha (src);
- if (!has_alpha)
+ if (!gdk_pixbuf_get_has_alpha(pixbuf))
return;
- width = gdk_pixbuf_get_width (src);
- height = gdk_pixbuf_get_height (src);
- srcrowstride = gdk_pixbuf_get_rowstride (src);
- destrowstride = gdk_pixbuf_get_rowstride (dest);
- target_pixels = gdk_pixbuf_get_pixels (dest);
- original_pixels = gdk_pixbuf_get_pixels (src);
+ width = gdk_pixbuf_get_width(pixbuf);
+ height = gdk_pixbuf_get_height(pixbuf);
+ padding = gdk_pixbuf_get_rowstride(pixbuf) - width * 4;
+ pixels = gdk_pixbuf_get_pixels(pixbuf);
for (i = 0; i < height; i++) {
- pixdest = target_pixels + i*destrowstride;
- pixsrc = original_pixels + i*srcrowstride;
for (j = 0; j < width; j++) {
- *(pixdest++) = *(pixsrc++);
- *(pixdest++) = *(pixsrc++);
- *(pixdest++) = *(pixsrc++);
- a = *(pixsrc++);
- *(pixdest++) = a / 2;
+ pixels++;
+ pixels++;
+ pixels++;
+ a = *(pixels);
+ *(pixels++) = a / 2;
}
+ pixels += padding;
}
}
@@ -348,7 +341,7 @@ add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginIconTheme *theme,
g_return_if_fail(filename != NULL);
pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
if (translucent)
- do_alphashift(pixbuf, pixbuf);
+ do_alphashift(pixbuf);
source = gtk_icon_source_new();
gtk_icon_source_set_pixbuf(source, pixbuf);
@@ -378,7 +371,7 @@ add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginIconTheme *theme,
g_return_if_fail(filename != NULL);
pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
if (translucent)
- do_alphashift(pixbuf, pixbuf);
+ do_alphashift(pixbuf);
source = gtk_icon_source_new();
gtk_icon_source_set_pixbuf(source, pixbuf);
diff --git a/pidgin/pixmaps/Makefile.am b/pidgin/pixmaps/Makefile.am
index 30f5682461..17d9098b82 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/pidgin/plugins/gestures/gestures.c b/pidgin/plugins/gestures/gestures.c
index 770cc197b9..4848a844b1 100644
--- a/pidgin/plugins/gestures/gestures.c
+++ b/pidgin/plugins/gestures/gestures.c
@@ -145,6 +145,15 @@ new_conv_cb(PurpleConversation *conv)
}
#if 0
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+mouse_button_menu_cb(GtkComboBox *opt, gpointer data)
+{
+ int button = gtk_combo_box_get_active(opt);
+
+ gstroke_set_mouse_button(button + 2);
+}
+#else
static void
mouse_button_menu_cb(GtkMenuItem *item, gpointer data)
{
@@ -153,6 +162,7 @@ mouse_button_menu_cb(GtkMenuItem *item, gpointer data)
gstroke_set_mouse_button(button + 2);
}
#endif
+#endif
static void
toggle_draw_cb(GtkToggleButton *toggle, gpointer data)
@@ -220,8 +230,10 @@ get_config_frame(PurplePlugin *plugin)
GtkWidget *toggle;
#if 0
GtkWidget *opt;
+#if GTK_CHECK_VERSION(2,4,0)
GtkWidget *menu, *item;
#endif
+#endif
/* Outside container */
ret = gtk_vbox_new(FALSE, 18);
@@ -231,6 +243,19 @@ get_config_frame(PurplePlugin *plugin)
vbox = pidgin_make_frame(ret, _("Mouse Gestures Configuration"));
#if 0
+#if GTK_CHECK_VERSION(2,4,0)
+ /* Mouse button drop-down menu */
+ opt = gtk_combo_box_new_text();
+
+ gtk_combo_box_append_text(_("Middle mouse button"));
+ gtk_combo_box_append_text(_("Right mouse button"));
+ g_signal_connect(G_OBJECT(opt), "changed",
+ G_CALLBACK(mouse_button_menu_cb), NULL);
+
+ gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(opt),
+ gstroke_get_mouse_button() - 2);
+#else
/* Mouse button drop-down menu */
menu = gtk_menu_new();
opt = gtk_option_menu_new();
@@ -250,6 +275,7 @@ get_config_frame(PurplePlugin *plugin)
gtk_option_menu_set_history(GTK_OPTION_MENU(opt),
gstroke_get_mouse_button() - 2);
#endif
+#endif
/* "Visual gesture display" checkbox */
toggle = gtk_check_button_new_with_mnemonic(_("_Visual gesture display"));
diff --git a/pidgin/plugins/gevolution/assoc-buddy.c b/pidgin/plugins/gevolution/assoc-buddy.c
index 7e5b074a9e..1c6639b92b 100644
--- a/pidgin/plugins/gevolution/assoc-buddy.c
+++ b/pidgin/plugins/gevolution/assoc-buddy.c
@@ -20,7 +20,6 @@
*/
#include "internal.h"
#include "gtkblist.h"
-#include "gtkexpander.h"
#include "pidgin.h"
#include "gtkutils.h"
#include "gtkimhtml.h"
diff --git a/pidgin/plugins/gtkbuddynote.c b/pidgin/plugins/gtkbuddynote.c
index d19fc3ca6e..bf08b8c1ac 100644
--- a/pidgin/plugins/gtkbuddynote.c
+++ b/pidgin/plugins/gtkbuddynote.c
@@ -31,11 +31,13 @@ append_to_tooltip(PurpleBlistNode *node, GString *text, gboolean full)
const gchar *note = purple_blist_node_get_string(node, "notes");
if ((note != NULL) && (*note != '\0')) {
- char *tmp;
+ char *tmp, *esc;
purple_markup_html_to_xhtml(note, NULL, &tmp);
- g_string_append_printf(text, _("\n<b>Buddy Note</b>: %s"),
- tmp);
+ esc = g_markup_escape_text(tmp, -1);
g_free(tmp);
+ g_string_append_printf(text, _("\n<b>Buddy Note</b>: %s"),
+ esc);
+ g_free(esc);
}
}
}
diff --git a/pidgin/plugins/win32/transparency/win2ktrans.c b/pidgin/plugins/win32/transparency/win2ktrans.c
index 9b31e7d3c1..a4ae3b538d 100644
--- a/pidgin/plugins/win32/transparency/win2ktrans.c
+++ b/pidgin/plugins/win32/transparency/win2ktrans.c
@@ -72,8 +72,6 @@ static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/win32/wintrans/bl_soli
static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/win32/wintrans/bl_always_on_top";
static GSList *window_list = NULL;
-static BOOL (*MySetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags) = NULL;
-
/*
* CODE
*/
@@ -81,31 +79,31 @@ static BOOL (*MySetLayeredWindowAttributes)(HWND hwnd, COLORREF crKey, BYTE bAlp
/* Set window transparency level */
static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled,
gboolean always_on_top) {
- if (MySetLayeredWindowAttributes) {
- HWND hWnd = GDK_WINDOW_HWND(window->window);
- LONG style = GetWindowLong(hWnd, GWL_EXSTYLE);
- if (enabled) {
- style |= WS_EX_LAYERED;
- } else {
- style &= ~WS_EX_LAYERED;
- }
- SetWindowLong(hWnd, GWL_EXSTYLE, style);
+ HWND hWnd = GDK_WINDOW_HWND(window->window);
+ LONG style = GetWindowLong(hWnd, GWL_EXSTYLE);
+ if (enabled) {
+ style |= WS_EX_LAYERED;
+ } else {
+ style &= ~WS_EX_LAYERED;
+ }
+ SetWindowLong(hWnd, GWL_EXSTYLE, style);
- if (enabled) {
- SetWindowPos(hWnd,
- always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST,
- 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- MySetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
- } else {
- /* Ask the window and its children to repaint */
- SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- RedrawWindow(hWnd, NULL, NULL,
- RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
- }
+ if (enabled) {
+ SetWindowPos(hWnd,
+ always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST,
+ 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
+ } else {
+ /* Ask the window and its children to repaint */
+ SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ RedrawWindow(hWnd, NULL, NULL,
+ RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
}
+
}
/* When a conv window is focused, if we're only transparent when unfocused,
@@ -491,14 +489,6 @@ static void update_existing_convs() {
* EXPORTED FUNCTIONS
*/
static gboolean plugin_load(PurplePlugin *plugin) {
- MySetLayeredWindowAttributes = (void*) wpurple_find_and_loadproc(
- "user32.dll", "SetLayeredWindowAttributes");
-
- if (!MySetLayeredWindowAttributes) {
- purple_debug_error(WINTRANS_PLUGIN_ID,
- "SetLayeredWindowAttributes API not found (Required W2K+)\n");
- return FALSE;
- }
purple_signal_connect(purple_conversations_get_handle(),
"conversation-created", plugin,
diff --git a/pidgin/win32/gtkwin32dep.c b/pidgin/win32/gtkwin32dep.c
index aebfce15a0..1da98d5cdb 100644
--- a/pidgin/win32/gtkwin32dep.c
+++ b/pidgin/win32/gtkwin32dep.c
@@ -47,8 +47,6 @@
#include "zlib.h"
#include "untar.h"
-#include <libintl.h>
-
#include "gtkwin32dep.h"
#include "win32dep.h"
#include "gtkconv.h"
@@ -64,8 +62,6 @@ HINSTANCE dll_hInstance = 0;
HWND messagewin_hwnd;
static int gtkwin32_handle;
-typedef BOOL (CALLBACK* LPFNFLASHWINDOWEX)(PFLASHWINFO);
-static LPFNFLASHWINDOWEX MyFlashWindowEx = NULL;
static gboolean pwm_handles_connections = TRUE;
@@ -308,6 +304,7 @@ static gboolean stop_flashing(GtkWidget *widget, GdkEventFocus *event, gpointer
void
winpidgin_window_flash(GtkWindow *window, gboolean flash) {
GdkWindow * gdkwin;
+ FLASHWINFO info;
g_return_if_fail(window != NULL);
@@ -319,25 +316,19 @@ winpidgin_window_flash(GtkWindow *window, gboolean flash) {
if(GDK_WINDOW_DESTROYED(gdkwin))
return;
- if(MyFlashWindowEx) {
- FLASHWINFO info;
-
- memset(&info, 0, sizeof(FLASHWINFO));
- info.cbSize = sizeof(FLASHWINFO);
- info.hwnd = GDK_WINDOW_HWND(gdkwin);
- if (flash) {
- DWORD flashCount;
- info.uCount = 3;
- if (SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &flashCount, 0))
- info.uCount = flashCount;
- info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
- } else
- info.dwFlags = FLASHW_STOP;
- info.dwTimeout = 0;
-
- MyFlashWindowEx(&info);
+ memset(&info, 0, sizeof(FLASHWINFO));
+ info.cbSize = sizeof(FLASHWINFO);
+ info.hwnd = GDK_WINDOW_HWND(gdkwin);
+ if (flash) {
+ DWORD flashCount;
+ info.uCount = 3;
+ if (SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &flashCount, 0))
+ info.uCount = flashCount;
+ info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
} else
- FlashWindow(GDK_WINDOW_HWND(gdkwin), flash);
+ info.dwFlags = FLASHW_STOP;
+ info.dwTimeout = 0;
+
}
void
@@ -384,11 +375,27 @@ winpidgin_conv_im_blink(PurpleAccount *account, const char *who, char **message,
}
void winpidgin_init(HINSTANCE hint) {
+ FARPROC proc;
purple_debug_info("winpidgin", "winpidgin_init start\n");
exe_hInstance = hint;
+ proc = wpurple_find_and_loadproc("exchndl.dll", "SetLogFile");
+ if (proc) {
+ gchar *debug_dir, *locale_debug_dir;
+
+ debug_dir = g_build_filename(purple_user_dir(), "pidgin.RPT", NULL);
+ locale_debug_dir = g_locale_from_utf8(debug_dir, -1, NULL, NULL, NULL);
+
+ purple_debug_info("winpidgin", "Setting exchndl.dll LogFile to %s\n", debug_dir);
+
+ (proc)(locale_debug_dir);
+
+ g_free(debug_dir);
+ g_free(locale_debug_dir);
+ }
+
/* IdleTracker Initialization */
if(!winpidgin_set_idlehooks())
purple_debug_error("winpidgin", "Failed to initialize idle tracker\n");
@@ -399,8 +406,6 @@ void winpidgin_init(HINSTANCE hint) {
messagewin_hwnd = winpidgin_message_window_init();
- MyFlashWindowEx = (LPFNFLASHWINDOWEX) wpurple_find_and_loadproc("user32.dll", "FlashWindowEx");
-
purple_debug_info("winpidgin", "winpidgin_init end\n");
}
@@ -436,36 +441,16 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
return TRUE;
}
-typedef HMONITOR WINAPI _MonitorFromWindow(HWND, DWORD);
-typedef BOOL WINAPI _GetMonitorInfo(HMONITOR, LPMONITORINFO);
-
static gboolean
get_WorkingAreaRectForWindow(HWND hwnd, RECT *workingAreaRc) {
- static _MonitorFromWindow *the_MonitorFromWindow;
- static _GetMonitorInfo *the_GetMonitorInfo;
- static gboolean initialized = FALSE;
HMONITOR monitor;
MONITORINFO info;
- if(!initialized) {
- the_MonitorFromWindow = (_MonitorFromWindow*)
- wpurple_find_and_loadproc("user32", "MonitorFromWindow");
- the_GetMonitorInfo = (_GetMonitorInfo*)
- wpurple_find_and_loadproc("user32", "GetMonitorInfoA");
- initialized = TRUE;
- }
-
- if(!the_MonitorFromWindow)
- return FALSE;
-
- if(!the_GetMonitorInfo)
- return FALSE;
-
- monitor = the_MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
+ monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
info.cbSize = sizeof(info);
- if(!the_GetMonitorInfo(monitor, &info))
+ if(!GetMonitorInfo(monitor, &info))
return FALSE;
CopyRect(workingAreaRc, &(info.rcWork));
diff --git a/pidgin/win32/nsis/langmacros.nsh b/pidgin/win32/nsis/langmacros.nsh
index 5c3696c73a..615c229667 100644
--- a/pidgin/win32/nsis/langmacros.nsh
+++ b/pidgin/win32/nsis/langmacros.nsh
@@ -91,8 +91,10 @@
!insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SPELLCHECK_SWEDISH ${CUR_LANG}
!insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_SPELLCHECK_UKRAINIAN ${CUR_LANG}
- !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_DEBUGSYMBOLS_ERROR ${CUR_LANG}
- !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_GTK_DOWNLOAD_ERROR ${CUR_LANG}
+ !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_DEBUGSYMBOLS_ERROR ${CUR_LANG}
+ !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT PIDGIN_GTK_DOWNLOAD_ERROR ${CUR_LANG}
+
+ !insertmacro PIDGIN_MACRO_LANGSTRING_INSERT TRANSLATIONS_SECTION_TITLE ${CUR_LANG}
!undef CUR_LANG
!macroend
diff --git a/pidgin/win32/nsis/pidgin-installer.nsi b/pidgin/win32/nsis/pidgin-installer.nsi
index 63ff566790..262c0c2c37 100644
--- a/pidgin/win32/nsis/pidgin-installer.nsi
+++ b/pidgin/win32/nsis/pidgin-installer.nsi
@@ -53,7 +53,7 @@ SetDateSave on
;Defines
!define PIDGIN_NSIS_INCLUDE_PATH "."
-!define PIDGIN_INSTALLER_DEPS "..\..\..\..\win32-dev\pidgin-inst-deps-0.2"
+!define PIDGIN_INSTALLER_DEPS "..\..\..\..\win32-dev\pidgin-inst-deps-20100223"
; Remove these and the stuff that uses them at some point
!define OLD_GAIM_REG_KEY "SOFTWARE\gaim"
@@ -352,12 +352,11 @@ Section $(GTK_SECTION_TITLE) SecGtk
Pop $R0
StrCmp $R0 "cancel" done
StrCmp $R0 "success" +2
- MessageBox MB_RETRYCANCEL "$(PIDGIN_GTK_DOWNLOAD_ERROR) : $R1" /SD IDCANCEL IDRETRY retry IDCANCEL done
+ MessageBox MB_RETRYCANCEL "$(PIDGIN_GTK_DOWNLOAD_ERROR) : $R2" /SD IDCANCEL IDRETRY retry IDCANCEL done
!endif
SetOutPath "$INSTDIR"
-
nsisunz::UnzipToLog $R1 "$INSTDIR"
Pop $R0
StrCmp $R0 "success" +2
@@ -610,17 +609,17 @@ SectionGroup /e $(PIDGIN_SPELLCHECK_SECTION_TITLE) SecSpellCheck
SectionGroupEnd
Section /o $(DEBUG_SYMBOLS_SECTION_TITLE) SecDebugSymbols
+
InitPluginsDir
-
- ; We need to download and extract the debug symbols
- StrCpy $R1 "$PLUGINSDIR\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
+ StrCpy $R1 "$PLUGINSDIR\dbgsym.zip"
!ifdef OFFLINE_INSTALLER
SetOutPath $PLUGINSDIR
- File /oname=pidgin-${PIDGIN_VERSION}-dbgsym.zip "..\..\..\..\gtk_installer\gtk-runtime-${GTK_INSTALL_VERSION}.zip"
+ File /oname=dbgsym.zip "..\..\..\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
!else
+ ; We need to download the debug symbols
retry:
StrCpy $R2 "${DOWNLOADER_URL}?version=${PIDGIN_VERSION}&dl_pkg=dbgsym"
DetailPrint "Downloading Debug Symbols... ($R2)"
@@ -632,6 +631,7 @@ Section /o $(DEBUG_SYMBOLS_SECTION_TITLE) SecDebugSymbols
!endif
+ SetOutPath "$INSTDIR"
nsisunz::UnzipToLog $R1 "$INSTDIR"
Pop $R0
StrCmp $R0 "success" +2
@@ -779,7 +779,7 @@ Section Uninstall
Delete "$INSTDIR\libsasl.dll"
Delete "$INSTDIR\libsilc-1-1-2.dll"
Delete "$INSTDIR\libsilcclient-1-1-2.dll"
- Delete "$INSTDIR\libxml2.dll"
+ Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libymsg.dll"
Delete "$INSTDIR\nspr4.dll"
Delete "$INSTDIR\nss3.dll"
@@ -801,7 +801,7 @@ Section Uninstall
; Remove the local GTK+ copy (if we're not just upgrading)
${GetParameters} $R0
ClearErrors
- ${GetOptions} "$R3" "/KEEPGTK=" $R1
+ ${GetOptions} "$R0" "/KEEPGTK=" $R1
IfErrors +2
StrCmp $R1 "1" +2
RMDir /r "$INSTDIR\Gtk"
@@ -1368,6 +1368,10 @@ Function preWelcomePage
Push $R0
Push $R1
+!ifdef OFFLINE_INSTALLER
+ !insertmacro SelectSection ${SecDebugSymbols}
+!endif
+
Call DoWeNeedGtk
Pop $R0
IntCmp $R0 1 done gtk_not_mandatory
diff --git a/pidgin/win32/nsis/translations/english.nsh b/pidgin/win32/nsis/translations/english.nsh
index d1f26da35f..d3b45be452 100644
--- a/pidgin/win32/nsis/translations/english.nsh
+++ b/pidgin/win32/nsis/translations/english.nsh
@@ -25,13 +25,14 @@
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SHORTCUTS_SECTION_TITLE "Shortcuts"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE "Desktop"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE "Start Menu"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING TRANSLATIONS_SECTION_TITLE "Localizations"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SECTION_DESCRIPTION "Core Pidgin files and dlls"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING GTK_SECTION_DESCRIPTION "A multi-platform GUI toolkit, used by Pidgin"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SHORTCUTS_SECTION_DESCRIPTION "Shortcuts for starting Pidgin"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DESKTOP_SHORTCUT_DESC "Create a shortcut to Pidgin on the Desktop"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_STARTMENU_SHORTCUT_DESC "Create a Start Menu entry for Pidgin"
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING DEBUG_SYMBOLS_SECTION_TITLE "Debug Symbols (for reporting crashes)"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING DEBUG_SYMBOLS_SECTION_TITLE "Debug Symbols (for reporting crashes)"
; GTK+ Directory Page
@@ -79,6 +80,7 @@
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SPELLCHECK_SWEDISH "Swedish"
!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_SPELLCHECK_UKRAINIAN "Ukrainian"
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DEBUGSYMBOLS_ERROR "Error Installing Debug Symbols"
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_DEBUGSYMBOLS_ERROR "Error Installing Debug Symbols"
+
+!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_GTK_DOWNLOAD_ERROR "Error Downloading the GTK+ Runtime"
-!insertmacro PIDGIN_MACRO_DEFAULT_STRING PIDGIN_GTK_DOWNLOAD_ERROR "Error Downloading the GTK+ Runtime"
diff --git a/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh b/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh
index d2693a94fe..79dab8778c 100644
--- a/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh
+++ b/pidgin/win32/nsis/translations/norwegian_nynorsk.nsh
@@ -9,7 +9,6 @@
; Startup Checks
!define INSTALLER_IS_RUNNING "Installasjonsprogrammet kjører allereie."
!define PIDGIN_IS_RUNNING "Pidgin kjører no. Lukk programmet og prøv igjen."
-!define GTK_INSTALLER_NEEDED "GTK+-kjøremiljøet manglar eller treng å bli oppdatert.$\rInstaller v${GTK_MIN_VERSION} eller nyare av GTK+-kjøremiljøet"
; License Page
!define PIDGIN_LICENSE_BUTTON "Neste >"
@@ -28,20 +27,12 @@
!define PIDGIN_DESKTOP_SHORTCUT_DESC "Lag ein snarveg til Pidgin på skrivebordet"
!define PIDGIN_STARTMENU_SHORTCUT_DESC "Lag ein snarveg til Pidgin på startmenyen"
-; GTK+ Directory Page
-!define GTK_UPGRADE_PROMPT "Fann ei gammal utgåve av GTK+-kjøremiljøet. Vil du oppdatera ho?$\rMerk: $(^Name) vil kanskje ikkje fungera om du ikkje oppdaterer."
-!define GTK_WINDOWS_INCOMPATIBLE "Windows 95/98/Me er ikkje kompatibelt med GTK+ 2.8.0 eller nyare. GTK+ ${GTK_INSTALL_VERSION} kjem ikkje til å bli installert.$\rInstallasjonen vil bli abvroten om ikkje GTK+ ${GTK_MIN_VERSION} eller nyare allereie er installert."
-
; Installer Finish Page
!define PIDGIN_FINISH_VISIT_WEB_SITE "Besøk Pidgin si nettside"
; Pidgin Section Prompts and Texts
!define PIDGIN_PROMPT_CONTINUE_WITHOUT_UNINSTALL "Klarte ikkje å avinstallera Pidgin-utgåva som er i bruk. Den nye utgåva kjem til å bli installert utan å ta vekk den gjeldande."
-; GTK+ Section Prompts
-!define GTK_INSTALL_ERROR "Klarte ikkje å installera GTK+-kjøremiljøet."
-!define GTK_BAD_INSTALL_PATH "Klarer ikkje å laga eller få tilgang til bana du skreiv."
-
; URL Handler section
!define URI_HANDLERS_SECTION_TITLE "URI-referanse"
diff --git a/pidgin/win32/nsis/translations/polish.nsh b/pidgin/win32/nsis/translations/polish.nsh
index d3643169e0..5d5f775646 100644
--- a/pidgin/win32/nsis/translations/polish.nsh
+++ b/pidgin/win32/nsis/translations/polish.nsh
@@ -25,17 +25,9 @@
!define PIDGIN_DESKTOP_SHORTCUT_DESC "Utworzenie skrótu do programu Pidgin na pulpicie"
!define PIDGIN_STARTMENU_SHORTCUT_DESC "Utworzenie wpisu w menu Start dla programu Pidgin"
-; GTK+ Directory Page
-!define GTK_UPGRADE_PROMPT "Odnaleziono star¹ wersjê biblioteki GTK+. Zaktualizowaæ j¹?$\rUwaga: program $(^Name) mo¿e bez tego nie dzia³aæ."
-!define GTK_WINDOWS_INCOMPATIBLE "Systemy Windows 95/98/Me s¹ niezgodne z bibliotek¹ GTK+ 2.8.0 lub nowsz¹. Biblioteka GTK+ ${GTK_INSTALL_VERSION} nie zostanie zainstalowana.$\rJeœli brak zainstalowanej biblioteki GTK+ ${GTK_MIN_VERSION} lub nowszej, instalacja zostanie przerwana."
-
; Installer Finish Page
!define PIDGIN_FINISH_VISIT_WEB_SITE "OdwiedŸ stronê WWW programu Pidgin"
-; GTK+ Section Prompts
-!define GTK_INSTALL_ERROR "B³¹d podczas instalowania biblioteki GTK+."
-!define GTK_BAD_INSTALL_PATH "Nie mo¿na uzyskaæ dostêpu do podanej œcie¿ki lub jej utworzyæ."
-
; Uninstall Section Prompts
!define un.PIDGIN_UNINSTALL_ERROR_1 "Instalator nie mo¿e odnaleŸæ wpisów w rejestrze dla programu Pidgin.$\rMo¿liwe, ¿e inny u¿ytkownik zainstalowa³ ten program."
-!define un.PIDGIN_UNINSTALL_ERROR_2 "Brak uprawnieñ do odinstalowania tego programu." \ No newline at end of file
+!define un.PIDGIN_UNINSTALL_ERROR_2 "Brak uprawnieñ do odinstalowania tego programu."
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0ed24d7cfb..5872365a9d 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
@@ -213,14 +214,12 @@ pidgin/eggtrayicon.c
pidgin/gtkaccount.c
pidgin/gtkblist-theme.c
pidgin/gtkblist.c
-pidgin/gtkcellview.c
pidgin/gtkcertmgr.c
pidgin/gtkconn.c
pidgin/gtkconv.c
pidgin/gtkdebug.c
pidgin/gtkdialogs.c
pidgin/gtkdocklet.c
-pidgin/gtkexpander.c
pidgin/gtkft.c
pidgin/gtkimhtml.c
pidgin/gtkimhtmltoolbar.c
@@ -241,7 +240,6 @@ pidgin/gtkstatusbox.c
pidgin/gtkutils.c
pidgin/gtkwhiteboard.c
pidgin/pidgin.h
-pidgin/pidgincombobox.c
pidgin/pidginstock.c
pidgin/pidgintooltip.c
pidgin/pixmaps/emotes/default/24/default.theme.in