diff options
author | Dan Vrátil <dvratil@redhat.com> | 2012-07-25 17:29:22 +0800 |
---|---|---|
committer | Dan Vrátil <dvratil@redhat.com> | 2012-07-25 17:29:22 +0800 |
commit | 8663b54cae296883452850f3baad6d4cbc92e220 (patch) | |
tree | f895a43b817e0115a57bc639b2b6a9e40caa1193 | |
parent | b456ff5423b9f4ffe5719e460e4b769bed28c934 (diff) | |
download | gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar.gz gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar.bz2 gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar.lz gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar.xz gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.tar.zst gsoc2013-evolution-8663b54cae296883452850f3baad6d4cbc92e220.zip |
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)
-rw-r--r-- | em-format/e-mail-formatter.h | 2 | ||||
-rw-r--r-- | em-format/e-mail-parser-text-plain.c | 3 | ||||
-rw-r--r-- | mail/e-mail-display.c | 6 | ||||
-rw-r--r-- | mail/e-mail-request.c | 24 | ||||
-rw-r--r-- | modules/text-highlight/Makefile.am | 16 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-display-popup-text-highlight.c | 370 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-display-popup-text-highlight.h | 30 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-formatter-text-highlight.c (renamed from modules/text-highlight/text-highlight.c) | 127 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-formatter-text-highlight.h (renamed from modules/text-highlight/text-highlight.h) | 0 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-parser-text-highlight.c | 159 | ||||
-rw-r--r-- | modules/text-highlight/e-mail-parser-text-highlight.h | 30 | ||||
-rw-r--r-- | modules/text-highlight/evolution-module-text-highlight.c | 7 | ||||
-rw-r--r-- | modules/text-highlight/languages.c | 529 | ||||
-rw-r--r-- | modules/text-highlight/languages.h | 39 |
14 files changed, 1298 insertions, 44 deletions
diff --git a/em-format/e-mail-formatter.h b/em-format/e-mail-formatter.h index c0c21c13b0..9b4e84d262 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 00a7b53b18..1795d019a9 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 be99ea226c..6cbbaa6091 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 0f185c2031..aee9c9cc91 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 9b27298474..8c7e639622 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 0000000000..0adea1dac7 --- /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/e-mail-display-popup-text-highlight.h b/modules/text-highlight/e-mail-display-popup-text-highlight.h new file mode 100644 index 0000000000..003f7d9bc2 --- /dev/null +++ b/modules/text-highlight/e-mail-display-popup-text-highlight.h @@ -0,0 +1,30 @@ +/* + * 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 + * 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/> + * + */ + +#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_display_popup_text_highlight_type_register (GTypeModule *type_module); + +G_END_DECLS + +#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 index 26f7708f76..e216245500 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 index af10da4c84..af10da4c84 100644 --- a/modules/text-highlight/text-highlight.h +++ b/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 0000000000..328e590f6d --- /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/e-mail-parser-text-highlight.h b/modules/text-highlight/e-mail-parser-text-highlight.h new file mode 100644 index 0000000000..cc55a777ac --- /dev/null +++ b/modules/text-highlight/e-mail-parser-text-highlight.h @@ -0,0 +1,30 @@ +/* + * 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 + * 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/> + * + */ + +#ifndef E_MAIL_PARSER_TEXT_HIGHLIGHT_H +#define E_MAIL_PARSER_TEXT_HIGHLIGHT_H + +#include <glib-object.h> + +G_BEGIN_DECLS + +void e_mail_parser_text_highlight_type_register (GTypeModule *type_module); + +G_END_DECLS + +#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 de6e469bde..78c3c4dcf5 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 0000000000..957b0aded9 --- /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/languages.h b/modules/text-highlight/languages.h new file mode 100644 index 0000000000..03f1442531 --- /dev/null +++ b/modules/text-highlight/languages.h @@ -0,0 +1,39 @@ +/* + * languages.h + * + * 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/> + * + */ + +#ifndef LANGUAGES_H +#define LANGUAGES_H + +#include <glib.h> + +typedef struct Language { + const gchar *action_name; + const gchar *action_label; + const gchar **extensions; + const gchar **mime_types; +} Language; + +const gchar * get_syntax_for_ext (const gchar *extension); +const gchar * get_syntax_for_mime_type (const gchar *mime_type); + +Language * get_default_langauges (gsize *len); +Language * get_additinal_languages (gsize *len); + +const gchar ** get_mime_types (void); + +#endif /* LANGUAGES_H */ |