[evolution] Highlighting of text parts and source codes



commit 8663b54cae296883452850f3baad6d4cbc92e220
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Jul 25 11:29:22 2012 +0200

    Highlighting of text parts and source codes
    
    This adds 'Format as' submenu to the preview pane context menu.
    The submenu is available only for text/plain parts or parts
    with a source code (we support about 40 various types). Using
    the 'highlight' utility, the formatter processes the part and
    highlights the source code it contains.
    
    (discussion in bug #680026)

 em-format/e-mail-formatter.h                       |    2 +
 em-format/e-mail-parser-text-plain.c               |    3 +-
 mail/e-mail-display.c                              |    6 +
 mail/e-mail-request.c                              |   24 +-
 modules/text-highlight/Makefile.am                 |   16 +-
 .../e-mail-display-popup-text-highlight.c          |  370 ++++++++++++++
 ...ght.h => e-mail-display-popup-text-highlight.h} |   10 +-
 ...ghlight.c => e-mail-formatter-text-highlight.c} |  127 ++++-
 ...ghlight.h => e-mail-formatter-text-highlight.h} |    0
 .../text-highlight/e-mail-parser-text-highlight.c  |  159 ++++++
 ...-highlight.h => e-mail-parser-text-highlight.h} |   10 +-
 .../evolution-module-text-highlight.c              |    7 +-
 modules/text-highlight/languages.c                 |  529 ++++++++++++++++++++
 .../{text-highlight.h => languages.h}              |   25 +-
 14 files changed, 1226 insertions(+), 62 deletions(-)
---
diff --git a/em-format/e-mail-formatter.h b/em-format/e-mail-formatter.h
index c0c21c1..9b4e84d 100644
--- a/em-format/e-mail-formatter.h
+++ b/em-format/e-mail-formatter.h
@@ -96,6 +96,8 @@ struct _EMailFormatterContext {
 
 	EMailFormatterMode mode;
 	guint32 flags;
+
+	gchar *uri;
 };
 
 struct _EMailFormatter {
diff --git a/em-format/e-mail-parser-text-plain.c b/em-format/e-mail-parser-text-plain.c
index 00a7b53..1795d01 100644
--- a/em-format/e-mail-parser-text-plain.c
+++ b/em-format/e-mail-parser-text-plain.c
@@ -98,8 +98,7 @@ process_part (EMailParser *parser,
 	}
 
 	type = camel_mime_part_get_content_type (part);
-	if (camel_content_type_is (type, "text", "*") &&
-		(!camel_content_type_is (type, "text", "calendar"))) {
+	if (!camel_content_type_is (type, "text", "calendar")) {
 
 		g_string_append_printf (part_id, ".plain_text.%d", part_number);
 
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index be99ea2..6cbbaa6 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -177,6 +177,12 @@ mail_display_button_press_event (GtkWidget *widget,
 	GList *extensions, *iter;
 	EWebView *web_view = E_WEB_VIEW (widget);
 
+	if (event->button != 3) {
+		return GTK_WIDGET_CLASS (
+			e_mail_display_parent_class)->button_press_event (
+				widget, event);
+	}
+
 	hit_test = webkit_web_view_get_hit_test_result (
 			WEBKIT_WEB_VIEW (web_view), event);
 
diff --git a/mail/e-mail-request.c b/mail/e-mail-request.c
index 0f185c2..aee9c9c 100644
--- a/mail/e-mail-request.c
+++ b/mail/e-mail-request.c
@@ -54,6 +54,7 @@ struct _EMailRequestPrivate {
 
 	GHashTable *uri_query;
 	gchar *uri_base;
+	gchar *full_uri;
 
         gchar *ret_mime_type;
 };
@@ -105,6 +106,7 @@ handle_mail_request (GSimpleAsyncResult *res,
 	context.message_uid = part_list->message_uid;
 	context.folder = part_list->folder;
 	context.parts = part_list->list;
+	context.uri = request->priv->full_uri;
 
 	if (context.mode == E_MAIL_FORMATTER_MODE_PRINTING)
 		formatter = e_mail_formatter_print_new ();
@@ -285,25 +287,22 @@ mail_request_finalize (GObject *object)
 
 	g_clear_object (&request->priv->output_stream);
 
-	if (request->priv->mime_type) {
-		g_free (request->priv->mime_type);
-		request->priv->mime_type = NULL;
-	}
+	g_free (request->priv->mime_type);
+	request->priv->mime_type = NULL;
 
 	if (request->priv->uri_query) {
 		g_hash_table_destroy (request->priv->uri_query);
 		request->priv->uri_query = NULL;
 	}
 
-	if (request->priv->ret_mime_type) {
-		g_free (request->priv->ret_mime_type);
-		request->priv->ret_mime_type = NULL;
-	}
+	g_free (request->priv->ret_mime_type);
+	request->priv->ret_mime_type = NULL;
 
-	if (request->priv->uri_base) {
-		g_free (request->priv->uri_base);
-		request->priv->uri_base = NULL;
-	}
+	g_free (request->priv->uri_base);
+	request->priv->uri_base = NULL;
+
+	g_free (request->priv->full_uri);
+	request->priv->full_uri = NULL;
 
 	G_OBJECT_CLASS (e_mail_request_parent_class)->finalize (object);
 }
@@ -337,6 +336,7 @@ mail_request_send_async (SoupRequest *request,
 		emr->priv->uri_query = NULL;
 	}
 
+	emr->priv->full_uri = soup_uri_to_string (uri, FALSE);
 	uri_str = g_strdup_printf (
 		"%s://%s%s", uri->scheme, uri->host, uri->path);
 	emr->priv->uri_base = uri_str;
diff --git a/modules/text-highlight/Makefile.am b/modules/text-highlight/Makefile.am
index 9b27298..8c7e639 100644
--- a/modules/text-highlight/Makefile.am
+++ b/modules/text-highlight/Makefile.am
@@ -9,10 +9,16 @@ module_text_highlight_la_CPPFLAGS =					\
 	$(EVOLUTION_DATA_SERVER_CFLAGS)					\
 	$(GNOME_PLATFORM_CFLAGS)
 
-module_text_highlight_la_SOURCES =				\
-	text-highlight.c					\
-	text-highlight.h					\
-	evolution-module-text-highlight.c
+module_text_highlight_la_SOURCES =					\
+	e-mail-display-popup-text-highlight.c				\
+	e-mail-display-popup-text-highlight.h				\
+	e-mail-formatter-text-highlight.c				\
+	e-mail-formatter-text-highlight.h				\
+	e-mail-parser-text-highlight.c					\
+	e-mail-parser-text-highlight.h					\
+	evolution-module-text-highlight.c				\
+	languages.c							\
+	languages.h
 
 module_text_highlight_la_LIBADD =					\
 	$(top_builddir)/e-util/libeutil.la				\
@@ -21,7 +27,7 @@ module_text_highlight_la_LIBADD =					\
 	$(EVOLUTION_DATA_SERVER_LIBS)					\
 	$(GNOME_PLATFORM_LIBS)
 
-module_text_highlight_la_LDFLAGS =				\
+module_text_highlight_la_LDFLAGS =					\
 	-avoid-version -module $(NO_UNDEFINED)
 
 -include $(top_srcdir)/git.mk
diff --git a/modules/text-highlight/e-mail-display-popup-text-highlight.c b/modules/text-highlight/e-mail-display-popup-text-highlight.c
new file mode 100644
index 0000000..0adea1d
--- /dev/null
+++ b/modules/text-highlight/e-mail-display-popup-text-highlight.c
@@ -0,0 +1,370 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "e-mail-display-popup-text-highlight.h"
+#include "mail/e-mail-display-popup-extension.h"
+#include "mail/e-mail-display.h"
+#include <shell/e-shell.h>
+#include <shell/e-shell-window.h>
+#include "mail/e-mail-browser.h"
+
+#include <libebackend/libebackend.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "languages.h"
+
+#define d(x)
+
+typedef struct _EMailDisplayPopupTextHighlight {
+	EExtension parent;
+
+	GtkActionGroup *action_group;
+
+	WebKitDOMDocument *document;
+} EMailDisplayPopupTextHighlight;
+
+typedef struct _EMailDisplayPopupTextHighlightClass {
+	EExtensionClass parent_class;
+} EMailDisplayPopupTextHighlightClass;
+
+#define E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), e_mail_display_popup_text_highlight_get_type(), EMailDisplayPopupTextHighlight))
+
+GType e_mail_display_popup_text_highlight_get_type (void);
+static void e_mail_display_popup_extension_interface_init (EMailDisplayPopupExtensionInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailDisplayPopupTextHighlight,
+	e_mail_display_popup_text_highlight,
+	E_TYPE_EXTENSION,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION,
+		e_mail_display_popup_extension_interface_init));
+
+static const gchar *ui =
+"<ui>"
+"  <popup name='context'>"
+"    <placeholder name='custom-actions-2'>"
+"      <separator />"
+"      <menu action='format-as-menu'>"
+"	 <placeholder name='format-as-actions' />"
+"	 <menu action='format-as-other-menu'>"
+"	 </menu>"
+"      </menu>"
+"    </placeholder>"
+"  </popup>"
+"</ui>";
+
+static const gchar *ui_reader =
+"<ui>"
+"  <popup name='mail-preview-popup'>"
+"    <placeholder name='mail-preview-popup-actions'>"
+"      <separator />"
+"      <menu action='format-as-menu'>"
+"	 <placeholder name='format-as-actions' />"
+"	 <menu action='format-as-other-menu'>"
+"	 </menu>"
+"      </menu>"
+"    </placeholder>"
+"  </popup>"
+"</ui>";
+
+static GtkActionEntry entries[] = {
+
+	{ "format-as-menu",
+	  NULL,
+	  N_("_Format as..."),
+	  NULL,
+	  NULL,
+	  NULL
+	},
+
+	{ "format-as-other-menu",
+	  NULL,
+	  N_("_Other languages"),
+	  NULL,
+	  NULL,
+	  NULL
+	}
+};
+
+static void
+reformat (GtkAction *old,
+	  GtkAction *action,
+	  gpointer user_data)
+{
+	EMailDisplayPopupTextHighlight *th_extension;
+	WebKitDOMDocument *doc;
+	WebKitDOMDOMWindow *window;
+	WebKitDOMElement *frame_element;
+	SoupURI *soup_uri;
+	GHashTable *query;
+	gchar *uri;
+
+
+	th_extension = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (user_data);
+	doc = th_extension->document;
+	if (!doc)
+		return;
+
+	uri = webkit_dom_document_get_document_uri (doc);
+	soup_uri = soup_uri_new (uri);
+	g_free (uri);
+
+	if (!soup_uri)
+		return;
+
+	if (!soup_uri->query) {
+		soup_uri_free (soup_uri);
+		return;
+	}
+
+	query = soup_form_decode (soup_uri->query);
+	g_hash_table_replace (
+		query, g_strdup ("__formatas"), (gpointer) gtk_action_get_name (action));
+
+	soup_uri_set_query_from_form (soup_uri, query);
+	g_hash_table_destroy (query);
+
+	uri = soup_uri_to_string (soup_uri, FALSE);
+	soup_uri_free (soup_uri);
+
+	/* Get frame's window and from the window the actual <iframe> element */
+	window = webkit_dom_document_get_default_view (doc);
+	frame_element = webkit_dom_dom_window_get_frame_element (window);
+	webkit_dom_html_iframe_element_set_src (
+		WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame_element), uri);
+
+	g_free (uri);
+
+	/* The frame has been reloaded, the document pointer is invalid now */
+	th_extension->document = NULL;
+}
+
+static GtkActionGroup*
+create_group (EMailDisplayPopupExtension *extension)
+{
+	EExtensible *extensible;
+	EWebView *web_view;
+	GtkUIManager *ui_manager, *shell_ui_manager;
+	GtkActionGroup *group;
+	EShell *shell;
+	GtkWindow *shell_window;
+	gint i;
+	gsize len;
+	guint merge_id, shell_merge_id;
+	Language *languages;
+	GSList *radio_group;
+	gint action_index;
+
+	extensible = e_extension_get_extensible (E_EXTENSION (extension));
+	web_view = E_WEB_VIEW (extensible);
+
+	ui_manager = e_web_view_get_ui_manager (web_view);
+	shell = e_shell_get_default ();
+	shell_window = e_shell_get_active_window (shell);
+	if (E_IS_SHELL_WINDOW (shell_window)) {
+		shell_ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (shell_window));
+	} else if (E_IS_MAIL_BROWSER (shell_window)) {
+		shell_ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (shell_window));
+	} else {
+		return NULL;
+	}
+
+	group = gtk_action_group_new ("format-as");
+	gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), NULL);
+
+	gtk_ui_manager_insert_action_group (ui_manager, group, 0);
+	gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL);
+
+	gtk_ui_manager_insert_action_group (shell_ui_manager, group, 0);
+	gtk_ui_manager_add_ui_from_string (shell_ui_manager, ui_reader, -1, NULL);
+
+	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
+	shell_merge_id = gtk_ui_manager_new_merge_id (shell_ui_manager);
+
+	languages = get_default_langauges (&len);
+	radio_group = NULL;
+	action_index = 0;
+	for (i = 0; i < len; i++) {
+
+		GtkRadioAction *action;
+		action = gtk_radio_action_new (
+				languages[i].action_name,
+				languages[i].action_label,
+				NULL, NULL, action_index);
+		action_index++;
+		gtk_action_group_add_action (group, GTK_ACTION (action));
+		g_signal_connect (action, "changed",
+			G_CALLBACK (reformat), extension);
+		gtk_radio_action_set_group (action, radio_group);
+		radio_group = gtk_radio_action_get_group (action);
+
+		g_object_unref (action);
+
+		gtk_ui_manager_add_ui (
+			ui_manager, merge_id,
+			 "/context/custom-actions-2/format-as-menu/format-as-actions",
+			languages[i].action_name, languages[i].action_name,
+			 GTK_UI_MANAGER_AUTO, FALSE);
+
+		gtk_ui_manager_add_ui (
+			shell_ui_manager, shell_merge_id,
+			"/mail-preview-popup/mail-preview-popup-actions/format-as-menu/format-as-actions",
+			languages[i].action_name, languages[i].action_name,
+			 GTK_UI_MANAGER_AUTO, FALSE);
+	}
+
+	languages = get_additinal_languages (&len);
+	for (i = 0; i < len; i++) {
+		GtkRadioAction *action;
+
+		action = gtk_radio_action_new (
+				languages[i].action_name,
+				languages[i].action_label,
+				NULL, NULL, action_index);
+		action_index++;
+		gtk_action_group_add_action (group, GTK_ACTION (action));
+		g_signal_connect (action, "changed",
+			G_CALLBACK (reformat), extension);
+
+		gtk_radio_action_set_group (action, radio_group);
+		radio_group = gtk_radio_action_get_group (action);
+
+		g_object_unref (action);
+
+		gtk_ui_manager_add_ui (
+			ui_manager, merge_id,
+			 "/context/custom-actions-2/format-as-menu/format-as-other-menu",
+			languages[i].action_name, languages[i].action_name,
+			 GTK_UI_MANAGER_AUTO, FALSE);
+
+		gtk_ui_manager_add_ui (
+			shell_ui_manager, shell_merge_id,
+			"/mail-preview-popup/mail-preview-popup-actions/format-as-menu/format-as-other-menu",
+			languages[i].action_name, languages[i].action_name,
+			 GTK_UI_MANAGER_AUTO, FALSE);
+	}
+
+	return group;
+}
+
+static void
+update_actions (EMailDisplayPopupExtension *extension,
+		WebKitHitTestResult *context)
+{
+	EMailDisplayPopupTextHighlight *th_extension;
+	WebKitDOMNode *node;
+	WebKitDOMDocument *document;
+	gchar *uri;
+
+	th_extension = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (extension);
+
+	if (th_extension->action_group == NULL) {
+		th_extension->action_group = create_group(extension);
+	}
+
+	g_object_get (G_OBJECT (context), "inner-node", &node, NULL);
+	document = webkit_dom_node_get_owner_document (node);
+	uri = webkit_dom_document_get_document_uri (document);
+
+
+	/* If the part below context menu was made by text-highlight formatter,
+	 * then try to check what formatter it's using at the moment and set
+	 * it as active in the popup menu */
+	if (uri && strstr (uri, ".text-highlight") != NULL) {
+		SoupURI *soup_uri;
+		gtk_action_group_set_visible (
+			th_extension->action_group, TRUE);
+
+		soup_uri = soup_uri_new (uri);
+		if (soup_uri && soup_uri->query) {
+			GHashTable *query = soup_form_decode (soup_uri->query);
+			gchar *highlighter;
+
+			highlighter = g_hash_table_lookup (query, "__formatas");
+			if (highlighter && *highlighter) {
+				GtkAction *action = gtk_action_group_get_action (
+					th_extension->action_group, highlighter);
+				if (action) {
+					gint value;
+					g_object_get (
+						G_OBJECT (action), "value",
+						&value, NULL);
+					gtk_radio_action_set_current_value (
+						GTK_RADIO_ACTION (action), value);
+				}
+			}
+			g_hash_table_destroy (query);
+		}
+
+		if (soup_uri) {
+			soup_uri_free (soup_uri);
+		}
+
+	} else {
+		gtk_action_group_set_visible(
+			th_extension->action_group, FALSE);
+	}
+
+	/* Set the th_extension->document AFTER changing the active action to
+	 * prevent the reformat() from doing some crazy reformatting
+	 * (reformat() returns immediatelly when th_extension->document is NULL) */
+	th_extension->document = document;
+
+	g_free (uri);
+}
+
+void
+e_mail_display_popup_text_highlight_type_register (GTypeModule *type_module)
+{
+	e_mail_display_popup_text_highlight_register_type (type_module);
+}
+
+static void
+e_mail_display_popup_text_highlight_class_init (EMailDisplayPopupTextHighlightClass *klass)
+{
+	EExtensionClass *extension_class;
+
+	e_mail_display_popup_text_highlight_parent_class = g_type_class_peek_parent (klass);
+
+	extension_class = E_EXTENSION_CLASS (klass);
+	extension_class->extensible_type = E_TYPE_MAIL_DISPLAY;
+}
+
+static void
+e_mail_display_popup_extension_interface_init (EMailDisplayPopupExtensionInterface *iface)
+{
+	iface->update_actions = update_actions;
+}
+
+void
+e_mail_display_popup_text_highlight_class_finalize (EMailDisplayPopupTextHighlightClass *klass)
+{
+
+}
+
+static void
+e_mail_display_popup_text_highlight_init (EMailDisplayPopupTextHighlight *extension)
+{
+	extension->action_group = NULL;
+}
diff --git a/modules/text-highlight/text-highlight.h b/modules/text-highlight/e-mail-display-popup-text-highlight.h
similarity index 73%
copy from modules/text-highlight/text-highlight.h
copy to modules/text-highlight/e-mail-display-popup-text-highlight.h
index af10da4..003f7d9 100644
--- a/modules/text-highlight/text-highlight.h
+++ b/modules/text-highlight/e-mail-display-popup-text-highlight.h
@@ -1,5 +1,5 @@
 /*
- * text-highlight.h
+ * e-mail-display-popup-text-highlight.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,15 +16,15 @@
  *
  */
 
-#ifndef TEXT_HIGHLIGHT_H
-#define TEXT_HIGHLIGHT_H
+#ifndef E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT_H
+#define E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT_H
 
 #include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void	e_mail_formatter_text_highlight_type_register (GTypeModule *type_module);
+void e_mail_display_popup_text_highlight_type_register (GTypeModule *type_module);
 
 G_END_DECLS
 
-#endif /* TEXT_HIGHLIGHT_H */
+#endif /* E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT_H */
diff --git a/modules/text-highlight/text-highlight.c b/modules/text-highlight/e-mail-formatter-text-highlight.c
similarity index 73%
rename from modules/text-highlight/text-highlight.c
rename to modules/text-highlight/e-mail-formatter-text-highlight.c
index 26f7708..e216245 100644
--- a/modules/text-highlight/text-highlight.c
+++ b/modules/text-highlight/e-mail-formatter-text-highlight.c
@@ -20,13 +20,17 @@
 #include <config.h>
 #endif
 
-#include "text-highlight.h"
+#include "e-mail-formatter-text-highlight.h"
+#include "languages.h"
 
 #include <em-format/e-mail-formatter-extension.h>
 #include <em-format/e-mail-formatter.h>
 #include <em-format/e-mail-part-utils.h>
 #include <e-util/e-util.h>
 
+#include <shell/e-shell-settings.h>
+#include <shell/e-shell.h>
+
 #include <libebackend/libebackend.h>
 #include <libedataserver/libedataserver.h>
 
@@ -61,11 +65,8 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (
 		E_TYPE_MAIL_FORMATTER_EXTENSION,
 		e_mail_formatter_formatter_extension_interface_init));
 
-static const gchar *formatter_mime_types[] = { "text/x-diff",
-					       "text/x-patch",
-					       NULL };
-
-static gchar * get_default_font (void)
+static gchar *
+get_default_font (void)
 {
 	gchar *font;
 	GSettings *settings;
@@ -74,9 +75,61 @@ static gchar * get_default_font (void)
 
 	font = g_settings_get_string (settings, "monospace-font-name");
 
+	g_object_unref (settings);
+
 	return font ? font : g_strdup ("monospace 10");
 }
 
+static gchar *
+get_syntax (EMailPart *part,
+	    const gchar *uri)
+{
+	gchar *syntax = NULL;
+
+	if (uri) {
+		SoupURI *soup_uri = soup_uri_new (uri);
+		GHashTable *query = soup_form_decode (soup_uri->query);
+
+		syntax = g_hash_table_lookup (query, "__formatas");
+		if (syntax) {
+			syntax = g_strdup (syntax);
+		}
+		g_hash_table_destroy (query);
+		soup_uri_free (soup_uri);
+	}
+
+	/* Try to detect syntax from attachment filename extension */
+	if (syntax == NULL) {
+		const gchar *filename = camel_mime_part_get_filename (part->part);
+		if (filename) {
+			gchar *ext = g_strrstr (filename, ".");
+			if (ext) {
+				syntax = (gchar *) get_syntax_for_ext (ext + 1);
+				syntax = g_strdup (syntax ? syntax : "txt");
+			}
+		}
+	}
+
+	/* Try it by mime type */
+	if (syntax == NULL) {
+		CamelContentType *ct = camel_mime_part_get_content_type (part->part);
+		if (ct) {
+			gchar *mime_type = camel_content_type_simple (ct);
+
+			syntax = (gchar *) get_syntax_for_mime_type (mime_type);
+			syntax = g_strdup (syntax ? syntax : "txt");
+			g_free (mime_type);
+		}
+	}
+
+	/* Out of ideas - use plain text */
+	if (syntax == NULL) {
+		syntax = g_strdup ("txt");
+	}
+
+	return syntax;
+}
+
 static gboolean
 emfe_text_highlight_format (EMailFormatterExtension *extension,
                             EMailFormatter *formatter,
@@ -85,6 +138,17 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
                             CamelStream *stream,
                             GCancellable *cancellable)
 {
+	/* Don't format text/html unless it's an attachment */
+	CamelContentType *ct = camel_mime_part_get_content_type (part->part);
+	if (ct && camel_content_type_is (ct, "text", "html")) {
+		const CamelContentDisposition *disp;
+		disp = camel_mime_part_get_content_disposition (part->part);
+
+		if (!disp || g_strcmp0 (disp->disposition, "attachment") != 0)
+			return FALSE;
+	}
+
+
 	if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING) {
 
 		CamelDataWrapper *dw;
@@ -102,8 +166,7 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 		filter_stream = camel_stream_filter_new (stream);
 		mime_filter = camel_mime_filter_tohtml_new (
 				CAMEL_MIME_FILTER_TOHTML_PRE |
-				CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES,
-				0x7a7a7a);
+				CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES, 0);
 		camel_stream_filter_add (
 			CAMEL_STREAM_FILTER (filter_stream), mime_filter);
 		g_object_unref (mime_filter);
@@ -124,18 +187,19 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 		GPid pid;
 		CamelStream *read, *write;
 		CamelDataWrapper *dw;
-		gchar *font_family, *font_size;
+		gchar *font_family, *font_size, *syntax;
 		gboolean use_custom_font;
-		GSettings *settings;
+		EShell *shell;
+		EShellSettings *settings;
 		PangoFontDescription *fd;
 		const gchar *argv[] = { "highlight",
-					NULL,	/* don't move these! */
-					NULL,
+					NULL,	/* --font= */
+					NULL,   /* --font-size= */
+					NULL,   /* --syntax= */
 					"--out-format=html",
 					"--include-style",
 					"--inline-css",
 					"--style=bclear",
-					"--syntax=diff",
 					"--failsafe",
 					NULL };
 
@@ -144,9 +208,20 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 			return FALSE;
 		}
 
+		syntax = get_syntax (part, context->uri);
+
+		/* Use the traditional text/plain formatter for plain-text */
+		if (g_strcmp0 (syntax, "txt") == 0) {
+			g_free (syntax);
+			return FALSE;
+		}
+
+		shell = e_shell_get_default ();
+		settings = e_shell_get_shell_settings (shell);
+
 		fd = NULL;
-		settings = g_settings_new ("org.gnome.evolution.mail");
-		use_custom_font = g_settings_get_boolean (settings, "use-custom-font");
+		use_custom_font = e_shell_settings_get_boolean (
+					settings, "mail-use-custom-fonts");
 		if (!use_custom_font) {
 			gchar *font;
 
@@ -154,17 +229,15 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 			fd = pango_font_description_from_string (font);
 			g_free (font);
 
-			g_object_unref (settings);
-
 		} else {
 			gchar *font;
 
-			font = g_settings_get_string (settings, "monospace-font");
+			font = e_shell_settings_get_string (
+					settings, "mail-font-monospace");
 			if (!font)
 				font = get_default_font ();
 
 			fd = pango_font_description_from_string (font);
-
 			g_free (font);
 		}
 
@@ -175,6 +248,8 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 
 		argv[1] = font_family;
 		argv[2] = font_size;
+		argv[3] = g_strdup_printf ("--syntax=%s", syntax);
+		g_free (syntax);
 
 		if (!g_spawn_async_with_pipes (
 			NULL, (gchar **) argv, NULL,
@@ -195,22 +270,28 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 
 		g_seekable_seek (G_SEEKABLE (read), 0, G_SEEK_SET, cancellable, NULL);
 		camel_stream_write_to_stream (read, stream, cancellable, NULL);
-		camel_stream_flush (read, cancellable, NULL);
 		g_object_unref (read);
 
 		g_free (font_family);
 		g_free (font_size);
+		g_free ((gchar *) argv[3]);
 		pango_font_description_free (fd);
 
 	} else {
 		gchar *uri, *str;
+		gchar *syntax;
+
+		syntax = get_syntax (part, NULL);
 
 		uri = e_mail_part_build_uri (
 			context->folder, context->message_uid,
 			"part_id", G_TYPE_STRING, part->id,
 			"mode", G_TYPE_INT, E_MAIL_FORMATTER_MODE_RAW,
+			"__formatas", G_TYPE_STRING, syntax,
 			NULL);
 
+		g_free (syntax);
+
 		str = g_strdup_printf (
 			"<div class=\"part-container\" style=\"border-color: #%06x; "
 			"background-color: #%06x;\">"
@@ -239,19 +320,19 @@ emfe_text_highlight_format (EMailFormatterExtension *extension,
 static const gchar *
 emfe_text_highlight_get_display_name (EMailFormatterExtension *extension)
 {
-	return _("Patch");
+	return _("Text Highlight");
 }
 
 static const gchar *
 emfe_text_highlight_get_description (EMailFormatterExtension *extension)
 {
-	return _("Format part as a patch");
+	return _("Syntax highlighting of mail parts");
 }
 
 static const gchar **
 emfe_text_highlight_mime_types (EMailExtension *extension)
 {
-	return formatter_mime_types;
+	return get_mime_types ();
 }
 
 static void
diff --git a/modules/text-highlight/text-highlight.h b/modules/text-highlight/e-mail-formatter-text-highlight.h
similarity index 100%
copy from modules/text-highlight/text-highlight.h
copy to modules/text-highlight/e-mail-formatter-text-highlight.h
diff --git a/modules/text-highlight/e-mail-parser-text-highlight.c b/modules/text-highlight/e-mail-parser-text-highlight.c
new file mode 100644
index 0000000..328e590
--- /dev/null
+++ b/modules/text-highlight/e-mail-parser-text-highlight.c
@@ -0,0 +1,159 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <camel/camel.h>
+
+#include "e-mail-parser-text-highlight.h"
+#include "languages.h"
+
+#include <em-format/e-mail-extension-registry.h>
+#include <em-format/e-mail-parser-extension.h>
+#include <em-format/e-mail-part.h>
+#include <em-format/e-mail-part-utils.h>
+
+#include <libebackend/libebackend.h>
+
+#define d(x)
+
+typedef struct _EMailParserTextHighlight {
+	EExtension parent;
+} EMailParserTextHighlight;
+
+typedef struct _EMailParserTextHighlightClass {
+	EExtensionClass parent_class;
+} EMailParserTextHighlightClass;
+
+GType e_mail_parser_text_highlight_get_type (void);
+static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface);
+static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (
+	EMailParserTextHighlight,
+	e_mail_parser_text_highlight,
+	E_TYPE_EXTENSION,
+	0,
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_EXTENSION,
+		e_mail_parser_mail_extension_interface_init)
+	G_IMPLEMENT_INTERFACE_DYNAMIC (
+		E_TYPE_MAIL_PARSER_EXTENSION,
+		e_mail_parser_parser_extension_interface_init));
+
+static GSList *
+empe_text_highlight_parse (EMailParserExtension *extension,
+			   EMailParser *parser,
+			   CamelMimePart *part,
+			   GString *part_id,
+			   GCancellable *cancellable)
+{
+	GSList *parts;
+	gint len;
+	CamelContentType *ct;
+
+	/* Prevent recursion */
+	if (strstr (part_id->str, ".text-highlight") != NULL) {
+		return NULL;
+	}
+
+	/* Don't parse text/html if it's not an attachment */
+	ct = camel_mime_part_get_content_type (part);
+	if (camel_content_type_is (ct, "text", "html")) {
+		const CamelContentDisposition *disp;
+
+		disp = camel_mime_part_get_content_disposition (part);
+		if (!disp || (g_strcmp0 (disp->disposition, "attachment") != 0)) {
+			return NULL;
+		}
+	}
+
+	len = part_id->len;
+	g_string_append (part_id, ".text-highlight");
+
+	/* All source codes and scripts are in general plain texts,
+	 * so let text/plain parser handle it. */
+	parts = e_mail_parser_parse_part_as (
+			parser, part, part_id, "text/plain", cancellable);
+
+	g_string_truncate (part_id, len);
+
+	return parts;
+}
+
+static const gchar **
+empe_mime_types (EMailExtension *extension)
+{
+	return get_mime_types ();
+}
+
+void
+e_mail_parser_text_highlight_type_register (GTypeModule *type_module)
+{
+	e_mail_parser_text_highlight_register_type (type_module);
+}
+
+static void
+e_mail_parser_mail_extension_interface_init (EMailExtensionInterface *iface)
+{
+	iface->mime_types = empe_mime_types;
+}
+
+static void
+e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface)
+{
+	iface->parse = empe_text_highlight_parse;
+}
+
+static void
+e_mail_parser_text_highlight_constructed (GObject *object)
+{
+	EExtensible *extensible;
+	EMailExtensionRegistry *reg;
+
+	extensible = e_extension_get_extensible (E_EXTENSION (object));
+	reg = E_MAIL_EXTENSION_REGISTRY (extensible);
+
+	e_mail_extension_registry_add_extension (reg, E_MAIL_EXTENSION (object));
+}
+
+static void
+e_mail_parser_text_highlight_class_init (EMailParserTextHighlightClass *class)
+{
+	GObjectClass *object_class;
+	EExtensionClass *extension_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = e_mail_parser_text_highlight_constructed;
+
+	extension_class = E_EXTENSION_CLASS (class);
+	extension_class->extensible_type = E_TYPE_MAIL_PARSER_EXTENSION_REGISTRY;
+}
+
+void
+e_mail_parser_text_highlight_class_finalize (EMailParserTextHighlightClass *class)
+{
+}
+
+static void
+e_mail_parser_text_highlight_init (EMailParserTextHighlight *parser)
+{
+
+}
diff --git a/modules/text-highlight/text-highlight.h b/modules/text-highlight/e-mail-parser-text-highlight.h
similarity index 75%
copy from modules/text-highlight/text-highlight.h
copy to modules/text-highlight/e-mail-parser-text-highlight.h
index af10da4..cc55a77 100644
--- a/modules/text-highlight/text-highlight.h
+++ b/modules/text-highlight/e-mail-parser-text-highlight.h
@@ -1,5 +1,5 @@
 /*
- * text-highlight.h
+ * e-mail-parser-text-highlight.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,15 +16,15 @@
  *
  */
 
-#ifndef TEXT_HIGHLIGHT_H
-#define TEXT_HIGHLIGHT_H
+#ifndef E_MAIL_PARSER_TEXT_HIGHLIGHT_H
+#define E_MAIL_PARSER_TEXT_HIGHLIGHT_H
 
 #include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void	e_mail_formatter_text_highlight_type_register (GTypeModule *type_module);
+void e_mail_parser_text_highlight_type_register (GTypeModule *type_module);
 
 G_END_DECLS
 
-#endif /* TEXT_HIGHLIGHT_H */
+#endif /* E_MAIL_PARSER_TEXT_HIGHLIGHT_H */
diff --git a/modules/text-highlight/evolution-module-text-highlight.c b/modules/text-highlight/evolution-module-text-highlight.c
index de6e469..78c3c4d 100644
--- a/modules/text-highlight/evolution-module-text-highlight.c
+++ b/modules/text-highlight/evolution-module-text-highlight.c
@@ -16,7 +16,9 @@
  *
  */
 
-#include "text-highlight.h"
+#include "e-mail-parser-text-highlight.h"
+#include "e-mail-formatter-text-highlight.h"
+#include "e-mail-display-popup-text-highlight.h"
 
 #include <gmodule.h>
 
@@ -28,8 +30,9 @@ G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
 	/* Register dynamically loaded types. */
-
+	e_mail_parser_text_highlight_type_register (type_module);
 	e_mail_formatter_text_highlight_type_register (type_module);
+	e_mail_display_popup_text_highlight_type_register (type_module);
 }
 
 G_MODULE_EXPORT void
diff --git a/modules/text-highlight/languages.c b/modules/text-highlight/languages.c
new file mode 100644
index 0000000..957b0ad
--- /dev/null
+++ b/modules/text-highlight/languages.c
@@ -0,0 +1,529 @@
+/*
+ * languages.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "languages.h"
+
+#include <glib/gi18n-lib.h>
+
+static const gchar **mime_types = NULL;
+G_LOCK_DEFINE_STATIC (mime_types);
+
+static Language languages[] = {
+
+	{ "txt", N_("_Plain text"),
+	  (const gchar* []) { (gchar[]) { "text" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/plain" },
+			      (gchar[]) { "text/*" }, NULL }
+	},
+
+	{ "assembler", N_("_Assembler"),
+	  (const gchar* []) { (gchar[]) { "asm" } , NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-asm" }, NULL }
+	},
+
+	{ "sh", N_("_Bash"),
+	  (const gchar* []) { (gchar[]) { "bash" }, (gchar[]) { "sh" },
+			      (gchar[]) { "ebuild" },  (gchar[])  {"eclass" },
+			      NULL },
+	  (const gchar* []) { (gchar[]) { "application/x-bsh" },
+			      (gchar[]) { "application/x-sh" },
+			      (gchar[]) { "application/x-shar" },
+			      (gchar[]) { "application/x-shellscript" },
+			      (gchar[]) { "text/x-script.sh" }, NULL }
+	},
+
+	{ "c", N_("_C/C++"),
+	  (const gchar* []) { (gchar[]) { "c" }, (gchar[]) { "c++" },
+			      (gchar[]) { "cc" }, (gchar[]) { "cpp" },
+			      (gchar[]) { "cu" }, (gchar[]) { "cxx" },
+			      (gchar[]) { "h" }, (gchar[]) { "hh" },
+			      (gchar[]) { "hpp" }, (gchar[]) { "hxx" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-c" }, NULL }
+	},
+
+	{ "csharp", N_("_C#"),
+	  (const gchar* []) { (gchar[]) { "cs" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-csharp" }, NULL }
+	},
+
+	{ "css", N_("_Cascade Style Sheet"),
+	  (const gchar* []) { (gchar[]) { "css" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/css" }, NULL }
+	},
+
+	{ "html", N_("_HTML"),
+	  (const gchar* []) { (gchar[]) { "html" }, (gchar[]) { "html" },
+			      (gchar[]) { "xhtml" }, (gchar[]) { "dhtml" }, NULL },
+	  (const gchar* []) { NULL } /* Don't register text-highlight as formatter
+	  				or parser of text/html as it would break
+	  				all text/html emails. */
+	},
+
+	{ "java", N_("_Java"),
+	  (const gchar* []) { (gchar[]) { "java" }, (gchar[]) { "groovy" },
+			      (gchar[]) { "grv" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/java-source" }, NULL }
+	},
+
+	{ "js", N_("_JavaScript"),
+	  (const gchar* []) { (gchar[]) { "js" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/javascript" },
+			      (gchar[]) { "application/x-javascript" }, NULL }
+	},
+
+	{ "diff", N_("_Patch/diff"),
+	  (const gchar* []) { (gchar[]) { "diff" }, (gchar[]) { "patch" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-diff" },
+	  		      (gchar[]) { "text/x-patch" }, NULL }
+	},
+
+	{ "perl", N_("_Perl"),
+	  (const gchar* []) { (gchar[]) { "perl" }, (gchar[]) { "cgi"},
+			      (gchar[]) { "perl" }, (gchar[]) { "pl" },
+			      (gchar[]) { "plex" }, (gchar[]) { "plx" },
+			      (gchar[]) { "pm" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-script.perl" },
+			      (gchar[]) { "text/x-script.perl-module" },
+			      (gchar[]) { "application/x-pixclscript" },
+			      (gchar[]) { "application/x-xpixmap" }, NULL }
+	},
+
+	{ "php", N_("_PHP"),
+	  (const gchar* []) { (gchar[]) { "php" }, (gchar[]) { "php3" },
+			      (gchar[]) { "php4" }, (gchar[]) { "php5" },
+			      (gchar[]) { "php6" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/php" },
+	  		      (gchar[]) { "text/x-php" },
+	  		      (gchar[]) { "application/php" },
+	  		      (gchar[]) { "application/x-php" },
+	  		      (gchar[]) { "application/x-httpd-php" },
+	  		      (gchar[]) { "application/x-httpd-php-source" },
+	  		      NULL }
+	},
+
+	{ "python", N_("_Python"),
+	  (const gchar* []) { (gchar[]) { "py" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-script.python" }, NULL }
+	},
+
+	{ "ruby", N_("_Ruby"),
+	  (const gchar* []) { (gchar[]) { "ruby" }, (gchar[]) { "pp" },
+			      (gchar[]) { "rb" }, (gchar[]) { "rjs" },
+			      (gchar[]) { "ruby" }, NULL },
+	  (const gchar* []) { (gchar[]) { "application/x-ruby" }, NULL }
+	},
+
+	{ "tcl", N_("_Tcl/Tk"),
+	  (const gchar* []) { (gchar[]) { "tcl" }, (gchar[]) { "ictl" },
+			      (gchar[]) { "wish" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-tcl" }, NULL }
+	},
+
+	{ "tex", N_("_TeX/LaTeX"),
+	  (const gchar* []) { (gchar[]) { "tex" }, (gchar[]) { "csl" },
+			      (gchar[]) { "sty" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-tex" }, NULL }
+	},
+
+	{ "vala", N_("_Vala"),
+	  (const gchar* []) { (gchar[]) { "vala" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-vala" }, NULL }
+	},
+
+	{ "vb", N_("_Visual Basic"),
+	  (const gchar* []) { (gchar[]) { "vb" }, (gchar[]) { "bas" },
+			      (gchar[]) { "basic" }, (gchar[]) { "bi" },
+			      (gchar[]) { "vbs" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "xml", N_("_XML"),
+	  (const gchar* []) { (gchar[]) { "xml" }, (gchar[]) { "dtd" },
+			      (gchar[]) { "ecf" }, (gchar[]) { "ent" },
+			      (gchar[]) { "hdr" }, (gchar[]) { "hub" },
+			      (gchar[]) { "jnlp" }, (gchar[]) { "nrm" },
+			      (gchar[]) { "resx" }, (gchar[]) { "sgm" },
+			      (gchar[]) { "sgml" }, (gchar[]) { "svg" },
+			      (gchar[]) { "tld" }, (gchar[]) { "vxml" },
+			      (gchar[]) { "wml" }, (gchar[]) { "xsd" },
+			      (gchar[]) { "xsl" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/xml" },
+			      (gchar[]) { "application/xml" },
+			      (gchar[]) { "application/x-xml" }, NULL }
+	}
+};
+
+static struct Language other_languages[] = {
+
+	{ "actionscript", N_("_ActionScript"),
+	  (const gchar* []) { (gchar[]) { "as" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "ada", N_("_ADA95"),
+	  (const gchar* []) { (gchar[]) { "a" }, (gchar[]) { "adb" },
+		              (gchar[]) { "ads" }, (gchar[]) { "gnad" },
+		              NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-adasrc" }, NULL }
+	},
+
+	{ "algol", N_("_ALGOL 68"),
+	  (const gchar* []) { (gchar[]) { "alg" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "awk", N_("(_G)AWK"),
+	  (const gchar* []) { (gchar[]) { "awk" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-awk" }, NULL }
+	},
+
+	{ "cobol", N_("_COBOL"),
+	  (const gchar* []) { (gchar[]) { "cbl" }, (gchar[]) { "cob" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-cobol" }, NULL }
+	},
+
+	{ "bat", N_("_DOS Batch"),
+	  (const gchar* []) { (gchar[]) { "bat" }, (gchar[]) { "cmd" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "d", N_("_D"),
+	  (const gchar* []) { (gchar[]) { "d" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "erlang", N_("_Erlang"),
+	  (const gchar* []) { (gchar[]) { "erl" }, (gchar[]) { "hrl" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-erlang" }, NULL }
+	},
+
+	{ "fortran77", N_("_FORTRAN 77"),
+	  (const gchar* []) { (gchar[]) { "f" }, (gchar[]) { "for" },
+			      (gchar[]) { "ftn" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-fortran" }, NULL }
+	},
+
+	{ "fortran90", N_("_FORTRAN 90"),
+	  (const gchar* []) { (gchar[]) { "f90" }, (gchar[]) { "f95" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-fortran" }, NULL }
+	},
+
+	{ "fsharp", N_("_F#"),
+	  (const gchar* []) { (gchar[]) { "fs" }, (gchar[]) { "fsx" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "go", N_("_Go"),
+	  (const gchar* []) { (gchar[]) { "go" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-go" }, NULL }
+	},
+
+	{ "haskell", N_("_Haskell"),
+	  (const gchar* []) { (gchar[]) { "hs" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-haskell" }, NULL }
+	},
+
+	{ "jsp", N_("_JSP"),
+	  (const gchar* []) { (gchar[]) { "jsp" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-jsp" }, NULL }
+	},
+
+	{ "lisp", N_("_Lisp"),
+	  (const gchar* []) { (gchar[]) { "cl" }, (gchar[]) { "clisp" },
+			      (gchar[]) { "el" }, (gchar[]) { "lsp" },
+			      (gchar[]) { "sbcl"}, (gchar[]) { "scom" },
+			      NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-emacs-lisp" }, NULL }
+	},
+
+	{ "lotus", N_("_Lotus"),
+	  (const gchar* []) { (gchar[]) { "ls" }, NULL },
+	  (const gchar* []) { (gchar[]) { "application/vnd.lotus-1-2-3" }, NULL }
+	},
+
+	{ "lua", N_("_Lua"),
+	  (const gchar* []) { (gchar[]) { "lua" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-lua" }, NULL }
+	},
+
+	{ "maple", N_("_Maple"),
+	  (const gchar* []) { (gchar[]) { "mpl" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "matlab", N_("_Matlab"),
+	  (const gchar* []) { (gchar[]) { "m" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-matlab" }, NULL }
+	},
+
+	{ "maya", N_("_Maya"),
+	  (const gchar* []) { (gchar[]) { "mel" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "oberon", N_("_Oberon"),
+	  (const gchar* []) { (gchar[]) { "ooc" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "objc", N_("_Objective C"),
+	  (const gchar* []) { (gchar[]) { "objc" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-objchdr" },
+			      (gchar[]) { "text/x-objcsrc" }, NULL }
+	},
+
+	{ "ocaml", N_("_OCaml"),
+	  (const gchar* []) { (gchar[]) { "ml" }, (gchar[]) { "mli" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-ocaml" }, NULL }
+	},
+
+	{ "octave", N_("_Octave"),
+	  (const gchar* []) { (gchar[]) { "octave" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "os", N_("_Object Script"),
+	  (const gchar* []) { (gchar[]) { "os" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "pascal", N_("_Pascal"),
+	  (const gchar* []) { (gchar[]) { "pas" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-pascal" }, NULL }
+	},
+
+	{ "pov", N_("_POV-Ray"),
+	  (const gchar* []) { (gchar[]) { "pov" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "pro", N_("_Prolog"),
+	  (const gchar* []) { (gchar[]) { "pro" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "ps", N_("_PostScript"),
+	  (const gchar* []) { (gchar[]) { "ps" } , NULL },
+	  (const gchar* []) { (gchar[]) { "application/postscript" }, NULL }
+	},
+
+	{ "r", N_("_R"),
+	  (const gchar* []) { (gchar[]) { "r" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "spec", N_("_RPM Spec"),
+	  (const gchar* []) { (gchar[]) { "spec" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-rpm-spec" }, NULL }
+	},
+
+	{ "scala", N_("_Scala"),
+	  (const gchar* []) { (gchar[]) { "scala" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-scala" }, NULL }
+	},
+
+	{ "smalltalk", N_("_Smalltalk"),
+	  (const gchar* []) { (gchar[]) { "gst" }, (gchar[]) { "sq" },
+			      (gchar[]) { "st" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "tcsh", N_("_TCSH"),
+	  (const gchar* []) { (gchar[]) { "tcsh" }, NULL },
+	  (const gchar* []) { NULL }
+	},
+
+	{ "vhd", N_("_VHDL"),
+	  (const gchar* []) { (gchar[]) { "vhd" }, NULL },
+	  (const gchar* []) { (gchar[]) { "text/x-vhdl" }, NULL }
+	}
+};
+
+Language *
+get_default_langauges (gsize *len)
+{
+	if (len) {
+		*len = G_N_ELEMENTS (languages);
+	}
+
+	return languages;
+}
+
+Language *
+get_additinal_languages (gsize *len)
+{
+	if (len) {
+		*len = G_N_ELEMENTS (other_languages);
+	}
+
+	return other_languages;
+}
+
+const gchar *
+get_syntax_for_ext(const gchar *extension)
+{
+	gint i;
+	gint j;
+
+	for (i = 0; i < G_N_ELEMENTS (languages); i++) {
+
+		Language *lang = &languages[i];
+		const gchar *ext;
+
+		j = 0;
+		ext = lang->extensions[j];
+		while (ext) {
+			if (g_ascii_strncasecmp (ext, extension, strlen (ext)) == 0) {
+				return lang->action_name;
+			}
+
+			j++;
+			ext = lang->extensions[j];
+		}
+	}
+
+	for (i = 0; i < G_N_ELEMENTS (other_languages); i++) {
+
+		Language *lang = &other_languages[i];
+		const gchar *ext;
+
+		j = 0;
+		ext = lang->extensions[j];
+		while (ext) {
+			if (g_ascii_strncasecmp (ext, extension, strlen (ext)) == 0) {
+				return lang->action_name;
+			}
+
+			j++;
+			ext = lang->extensions[j];
+		}
+	}
+
+	return NULL;
+}
+
+const gchar *
+get_syntax_for_mime_type(const gchar *mime_type)
+{
+	gint i;
+	gint j;
+
+	for (i = 0; i < G_N_ELEMENTS (languages); i++) {
+
+		Language *lang = &languages[i];
+		const gchar *mt;
+
+		j = 0;
+		mt = lang->mime_types[j];
+		while (mt) {
+			if (g_ascii_strncasecmp (mt, mime_type, strlen (mt)) == 0) {
+				return lang->action_name;
+			}
+
+			j++;
+			mt = lang->mime_types[j];
+		}
+	}
+
+	for (i = 0; i < G_N_ELEMENTS (other_languages); i++) {
+
+		Language *lang = &other_languages[i];
+		const gchar *mt;
+
+		j = 0;
+		mt = lang->mime_types[j];
+		while (mt) {
+			if (g_ascii_strncasecmp (mt, mime_type, strlen (mt)) == 0) {
+				return lang->action_name;
+			}
+
+			j++;
+			mt = lang->mime_types[j];
+		}
+	}
+
+	return NULL;
+}
+
+
+const gchar **
+get_mime_types (void)
+{
+	G_LOCK (mime_types);
+	if (mime_types == NULL) {
+		gchar **list;
+		gsize array_len;
+		gint i, pos;
+
+		array_len = G_N_ELEMENTS (languages);
+		pos = 0;
+
+		list = g_malloc (array_len * sizeof (gchar *));
+
+		for (i = 0; i < G_N_ELEMENTS (languages); i++) {
+			Language *lang = &languages[i];
+
+			gint j = 0;
+			while (lang->mime_types[j] != NULL) {
+				if (pos == array_len) {
+					array_len += 10;
+					list = g_realloc (list, array_len * sizeof (gchar *));
+				}
+
+				list[pos] = (gchar *) lang->mime_types[j];
+				pos++;
+				j++;
+			}
+		}
+
+		for (i = 0; i < G_N_ELEMENTS (other_languages); i++) {
+			Language *lang = &other_languages[i];
+
+			gint j = 0;
+			while (lang->mime_types[j] != NULL) {
+				if (pos == array_len) {
+					array_len += 10;
+					list = g_realloc (list, array_len * sizeof (gchar *));
+				}
+
+				list[pos] = (gchar *) lang->mime_types[j];
+				pos++;
+				j++;
+			}
+		}
+
+		if (pos == array_len) {
+			array_len += 1;
+			list = g_realloc (list, array_len * sizeof (gchar *));
+		}
+
+		/* Ensure the array is null-terminated */
+		for (i = pos; i < array_len; i++) {
+			list[i] = NULL;
+		}
+
+		mime_types = (const gchar **) list;
+	}
+	G_UNLOCK (mime_types);
+
+	return mime_types;
+}
diff --git a/modules/text-highlight/text-highlight.h b/modules/text-highlight/languages.h
similarity index 56%
rename from modules/text-highlight/text-highlight.h
rename to modules/text-highlight/languages.h
index af10da4..03f1442 100644
--- a/modules/text-highlight/text-highlight.h
+++ b/modules/text-highlight/languages.h
@@ -1,5 +1,5 @@
 /*
- * text-highlight.h
+ * languages.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,15 +16,24 @@
  *
  */
 
-#ifndef TEXT_HIGHLIGHT_H
-#define TEXT_HIGHLIGHT_H
+#ifndef LANGUAGES_H
+#define LANGUAGES_H
 
-#include <glib-object.h>
+#include <glib.h>
 
-G_BEGIN_DECLS
+typedef struct Language {
+	const gchar *action_name;
+	const gchar *action_label;
+	const gchar **extensions;
+	const gchar **mime_types;
+} Language;
 
-void	e_mail_formatter_text_highlight_type_register (GTypeModule *type_module);
+const gchar *	get_syntax_for_ext 		(const gchar *extension);
+const gchar *	get_syntax_for_mime_type	(const gchar *mime_type);
 
-G_END_DECLS
+Language *	get_default_langauges		(gsize *len);
+Language *	get_additinal_languages		(gsize *len);
 
-#endif /* TEXT_HIGHLIGHT_H */
+const gchar **	get_mime_types			(void);
+
+#endif /* LANGUAGES_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]