# HG changeset patch # User Evan Schoenberg # Date 1209768674 0 # Node ID 42dfa1139b5cd680408e8e45c10de238c9921f62 # Parent d5b3afea87640b239631a447ac9420cb6acaf826# Parent 0d7ceae153bdc10460befbff6f5398900370c265 merge of '21d37789f674809d615fc7676a092f1da438b0f5' and 'aafbbc317ab5f69e31e0bb6cabc264bb70745ef2' diff -r d5b3afea8764 -r 42dfa1139b5c COPYRIGHT --- a/COPYRIGHT Fri May 02 22:50:13 2008 +0000 +++ b/COPYRIGHT Fri May 02 22:51:14 2008 +0000 @@ -263,6 +263,7 @@ John Moody Tim Mooney Sergio Moretto +Andrei Mozzhuhin Christian Muise Richard Nelson Dennis Nezic diff -r d5b3afea8764 -r 42dfa1139b5c ChangeLog --- a/ChangeLog Fri May 02 22:50:13 2008 +0000 +++ b/ChangeLog Fri May 02 22:51:14 2008 +0000 @@ -14,8 +14,16 @@ * Added a plugin (not built by default) which adds a Send button back to the conversation window. People without physical keyboards have a hard time with the lack of the button. - * Clicking on the buddyicon in the conversation window toggles the size of - the icon between small and large. + * Clicking on the buddyicon in the conversation window toggles the + size of the icon between small and large. + * The settings of a chat (e.g. Handle in an XMPP chat, or Exchange in + an AIM chat) can be edited from its context menu in the buddy list. + * Add a "Present conversation window" preference to the Message + Notification plugin, the "Raise conversation window" option does not + unminimize windows or draw attention to them when they are on other + workspaces the "Present" option should. + * Add a preference to set Escape as the keyboard shortcut for closing + the conversation window. General: * The configure script now dies on more absent dependencies. The @@ -28,6 +36,9 @@ * The Contact Availability Prediction plugin must now be explicitly enabled. Use the --enable-cap argument to configure to enable it. + Finch: + * New default binding ctrl+x to open context menus. + version 2.4.1 (03/31/2008): http://developer.pidgin.im/query?status=closed&milestone=2.4.1 diff -r d5b3afea8764 -r 42dfa1139b5c ChangeLog.API --- a/ChangeLog.API Fri May 02 22:50:13 2008 +0000 +++ b/ChangeLog.API Fri May 02 22:51:14 2008 +0000 @@ -1,10 +1,6 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.x.x: - libpurple: - Added: - * serv_got_join_chat_failed - * chat-join-failed signal (see conversation-signals.dox) perl: Added: * Purple::Prefs::get_children_names. diff -r d5b3afea8764 -r 42dfa1139b5c doc/conversation-signals.dox --- a/doc/conversation-signals.dox Fri May 02 22:50:13 2008 +0000 +++ b/doc/conversation-signals.dox Fri May 02 22:51:14 2008 +0000 @@ -27,7 +27,6 @@ @signal chat-invited-user @signal chat-invited @signal chat-joined - @signal chat-join-failed @signal chat-left @signal chat-topic-changed @signal conversation-extended-menu @@ -401,16 +400,6 @@ @param conv The conversation that joined the chat room. @endsignaldef - @signaldef chat-join-failed - @signalproto -void (*chat_join_failed)(PurpleConnection *gc, const char *name); - @endsignalproto - @signaldesc - Emitted when an account fails to join a chat room - @param gc The PurpleConnection of the account which failed to join the chat. - @param name The name of the chat. - @endsignaldef - @signaldef chat-left @signalproto void (*chat_left)(PurpleConversation *conv); diff -r d5b3afea8764 -r 42dfa1139b5c finch/gntaccount.c --- a/finch/gntaccount.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/gntaccount.c Fri May 02 22:51:14 2008 +0000 @@ -122,7 +122,7 @@ if (value == NULL || *value == '\0') { purple_notify_error(NULL, _("Error"), _("Account was not added"), - _("Screenname of an account must be non-empty.")); + _("Username of an account must be non-empty.")); return; } @@ -526,7 +526,7 @@ gnt_box_add_widget(GNT_BOX(window), hbox); dialog->screenname = entry = gnt_entry_new(NULL); - gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Screen name:"))); + gnt_box_add_widget(GNT_BOX(hbox), gnt_label_new(_("Username:"))); gnt_box_add_widget(GNT_BOX(hbox), entry); /* User splits */ diff -r d5b3afea8764 -r 42dfa1139b5c finch/gntblist.c --- a/finch/gntblist.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/gntblist.c Fri May 02 22:51:14 2008 +0000 @@ -380,6 +380,27 @@ fnode = FINCH_GET_DATA(node); if (fnode && fnode->signed_timer) flag |= GNT_TEXT_FLAG_BLINK; + } else if (PURPLE_BLIST_NODE_IS_GROUP(node)) { + /* If the node is collapsed, then check to see if any of the priority buddies of + * any of the contacts within this group recently signed on/off, and set the blink + * flag appropriately. */ + /* XXX: Refs #5444 */ + /* XXX: there's no way I can ask if the node is expanded or not? *sigh* + * API addition would be necessary */ +#if 0 + if (!gnt_tree_get_expanded(GNT_TREE(ggblist->tree), node)) { + for (node = purple_blist_node_get_first_child(node); node; + node = purple_blist_node_get_sibling_next(node)) { + PurpleBlistNode *pnode; + pnode = purple_contact_get_priority_buddy((PurpleContact*)node); + fnode = FINCH_GET_DATA(node); + if (fnode && fnode->signed_timer) { + flag |= GNT_TEXT_FLAG_BLINK; + break; + } + } + } +#endif } return flag; @@ -560,7 +581,7 @@ PurpleBuddy *buddy; if (!username) - error = _("You must provide a screename for the buddy."); + error = _("You must provide a username for the buddy."); else if (!group) error = _("You must provide a group."); else if (!account) @@ -598,7 +619,7 @@ purple_request_fields_add_group(fields, group); - field = purple_request_field_string_new("screenname", _("Screen Name"), username, FALSE); + field = purple_request_field_string_new("screenname", _("Username"), username, FALSE); purple_request_field_group_add_field(group, field); field = purple_request_field_string_new("alias", _("Alias (optional)"), alias, FALSE); @@ -1034,7 +1055,11 @@ else val = g_strdup(purple_request_field_string_get_value(field)); - g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val); /* val should not be free'd */ + if (!val) { + g_hash_table_remove(purple_chat_get_components(chat), id); + } else { + g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val); /* val should not be free'd */ + } } } } @@ -1065,8 +1090,13 @@ } else { field = purple_request_field_string_new(pce->identifier, pce->label, g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier), FALSE); + if (pce->secret) + purple_request_field_string_set_masked(field, TRUE); } + if (pce->required) + purple_request_field_set_required(field, TRUE); + purple_request_field_group_add_field(group, field); g_free(pce); } @@ -2597,7 +2627,7 @@ purple_request_fields(purple_get_blist(), _("Block/Unblock"), NULL, - _("Please enter the screen name or alias of the person " + _("Please enter the username or alias of the person " "you would like to Block/Unblock."), fields, _("OK"), G_CALLBACK(block_select_cb), @@ -2648,7 +2678,7 @@ purple_request_fields(purple_get_blist(), _("New Instant Message"), NULL, - _("Please enter the screen name or alias of the person " + _("Please enter the username or alias of the person " "you would like to IM."), fields, _("OK"), G_CALLBACK(send_im_select_cb), diff -r d5b3afea8764 -r 42dfa1139b5c finch/gntlog.c --- a/finch/gntlog.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/gntlog.c Fri May 02 22:51:14 2008 +0000 @@ -139,7 +139,8 @@ } -static void destroy_cb(GntWidget *w, struct log_viewer_hash_t *ht) { +static void destroy_cb(GntWidget *w, struct log_viewer_hash_t *ht) +{ FinchLogViewer *lv = syslog_viewer; if (ht != NULL) { @@ -162,12 +163,12 @@ gnt_widget_destroy(w); } -static void log_select_cb(GntWidget *w, gpointer old, gpointer new, FinchLogViewer *viewer) { +static void log_select_cb(GntWidget *w, gpointer old, gpointer new, FinchLogViewer *viewer) +{ GntTree *tree = GNT_TREE(w); PurpleLog *log = NULL; PurpleLogReadFlags flags; char *read = NULL, *strip, *newline; - int h; if (!viewer->search && !gnt_tree_get_parent_key(tree, new)) return; @@ -204,8 +205,6 @@ gnt_text_view_clear(GNT_TEXT_VIEW(viewer->text)); gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(viewer->text), strip, GNT_TEXT_FLAG_NORMAL); - gnt_widget_get_size(viewer->text, NULL, &h); - gnt_text_view_scroll(GNT_TEXT_VIEW(viewer->text), h - 2); g_free(read); g_free(strip); } @@ -321,6 +320,7 @@ /* Viewer ************/ lv->text = gnt_text_view_new(); gnt_box_add_widget(GNT_BOX(hbox), lv->text); + gnt_text_view_set_flag(GNT_TEXT_VIEW(lv->text), GNT_TEXT_VIEW_TOP_ALIGN); hbox = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(vbox), hbox); diff -r d5b3afea8764 -r 42dfa1139b5c finch/gntrequest.c --- a/finch/gntrequest.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/gntrequest.c Fri May 02 22:51:14 2008 +0000 @@ -295,8 +295,7 @@ * updating the fields at the end like here, it updates the appropriate field * instantly whenever a change is made. That allows it to make sure the * 'required' fields are entered before the user can hit OK. It's not the case - * here, althought it can be done. I am not honouring the 'required' fields - * for the moment. */ + * here, althought it can be done. */ for (list = purple_request_fields_get_groups(fields); list; list = list->next) { PurpleRequestFieldGroup *group = list->data; @@ -368,6 +367,15 @@ } } + purple_notify_close_with_handle(button); + + if (!purple_request_fields_all_required_filled(fields)) { + purple_notify_error(button, _("Error"), + _("You must fill all the required fields."), + _("The required fields are underlined.")); + return; + } + if (callback) callback(data, fields); @@ -587,7 +595,11 @@ if (type != PURPLE_REQUEST_FIELD_BOOLEAN && label) { - GntWidget *l = gnt_label_new(label); + GntWidget *l; + if (purple_request_field_is_required(field)) + l = gnt_label_new_with_format(label, GNT_TEXT_FLAG_UNDERLINE); + else + l = gnt_label_new(label); gnt_widget_set_size(l, 0, 1); gnt_box_add_widget(GNT_BOX(hbox), l); } diff -r d5b3afea8764 -r 42dfa1139b5c finch/gntsound.c --- a/finch/gntsound.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/gntsound.c Fri May 02 22:51:14 2008 +0000 @@ -103,7 +103,7 @@ {PURPLE_SOUND_CHAT_YOU_SAY, N_("You talk in chat"), "send_chat_msg", "send.wav", NULL}, {PURPLE_SOUND_CHAT_SAY, N_("Others talk in chat"), "chat_msg_recv", "receive.wav", NULL}, {PURPLE_SOUND_POUNCE_DEFAULT, NULL, "pounce_default", "alert.wav", NULL}, - {PURPLE_SOUND_CHAT_NICK, N_("Someone says your screen name in chat"), "nick_said", "alert.wav", NULL} + {PURPLE_SOUND_CHAT_NICK, N_("Someone says your username in chat"), "nick_said", "alert.wav", NULL} }; const char * diff -r d5b3afea8764 -r 42dfa1139b5c finch/libgnt/gntwidget.c --- a/finch/libgnt/gntwidget.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/libgnt/gntwidget.c Fri May 02 22:51:14 2008 +0000 @@ -257,6 +257,7 @@ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "context-menu", context_menu, GNT_KEY_POPUP, NULL); gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_F11, NULL); + gnt_bindable_register_binding(GNT_BINDABLE_CLASS(klass), "context-menu", GNT_KEY_CTRL_X, NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); GNTDEBUG; diff -r d5b3afea8764 -r 42dfa1139b5c finch/libgnt/gntwm.c --- a/finch/libgnt/gntwm.c Fri May 02 22:50:13 2008 +0000 +++ b/finch/libgnt/gntwm.c Fri May 02 22:51:14 2008 +0000 @@ -1516,7 +1516,7 @@ gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "help-for-window", help_for_window, "\033" "|", NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-start", ignore_keys_start, - GNT_KEY_CTRL_G, NULL); + NULL, NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "ignore-keys-end", ignore_keys_end, "\033" GNT_KEY_CTRL_G, NULL); gnt_bindable_class_register_action(GNT_BINDABLE_CLASS(klass), "window-next-urgent", window_next_urgent, diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/conversation.c --- a/libpurple/conversation.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/conversation.c Fri May 02 22:51:14 2008 +0000 @@ -2368,12 +2368,6 @@ purple_value_new(PURPLE_TYPE_SUBTYPE, PURPLE_SUBTYPE_CONVERSATION)); - purple_signal_register(handle, "chat-join-failed", - purple_marshal_VOID__POINTER_POINTER, NULL, 2, - purple_value_new(PURPLE_TYPE_SUBTYPE, - PURPLE_SUBTYPE_CONNECTION), - purple_value_new(PURPLE_TYPE_STRING)); - purple_signal_register(handle, "chat-left", purple_marshal_VOID__POINTER, NULL, 1, purple_value_new(PURPLE_TYPE_SUBTYPE, diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/idle.c --- a/libpurple/idle.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/idle.c Fri May 02 22:51:14 2008 +0000 @@ -252,7 +252,7 @@ PurpleAccount *account; account = purple_connection_get_account(gc); - set_account_unidle(account); + idled_accts = g_list_remove(idled_accts, account); } static void diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/plugins/newline.c --- a/libpurple/plugins/newline.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/plugins/newline.c Fri May 02 22:51:14 2008 +0000 @@ -102,11 +102,11 @@ "core-plugin_pack-newline", /**< id */ N_("New Line"), /**< name */ - DISPLAY_VERSION, /**< version */ + DISPLAY_VERSION, /**< version */ N_("Prepends a newline to displayed message."), /**< summary */ N_("Prepends a newline to messages so that the " "rest of the message appears below the " - "screen name in the conversation window."), /**< description */ + "username in the conversation window."), /**< description */ "Stu Tomlinson ", /**< author */ PURPLE_WEBSITE, /**< homepage */ diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/jabber/auth.c --- a/libpurple/protocols/jabber/auth.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/jabber/auth.c Fri May 02 22:51:14 2008 +0000 @@ -54,6 +54,11 @@ PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("Server requires TLS/SSL for login. No TLS/SSL support found.")); return TRUE; + } else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE)) { + purple_connection_error_reason (js->gc, + PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, + _("You require encryption, but no TLS/SSL support found.")); + return TRUE; } } diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/jabber/buddy.c --- a/libpurple/protocols/jabber/buddy.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/jabber/buddy.c Fri May 02 22:51:14 2008 +0000 @@ -56,8 +56,7 @@ { g_return_if_fail(jb != NULL); - if(jb->error_msg) - g_free(jb->error_msg); + g_free(jb->error_msg); while(jb->resources) jabber_buddy_resource_free(jb->resources->data); @@ -155,12 +154,8 @@ } jbr->priority = priority; jbr->state = state; - if(jbr->status) - g_free(jbr->status); - if (status) - jbr->status = g_markup_escape_text(status, -1); - else - jbr->status = NULL; + g_free(jbr->status); + jbr->status = status != NULL ? g_markup_escape_text(status, -1) : NULL; return jbr; } @@ -502,6 +497,11 @@ if(((JabberStream*)gc->proto_data)->pep) { /* XEP-0084: User Avatars */ if(img) { + /* + * TODO: This is pretty gross. The Jabber PRPL really shouldn't + * do voodoo to try to determine the image type, height + * and width. + */ /* A PNG header, including the IHDR, but nothing else */ const struct { guchar signature[8]; /* must be hex 89 50 4E 47 0D 0A 1A 0A */ diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/jabber/chat.c --- a/libpurple/protocols/jabber/chat.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/jabber/chat.c Fri May 02 22:51:14 2008 +0000 @@ -222,39 +222,33 @@ if(!handle) handle = js->user->node; - tmp = g_strdup_printf("%s@%s", room, server); - room_jid = g_strdup(jabber_normalize(NULL, tmp)); - g_free(tmp); - if(!jabber_nodeprep_validate(room)) { char *buf = g_strdup_printf(_("%s is not a valid room name"), room); purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"), buf); - serv_got_join_chat_failed(gc, room_jid); - g_free(room_jid); g_free(buf); return; } else if(!jabber_nameprep_validate(server)) { char *buf = g_strdup_printf(_("%s is not a valid server name"), server); purple_notify_error(gc, _("Invalid Server Name"), _("Invalid Server Name"), buf); - serv_got_join_chat_failed(gc, room_jid); - g_free(room_jid); g_free(buf); return; } else if(!jabber_resourceprep_validate(handle)) { char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle); purple_notify_error(gc, _("Invalid Room Handle"), _("Invalid Room Handle"), buf); - serv_got_join_chat_failed(gc, room_jid); g_free(buf); - g_free(room_jid); return; } if(jabber_chat_find(js, room, server)) return; + tmp = g_strdup_printf("%s@%s", room, server); + room_jid = g_strdup(jabber_normalize(NULL, tmp)); + g_free(tmp); + chat = g_new0(JabberChat, 1); chat->js = gc->proto_data; diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/jabber/presence.c --- a/libpurple/protocols/jabber/presence.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/jabber/presence.c Fri May 02 22:51:14 2008 +0000 @@ -369,17 +369,29 @@ typedef struct _JabberPresenceCapabilities { JabberStream *js; - JabberBuddyResource *jbr; + JabberBuddy *jb; char *from; } JabberPresenceCapabilities; static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, gpointer user_data) { JabberPresenceCapabilities *userdata = user_data; + JabberID *jid; + JabberBuddyResource *jbr; GList *iter; - if(userdata->jbr->caps) - jabber_caps_free_clientinfo(userdata->jbr->caps); - userdata->jbr->caps = info; + jid = jabber_id_new(userdata->from); + jbr = jabber_buddy_find_resource(userdata->jb, jid->resource); + jabber_id_free(jid); + + if(!jbr) { + g_free(userdata->from); + g_free(userdata); + return; + } + + if(jbr->caps) + jabber_caps_free_clientinfo(jbr->caps); + jbr->caps = info; if (info) { for(iter = info->features; iter; iter = g_list_next(iter)) { @@ -575,7 +587,6 @@ serv_got_chat_left(js->gc, chat->id); } else { title = g_strdup_printf(_("Error joining chat %s"), from); - serv_got_join_chat_failed(js->gc, room_jid); } purple_notify_error(js->gc, title, title, msg); g_free(title); @@ -742,7 +753,7 @@ if(node && ver) { JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); userdata->js = js; - userdata->jbr = jbr; + userdata->jb = jb; userdata->from = g_strdup(from); jabber_caps_get_info(js, from, node, ver, ext, jabber_presence_set_capabilities, userdata); } diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/jabber/usermood.c --- a/libpurple/protocols/jabber/usermood.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/jabber/usermood.c Fri May 02 22:51:14 2008 +0000 @@ -147,7 +147,7 @@ static void do_mood_set_from_fields(PurpleConnection *gc, PurpleRequestFields *fields) { JabberStream *js; - int max_mood_idx; + const int max_mood_idx = sizeof(moodstrings) / sizeof(moodstrings[0]) - 1; int selected_mood = purple_request_fields_get_choice(fields, "mood"); if (!PURPLE_CONNECTION_IS_VALID(gc)) { @@ -157,9 +157,6 @@ js = gc->proto_data; - /* This is ugly, but protects us from unexpected values. */ - for (max_mood_idx = 0; moodstrings[max_mood_idx]; max_mood_idx++); - if (selected_mood < 0 || selected_mood >= max_mood_idx) { purple_debug_error("jabber", "Invalid mood index (%d) selected.\n", selected_mood); return; diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/msn/error.c --- a/libpurple/protocols/msn/error.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/msn/error.c Fri May 02 22:51:14 2008 +0000 @@ -56,7 +56,7 @@ g_snprintf(msg, sizeof(msg), _("Already logged in")); break; case 208: - g_snprintf(msg, sizeof(msg), _("Invalid screen name")); + g_snprintf(msg, sizeof(msg), _("Invalid username")); break; case 209: g_snprintf(msg, sizeof(msg), _("Invalid friendly name")); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/msn/state.c --- a/libpurple/protocols/msn/state.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/msn/state.c Fri May 02 22:51:14 2008 +0000 @@ -87,7 +87,8 @@ msn_parse_currentmedia(const char *cmedia, CurrentMedia *media) { char **cmedia_array; - int strings; + int strings = 0; + gboolean parsed = FALSE; if ((cmedia == NULL) || (*cmedia == '\0')) { purple_debug_info("msn", "No currentmedia string\n"); @@ -108,31 +109,39 @@ * 6: Album * 7: ? */ - strings = 0; +#if GLIB_CHECK_VERSION(2,6,0) + strings = g_strv_length(cmedia_array); +#else while (cmedia_array[++strings] != NULL); +#endif + + if (strings >= 4 && !strcmp(cmedia_array[2], "1")) { + parsed = TRUE; - if (strings < 4) - return FALSE; - if (strcmp(cmedia_array[2], "1")) - return FALSE; + g_free(media->title); + if (strings == 4) { + media->title = g_strdup(cmedia_array[3]); + } else { + media->title = g_strdup(cmedia_array[4]); + } - if (strings == 4) { - media->title = g_strdup(cmedia_array[3]); - } else { - media->title = g_strdup(cmedia_array[4]); + g_free(media->artist); + if (strings > 5) + media->artist = g_strdup(cmedia_array[5]); + else + media->artist = NULL; + + g_free(media->album); + if (strings > 6) + media->album = g_strdup(cmedia_array[6]); + else + media->album = NULL; + } - if (strings > 5) - media->artist = g_strdup(cmedia_array[5]); - else - media->artist = NULL; + g_strfreev(cmedia_array); - if (strings > 6) - media->album = g_strdup(cmedia_array[6]); - else - media->album = NULL; - - return TRUE; + return parsed; } /* get the CurrentMedia info from the XML string */ diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/msn/userlist.c --- a/libpurple/protocols/msn/userlist.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/msn/userlist.c Fri May 02 22:51:14 2008 +0000 @@ -714,7 +714,7 @@ char *str = g_strdup_printf(_("Unable to add \"%s\"."), who); purple_notify_error(NULL, NULL, str, - _("The screen name specified is invalid.")); + _("The username specified is invalid.")); g_free(str); return; diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/msnp9/error.c --- a/libpurple/protocols/msnp9/error.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/msnp9/error.c Fri May 02 22:51:14 2008 +0000 @@ -56,7 +56,7 @@ g_snprintf(msg, sizeof(msg), _("Already logged in")); break; case 208: - g_snprintf(msg, sizeof(msg), _("Invalid screen name")); + g_snprintf(msg, sizeof(msg), _("Invalid username")); break; case 209: g_snprintf(msg, sizeof(msg), _("Invalid friendly name")); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/msnp9/userlist.c --- a/libpurple/protocols/msnp9/userlist.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/msnp9/userlist.c Fri May 02 22:51:14 2008 +0000 @@ -652,7 +652,7 @@ { char *str = g_strdup_printf(_("Unable to add \"%s\"."), who); purple_notify_error(NULL, NULL, str, - _("The screen name specified is invalid.")); + _("The username specified is invalid.")); g_free(str); } diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/novell/nmuser.c --- a/libpurple/protocols/novell/nmuser.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/novell/nmuser.c Fri May 02 22:51:14 2008 +0000 @@ -1919,10 +1919,10 @@ case NMERR_AUTHENTICATION_FAILED: case NMERR_CREDENTIALS_MISSING: - return _("Incorrect screen name or password"); + return _("Incorrect username or password"); case NMERR_HOST_NOT_FOUND: - return _("Could not recognize the host of the screen name you entered"); + return _("Could not recognize the host of the username you entered"); case NMERR_ACCESS_DENIED: return _("Your account has been disabled because too many incorrect passwords were entered"); @@ -1935,7 +1935,7 @@ return _("You have reached your limit for the number of contacts allowed"); case NMERR_OBJECT_NOT_FOUND: - return _("You have entered an incorrect screen name"); + return _("You have entered an incorrect username"); case NMERR_DIRECTORY_UPDATE: return _("An error occurred while updating the directory"); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/oscar/misc.c --- a/libpurple/protocols/oscar/misc.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/oscar/misc.c Fri May 02 22:51:14 2008 +0000 @@ -39,7 +39,6 @@ void aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype) { - FlapFrame *frame; aim_snacid_t snacid = 0x00000000; flap_connection_send_snac(od, conn, family, subtype, 0x0000, snacid, NULL); @@ -48,7 +47,6 @@ void aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype) { - FlapFrame *frame; aim_snacid_t snacid; snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/simple/simple.c Fri May 02 22:51:14 2008 +0000 @@ -1890,7 +1890,7 @@ if (strpbrk(username, " \t\v\r\n") != NULL) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, - _("SIP screen names may not contain whitespaces or @ symbols")); + _("SIP usernames may not contain whitespaces or @ symbols")); return; } diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/toc/toc.c --- a/libpurple/protocols/toc/toc.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/toc/toc.c Fri May 02 22:51:14 2008 +0000 @@ -546,7 +546,7 @@ g_snprintf(buf, sizeof(buf), _("Failure unknown: %s."), w); break; case 980: - g_snprintf(buf, sizeof(buf), _("Incorrect screen name or password.")); + g_snprintf(buf, sizeof(buf), _("Incorrect username or password.")); break; case 981: g_snprintf(buf, sizeof(buf), _("The service is temporarily unavailable.")); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/yahoo/yahoo.c --- a/libpurple/protocols/yahoo/yahoo.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo.c Fri May 02 22:51:14 2008 +0000 @@ -2124,7 +2124,7 @@ switch (err) { case 3: - msg = g_strdup(_("Invalid screen name.")); + msg = g_strdup(_("Invalid username.")); reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME; break; case 13: diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/yahoo/yahoo_aliases.c --- a/libpurple/protocols/yahoo/yahoo_aliases.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_aliases.c Fri May 02 22:51:14 2008 +0000 @@ -68,7 +68,8 @@ purple_debug_info("yahoo", "No Aliases to process.%s%s\n", error_message ? " Error:" : "", error_message ? error_message : ""); } else { - const char *yid, *full_name, *nick_name, *alias, *id, *fn, *ln, *nn; + gchar *full_name, *nick_name, *alias; + const char *yid, *id, *fn, *ln, *nn; PurpleBuddy *b = NULL; xmlnode *item, *contacts; @@ -92,7 +93,9 @@ nn = xmlnode_get_attrib(item,"nn"); id = xmlnode_get_attrib(item,"id"); - /* Yahoo stores first and last names separately, lets put them together into a full name */ + full_name = nick_name = alias = NULL; + + /* Yahoo stores first and last names separately, lets put them together into a full name */ if (yd->jp) full_name = g_strstrip(g_strdup_printf("%s %s", (ln != NULL ? ln : "") , (fn != NULL ? fn : ""))); else @@ -103,8 +106,6 @@ alias = nick_name; /* If we have a nickname from Yahoo, let's use it */ else if (strlen(full_name) != 0) alias = full_name; /* If no Yahoo nickname, we can use the full_name created above */ - else - alias = NULL; /* No nickname, first name or last name, then you get no alias !! */ /* Find the local buddy that matches */ b = purple_find_buddy(cb->gc->account, yid); @@ -118,6 +119,7 @@ yu->firstname = g_strdup(fn); yu->lastname = g_strdup(ln); yu->nickname = g_strdup(nn); + /* TODO: Isn't there a possiblity that b->proto_data is already set? */ b->proto_data=yu; /* Finally, if we received an alias, we better update the buddy list */ @@ -132,6 +134,9 @@ } else { purple_debug_info("yahoo", "Bizarre, received alias for %s, but they are not on your list...\n", yid); } + + g_free(full_name); + g_free(nick_name); } } xmlnode_free(contacts); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/protocols/yahoo/yahoo_filexfer.c --- a/libpurple/protocols/yahoo/yahoo_filexfer.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/protocols/yahoo/yahoo_filexfer.c Fri May 02 22:51:14 2008 +0000 @@ -998,6 +998,7 @@ url = g_strdup_printf("%ld.%ld.%ld.%ld", d, c, b, a); if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) { purple_xfer_cancel_remote(xfer); + g_free(url); return; } g_free(url); diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/server.c --- a/libpurple/server.c Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/server.c Fri May 02 22:51:14 2008 +0000 @@ -967,12 +967,6 @@ purple_signal_emit(purple_conversations_get_handle(), "chat-left", conv); } -void serv_got_join_chat_failed(PurpleConnection *gc, const char *name) -{ - purple_signal_emit(purple_conversations_get_handle(), "chat-join-failed", - gc, name); -} - void serv_got_chat_in(PurpleConnection *g, int id, const char *who, PurpleMessageFlags flags, const char *message, time_t mtime) { diff -r d5b3afea8764 -r 42dfa1139b5c libpurple/server.h --- a/libpurple/server.h Fri May 02 22:50:13 2008 +0000 +++ b/libpurple/server.h Fri May 02 22:51:14 2008 +0000 @@ -166,15 +166,6 @@ PurpleConversation *serv_got_joined_chat(PurpleConnection *gc, int id, const char *name); -/** - * Called by a prpl when an attempt to join a chat via serv_join_chat() - * fails. - * - * @param gc The connection on which chat joining failed - * @param name The name of the chat which we did not join - */ -void serv_got_join_chat_failed(PurpleConnection *gc, const char *name); - void serv_got_chat_left(PurpleConnection *g, int id); void serv_got_chat_in(PurpleConnection *g, int id, const char *who, PurpleMessageFlags flags, const char *message, time_t mtime); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkaccount.c Fri May 02 22:51:14 2008 +0000 @@ -408,7 +408,7 @@ g_object_set(G_OBJECT(dialog->screenname_entry), "truncate-multiline", TRUE, NULL); #endif - add_pref_box(dialog, vbox, _("Screen _name:"), dialog->screenname_entry); + add_pref_box(dialog, vbox, _("_Username:"), dialog->screenname_entry); g_signal_connect(G_OBJECT(dialog->screenname_entry), "changed", G_CALLBACK(screenname_changed_cb), dialog); @@ -496,10 +496,6 @@ dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"), dialog->password_entry); - /* Alias */ - dialog->alias_entry = gtk_entry_new(); - add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry); - /* Remember Password */ dialog->remember_pass_check = gtk_check_button_new_with_mnemonic(_("Remember pass_word")); @@ -571,6 +567,10 @@ gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_widget_show(vbox); + /* Alias */ + dialog->alias_entry = gtk_entry_new(); + add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry); + /* New mail notifications */ dialog->new_mail_check = gtk_check_button_new_with_mnemonic(_("New _mail notifications")); @@ -654,6 +654,7 @@ set_dialog_icon(dialog, NULL, 0, NULL); } +#if 0 if (!dialog->prpl_info || (!(dialog->prpl_info->options & OPT_PROTO_MAIL_CHECK) && (dialog->prpl_info->icon_spec.format == NULL))) { @@ -661,6 +662,7 @@ /* Nothing to see :( aww. */ gtk_widget_hide(dialog->user_frame); } +#endif } static void @@ -1911,7 +1913,7 @@ /* Screen Name column */ column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(column, _("Screen Name")); + gtk_tree_view_column_set_title(column, _("Username")); gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1); gtk_tree_view_column_set_resizable(column, TRUE); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkblist.c --- a/pidgin/gtkblist.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkblist.c Fri May 02 22:51:14 2008 +0000 @@ -614,6 +614,78 @@ pidgin_blist_refresh(list); } +static void +chat_components_edit_ok(PurpleChat *chat, PurpleRequestFields *allfields) +{ + GList *groups, *fields; + + for (groups = purple_request_fields_get_groups(allfields); groups; groups = groups->next) { + fields = purple_request_field_group_get_fields(groups->data); + for (; fields; fields = fields->next) { + PurpleRequestField *field = fields->data; + const char *id; + char *val; + + id = purple_request_field_get_id(field); + if (purple_request_field_get_type(field) == PURPLE_REQUEST_FIELD_INTEGER) + val = g_strdup_printf("%d", purple_request_field_int_get_value(field)); + else + val = g_strdup(purple_request_field_string_get_value(field)); + + if (!val) { + g_hash_table_remove(purple_chat_get_components(chat), id); + } else { + g_hash_table_replace(purple_chat_get_components(chat), g_strdup(id), val); /* val should not be free'd */ + } + } + } +} + +static void chat_components_edit(GtkWidget *w, PurpleBlistNode *node) +{ + PurpleRequestFields *fields = purple_request_fields_new(); + PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL); + PurpleRequestField *field; + GList *parts, *iter; + struct proto_chat_entry *pce; + PurpleConnection *gc; + PurpleChat *chat = (PurpleChat*)node; + + purple_request_fields_add_group(fields, group); + + gc = purple_account_get_connection(purple_chat_get_account(chat)); + parts = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->chat_info(gc); + + for (iter = parts; iter; iter = iter->next) { + pce = iter->data; + if (pce->is_int) { + int val; + const char *str = g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier); + if (!str || sscanf(str, "%d", &val) != 1) + val = pce->min; + field = purple_request_field_int_new(pce->identifier, pce->label, val); + } else { + field = purple_request_field_string_new(pce->identifier, pce->label, + g_hash_table_lookup(purple_chat_get_components(chat), pce->identifier), FALSE); + if (pce->secret) + purple_request_field_string_set_masked(field, TRUE); + } + + if (pce->required) + purple_request_field_set_required(field, TRUE); + + purple_request_field_group_add_field(group, field); + g_free(pce); + } + + g_list_free(parts); + + purple_request_fields(NULL, _("Edit Chat"), NULL, _("Please update the necessary fields."), + fields, _("Save"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL, + NULL, NULL, NULL, + chat); +} + static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node) { GtkTreeIter iter; @@ -1510,6 +1582,8 @@ pidgin_separator(menu); + pidgin_new_item_from_stock(menu, _("_Edit Settings..."), NULL, + G_CALLBACK(chat_components_edit), node, 0, 0, NULL); pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS, G_CALLBACK(gtk_blist_menu_alias_cb), node, 0, 0, NULL); pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE, @@ -3665,13 +3739,13 @@ } return text; } - else - if (hidden_conv) { - char *tmp = esc; - esc = g_strdup_printf("%s", esc); - g_free(tmp); - } - return esc; + else if (hidden_conv) + { + char *tmp = esc; + esc = g_strdup_printf("%s", esc); + g_free(tmp); + } + return esc; } prpl = purple_find_prpl(purple_account_get_protocol_id(b->account)); @@ -6393,7 +6467,7 @@ gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 0, 2, 0, 1); - label = gtk_label_new_with_mnemonic(_("Buddy's _screen name:")); + label = gtk_label_new_with_mnemonic(_("Buddy's _username:")); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkconv.c --- a/pidgin/gtkconv.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkconv.c Fri May 02 22:51:14 2008 +0000 @@ -3052,7 +3052,7 @@ { N_("/Options/Enable _Sounds"), NULL, menu_sounds_cb, 0, "", NULL }, { "/Options/sep0", NULL, NULL, 0, "", NULL }, { N_("/Options/Show Formatting _Toolbars"), NULL, menu_toolbar_cb, 0, "", NULL }, - { N_("/Options/Show Ti_mestamps"), "F2", menu_timestamps_cb, 0, "", NULL }, + { N_("/Options/Show Ti_mestamps"), NULL, menu_timestamps_cb, 0, "", NULL }, }; static const int menu_item_count = @@ -3980,11 +3980,10 @@ } static void -tab_complete_process_item(int *most_matched, char *entered, char **partial, char *nick_partial, +tab_complete_process_item(int *most_matched, char *entered, gsize entered_bytes, char **partial, char *nick_partial, GList **matches, gboolean command, char *name) { - strncpy(nick_partial, name, strlen(entered)); - nick_partial[strlen(entered)] = '\0'; + memcpy(nick_partial, name, entered_bytes); if (purple_utf8_strcasecmp(nick_partial, entered)) return; @@ -4029,6 +4028,7 @@ const char *prefix; GList *matches = NULL; gboolean command = FALSE; + gsize entered_bytes = 0; gtkconv = PIDGIN_CONVERSATION(conv); @@ -4048,19 +4048,24 @@ /* if we're at the end of ": " we need to move back 2 spaces */ start = strlen(text) - 1; - if (strlen(text) >= 2 && !strncmp(&text[start-1], ": ", 2)) { + if (start >= 1 && !strncmp(&text[start-1], ": ", 2)) { gtk_text_iter_backward_chars(&word_start, 2); - start-=2; - } - - /* find the start of the word that we're tabbing */ - while (start >= 0 && text[start] != ' ') { - gtk_text_iter_backward_char(&word_start); - start--; + } + + /* find the start of the word that we're tabbing. + * Using gtk_text_iter_backward_word_start won't work, because a nick can contain + * characters (e.g. '.', '/' etc.) that Pango may think are word separators. */ + while (gtk_text_iter_backward_char(&word_start)) { + if (gtk_text_iter_get_char(&word_start) == ' ') { + /* Reached the whitespace before the start of the word. Move forward once */ + gtk_text_iter_forward_char(&word_start); + break; + } } prefix = pidgin_get_cmd_prefix(); - if (start == -1 && (strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) { + if (gtk_text_iter_get_offset(&word_start) == 0 && + (strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) { command = TRUE; gtk_text_iter_forward_chars(&word_start, strlen(prefix)); } @@ -4069,13 +4074,14 @@ entered = gtk_text_buffer_get_text(gtkconv->entry_buffer, &word_start, &cursor, FALSE); + entered_bytes = strlen(entered); if (!g_utf8_strlen(entered, -1)) { g_free(entered); return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; } - nick_partial = g_malloc(strlen(entered)+1); + nick_partial = g_malloc0(entered_bytes + 1); if (command) { GList *list = purple_cmd_list(conv); @@ -4083,7 +4089,7 @@ /* Commands */ for (l = list; l != NULL; l = l->next) { - tab_complete_process_item(&most_matched, entered, &partial, nick_partial, + tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, &matches, TRUE, l->data); } g_list_free(list); @@ -4096,7 +4102,7 @@ /* Users */ for (; l != NULL; l = l->next) { - tab_complete_process_item(&most_matched, entered, &partial, nick_partial, + tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, &matches, TRUE, ((PurpleConvChatBuddy *)l->data)->name); } @@ -4114,7 +4120,7 @@ -1); if (name && alias && strcmp(name, alias)) - tab_complete_process_item(&most_matched, entered, &partial, nick_partial, + tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, &matches, FALSE, alias); g_free(name); g_free(alias); @@ -4452,7 +4458,9 @@ GdkRectangle oneline; int height, diff; int pad_top, pad_inside, pad_bottom; - int max_height = gtkconv->tab_cont->allocation.height / 2; + int total_height = (gtkconv->imhtml->allocation.height + gtkconv->entry->allocation.height); + int max_height = total_height / 2; + int min_height; pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry)); @@ -4476,12 +4484,11 @@ /* Make sure there's enough room for at least two lines. Allocate enough space to * prevent scrolling when the second line is a continuation of the first line, or * is the beginning of a new paragraph. */ - height = MAX(height, 2 * (oneline.height + MAX(pad_inside, pad_top + pad_bottom))); - - height = MIN(height, max_height); + min_height = 2 * (oneline.height + MAX(pad_inside, pad_top + pad_bottom)); + height = CLAMP(height, min_height, max_height); diff = height - gtkconv->entry->allocation.height; - if (diff == 0 || (diff < 0 && -diff < oneline.height / 2)) + if (ABS(diff) < oneline.height / 2) return FALSE; gtk_widget_set_size_request(gtkconv->lower_hbox, -1, @@ -4758,6 +4765,7 @@ /* Setup the gtkimhtml widget */ frame = pidgin_create_imhtml(FALSE, >kconv->imhtml, NULL, &imhtml_sw); + gtk_widget_set_size_request(gtkconv->imhtml, -1, 0); if (chat) { GtkWidget *hpaned; diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkdialogs.c --- a/pidgin/gtkdialogs.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkdialogs.c Fri May 02 22:51:14 2008 +0000 @@ -760,7 +760,7 @@ purple_request_fields(purple_get_blist(), _("New Instant Message"), NULL, - _("Please enter the screen name or alias of the person " + _("Please enter the username or alias of the person " "you would like to IM."), fields, _("OK"), G_CALLBACK(pidgin_dialogs_im_cb), @@ -899,7 +899,7 @@ purple_request_fields(purple_get_blist(), _("Get User Info"), NULL, - _("Please enter the screen name or alias of the person " + _("Please enter the username or alias of the person " "whose info you would like to view."), fields, _("OK"), G_CALLBACK(pidgin_dialogs_info_cb), @@ -991,7 +991,7 @@ purple_request_fields(purple_get_blist(), _("View User Log"), NULL, - _("Please enter the screen name or alias of the person " + _("Please enter the username or alias of the person " "whose log you would like to view."), fields, _("OK"), G_CALLBACK(pidgin_dialogs_log_cb), diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkprefs.c Fri May 02 22:51:14 2008 +0000 @@ -825,6 +825,106 @@ gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE); } + +#define CONVERSATION_CLOSE_ACCEL_PATH "
/Conversation/Close" + +/* Filled in in keyboard_shortcuts(). */ +static GtkAccelKey ctrl_w = { 0, 0, 0 }; +static GtkAccelKey escape = { 0, 0, 0 }; + +static guint escape_closes_conversation_cb_id = 0; + +static gboolean +accel_is_escape(GtkAccelKey *k) +{ + return (k->accel_key == escape.accel_key + && k->accel_mods == escape.accel_mods); +} + +/* Update the tickybox in Preferences when the keybinding for Conversation -> + * Close is changed via Gtk. + */ +static void +conversation_close_accel_changed_cb (GtkAccelMap *object, + gchar *accel_path, + guint accel_key, + GdkModifierType accel_mods, + gpointer checkbox_) +{ + GtkToggleButton *checkbox = GTK_TOGGLE_BUTTON(checkbox_); + GtkAccelKey new = { accel_key, accel_mods, 0 }; + + g_signal_handler_block(checkbox, escape_closes_conversation_cb_id); + gtk_toggle_button_set_active(checkbox, accel_is_escape(&new)); + g_signal_handler_unblock(checkbox, escape_closes_conversation_cb_id); +} + + +static void +escape_closes_conversation_cb(GtkWidget *w, + gpointer unused) +{ + gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); + gboolean changed; + GtkAccelKey *new_key = active ? &escape : &ctrl_w; + + changed = gtk_accel_map_change_entry(CONVERSATION_CLOSE_ACCEL_PATH, + new_key->accel_key, new_key->accel_mods, TRUE); + + /* If another path is already bound to the new accelerator, + * _change_entry tries to delete that binding (because it was passed + * replace=TRUE). If that other path is locked, then _change_entry + * will fail. We don't ever lock any accelerator paths, so this case + * should never arise. + */ + if(!changed) + purple_debug_warning("gtkprefs", "Escape accel failed to change\n"); + + /* TODO: create pidgin_accels_schedule_save */ + pidgin_save_accels_cb(NULL, 0, 0, NULL, NULL); +} + + +/* Creates preferences for keyboard shortcuts that it's hard to change with the + * standard Gtk accelerator-changing mechanism. + */ +static void +keyboard_shortcuts(GtkWidget *page) +{ + GtkWidget *vbox = pidgin_make_frame(page, _("Keyboard Shortcuts")); + GtkWidget *checkbox; + GtkAccelKey current = { 0, 0, 0 }; + GtkAccelMap *map = gtk_accel_map_get(); + + /* Maybe it would be better just to hardcode the values? + * -- resiak, 2007-04-30 + */ + if (ctrl_w.accel_key == 0) + { + gtk_accelerator_parse ("w", &(ctrl_w.accel_key), + &(ctrl_w.accel_mods)); + g_assert(ctrl_w.accel_key != 0); + + gtk_accelerator_parse ("Escape", &(escape.accel_key), + &(escape.accel_mods)); + g_assert(escape.accel_key != 0); + } + + checkbox = gtk_check_button_new_with_mnemonic( + _("Cl_ose conversations with the Escape key")); + gtk_accel_map_lookup_entry(CONVERSATION_CLOSE_ACCEL_PATH, ¤t); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), + accel_is_escape(¤t)); + + escape_closes_conversation_cb_id = g_signal_connect(checkbox, + "clicked", G_CALLBACK(escape_closes_conversation_cb), NULL); + + g_signal_connect(map, "changed::" CONVERSATION_CLOSE_ACCEL_PATH, + G_CALLBACK(conversation_close_accel_changed_cb), checkbox); + + gtk_box_pack_start(GTK_BOX(vbox), checkbox, FALSE, FALSE, 0); +} + static GtkWidget * interface_page(void) { @@ -904,6 +1004,10 @@ g_list_free(names); + + keyboard_shortcuts(ret); + + gtk_widget_show_all(ret); g_object_unref(sg); return ret; diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtkrequest.c Fri May 02 22:51:14 2008 +0000 @@ -1120,6 +1120,16 @@ gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); gtk_widget_show(img); + /* Cancel button */ + button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(cancel_text), G_CALLBACK(multifield_cancel_cb), data); + GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); + + /* OK button */ + button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(ok_text), G_CALLBACK(multifield_ok_cb), data); + data->ok_button = button; + GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); + gtk_window_set_default(GTK_WINDOW(win), button); + /* Setup the vbox */ vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); @@ -1272,6 +1282,7 @@ size_t col_offset = col_num * 2; PurpleRequestFieldType type; GtkWidget *widget = NULL; + const char *field_label; label = NULL; field = fl->data; @@ -1282,17 +1293,17 @@ } type = purple_request_field_get_type(field); + field_label = purple_request_field_get_label(field); - if (type != PURPLE_REQUEST_FIELD_BOOLEAN && - purple_request_field_get_label(field)) + if (type != PURPLE_REQUEST_FIELD_BOOLEAN && field_label) { - char *text; + char *text = NULL; - text = g_strdup_printf("%s:", - purple_request_field_get_label(field)); + if (field_label[strlen(field_label) - 1] != ':') + text = g_strdup_printf("%s:", field_label); label = gtk_label_new(NULL); - gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text); + gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), text ? text : field_label); g_free(text); gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); @@ -1393,18 +1404,8 @@ g_object_unref(sg); - /* Cancel button */ - button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(cancel_text), G_CALLBACK(multifield_cancel_cb), data); - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - - /* OK button */ - button = pidgin_dialog_add_button(GTK_DIALOG(win), text_to_stock(ok_text), G_CALLBACK(multifield_ok_cb), data); - data->ok_button = button; - GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); - gtk_window_set_default(GTK_WINDOW(win), button); - if (!purple_request_fields_all_required_filled(fields)) - gtk_widget_set_sensitive(button, FALSE); + gtk_widget_set_sensitive(data->ok_button, FALSE); pidgin_auto_parent_window(win); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtksavedstatuses.c Fri May 02 22:51:14 2008 +0000 @@ -968,7 +968,7 @@ /* Screen Name column */ column = gtk_tree_view_column_new(); gtk_tree_view_column_set_resizable(column, TRUE); - gtk_tree_view_column_set_title(column, _("Screen Name")); + gtk_tree_view_column_set_title(column, _("Username")); gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1); gtk_tree_view_column_set_resizable(column, TRUE); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/gtksound.c --- a/pidgin/gtksound.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/gtksound.c Fri May 02 22:51:14 2008 +0000 @@ -70,7 +70,7 @@ {N_("Others talk in chat"), "chat_msg_recv", "receive.wav"}, /* this isn't a terminator, it's the buddy pounce default sound event ;-) */ {NULL, "pounce_default", "alert.wav"}, - {N_("Someone says your screen name in chat"), "nick_said", "alert.wav"} + {N_("Someone says your username in chat"), "nick_said", "alert.wav"} }; static gboolean diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/plugins/gevolution/new_person_dialog.c --- a/pidgin/plugins/gevolution/new_person_dialog.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/plugins/gevolution/new_person_dialog.c Fri May 02 22:51:14 2008 +0000 @@ -267,7 +267,7 @@ } else { - label = gtk_label_new(_("Please enter the buddy's screen name and " + label = gtk_label_new(_("Please enter the buddy's username and " "account type below.")); } @@ -291,7 +291,7 @@ /* Screen Name */ dialog->screenname = gtk_entry_new(); - add_pref_box(sg, vbox, _("Screen name:"), dialog->screenname); + add_pref_box(sg, vbox, _("Username:"), dialog->screenname); if (username != NULL) gtk_entry_set_text(GTK_ENTRY(dialog->screenname), username); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/plugins/notify.c --- a/pidgin/plugins/notify.c Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/plugins/notify.c Fri May 02 22:51:14 2008 +0000 @@ -112,7 +112,7 @@ /* notification set/unset */ static int notify(PurpleConversation *conv, gboolean increment); -static void notify_win(PidginWindow *purplewin); +static void notify_win(PidginWindow *purplewin, PurpleConversation *conv); static void unnotify(PurpleConversation *conv, gboolean reset); static int unnotify_cb(GtkWidget *widget, gpointer data, PurpleConversation *conv); @@ -141,6 +141,9 @@ /* raise function */ static void handle_raise(PidginWindow *purplewin); +/* present function */ +static void handle_present(PurpleConversation *conv); + /****************************************/ /* Begin doing stuff below this line... */ /****************************************/ @@ -193,14 +196,14 @@ purple_conversation_set_data(conv, "notify-message-count", GINT_TO_POINTER(count)); } - notify_win(purplewin); + notify_win(purplewin, conv); } return 0; } static void -notify_win(PidginWindow *purplewin) +notify_win(PidginWindow *purplewin, PurpleConversation *conv) { if (count_messages(purplewin) <= 0) return; @@ -215,6 +218,8 @@ handle_urgent(purplewin, TRUE); if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_raise")) handle_raise(purplewin); + if (purple_prefs_get_bool("/plugins/gtk/X11/notify/method_present")) + handle_present(conv); } static void @@ -564,6 +569,12 @@ } static void +handle_present(PurpleConversation *conv) +{ + purple_conversation_present(conv); +} + +static void type_toggle_cb(GtkWidget *widget, gpointer data) { gboolean on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); @@ -694,7 +705,7 @@ G_CALLBACK(type_toggle_cb), "type_chat"); ref = toggle; - toggle = gtk_check_button_new_with_mnemonic(_("\t_Only when someone says your screen name")); + toggle = gtk_check_button_new_with_mnemonic(_("\t_Only when someone says your username")); gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), purple_prefs_get_bool("/plugins/gtk/X11/notify/type_chat_nick")); @@ -771,6 +782,14 @@ g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(method_toggle_cb), "method_raise"); + /* Present conversation method button */ + toggle = gtk_check_button_new_with_mnemonic(_("_Present conversation window")); + gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), + purple_prefs_get_bool("/plugins/gtk/X11/notify/method_present")); + g_signal_connect(G_OBJECT(toggle), "toggled", + G_CALLBACK(method_toggle_cb), "method_present"); + /*---------- "Notification Removals" ----------*/ frame = pidgin_make_frame(ret, _("Notification Removal")); vbox = gtk_vbox_new(FALSE, 5); @@ -945,6 +964,7 @@ purple_prefs_add_bool("/plugins/gtk/X11/notify/method_count", FALSE); purple_prefs_add_bool("/plugins/gtk/X11/notify/method_count_xprop", FALSE); purple_prefs_add_bool("/plugins/gtk/X11/notify/method_raise", FALSE); + purple_prefs_add_bool("/plugins/gtk/X11/notify/method_present", FALSE); purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_focus", TRUE); purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_click", FALSE); purple_prefs_add_bool("/plugins/gtk/X11/notify/notify_type", TRUE); diff -r d5b3afea8764 -r 42dfa1139b5c pidgin/win32/nsis/pidgin-installer.nsi --- a/pidgin/win32/nsis/pidgin-installer.nsi Fri May 02 22:50:13 2008 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Fri May 02 22:51:14 2008 +0000 @@ -49,6 +49,7 @@ !include "WordFunc.nsh" !insertmacro VersionCompare !insertmacro WordFind +!insertmacro un.WordFind ;-------------------------------- ;Defines @@ -549,23 +550,18 @@ ;-------------------------------- ;URI Handling -SectionGroup /e $(URI_HANDLERS_SECTION_TITLE) SecURIHandlers - Section /o "aim:" SecURI_AIM - Push "aim" - Call RegisterURIHandler - SectionEnd - Section /o "msnim:" SecURI_MSNIM - Push "msnim" + +!macro URI_SECTION proto + Section /o "${proto}:" SecURI_${proto} + Push "${proto}" Call RegisterURIHandler SectionEnd - Section /o "myim:" SecURI_MYIM - Push "myim" - Call RegisterURIHandler - SectionEnd - Section /o "ymsgr:" SecURI_YMSGR - Push "ymsgr" - Call RegisterURIHandler - SectionEnd +!macroend +SectionGroup /e $(URI_HANDLERS_SECTION_TITLE) SecURIHandlers + !insertmacro URI_SECTION "aim" + !insertmacro URI_SECTION "msnim" + !insertmacro URI_SECTION "myim" + !insertmacro URI_SECTION "ymsgr" SectionGroupEnd ;-------------------------------- @@ -694,7 +690,19 @@ ; The WinPrefs plugin may have left this behind.. DeleteRegValue HKCU "${STARTUP_RUN_KEY}" "Pidgin" DeleteRegValue HKLM "${STARTUP_RUN_KEY}" "Pidgin" - ; Remove Language preference info (TODO: check if NSIS removes this) + ; Remove Language preference info + DeleteRegValue HKCU "${PIDGIN_REG_KEY}" "Installer Language" + + ; Remove any URI handlers + ; I can't think of an easy way to maintain a list in a single place + Push "aim" + Call un.UnregisterURIHandler + Push "msnim" + Call un.UnregisterURIHandler + Push "myim" + Call un.UnregisterURIHandler + Push "ymsgr" + Call un.UnregisterURIHandler Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem" Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem" @@ -903,12 +911,12 @@ ReadRegStr $R3 HKCR "$R2" "" IfErrors default_on ;there is no current handler - ; Check if Pidgin is the current handler - ClearErrors - ReadRegStr $R3 HKCR "$R2\shell\Open\command" "" - IfErrors end_loop - ${WordFind} "$R3" "pidgin.exe" "E+1{" $R3 - IfErrors end_loop default_on + Push $R2 + Call CheckIfPidginIsCurrentURIHandler + Pop $R3 + + ; If Pidgin isn't the current handler, we don't steal it automatically + IntCmp $R3 0 end_loop ;We default the URI handler checkbox on default_on: @@ -926,9 +934,58 @@ Pop $R0 FunctionEnd ;SelectURIHandlerSections +; Check if Pidgin is the current handler +; Returns a boolean on the stack +!macro CheckIfPidginIsCurrentURIHandlerMacro UN +Function ${UN}CheckIfPidginIsCurrentURIHandler + Exch $R0 + ClearErrors + + ReadRegStr $R0 HKCR "$R0\shell\Open\command" "" + IfErrors 0 +3 + IntOp $R0 0 + 0 + Goto done + + !ifdef __UNINSTALL__ + ${un.WordFind} "$R0" "pidgin.exe" "E+1{" $R0 + !else + ${WordFind} "$R0" "pidgin.exe" "E+1{" $R0 + !endif + IntOp $R0 0 + 1 + IfErrors 0 +2 + IntOp $R0 0 + 0 + + done: + Exch $R0 +FunctionEnd +!macroend +!insertmacro CheckIfPidginIsCurrentURIHandlerMacro "" +!insertmacro CheckIfPidginIsCurrentURIHandlerMacro "un." + +; If Pidgin is the current URI handler for the specified protocol, remove it. +Function un.UnregisterURIHandler + Exch $R0 + Push $R1 + + Push $R0 + Call un.CheckIfPidginIsCurrentURIHandler + Pop $R1 + + ; If Pidgin isn't the current handler, leave it as-is + IntCmp $R1 0 done + + ;Unregister the URI handler + DetailPrint "Unregistering $R0 URI Handler" + DeleteRegKey HKCR "$R0" + + done: + Pop $R1 + Pop $R0 +FunctionEnd Function RegisterURIHandler Exch $R0 + DetailPrint "Registering $R0 URI Handler" DeleteRegKey HKCR "$R0" WriteRegStr HKCR "$R0" "" "URL:$R0" WriteRegStr HKCR "$R0" "URL Protocol" "" @@ -1198,12 +1255,14 @@ StrCpy $SPELLCHECK_SEL "" ;Try to copy the old Gaim installer Lang Reg. key + ;(remove it after we're done to prevent this being done more than once) ClearErrors ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "Installer Language" IfErrors 0 +5 ClearErrors - ReadRegStr $R0 HKCU "SOFTWARE\gaim" "Installer Language" - IfErrors +2 + ReadRegStr $R0 HKCU "${OLD_GAIM_REG_KEY}" "Installer Language" + IfErrors +3 + DeleteRegValue HKCU "${OLD_GAIM_REG_KEY}" "Installer Language" WriteRegStr HKCU "${PIDGIN_REG_KEY}" "Installer Language" "$R0" !insertmacro SetSectionFlag ${SecSpellCheck} ${SF_RO} @@ -1321,6 +1380,7 @@ Function un.onInit Call un.RunCheck StrCpy $name "Pidgin ${PIDGIN_VERSION}" +;LogSet on ; Get stored language preference !insertmacro MUI_UNGETLANGUAGE