Mercurial > pidgin
changeset 21876:2ca7a3d28186
merge of '0bab002372d4ff0eac85fc22d99e014cd044b900'
and 'f60024a049490db3b4b14922c237f7bc7c140045'
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Tue, 18 Dec 2007 18:18:31 +0000 |
parents | 567b77c90a1b (current diff) 91684de72a5c (diff) |
children | c7c5e2ff2b04 |
files | |
diffstat | 35 files changed, 822 insertions(+), 304 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Sat Dec 15 22:58:57 2007 +0000 +++ b/ChangeLog Tue Dec 18 18:18:31 2007 +0000 @@ -8,6 +8,11 @@ Bonjour protocol. Avahi (or Apple's Bonjour runtime on win32) is now required to use Bonjour. + Pidgin: + * Added the ability to theme conversation name colors (red and blue) + through your GTK+ theme, and exposed those theme settings to the + Pidgin GTK+ Theme Control plugin (Dustin Howett) + Finch: * Color is used in the buddylist to indicate status, and the conversation window to indicate various message attributes. Look at the sample gntrc @@ -16,6 +21,27 @@ request dialog. M-d will properly delete-forward-word, and M-f has been fixed to imitate readline's behavior. +version 2.3.1 (12/7/2007): + http://developer.pidgin.im/query?status=closed&milestone=2.3.1 + NOTE: Due to the way this release was made, it is possible that + bugs marked as fixed in 2.3.1 will not be fixed until the + next release. + + * Fixed a number of MSN bugs introduced in 2.3.0, resolving problems + connecting to MSN and random local display name changes + * Going idle on MySpaceIM will no longer clear your status and message. + * Idle MySpaceIM buddies should now appear online at login. + * Fixed crashes in XMPP when discovering a client's capabilities + * Don't set the current tune title if it's NULL (XMPP/Google Talk) + * Don't allow buddies to be manually added to Bonjour + * Don't advertise IPv6 on Bonjour because we don't support it + * Compile fixes for FreeBSD and Solaris + * Update QQ client version so some accounts can connect again + * Do not allow ISON requests to stack in IRC, preventing flooding IRC + servers when temporary network outages are restored + * Plug several leaks in the perl plugin loader + * Prevent autoaccept plugin overwriting existing files + version 2.3.0 (11/24/2007): http://developer.pidgin.im/query?status=closed&milestone=2.3.0 NOTE: Some bugs marked fixed in 2.2.1, 2.2.2 or 2.2.3 may not
--- a/Makefile.am Sat Dec 15 22:58:57 2007 +0000 +++ b/Makefile.am Tue Dec 18 18:18:31 2007 +0000 @@ -30,10 +30,12 @@ distcheck-hook: libpurple/plugins/perl/common/Purple.pm pidgin/plugins/perl/common/Pidgin.pm # cp libpurple/plugins/perl/common/Gaim.pm $(distdir)/libpurple/plugins/perl/common +if ENABLE_GTK appsdir = $(datadir)/applications apps_in_files = pidgin.desktop.in apps_DATA = $(apps_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ +endif if ENABLE_GTK GTK_DIR=pidgin
--- a/NEWS Sat Dec 15 22:58:57 2007 +0000 +++ b/NEWS Tue Dec 18 18:18:31 2007 +0000 @@ -1,5 +1,19 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +2.3.1 (12/7/2007): + Stu: I'm sorry for the MSN problems and the plugin crashes in 2.3.0. + Hopefully this will redeem us. This fixes a number of bugs. I'm a + bit late but I'd like to welcome John to the team. Enjoy! + + Luke: I've done absolutely nothing in the last 2 weeks, except watch + others commit bug and, more, leak fixes. People should be noticing + remarkably fewer memory leaks now than 2 or more releases ago. + + Kevin: I'm not quite sure what happened to our MySpaceIM Summer of + Code student, but I fixed a few MySpace bugs with idle and status. + I will try to fix some of the other more significant bugs, after I + figure out the protocol, especially including grouping issues. + 2.3.0 (11/20/2007): Luke: While this does not have the new MSN code, rest assured that we are working on it and that it is nearing release. This contains
--- a/libpurple/account.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/account.c Tue Dec 18 18:18:31 2007 +0000 @@ -331,6 +331,12 @@ if(err == NULL) return node; + /* It doesn't make sense to have transient errors persist across a + * restart. + */ + if(!purple_connection_error_is_fatal (err->type)) + return node; + child = xmlnode_new_child(node, "type"); snprintf(type_str, sizeof(type_str), "%u", err->type); xmlnode_insert_data(child, type_str, -1);
--- a/libpurple/buddyicon.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/buddyicon.c Tue Dec 18 18:18:31 2007 +0000 @@ -98,8 +98,7 @@ { const char *dirname; char *path; - FILE *file = NULL; - + g_return_if_fail(img != NULL); if (!purple_buddy_icons_is_caching()) @@ -120,24 +119,12 @@ } } - if ((file = g_fopen(path, "wb")) != NULL) - { - if (!fwrite(purple_imgstore_get_data(img), purple_imgstore_get_size(img), 1, file)) - { - purple_debug_error("buddyicon", "Error writing %s: %s\n", - path, g_strerror(errno)); - } - else - purple_debug_info("buddyicon", "Wrote cache file: %s\n", path); - - fclose(file); - } - else - { + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { + purple_util_write_data_to_file_absolute(path, purple_imgstore_get_data(img), + purple_imgstore_get_size(img)); + } else { purple_debug_error("buddyicon", "Unable to create file %s: %s\n", path, g_strerror(errno)); - g_free(path); - return; } g_free(path); }
--- a/libpurple/dnsquery.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/dnsquery.c Tue Dec 18 18:18:31 2007 +0000 @@ -547,7 +547,7 @@ { #ifdef HAVE_GETADDRINFO g_snprintf(message, sizeof(message), _("Error resolving %s:\n%s"), - query_data->hostname, gai_strerror(err)); + query_data->hostname, purple_gai_strerror(err)); #else g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, err); @@ -695,7 +695,7 @@ } freeaddrinfo(tmp); } else { - query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, gai_strerror(rc)); + query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, purple_gai_strerror(rc)); } #else if ((hp = gethostbyname(query_data->hostname))) {
--- a/libpurple/ft.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/ft.c Tue Dec 18 18:18:31 2007 +0000 @@ -479,10 +479,11 @@ /* Sending a file */ /* Check the filename. */ #ifdef _WIN32 - if (g_strrstr(filename, "../") || g_strrstr(filename, "..\\")) { + if (g_strrstr(filename, "../") || g_strrstr(filename, "..\\")) #else - if (g_strrstr(filename, "../")) { + if (g_strrstr(filename, "../")) #endif + { char *utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); msg = g_strdup_printf(_("%s is not a valid filename.\n"), utf8);
--- a/libpurple/log.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/log.c Tue Dec 18 18:18:31 2007 +0000 @@ -348,7 +348,6 @@ void(*get_log_sets)(PurpleLogSetCallback cb, GHashTable *sets), gboolean(*remove)(PurpleLog *log), gboolean(*is_deletable)(PurpleLog *log)) -{ #endif PurpleLogLogger *logger; va_list args;
--- a/libpurple/network.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/network.c Tue Dec 18 18:18:31 2007 +0000 @@ -289,7 +289,7 @@ errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); if (errnum != 0) { #ifndef _WIN32 - purple_debug_warning("network", "getaddrinfo: %s\n", gai_strerror(errnum)); + purple_debug_warning("network", "getaddrinfo: %s\n", purple_gai_strerror(errnum)); if (errnum == EAI_SYSTEM) purple_debug_warning("network", "getaddrinfo: system error: %s\n", g_strerror(errno)); #else
--- a/libpurple/plugins/perl/common/Prpl.xs Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/plugins/perl/common/Prpl.xs Tue Dec 18 18:18:31 2007 +0000 @@ -54,3 +54,20 @@ Purple::Account account const char *name time_t login_time + +int +purple_prpl_send_raw(gc, str) + Purple::Connection gc + const char *str +PREINIT: + PurplePluginProtocolInfo *prpl_info; +CODE: + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + if (prpl_info && prpl_info->send_raw != NULL) { + RETVAL = prpl_info->send_raw(gc, str, strlen(str)); + } else { + RETVAL = 0; + } +OUTPUT: + RETVAL +
--- a/libpurple/protocols/jabber/auth.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/jabber/auth.c Tue Dec 18 18:18:31 2007 +0000 @@ -330,14 +330,21 @@ disallow_plaintext_auth); g_free(msg); return; - /* Everything else has failed, so fail the - * connection. Should probably have a better - * error here. - */ + } else { - purple_connection_error_reason (js->gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, - _("Server does not use any supported authentication method")); + /* We have no mechs which can work. + * Try falling back on the old jabber:iq:auth method. We get here if the server supports + * one or more sasl mechs, we are compiled with cyrus-sasl support, but we support or can connect with none of + * the offerred mechs. jabberd 2.0 w/ SASL and Apple's iChat Server 10.5 both handle and expect + * jabber:iq:auth in this situation. iChat Server in particular offers SASL GSSAPI by default, which is often + * not configured on the client side, and expects a fallback to jabber:iq:auth when it (predictably) fails. + * + * Note: xep-0078 points out that using jabber:iq:auth after a sasl failure is wrong. However, + * I believe this refers to actual authentication failure, not a simple lack of concordant mechanisms. + * Doing otherwise means that simply compiling with SASL support renders the client unable to connect to servers + * which would connect without issue otherwise. -evands + */ + jabber_auth_start_old(js); return; } /* not reached */ @@ -563,6 +570,75 @@ } } +/*! + * @brief Given the server challenge (message) and the key (password), calculate the HMAC-MD5 digest + * + * This is the crammd5 response. Inspired by cyrus-sasl's _sasl_hmac_md5() + */ +static void +auth_hmac_md5(const char *challenge, size_t challenge_len, const char *key, size_t key_len, guchar *digest) +{ + PurpleCipher *cipher; + PurpleCipherContext *context; + int i; + /* inner padding - key XORd with ipad */ + unsigned char k_ipad[65]; + /* outer padding - key XORd with opad */ + unsigned char k_opad[65]; + + cipher = purple_ciphers_find_cipher("md5"); + + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (strlen(key) > 64) { + guchar keydigest[16]; + + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, (const guchar *)key, strlen(key)); + purple_cipher_context_digest(context, 16, keydigest, NULL); + purple_cipher_context_destroy(context); + + key = (char *)keydigest; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset(k_ipad, '\0', sizeof k_ipad); + memset(k_opad, '\0', sizeof k_opad); + memcpy(k_ipad, (void *)key, key_len); + memcpy(k_opad, (void *)key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + /* perform inner MD5 */ + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, k_ipad, 64); /* start with inner pad */ + purple_cipher_context_append(context, (const guchar *)challenge, challenge_len); /* then text of datagram */ + purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 1st pass */ + purple_cipher_context_destroy(context); + + /* perform outer MD5 */ + context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, k_opad, 64); /* start with outer pad */ + purple_cipher_context_append(context, digest, 16); /* then results of 1st hash */ + purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 2nd pass */ + purple_cipher_context_destroy(context); +} + static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) { JabberIq *iq; @@ -608,6 +684,33 @@ jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq); + } else if(js->stream_id && xmlnode_get_child(query, "crammd5")) { + const char *challenge; + guchar digest[16]; + char h[17], *p; + int i; + + iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); + query = xmlnode_get_child(iq->node, "query"); + + x = xmlnode_new_child(query, "username"); + xmlnode_insert_data(x, js->user->node, -1); + x = xmlnode_new_child(query, "resource"); + xmlnode_insert_data(x, js->user->resource, -1); + + x = xmlnode_new_child(query, "crammd5"); + challenge = xmlnode_get_attrib(xmlnode_get_child(query, "crammd5"), "challenge"); + auth_hmac_md5(challenge, strlen(challenge), pw, strlen(pw), &digest); + + /* Translate the digest to a hexadecimal notation */ + p = h; + for(i=0; i<16; i++, p+=2) + snprintf(p, 3, "%02x", digest[i]); + xmlnode_insert_data(x, h, -1); + + jabber_iq_set_callback(iq, auth_old_result_cb, NULL); + jabber_iq_send(iq); + } else if(xmlnode_get_child(query, "password")) { if(js->gsc == NULL && !purple_account_get_bool(js->gc->account, "auth_plain_in_clear", FALSE)) {
--- a/libpurple/protocols/jabber/buddy.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/jabber/buddy.c Tue Dec 18 18:18:31 2007 +0000 @@ -1153,8 +1153,10 @@ void jabber_vcard_fetch_mine(JabberStream *js) { - JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "vcard-temp"); - + JabberIq *iq = jabber_iq_new(js, JABBER_IQ_GET); + + xmlnode *vcard = xmlnode_new_child(iq->node, "vCard"); + xmlnode_set_namespace(vcard, "vcard-temp"); jabber_iq_set_callback(iq, jabber_vcard_save_mine, NULL); jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/jabber.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/jabber/jabber.c Tue Dec 18 18:18:31 2007 +0000 @@ -388,9 +388,29 @@ g_free(txt); } +static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer timeout) +{ + g_source_remove(GPOINTER_TO_INT(timeout)); +} + +static gboolean jabber_pong_timeout(PurpleConnection *gc) +{ + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Ping timeout")); + return FALSE; +} + void jabber_keepalive(PurpleConnection *gc) { - jabber_send_raw(gc->proto_data, "\t", -1); + JabberIq *iq = jabber_iq_new(gc->proto_data, JABBER_IQ_GET); + guint timeout; + + xmlnode *ping = xmlnode_new_child(iq->node, "ping"); + xmlnode_set_namespace(ping, "urn:xmpp:ping"); + + timeout = purple_timeout_add_seconds(20, (GSourceFunc)(jabber_pong_timeout), gc); + jabber_iq_set_callback(iq, jabber_pong_cb, GINT_TO_POINTER(timeout)); + jabber_iq_send(iq); } static void
--- a/libpurple/protocols/jabber/libxmpp.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/jabber/libxmpp.c Tue Dec 18 18:18:31 2007 +0000 @@ -53,7 +53,7 @@ OPT_PROTO_SLASH_COMMANDS_NATIVE, NULL, /* user_splits */ NULL, /* protocol_options */ - {"png", 32, 32, 96, 96, 8191, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ + {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */ jabber_list_icon, /* list_icon */ jabber_list_emblem, /* list_emblems */ jabber_status_text, /* status_text */
--- a/libpurple/protocols/msn/contact.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/msn/contact.c Tue Dec 18 18:18:31 2007 +0000 @@ -1289,16 +1289,16 @@ purple_debug_info("MSNCL", "Adding group %s with guid = %s to the userlist\n", state->new_group_name, guid); msn_group_new(session->userlist, guid, state->new_group_name); - g_free(guid); - if (state->action & MSN_ADD_BUDDY) { msn_userlist_add_buddy(session->userlist, state->who, state->new_group_name); } else if (state->action & MSN_MOVE_BUDDY) { msn_add_contact_to_group(session->contact, state, state->who, guid); + g_free(guid); return; } + g_free(guid); } else { purple_debug_info("MSNCL", "Adding group %s failed\n", state->new_group_name);
--- a/libpurple/protocols/msn/soap.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/msn/soap.c Tue Dec 18 18:18:31 2007 +0000 @@ -813,10 +813,8 @@ purple_debug_info("MSN SOAP", "Currently processing another SOAP request\n"); } else { purple_debug_info("MSN SOAP", "No requests left to dispatch\n"); +#endif } -#else - } -#endif }
--- a/libpurple/protocols/yahoo/util.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/protocols/yahoo/util.c Tue Dec 18 18:18:31 2007 +0000 @@ -715,12 +715,15 @@ } else if (((len - i) >= 4) && !strncmp(&src[i], ">", 4)) { g_string_append_c(dest, '>'); i += 3; - } else if (((len - i) >= 5) && !strncmp(&src[i], "&", 4)) { + } else if (((len - i) >= 5) && !strncmp(&src[i], "&", 5)) { g_string_append_c(dest, '&'); i += 4; - } else if (((len - i) >= 6) && !strncmp(&src[i], """, 4)) { + } else if (((len - i) >= 6) && !strncmp(&src[i], """, 6)) { g_string_append_c(dest, '"'); i += 5; + } else if (((len - i) >= 6) && !strncmp(&src[i], "'", 6)) { + g_string_append_c(dest, '\''); + i += 5; } else { g_string_append_c(dest, src[i]); }
--- a/libpurple/request.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/request.c Tue Dec 18 18:18:31 2007 +0000 @@ -1208,6 +1208,8 @@ g_return_val_if_fail(ok_text != NULL, NULL); g_return_val_if_fail(ok_cb != NULL, NULL); + g_return_val_if_fail(cancel_text != NULL, NULL); + g_return_val_if_fail(cancel_cb != NULL, NULL); ops = purple_request_get_ui_ops(); @@ -1296,6 +1298,8 @@ g_return_val_if_fail(fields != NULL, NULL); g_return_val_if_fail(ok_text != NULL, NULL); g_return_val_if_fail(ok_cb != NULL, NULL); + g_return_val_if_fail(cancel_text != NULL, NULL); + g_return_val_if_fail(cancel_cb != NULL, NULL); ops = purple_request_get_ui_ops();
--- a/libpurple/request.h Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/request.h Tue Dec 18 18:18:31 2007 +0000 @@ -183,39 +183,53 @@ */ typedef struct { + /** @see purple_request_input(). */ void *(*request_input)(const char *title, const char *primary, - const char *secondary, const char *default_value, - gboolean multiline, gboolean masked, gchar *hint, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *secondary, const char *default_value, + gboolean multiline, gboolean masked, gchar *hint, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data); + + /** @see purple_request_choice_varg(). */ void *(*request_choice)(const char *title, const char *primary, - const char *secondary, int default_value, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, va_list choices); + const char *secondary, int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data, + va_list choices); + + /** @see purple_request_action_varg(). */ void *(*request_action)(const char *title, const char *primary, - const char *secondary, int default_action, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, - va_list actions); + const char *secondary, int default_action, + PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data, + size_t action_count, va_list actions); + + /** @see purple_request_fields(). */ void *(*request_fields)(const char *title, const char *primary, - const char *secondary, PurpleRequestFields *fields, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + const char *secondary, PurpleRequestFields *fields, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data); + + /** @see purple_request_file(). */ void *(*request_file)(const char *title, const char *filename, - gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + gboolean savedialog, GCallback ok_cb, + GCallback cancel_cb, PurpleAccount *account, + const char *who, PurpleConversation *conv, + void *user_data); + void (*close_request)(PurpleRequestType type, void *ui_handle); + + /** @see purple_request_folder(). */ void *(*request_folder)(const char *title, const char *dirname, - GCallback ok_cb, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, + PurpleConversation *conv, void *user_data); void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); @@ -1159,198 +1173,247 @@ * Prompts the user for text input. * * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. The - * handle is used to programmatically close - * the request dialog when it is no longer - * needed. For PRPLs this is often a pointer - * to the PurpleConnection instance. For plugins - * this should be a similar, unique memory - * location. This value is important because - * it allows a request to be closed, say, when - * you sign offline. If the request is NOT - * closed it is VERY likely to cause a crash - * whenever the callback handler functions are - * triggered. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. + * things this is <em>extremely</em> important. The + * handle is used to programmatically close the request + * dialog when it is no longer needed. For PRPLs this + * is often a pointer to the #PurpleConnection + * instance. For plugins this should be a similar, + * unique memory location. This value is important + * because it allows a request to be closed with + * purple_request_close_with_handle() when, for + * example, you sign offline. If the request is + * <em>not</em> closed it is <strong>very</strong> + * likely to cause a crash whenever the callback + * handler functions are triggered. + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. * @param default_value The default value. - * @param multiline TRUE if the inputted text can span multiple lines. - * @param masked TRUE if the inputted text should be masked in some way. + * @param multiline @c TRUE if the inputted text can span multiple lines. + * @param masked @c TRUE if the inputted text should be masked in some + * way (such as by displaying characters as stars). This + * might be because the input is some kind of password. * @param hint Optionally suggest how the input box should appear. - * Use "html," for example, to allow the user to enter + * Use "html", for example, to allow the user to enter * HTML. - * @param ok_text The text for the @c OK button. - * @param ok_cb The callback for the @c OK button. - * @param cancel_text The text for the @c Cancel button. - * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ok_text The text for the @c OK button, which may not be @c NULL. + * @param ok_cb The callback for the @c OK button, which may not be @c + * NULL. + * @param cancel_text The text for the @c Cancel button, which may not be @c + * NULL. + * @param cancel_cb The callback for the @c Cancel button, which may not be + * @c NULL. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is. + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is. + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is. * @param user_data The data to pass to the callback. * * @return A UI-specific handle. */ -void *purple_request_input(void *handle, const char *title, - const char *primary, const char *secondary, - const char *default_value, - gboolean multiline, gboolean masked, gchar *hint, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); +void *purple_request_input(void *handle, const char *title, const char *primary, + const char *secondary, const char *default_value, gboolean multiline, + gboolean masked, gchar *hint, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data); /** * Prompts the user for multiple-choice input. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. - * @param default_value The default value. - * @param ok_text The text for the @c OK button. - * @param ok_cb The callback for the @c OK button. - * @param cancel_text The text for the @c Cancel button. - * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. + * @param default_value The default choice; this should be one of the values + * listed in the varargs. + * @param ok_text The text for the @c OK button, which may not be @c NULL. + * @param ok_cb The callback for the @c OK button, which may not be @c + * NULL. + * @param cancel_text The text for the @c Cancel button, which may not be @c + * NULL. + * @param cancel_cb The callback for the @c Cancel button, which may not be + * @c NULL. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is. + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is. + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is. * @param user_data The data to pass to the callback. - * @param ... The choices. This argument list should be - * terminated with a NULL parameter. + * @param ... The choices, which should be pairs of <tt>char *</tt> + * descriptions and <tt>int</tt> values, terminated with a + * @c NULL parameter. * * @return A UI-specific handle. */ -void *purple_request_choice(void *handle, const char *title, - const char *primary, const char *secondary, - int default_value, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, ...) G_GNUC_NULL_TERMINATED; +void *purple_request_choice(void *handle, const char *title, const char *primary, + const char *secondary, int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data, ...) G_GNUC_NULL_TERMINATED; /** * Prompts the user for multiple-choice input. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. - * @param default_value The default value. - * @param ok_text The text for the @c OK button. - * @param ok_cb The callback for the @c OK button. - * @param cancel_text The text for the @c Cancel button. - * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. + * @param default_value The default choice; this should be one of the values + * listed in the varargs. + * @param ok_text The text for the @c OK button, which may not be @c NULL. + * @param ok_cb The callback for the @c OK button, which may not be @c + * NULL. + * @param cancel_text The text for the @c Cancel button, which may not be @c + * NULL. + * @param cancel_cb The callback for the @c Cancel button, which may not be + * @c NULL. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is * @param user_data The data to pass to the callback. - * @param choices The choices. This argument list should be - * terminated with a @c NULL parameter. + * @param choices The choices, which should be pairs of <tt>char *</tt> + * descriptions and <tt>int</tt> values, terminated with a + * @c NULL parameter. * * @return A UI-specific handle. */ void *purple_request_choice_varg(void *handle, const char *title, - const char *primary, const char *secondary, - int default_value, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, va_list choices); + const char *primary, const char *secondary, int default_value, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data, va_list choices); /** * Prompts the user for an action. * * This is often represented as a dialog with a button for each action. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. - * @param default_action The default value. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. + * @param default_action The default action, zero-indexed; if the third action + * supplied should be the default, supply <tt>2</tt>. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is. + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is. + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is. * @param user_data The data to pass to the callback. * @param action_count The number of actions. * @param ... A list of actions. These are pairs of * arguments. The first of each pair is the - * string that appears on the button. It should + * <tt>char *</tt> that appears on the button. It should * have an underscore before the letter you want * to use as the accelerator key for the button. - * The second of each pair is the callback + * The second of each pair is the <tt>GCallback</tt> * function to use when the button is clicked. * * @return A UI-specific handle. */ -void *purple_request_action(void *handle, const char *title, - const char *primary, const char *secondary, - int default_action, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, ...); +void *purple_request_action(void *handle, const char *title, const char *primary, + const char *secondary, int default_action, PurpleAccount *account, + const char *who, PurpleConversation *conv, void *user_data, + size_t action_count, ...); /** * Prompts the user for an action. * * This is often represented as a dialog with a button for each action. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. - * @param default_action The default value. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. + * @param default_action The default action, zero-indexed; if the third action + * supplied should be the default, supply <tt>2</tt>. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is. + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is. + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is. * @param user_data The data to pass to the callback. * @param action_count The number of actions. - * @param actions A list of actions and callbacks. + * @param actions A list of actions. These are pairs of + * arguments. The first of each pair is the + * <tt>char *</tt> that appears on the button. It should + * have an underscore before the letter you want + * to use as the accelerator key for the button. + * The second of each pair is the <tt>GCallback</tt> + * function to use when the button is clicked. * * @return A UI-specific handle. */ void *purple_request_action_varg(void *handle, const char *title, - const char *primary, const char *secondary, - int default_action, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data, size_t action_count, - va_list actions); + const char *primary, const char *secondary, int default_action, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data, size_t action_count, va_list actions); /** * Displays groups of fields for the user to fill in. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title of the message. - * @param primary The main point of the message. - * @param secondary The secondary information. + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. + * @param primary The main point of the message, or @c NULL if you're + * feeling enigmatic. + * @param secondary Secondary information, or @c NULL if there is none. * @param fields The list of fields. - * @param ok_text The text for the @c OK button. - * @param ok_cb The callback for the @c OK button. - * @param cancel_text The text for the @c Cancel button. - * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy associated with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param ok_text The text for the @c OK button, which may not be @c NULL. + * @param ok_cb The callback for the @c OK button, which may not be @c + * NULL. + * @param cancel_text The text for the @c Cancel button, which may not be @c + * NULL. + * @param cancel_cb The callback for the @c Cancel button, which may not be + * @c NULL. + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. */ -void *purple_request_fields(void *handle, const char *title, - const char *primary, const char *secondary, - PurpleRequestFields *fields, - const char *ok_text, GCallback ok_cb, - const char *cancel_text, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); +void *purple_request_fields(void *handle, const char *title, const char *primary, + const char *secondary, PurpleRequestFields *fields, + const char *ok_text, GCallback ok_cb, + const char *cancel_text, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data); /** * Closes a request. @@ -1363,7 +1426,10 @@ /** * Closes all requests registered with the specified handle. * - * @param handle The handle. + * @param handle The handle, as supplied as the @a handle parameter to one of the + * <tt>purple_request_*</tt> functions. + * + * @see purple_request_input(). */ void purple_request_close_with_handle(void *handle); @@ -1401,50 +1467,57 @@ * Displays a file selector request dialog. Returns the selected filename to * the callback. Can be used for either opening a file or saving a file. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title for the dialog (may be @c NULL) + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. * @param filename The default filename (may be @c NULL) * @param savedialog True if this dialog is being used to save a file. * False if it is being used to open a file. * @param ok_cb The callback for the @c OK button. * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. */ void *purple_request_file(void *handle, const char *title, const char *filename, - gboolean savedialog, - GCallback ok_cb, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + gboolean savedialog, GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data); /** * Displays a folder select dialog. Returns the selected filename to * the callback. * - * @param handle The plugin or connection handle. For some - * things this is EXTREMELY important. See - * the comments on purple_request_input. - * @param title The title for the dialog (may be @c NULL) + * @param handle The plugin or connection handle. For some things this + * is <em>extremely</em> important. See the comments on + * purple_request_input(). + * @param title The title of the message, or @c NULL if it should have + * no title. * @param dirname The default directory name (may be @c NULL) * @param ok_cb The callback for the @c OK button. * @param cancel_cb The callback for the @c Cancel button. - * @param account The PurpleAccount associated with this request, or NULL if none is - * @param who The username of the buddy assocaited with this request, or NULL if none is - * @param conv The PurpleConversation associated with this request, or NULL if none is + * @param account The #PurpleAccount associated with this request, or @c + * NULL if none is + * @param who The username of the buddy assonciated with this request, + * or @c NULL if none is + * @param conv The #PurpleConversation associated with this request, or + * @c NULL if none is * @param user_data The data to pass to the callback. * * @return A UI-specific handle. */ void *purple_request_folder(void *handle, const char *title, const char *dirname, - GCallback ok_cb, GCallback cancel_cb, - PurpleAccount *account, const char *who, PurpleConversation *conv, - void *user_data); + GCallback ok_cb, GCallback cancel_cb, + PurpleAccount *account, const char *who, PurpleConversation *conv, + void *user_data); /*@}*/
--- a/libpurple/status.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/status.c Tue Dec 18 18:18:31 2007 +0000 @@ -607,13 +607,10 @@ if (old_status != NULL) { - tmp = g_strdup_printf(_("%s changed status from %s to %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name, purple_status_get_name(old_status), purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) changed status from %s to %s"), buddy_alias, buddy->name, - purple_status_get_name(old_status), - purple_status_get_name(new_status)); - + logtmp = g_markup_escape_text(tmp, -1); } else { @@ -621,18 +618,15 @@ if (purple_status_is_active(new_status)) { - tmp = g_strdup_printf(_("%s is now %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name, purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) is now %s"), buddy_alias, buddy->name, - purple_status_get_name(new_status)); - + logtmp = g_markup_escape_text(tmp, -1); } else { - tmp = g_strdup_printf(_("%s is no longer %s"), buddy_alias, + tmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name, purple_status_get_name(new_status)); - logtmp = g_strdup_printf(_("%s (%s) is no longer %s"), buddy_alias, buddy->name, - purple_status_get_name(new_status)); + logtmp = g_markup_escape_text(tmp, -1); } } @@ -1244,12 +1238,15 @@ if (log != NULL) { - char *tmp = g_strdup_printf(_("%s became idle"), + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became idle"), purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp); - g_free(tmp); + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); } } } @@ -1261,12 +1258,15 @@ if (log != NULL) { - char *tmp = g_strdup_printf(_("%s became unidle"), + char *tmp, *tmp2; + tmp = g_strdup_printf(_("%s became unidle"), purple_buddy_get_alias(buddy)); + tmp2 = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, - purple_buddy_get_alias(buddy), current_time, tmp); - g_free(tmp); + purple_buddy_get_alias(buddy), current_time, tmp2); + g_free(tmp2); } } } @@ -1321,13 +1321,15 @@ if (log != NULL) { - char *msg; + char *msg, *tmp; if (idle) - msg = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); + tmp = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account)); else - msg = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); + tmp = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account)); + msg = g_markup_escape_text(tmp, -1); + g_free(tmp); purple_log_write(log, PURPLE_MESSAGE_SYSTEM, purple_account_get_username(account), (idle ? idle_time : current_time), msg);
--- a/libpurple/util.c Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/util.c Tue Dec 18 18:18:31 2007 +0000 @@ -4257,6 +4257,53 @@ return g_string_free(workstr, FALSE); } +/* + * This function is copied from g_strerror() but changed to use + * gai_strerror(). + */ +G_CONST_RETURN gchar * +purple_gai_strerror(gint errnum) +{ + static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT; + char *msg; + int saved_errno = errno; + + const char *msg_locale; + + msg_locale = gai_strerror(errnum); + if (g_get_charset(NULL)) + { + /* This string is already UTF-8--great! */ + errno = saved_errno; + return msg_locale; + } + else + { + gchar *msg_utf8 = g_locale_to_utf8(msg_locale, -1, NULL, NULL, NULL); + if (msg_utf8) + { + /* Stick in the quark table so that we can return a static result */ + GQuark msg_quark = g_quark_from_string(msg_utf8); + g_free(msg_utf8); + + msg_utf8 = (gchar *)g_quark_to_string(msg_quark); + errno = saved_errno; + return msg_utf8; + } + } + + msg = g_static_private_get(&msg_private); + if (!msg) + { + msg = g_new(gchar, 64); + g_static_private_set(&msg_private, msg, g_free); + } + + sprintf(msg, "unknown error (%d)", errnum); + + errno = saved_errno; + return msg; +} char * purple_utf8_ncr_encode(const char *str)
--- a/libpurple/util.h Sat Dec 15 22:58:57 2007 +0000 +++ b/libpurple/util.h Tue Dec 18 18:18:31 2007 +0000 @@ -1110,6 +1110,17 @@ gchar *purple_utf8_salvage(const char *str); /** + * Return the UTF-8 version of gai_strerror(). It calls gai_strerror() + * then converts the result to UTF-8. This function is analogous to + * g_strerror(). + * + * @param errnum The error code. + * + * @return The UTF-8 error message. + */ +G_CONST_RETURN gchar *purple_gai_strerror(gint errnum); + +/** * Compares two UTF-8 strings case-insensitively. This string is * more expensive than a simple g_utf8_collate() comparison because * it calls g_utf8_casefold() on each string, which allocates new
--- a/pidgin/gtkblist.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkblist.c Tue Dec 18 18:18:31 2007 +0000 @@ -4643,6 +4643,13 @@ } static void +clear_elsewhere_errors(PidginMiniDialog *mini_dialog, + gpointer unused) +{ + elsewhere_foreach_account(mini_dialog, purple_account_clear_current_error); +} + +static void ensure_signed_on_elsewhere_minidialog(PidginBuddyList *gtkblist) { PidginBuddyListPrivate *priv = PIDGIN_BUDDY_LIST_GET_PRIVATE(gtkblist); @@ -4657,6 +4664,12 @@ pidgin_mini_dialog_add_button(mini_dialog, _("Re-enable"), reconnect_elsewhere_accounts, NULL); + /* Make dismissing the dialog clear the errors. The "destroy" signal + * does not appear to fire at quit, which is fortunate! + */ + g_signal_connect(G_OBJECT(mini_dialog), "destroy", + (GCallback) clear_elsewhere_errors, NULL); + add_error_dialog(gtkblist, GTK_WIDGET(mini_dialog)); /* Set priv->signed_on_elsewhere to NULL when the dialog is destroyed */
--- a/pidgin/gtkconv.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkconv.c Tue Dec 18 18:18:31 2007 +0000 @@ -95,9 +95,10 @@ #define PIDGIN_CONV_ALL ((1 << 7) - 1) -#define SEND_COLOR "#204a87" -#define RECV_COLOR "#cc0000" -#define HIGHLIGHT_COLOR "#AF7F00" +#define DEFAULT_SEND_COLOR "#204a87" +#define DEFAULT_RECV_COLOR "#cc0000" +#define DEFAULT_HIGHLIGHT_COLOR "#AF7F00" +#define DEFAULT_ACTION_COLOR "#062585" /* Undef this to turn off "custom-smiley" debug messages */ #define DEBUG_CUSTOM_SMILEY @@ -3790,7 +3791,7 @@ if (is_me) { GdkColor send_color; - gdk_color_parse(SEND_COLOR, &send_color); + gdk_color_parse(DEFAULT_SEND_COLOR, &send_color); #if GTK_CHECK_VERSION(2,6,0) gtk_list_store_insert_with_values(ls, &iter, @@ -4341,8 +4342,8 @@ lines = gtk_text_buffer_get_line_count(buffer); - /* Show a maximum of 4 lines, minimum of 2 */ - lines = MIN(MAX(lines, 2), 4); + /* Show a maximum of 4 lines */ + lines = MIN(lines, 4); wrapped_lines = MIN(MAX(wrapped_lines, 2), 4); pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); @@ -5602,6 +5603,7 @@ } else { if (purple_message_meify(new_message, -1)) { + GdkColor *col; str = g_malloc(1024); if (flags & PURPLE_MESSAGE_AUTO_RESP) { @@ -5614,9 +5616,20 @@ } if (flags & PURPLE_MESSAGE_NICK) - strcpy(color, HIGHLIGHT_COLOR); + gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "highlight-name-color", &col, NULL); else - strcpy(color, "#062585"); + gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "action-name-color", &col, NULL); + + if(col) { + g_snprintf(color, sizeof(color), "#%02X%02X%02X", + col->red >> 8, col->green >> 8, col->blue >> 8); + } + else { + if (flags & PURPLE_MESSAGE_NICK) + strcpy(color, DEFAULT_HIGHLIGHT_COLOR); + else + strcpy(color, DEFAULT_ACTION_COLOR); + } } else { str = g_malloc(1024); @@ -5628,19 +5641,46 @@ g_snprintf(str, 1024, "%s:", alias_escaped); tag_end_offset = 1; } - if (flags & PURPLE_MESSAGE_NICK) - strcpy(color, HIGHLIGHT_COLOR); + if (flags & PURPLE_MESSAGE_NICK) { + GdkColor *col; + gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "highlight-name-color", &col, NULL); + if(col) { + g_snprintf(color, sizeof(color), "#%02X%02X%02X", + col->red >> 8, col->green >> 8, col->blue >> 8); + } + else { + strcpy(color, DEFAULT_HIGHLIGHT_COLOR); + } + } else if (flags & PURPLE_MESSAGE_RECV) { if (type == PURPLE_CONV_TYPE_CHAT) { GdkColor *col = get_nick_color(gtkconv, name); g_snprintf(color, sizeof(color), "#%02X%02X%02X", col->red >> 8, col->green >> 8, col->blue >> 8); - } else - strcpy(color, RECV_COLOR); + } else { + GdkColor *col; + gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "receive-name-color", &col, NULL); + if(col) { + g_snprintf(color, sizeof(color), "#%02X%02X%02X", + col->red >> 8, col->green >> 8, col->blue >> 8); + } + else { + strcpy(color, DEFAULT_RECV_COLOR); + } + } } - else if (flags & PURPLE_MESSAGE_SEND) - strcpy(color, SEND_COLOR); + else if (flags & PURPLE_MESSAGE_SEND) { + GdkColor *col; + gtk_widget_style_get(GTK_WIDGET(gtkconv->imhtml), "send-name-color", &col, NULL); + if(col) { + g_snprintf(color, sizeof(color), "#%02X%02X%02X", + col->red >> 8, col->green >> 8, col->blue >> 8); + } + else { + strcpy(color, DEFAULT_SEND_COLOR); + } + } else { purple_debug_error("gtkconv", "message missing flags\n"); strcpy(color, "#000000"); @@ -9923,8 +9963,8 @@ GdkColor send_color; time_t breakout_time; - gdk_color_parse(HIGHLIGHT_COLOR, &nick_highlight); - gdk_color_parse(SEND_COLOR, &send_color); + gdk_color_parse(DEFAULT_HIGHLIGHT_COLOR, &nick_highlight); + gdk_color_parse(DEFAULT_SEND_COLOR, &send_color); srand(background.red + background.green + background.blue + 1);
--- a/pidgin/gtkimhtml.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkimhtml.c Tue Dec 18 18:18:31 2007 +0000 @@ -1136,14 +1136,13 @@ #ifdef _WIN32 /* If we're on windows, let's see if we can get data from the HTML Format clipboard before we try to paste from the GTK buffer */ - if (!clipboard_paste_html_win32(imhtml)) { + if (!clipboard_paste_html_win32(imhtml)) #endif + { GtkClipboard *clipboard = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD); gtk_clipboard_request_contents(clipboard, gdk_atom_intern("text/html", FALSE), paste_received_cb, imhtml); -#ifdef _WIN32 } -#endif g_signal_stop_emission_by_name(imhtml, "paste-clipboard"); } @@ -1397,6 +1396,22 @@ _("Hyperlink prelight color"), _("Color to draw hyperlinks when mouse is over them."), GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("send-name-color", + _("Sent Message Name Color"), + _("Color to draw the name of a message you sent."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("receive-name-color", + _("Received Message Name Color"), + _("Color to draw the name of a message you received."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("highlight-name-color", + _("\"Attention\" Name Color"), + _("Color to draw the name of a message you received containing your name."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("action-name-color", + _("Action Message Name Color"), + _("Color to draw the name of an action message."), + GDK_TYPE_COLOR, G_PARAM_READABLE)); binding_set = gtk_binding_set_by_class (parent_class); gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "format_function_toggle", 1, G_TYPE_INT, GTK_IMHTML_BOLD); @@ -3467,6 +3482,9 @@ return; } #endif /* FILECHOOSER */ +#if 0 /* mismatched curly braces */ + } +#endif /* * XXX - We should probably prompt the user to determine if they really
--- a/pidgin/gtkimhtmltoolbar.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Tue Dec 18 18:18:31 2007 +0000 @@ -467,10 +467,11 @@ GtkTextMark *ins; #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */ - if (response != GTK_RESPONSE_ACCEPT) { + if (response != GTK_RESPONSE_ACCEPT) #else /* FILECHOOSER */ - if (response != GTK_RESPONSE_OK) { + if (response != GTK_RESPONSE_OK) #endif /* FILECHOOSER */ + { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image), FALSE); return; } @@ -1096,8 +1097,8 @@ {PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, do_small, &toolbar->smaller_size, _("Decrease Font Size")}, {"", NULL, NULL, NULL}, {PIDGIN_STOCK_TOOLBAR_FONT_FACE, toggle_font, &toolbar->font, _("Font Face")}, - {PIDGIN_STOCK_TOOLBAR_FGCOLOR, toggle_bg_color, &toolbar->bgcolor, _("Background Color")}, - {PIDGIN_STOCK_TOOLBAR_BGCOLOR, toggle_fg_color, &toolbar->fgcolor, _("Foreground Color")}, + {PIDGIN_STOCK_TOOLBAR_BGCOLOR, toggle_bg_color, &toolbar->bgcolor, _("Background Color")}, + {PIDGIN_STOCK_TOOLBAR_FGCOLOR, toggle_fg_color, &toolbar->fgcolor, _("Foreground Color")}, {"", NULL, NULL, NULL}, {PIDGIN_STOCK_CLEAR, clear_formatting_cb, &toolbar->clear, _("Reset Formatting")}, {"", NULL, NULL, NULL},
--- a/pidgin/gtkmain.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkmain.c Tue Dec 18 18:18:31 2007 +0000 @@ -397,6 +397,7 @@ if (terse) { text = g_strdup_printf(_("%s %s. Try `%s -h' for more information.\n"), PIDGIN_NAME, DISPLAY_VERSION, name); } else { +#ifndef WIN32 text = g_strdup_printf(_("%s %s\n" "Usage: %s [OPTION]...\n\n" " -c, --config=DIR use DIR for config files\n" @@ -406,10 +407,20 @@ " -n, --nologin don't automatically login\n" " -l, --login[=NAME] automatically login (optional argument NAME specifies\n" " account(s) to use, separated by commas)\n" -#ifndef WIN32 " --display=DISPLAY X display to use\n" + " -v, --version display the current version and exit\n"), PIDGIN_NAME, DISPLAY_VERSION, name); +#else + text = g_strdup_printf(_("%s %s\n" + "Usage: %s [OPTION]...\n\n" + " -c, --config=DIR use DIR for config files\n" + " -d, --debug print debugging messages to stdout\n" + " -h, --help display this help and exit\n" + " -m, --multiple do not ensure single instance\n" + " -n, --nologin don't automatically login\n" + " -l, --login[=NAME] automatically login (optional argument NAME specifies\n" + " account(s) to use, separated by commas)\n" + " -v, --version display the current version and exit\n"), PIDGIN_NAME, DISPLAY_VERSION, name); #endif - " -v, --version display the current version and exit\n"), PIDGIN_NAME, DISPLAY_VERSION, name); } purple_print_utf8_to_console(stdout, text);
--- a/pidgin/gtkrequest.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkrequest.c Tue Dec 18 18:18:31 2007 +0000 @@ -1502,7 +1502,9 @@ } #endif /* FILECHOOSER */ - +#if 0 /* mismatched curly braces */ + } +#endif if ((data->u.file.savedialog == TRUE) && (g_file_test(data->u.file.name, G_FILE_TEST_EXISTS))) { purple_request_action(data, NULL, _("That file already exists"),
--- a/pidgin/gtkutils.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/gtkutils.c Tue Dec 18 18:18:31 2007 +0000 @@ -1399,7 +1399,7 @@ char *str; str = g_strdup_printf(_("The following error has occurred loading %s: %s"), - data->filename, strerror(errno)); + data->filename, g_strerror(errno)); purple_notify_error(NULL, NULL, _("Failed to load image"), str); @@ -2306,6 +2306,9 @@ } #endif /* FILECHOOSER */ +#if 0 /* mismatched curly braces */ + } +#endif if (dialog->callback) dialog->callback(filename, dialog->data); gtk_widget_destroy(dialog->icon_filesel);
--- a/pidgin/minidialog.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/minidialog.c Tue Dec 18 18:18:31 2007 +0000 @@ -35,7 +35,40 @@ #include "pidgin/pidgin.h" #include "pidgin/pidginstock.h" -G_DEFINE_TYPE (PidginMiniDialog, pidgin_mini_dialog, GTK_TYPE_VBOX) +static void pidgin_mini_dialog_init (PidginMiniDialog *self); +static void pidgin_mini_dialog_class_init (PidginMiniDialogClass *klass); + +static gpointer pidgin_mini_dialog_parent_class = NULL; + +static void +pidgin_mini_dialog_class_intern_init (gpointer klass) +{ + pidgin_mini_dialog_parent_class = g_type_class_peek_parent (klass); + pidgin_mini_dialog_class_init ((PidginMiniDialogClass*) klass); +} + +GType +pidgin_mini_dialog_get_type (void) +{ + static GType g_define_type_id = 0; + if (G_UNLIKELY (g_define_type_id == 0)) + { + static const GTypeInfo g_define_type_info = { + sizeof (PidginMiniDialogClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pidgin_mini_dialog_class_intern_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (PidginMiniDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) pidgin_mini_dialog_init, + }; + g_define_type_id = g_type_register_static (GTK_TYPE_VBOX, + "PidginMiniDialog", &g_define_type_info, 0); + } + return g_define_type_id; +} enum {
--- a/pidgin/plugins/crazychat/cc_network.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/plugins/crazychat/cc_network.c Tue Dec 18 18:18:31 2007 +0000 @@ -529,7 +529,7 @@ while (total < len) { n = send(s, buf + total, bytesleft, 0); if (n == -1) { - Debug("ERROR: %s\n", strerror(errno)); + Debug("ERROR: %s\n", g_strerror(errno)); return -1; } total += n;
--- a/pidgin/plugins/pidginrc.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/plugins/pidginrc.c Tue Dec 18 18:18:31 2007 +0000 @@ -30,17 +30,29 @@ static const gchar *color_prefs[] = { "/plugins/gtk/purplerc/color/GtkWidget::cursor-color", "/plugins/gtk/purplerc/color/GtkWidget::secondary-cursor-color", - "/plugins/gtk/purplerc/color/GtkIMHtml::hyperlink-color" + "/plugins/gtk/purplerc/color/GtkIMHtml::hyperlink-color", + "/plugins/gtk/purplerc/color/GtkIMHtml::send-name-color", + "/plugins/gtk/purplerc/color/GtkIMHtml::receive-name-color", + "/plugins/gtk/purplerc/color/GtkIMHtml::highlight-name-color", + "/plugins/gtk/purplerc/color/GtkIMHtml::action-name-color" }; static const gchar *color_prefs_set[] = { "/plugins/gtk/purplerc/set/color/GtkWidget::cursor-color", "/plugins/gtk/purplerc/set/color/GtkWidget::secondary-cursor-color", - "/plugins/gtk/purplerc/set/color/GtkIMHtml::hyperlink-color" + "/plugins/gtk/purplerc/set/color/GtkIMHtml::hyperlink-color", + "/plugins/gtk/purplerc/set/color/GtkIMHtml::send-name-color", + "/plugins/gtk/purplerc/set/color/GtkIMHtml::receive-name-color", + "/plugins/gtk/purplerc/set/color/GtkIMHtml::highlight-name-color", + "/plugins/gtk/purplerc/set/color/GtkIMHtml::action-name-color" }; static const gchar *color_names[] = { N_("Cursor Color"), N_("Secondary Cursor Color"), - N_("Hyperlink Color") + N_("Hyperlink Color"), + N_("Sent Message Name Color"), + N_("Received Message Name Color"), + N_("Highlighted Message Name Color"), + N_("Action Message Name Color") }; static GtkWidget *color_widgets[G_N_ELEMENTS(color_prefs)];
--- a/pidgin/win32/nsis/pidgin-installer.nsi Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Tue Dec 18 18:18:31 2007 +0000 @@ -1154,11 +1154,21 @@ !macro RunCheckMacro UN Function ${UN}RunCheck Push $R0 - System::Call 'kernel32::OpenMutex(i 2031617, b 0, t "pidgin_is_running") i .R0' - IntCmp $R0 0 done - MessageBox MB_OK|MB_ICONEXCLAMATION $(PIDGIN_IS_RUNNING) /SD IDOK + Push $R1 + + IntOp $R1 0 + 0 + retry_runcheck: + ; Close the Handle (needed if we're retrying) + IntCmp $R1 0 +2 + System::Call 'kernel32::CloseHandle(i $R1) i .R1' + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_is_running") i .R1 ?e' + Pop $R0 + IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume + MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(PIDGIN_IS_RUNNING) /SD IDCANCEL IDRETRY retry_runcheck Abort + done: + Pop $R1 Pop $R0 FunctionEnd !macroend @@ -1169,10 +1179,16 @@ Push $R0 Push $R1 Push $R2 - System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .r1 ?e' + + IntOp $R1 0 + 0 + retry_runcheck: + ; Close the Handle (needed if we're retrying) + IntCmp $R1 0 +2 + System::Call 'kernel32::CloseHandle(i $R1) i .R1' + System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .R1 ?e' Pop $R0 - StrCmp $R0 0 +3 - MessageBox MB_OK|MB_ICONEXCLAMATION $(INSTALLER_IS_RUNNING) /SD IDOK + IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume + MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(INSTALLER_IS_RUNNING) /SD IDCANCEL IDRETRY retry_runcheck Abort Call RunCheck StrCpy $name "Pidgin ${PIDGIN_VERSION}"
--- a/pidgin/win32/winpidgin.c Sat Dec 15 22:58:57 2007 +0000 +++ b/pidgin/win32/winpidgin.c Tue Dec 18 18:18:31 2007 +0000 @@ -445,11 +445,12 @@ #define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13) #define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14) -static BOOL winpidgin_set_running() { +static BOOL winpidgin_set_running(BOOL fail_if_running) { HANDLE h; if ((h = CreateMutex(NULL, FALSE, "pidgin_is_running"))) { - if (GetLastError() == ERROR_ALREADY_EXISTS) { + DWORD err = GetLastError(); + if (err == ERROR_ALREADY_EXISTS && fail_if_running) { HWND msg_win; printf("An instance of Pidgin is already running.\n"); @@ -465,7 +466,8 @@ NULL, MB_OK | MB_TOPMOST); return FALSE; - } + } else + printf("Error (%d) accessing \"pidgin_is_running\" mutex.\n", err); } return TRUE; } @@ -628,8 +630,8 @@ winpidgin_set_locale(); /* If help, version or multiple flag used, do not check Mutex */ - if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v") && !strstr(lpszCmdLine, "-m")) - if (!getenv("PIDGIN_MULTI_INST") && !winpidgin_set_running()) + if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v")) + if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && strstr(lpszCmdLine, "-m") == NULL)) return 0; /* Now we are ready for Pidgin .. */
--- a/po/de.po Sat Dec 15 22:58:57 2007 +0000 +++ b/po/de.po Tue Dec 18 18:18:31 2007 +0000 @@ -11,8 +11,8 @@ msgstr "" "Project-Id-Version: de\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-12-06 15:10+0100\n" -"PO-Revision-Date: 2007-12-06 15:10+0100\n" +"POT-Creation-Date: 2007-12-18 16:51+0100\n" +"PO-Revision-Date: 2007-12-18 16:50+0100\n" "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n" "Language-Team: Deutsch <de@li.org>\n" "MIME-Version: 1.0\n" @@ -3412,12 +3412,12 @@ msgid "Plaintext Authentication" msgstr "Klartext-Authentifizierung" +msgid "Invalid response from server." +msgstr "Ungültige Serverantwort." + msgid "Server does not use any supported authentication method" msgstr "Der Server benutzt keine der unterstützten Authentifizierungsmethoden" -msgid "Invalid response from server." -msgstr "Ungültige Serverantwort." - msgid "" "This server requires plaintext authentication over an unencrypted " "connection. Allow this and continue authentication?" @@ -3830,6 +3830,9 @@ msgid "Write error" msgstr "Schreibfehler" +msgid "Ping timeout" +msgstr "Ping-Zeitüberschreitung" + msgid "Read Error" msgstr "Fehler beim Lesen" @@ -9513,26 +9516,14 @@ msgstr "Musik hören" #, c-format -msgid "%s changed status from %s to %s" -msgstr "%s hat den Status von %s zu %s geändert" - -#, c-format msgid "%s (%s) changed status from %s to %s" msgstr "%s (%s) hat den Status von %s zu %s geändert" #, c-format -msgid "%s is now %s" -msgstr "%s ist jetzt %s" - -#, c-format msgid "%s (%s) is now %s" msgstr "%s (%s) ist jetzt %s" #, c-format -msgid "%s is no longer %s" -msgstr "%s ist nicht mehr %s" - -#, c-format msgid "%s (%s) is no longer %s" msgstr "%s (%s) ist nicht mehr %s" @@ -9638,6 +9629,28 @@ msgid "Unable to connect to %s: %s" msgstr "Verbindung zu %s nicht möglich: %s" +#. 10053 +#, fuzzy, c-format +msgid "Connection interrupted by other software on your computer." +msgstr "" +"Die Verbindung wurde von einer anderen Software auf ihrem Computer " +"unterbrochen." + +#. 10054 +#, fuzzy, c-format +msgid "Remote host closed connection." +msgstr "Der entfernte Host hat die Verbindung beendet." + +#. 10060 +#, c-format +msgid "Connection timed out." +msgstr "Verbindungsabbruch wegen Zeitüberschreitung." + +#. 10061 +#, c-format +msgid "Connection refused." +msgstr "Verbindung abgelehnt." + msgid "Internet Messenger" msgstr "Internet-Sofortnachrichtendienst" @@ -11084,6 +11097,32 @@ msgstr "" "Farbe zum Darstellen von Hyperlinks, wenn sich die Maus darüber befindet." +#, fuzzy +msgid "Sent Message Name Color" +msgstr "Gesendete Nachrichten" + +msgid "Color to draw the name of a message you sent." +msgstr "" + +#, fuzzy +msgid "Received Message Name Color" +msgstr "Empfangene Nachrichten" + +msgid "Color to draw the name of a message you received." +msgstr "" + +msgid "\"Attention\" Name Color" +msgstr "" + +msgid "Color to draw the name of a message you received containing your name." +msgstr "" + +msgid "Action Message Name Color" +msgstr "" + +msgid "Color to draw the name of an action message." +msgstr "" + msgid "_Copy E-Mail Address" msgstr "Kopiere _E-Mail-Adresse" @@ -11694,8 +11733,8 @@ "This is how your outgoing message text will appear when you use protocols " "that support formatting." msgstr "" -"So wird der ausgehende Nachrichtentext aussehen, wenn Sie " -"Protokollebenutzen, die Formatierung unterstützen." +"So wird der ausgehende Nachrichtentext aussehen, wenn Sie Protokolle " +"benutzen, die Formatierung unterstützen." msgid "Cannot start proxy configuration program." msgstr "Kann das Proxy-Konfigurationsprogramm nicht starten." @@ -12773,6 +12812,10 @@ msgid "Hyperlink Color" msgstr "Hyperlink-Farbe" +#, fuzzy +msgid "Highlighted Message Name Color" +msgstr "Hervorgehobene Nachrichten" + msgid "GtkTreeView Horizontal Separation" msgstr "GtkTreeview horizontaler Abstand" @@ -13160,3 +13203,12 @@ msgid "This plugin is useful for debbuging XMPP servers or clients." msgstr "" "Dieses Plugin ist nützlich zur Fehlersuche in XMPP-Servern oder -Clients." + +#~ msgid "%s changed status from %s to %s" +#~ msgstr "%s hat den Status von %s zu %s geändert" + +#~ msgid "%s is now %s" +#~ msgstr "%s ist jetzt %s" + +#~ msgid "%s is no longer %s" +#~ msgstr "%s ist nicht mehr %s"