Index: src/balsa-message.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-message.c,v
retrieving revision 1.174
diff -u -r1.174 balsa-message.c
--- src/balsa-message.c	2001/08/10 13:40:52	1.174
+++ src/balsa-message.c	2001/08/21 11:53:23
@@ -53,6 +53,14 @@
 
 #define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
 
+#ifndef GNOME_EXEC_WORKS
+#include <sys/types.h>
+#include <sys/wait.h>
+#define gnome_execute_async(dir, argc, argv) _gnome_execute_async((dir), (argc), (argv)) 
+#define gnome_execute_shell(dir, cmd) _gnome_execute_shell((dir), (cmd))
+#define gnome_url_show(url) _gnome_url_show((url))
+#endif
+
 enum {
     SELECT_PART,
     LAST_SIGNAL,
@@ -1045,6 +1053,172 @@
 
 
 /* HELPER FUNCTIONS ----------------------------------------------- */
+static int _gnome_execute_async(const char *dir, int argc, char * const argv[])
+{
+    pid_t child;
+
+    if((child=fork())==0) {
+	pid_t grand_child;
+
+	if((grand_child=fork())==0) {
+#ifdef _NO_SYSTEM
+	    if(dir) chdir(dir);
+	    
+	    execvp(argv[0], argv);	/* **** But this is what fails... */
+	    _exit(1);		/* If exec fails */
+#else
+	    char cmd[PATH_MAX+1];
+	    int i;
+	
+	    if(dir) chdir(dir);
+	    
+	    cmd[0]='\0';
+	    for(i=0; i<argc && argv[i]; i++) {
+		strncat(cmd, "'", sizeof(cmd));
+		strncat(cmd, argv[i], sizeof(cmd));
+		strncat(cmd, "' ", sizeof(cmd));
+	    }
+	    system(cmd);
+	    _exit(0);
+#endif /* _NO_SYSTEM */
+	}
+	_exit(0);
+
+    } else if(child>0) {
+	waitpid(child, NULL, 0);
+    }
+	
+    return child;
+}
+
+
+static int _gnome_execute_shell(const char *dir, const char *cmd) 
+{
+    char *shell=gnome_util_user_shell(), *argv[4];
+    int status;
+    
+    g_return_val_if_fail(cmd != NULL, -1);
+
+    argv[0]=shell;
+    argv[1]="-c";
+    argv[2]=(char *)cmd;
+    argv[3]=NULL;
+	
+    status=gnome_execute_async(dir, 4, argv);
+    
+    g_free(shell);
+
+    return status;
+}
+
+#define DEFAULT_HANDLER "gnome-moz-remote --newwin \"%s\""
+
+static gchar *gnome_url_default_handler ()
+{
+	static gchar *default_handler = 0;
+	
+	if (!default_handler) {
+		gchar *str, *app;
+		gboolean def;
+		str = gnome_config_get_string_with_default ("/Gnome/URL Handlers/default-show",
+							    &def);
+		if (def) {
+			app = gnome_is_program_in_path ("nautilus");
+			if (app) {
+				g_free (app);
+				app = "nautilus \"%s\"";
+			} else
+				app = "gnome-help-browser \"%s\"";
+
+			/* first time gnome_url_show is run -- set up some useful defaults */
+			default_handler = DEFAULT_HANDLER;
+			gnome_config_set_string ("/Gnome/URL Handlers/default-show", default_handler);
+
+			g_free (gnome_config_get_string_with_default(
+				"/Gnome/URL Handlers/info-show", &def));
+			if (def)
+				gnome_config_set_string ("/Gnome/URL Handlers/info-show", app);
+			g_free (gnome_config_get_string_with_default(
+				"/Gnome/URL Handlers/man-show", &def));
+			if (def)
+				gnome_config_set_string ("/Gnome/URL Handlers/man-show", app);
+			g_free (gnome_config_get_string_with_default(
+				"/Gnome/URL Handlers/ghelp-show", &def));
+			if (def)
+				gnome_config_set_string ("/Gnome/URL Handlers/ghelp-show", app);
+
+			gnome_config_sync_file ("/Gnome/");
+		} else
+			default_handler = str;
+	}
+	return default_handler;
+}
+
+static void _gnome_url_show(const gchar *url)
+{
+	gint i;
+	gchar *pos, *template;
+	gboolean free_template = FALSE;
+	int argc;
+       	char **argv;
+	
+	g_return_if_fail (url != NULL);
+	pos = strchr (url, ':');
+
+	if (pos){
+		gchar *protocol, *path;
+		gboolean def;
+		
+		g_return_if_fail (pos >= url);
+		protocol = g_new (gchar, pos - url + 1);
+		strncpy (protocol, url, pos - url);
+		protocol [pos - url] = '\0';
+		g_strdown (protocol);
+		
+		path = g_strconcat ("/Gnome/URL Handlers/", protocol, "-show", NULL);
+		template = gnome_config_get_string_with_default (path, &def);
+		g_free (path);
+		if (def)
+		    template = gnome_url_default_handler ();
+		else
+			free_template = TRUE;
+		g_free (protocol);
+	} else /* no : ? -- this shouldn't happen.  Use default handler */
+		template = gnome_url_default_handler ();
+
+	/* we use a popt function as it does exactly what we want to do and
+	   gnome already uses popt */
+	if(poptParseArgvString(template, &argc, &argv) != 0) {
+		/* can't parse */
+		g_warning("Parse error of '%s'", template);
+		return;
+	}
+
+	/* we can just replace the entry in the array since the
+	 * array is all in one buffer, we won't leak */
+	for(i = 0; i < argc; i++) {
+		if(strcmp(argv[i], "%s") == 0)
+			/* we can safely cast as it will not get freed nor
+			 * modified */
+			argv[i] = (char *)url;
+	}
+
+	/* use execute async, and not the shell, shell is evil and a
+	 * security hole */
+	gnome_execute_async (NULL, argc, argv);
+
+	if (free_template)
+		g_free (template);
+
+	/* the way the poptParseArgvString works is that the entire thing
+	 * is allocated as one buffer, so just free will suffice, also
+	 * it must be free and not g_free */
+	free(argv);
+}
+
+
+
+
 static GdkFont*
 find_body_font(LibBalsaMessageBody * body)
 {
@@ -1579,7 +1753,6 @@
 }
 
 /* END OF HELPER FUNCTIONS ----------------------------------------------- */
-
 static void
 part_info_init_mimetext(BalsaMessage * bm, BalsaPartInfo * info)
 {
@@ -1631,10 +1804,18 @@
     if (ishtml) {
 #ifdef HAVE_GTKHTML
 	part_info_init_html(bm, info, ptr, alloced);
+	g_free(ptr);
+	ptr=NULL;
 #else
+	char *html=convert_html(ptr);;
+	
 	part_info_init_unknown(bm, info);
+
+	g_free(ptr);
+	ptr=html;
 #endif
-    } else {
+    } 
+    if(ptr) {
 	regex_t rex;
 	GtkWidget *item = NULL;
 	GdkFont *fnt = NULL;
@@ -1723,10 +1904,13 @@
 	
 	gtk_widget_show(item);
 	info->focus_widget = item;
-	info->widget = item;
+	if(info->widget && GTK_IS_BOX(info->widget))
+	    gtk_box_pack_end(GTK_BOX(info->widget), item, FALSE, FALSE, 2);
+	else 
+	    info->widget = item;
 	info->can_display = TRUE;
+	g_free(ptr);
     }
-    g_free(ptr);
     
     fclose(fp);
 }
Index: libbalsa/mime.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/mime.c,v
retrieving revision 1.38
diff -u -r1.38 mime.c
--- libbalsa/mime.c	2000/10/06 15:50:51	1.38
+++ libbalsa/mime.c	2001/08/21 11:53:23
@@ -21,6 +21,7 @@
  */
 
 #include <string.h>
+#include  <ctype.h>
 #include "config.h"
 
 #include "libbalsa.h"
@@ -36,6 +37,133 @@
 				  LibBalsaMessageBody * body,
 				  gchar * reply_prefix_str, gint llen);
 
+static gchar char_ref_char(const gchar *char_ref) 
+{
+    if(char_ref[1]=='#')
+	return (gchar )atoi(char_ref+1);
+    /* These are essential: */
+    else if(g_strcasecmp(char_ref, "lt")==0)
+	return '<';
+    else if(g_strcasecmp(char_ref, "gt")==0)
+	return '>';
+    else if(g_strcasecmp(char_ref, "amp")==0)
+	return '&';
+    else if(g_strcasecmp(char_ref, "nbsp")==0)
+	return ' ';
+    /* Some special characters I'm are using a lot... */
+    else if(strcmp(char_ref, "aelig")==0)
+	return 'æ';
+    else if(strcmp(char_ref, "AElig")==0)
+	return 'Æ';
+    else if(strcmp(char_ref, "oslash")==0)
+	return 'ø';
+    else if(strcmp(char_ref, "Oslash")==0)
+	return 'Ø';
+    else if(strcmp(char_ref, "aring")==0)
+	return 'å';
+    else if(strcmp(char_ref, "Aring")==0)
+	return 'Å';
+    /* Return first character for the rest. Often makes sense because reference
+       is "<character base><info on accent etc.>" */
+    return char_ref[0];
+}
+
+static gchar *extract_tag(gchar **html, gchar end_sep)
+/* Pre : *html is at start of tag, i.e. points to '<' or similar
+   Post: *html points to position after end of tag. */
+{
+    gchar *end=strchr(*html, end_sep), *tag;
+
+    if(!end)			/* No '>', skip rest of string. */
+	end=*html+strlen(*html);
+    
+    tag=g_strndup(*html+1, end-*html-1);
+    *html=end+1;
+    
+    return tag;
+}
+
+gchar *convert_html(const gchar *html)
+/* Remarks: This is just a quick hack - look for external library routine 
+            that will do this */
+{
+    gchar *txt=calloc(strlen(html)+1, sizeof(gchar));
+
+    if(txt) {
+	gchar *c_html=(gchar *)html, *c_txt=txt;
+	gboolean skip=FALSE;
+
+	while(*c_html) {
+	    if(*c_html=='<') {
+		gchar *tag=extract_tag(&c_html, '>');
+		
+		if(g_strncasecmp(tag, "head", 4)==0) {
+		    skip=TRUE;
+		} else if(g_strncasecmp(tag, "body", 4)==0) {
+		    skip=FALSE;
+		} 
+
+		if(!skip) {
+		    if(g_strcasecmp(tag, "br")==0 || 
+		       g_strcasecmp(tag, "tr")==0) {
+			*c_txt++='\n';
+		    } else if(g_strcasecmp(tag, "p")==0 ||
+			      (tolower(tag[0])=='h' && isdigit(tag[1]))) {
+			*c_txt++='\n';
+			*c_txt++='\n';
+		    } else if(g_strcasecmp(tag, "li")==0) {
+			*c_txt++='\n';
+			*c_txt++='*';
+			*c_txt++='\t';
+		    } else if(g_strcasecmp(tag, "td")==0 || 
+			      g_strcasecmp(tag, "th")==0) {
+		     /* Note: Can't do a lot more than starting a new
+			      paragraph (more or less), since we are not
+			      able to interleave text from different cells. */
+			*c_txt++='\n';
+			*c_txt++='\n';
+			*c_txt++='\t';
+		    } else {
+			gchar *ref=strstr(tag, "href=");
+		    
+			if(!ref) { /* *** Want 'strcasestr' */
+			    ref=strstr(tag, "HREF=");
+			}
+		    
+			if(ref) {
+			    *c_txt++='[';
+			    ref+=5;
+			    
+			    while(*ref && *ref!=' ')
+				*c_txt++=*ref++;
+			    *c_txt++=']';
+			}
+		    }
+		}
+		g_free(tag);
+	    } else if(skip) {
+		c_html++;
+	    } else if(*c_html=='&') {
+		gchar *char_ref=extract_tag(&c_html, ';');
+
+		*c_txt++=char_ref_char(char_ref);
+		g_free(char_ref);
+	    } else if(*c_html=='\n' || *c_html==' ' || *c_html=='\t') {
+		gchar prev=*(c_txt-1);
+
+		c_html++;
+		
+		if(c_txt!=txt && prev!=' ' && prev!='\n' && prev!='\t')
+		    *c_txt++=' ';
+	    } else {
+		*c_txt++=*c_html++;
+	    }
+	}
+    }
+    return txt;
+}
+
+
 static GString *
 process_mime_part(LibBalsaMessage * message, LibBalsaMessageBody * body,
 		  gchar * reply_prefix_str, gint llen)
@@ -44,7 +172,10 @@
     size_t alloced;
     gchar *res = NULL;
     GString *reply = NULL;
+    gchar *content_type = libbalsa_message_body_get_content_type(body);
+    gboolean ishtml=(g_strcasecmp(content_type, "text/html") == 0);
 
+    
     switch (libbalsa_message_body_type(body)) {
     case LIBBALSA_MESSAGE_BODY_TYPE_OTHER:
     case LIBBALSA_MESSAGE_BODY_TYPE_AUDIO:
@@ -68,6 +199,17 @@
 	fclose(part);
 	if (!res)
 	    break;
+
+	if(ishtml) {
+	    gchar *res_ascii=convert_html(res);
+	    
+	    if(res_ascii) {
+		g_free(res);
+		res=res_ascii;
+	    }
+	}
+	    
+
 	if (llen > 0) {
 	    if (reply_prefix_str)
 		llen -= strlen(reply_prefix_str);
@@ -93,6 +235,8 @@
 	g_free(res);
 	break;
     }
+    g_free(content_type);	
+
     return reply;
 }
 
Index: libbalsa/mime.h
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/mime.h,v
retrieving revision 1.13
diff -u -r1.13 mime.h
--- libbalsa/mime.h	2000/10/06 15:50:51	1.13
+++ libbalsa/mime.h	2001/08/21 11:53:23
@@ -27,6 +27,7 @@
 
 #include "libbalsa.h"
 
+gchar *convert_html(const gchar *html);
 GString *content2reply(LibBalsaMessage * message,
 		       gchar * reply_prefix_str, gint llen);	/* arp */
 
