# HG changeset patch # User Richard Nelson # Date 1186364724 0 # Node ID 580e0bfe7e339be565cf27b472e8986fb58e8d8b # Parent 6af9201ac685a1809a9fc1de71ff79a9e95a81ed# Parent 5a5ca643830892fde99e2044c1254215033efb3c merge of '412ec3e9ae5d5532710d56efecc7543837a91cbb' and '8f73315c03954666c69c055abbe62ee2e135c4cf' diff -r 5a5ca6438308 -r 580e0bfe7e33 configure.ac --- a/configure.ac Mon Aug 06 01:36:57 2007 +0000 +++ b/configure.ac Mon Aug 06 01:45:24 2007 +0000 @@ -593,6 +593,46 @@ AC_SUBST(MEANWHILE_LIBS) dnl ####################################################################### +dnl # Check for Native Avahi headers (for Bonjour) +dnl ####################################################################### +AC_ARG_WITH(avahi-client-includes, [AC_HELP_STRING([--with-avahi-client-includes=DIR], [compile the Bonjour plugin against the Avahi Client includes in DIR])], [ac_avahi_client_includes="$withval"], [ac_avahi_client_includes="no"]) +AC_ARG_WITH(avahi-client-libs, [AC_HELP_STRING([--with-avahi-client-libs=DIR], [compile the Bonjour plugin against the Avahi Client libs in DIR])], [ac_avahi_client_libs="$withval"], [ac_avahi_client_libs="no"]) +AVAHI_CFLAGS="" +AVAHI_LIBS="" + +dnl Attempt to autodetect Avahi +PKG_CHECK_MODULES(AVAHI, [avahi-client avahi-glib], [ + avahiincludes="yes" + avahilibs="yes" +], [ + AC_MSG_RESULT(no) + avahiincludes="no" + avahilibs="no" +]) + +dnl Override AVAHI_CFLAGS if the user specified an include dir +if test "$ac_avahi_client_includes" != "no"; then + AVAHI_CFLAGS="-I$ac_avahi_client_includes" +fi +CPPFLAGS_save="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $AVAHI_CFLAGS" +AC_CHECK_HEADER(avahi-client/client.h, [avahiincludes=yes], [avahiincludes=no]) +CPPFLAGS="$CPPFLAGS $AVAHI_CFLAGS $GLIB_CFLAGS" +AC_CHECK_HEADER(avahi-glib/glib-malloc.h, [avahiincludes=yes], [avahiincludes=no]) +CPPFLAGS="$CPPFLAGS_save" + +dnl Override AVAHI_LIBS if the user specified a libs dir +if test "$ac_avahi_client_libs" != "no"; then + AVAHI_LIBS="-L$ac_avahi_client_libs -lavahi-common -lavahi-client -lavahi-glib " +fi +AC_CHECK_LIB(avahi-client, avahi_client_new, [avahilibs=yes], [avahilibs=no], $AVAHI_LIBS) + +AC_SUBST(AVAHI_CFLAGS) +AC_SUBST(AVAHI_LIBS) + +AM_CONDITIONAL(MDNS_AVAHI, test "x$avahiincludes" = "xyes" -a "x$avahilibs" = "xyes") + +dnl ####################################################################### dnl # Check for Howl headers (for Bonjour) dnl ####################################################################### AC_ARG_WITH(howl-includes, [AC_HELP_STRING([--with-howl-includes=DIR], [compile the Bonjour plugin against the Howl includes in DIR])], [ac_howl_includes="$withval"], [ac_howl_includes="no"]) @@ -601,6 +641,7 @@ HOWL_LIBS="" dnl Attempt to autodetect avahi-compat-howl +dnl TODO: (This should be removed when the native avahi stuff is stable) PKG_CHECK_MODULES(HOWL, avahi-compat-howl, [ howlincludes="yes" howllibs="yes" @@ -640,6 +681,9 @@ AC_SUBST(HOWL_CFLAGS) AC_SUBST(HOWL_LIBS) +AM_CONDITIONAL(MDNS_HOWL, test "x$howlincludes" = "xyes" -a "x$howllibs" = "xyes") + + dnl ####################################################################### dnl # Check for SILC client includes and libraries dnl ####################################################################### @@ -819,8 +863,10 @@ if test "x$have_meanwhile" != "xyes" ; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'` fi -if test "x$howlincludes" != "xyes" -o "x$howllibs" != "xyes"; then - STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` +if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then + if test "x$howlincludes" != "xyes" -o "x$howllibs" != "xyes"; then + STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'` + fi fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'` @@ -873,7 +919,7 @@ *) echo "Invalid static protocol $i!!" ; exit ;; esac done -AM_CONDITIONAL(STATIC_BONJOUR, test "x$static_bonjour" = "xyes" -a "x$howlincludes" = "xyes" -a "x$howllibs" = "xyes") +AM_CONDITIONAL(STATIC_BONJOUR, test "x$static_bonjour" = "xyes") AM_CONDITIONAL(STATIC_GG, test "x$static_gg" = "xyes") AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes") AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes") @@ -898,8 +944,10 @@ if test "x$have_meanwhile" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'` fi -if test "x$howlincludes" != "xyes" -o "x$howllibs" != "xyes"; then - DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` +if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then + if test "x$howlincludes" != "xyes" -o "x$howllibs" != "xyes"; then + DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'` + fi fi if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'` @@ -930,7 +978,7 @@ *) echo "Invalid dynamic protocol $i!!" ; exit ;; esac done -AM_CONDITIONAL(DYNAMIC_BONJOUR, test "x$dynamic_bonjour" = "xyes" -a "x$bonjourincludes" = "xyes" -a "x$bonjourclient" = "xyes") +AM_CONDITIONAL(DYNAMIC_BONJOUR, test "x$dynamic_bonjour" = "xyes" -a [ [ "x$avahiincludes" = "xyes" -a "x$avahilibs " = "xyes" ] -o [ "x$howlincludes" = "xyes" -a "x$howllibs" = "xyes" ] ] ) AM_CONDITIONAL(DYNAMIC_GG, test "x$dynamic_gg" = "xyes") AM_CONDITIONAL(DYNAMIC_IRC, test "x$dynamic_irc" = "xyes") AM_CONDITIONAL(DYNAMIC_JABBER, test "x$dynamic_jabber" = "xyes") diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/bonjour/Makefile.am --- a/libpurple/protocols/bonjour/Makefile.am Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/bonjour/Makefile.am Mon Aug 06 01:45:24 2007 +0000 @@ -1,6 +1,7 @@ EXTRA_DIST = \ - mdns_win32.c \ - Makefile.mingw + mdns_win32.c \ + dns_sd_proxy.h \ + Makefile.mingw pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) @@ -9,18 +10,24 @@ bonjour.h \ buddy.c \ buddy.h \ - dns_sd_proxy.h \ jabber.c \ jabber.h \ mdns_common.c \ mdns_common.h \ - mdns_howl.c \ mdns_interface.h \ mdns_types.h \ parser.c \ parser.h -AM_CFLAGS = $(st) -DUSE_BONJOUR_HOWL +if MDNS_AVAHI + BONJOURSOURCES += mdns_avahi.c +else + if MDNS_HOWL + BONJOURSOURCES += mdns_howl.c + endif +endif + +AM_CFLAGS = $(st) libbonjour_la_LDFLAGS = -module -avoid-version @@ -30,14 +37,29 @@ noinst_LIBRARIES = libbonjour.a libbonjour_a_SOURCES = $(BONJOURSOURCES) libbonjour_a_CFLAGS = $(AM_CFLAGS) -libbonjour_a_LIBADD = $(HOWL_LIBS) +libbonjour_a_LIBADD = + +if MDNS_AVAHI + libbonjour_a_LIBADD += $(AVAHI_LIBS) +else + if MDNS_HOWL + libbonjour_a_LIBADD += $(HOWL_LIBS) + endif +endif else st = pkg_LTLIBRARIES = libbonjour.la libbonjour_la_SOURCES = $(BONJOURSOURCES) -libbonjour_la_LIBADD = $(GLIB_LIBS) $(HOWL_LIBS) $(LIBXML_LIBS) +libbonjour_la_LIBADD = $(GLIB_LIBS) $(LIBXML_LIBS) +if MDNS_AVAHI + libbonjour_la_LIBADD += $(AVAHI_LIBS) +else + if MDNS_HOWL + libbonjour_la_LIBADD += $(HOWL_LIBS) + endif +endif endif @@ -47,5 +69,13 @@ -I$(top_builddir)/libpurple \ $(GLIB_CFLAGS) \ $(DEBUG_CFLAGS) \ - $(HOWL_CFLAGS) \ $(LIBXML_CFLAGS) + +if MDNS_AVAHI + AM_CPPFLAGS += $(AVAHI_CFLAGS) +else + if MDNS_HOWL + AM_CPPFLAGS += $(HOWL_CFLAGS) + endif +endif + diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/bonjour/mdns_avahi.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/bonjour/mdns_avahi.c Mon Aug 06 01:45:24 2007 +0000 @@ -0,0 +1,349 @@ +/* + * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "internal.h" + +#include "mdns_interface.h" +#include "debug.h" +#include "buddy.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/* data used by avahi bonjour implementation */ +typedef struct _avahi_session_impl_data { + AvahiClient *client; + AvahiGLibPoll *glib_poll; + AvahiServiceBrowser *sb; + AvahiEntryGroup *group; +} AvahiSessionImplData; + +static void +_resolver_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, + AvahiResolverEvent event, const char *name, const char *type, const char *domain, + const char *host_name, const AvahiAddress *a, uint16_t port, AvahiStringList *txt, + AvahiLookupResultFlags flags, void *userdata) { + + BonjourBuddy *buddy; + PurpleAccount *account = userdata; + AvahiStringList *l; + size_t size; + char *key, *value; + int ret; + + g_return_if_fail(r != NULL); + + switch (event) { + case AVAHI_RESOLVER_FAILURE: + purple_debug_error("bonjour", "_resolve_callback - Failure: %s\n", + avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r)))); + break; + case AVAHI_RESOLVER_FOUND: + /* create a buddy record */ + buddy = bonjour_buddy_new(name, account); + + /* Get the ip as a string */ + buddy->ip = g_malloc(AVAHI_ADDRESS_STR_MAX); + avahi_address_snprint(buddy->ip, AVAHI_ADDRESS_STR_MAX, a); + + buddy->port_p2pj = port; + + /* Obtain the parameters from the text_record */ + l = txt; + while (l != NULL) { + ret = avahi_string_list_get_pair(l, &key, &value, &size); + l = l->next; + if (ret < 0) + continue; + set_bonjour_buddy_value(buddy, key, value, size); + /* TODO: Since we're using the glib allocator, I think we + * can use the values instead of re-copying them */ + avahi_free(key); + avahi_free(value); + } + + if (!bonjour_buddy_check(buddy)) + bonjour_buddy_delete(buddy); + else + /* Add or update the buddy in our buddy list */ + bonjour_buddy_add_to_purple(buddy); + + break; + default: + purple_debug_info("bonjour", "Unrecognized Service Resolver event: %d.\n", event); + } + + avahi_service_resolver_free(r); +} + +static void +_browser_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, + AvahiProtocol protocol, AvahiBrowserEvent event, + const char *name, const char *type, const char *domain, + AvahiLookupResultFlags flags, void *userdata) { + + PurpleAccount *account = userdata; + PurpleBuddy *gb = NULL; + + switch (event) { + case AVAHI_BROWSER_FAILURE: + purple_debug_error("bonjour", "_browser_callback - Failure: %s\n", + avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); + /* TODO: This is an error that should be handled. */ + break; + case AVAHI_BROWSER_NEW: + /* A new peer has joined the network and uses iChat bonjour */ + purple_debug_info("bonjour", "_browser_callback - new service\n"); + /* Make sure it isn't us */ + if (g_ascii_strcasecmp(name, account->username) != 0) { + if (!avahi_service_resolver_new(avahi_service_browser_get_client(b), + interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, + 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)))); + } + } + break; + case AVAHI_BROWSER_REMOVE: + purple_debug_info("bonjour", "_browser_callback - Remove service\n"); + gb = purple_find_buddy(account, name); + if (gb != NULL) { + bonjour_buddy_delete(gb->proto_data); + purple_blist_remove_buddy(gb); + } + break; + case AVAHI_BROWSER_ALL_FOR_NOW: + case AVAHI_BROWSER_CACHE_EXHAUSTED: + purple_debug_warning("bonjour", "(Browser) %s\n", + event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); + break; + default: + purple_debug_info("bonjour", "Unrecognized Service browser event: %d.\n", event); + } +} + +static void +_entry_group_cb(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { + AvahiSessionImplData *idata = userdata; + + g_return_if_fail(g == idata->group || idata->group == NULL); + + switch(state) { + case AVAHI_ENTRY_GROUP_ESTABLISHED: + purple_debug_info("bonjour", "Successfully registered service.\n"); + break; + case AVAHI_ENTRY_GROUP_COLLISION: + purple_debug_error("bonjour", "Collision registering entry group.\n"); + /* TODO: Handle error - this should log out the account. (Possibly with "wants to die")*/ + break; + case AVAHI_ENTRY_GROUP_FAILURE: + purple_debug_error("bonjour", "Error registering entry group: %s\n.", + avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g)))); + /* TODO: Handle error - this should log out the account.*/ + break; + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + break; + } + +} + +/**************************** + * mdns_interface functions * + ****************************/ + +gboolean _mdns_init_session(BonjourDnsSd *data) { + AvahiSessionImplData *idata = g_new0(AvahiSessionImplData, 1); + const AvahiPoll *poll_api; + int error; + + /* Tell avahi to use g_malloc and g_free */ + avahi_set_allocator (avahi_glib_allocator ()); + + /* This currently depends on the glib mainloop, + * we should make it use the libpurple abstraction */ + + idata->glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT); + + poll_api = avahi_glib_poll_get(idata->glib_poll); + + idata->client = avahi_client_new(poll_api, 0, NULL, data, &error); + + if (idata->client == NULL) { + purple_debug_error("bonjour", "Error initializing Avahi: %s", avahi_strerror(error)); + avahi_glib_poll_free(idata->glib_poll); + g_free(idata); + return FALSE; + } + + data->mdns_impl_data = idata; + + return TRUE; +} + +gboolean _mdns_publish(BonjourDnsSd *data, PublishType type) { + int publish_result = 0; + char portstring[6]; + const char *jid, *aim, *email; + AvahiSessionImplData *idata = data->mdns_impl_data; + AvahiStringList *lst = NULL; + + g_return_val_if_fail(idata != NULL, FALSE); + + if (!idata->group) { + idata->group = avahi_entry_group_new(idata->client, + _entry_group_cb, idata); + if (!idata->group) { + purple_debug_error("bonjour", + "Unable to initialize the data for the mDNS (%s).\n", + avahi_strerror(avahi_client_errno(idata->client))); + return FALSE; + } + } + + /* Convert the port to a string */ + snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj); + + jid = purple_account_get_string(data->account, "jid", NULL); + aim = purple_account_get_string(data->account, "AIM", NULL); + email = purple_account_get_string(data->account, "email", NULL); + + /* We should try to follow XEP-0174, but some clients have "issues", so we humor them. + * See http://telepathy.freedesktop.org/wiki/SalutInteroperability + */ + + /* Needed by iChat */ + lst = avahi_string_list_add_pair(lst,"txtvers", "1"); + /* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */ + lst = avahi_string_list_add_pair(lst, "1st", data->first); + /* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */ + lst = avahi_string_list_add_pair(lst, "last", data->last); + /* Needed by Adium */ + lst = avahi_string_list_add_pair(lst, "port.p2pj", portstring); + /* Needed by iChat, Gaim/Pidgin <= 2.0.1 */ + lst = avahi_string_list_add_pair(lst, "status", data->status); + /* Currently always set to "!" since we don't support AV and wont ever be in a conference */ + lst = avahi_string_list_add_pair(lst, "vc", data->vc); + lst = avahi_string_list_add_pair(lst, "ver", VERSION); + if (email != NULL && *email != '\0') + lst = avahi_string_list_add_pair(lst, "email", email); + if (jid != NULL && *jid != '\0') + lst = avahi_string_list_add_pair(lst, "jid", jid); + /* Nonstandard, but used by iChat */ + if (aim != NULL && *aim != '\0') + lst = avahi_string_list_add_pair(lst, "AIM", aim); + if (data->msg != NULL && *data->msg != '\0') + lst = avahi_string_list_add_pair(lst, "msg", data->msg); + if (data->phsh != NULL && *data->phsh != '\0') + lst = avahi_string_list_add_pair(lst, "phsh", data->phsh); + + /* TODO: ext, nick, node */ + + + /* Publish the service */ + switch (type) { + case PUBLISH_START: + publish_result = avahi_entry_group_add_service_strlst( + idata->group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, + purple_account_get_username(data->account), + ICHAT_SERVICE, 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_UNSPEC, 0, + purple_account_get_username(data->account), + ICHAT_SERVICE, NULL, lst); + break; + } + + /* Free the memory used by temp data */ + avahi_string_list_free(lst); + + if (publish_result < 0) { + purple_debug_error("bonjour", + "Failed to add the " ICHAT_SERVICE " service. Error: %s\n", + avahi_strerror(publish_result)); + return FALSE; + } + + if ((publish_result = avahi_entry_group_commit(idata->group)) < 0) { + purple_debug_error("bonjour", + "Failed to commit " ICHAT_SERVICE " service. Error: %s\n", + avahi_strerror(publish_result)); + return FALSE; + } + + return TRUE; +} + +gboolean _mdns_browse(BonjourDnsSd *data) { + AvahiSessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); + + idata->sb = avahi_service_browser_new(idata->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, ICHAT_SERVICE, NULL, 0, _browser_callback, data->account); + if (!idata->sb) { + + purple_debug_error("bonjour", + "Unable to initialize service browser. Error: %s\n.", + avahi_strerror(avahi_client_errno(idata->client))); + return FALSE; + } + + return TRUE; +} + +/* This is done differently than with Howl/Apple Bonjour */ +guint _mdns_register_to_mainloop(BonjourDnsSd *data) { + return 0; +} + +void _mdns_stop(BonjourDnsSd *data) { + AvahiSessionImplData *idata = data->mdns_impl_data; + + if (idata == NULL || idata->client == NULL) + return; + + if (idata->sb != NULL) + avahi_service_browser_free(idata->sb); + + avahi_client_free(idata->client); + avahi_glib_poll_free(idata->glib_poll); + + g_free(idata); + + data->mdns_impl_data = NULL; +} + +void _mdns_init_buddy(BonjourBuddy *buddy) { +} + +void _mdns_delete_buddy(BonjourBuddy *buddy) { +} + +void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) { +} diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/bonjour/mdns_common.c --- a/libpurple/protocols/bonjour/mdns_common.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Mon Aug 06 01:45:24 2007 +0000 @@ -111,5 +111,6 @@ _mdns_stop(data); gc = purple_account_get_connection(data->account); - purple_input_remove(gc->inpa); + if (gc->inpa > 0) + purple_input_remove(gc->inpa); } diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/bonjour/mdns_howl.c --- a/libpurple/protocols/bonjour/mdns_howl.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_howl.c Mon Aug 06 01:45:24 2007 +0000 @@ -145,7 +145,7 @@ break; case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: purple_debug_info("bonjour", "_browser_reply --> Remove service\n"); - gb = purple_find_buddy((PurpleAccount*)extra, name); + gb = purple_find_buddy(account, name); if (gb != NULL) { bonjour_buddy_delete(gb->proto_data); @@ -258,14 +258,14 @@ break; } + /* Free the memory used by temp data */ + sw_text_record_fina(dns_data); + if (publish_result != SW_OKAY) { - purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n"); + purple_debug_error("bonjour", "Unable to publish or change the status of the " ICHAT_SERVICE " service.\n"); return FALSE; } - /* Free the memory used by temp data */ - sw_text_record_fina(dns_data); - return TRUE; } @@ -283,7 +283,7 @@ guint _mdns_register_to_mainloop(BonjourDnsSd *data) { HowlSessionImplData *idata = data->mdns_impl_data; - g_return_val_if_fail(idata != NULL, FALSE); + g_return_val_if_fail(idata != NULL, 0); return purple_input_add(sw_discovery_socket(idata->session), PURPLE_INPUT_READ, _mdns_handle_event, idata->session); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/bonjour/mdns_win32.c --- a/libpurple/protocols/bonjour/mdns_win32.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Mon Aug 06 01:45:24 2007 +0000 @@ -340,7 +340,7 @@ guint _mdns_register_to_mainloop(BonjourDnsSd *data) { Win32SessionImplData *idata = data->mdns_impl_data; - g_return_val_if_fail(idata != NULL, FALSE); + g_return_val_if_fail(idata != NULL, 0); return purple_input_add(DNSServiceRefSockFD(idata->browser), PURPLE_INPUT_READ, _mdns_handle_event, idata->browser); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/buddy_opt.c --- a/libpurple/protocols/qq/buddy_opt.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Mon Aug 06 01:45:24 2007 +0000 @@ -270,11 +270,11 @@ if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { read_packet_b(data, &cursor, len, &reply); if (reply != QQ_ADD_BUDDY_AUTH_REPLY_OK) { - purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy with auth request fails\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy with auth request failed\n"); if (NULL == (segments = split_data(data, len, "\x1f", 2))) return; msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); - purple_notify_error(gc, NULL, _("Add buddy with auth request fails"), msg_utf8); + purple_notify_error(gc, NULL, _("Add buddy with auth request failed"), msg_utf8); g_free(msg_utf8); } else { purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy with auth request OK\n"); @@ -305,6 +305,7 @@ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove buddy fails\n"); } else { /* if reply */ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove buddy OK\n"); + /* TODO: We don't really need to notify the user about this, do we? */ purple_notify_info(gc, NULL, _("You have successfully removed a buddy"), NULL); } } else { @@ -333,7 +334,8 @@ purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove self fails\n"); else { /* if reply */ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove self from a buddy OK\n"); - purple_notify_info(gc, NULL, _("You have successfully removed yourself from a buddy"), NULL); + /* TODO: Does the user really need to be notified about this? */ + purple_notify_info(gc, NULL, _("You have successfully removed yourself from your friend's buddy list"), NULL); } } else { purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt remove self reply\n"); @@ -413,7 +415,7 @@ g_free(nombre); } else { /* add OK */ qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE); - msg = g_strdup_printf(_("You have added %d in buddy list"), for_uid); + msg = g_strdup_printf(_("You have added %d to buddy list"), for_uid); purple_notify_info(gc, NULL, msg, NULL); g_free(msg); } diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/group.c --- a/libpurple/protocols/qq/group.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/group.c Mon Aug 06 01:45:24 2007 +0000 @@ -117,7 +117,7 @@ purple_roomlist_set_in_progress(qd->roomlist, TRUE); purple_request_input(gc, _("QQ Qun"), - _("Please input external group ID"), + _("Please enter external group ID"), _("You can only search for permanent QQ groups\n"), NULL, FALSE, FALSE, NULL, _("Search"), G_CALLBACK(_qq_group_search_callback), diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/group_im.c Mon Aug 06 01:45:24 2007 +0000 @@ -123,7 +123,7 @@ convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT); - msg = g_strdup_printf(_("User %d applied to join group %d"), user_uid, external_group_id); + msg = g_strdup_printf(_("User %d requested to join group %d"), user_uid, external_group_id); reason = g_strdup_printf(_("Reason: %s"), reason_utf8); g = g_new0(group_member_opt, 1); @@ -177,7 +177,7 @@ convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT); msg = g_strdup_printf - (_("You request to join group %d has been rejected by admin %d"), external_group_id, admin_uid); + (_("Your request to join group %d has been rejected by admin %d"), external_group_id, admin_uid); reason = g_strdup_printf(_("Reason: %s"), reason_utf8); purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason); @@ -218,7 +218,7 @@ convert_as_pascal_string(*cursor, &reason_utf8, QQ_CHARSET_DEFAULT); msg = g_strdup_printf - (_("You request to join group %d has been approved by admin %d"), external_group_id, admin_uid); + (_("Your request to join group %d has been approved by admin %d"), external_group_id, admin_uid); purple_notify_warning(gc, _("QQ Qun Operation"), msg, NULL); @@ -254,7 +254,7 @@ g_return_if_fail(external_group_id > 0 && uid > 0); - msg = g_strdup_printf(_("You [%d] has exit group \"%d\""), uid, external_group_id); + msg = g_strdup_printf(_("You [%d] have left group \"%d\""), uid, external_group_id); purple_notify_info(gc, _("QQ Qun Operation"), msg, NULL); group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); @@ -288,7 +288,7 @@ g_return_if_fail(external_group_id > 0 && uid > 0); - msg = g_strdup_printf(_("You [%d] has been added by group \"%d\""), uid, external_group_id); + msg = g_strdup_printf(_("You [%d] have been added to group \"%d\""), uid, external_group_id); purple_notify_info(gc, _("QQ Qun Operation"), msg, _("This group has been added to your buddy list")); group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/group_internal.c --- a/libpurple/protocols/qq/group_internal.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/group_internal.c Mon Aug 06 01:45:24 2007 +0000 @@ -38,7 +38,7 @@ switch (group->my_status) { case QQ_GROUP_MEMBER_STATUS_NOT_MEMBER: - status_desc = _("I am not member"); + status_desc = _("I am not a member"); break; case QQ_GROUP_MEMBER_STATUS_IS_MEMBER: status_desc = _("I am a member"); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/group_join.c --- a/libpurple/protocols/qq/group_join.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/group_join.c Mon Aug 06 01:45:24 2007 +0000 @@ -230,7 +230,7 @@ purple_blist_remove_chat(chat); qq_group_delete_internal_record(qd, internal_group_id); } - purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully exited the group"), NULL); + purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the group"), NULL); } else { purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Invalid exit group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes); @@ -254,8 +254,8 @@ if (bytes == expected_bytes) purple_notify_info - (gc, _("QQ Group Auth"), - _("Your authorization operation has been accepted by the QQ server"), NULL); + (gc, _("QQ Group Auth"), + _("Your authorization request has been accepted by the QQ server"), NULL); else purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Invalid join group reply, expect %d bytes, read %d bytes\n", expected_bytes, bytes); @@ -325,8 +325,8 @@ errno = 0; external_group_id = strtol(external_group_id_ptr, NULL, 10); if (errno != 0) { - purple_notify_error(gc, _("Error"), - _("You inputted a group id outside the acceptable range"), NULL); + purple_notify_error(gc, _("Error"), + _("You entered a group ID outside the acceptable range"), NULL); return; } @@ -357,12 +357,12 @@ g->uid = internal_group_id; purple_request_action(gc, _("QQ Qun Operation"), - _("Are you sure to exit this Qun?"), + _("Are you sure you want to leave this Qun?"), _ ("Note, if you are the creator, \nthis operation will eventually remove this Qun."), 1, purple_connection_get_account(gc), NULL, NULL, g, 2, _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), - _("Go ahead"), G_CALLBACK(_qq_group_exit_with_gc_and_id)); + _("Continue"), G_CALLBACK(_qq_group_exit_with_gc_and_id)); } diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/group_opt.c --- a/libpurple/protocols/qq/group_opt.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/group_opt.c Mon Aug 06 01:45:24 2007 +0000 @@ -120,8 +120,8 @@ { g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); - qq_send_packet_get_info(g->gc, g->member, TRUE); /* we wanna see window */ - purple_request_action(g->gc, NULL, _("Do you wanna approve the request?"), "", 2, + qq_send_packet_get_info(g->gc, g->member, TRUE); /* we want to see window */ + purple_request_action(g->gc, NULL, _("Do you want to approve the request?"), "", 2, purple_connection_get_account(g->gc), NULL, NULL, g, 2, _("Reject"), G_CALLBACK(qq_group_reject_application_with_struct), @@ -134,7 +134,7 @@ g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); msg1 = g_strdup_printf(_("You rejected %d's request"), g->member); - msg2 = g_strdup(_("Input your reason:")); + msg2 = g_strdup(_("Enter your reason:")); nombre = uid_to_purple_name(g->member); purple_request_input(g->gc, /* title */ NULL, msg1, msg2, @@ -232,7 +232,7 @@ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->external_group_id); - purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modify Qun member"), NULL); + purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun member"), NULL); } void qq_group_modify_info(PurpleConnection *gc, qq_group *group) @@ -302,7 +302,7 @@ purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->external_group_id); qq_group_refresh(gc, group); - purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modify Qun information"), NULL); + purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL); } /* we create a very simple group first, and then let the user to modify */ diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/im.c --- a/libpurple/protocols/qq/im.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/im.c Mon Aug 06 01:45:24 2007 +0000 @@ -573,7 +573,7 @@ read_packet_b(data, &cursor, len, &reply); if (reply != QQ_SEND_IM_REPLY_OK) { purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Send IM fail\n"); - purple_notify_error(gc, _("Server ACK"), _("Failed to send IM."), NULL); + purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL); } else purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM ACK OK\n"); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/keep_alive.c --- a/libpurple/protocols/qq/keep_alive.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/keep_alive.c Mon Aug 06 01:45:24 2007 +0000 @@ -84,7 +84,7 @@ /* segments[0] and segment[1] are all 0x30 ("0") */ qd->all_online = strtol(segments[2], NULL, 10); if(0 == qd->all_online) - purple_connection_error(gc, _("Keep alive error, seems connection lost!")); + purple_connection_error(gc, _("Keep alive error")); g_free(qd->my_ip); qd->my_ip = g_strdup(segments[3]); qd->my_port = strtol(segments[4], NULL, 10); diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/login_logout.c --- a/libpurple/protocols/qq/login_logout.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/login_logout.c Mon Aug 06 01:45:24 2007 +0000 @@ -405,7 +405,7 @@ ">>> %d bytes -> [default] decrypt and dump\n%s", buf_len, hex_dump); try_dump_as_gbk(buf, buf_len); - purple_connection_error(gc, _("Request login token error!")); + purple_connection_error(gc, _("Error requesting login token")); } g_free(hex_dump); } diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/qq.c Mon Aug 06 01:45:24 2007 +0000 @@ -195,7 +195,8 @@ { qq_buddy *q_bud; gchar *ip_str; - char *tmp, *tmp2; + char *tmp; + const char *tmp2; g_return_if_fail(b != NULL); @@ -206,11 +207,12 @@ { ip_str = gen_ip_str(q_bud->ip); if (strlen(ip_str) != 0) { - tmp = g_strdup_printf(_("%s Address"), - ((q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) ? "TCP" : "UDP")); - tmp2 = g_strdup_printf("%s:%d", ip_str, q_bud->port); - purple_notify_user_info_add_pair(user_info, tmp, tmp2); - g_free(tmp2); + if (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) + tmp2 = _("TCP Address"); + else + tmp2 = _("UDP Address"); + tmp = g_strdup_printf("%s:%d", ip_str, q_bud->port); + purple_notify_user_info_add_pair(user_info, tmp2, tmp); g_free(tmp); } g_free(ip_str); @@ -238,7 +240,7 @@ if (q_bud->level) { tmp = g_strdup_printf("%d", q_bud->level); purple_notify_user_info_add_pair(user_info, _("Level"), tmp); - g_free(tmp); + g_free(tmp); } /* For debugging */ /* @@ -275,19 +277,19 @@ GList *types = NULL; status = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, - "available", _("QQ: Available"), FALSE, TRUE, FALSE); + "available", _("Available"), FALSE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_AWAY, - "away", _("QQ: Away"), FALSE, TRUE, FALSE); + "away", _("Away"), FALSE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, - "invisible", _("QQ: Invisible"), FALSE, TRUE, FALSE); + "invisible", _("Invisible"), FALSE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, - "offline", _("QQ: Offline"), FALSE, TRUE, FALSE); + "offline", _("Offline"), FALSE, TRUE, FALSE); types = g_list_append(types, status); status = purple_status_type_new_full(PURPLE_STATUS_MOBILE, @@ -416,7 +418,7 @@ g->uid = uid; purple_request_action(gc, _("Block Buddy"), - _("Are you sure to block this buddy?"), NULL, + _("Are you sure you want to block this buddy?"), NULL, 1, g, 2, _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), @@ -470,7 +472,7 @@ PurpleConnection *gc = (PurpleConnection *) action->context; purple_request_input(gc, _("Create QQ Qun"), _("Input Qun name here"), - _("Only QQ member can create permanent Qun"), + _("Only QQ members can create permanent Qun"), "OpenQ", FALSE, FALSE, NULL, _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, gc); } @@ -528,7 +530,7 @@ PurplePluginAction *act; m = NULL; - act = purple_plugin_action_new(_("Modify My Information"), _qq_menu_modify_my_info); + act = purple_plugin_action_new(_("Set My Information"), _qq_menu_modify_my_info); m = g_list_append(m, act); act = purple_plugin_action_new(_("Change Password"), _qq_menu_change_password); @@ -555,7 +557,7 @@ PurpleMenuAction *act; m = NULL; - act = purple_menu_action_new(_("Exit this QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); + act = purple_menu_action_new(_("Leave this QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); m = g_list_append(m, act); /* TODO: enable this diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/qq_proxy.c --- a/libpurple/protocols/qq/qq_proxy.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/qq_proxy.c Mon Aug 06 01:45:24 2007 +0000 @@ -493,13 +493,8 @@ errno = 0; ret = send(qd->fd, data, len, 0); } - if (ret == -1) { - purple_connection_error(qd->gc, _("Socket send error")); - return ret; - } else if (errno == ECONNREFUSED) { - purple_connection_error(qd->gc, _("Connection refused")); - return ret; - } + if (ret == -1) + purple_connection_error(qd->gc, strerror(errno)); return ret; } diff -r 5a5ca6438308 -r 580e0bfe7e33 libpurple/protocols/qq/sys_msg.c --- a/libpurple/protocols/qq/sys_msg.c Mon Aug 06 01:36:57 2007 +0000 +++ b/libpurple/protocols/qq/sys_msg.c Mon Aug 06 01:45:24 2007 +0000 @@ -80,12 +80,11 @@ uid = g->uid; g_return_if_fail(gc != 0 && uid != 0); - qq_send_packet_get_info(gc, uid, TRUE); /* we wanna see window */ + qq_send_packet_get_info(gc, uid, TRUE); /* we want to see window */ nombre = uid_to_purple_name(uid); - /* TODO: 'wanna' is not an appropriate word for this string. Fix after string freeze. */ purple_request_action - (gc, NULL, _("Do you wanna approve the request?"), "", 2, + (gc, NULL, _("Do you want to approve the request?"), "", 2, purple_connection_get_account(gc), nombre, NULL, g, 2, _("Reject"), G_CALLBACK(qq_reject_add_request_with_gc_and_uid), @@ -105,11 +104,10 @@ uid = g->uid; g_return_if_fail(gc != 0 && uid != 0); - qq_send_packet_get_info(gc, uid, TRUE); /* we wanna see window */ - /* TODO: 'wanna' is not an appropriate word for this string. Fix after string freeze. */ + qq_send_packet_get_info(gc, uid, TRUE); /* we want to see window */ nombre = uid_to_purple_name(uid); purple_request_action - (gc, NULL, _("Do you wanna add this buddy?"), "", 2, + (gc, NULL, _("Do you want to add this buddy?"), "", 2, purple_connection_get_account(gc), nombre, NULL, g, 2, _("Cancel"), NULL, @@ -175,7 +173,7 @@ _("Add"), G_CALLBACK(qq_add_buddy_with_gc_and_uid), _("Search"), G_CALLBACK(_qq_search_before_add_with_gc_and_uid)); } else { - message = g_strdup_printf(_("%s has added you [%s]"), from, to); + message = g_strdup_printf(_("%s has added you [%s] to his or her buddy list"), from, to); _qq_sys_msg_log_write(gc, message, from); purple_notify_info(gc, NULL, message, NULL); } @@ -211,7 +209,7 @@ qd = (qq_data *) gc->proto_data; qq_add_buddy_by_recv_packet(gc, strtol(from, NULL, 10), TRUE, TRUE); - message = g_strdup_printf(_("User %s has approved your request"), from); + message = g_strdup_printf(_("User %s approved your request"), from); _qq_sys_msg_log_write(gc, message, from); purple_notify_info(gc, NULL, message, NULL); @@ -236,9 +234,8 @@ name = uid_to_purple_name(uid); - /* TODO: 'wanna' is not an appropriate word for this string. Fix after string freeze */ /* TODO: this should go through purple_account_request_authorization() */ - message = g_strdup_printf(_("%s wanna add you [%s] as friends"), from, to); + message = g_strdup_printf(_("%s wants to add you [%s] as a friend"), from, to); reason = g_strdup_printf(_("Message: %s"), msg_utf8); _qq_sys_msg_log_write(gc, message, from); diff -r 5a5ca6438308 -r 580e0bfe7e33 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Mon Aug 06 01:36:57 2007 +0000 +++ b/pidgin/gtkconv.c Mon Aug 06 01:45:24 2007 +0000 @@ -187,6 +187,9 @@ static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); +static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, + int width, int height); + static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; GtkStyle *style = gtk_widget_get_style(gtkconv->imhtml); @@ -7169,25 +7172,28 @@ purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/tabs", TRUE); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/tab_side", GTK_POS_TOP); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/x", 0); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/y", 0); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE); purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", ""); /* Conversations -> Chat */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat"); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", 410); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_height", 160); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", 50); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", 80); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/height", 0); + /* Conversations -> IM */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/im"); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/x", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/y", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/width", 0); + purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/height", 0); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons", TRUE); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width", 410); - purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height", 160); purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 50); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE); @@ -8331,10 +8337,8 @@ return FALSE; /* don't save if nothing changed */ - if (x == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/x") && - y == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/y") && - event->width == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_width") && - event->height == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/default_height")) + if (x == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/x") && + y == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/y")) return FALSE; /* carry on normally */ /* don't save off-screen positioning */ @@ -8344,9 +8348,9 @@ y > gdk_screen_height()) return FALSE; /* carry on normally */ - /* store the position */ - purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/x", x); - purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/y", y); + /* store the position */ + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/x", x); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/y", y); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/width", event->width); purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/height", event->height); @@ -8356,35 +8360,38 @@ } static void -pidgin_conv_restore_position(PidginWindow *win) { - int conv_x, conv_y, conv_width, conv_height; - - conv_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"); - +pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y, + int conv_width, int conv_height) +{ /* if the window exists, is hidden, we're saving positions, and the * position is sane... */ - if (win && win->window && - !GTK_WIDGET_VISIBLE(win->window) && conv_width != 0) { - - conv_x = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/x"); - conv_y = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/y"); - conv_height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height"); - - /* ...check position is on screen... */ - if (conv_x >= gdk_screen_width()) - conv_x = gdk_screen_width() - 100; - else if (conv_x + conv_width < 0) - conv_x = 100; - - if (conv_y >= gdk_screen_height()) - conv_y = gdk_screen_height() - 100; - else if (conv_y + conv_height < 0) - conv_y = 100; - - /* ...and move it back. */ - gtk_window_move(GTK_WINDOW(win->window), conv_x, conv_y); - gtk_window_resize(GTK_WINDOW(win->window), conv_width, conv_height); - } + if (win && win->window && + !GTK_WIDGET_VISIBLE(win->window) && conv_width != 0) { + + /* ...check position is on screen... */ + if (conv_x >= gdk_screen_width()) + conv_x = gdk_screen_width() - 100; + else if (conv_x + conv_width < 0) + conv_x = 100; + + if (conv_y >= gdk_screen_height()) + conv_y = gdk_screen_height() - 100; + else if (conv_y + conv_height < 0) + conv_y = 100; + + /* ...and move it back. */ + gtk_window_move(GTK_WINDOW(win->window), conv_x, conv_y); + gtk_window_resize(GTK_WINDOW(win->window), conv_width, conv_height); + } +} + +static void +pidgin_conv_restore_position(PidginWindow *win) { + pidgin_conv_set_position_size(win, + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/x"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/y"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/width"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/height")); } PidginWindow * @@ -8409,8 +8416,6 @@ g_signal_connect(G_OBJECT(win->window), "delete_event", G_CALLBACK(close_win_cb), win); - g_signal_connect(G_OBJECT(win->window), "configure_event", - G_CALLBACK(gtk_conv_configure_cb), NULL); g_signal_connect(G_OBJECT(win->window), "focus_in_event", G_CALLBACK(focus_win_cb), win); @@ -8937,6 +8942,9 @@ if (win == NULL) { win = pidgin_conv_window_new(); + g_signal_connect(G_OBJECT(win->window), "configure_event", + G_CALLBACK(gtk_conv_configure_cb), NULL); + pidgin_conv_window_add_gtkconv(win, conv); pidgin_conv_window_show(win); } else { @@ -8945,6 +8953,53 @@ } /* This one places conversations in the last made window of the same type. */ +static gboolean +conv_placement_last_created_win_type_configured_cb(GtkWidget *w, + GdkEventConfigure *event, PidginConversation *conv) +{ + int x, y; + PurpleConversationType type = purple_conversation_get_type(conv->active_conv); + GList *all; + + if (GTK_WIDGET_VISIBLE(w)) + gtk_window_get_position(GTK_WINDOW(w), &x, &y); + else + return FALSE; /* carry on normally */ + + /* Workaround for GTK+ bug # 169811 - "configure_event" is fired + * when the window is being maximized */ + if (gdk_window_get_state(w->window) & GDK_WINDOW_STATE_MAXIMIZED) + return FALSE; + + /* don't save off-screen positioning */ + if (x + event->width < 0 || + y + event->height < 0 || + x > gdk_screen_width() || + y > gdk_screen_height()) + return FALSE; /* carry on normally */ + + for (all = conv->convs; all != NULL; all = all->next) { + if (type != purple_conversation_get_type(all->data)) { + /* this window has different types of conversation, don't save */ + return FALSE; + } + } + + if (type == PURPLE_CONV_TYPE_IM) { + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/x", x); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/y", y); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/width", event->width); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/im/height", event->height); + } else if (type == PURPLE_CONV_TYPE_CHAT) { + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", x); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", y); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", event->width); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/height", event->height); + } + + return FALSE; +} + static void conv_placement_last_created_win_type(PidginConversation *conv) { @@ -8955,8 +9010,26 @@ if (win == NULL) { win = pidgin_conv_window_new(); + if (PURPLE_CONV_TYPE_IM == purple_conversation_get_type(conv->active_conv) || + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/width") == 0) { + pidgin_conv_set_position_size(win, + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/x"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/y"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height")); + } else if (PURPLE_CONV_TYPE_CHAT == purple_conversation_get_type(conv->active_conv)) { + pidgin_conv_set_position_size(win, + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/x"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/y"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/width"), + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/chat/height")); + } + pidgin_conv_window_add_gtkconv(win, conv); pidgin_conv_window_show(win); + + g_signal_connect(G_OBJECT(win->window), "configure_event", + G_CALLBACK(conv_placement_last_created_win_type_configured_cb), conv); } else pidgin_conv_window_add_gtkconv(win, conv); } @@ -8968,6 +9041,8 @@ PidginWindow *win; win = pidgin_conv_window_new(); + g_signal_connect(G_OBJECT(win->window), "configure_event", + G_CALLBACK(gtk_conv_configure_cb), NULL); pidgin_conv_window_add_gtkconv(win, conv); diff -r 5a5ca6438308 -r 580e0bfe7e33 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Mon Aug 06 01:36:57 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Aug 06 01:45:24 2007 +0000 @@ -2236,4 +2236,13 @@ purple_prefs_remove(PIDGIN_PREFS_ROOT "/away/queue_messages"); purple_prefs_remove(PIDGIN_PREFS_ROOT "/away"); purple_prefs_remove("/plugins/gtk/docklet/queue_messages"); + + purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/chat/default_width"); + purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/chat/default_height"); + purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/im/default_width"); + purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/im/default_height"); + purple_prefs_rename(PIDGIN_PREFS_ROOT "/conversations/x", + PIDGIN_PREFS_ROOT "/conversations/im/x"); + purple_prefs_rename(PIDGIN_PREFS_ROOT "/conversations/y", + PIDGIN_PREFS_ROOT "/conversations/im/y"); }