Mon, 30 Jul 2007 00:05:02 +0000
propagate from branch 'im.pidgin.pidgin' (head 75a15398655acecce933518015eac8b6a7340fd2)
to branch 'im.pidgin.soc.2007.xmpp' (head 6065977448124f2e46cdfa43291659676625bc65)
| libpurple/protocols/jabber/jabber.c | file | annotate | diff | comparison | revisions | |
| libpurple/protocols/jabber/presence.c | file | annotate | diff | comparison | revisions |
--- a/AUTHORS Mon Jul 30 00:01:08 2007 +0000 +++ b/AUTHORS Mon Jul 30 00:05:02 2007 +0000 @@ -19,6 +19,7 @@ Daniel 'datallah' Atallah - Developer Ethan 'Paco-Paco' Blanton - Developer Thomas Butter - Developer +Ka-Hing Cheung - Developer Sadrul Habib Chowdhury - Developer Mark 'KingAnt' Doliner - Developer Christian 'ChipX86' Hammond - Developer & Webmaster @@ -38,7 +39,6 @@ Crazy Patch Writers: ------------------- John 'rekkanoryo' Bailey -Ka-Hing 'javabsp' Cheung Felipe 'shx' Contreras Decklin Foster Casey Harkins
--- a/ChangeLog Mon Jul 30 00:01:08 2007 +0000 +++ b/ChangeLog Mon Jul 30 00:05:02 2007 +0000 @@ -1,6 +1,6 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.1.0 (??/??/????): +version 2.1.0 (07/28/2007): libpurple: * Core changes to allow UIs to use second-granularity for scheduling. Pidgin and Finch, which use the glib event loop, were changed to use
--- a/ChangeLog.API Mon Jul 30 00:01:08 2007 +0000 +++ b/ChangeLog.API Mon Jul 30 00:05:02 2007 +0000 @@ -1,6 +1,6 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul -version 2.1.0 (??/??/????): +version 2.1.0 (7/28/2007): libpurple: Added: * purple-remote: added getstatus command @@ -29,6 +29,8 @@ * purple_xfer_get_remote_user * purple_pounces_get_all_for_ui * purple_prefs_get_children_names + * added displaying-email-notification and + displaying-emails-notification signals Changed: * The documentation of the following functions now properly @@ -74,6 +76,8 @@ * pidgin_menu_position_func_helper * pidgin_blist_get_name_markup, returns the buddy list markup text for a given buddy. + * pidgin_blist_draw_tooltip and pidgin_blist_tooltip_destroy + for creating blist tooltips from outside of buddy list code * pidgin_themes_remove_smiley_theme Changed:
--- a/ChangeLog.win32 Mon Jul 30 00:01:08 2007 +0000 +++ b/ChangeLog.win32 Mon Jul 30 00:05:02 2007 +0000 @@ -1,4 +1,4 @@ -version 2.1.0 (??/??/????): +version 2.1.0 (7/28/2007): * Updated launcher application (pidgin.exe) to support portable mode via `pidgin.exe --portable-mode` or by renaming the binary to `pidgin-portable.exe`
--- a/NEWS Mon Jul 30 00:01:08 2007 +0000 +++ b/NEWS Mon Jul 30 00:05:02 2007 +0000 @@ -1,5 +1,14 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +2.1.0 (7/28/2007): + Sean: This release took a bit longer than 3 weeks, but boy is it + worth it! We're beginning to experiment with new UI concepts and + this release features a largely re-designed conversation window. + We've closed 150 tickets for this release; much thanks go to all + the developers, translators, and testers who made this possible. + + Ka-Hing: Sean said no one else NEWS'ed, so I figure I should. + 2.0.2 (6/14/2007): Sean: Another big maintenance release. Again, about 100 tickets were resolved in this release, and they keep coming in. Lots of bug fixes,
--- a/configure.ac Mon Jul 30 00:01:08 2007 +0000 +++ b/configure.ac Mon Jul 30 00:05:02 2007 +0000 @@ -47,7 +47,7 @@ m4_define([purple_major_version], [2]) m4_define([purple_minor_version], [1]) m4_define([purple_micro_version], [0]) -m4_define([purple_version_suffix], [devel]) +m4_define([purple_version_suffix], []) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix])) @@ -56,7 +56,7 @@ m4_define([gnt_major_version], [2]) m4_define([gnt_minor_version], [0]) m4_define([gnt_micro_version], [0]) -m4_define([gnt_version_suffix], [devel]) +m4_define([gnt_version_suffix], []) m4_define([gnt_version], [gnt_major_version.gnt_minor_version.gnt_micro_version]) m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
--- a/doc/notify-signals.dox Mon Jul 30 00:01:08 2007 +0000 +++ b/doc/notify-signals.dox Mon Jul 30 00:05:02 2007 +0000 @@ -2,6 +2,8 @@ @signals @signal displaying-userinfo + @signal displaying-email-notification + @signal displaying-emails-notification @endsignals @signaldef displaying-userinfo @@ -18,5 +20,37 @@ @param user_info The information to be displayed, as PurpleNotifyUserInfoEntry objects @endsignaldef + @signaldef displaying-email-notification + @signalproto +void (*displaying_email_notification)(const char *subject, + const char *from, + const char *to, + const char *url); + @endsignalproto + @signaldesc + Emitted before email notification is handed to the UI to display. + @param subject Subject of email being notified of. + @param from Who the email is from. + @param to Who the email is to. + @param url A url to view the email. + @endsignaldef + + @signaldef displaying-emails-notification + @signalproto +void (*displaying_emails_notification)(const char **subjects, + const char **froms, + const char **tos, + const char **urls, + guint count); + @endsignalproto + @signaldesc + Emitted before notification of multiple emails is handed to the UI to display. + @param subjects Subjects of emails being notified of. + @param froms Who the emails are from. + @param tos Who the emails are to. + @param urls The urls to view the emails. + @param count Number of emails being notified of. + @endsignaldef + */ // vim: syntax=c tw=75 et
--- a/doc/pidgin.1.in Mon Jul 30 00:01:08 2007 +0000 +++ b/doc/pidgin.1.in Mon Jul 30 00:05:02 2007 +0000 @@ -539,6 +539,8 @@ .br Thomas Butter (developer) .br + Ka-Hing Cheung (developer) +.br Sadrul Habib Chowdhury (developer) .br Mark 'KingAnt' Doliner (developer) <\fIthekingant@users.sourceforge.net\fR> @@ -575,8 +577,6 @@ John 'rekkanoryo' Bailey .br -Ka-Hing 'javabsp' Cheung -.br Felipe 'shx' Contreras .br Decklin Foster
--- a/finch/gntblist.c Mon Jul 30 00:01:08 2007 +0000 +++ b/finch/gntblist.c Mon Jul 30 00:05:02 2007 +0000 @@ -354,11 +354,13 @@ PurpleGroup *grp; GHashTable *hash = NULL; PurpleConnection *gc; + gboolean autojoin; account = purple_request_fields_get_account(allfields, "account"); name = purple_request_fields_get_string(allfields, "name"); alias = purple_request_fields_get_string(allfields, "alias"); group = purple_request_fields_get_string(allfields, "group"); + autojoin = purple_request_fields_get_bool(allfields, "autojoin"); if (!purple_account_is_connected(account) || !name || !*name) return; @@ -380,6 +382,9 @@ } purple_blist_add_chat(chat, grp, NULL); purple_blist_alias_chat(chat, alias); + purple_blist_node_set_bool((PurpleBlistNode*)chat, "gnt-autojoin", autojoin); + if (autojoin) + serv_join_chat(chat->account->gc, chat->components); } } @@ -407,6 +412,9 @@ field = purple_request_field_string_new("group", _("Group"), grp ? grp->name : NULL, FALSE); purple_request_field_group_add_field(group, field); + field = purple_request_field_bool_new("autojoin", _("Auto-join"), FALSE); + purple_request_field_group_add_field(group, field); + purple_request_fields(NULL, _("Add Chat"), NULL, _("You can edit more information from the context menu later."), fields, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL, @@ -1317,8 +1325,10 @@ strip = purple_markup_strip_html(tmp); g_string_append(str, strip); - if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE)) + if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOBILE)) { + g_string_append(str, "\n"); g_string_append(str, _("On Mobile")); + } g_free(strip); g_free(tmp);
--- a/finch/gntconv.c Mon Jul 30 00:01:08 2007 +0000 +++ b/finch/gntconv.c Mon Jul 30 00:05:02 2007 +0000 @@ -259,7 +259,7 @@ gnt_text_view_scroll(GNT_TEXT_VIEW(ggc->tv), 0); } else { title = get_conversation_title(conv, account); - gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", NULL, TRUE); + gnt_text_view_tag_change(GNT_TEXT_VIEW(ggc->tv), "typing", " ", TRUE); } gnt_screen_rename_widget(ggc->window, title); g_free(title); @@ -588,7 +588,6 @@ char *strip, *newline; GntTextFormatFlags fl = 0; int pos; - gboolean notify; g_return_if_fail(ggconv != NULL); @@ -601,7 +600,7 @@ pos = gnt_text_view_get_lines_below(GNT_TEXT_VIEW(ggconv->tv)); - notify = !!gnt_text_view_tag_change(GNT_TEXT_VIEW(ggconv->tv), "typing", NULL, TRUE); + gnt_text_view_tag_change(GNT_TEXT_VIEW(ggconv->tv), "typing", NULL, TRUE); gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), "\n", GNT_TEXT_FLAG_NORMAL); /* Unnecessary to print the timestamp for delayed message */ @@ -643,7 +642,8 @@ g_free(newline); g_free(strip); - if (notify) { + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM && + purple_conv_im_get_typing_state(PURPLE_CONV_IM(conv)) == PURPLE_TYPING) { strip = g_strdup_printf(_("\n%s is typing..."), purple_conversation_get_name(conv)); gnt_text_view_append_text_with_tag(GNT_TEXT_VIEW(ggconv->tv), strip, GNT_TEXT_FLAG_DIM, "typing");
--- a/libpurple/Makefile.mingw Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/Makefile.mingw Mon Jul 30 00:05:02 2007 +0000 @@ -127,8 +127,8 @@ ## CLEAN RULES ## clean: - rm -f $(OBJECTS) $(RC_SRC) - rm -f $(TARGET).dll $(TARGET).dll.a $(PURPLE_VERSION_H) + rm -f $(OBJECTS) $(RC_SRC) $(PURPLE_VERSION_H) + rm -f $(TARGET).dll $(TARGET).dll.a $(TARGET).def $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
--- a/libpurple/idle.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/idle.c Mon Jul 30 00:05:02 2007 +0000 @@ -30,8 +30,6 @@ #include "savedstatuses.h" #include "signals.h" -#define IDLEMARK 600 /* 10 minutes! */ - typedef enum { PURPLE_IDLE_NOT_AWAY = 0, @@ -121,7 +119,7 @@ gboolean report_idle = TRUE; gint away_seconds = 0; gint idle_recheck_interval = 0; - + gint idle_poll_seconds = purple_prefs_get_int("/purple/away/mins_before_away") * 60; purple_signal_emit(purple_blist_get_handle(), "update-idle"); idle_reporting = purple_prefs_get_string("/purple/away/idle_reporting"); @@ -132,7 +130,7 @@ { /* Use system idle time (mouse or keyboard movement, etc.) */ time_idle = idle_ui_ops->get_time_idle(); - idle_recheck_interval = 60; + idle_recheck_interval = 1; } else if (!strcmp(idle_reporting, "purple")) { @@ -153,7 +151,7 @@ if ((idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL)) { time_idle = idle_ui_ops->get_time_idle(); - idle_recheck_interval = 60; + idle_recheck_interval = 1; } else { @@ -173,7 +171,7 @@ } } - time_until_next_idle_event = IDLEMARK - time_idle; + time_until_next_idle_event = idle_poll_seconds - time_idle; if (time_until_next_idle_event < 0) { /* If we're already idle, check again as appropriate. */ @@ -197,7 +195,7 @@ } /* Idle reporting stuff */ - if (report_idle && (time_idle >= IDLEMARK)) + if (report_idle && (time_idle >= idle_poll_seconds)) { GList *l; for (l = purple_connections_get_all(); l != NULL; l = l->next) @@ -206,7 +204,7 @@ set_account_idle(purple_connection_get_account(gc), time_idle); } } - else if (!report_idle || (time_idle < IDLEMARK)) + else if (!report_idle || (time_idle < idle_poll_seconds )) { while (idled_accts != NULL) set_account_unidle(idled_accts->data); @@ -306,6 +304,11 @@ static gboolean _do_purple_idle_touch_cb(gpointer data) { + int idle_poll_minutes = purple_prefs_get_int("/purple/away/mins_before_away"); + + /* +1 more for g_timeout_add_seconds rounding. */ + idle_timer = purple_timeout_add_seconds((idle_poll_minutes * 60) + 2, check_idleness_timer, NULL); + purple_idle_touch(); return FALSE; @@ -315,11 +318,6 @@ void purple_idle_init() { - /* Add the timer to check if we're idle. - * IDLEMARK + 1 as the boundary, - * +1 more for g_timeout_add_seconds rounding. */ - idle_timer = purple_timeout_add_seconds((IDLEMARK + 2), check_idleness_timer, NULL); - purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg", purple_idle_get_handle(), PURPLE_CALLBACK(im_msg_sent_cb), NULL);
--- a/libpurple/notify.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/notify.c Mon Jul 30 00:05:02 2007 +0000 @@ -112,6 +112,10 @@ info = g_new0(PurpleNotifyInfo, 1); info->type = PURPLE_NOTIFY_EMAIL; info->handle = handle; + + purple_signal_emit(purple_notify_get_handle(), "displaying-email-notification", + subject, from, to, url); + info->ui_handle = ops->notify_email(handle, subject, from, to, url); info->cb = cb; info->cb_user_data = user_data; @@ -164,6 +168,10 @@ info = g_new0(PurpleNotifyInfo, 1); info->type = PURPLE_NOTIFY_EMAILS; info->handle = handle; + + purple_signal_emit(purple_notify_get_handle(), "displaying-emails-notification", + subjects, froms, tos, urls, count); + info->ui_handle = ops->notify_emails(handle, count, detailed, subjects, froms, tos, urls); info->cb = cb; @@ -799,6 +807,21 @@ { gpointer handle = purple_notify_get_handle(); + purple_signal_register(handle, "displaying-email-notification", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER, NULL, 4, + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING), + purple_value_new(PURPLE_TYPE_STRING)); + + purple_signal_register(handle, "displaying-emails-notification", + purple_marshal_VOID__POINTER_POINTER_POINTER_POINTER_UINT, NULL, 5, + purple_value_new(PURPLE_TYPE_POINTER), + purple_value_new(PURPLE_TYPE_POINTER), + purple_value_new(PURPLE_TYPE_POINTER), + purple_value_new(PURPLE_TYPE_POINTER), + purple_value_new(PURPLE_TYPE_UINT)); + purple_signal_register(handle, "displaying-userinfo", purple_marshal_VOID__POINTER_POINTER_POINTER, NULL, 3, purple_value_new(PURPLE_TYPE_SUBTYPE,
--- a/libpurple/plugin.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/plugin.c Mon Jul 30 00:05:02 2007 +0000 @@ -692,7 +692,10 @@ dependency = purple_plugins_find_with_id(dep_name); - dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id); + if (dependency != NULL) + dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id); + else + purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); } if (plugin->native_plugin) {
--- a/libpurple/plugins/perl/common/Account.xs Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/plugins/perl/common/Account.xs Mon Jul 30 00:05:02 2007 +0000 @@ -307,6 +307,9 @@ } g_list_free(list); +void +purple_accounts_restore_current_statuses() + Purple::Account purple_accounts_find(name, protocol) const char * name
--- a/libpurple/plugins/perl/common/BuddyIcon.xs Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/plugins/perl/common/BuddyIcon.xs Mon Jul 30 00:05:02 2007 +0000 @@ -45,6 +45,10 @@ int *width int *height +char * +purple_buddy_icon_get_full_path(icon); + Purple::Buddy::Icon icon + MODULE = Purple::Buddy::Icon PACKAGE = Purple::Buddy::Icons PREFIX = purple_buddy_icons_ PROTOTYPES: ENABLE
--- a/libpurple/plugins/signals-test.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/plugins/signals-test.c Mon Jul 30 00:05:02 2007 +0000 @@ -522,6 +522,26 @@ } /************************************************************************** + * Notify signals callbacks + **************************************************************************/ +static void +notify_email_cb(char *subject, char *from, char *to, char *url) { + purple_debug_misc("signals test", "notify email: subject=%s, from=%s, to=%s, url=%s\n", + subject, from, to, url); +} + +static void +notify_emails_cb(char **subjects, char **froms, char **tos, char **urls, guint count) { + int i; + purple_debug_misc("signals test", "notify emails: count=%d\n", count); + for(i=0; i<count && i<5; i++) { + if(subjects[i]==NULL || froms[i]==NULL || tos[i]==NULL || urls[i]==NULL) continue; + purple_debug_misc("signals test", "notify emails[%d]: subject=%s, from=%s, to=%s, url=%s\n", + i, subjects[i], froms[i], tos[i], urls[i]); + } +} + +/************************************************************************** * Plugin stuff **************************************************************************/ static gboolean @@ -535,6 +555,7 @@ void *ciphers_handle = purple_ciphers_get_handle(); void *ft_handle = purple_xfers_get_handle(); void *sound_handle = purple_sounds_get_handle(); + void *notify_handle = purple_notify_get_handle(); /* Accounts subsystem signals */ purple_signal_connect(accounts_handle, "account-connecting", @@ -666,6 +687,12 @@ purple_signal_connect(sound_handle, "playing-sound-event", plugin, PURPLE_CALLBACK(sound_playing_event_cb), NULL); + /* Notify signals */ + purple_signal_connect(notify_handle, "displaying-email-notification", + plugin, PURPLE_CALLBACK(notify_email_cb), NULL); + purple_signal_connect(notify_handle, "displaying-emails-notification", + plugin, PURPLE_CALLBACK(notify_emails_cb), NULL); + return TRUE; }
--- a/libpurple/protocols/bonjour/jabber.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/bonjour/jabber.c Mon Jul 30 00:05:02 2007 +0000 @@ -350,7 +350,6 @@ PurpleAccount *account = pb->account; BonjourBuddy *bb = pb->proto_data; gboolean closed_conversation = FALSE; - xmlnode *message_node; /* Read the data from the socket */ if ((message_length = _read_data(socket, &message)) == -1) { @@ -374,9 +373,6 @@ } } - /* Parse the message into an XMLnode for analysis */ - message_node = xmlnode_from_str(message, strlen(message)); - /* * Check that this is not the end of the conversation. This is * using a magic string, but xmlnode won't play nice when just @@ -396,16 +392,22 @@ purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } - } else if (message_node != NULL) { - /* Parse the message to get the data and send to the ui */ - _jabber_parse_and_write_message_to_ui(message_node, account->gc, pb); } else { - /* TODO: Deal with receiving only a partial message */ + xmlnode *message_node; + + /* Parse the message into an XMLnode for analysis */ + message_node = xmlnode_from_str(message, strlen(message)); + + if (message_node != NULL) { + /* Parse the message to get the data and send to the ui */ + _jabber_parse_and_write_message_to_ui(message_node, account->gc, pb); + xmlnode_free(message_node); + } else { + /* TODO: Deal with receiving only a partial message */ + } } g_free(message); - if (message_node != NULL) - xmlnode_free(message_node); } struct _stream_start_data { @@ -638,7 +640,7 @@ PurpleBuddy *pb = data; BonjourBuddy *bb = pb->proto_data; int len, ret; - char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), purple_buddy_get_name(pb)); + char *stream_start; bb->conversation->connect_data = NULL; @@ -659,6 +661,7 @@ return; } + stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), purple_buddy_get_name(pb)); len = strlen(stream_start); /* Start the stream and send queued messages */
--- a/libpurple/protocols/jabber/jabber.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Mon Jul 30 00:05:02 2007 +0000 @@ -1975,6 +1975,10 @@ const char *cmd, char **args, char **error, void *data) { JabberChat *chat = jabber_chat_find_by_conv(conv); + + if (!chat) + return PURPLE_CMD_RET_FAILED; + jabber_chat_request_room_configure(chat); return PURPLE_CMD_RET_OK; } @@ -1983,6 +1987,10 @@ const char *cmd, char **args, char **error, void *data) { JabberChat *chat = jabber_chat_find_by_conv(conv); + + if (!chat) + return PURPLE_CMD_RET_FAILED; + jabber_chat_register(chat); return PURPLE_CMD_RET_OK; } @@ -1991,6 +1999,10 @@ const char *cmd, char **args, char **error, void *data) { JabberChat *chat = jabber_chat_find_by_conv(conv); + + if (!chat) + return PURPLE_CMD_RET_FAILED; + jabber_chat_change_topic(chat, args ? args[0] : NULL); return PURPLE_CMD_RET_OK; } @@ -2000,7 +2012,7 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if(!args || !args[0]) + if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; jabber_chat_change_nick(chat, args[0]); @@ -2011,6 +2023,10 @@ const char *cmd, char **args, char **error, void *data) { JabberChat *chat = jabber_chat_find_by_conv(conv); + + if (!chat) + return PURPLE_CMD_RET_FAILED; + jabber_chat_part(chat, args ? args[0] : NULL); return PURPLE_CMD_RET_OK; } @@ -2020,7 +2036,7 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if(!args || !args[0]) + if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; if(!jabber_chat_ban_user(chat, args[0], args[1])) { @@ -2036,7 +2052,7 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if (!args || !args[0] || !args[1]) + if (!chat || !args || !args[0] || !args[1]) return PURPLE_CMD_RET_FAILED; if (strcmp(args[1], "owner") != 0 && @@ -2061,7 +2077,7 @@ { JabberChat *chat; - if (!args || !args[0] || !args[1]) + if (!chat || !args || !args[0] || !args[1]) return PURPLE_CMD_RET_FAILED; if (strcmp(args[1], "moderator") != 0 && @@ -2102,7 +2118,7 @@ JabberChat *chat = jabber_chat_find_by_conv(conv); GHashTable *components; - if(!args || !args[0]) + if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); @@ -2124,7 +2140,7 @@ { JabberChat *chat = jabber_chat_find_by_conv(conv); - if(!args || !args[0]) + if(!chat || !args || !args[0]) return PURPLE_CMD_RET_FAILED; if(!jabber_chat_kick_user(chat, args[0], args[1])) { @@ -2141,6 +2157,9 @@ JabberChat *chat = jabber_chat_find_by_conv(conv); char *who; + if (!chat) + return PURPLE_CMD_RET_FAILED; + who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]); jabber_message_send_im(purple_conversation_get_gc(conv), who, args[1], 0);
--- a/libpurple/protocols/jabber/presence.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/jabber/presence.c Mon Jul 30 00:05:02 2007 +0000 @@ -514,6 +514,12 @@ _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); } + } else if(code && !strcmp(code, "210")) { + /* server rewrote room-nick */ + if((chat = jabber_chat_find(js, jid->node, jid->domain))) { + g_free(chat->handle); + chat->handle = g_strdup(jid->resource); + } } } if((z = xmlnode_get_child(y, "item"))) { @@ -549,7 +555,8 @@ if(chat->conv) { title = g_strdup_printf(_("Error in chat %s"), from); - serv_got_chat_left(js->gc, chat->id); + if (g_hash_table_size(chat->members) == 0) + serv_got_chat_left(js->gc, chat->id); } else { title = g_strdup_printf(_("Error joining chat %s"), from); } @@ -557,7 +564,9 @@ g_free(title); g_free(msg); - jabber_chat_destroy(chat); + if (g_hash_table_size(chat->members) == 0) + /* Only destroy the chat if the error happened while joining */ + jabber_chat_destroy(chat); jabber_id_free(jid); g_free(status); g_free(room_jid);
--- a/libpurple/protocols/oscar/family_chatnav.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/oscar/family_chatnav.c Mon Jul 30 00:05:02 2007 +0000 @@ -427,7 +427,7 @@ if (snac2->type == 0x0002) /* request chat rights */ ret = parseinfo_perms(od, conn, mod, frame, snac, bs, snac2); else if (snac2->type == 0x0003) /* request exchange info */ - purple_debug_misc("oscar", "chatnav_parse_info: resposne to exchange info\n"); + purple_debug_misc("oscar", "chatnav_parse_info: response to exchange info\n"); else if (snac2->type == 0x0004) /* request room info */ purple_debug_misc("oscar", "chatnav_parse_info: response to room info\n"); else if (snac2->type == 0x0005) /* request more room info */
--- a/libpurple/protocols/oscar/family_locate.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/oscar/family_locate.c Mon Jul 30 00:05:02 2007 +0000 @@ -636,13 +636,15 @@ * Parse out the Type-Length-Value triples as they're found. */ for (curtlv = 0; curtlv < tlvcnt; curtlv++) { + guint16 type; + guint8 number, length; int endpos; - guint16 type, length; type = byte_stream_get16(bs); - length = byte_stream_get16(bs); + number = byte_stream_get8(bs); + length = byte_stream_get8(bs); - endpos = byte_stream_curpos(bs) + length; + endpos = byte_stream_curpos(bs) + MIN(length, byte_stream_empty(bs)); if (type == 0x0001) { /* @@ -814,27 +816,33 @@ * contain information about the buddy icon the user * has stored on the server. */ - int type2, number, length2; + guint16 type2; + guint8 number2, length2; + int endpos2; - while (byte_stream_curpos(bs) < endpos) { + /* + * Continue looping as long as we're able to read type2, + * number2, and length2. + */ + while (byte_stream_curpos(bs) + 4 <= endpos) { type2 = byte_stream_get16(bs); - number = byte_stream_get8(bs); + number2 = byte_stream_get8(bs); length2 = byte_stream_get8(bs); + endpos2 = byte_stream_curpos(bs) + MIN(length2, byte_stream_empty(bs)); + switch (type2) { case 0x0000: { /* This is an official buddy icon? */ /* This is always 5 bytes of "0x02 01 d2 04 72"? */ - byte_stream_advance(bs, length2); } break; case 0x0001: { /* A buddy icon checksum */ - if ((length2 > 0) && ((number == 0x00) || (number == 0x01))) { + if ((length2 > 0) && ((number2 == 0x00) || (number2 == 0x01))) { g_free(outinfo->iconcsum); - outinfo->iconcsumtype = number; + outinfo->iconcsumtype = number2; outinfo->iconcsum = byte_stream_getraw(bs, length2); outinfo->iconcsumlen = length2; - } else - byte_stream_advance(bs, length2); + } } break; case 0x0002: { /* A status/available message */ @@ -879,11 +887,10 @@ outinfo->itmsurl_encoding = NULL; } } break; + } - default: { - byte_stream_advance(bs, length2); - } break; - } + /* Save ourselves. */ + byte_stream_setpos(bs, endpos2); } } else if (type == 0x001e) {
--- a/libpurple/protocols/oscar/oscar.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Mon Jul 30 00:05:02 2007 +0000 @@ -6606,7 +6606,7 @@ if (message) { /* Spaces are encoded as '+' */ g_strdelimit(message, "+", ' '); - purple_conv_im_send(PURPLE_CONV_IM(conv), message); + purple_conv_send_confirm(conv, message); } } /*else
--- a/libpurple/protocols/oscar/tlv.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/oscar/tlv.c Mon Jul 30 00:05:02 2007 +0000 @@ -423,25 +423,6 @@ } /** - * Adds the given userinfo struct to a TLV chain. - * - * @param list Destination chain. - * @param type TLV type to add. - * @return The size of the value added. - */ -int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo) -{ - guint8 buf[1024]; /* TODO: Don't use a fixed length buffer */ - ByteStream bs; - - byte_stream_init(&bs, buf, sizeof(buf)); - - aim_putuserinfo(&bs, userinfo); - - return aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), buf); -} - -/** * Adds the given chatroom info to a TLV chain. * * @param list Destination chain.
--- a/libpurple/protocols/qq/qq.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/qq/qq.c Mon Jul 30 00:05:02 2007 +0000 @@ -747,10 +747,7 @@ { PurpleAccountOption *option; - option = purple_account_option_bool_new(_("Login in TCP"), "use_tcp", FALSE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - option = purple_account_option_bool_new(_("Login Hidden"), "hidden", FALSE); + option = purple_account_option_bool_new(_("Connect using TCP"), "use_tcp", FALSE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_string_new(_("Server"), "server", NULL);
--- a/libpurple/protocols/yahoo/yahoo.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Mon Jul 30 00:05:02 2007 +0000 @@ -1917,6 +1917,7 @@ char *msg; char *url = NULL; char *fullmsg; + PurpleAccount *account = gc->account; while (l) { struct yahoo_pair *pair = l->data; @@ -1949,6 +1950,9 @@ return; } #endif + if (!purple_account_get_remember_password(account)) + purple_account_set_password(account, NULL); + msg = g_strdup(_("Incorrect password.")); break; case 14: @@ -3915,7 +3919,7 @@ if (message) { /* Spaces are encoded as '+' */ g_strdelimit(message, "+", ' '); - purple_conv_im_send(PURPLE_CONV_IM(conv), message); + purple_conv_send_confirm(conv, message); } } /*else
--- a/libpurple/savedstatuses.c Mon Jul 30 00:01:08 2007 +0000 +++ b/libpurple/savedstatuses.c Mon Jul 30 00:05:02 2007 +0000 @@ -869,9 +869,9 @@ purple_idle_touch(); old = purple_savedstatus_get_current(); - purple_prefs_set_bool("/purple/savedstatus/isidleaway", idleaway); saved_status = idleaway ? purple_savedstatus_get_idleaway() : purple_savedstatus_get_default(); + purple_prefs_set_bool("/purple/savedstatus/isidleaway", idleaway); if (idleaway && (purple_savedstatus_get_type(old) != PURPLE_STATUS_AVAILABLE)) /* Our global status is already "away," so don't change anything */
--- a/pidgin/Makefile.mingw Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/Makefile.mingw Mon Jul 30 00:05:02 2007 +0000 @@ -167,8 +167,9 @@ clean: $(MAKE) -C $(PIDGIN_IDLETRACK_TOP) -f $(MINGW_MAKEFILE) clean $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean + $(MAKE) -C $(PIDGIN_PIXMAPS_TOP) -f $(MINGW_MAKEFILE) clean rm -f $(PIDGIN_OBJECTS) $(PIDGIN_RC_SRC) $(EXE_OBJECTS) $(EXE_RC_SRC) - rm -f $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a + rm -f $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a $(PIDGIN_TARGET).def rm -f $(EXE_TARGET).exe include $(PIDGIN_COMMON_TARGETS)
--- a/pidgin/gtkblist.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkblist.c Mon Jul 30 00:05:02 2007 +0000 @@ -136,8 +136,6 @@ static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node); static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded); -static void pidgin_blist_tooltip_destroy(void); - struct _pidgin_blist_node { GtkTreeRowReference *row; gboolean contact_expanded; @@ -629,8 +627,7 @@ gc = purple_account_get_connection(data->account); - while ((tmp = gtk_container_get_children(GTK_CONTAINER(data->entries_box)))) - gtk_widget_destroy(tmp->data); + gtk_container_foreach(GTK_CONTAINER(data->entries_box), (GtkCallback)gtk_widget_destroy, NULL); g_list_free(data->entries); data->entries = NULL; @@ -1151,7 +1148,8 @@ pidgin_new_item_from_stock(menu, _("Add Buddy _Pounce"), NULL, G_CALLBACK(gtk_blist_menu_bp_cb), buddy, 0, 0, NULL); - if(((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { + if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && + !sub && !contact_expanded) { pidgin_new_item_from_stock(menu, _("View _Log"), NULL, G_CALLBACK(gtk_blist_menu_showlog_cb), contact, 0, 0, NULL); @@ -1165,7 +1163,8 @@ (PurpleBlistNode *)buddy); pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy); - if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) { + if (((PurpleBlistNode*)buddy)->parent && ((PurpleBlistNode*)buddy)->parent->child->next && + !sub && !contact_expanded) { pidgin_separator(menu); pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy); pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS, @@ -1247,7 +1246,8 @@ static GtkWidget * -create_chat_menu(PurpleBlistNode *node, PurpleChat *c) { +create_chat_menu(PurpleBlistNode *node, PurpleChat *c) +{ GtkWidget *menu; gboolean autojoin; @@ -1305,7 +1305,8 @@ } static GtkWidget * -create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b) { +create_buddy_menu(PurpleBlistNode *node, PurpleBuddy *b) +{ struct _pidgin_blist_node *gtknode = (struct _pidgin_blist_node *)node->ui_data; GtkWidget *menu; GtkWidget *menuitem; @@ -2495,7 +2496,7 @@ } -static void pidgin_blist_tooltip_destroy() +void pidgin_blist_tooltip_destroy() { while(gtkblist->tooltipdata) { struct tooltip_data *td = gtkblist->tooltipdata->data; @@ -2583,6 +2584,22 @@ GtkTreeIter iter; PurpleBlistNode *node; GValue val; + + if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) + return FALSE; + gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); + val.g_type = 0; + gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); + node = g_value_get_pointer(&val); + + pidgin_blist_draw_tooltip(node, gtkblist->window); + + gtk_tree_path_free(path); + return FALSE; +} + +void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget) +{ int scr_w, scr_h, w, h, x, y; #if GTK_CHECK_VERSION(2,2,0) int mon_num; @@ -2591,6 +2608,9 @@ gboolean tooltip_top = FALSE; struct _pidgin_blist_node *gtknode; GdkRectangle mon_size; + + if (node == NULL) + return; /* * Attempt to free the previous tooltip. I have a feeling @@ -2598,14 +2618,6 @@ */ pidgin_blist_tooltip_destroy(); - if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), gtkblist->tip_rect.x, gtkblist->tip_rect.y, &path, NULL, NULL, NULL)) - return FALSE; - gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); - val.g_type = 0; - gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val); - node = g_value_get_pointer(&val); - - gtk_tree_path_free(path); gtkblist->tipwindow = gtk_window_new(GTK_WINDOW_POPUP); @@ -2643,13 +2655,13 @@ } else { gtk_widget_destroy(gtkblist->tipwindow); gtkblist->tipwindow = NULL; - return FALSE; + return; } if (gtkblist->tooltipdata == NULL) { gtk_widget_destroy(gtkblist->tipwindow); gtkblist->tipwindow = NULL; - return FALSE; + return; } gtknode = node->ui_data; @@ -2685,9 +2697,6 @@ h = mon_size.height - 10; #endif - if (GTK_WIDGET_NO_WINDOW(gtkblist->window)) - y+=gtkblist->window->allocation.y; - x -= ((w >> 1) + 4); if ((y + h + 4) > scr_h || tooltip_top) @@ -2713,7 +2722,7 @@ gtk_window_move(GTK_WINDOW(gtkblist->tipwindow), x, y); gtk_widget_show(gtkblist->tipwindow); - return FALSE; + return; } static gboolean pidgin_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context, @@ -4000,6 +4009,7 @@ char *primary; const char *text; gboolean enabled; + GList *list; account = user_data; primary = g_strdup_printf(_("%s disconnected"), @@ -4018,8 +4028,10 @@ g_free(primary); gtk_widget_destroy(GTK_WIDGET(widget)); g_hash_table_remove(gtkblist->connection_errors, account); - if (gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons)) == NULL) { + if ((list = gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons))) == NULL) { gtk_widget_hide(gtkblist->error_buttons); + } else { + g_list_free(list); } } @@ -4089,7 +4101,7 @@ /* Remove the old error buttons */ for (l = gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons)); l != NULL; - l = l->next) + l = g_list_delete_link(l, l)) { gtk_widget_destroy(GTK_WIDGET(l->data)); } @@ -5648,8 +5660,7 @@ gc = purple_account_get_connection(data->account); - while ((tmp = gtk_container_get_children(GTK_CONTAINER(data->entries_box)))) - gtk_widget_destroy(tmp->data); + gtk_container_foreach(GTK_CONTAINER(data->entries_box), (GtkCallback)gtk_widget_destroy, NULL); g_list_free(data->entries); @@ -6526,7 +6537,7 @@ return; /* Clear the old Accounts menu */ - for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = l->next) { + for (l = gtk_container_get_children(GTK_CONTAINER(accountmenu)); l; l = g_list_delete_link(l, l)) { menuitem = l->data; if (menuitem != gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts/Add\\/Edit"))) @@ -6737,7 +6748,7 @@ return; /* Clear the old menu */ - for (l = gtk_container_get_children(GTK_CONTAINER(sortmenu)); l; l = l->next) { + for (l = gtk_container_get_children(GTK_CONTAINER(sortmenu)); l; l = g_list_delete_link(l, l)) { menuitem = l->data; gtk_widget_destroy(GTK_WIDGET(menuitem)); }
--- a/pidgin/gtkblist.h Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkblist.h Mon Jul 30 00:05:02 2007 +0000 @@ -370,4 +370,21 @@ */ gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected, gboolean aliased); +/** + * Creates the Buddy List tooltip at the current pointer location for the given buddy list node. + * + * This tooltip will be destroyed the next time this function is called, or when XXXX + * is called + * + * @param buddy The buddy to show a tooltip for + * @param widget The widget to draw the tooltip on + */ +void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget); + +/** + * Destroys the current (if any) Buddy List tooltip + */ +void pidgin_blist_tooltip_destroy(void); + + #endif /* _PIDGINBLIST_H_ */
--- a/pidgin/gtkcellrendererexpander.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkcellrendererexpander.c Mon Jul 30 00:05:02 2007 +0000 @@ -285,5 +285,5 @@ else gtk_tree_view_expand_row(GTK_TREE_VIEW(widget),path,FALSE); gtk_tree_path_free(path); - return FALSE; + return TRUE; }
--- a/pidgin/gtkconv.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkconv.c Mon Jul 30 00:05:02 2007 +0000 @@ -239,7 +239,6 @@ if (!PIDGIN_IS_PIDGIN_CONVERSATION(conv)) return FALSE; - if (gtkconv->auto_resize) { return FALSE; } @@ -264,7 +263,6 @@ if (w == gtkconv->lower_hbox) purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", allocation->height); } - return FALSE; } @@ -2367,6 +2365,8 @@ &(gtkconv->infopane_iter), CONV_EMBLEM_COLUMN, emblem, -1); + /* XXX seanegan Why do I have to do this? */ + gtk_widget_queue_draw(gtkconv->infopane); if (status != NULL) g_object_unref(status); @@ -2913,22 +2913,19 @@ } } -static void -regenerate_options_items(PidginWindow *win) -{ - GtkWidget *menu; +/* Returns TRUE if some items were added to the menu, FALSE otherwise */ +static gboolean +populate_menu_with_options(GtkWidget *menu, PidginConversation *gtkconv, gboolean all) +{ GList *list; - PidginConversation *gtkconv; PurpleConversation *conv; PurpleBlistNode *node = NULL; PurpleChat *chat = NULL; PurpleBuddy *buddy = NULL; - - gtkconv = pidgin_conv_window_get_active_gtkconv(win); + gboolean ret; + conv = gtkconv->active_conv; - menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); - if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { chat = purple_blist_find_chat(conv->account, conv->name); @@ -2973,23 +2970,43 @@ else if (buddy) node = (PurpleBlistNode *)buddy; + /* Now add the stuff */ + if (all && buddy) { + pidgin_blist_make_buddy_menu(menu, buddy, TRUE); + } else if (node) { + if (purple_account_is_connected(conv->account)) + pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); + pidgin_append_blist_node_extended_menu(menu, node); + } + + if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) { + ret = FALSE; + } else { + g_list_free(list); + ret = TRUE; + } + return ret; +} + +static void +regenerate_options_items(PidginWindow *win) +{ + GtkWidget *menu; + PidginConversation *gtkconv; + GList *list; + + gtkconv = pidgin_conv_window_get_active_gtkconv(win); + menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More")); + /* Remove the previous entries */ for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; ) { GtkWidget *w = list->data; - list = list->next; + list = g_list_delete_link(list, list); gtk_widget_destroy(w); } - /* Now add the stuff */ - if (node) - { - if (purple_account_is_connected(conv->account)) - pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node); - pidgin_append_blist_node_extended_menu(menu, node); - } - - if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL) + if (!populate_menu_with_options(menu, gtkconv, FALSE)) { GtkWidget *item = gtk_menu_item_new_with_label(_("No actions available")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); @@ -3370,12 +3387,11 @@ gtk_widget_show(win->menu.send_to); - menu = gtk_menu_item_get_submenu( - GTK_MENU_ITEM(win->menu.send_to)); + menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to)); for (child = gtk_container_get_children(GTK_CONTAINER(menu)); child != NULL; - child = child->next) { + child = g_list_delete_link(child, child)) { GtkWidget *item = child->data; PurpleBuddy *item_buddy; @@ -4260,12 +4276,12 @@ height = (oneline.height + pad_top + pad_bottom) * lines; height += (oneline.height + pad_inside) * (wrapped_lines - lines); + gtkconv->auto_resize = TRUE; + g_idle_add(reset_auto_resize_cb, gtkconv); gtk_widget_size_request(gtkconv->lower_hbox, &sr); if (sr.height < height + PIDGIN_HIG_BOX_SPACE) { - gtkconv->auto_resize = TRUE; gtkconv->entry_growing = TRUE; - gtk_widget_set_size_request(gtkconv->entry, -1, height); - g_idle_add(reset_auto_resize_cb, gtkconv); + gtk_widget_set_size_request(gtkconv->lower_hbox, -1, height + PIDGIN_HIG_BOX_SPACE); } } @@ -4392,6 +4408,50 @@ gtk_container_add(GTK_CONTAINER(sw), list); } +static int tooltip_timeout = 0; + +static gboolean +pidgin_conv_tooltip_timeout(PidginConversation *gtkconv) +{ + PurpleBlistNode *node = NULL; + PurpleConversation *conv = gtkconv->active_conv; + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); + } else { + node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); + } + + if (node) + pidgin_blist_draw_tooltip(node, gtkconv->infopane); + return FALSE; +} + +static void +pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv) +{ + pidgin_blist_tooltip_destroy(); + if (tooltip_timeout) { + g_source_remove(tooltip_timeout); + tooltip_timeout = 0; + } +} + +static gboolean +pidgin_conv_motion_cb (GtkWidget *infopane, GdkEventMotion *event, PidginConversation *gtkconv) +{ + int delay = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/tooltip_delay"); + + pidgin_blist_tooltip_destroy(); + if (delay == 0) + return FALSE; + + if (tooltip_timeout != 0) + g_source_remove(tooltip_timeout); + + tooltip_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_conv_tooltip_timeout, gtkconv); + return FALSE; +} + static GtkWidget * setup_common_pane(PidginConversation *gtkconv) { @@ -4412,16 +4472,24 @@ /* Setup the info pane */ event_box = gtk_event_box_new(); +#if GTK_CHECK_VERSION(2,4,0) + gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE); +#endif gtk_widget_show(event_box); gtkconv->infopane_hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), event_box, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(event_box), gtkconv->infopane_hbox); gtk_widget_show(gtkconv->infopane_hbox); gtk_widget_add_events(event_box, - GDK_BUTTON1_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); + GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(infopane_press_cb), gtkconv); + g_signal_connect(G_OBJECT(event_box), "motion-notify-event", + G_CALLBACK(pidgin_conv_motion_cb), gtkconv); + g_signal_connect(G_OBJECT(event_box), "leave-notify-event", + G_CALLBACK(pidgin_conv_leave_cb), gtkconv); + gtkconv->infopane = gtk_cell_view_new(); gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF); @@ -4547,7 +4615,6 @@ default_formatize(gtkconv); g_signal_connect_after(G_OBJECT(gtkconv->entry), "format_function_clear", G_CALLBACK(clear_formatting_cb), gtkconv); - return paned; } @@ -6522,7 +6589,6 @@ gtk_widget_show(event); gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale); - gtkconv->auto_resize = TRUE; gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon); gtk_widget_show(gtkconv->u.im->icon); @@ -7643,52 +7709,40 @@ static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) { - int nb_x, nb_y; - if (e->type != GDK_BUTTON_PRESS) return FALSE; if (e->button == 3) { /* Right click was pressed. Popup the Send To menu. */ - GtkWidget *menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); - if (menu) - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time); - else + GtkWidget *menu = gtk_menu_new(), *sub; + sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); + + if (populate_menu_with_options(menu, gtkconv, TRUE)) + pidgin_separator(menu); + else if (!sub || + !GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) { + gtk_widget_destroy(menu); return FALSE; - return TRUE; - } else if (e->button != 1) { - return FALSE; - } - - if (gtkconv->win->in_drag) { - purple_debug(PURPLE_DEBUG_WARNING, "gtkconv", - "Already in the middle of a window drag at tab_press_cb\n"); + } else { + menu = sub; + sub = NULL; + } + + if (sub) { + GtkWidget *item = gtk_menu_item_new_with_mnemonic(_("_Send To")); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), sub); + gtk_widget_show(item); + gtk_widget_show_all(sub); + } + + gtk_widget_show_all(menu); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time); return TRUE; } - - gtkconv->win->in_predrag = TRUE; - gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont); - - gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y); - - gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x; - gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y; - gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x; - gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y; - - /* Connect the new motion signals. */ - gtkconv->win->drag_motion_signal = - g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event", - G_CALLBACK(notebook_motion_cb), gtkconv->win); - - gtkconv->win->drag_leave_signal = - g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event", - G_CALLBACK(notebook_leave_cb), gtkconv->win); - return FALSE; - -} - +} + static gboolean notebook_press_cb(GtkWidget *widget, GdkEventButton *e, PidginWindow *win) { @@ -8269,8 +8323,8 @@ 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); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/x", x); + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/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); @@ -8279,6 +8333,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"); + + /* 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); + } +} + PidginWindow * pidgin_conv_window_new() { @@ -8293,8 +8379,7 @@ /* Create the window. */ win->window = pidgin_create_window(NULL, 0, "conversation", TRUE); - gtk_window_set_default_size(GTK_WINDOW(win->window), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/width"), - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/im/height")); + pidgin_conv_restore_position(win); if (available_list == NULL) { create_icon_lists(win->window);
--- a/pidgin/gtkdialogs.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkdialogs.c Mon Jul 30 00:05:02 2007 +0000 @@ -72,6 +72,7 @@ {"Daniel 'datallah' Atallah", N_("developer"), NULL}, {"Ethan 'Paco-Paco' Blanton", N_("developer"), NULL}, {"Thomas Butter", N_("developer"), NULL}, + {"Ka-Hing Cheung", N_("developer"), NULL}, {"Sadrul Habib Chowdhury", N_("developer"), NULL}, {"Mark 'KingAnt' Doliner", N_("developer"), NULL}, {"Christian 'ChipX86' Hammond", N_("developer & webmaster"), NULL}, @@ -94,7 +95,6 @@ /* Order: Alphabetical by Last Name */ static struct developer patch_writers[] = { {"John 'rekkanoryo' Bailey", NULL, NULL}, - {"Ka-Hing 'javabsp' Cheung", NULL, NULL}, {"Felipe 'shx' Contreras", NULL, NULL}, {"Decklin Foster", NULL, NULL}, {"Peter 'Bleeter' Lawler", NULL, NULL},
--- a/pidgin/gtkimhtml.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkimhtml.c Mon Jul 30 00:05:02 2007 +0000 @@ -348,13 +348,28 @@ } } -static void gtk_size_allocate_cb(GtkIMHtml *widget, GtkAllocation *alloc, gpointer user_data) +static void (*parent_size_allocate)(GtkWidget *widget, GtkAllocation *alloc); + +static void gtk_imhtml_size_allocate(GtkWidget *widget, GtkAllocation *alloc) { + GtkIMHtml *imhtml = GTK_IMHTML(widget); GdkRectangle rect; int xminus; + int height = 0, y = 0; + GtkTextIter iter; + gboolean scroll = TRUE; + + gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &rect); - if(widget->old_rect.width != rect.width || widget->old_rect.height != rect.height){ + gtk_text_view_get_line_yrange(GTK_TEXT_VIEW(imhtml), &iter, &y, &height); + + if(((y + height) - (rect.y + rect.height)) > height + && gtk_text_buffer_get_char_count(imhtml->text_buffer)){ + scroll = FALSE; + } + + if(imhtml->old_rect.width != rect.width || imhtml->old_rect.height != rect.height){ GList *iter = GTK_IMHTML(widget)->scalables; xminus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(widget)) + @@ -369,8 +384,12 @@ } } - widget->old_rect = rect; - return; + imhtml->old_rect = rect; + parent_size_allocate(widget, alloc); + + /* Don't scroll here if we're in the middle of a smooth scroll */ + if (scroll && imhtml->scroll_time == NULL) + gtk_imhtml_scroll_to_end(imhtml, FALSE); } static gint @@ -1345,6 +1364,9 @@ gobject_class->finalize = gtk_imhtml_finalize; widget_class->drag_motion = gtk_text_view_drag_motion; widget_class->expose_event = gtk_imhtml_expose_event; + parent_size_allocate = widget_class->size_allocate; + widget_class->size_allocate = gtk_imhtml_size_allocate; + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-color", _("Hyperlink color"), _("Color to draw hyperlinks."), @@ -1409,7 +1431,6 @@ g_free, (GDestroyNotify)gtk_smiley_tree_destroy); imhtml->default_smilies = gtk_smiley_tree_new(); - g_signal_connect(G_OBJECT(imhtml), "size-allocate", G_CALLBACK(gtk_size_allocate_cb), NULL); g_signal_connect(G_OBJECT(imhtml), "motion-notify-event", G_CALLBACK(gtk_motion_event_notify), NULL); g_signal_connect(G_OBJECT(imhtml), "leave-notify-event", G_CALLBACK(gtk_leave_event_notify), NULL); g_signal_connect(G_OBJECT(imhtml), "enter-notify-event", G_CALLBACK(gtk_enter_event_notify), NULL);
--- a/pidgin/gtkpounce.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkpounce.c Mon Jul 30 00:05:02 2007 +0000 @@ -565,7 +565,7 @@ dialog->buddy_entry = gtk_entry_new(); - pidgin_setup_screenname_autocomplete(dialog->buddy_entry, dialog->account_menu, FALSE); + pidgin_setup_screenname_autocomplete_with_filter(dialog->buddy_entry, dialog->account_menu, pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(FALSE)); gtk_box_pack_start(GTK_BOX(hbox), dialog->buddy_entry, TRUE, TRUE, 0); gtk_widget_show(dialog->buddy_entry);
--- a/pidgin/gtkprefs.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkprefs.c Mon Jul 30 00:05:02 2007 +0000 @@ -994,7 +994,7 @@ pidgin_prefs_checkbox(_("Show _formatting on incoming messages"), PIDGIN_PREFS_ROOT "/conversations/show_incoming_formatting", vbox); - iconpref1 = pidgin_prefs_checkbox(_("Show Buddy _Details"), + iconpref1 = pidgin_prefs_checkbox(strchr(_("/Buddies/Show Buddy _Details")+1,'/')+1, PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", vbox); iconpref2 = pidgin_prefs_checkbox(_("Enable buddy ic_on animation"), PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons", vbox);
--- a/pidgin/gtkrequest.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkrequest.c Mon Jul 30 00:05:02 2007 +0000 @@ -711,7 +711,7 @@ } } } - pidgin_setup_screenname_autocomplete(entry, optmenu, !strcmp(type_hint, "screenname-all")); + pidgin_setup_screenname_autocomplete_with_filter(entry, optmenu, pidgin_screenname_autocomplete_default_filter, GINT_TO_POINTER(!strcmp(type_hint, "screenname-all"))); } } }
--- a/pidgin/gtkstatusbox.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkstatusbox.c Mon Jul 30 00:05:02 2007 +0000 @@ -1016,8 +1016,8 @@ } } -static gboolean -pidgin_status_box_regenerate_real(PidginStatusBox *status_box) +static void +pidgin_status_box_regenerate(PidginStatusBox *status_box) { GdkPixbuf *pixbuf, *pixbuf2, *pixbuf3, *pixbuf4, *pixbuf5; GtkIconSize icon_size; @@ -1081,21 +1081,11 @@ } gtk_tree_view_set_model(GTK_TREE_VIEW(status_box->tree_view), GTK_TREE_MODEL(status_box->dropdown_store)); gtk_tree_view_set_search_column(GTK_TREE_VIEW(status_box->tree_view), TEXT_COLUMN); - - return FALSE; -} - -static void -pidgin_status_box_regenerate(PidginStatusBox *status_box) -{ - /* we have to do this in a timeout, so we avoid recursing - * to infinity (and beyond) */ - purple_timeout_add(0, (GSourceFunc)pidgin_status_box_regenerate_real, status_box); } static gboolean combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkIMHtml *imhtml) { - pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); + pidgin_status_box_popup(PIDGIN_STATUS_BOX(w)); return TRUE; }
--- a/pidgin/gtkutils.c Mon Jul 30 00:01:08 2007 +0000 +++ b/pidgin/gtkutils.c Mon Jul 30 00:05:02 2007 +0000 @@ -137,6 +137,10 @@ wnd = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); if (title) gtk_window_set_title(wnd, title); +#ifdef _WIN32 + else + gtk_window_set_title(wnd, PIDGIN_ALERT_TITLE); +#endif gtk_container_set_border_width(GTK_CONTAINER(wnd), border_width); if (role) gtk_window_set_role(wnd, role); @@ -1743,16 +1747,22 @@ # define NEW_STYLE_COMPLETION #endif -#ifndef NEW_STYLE_COMPLETION typedef struct { + GtkWidget *entry; + GtkWidget *accountopt; + + PidginFilterBuddyCompletionEntryFunc filter_func; + gpointer filter_func_user_data; + +#ifdef NEW_STYLE_COMPLETION + GtkListStore *store; +#else GCompletion *completion; - gboolean completion_started; - gboolean all; - + GList *log_items; +#endif /* NEW_STYLE_COMPLETION */ } PidginCompletionData; -#endif #ifndef NEW_STYLE_COMPLETION static gboolean @@ -1870,15 +1880,15 @@ } static gboolean screenname_completion_match_selected_cb(GtkEntryCompletion *completion, - GtkTreeModel *model, GtkTreeIter *iter, gpointer *user_data) + GtkTreeModel *model, GtkTreeIter *iter, PidginCompletionData *data) { GValue val; - GtkWidget *optmenu = user_data[1]; + GtkWidget *optmenu = data->accountopt; PurpleAccount *account; val.g_type = 0; gtk_tree_model_get_value(model, iter, 1, &val); - gtk_entry_set_text(GTK_ENTRY(user_data[0]), g_value_get_string(&val)); + gtk_entry_set_text(GTK_ENTRY(data->entry), g_value_get_string(&val)); g_value_unset(&val); gtk_tree_model_get_value(model, iter, 4, &val); @@ -1971,83 +1981,47 @@ } #endif /* NEW_STYLE_COMPLETION */ -static void get_log_set_name(PurpleLogSet *set, gpointer value, gpointer **set_hash_data) +static void get_log_set_name(PurpleLogSet *set, gpointer value, PidginCompletionData *data) { - /* 1. Don't show buddies because we will have gotten them already. - * 2. Only show those with non-NULL accounts that are currently connected. - * 3. The boxes that use this autocomplete code handle only IMs. */ - if (!set->buddy && - (GPOINTER_TO_INT(set_hash_data[1]) || - (set->account != NULL && purple_account_is_connected(set->account))) && - set->type == PURPLE_LOG_IM) { + PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; + gpointer user_data = data->filter_func_user_data; + + /* 1. Don't show buddies because we will have gotten them already. + * 2. The boxes that use this autocomplete code handle only IMs. */ + if (!set->buddy && set->type == PURPLE_LOG_IM) { + PidginBuddyCompletionEntry entry; + entry.is_buddy = FALSE; + entry.entry.logged_buddy = set; + + if (filter_func(&entry, user_data)) { #ifdef NEW_STYLE_COMPLETION - add_screenname_autocomplete_entry((GtkListStore *)set_hash_data[0], - NULL, NULL, set->account, set->name); + add_screenname_autocomplete_entry(data->store, + NULL, NULL, set->account, set->name); #else - GList **items = ((GList **)set_hash_data[0]); /* Steal the name for the GCompletion. */ - *items = g_list_append(*items, set->name); + data->log_items = g_list_append(data->log_items, set->name); set->name = set->normalized_name = NULL; #endif /* NEW_STYLE_COMPLETION */ + } } } -#ifdef NEW_STYLE_COMPLETION -static void -add_completion_list(GtkListStore *store) -{ - PurpleBlistNode *gnode, *cnode, *bnode; - gboolean all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(store), "screenname-all")); - GHashTable *sets; - gpointer set_hash_data[] = {store, GINT_TO_POINTER(all)}; - - gtk_list_store_clear(store); - - for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) - { - if (!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - - for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) - { - if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - - for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) - { - PurpleBuddy *buddy = (PurpleBuddy *)bnode; - - if (!all && !purple_account_is_connected(buddy->account)) - continue; - - add_screenname_autocomplete_entry(store, - ((PurpleContact *)cnode)->alias, - purple_buddy_get_contact_alias(buddy), - buddy->account, - buddy->name - ); - } - } - } - - sets = purple_log_get_log_sets(); - g_hash_table_foreach(sets, (GHFunc)get_log_set_name, &set_hash_data); - g_hash_table_destroy(sets); -} -#else static void add_completion_list(PidginCompletionData *data) { PurpleBlistNode *gnode, *cnode, *bnode; - GCompletion *completion; - GList *item = g_list_append(NULL, NULL); + PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func; + gpointer user_data = data->filter_func_user_data; GHashTable *sets; - gpointer set_hash_data[2]; - - completion = data->completion; - - g_list_foreach(completion->items, (GFunc)g_free, NULL); - g_completion_clear_items(completion); + +#ifdef NEW_STYLE_COMPLETION + gtk_list_store_clear(data->store); +#else + GList *item = g_list_append(NULL, NULL); + + g_list_foreach(data->completion->items, (GFunc)g_free, NULL); + g_completion_clear_items(data->completion); +#endif /* NEW_STYLE_COMPLETION */ for (gnode = purple_get_blist()->root; gnode != NULL; gnode = gnode->next) { @@ -2061,28 +2035,41 @@ for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) { - PurpleBuddy *buddy = (PurpleBuddy *)bnode; - - if (!data->all && !purple_account_is_connected(buddy->account)) - continue; - + PidginBuddyCompletionEntry entry; + entry.is_buddy = TRUE; + entry.entry.buddy = (PurpleBuddy *) bnode; + + if (filter_func(&entry, user_data)) { +#ifdef NEW_STYLE_COMPLETION + add_screenname_autocomplete_entry(data->store, + ((PurpleContact *)cnode)->alias, + purple_buddy_get_contact_alias(entry.entry.buddy), + entry.entry.buddy->account, + entry.entry.buddy->name + ); + } +#else item->data = g_strdup(buddy->name); g_completion_add_items(data->completion, item); +#endif /* NEW_STYLE_COMPLETION */ } } } + +#ifndef NEW_STYLE_COMPLETION g_list_free(item); + data->log_items = NULL; +#endif /* NEW_STYLE_COMPLETION */ sets = purple_log_get_log_sets(); - item = NULL; - set_hash_data[0] = &item; - set_hash_data[1] = GINT_TO_POINTER(data->all); - g_hash_table_foreach(sets, (GHFunc)get_log_set_name, &set_hash_data); + g_hash_table_foreach(sets, (GHFunc)get_log_set_name, data); g_hash_table_destroy(sets); - g_completion_add_items(data->completion, item); - g_list_free(item); + +#ifndef NEW_STYLE_COMPLETION + g_completion_add_items(data->completion, data->log_items); + g_list_free(data->log_items); +#endif /* NEW_STYLE_COMPLETION */ } -#endif static void screenname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) @@ -2097,23 +2084,34 @@ add_completion_list(data); } + void -pidgin_setup_screenname_autocomplete(GtkWidget *entry, GtkWidget *accountopt, gboolean all) +pidgin_setup_screenname_autocomplete_with_filter(GtkWidget *entry, GtkWidget *accountopt, PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data) { - gpointer cb_data = NULL; + PidginCompletionData *data; #ifdef NEW_STYLE_COMPLETION /* Store the displayed completion value, the screenname, the UTF-8 normalized & casefolded screenname, * the UTF-8 normalized & casefolded value for comparison, and the account. */ - GtkListStore *store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + GtkListStore *store; GtkEntryCompletion *completion; - gpointer *data; - - g_object_set_data(G_OBJECT(store), "screenname-all", GINT_TO_POINTER(all)); - add_completion_list(store); - - cb_data = store; + + data = g_new0(PidginCompletionData, 1); + store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + data->entry = entry; + data->accountopt = accountopt; + if (filter_func == NULL) { + data->filter_func = pidgin_screenname_autocomplete_default_filter; + data->filter_func_user_data = NULL; + } else { + data->filter_func = filter_func; + data->filter_func_user_data = user_data; + } + data->store = store; + + add_completion_list(data); /* Sort the completion list by screenname. */ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), @@ -2122,9 +2120,6 @@ completion = gtk_entry_completion_new(); gtk_entry_completion_set_match_func(completion, screenname_completion_match_func, NULL, NULL); - data = g_new0(gpointer, 2); - data[0] = entry; - data[1] = accountopt; g_signal_connect(G_OBJECT(completion), "match-selected", G_CALLBACK(screenname_completion_match_selected_cb), data); @@ -2137,18 +2132,25 @@ gtk_entry_completion_set_text_column(completion, 0); #else /* !NEW_STYLE_COMPLETION */ - PidginCompletionData *data; data = g_new0(PidginCompletionData, 1); + data->entry = entry; + data->accountopt = accountopt; + if (filter_func == NULL) { + data->filter_func = pidgin_screenname_autocomplete_default_filter; + data->filter_func_user_data = NULL; + } else { + data->filter_func = filter_func; + data->filter_func_user_data = user_data; + } data->completion = g_completion_new(NULL); - data->all = all; + data->completion_started = FALSE; + + add_completion_list(data); g_completion_set_compare(data->completion, g_ascii_strncasecmp); - add_completion_list(data); - cb_data = data; - g_signal_connect(G_OBJECT(entry), "event", G_CALLBACK(completion_entry_event), data); g_signal_connect(G_OBJECT(entry), "destroy", @@ -2156,22 +2158,37 @@ #endif /* !NEW_STYLE_COMPLETION */ - if (!all) - { - purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, - PURPLE_CALLBACK(repopulate_autocomplete), cb_data); - purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, - PURPLE_CALLBACK(repopulate_autocomplete), cb_data); - } + purple_signal_connect(purple_connections_get_handle(), "signed-on", entry, + PURPLE_CALLBACK(repopulate_autocomplete), data); + purple_signal_connect(purple_connections_get_handle(), "signed-off", entry, + PURPLE_CALLBACK(repopulate_autocomplete), data); purple_signal_connect(purple_accounts_get_handle(), "account-added", entry, - PURPLE_CALLBACK(repopulate_autocomplete), cb_data); + PURPLE_CALLBACK(repopulate_autocomplete), data); purple_signal_connect(purple_accounts_get_handle(), "account-removed", entry, - PURPLE_CALLBACK(repopulate_autocomplete), cb_data); + PURPLE_CALLBACK(repopulate_autocomplete), data); g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), data); } +gboolean