changeset 24109:f29588a95ea9

Add custom smiley support for XMPP. Closes #5627. committer: Sadrul Habib Chowdhury <imadil@gmail.com>
author Marcus Lundblad <ml@update.uu.se>
date Tue, 23 Sep 2008 07:38:47 +0000
parents 384217df4ee7 (diff) 883e6318883f (current diff)
children 2c6c9d72f54f
files ChangeLog
diffstat 13 files changed, 162 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Sep 17 19:24:54 2008 +0000
+++ b/ChangeLog	Tue Sep 23 07:38:47 2008 +0000
@@ -11,10 +11,14 @@
 	* Fix a case where a conversation window could close unexpectedly.
 	* A mute sounds option has been added to the preferences window to
 	  help with discoverability.  CTRL+S is no longer bound to mute.
+	* Added ability to change the color of visited links (using the theme
+	  control plugin, or setting the color in ~/.gtkrc-2.0)
 
 	Finch:
 	* A new 'Nested Grouping' option in the 'Grouping' plugin. Group
 	  hierarchies are defined by the '/' character in the group names
+	* A bug was fixed where some key-bindings wouldn't work with some TERMs
+	  (e.g. xterm-color, screen-linux etc.)
 
 	XMPP:
 	* Sending and receiving custom smileys using the specification in
--- a/finch/libgnt/gntkeys.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/finch/libgnt/gntkeys.c	Tue Sep 23 07:38:47 2008 +0000
@@ -47,12 +47,12 @@
 			term = "";  /* Just in case */
 	}
 
-	if (strcmp(term, "xterm") == 0 || strcmp(term, "rxvt") == 0) {
+	if (strstr(term, "xterm") == term || strcmp(term, "rxvt") == 0) {
 		gnt_key_cup    = "\033" "[1;5A";
 		gnt_key_cdown  = "\033" "[1;5B";
 		gnt_key_cright = "\033" "[1;5C";
 		gnt_key_cleft  = "\033" "[1;5D";
-	} else if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0) {
+	} else if (strstr(term, "screen") == term || strcmp(term, "rxvt-unicode") == 0) {
 		gnt_key_cup    = "\033" "Oa";
 		gnt_key_cdown  = "\033" "Ob";
 		gnt_key_cright = "\033" "Oc";
@@ -147,11 +147,11 @@
 	if (*text == 27 && *(text + 1) == '[' &&
 			(*(text + 2) >= 'A' && *(text + 2) <= 'D')) {
 		/* Apparently this is necessary for urxvt and screen and xterm */
-		if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 ||
-				strcmp(term, "xterm") == 0)
+		if (strstr(term, "screen") == term || strcmp(term, "rxvt-unicode") == 0 ||
+				strstr(term, "xterm") == term)
 			*(text + 1) = 'O';
 	} else if (*(unsigned char*)text == 195) {
-		if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) {
+		if (*(text + 2) == 0 && strstr(term, "xterm") == term) {
 			*(text) = 27;
 			*(text + 1) -= 64;  /* Say wha? */
 		}
--- a/libpurple/protocols/bonjour/jabber.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Tue Sep 23 07:38:47 2008 +0000
@@ -946,7 +946,7 @@
 bonjour_jabber_send_message(BonjourJabber *jdata, const gchar *to, const gchar *body)
 {
 	xmlnode *message_node, *node, *node2;
-	gchar *message;
+	gchar *message, *xhtml;
 	PurpleBuddy *pb;
 	BonjourBuddy *bb;
 	int ret;
@@ -958,6 +958,8 @@
 		return -10000;
 	}
 
+	purple_markup_html_to_xhtml(body, &xhtml, &message);
+
 	bb = pb->proto_data;
 
 	message_node = xmlnode_new("message");
@@ -967,7 +969,6 @@
 
 	/* Enclose the message from the UI within a "font" node */
 	node = xmlnode_new_child(message_node, "body");
-	message = purple_markup_strip_html(body);
 	xmlnode_insert_data(node, message, strlen(message));
 	g_free(message);
 
@@ -975,8 +976,9 @@
 	xmlnode_set_namespace(node, "http://www.w3.org/1999/xhtml");
 
 	node = xmlnode_new_child(node, "body");
-	message = g_strdup_printf("<font>%s</font>", body);
+	message = g_strdup_printf("<font>%s</font>", xhtml);
 	node2 = xmlnode_from_str(message, strlen(message));
+	g_free(xhtml);
 	g_free(message);
 	xmlnode_insert_child(node, node2);
 
--- a/libpurple/protocols/msn/notification.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/msn/notification.c	Tue Sep 23 07:38:47 2008 +0000
@@ -613,16 +613,13 @@
 	xmlnode_set_attrib(adl_node, "l", "1");
 
 	/*get the userlist*/
-	for (l = session->userlist->users; l != NULL; l = l->next) {
+	for (l = session->userlist->users; l != NULL; l = l->next){
 		user = l->data;
 
 		/* skip RL & PL during initial dump */
 		if (!(user->list_op & MSN_LIST_OP_MASK))
 			continue;
 
-		if (!strcmp(user->passport, "messenger@microsoft.com"))
-			continue;
-
 		msn_add_contact_xml(session, adl_node, user->passport,
 			user->list_op & MSN_LIST_OP_MASK, user->networkid);
 
@@ -774,6 +771,53 @@
 }
 
 static void
+adl_241_error_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+	size_t len)
+{
+	/* khc: some googling suggests that error 241 means the buddy is somehow
+	   in the local list, but not the server list, and that we should add
+	   those buddies to the addressbook. For now I will just notify the user
+	   about the raw payload, because I am lazy */
+	MsnSession *session;
+	PurpleAccount *account;
+	PurpleConnection *gc;
+	xmlnode *adl;
+	xmlnode *domain;
+	GString *emails;
+
+	session = cmdproc->session;
+	account = session->account;
+	gc = purple_account_get_connection(account);
+
+	adl = xmlnode_from_str(payload, len);
+	emails = g_string_new(NULL);
+
+	domain = xmlnode_get_child(adl, "d");
+	while (domain) {
+		const char *domain_str = xmlnode_get_attrib(domain, "n");
+		xmlnode *contact = xmlnode_get_child(domain, "c");
+		while (contact) {
+			g_string_append_printf(emails, "%s@%s\n",
+				xmlnode_get_attrib(contact, "n"), domain_str);
+			contact = xmlnode_get_next_twin(contact);
+		}
+		domain = xmlnode_get_next_twin(domain);
+	}
+
+	purple_notify_error(gc, NULL,
+		_("The following users are missing from your addressbook"), emails->str);
+	g_string_free(emails, TRUE);
+	xmlnode_free(adl);
+}
+
+static void
+adl_241_error_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+{
+	cmdproc->last_cmd->payload_cb = adl_241_error_cmd_post;
+	cmd->payload_len = atoi(cmd->params[1]);
+}
+
+static void
 fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
 			 size_t len)
 {
@@ -1132,6 +1176,7 @@
 	friendly = purple_url_decode(cmd->params[3]);
 
 	user = msn_userlist_find_user(session->userlist, passport);
+	if (user == NULL) return;
 
 	old_friendly = msn_user_get_friendly_name(user);
 	if (!old_friendly || (old_friendly && (!friendly || strcmp(old_friendly, friendly))))
@@ -1961,6 +2006,8 @@
 
 	msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
 
+	msn_table_add_cmd(cbs_table, NULL, "241", adl_241_error_cmd);
+
 	msn_table_add_error(cbs_table, "ADD", add_error);
 	msn_table_add_error(cbs_table, "ADL", adl_error);
 	msn_table_add_error(cbs_table, "REG", reg_error);
--- a/libpurple/protocols/null/nullprpl.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/null/nullprpl.c	Tue Sep 23 07:38:47 2008 +0000
@@ -46,8 +46,12 @@
 
 #include <glib.h>
 
+/* If you're using this as the basis of a prpl that will be distributed
+ * separately from libpurple, remove the internal.h include below and replace
+ * it with code to include your own config.h or similar.  If you're going to
+ * provide for translation, you'll also need to setup the gettext macros. */
 #include "internal.h"
-#include "config.h"
+
 #include "account.h"
 #include "accountopt.h"
 #include "blist.h"
--- a/libpurple/protocols/yahoo/yahoo.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Tue Sep 23 07:38:47 2008 +0000
@@ -55,6 +55,12 @@
 
 /* #define TRY_WEBMESSENGER_LOGIN 0 */
 
+/* One hour */
+#define PING_TIMEOUT 3600
+
+/* One minute */
+#define KEEPALIVE_TIMEOUT 60
+
 static void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *, PurpleGroup *);
 #ifdef TRY_WEBMESSENGER_LOGIN
 static void yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message);
@@ -3001,6 +3007,7 @@
 	yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
 	yd->confs = NULL;
 	yd->conf_id = 2;
+	yd->last_keepalive = yd->last_ping = time(NULL);
 
 	yd->current_status = get_yahoo_status_from_purple_status(status);
 
@@ -3059,7 +3066,7 @@
 	}
 	g_slist_free(yd->cookies);
 
-	yd->chat_online = 0;
+	yd->chat_online = FALSE;
 	if (yd->in_chat)
 		yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
 
@@ -3871,21 +3878,36 @@
 
 static void yahoo_keepalive(PurpleConnection *gc)
 {
+	struct yahoo_packet *pkt;
 	struct yahoo_data *yd = gc->proto_data;
-	struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0);
-	yahoo_packet_send_and_free(pkt, yd);
-
-	if (!yd->chat_online)
-		return;
-
-	if (yd->wm) {
-		ycht_chat_send_keepalive(yd->ycht);
-		return;
+	time_t now = time(NULL);
+
+	/* We're only allowed to send a ping once an hour or the servers will boot us */
+	if ((now - yd->last_ping) >= PING_TIMEOUT) {
+		yd->last_ping = now;
+
+		/* The native client will only send PING or CHATPING */
+		if (yd->chat_online) {
+			if (yd->wm) {
+				ycht_chat_send_keepalive(yd->ycht);
+			} else {
+				pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, 0);
+				yahoo_packet_hash_str(pkt, 109, purple_connection_get_display_name(gc));
+				yahoo_packet_send_and_free(pkt, yd);
+			}
+		} else {
+			pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, 0);
+			yahoo_packet_send_and_free(pkt, yd);
+		}
 	}
 
-	pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, 0);
-	yahoo_packet_hash_str(pkt, 109, purple_connection_get_display_name(gc));
-	yahoo_packet_send_and_free(pkt, yd);
+	if ((now - yd->last_keepalive) >= KEEPALIVE_TIMEOUT) {
+		yd->last_keepalive = now;
+		pkt = yahoo_packet_new(YAHOO_SERVICE_KEEPALIVE, YAHOO_STATUS_AVAILABLE, 0);
+		yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
+		yahoo_packet_send_and_free(pkt, yd);
+	}
+
 }
 
 static void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
--- a/libpurple/protocols/yahoo/yahoo.h	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.h	Tue Sep 23 07:38:47 2008 +0000
@@ -176,6 +176,8 @@
 	 * the server expects us to keep track of the group for which it is sending us contact names.
 	 */
 	char *current_list15_grp;
+	time_t last_ping;
+	time_t last_keepalive;
 };
 
 #define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
--- a/libpurple/protocols/yahoo/yahoo_packet.h	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.h	Tue Sep 23 07:38:47 2008 +0000
@@ -76,7 +76,7 @@
 	YAHOO_SERVICE_IGNORECONTACT,    /* > 1, 7, 13 < 1, 66, 13, 0*/
 	YAHOO_SERVICE_REJECTCONTACT,
 	YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
-	/* YAHOO_SERVICE_??? = 0x8A, */
+	YAHOO_SERVICE_KEEPALIVE = 0x8A,
 	YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
 	YAHOO_SERVICE_CHATGOTO,
 	YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
--- a/libpurple/protocols/yahoo/yahoochat.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Tue Sep 23 07:38:47 2008 +0000
@@ -369,7 +369,7 @@
 	struct yahoo_data *yd = (struct yahoo_data *) gc->proto_data;
 
 	if (pkt->status == 1) {
-		yd->chat_online = 1;
+		yd->chat_online = TRUE;
 
 		/* We need to goto a user in chat */
 		if (yd->pending_chat_goto) {
@@ -411,7 +411,7 @@
 	}
 
 	if (pkt->status == 1) {
-		yd->chat_online = 0;
+		yd->chat_online = FALSE;
 		g_free(yd->pending_chat_room);
 		yd->pending_chat_room = NULL;
 		g_free(yd->pending_chat_id);
@@ -881,7 +881,7 @@
 	yahoo_packet_hash_str(pkt, 1, dn);
 	yahoo_packet_send_and_free(pkt, yd);
 
-	yd->chat_online = 0;
+	yd->chat_online = FALSE;
 	g_free(yd->pending_chat_room);
 	yd->pending_chat_room = NULL;
 	g_free(yd->pending_chat_id);
--- a/pidgin/gtkimhtml.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/pidgin/gtkimhtml.c	Tue Sep 23 07:38:47 2008 +0000
@@ -446,6 +446,20 @@
 	parent_style_set(widget, prev_style);
 }
 
+static void
+gtk_imhtml_set_link_color(GtkIMHtml *imhtml, GtkTextTag *tag)
+{
+	GdkColor *color = NULL;
+	gboolean visited = !!g_object_get_data(G_OBJECT(tag), "visited");
+	gtk_widget_style_get(GTK_WIDGET(imhtml), visited ? "hyperlink-visited-color" : "hyperlink-color", &color, NULL);
+	if (color) {
+		g_object_set(G_OBJECT(tag), "foreground-gdk", color, NULL);
+		gdk_color_free(color);
+	} else {
+		g_object_set(G_OBJECT(tag), "foreground", visited ? "#800000" : "blue", NULL);
+	}
+}
+
 static gint
 gtk_imhtml_tip_paint (GtkIMHtml *imhtml)
 {
@@ -566,7 +580,6 @@
 	int x, y;
 	char *tip = NULL;
 	GSList *tags = NULL, *templist = NULL;
-	GdkColor *norm, *pre;
 	GtkTextTag *tag = NULL, *oldprelit_tag;
 	GtkTextChildAnchor* anchor;
 	gboolean hand = TRUE;
@@ -588,13 +601,15 @@
 		templist = templist->next;
 	}
 
-	if (tip) {
-		gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-prelight-color", &pre, NULL);
+	if (tip && (!tag || !g_object_get_data(G_OBJECT(tag), "visited"))) {
 		GTK_IMHTML(imhtml)->prelit_tag = tag;
 		if (tag != oldprelit_tag) {
-			if (pre)
+			GdkColor *pre = NULL;
+			gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-prelight-color", &pre, NULL);
+			if (pre) {
 				g_object_set(G_OBJECT(tag), "foreground-gdk", pre, NULL);
-			else
+				gdk_color_free(pre);
+			} else
 				g_object_set(G_OBJECT(tag), "foreground", "#70a0ff", NULL);
 		}
 	} else {
@@ -602,11 +617,7 @@
 	}
 
 	if ((oldprelit_tag != NULL) && (GTK_IMHTML(imhtml)->prelit_tag != oldprelit_tag)) {
-		gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &norm, NULL);
-		if (norm)
-			g_object_set(G_OBJECT(oldprelit_tag), "foreground-gdk", norm, NULL);
-		else
-			g_object_set(G_OBJECT(oldprelit_tag), "foreground", "blue", NULL);
+		gtk_imhtml_set_link_color(GTK_IMHTML(imhtml), oldprelit_tag);
 	}
 
 	if (GTK_IMHTML(imhtml)->tip) {
@@ -670,12 +681,7 @@
 {
 	/* when leaving the widget, clear any current & pending tooltips and restore the cursor */
 	if (GTK_IMHTML(imhtml)->prelit_tag) {
-		GdkColor *norm;
-		gtk_widget_style_get(GTK_WIDGET(imhtml), "hyperlink-color", &norm, NULL);
-		if (norm)
-			g_object_set(G_OBJECT(GTK_IMHTML(imhtml)->prelit_tag), "foreground-gdk", norm, NULL);
-		else
-			g_object_set(G_OBJECT(GTK_IMHTML(imhtml)->prelit_tag), "foreground", "blue", NULL);
+		gtk_imhtml_set_link_color(GTK_IMHTML(imhtml), GTK_IMHTML(imhtml)->prelit_tag);
 		GTK_IMHTML(imhtml)->prelit_tag = NULL;
 	}
 
@@ -1482,6 +1488,10 @@
 	                                        _("Hyperlink color"),
 	                                        _("Color to draw hyperlinks."),
 	                                        GDK_TYPE_COLOR, G_PARAM_READABLE));
+	gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-visited-color",
+	                                        _("Hyperlink visited color"),
+	                                        _("Color to draw hyperlinks after it has been visited (or activated)."),
+	                                        GDK_TYPE_COLOR, G_PARAM_READABLE));
 	gtk_widget_class_install_style_property(widget_class, g_param_spec_boxed("hyperlink-prelight-color",
 	                                        _("Hyperlink prelight color"),
 	                                        _("Color to draw hyperlinks when mouse is over them."),
@@ -1679,20 +1689,24 @@
 struct url_data {
 	GObject *object;
 	gchar *url;
+	GtkTextTag *tag;
 };
 
 static void url_data_destroy(gpointer mydata)
 {
 	struct url_data *data = mydata;
 	g_object_unref(data->object);
+	g_object_unref(data->tag);
 	g_free(data->url);
 	g_free(data);
 }
 
-static void url_open(GtkWidget *w, struct url_data *data) {
+static void url_open(GtkWidget *w, struct url_data *data)
+{
 	if(!data) return;
 	g_signal_emit(data->object, signals[URL_CLICKED], 0, data->url);
-
+	g_object_set_data(G_OBJECT(data->tag), "visited", GINT_TO_POINTER(TRUE));
+	gtk_imhtml_set_link_color(GTK_IMHTML(data->object), data->tag);
 }
 
 static void url_copy(GtkWidget *w, gchar *url) {
@@ -1706,7 +1720,8 @@
 }
 
 /* The callback for an event on a link tag. */
-static gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused) {
+static gboolean tag_event(GtkTextTag *tag, GObject *imhtml, GdkEvent *event, GtkTextIter *arg2, gpointer unused)
+{
 	GdkEventButton *event_button = (GdkEventButton *) event;
 	if (GTK_IMHTML(imhtml)->editable)
 		return FALSE;
@@ -1723,12 +1738,15 @@
 			g_object_ref(G_OBJECT(tag));
 			g_signal_emit(imhtml, signals[URL_CLICKED], 0, g_object_get_data(G_OBJECT(tag), "link_url"));
 			g_object_unref(G_OBJECT(tag));
+			g_object_set_data(G_OBJECT(tag), "visited", GINT_TO_POINTER(TRUE));
+			gtk_imhtml_set_link_color(GTK_IMHTML(imhtml), tag);
 			return FALSE;
 		} else if(event_button->button == 3) {
 			GtkWidget *img, *item, *menu;
 			struct url_data *tempdata = g_new(struct url_data, 1);
 			tempdata->object = g_object_ref(imhtml);
 			tempdata->url = g_strdup(g_object_get_data(G_OBJECT(tag), "link_url"));
+			tempdata->tag = g_object_ref(tag);
 
 			/* Don't want the tooltip around if user right-clicked on link */
 			if (GTK_IMHTML(imhtml)->tip_window) {
--- a/pidgin/gtkmenutray.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/pidgin/gtkmenutray.c	Tue Sep 23 07:38:47 2008 +0000
@@ -84,6 +84,14 @@
 }
 
 static void
+pidgin_menu_tray_map(GtkWidget *widget)
+{
+	GTK_WIDGET_CLASS(parent_class)->map(widget);
+	gtk_container_add(GTK_CONTAINER(widget),
+			PIDGIN_MENU_TRAY(widget)->tray);
+}
+
+static void
 pidgin_menu_tray_finalize(GObject *obj)
 {
 	PidginMenuTray *tray = PIDGIN_MENU_TRAY(obj);
@@ -109,6 +117,7 @@
 pidgin_menu_tray_class_init(PidginMenuTrayClass *klass) {
 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
 	GtkItemClass *item_class = GTK_ITEM_CLASS(klass);
+	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
 	GParamSpec *pspec;
 
 	parent_class = g_type_class_peek_parent(klass);
@@ -119,6 +128,8 @@
 	item_class->select = pidgin_menu_tray_select;
 	item_class->deselect = pidgin_menu_tray_deselect;
 
+	widget_class->map = pidgin_menu_tray_map;
+
 	pspec = g_param_spec_object("box", "The box",
 								"The box",
 								GTK_TYPE_BOX,
@@ -152,8 +163,6 @@
 		gtk_widget_set_size_request(widget, -1, height);
 	}
 
-	gtk_container_add(GTK_CONTAINER(menu_tray), menu_tray->tray);
-
 	gtk_widget_show(menu_tray->tray);
 }
 
--- a/pidgin/plugins/pidginrc.c	Wed Sep 17 19:24:54 2008 +0000
+++ b/pidgin/plugins/pidginrc.c	Tue Sep 23 07:38:47 2008 +0000
@@ -31,6 +31,7 @@
 	"/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-visited-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",
@@ -40,6 +41,7 @@
 	"/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-visited-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",
@@ -49,6 +51,7 @@
 	N_("Cursor Color"),
 	N_("Secondary Cursor Color"),
 	N_("Hyperlink Color"),
+	N_("Visited Hyperlink Color"),
 	N_("Sent Message Name Color"),
 	N_("Received Message Name Color"),
 	N_("Highlighted Message Name Color"),
--- a/po/POTFILES.in	Wed Sep 17 19:24:54 2008 +0000
+++ b/po/POTFILES.in	Tue Sep 23 07:38:47 2008 +0000
@@ -183,8 +183,6 @@
 libpurple/util.c
 libpurple/win32/libc_interface.c
 pidgin.desktop.in
-pidgin/artwork/hicolor/24x24/emotes/default.theme.in
-pidgin/artwork/hicolor/24x24/emotes/none/none.theme.in
 pidgin/eggtrayicon.c
 pidgin/gtkaccount.c
 pidgin/gtkblist.c