[Commits] [SCM] claws branch, master, updated. 3.9.3-29-gb079a3a

mones at claws-mail.org mones at claws-mail.org
Fri Feb 21 19:59:51 CET 2014


The branch master of project "claws" (Claws Mail) has been updated
       via  b079a3a27273d2441202ab9ac80a94645afc6017 (commit)
       via  daea250f36c7346e018cdc8a759f10ff0c9834f5 (commit)
       via  a3ec21768c199ad01785f8ec177cf60470824759 (commit)
      from  37df4f1b3240328a17c03108319ad315447e7fb7 (commit)


- Log -----------------------------------------------------------------
commit b079a3a27273d2441202ab9ac80a94645afc6017
Author: Ricardo Mones <ricardo at mones.org>
Date:   Sun Feb 16 19:21:54 2014 +0100

    Use new internal plugin for rendering avatars
    
    Updates and simplifies rendering logic in header pane,
    message view and text view and when adding pictures to
    address book.

diff --git a/src/headerview.c b/src/headerview.c
index 2d7074b..7880d25 100644
--- a/src/headerview.c
+++ b/src/headerview.c
@@ -31,10 +31,6 @@
 #include <string.h>
 #include <time.h>
 
-#if HAVE_LIBCOMPFACE
-#  include <compface.h>
-#endif
-
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 #include "headerview.h"
@@ -45,13 +41,10 @@
 #include "base64.h"
 #include "headers.h"
 #include "addrindex.h"
+#include "hooks.h"
+#include "avatars.h"
 
-#if HAVE_LIBCOMPFACE
-static gint headerview_show_xface	(HeaderView	*headerview,
-					 MsgInfo	*msginfo);
-#endif
-
-static gint headerview_show_face	(HeaderView	*headerview,
+static gint headerview_show_avatar	(HeaderView	*headerview,
 					 MsgInfo	*msginfo);
 static gint headerview_show_contact_pic	(HeaderView	*headerview,
 					 MsgInfo	*msginfo);
@@ -221,91 +214,50 @@ void headerview_show(HeaderView *headerview, MsgInfo *msginfo)
 		gtk_widget_show(headerview->tags_body_label);
 		g_free(tags);
 	}
-	if (!headerview_show_face(headerview, msginfo))
-		return;
-
-#if HAVE_LIBCOMPFACE
-	if (!headerview_show_xface(headerview, msginfo))
+	if (!headerview_show_avatar(headerview, msginfo))
 		return;
-#endif
 
 	if (!headerview_show_contact_pic(headerview, msginfo))
 		return;
 
 }
 
-#if HAVE_LIBCOMPFACE
-static gint headerview_show_xface(HeaderView *headerview, MsgInfo *msginfo)
+static gint headerview_show_avatar (HeaderView *headerview, MsgInfo *msginfo)
 {
+	AvatarRender *avatarr = avatars_avatarrender_new(msginfo);
 	GtkWidget *hbox = headerview->hbox;
 	GtkWidget *image;
-	gchar *xface = procmsg_msginfo_get_avatar(msginfo, AVATAR_XFACE);
 
-	if (!msginfo->extradata || !xface || strlen(xface) < 5) {
-		if (headerview->image &&
-		    gtk_widget_get_visible(headerview->image)) {
+	hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
+
+	if (!avatarr->image) {
+		if (headerview->image
+				&& gtk_widget_get_visible(headerview->image)) {
 			gtk_widget_hide(headerview->image);
 			gtk_widget_queue_resize(hbox);
 		}
+		avatars_avatarrender_free(avatarr);
 		return -1;
 	}
-	if (!gtk_widget_get_visible(headerview->hbox)) return -1;
-
-	if (headerview->image) {
-		gtk_widget_destroy(headerview->image);
-		headerview->image = NULL;
-	}
-
-	image = xface_get_from_header(xface);
-
-	if (image) {
-		gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-		gtk_widget_show(image);
-	}
-
-	headerview->image = image;
-	if (image) {
-		headerview_save_contact_pic(headerview, msginfo);
-	}
-	return 0;
-}
-#endif
-
-static gint headerview_show_face (HeaderView *headerview, MsgInfo *msginfo)
-{
-	GtkWidget *hbox = headerview->hbox;
-	GtkWidget *image;
-	gchar *face = procmsg_msginfo_get_avatar(msginfo, AVATAR_FACE);
-
-	if (!msginfo->extradata || !face) {
-		if (headerview->image &&
-		    gtk_widget_get_visible(headerview->image)) {
-			gtk_widget_hide(headerview->image);
-			gtk_widget_queue_resize(hbox);
-		}
+	if (!gtk_widget_get_visible(hbox)) {
+		avatars_avatarrender_free(avatarr);
 		return -1;
 	}
-	if (!gtk_widget_get_visible(headerview->hbox)) return -1;
 
 	if (headerview->image) {
 		gtk_widget_destroy(headerview->image);
 		headerview->image = NULL;
 	}
 
-	image = face_get_from_header(face);
+	gtk_box_pack_start(GTK_BOX(hbox), avatarr->image, FALSE, FALSE, 0);
+	gtk_widget_show(avatarr->image);
 
-	if (image) {
-		gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-		gtk_widget_show(image);
-	}
+	headerview->image = avatarr->image;
+	avatarr->image = NULL; /* avoid destroying */
+	avatars_avatarrender_free(avatarr);
 
-	headerview->image = image;
-	if (image == NULL)
-		return -1;
-	else {
-		headerview_save_contact_pic(headerview, msginfo);
-		return 0;
-	}
+	headerview_save_contact_pic(headerview, msginfo);
+	return 0;
 }
 
 static void headerview_save_contact_pic (HeaderView *headerview, MsgInfo *msginfo)
diff --git a/src/messageview.c b/src/messageview.c
index 1f1f094..bfab482 100644
--- a/src/messageview.c
+++ b/src/messageview.c
@@ -67,6 +67,7 @@
 #include "version.h"
 #include "statusbar.h"
 #include "folder_item_prefs.h"
+#include "avatars.h"
 #ifndef USE_NEW_ADDRBOOK
 	#include "addressbook.h"
 #else
@@ -2823,9 +2824,8 @@ static void add_address_cb(GtkAction *action, gpointer data)
 	MessageView *messageview = (MessageView *)data;
 	MsgInfo *msginfo, *full_msginfo;
 	gchar *from;
-	GtkWidget *image = NULL;
 	GdkPixbuf *picture = NULL;
-	gchar *face;
+	AvatarRender *avatarr;
 
 	if (!messageview->msginfo || !messageview->msginfo->from) 
 		return;
@@ -2836,21 +2836,14 @@ static void add_address_cb(GtkAction *action, gpointer data)
 	extract_address(from);
 	
 	full_msginfo = procmsg_msginfo_get_full_info(msginfo);
-	face = procmsg_msginfo_get_avatar(full_msginfo, AVATAR_FACE);
-	if (face) {
-		image = face_get_from_header(face);
-	}
-#if HAVE_LIBCOMPFACE
-	else {
-		gchar *xface = procmsg_msginfo_get_avatar(full_msginfo, AVATAR_XFACE);
-		if (xface) {
-			image = xface_get_from_header(xface);
-		}
-	}
-#endif
+
+	avatarr = avatars_avatarrender_new(full_msginfo);
+	hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
+
 	procmsg_msginfo_free(full_msginfo);
-	if (image)
-		picture = gtk_image_get_pixbuf(GTK_IMAGE(image));
+
+	if (avatarr->image != NULL)
+		picture = gtk_image_get_pixbuf(GTK_IMAGE(avatarr->image));
 
 #ifndef USE_NEW_ADDRBOOK
 	addressbook_add_contact(msginfo->fromname, from, NULL, picture);
@@ -2859,8 +2852,7 @@ static void add_address_cb(GtkAction *action, gpointer data)
 		debug_print( "addressbook_add_contact - added\n" );
 	}
 #endif
-	if (image)
-		gtk_widget_destroy(image);
+	avatars_avatarrender_free(avatarr);
 }
 
 static void create_filter_cb(GtkAction *gaction, gpointer data)
diff --git a/src/summaryview.c b/src/summaryview.c
index 3bd2ac0..8da3900 100644
--- a/src/summaryview.c
+++ b/src/summaryview.c
@@ -81,6 +81,7 @@
 #include "edittags.h"
 #include "manual.h"
 #include "manage_window.h"
+#include "avatars.h"
 
 #define SUMMARY_COL_MARK_WIDTH		10
 #define SUMMARY_COL_STATUS_WIDTH	13
@@ -4682,9 +4683,8 @@ void summary_add_address(SummaryView *summaryview)
 {
 	MsgInfo *msginfo, *full_msginfo;
 	gchar *from;
-	GtkWidget *image = NULL;
 	GdkPixbuf *picture = NULL;
-	gchar *face;
+	AvatarRender *avatarr;
 
 	msginfo = gtk_cmctree_node_get_row_data(GTK_CMCTREE(summaryview->ctree),
 					      summaryview->selected);
@@ -4696,21 +4696,14 @@ void summary_add_address(SummaryView *summaryview)
 	extract_address(from);
 	
 	full_msginfo = procmsg_msginfo_get_full_info(msginfo);
-	face = procmsg_msginfo_get_avatar(full_msginfo, AVATAR_FACE);
-	if (face) {
-		image = face_get_from_header(face);
-	} 
-#if HAVE_LIBCOMPFACE
-	else {
-		gchar *xface = procmsg_msginfo_get_avatar(full_msginfo, AVATAR_XFACE);
-		if (xface) {
-			image = xface_get_from_header(xface);
-		}
-	}
-#endif
+
+	avatarr = avatars_avatarrender_new(full_msginfo);
+	hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
+
 	procmsg_msginfo_free(full_msginfo);
-	if (image)
-		picture = gtk_image_get_pixbuf(GTK_IMAGE(image));
+
+	if (avatarr->image)
+		picture = gtk_image_get_pixbuf(GTK_IMAGE(avatarr->image));
 
 #ifndef USE_NEW_ADDRBOOK
 	addressbook_add_contact(msginfo->fromname, from, NULL, picture);
@@ -4719,8 +4712,7 @@ void summary_add_address(SummaryView *summaryview)
 		debug_print( "addressbook_add_contact - added\n" );
 	}
 #endif
-	if (image)
-		gtk_widget_destroy(image);
+	avatars_avatarrender_free(avatarr);
 }
 
 void summary_select_all(SummaryView *summaryview)
diff --git a/src/textview.c b/src/textview.c
index 5575bfd..5106d45 100644
--- a/src/textview.c
+++ b/src/textview.c
@@ -37,9 +37,6 @@
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
-#if HAVE_LIBCOMPFACE
-#  include <compface.h>
-#endif
 
 #include "main.h"
 #include "summaryview.h"
@@ -72,6 +69,7 @@
 #include "tags.h"
 #include "manage_window.h"
 #include "folder_item_prefs.h"
+#include "avatars.h"
 
 static GdkColor quote_colors[3] = {
 	{(gulong)0, (gushort)0, (gushort)0, (gushort)0},
@@ -1965,26 +1963,31 @@ static GPtrArray *textview_scan_header(TextView *textview, FILE *fp)
 	return sorted_headers;
 }
 
-static void textview_show_face(TextView *textview)
+static void textview_show_avatar(TextView *textview)
 {
 	GtkAllocation allocation;
 	GtkTextView *text = GTK_TEXT_VIEW(textview->text);
 	MsgInfo *msginfo = textview->messageview->msginfo;
 	int x = 0;
-	gchar *face;
+	AvatarRender *avatarr;
 	
 	if (prefs_common.display_header_pane || !prefs_common.display_xface)
 		goto bail;
 	
-	face = procmsg_msginfo_get_avatar(msginfo, AVATAR_FACE);
-	if (!face)
+	avatarr = avatars_avatarrender_new(msginfo);
+	hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
+
+	if (!avatarr->image) {
+		avatars_avatarrender_free(avatarr);
 		goto bail;
+	}
 
 	if (textview->image) 
 		gtk_widget_destroy(textview->image);
 	
-	textview->image = face_get_from_header(face);
-	cm_return_if_fail(textview->image != NULL);
+	textview->image = avatarr->image;
+	avatarr->image = NULL; /* avoid destroying */
+	avatars_avatarrender_free(avatarr);
 
 	gtk_widget_show(textview->image);
 	
@@ -1995,7 +1998,6 @@ static void textview_show_face(TextView *textview)
 		GTK_TEXT_WINDOW_TEXT, x, 5);
 
 	gtk_widget_show_all(textview->text);
-	
 
 	return;
 bail:
@@ -2030,58 +2032,6 @@ void textview_show_icon(TextView *textview, const gchar *stock_id)
 	return;
 }
 
-#if HAVE_LIBCOMPFACE
-static void textview_show_xface(TextView *textview)
-{
-	GtkAllocation allocation;
-	MsgInfo *msginfo = textview->messageview->msginfo;
-	GtkTextView *text = GTK_TEXT_VIEW(textview->text);
-	int x = 0;
-	GdkWindow *window = NULL;
-	gchar *face, *xface;
-	
-	if (prefs_common.display_header_pane || !prefs_common.display_xface)
-		goto bail;
-	
-	if (!msginfo || !msginfo->extradata || !msginfo->extradata->avatars)
-		goto bail;
-
-	face = procmsg_msginfo_get_avatar(msginfo, AVATAR_FACE);
-	if (face)
-		return;
-	
-	xface = procmsg_msginfo_get_avatar(msginfo, AVATAR_XFACE);
-	if (!xface || strlen(xface) < 5)
-		goto bail;
-
-	if (textview->image) 
-		gtk_widget_destroy(textview->image);
-
-	window = mainwindow_get_mainwindow() ?
-			mainwindow_get_mainwindow()->window->window :
-			textview->text->window;
-	textview->image = xface_get_from_header(xface);
-	cm_return_if_fail(textview->image != NULL);
-
-	gtk_widget_show(textview->image);
-	
-	gtk_widget_get_allocation(textview->text, &allocation);
-	x = allocation.width - WIDTH -5;
-
-	gtk_text_view_add_child_in_window(text, textview->image, 
-		GTK_TEXT_WINDOW_TEXT, x, 5);
-
-	gtk_widget_show_all(textview->text);
-	
-	return;
-bail:
-	if (textview->image) 
-		gtk_widget_destroy(textview->image);
-	textview->image = NULL;
-	
-}
-#endif
-
 static void textview_save_contact_pic(TextView *textview)
 {
 #ifndef USE_NEW_ADDRBOOK
@@ -2089,14 +2039,8 @@ static void textview_save_contact_pic(TextView *textview)
 	gchar *filename = NULL;
 	GError *error = NULL;
 	GdkPixbuf *picture = NULL;
-	gchar *face, *xface;
-				
-	if (!msginfo->extradata || !msginfo->extradata->avatars)
-		return;
 
-	face = procmsg_msginfo_get_avatar(msginfo, AVATAR_FACE);
-        xface = procmsg_msginfo_get_avatar(msginfo, AVATAR_XFACE);
-	if (!face && !xface)
+	if (!msginfo->extradata || !msginfo->extradata->avatars)
 		return;
 
 	if (textview->image) 
@@ -2130,15 +2074,12 @@ static void textview_show_contact_pic(TextView *textview)
 	GdkPixbuf *picture = NULL;
 	gint w, h;
 	GtkAllocation allocation;
-	gchar *face, *xface;
-				
+
 	if (prefs_common.display_header_pane
 		|| !prefs_common.display_xface)
 		goto bail;
 	
-	face = procmsg_msginfo_get_avatar(msginfo, AVATAR_FACE);
-	xface = procmsg_msginfo_get_avatar(msginfo, AVATAR_XFACE);
-	if (msginfo->extradata && (face || xface)) /* FIXME extradata not needed */
+	if (msginfo->extradata && msginfo->extradata->avatars)
 		return;
 
 	if (textview->image) 
@@ -2345,10 +2286,8 @@ static void textview_show_header(TextView *textview, GPtrArray *headers)
 							 "header", NULL);
 	}
 	
-	textview_show_face(textview);
-#if HAVE_LIBCOMPFACE
-	textview_show_xface(textview);
-#endif
+	textview_show_avatar(textview);
+
 	textview_save_contact_pic(textview);
 	textview_show_contact_pic(textview);
 }
@@ -3170,7 +3109,7 @@ static void add_uri_to_addrbook_cb (GtkAction *action, TextView *textview)
 	gchar *fromname, *fromaddress;
 	ClickableText *uri = g_object_get_data(G_OBJECT(textview->mail_popup_menu),
 					   "menu_button");
-	GtkWidget *image = NULL;
+	AvatarRender *avatarr = NULL;
 	GdkPixbuf *picture = NULL;
 	gboolean use_picture = FALSE;
 
@@ -3188,26 +3127,16 @@ static void add_uri_to_addrbook_cb (GtkAction *action, TextView *textview)
 	extract_address(fromaddress);
 
 	if (use_picture) {
-		gchar *face = procmsg_msginfo_get_avatar(
-					textview->messageview->msginfo,
-					AVATAR_FACE);
-		if (face) {
-			image = face_get_from_header(face);
-		}
-#if HAVE_LIBCOMPFACE 
-		else {
-			gchar *xface = procmsg_msginfo_get_avatar(
-						textview->messageview->msginfo,
-						AVATAR_XFACE);
-			if (xface) {
-				image = xface_get_from_header(xface);
-			}
-		}
-#endif
+		avatarr = avatars_avatarrender_new(textview->messageview->msginfo);
+		hooks_invoke(AVATAR_IMAGE_RENDER_HOOKLIST, avatarr);
 	}
 
-	if (image)
-		picture = gtk_image_get_pixbuf(GTK_IMAGE(image));
+	if (avatarr && avatarr->image) {
+		picture = gtk_image_get_pixbuf(GTK_IMAGE(avatarr->image));
+	}
+	if (avatarr) {
+		avatars_avatarrender_free(avatarr);
+	}
 
 #ifndef USE_NEW_ADDRBOOK
 	addressbook_add_contact( fromname, fromaddress, NULL, picture);

commit daea250f36c7346e018cdc8a759f10ff0c9834f5
Author: Ricardo Mones <ricardo at mones.org>
Date:   Sat Feb 15 20:40:43 2014 +0100

    New hooklist for rendering avatars and some utils
    
     • Create and destroy hooklist parameter structs
     • Initialization function to install default handler

diff --git a/src/Makefile.am b/src/Makefile.am
index e5bd012..375d561 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -130,6 +130,7 @@ claws_mail_SOURCES = \
 	advsearch.c \
 	alertpanel.c \
 	autofaces.c \
+	avatars.c \
 	codeconv.c \
 	compose.c \
 	crash.c \
@@ -244,6 +245,7 @@ claws_mailinclude_HEADERS = \
 	advsearch.h \
 	alertpanel.h \
 	autofaces.h \
+	avatars.h \
 	codeconv.h \
 	compose.h \
 	crash.h \
diff --git a/src/avatars.c b/src/avatars.c
new file mode 100644
index 0000000..51acba4
--- /dev/null
+++ b/src/avatars.c
@@ -0,0 +1,110 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2014 Ricardo Mones and the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "defs.h"
+#include "hooks.h"
+#include "gtkutils.h"
+#include "procmsg.h"
+#include "prefs_common.h"
+#include "avatars.h"
+
+static guint avatar_render_hook_id = -1;
+
+AvatarRender *avatars_avatarrender_new(MsgInfo *msginfo)
+{
+	AvatarRender *ar = g_new0(AvatarRender, 1);
+	ar->full_msginfo = msginfo;
+	ar->image = NULL;
+
+	return ar;
+}
+
+void avatars_avatarrender_free(AvatarRender *avrender)
+{
+	if (avrender == NULL)
+		return;
+
+	if (avrender->image != NULL) {
+		gtk_widget_destroy(avrender->image);
+	}
+	g_free(avrender);
+}
+
+gboolean avatars_internal_rendering_hook(gpointer source, gpointer data)
+{
+	AvatarRender *avatarr = (AvatarRender *)source;
+	gchar *aface;
+
+	if (!(prefs_common.enable_avatars | AVATARS_ENABLE_RENDER)) {
+		debug_print("Internal rendering of avatars is disabled");
+		return FALSE;
+	}
+
+	if (avatarr == NULL) {
+		g_warning("Internal rendering invoked with NULL argument");
+		return FALSE;
+	}
+
+	if (avatarr->image != NULL) {
+		g_warning("Memory leak: image widget not destroyed");
+	}
+
+	aface = procmsg_msginfo_get_avatar(avatarr->full_msginfo, AVATAR_FACE);
+	if (aface) {
+		avatarr->image = face_get_from_header(aface);
+	}
+#if HAVE_LIBCOMPFACE
+	else {
+		aface = procmsg_msginfo_get_avatar(avatarr->full_msginfo, AVATAR_XFACE);
+		if (aface) {
+			avatarr->image = xface_get_from_header(aface);
+		}
+	}
+#endif
+	return FALSE;
+}
+
+void avatars_init(void)
+{
+	if (avatar_render_hook_id != -1) {
+		g_warning(_("Internal avatars rendering already initialized"));
+		return;
+	}
+	avatar_render_hook_id = hooks_register_hook(AVATAR_IMAGE_RENDER_HOOKLIST, avatars_internal_rendering_hook, NULL);
+	if (avatar_render_hook_id == -1) {
+		g_warning(_("Failed to register avatars internal rendering hook"));
+	}
+}
+
+void avatars_done(void)
+{
+	if (avatar_render_hook_id != -1) {
+		hooks_unregister_hook(AVATAR_IMAGE_RENDER_HOOKLIST, avatar_render_hook_id);
+		avatar_render_hook_id = -1;
+	}
+}
+
diff --git a/src/avatars.h b/src/avatars.h
new file mode 100644
index 0000000..d6f304a
--- /dev/null
+++ b/src/avatars.h
@@ -0,0 +1,47 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2014 Ricardo Mones and the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __AVATARS_H__
+#define __AVATARS_H__
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "proctypes.h"
+
+#define AVATAR_IMAGE_RENDER_HOOKLIST "avatar_image_render"
+
+typedef struct _AvatarRender	AvatarRender;
+
+struct _AvatarRender
+{
+	MsgInfo *full_msginfo;
+	GtkWidget *image;
+};
+
+AvatarRender *avatars_avatarrender_new		(MsgInfo *msginfo);
+void avatars_avatarrender_free			(AvatarRender *avrender);
+
+gboolean avatars_internal_rendering_hook	(gpointer source,
+						 gpointer data);
+
+void avatars_init				(void);
+void avatars_done				(void);
+
+#endif
diff --git a/src/main.c b/src/main.c
index c7d3eac..70f8da4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -126,6 +126,7 @@
 #include "menu.h"
 #include "quicksearch.h"
 #include "advsearch.h"
+#include "avatars.h"
 
 #ifdef HAVE_LIBETPAN
 #include "imap-thread.h"
@@ -1403,6 +1404,7 @@ int main(int argc, char *argv[])
 
 	claws_register_idle_function(claws_gtk_idle);
 
+	avatars_init();
 	prefs_toolbar_init();
 
 	num_folder_class = g_list_length(folder_get_list());
@@ -1655,6 +1657,7 @@ static void exit_claws(MainWindow *mainwin)
 
 	matcher_done();
 	prefs_toolbar_done();
+	avatars_done();
 
 #ifndef USE_NEW_ADDRBOOK
 	addressbook_destroy();

commit a3ec21768c199ad01785f8ec177cf60470824759
Author: Ricardo Mones <ricardo at mones.org>
Date:   Wed Feb 12 23:56:32 2014 +0100

    New hooklist to collect avatar data from headers
    
    Also:
     • Refactorize X-Face/Face capture as an internal plugin.
     • Add hidden preference ‘enable_avatars’ to control the internal
       capture/render process, and which allows disabling it by external
       plugins for example.

diff --git a/manual/advanced.xml b/manual/advanced.xml
index dfcd319..5d4cb67 100644
--- a/manual/advanced.xml
+++ b/manual/advanced.xml
@@ -630,6 +630,22 @@
 	</listitem>
       </varlistentry>
       <varlistentry>
+	<term><literal>enable_avatars</literal></term>
+	<listitem>
+	  <para>
+	Enables capture and/or rendering of internal avatars (Face and
+	also X-Face headers if built with compface support). 
+	'0' disables both, '1' enables capture only, '2' enables rendering
+	only and '3' enables both.
+	  </para>
+	  <para>
+        Note that external plugins already providing these features may
+	disable partially or completely this to speed up process, regardless
+	of the configured value.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
 	<term><literal>enable_dotted_lines</literal></term>
 	<listitem>
 	  <para>
diff --git a/src/prefs_common.c b/src/prefs_common.c
index e2c676b..93fcce6 100644
--- a/src/prefs_common.c
+++ b/src/prefs_common.c
@@ -1177,6 +1177,7 @@ static PrefParam param[] = {
 	 NULL, NULL, NULL},
 	{"address_search_wildcard", "TRUE", &prefs_common.address_search_wildcard, P_BOOL,
 	 NULL, NULL, NULL},
+	{"enable_avatars", "3", &prefs_common.enable_avatars, P_INT, NULL, NULL, NULL},
 
 	{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
 };
diff --git a/src/prefs_common.h b/src/prefs_common.h
index cc89e33..37ccfe6 100644
--- a/src/prefs_common.h
+++ b/src/prefs_common.h
@@ -102,6 +102,14 @@ typedef enum
 	SHOW_BOTH
 } SummaryFromShow;
 
+typedef enum
+{
+	AVATARS_DISABLE = 0,
+	AVATARS_ENABLE_CAPTURE = 1,
+	AVATARS_ENABLE_RENDER = 2,
+	AVATARS_ENABLE_BOTH = 3
+} EnableAvatars;
+
 struct _PrefsCommon
 {
 	/* Receive */
@@ -522,6 +530,8 @@ struct _PrefsCommon
 	
 	gboolean folder_search_wildcard;
 	gboolean address_search_wildcard;
+
+	guint enable_avatars;
 };
 
 extern PrefsCommon prefs_common;
diff --git a/src/procheader.c b/src/procheader.c
index 2acafb8..4b7ff05 100644
--- a/src/procheader.c
+++ b/src/procheader.c
@@ -38,6 +38,7 @@
 #include "procmsg.h"
 #include "codeconv.h"
 #include "prefs_common.h"
+#include "hooks.h"
 #include "utils.h"
 #include "defs.h"
 
@@ -462,17 +463,37 @@ MsgInfo *procheader_parse_stream(FILE *fp, MsgFlags flags, gboolean full,
 	return parse_stream(fp, FALSE, flags, full, decrypted);
 }
 
+static gboolean avatar_from_some_face(gpointer source, gpointer userdata)
+{
+	AvatarCaptureData *acd = (AvatarCaptureData *)source;
+	
+	if (*(acd->content) == '\0') /* won't be null, but may be empty */
+		return FALSE;
+
+	if (!strcmp(acd->header, hentry_full[H_FACE].name)) {
+		debug_print("avatar_from_some_face: found 'Face' header\n");
+		procmsg_msginfo_add_avatar(acd->msginfo, AVATAR_FACE, acd->content);
+	}
+#if HAVE_LIBCOMPFACE
+	else if (!strcmp(acd->header, hentry_full[H_X_FACE].name)) {
+		debug_print("avatar_from_some_face: found 'X-Face' header\n");
+		procmsg_msginfo_add_avatar(acd->msginfo, AVATAR_XFACE, acd->content);
+	}
+#endif
+	return FALSE;
+}
+
 static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
 			     gboolean full, gboolean decrypted)
 {
 	MsgInfo *msginfo;
-	MsgInfoAvatar *avatar;
 	gchar buf[BUFFSIZE];
 	gchar *p, *tmp;
 	gchar *hp;
 	HeaderEntry *hentry;
 	gint hnum;
 	void *orig_data = data;
+	guint hook_id = -1;
 
 	get_one_field_func get_one_field =
 		isstring ? (get_one_field_func)string_get_one_field
@@ -510,6 +531,10 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
 	
 	msginfo->inreplyto = NULL;
 
+	if (prefs_common.enable_avatars | AVATARS_ENABLE_CAPTURE) {
+		hook_id = hooks_register_hook(AVATAR_HEADER_UPDATE_HOOKLIST, avatar_from_some_face, NULL);
+	}
+
 	while ((hnum = get_one_field(buf, sizeof(buf), data, hentry))
 	       != -1) {
 		hp = buf + strlen(hentry[hnum].name);
@@ -616,22 +641,6 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
 			MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW|MSG_UNREAD);
 			break;
 #endif			
-		case H_FACE:
-			if (!msginfo->extradata)
-				msginfo->extradata = g_new0(MsgInfoExtraData, 1);
-			avatar = g_new0(MsgInfoAvatar, 1);
-			avatar->avatar_id = AVATAR_FACE;
-			avatar->avatar_src = g_strdup(hp);
-			msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, avatar);
-			break;
-		case H_X_FACE:
-			if (!msginfo->extradata)
-				msginfo->extradata = g_new0(MsgInfoExtraData, 1);
-			avatar = g_new0(MsgInfoAvatar, 1);
-			avatar->avatar_id = AVATAR_XFACE;
-			avatar->avatar_src = g_strdup(hp);
-			msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, avatar);
-			break;
 		case H_DISPOSITION_NOTIFICATION_TO:
 			if (!msginfo->extradata)
 				msginfo->extradata = g_new0(MsgInfoExtraData, 1);
@@ -740,12 +749,28 @@ static MsgInfo *parse_stream(void *data, gboolean isstring, MsgFlags flags,
 		default:
 			break;
 		}
+		/* to avoid performance penalty hooklist is invoked only for
+		   headers known to be able to generate avatars */
+		if (hnum == H_FROM || hnum == H_X_FACE || hnum == H_FACE) {
+			AvatarCaptureData *acd = g_new0(AvatarCaptureData, 1);
+			/* no extra memory is wasted, hooks are expected to
+			   take care of copying members when needed */
+			acd->msginfo = msginfo;
+			acd->header  = hentry_full[hnum].name;
+			acd->content = hp;
+			hooks_invoke(AVATAR_HEADER_UPDATE_HOOKLIST, (gpointer)acd);
+			g_free(acd);
+		}
 	}
 
 	if (!msginfo->inreplyto && msginfo->references)
 		msginfo->inreplyto =
 			g_strdup((gchar *)msginfo->references->data);
 
+	if (hook_id != -1) {
+		hooks_unregister_hook(AVATAR_HEADER_UPDATE_HOOKLIST, hook_id);
+	}
+
 	return msginfo;
 }
 
diff --git a/src/procheader.h b/src/procheader.h
index adbc82a..b8e48fc 100644
--- a/src/procheader.h
+++ b/src/procheader.h
@@ -26,6 +26,8 @@
 
 #include "proctypes.h"
 
+#define AVATAR_HEADER_UPDATE_HOOKLIST "avatar_header_update"
+
 struct _HeaderEntry
 {
 	gchar	 *name;
diff --git a/src/procmsg.c b/src/procmsg.c
index 3bb41c9..767fe64 100644
--- a/src/procmsg.c
+++ b/src/procmsg.c
@@ -788,6 +788,20 @@ gchar *procmsg_msginfo_get_avatar(MsgInfo *msginfo, gint type)
 	return NULL;
 }
 
+void procmsg_msginfo_add_avatar(MsgInfo *msginfo, gint type, const gchar *data)
+{
+	MsgInfoAvatar *av;
+
+	if (!msginfo->extradata)
+		msginfo->extradata = g_new0(MsgInfoExtraData, 1);
+
+	av = g_new0(MsgInfoAvatar, 1);
+	av->avatar_id = type;
+	av->avatar_src = g_strdup(data);
+
+	msginfo->extradata->avatars = g_slist_append(msginfo->extradata->avatars, av);
+}
+
 gchar *procmsg_msginfo_get_identifier(MsgInfo *msginfo)
 {
 	gchar *folder_id;
diff --git a/src/procmsg.h b/src/procmsg.h
index 14d147e..52b04c0 100644
--- a/src/procmsg.h
+++ b/src/procmsg.h
@@ -285,6 +285,13 @@ struct _MailFilteringData
 	PrefsAccount *account;
 };
 
+struct	_AvatarCaptureData
+{
+	MsgInfo *msginfo;
+	const gchar *header;
+	const gchar *content;
+};
+
 GSList *procmsg_read_cache		(FolderItem	*item,
 					 gboolean	 scan_file);
 void	procmsg_msg_list_free		(MsgInfoList	*mlist);
@@ -397,4 +404,5 @@ MsgInfo *procmsg_get_msginfo_from_identifier(const gchar *id);
 gchar *procmsg_msginfo_get_identifier(MsgInfo *msginfo);
 
 gchar *procmsg_msginfo_get_avatar(MsgInfo *msginfo, gint type);
+void procmsg_msginfo_add_avatar(MsgInfo *msginfo, gint type, const gchar *data);
 #endif /* __PROCMSG_H__ */
diff --git a/src/proctypes.h b/src/proctypes.h
index fd080c7..ef6ec58 100644
--- a/src/proctypes.h
+++ b/src/proctypes.h
@@ -40,6 +40,9 @@ typedef struct _MsgInfoUpdate 		MsgInfoUpdate;
 struct _MailFilteringData;
 typedef struct _MailFilteringData	MailFilteringData;
 
+struct _AvatarCaptureData;
+typedef struct _AvatarCaptureData	AvatarCaptureData;
+
 struct _MsgInfoExtraData;
 typedef struct _MsgInfoExtraData	MsgInfoExtraData;
 

-----------------------------------------------------------------------

Summary of changes:
 manual/advanced.xml         |   16 ++++++
 src/Makefile.am             |    2 +
 src/avatars.c               |  110 ++++++++++++++++++++++++++++++++++++++
 src/{wizard.h => avatars.h} |   29 +++++++---
 src/headerview.c            |   90 ++++++++-----------------------
 src/main.c                  |    3 ++
 src/messageview.c           |   28 ++++------
 src/prefs_common.c          |    1 +
 src/prefs_common.h          |   10 ++++
 src/procheader.c            |   59 +++++++++++++++------
 src/procheader.h            |    2 +
 src/procmsg.c               |   14 +++++
 src/procmsg.h               |    8 +++
 src/proctypes.h             |    3 ++
 src/summaryview.c           |   28 ++++------
 src/textview.c              |  123 +++++++++----------------------------------
 16 files changed, 300 insertions(+), 226 deletions(-)
 create mode 100644 src/avatars.c
 copy src/{wizard.h => avatars.h} (58%)


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list