[evolution/wip/mcrha/webkit-jsc-api] Replace Monospace with Font Name for page and text selection



commit 088bbec0245018460deb483a50f82f3ec1c43c89
Author: Milan Crha <mcrha redhat com>
Date:   Tue Nov 26 16:03:16 2019 +0100

    Replace Monospace with Font Name for page and text selection

 data/webkit/e-editor.js                     |  47 +++++++++-
 src/e-util/e-content-editor.c               |  87 ++++++------------
 src/e-util/e-content-editor.h               |  12 ++-
 src/e-util/e-html-editor-actions.c          |  33 ++++---
 src/e-util/e-html-editor-actions.h          |   2 -
 src/e-util/e-html-editor-manager.ui         |   3 -
 src/e-util/e-html-editor-page-dialog.c      |  66 +++++++++++--
 src/e-util/e-html-editor-private.h          |   5 +
 src/e-util/e-html-editor.c                  | 138 ++++++++++++++++++++++++++++
 src/e-util/test-html-editor-units-utils.c   |  22 ++++-
 src/e-util/test-html-editor-units.c         |  10 +-
 src/modules/webkit-editor/e-webkit-editor.c |  91 +++++++++---------
 12 files changed, 379 insertions(+), 137 deletions(-)
---
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index 7c615d219c..e9dae1be2d 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -88,7 +88,8 @@ var EvoEditor = {
                bodyFgColor : null,
                bodyBgColor : null,
                bodyLinkColor : null,
-               bodyVlinkColor : null
+               bodyVlinkColor : null,
+               bodyFontFamily : null
        }
 };
 
@@ -174,13 +175,18 @@ EvoEditor.maybeUpdateFormattingState = function(force)
        value = computedStyle ? computedStyle.fontFamily : "";
        if (force || value != EvoEditor.formattingState.fontFamily) {
                EvoEditor.formattingState.fontFamily = value;
-               changes["fontFamily"] = value;
+               changes["fontFamily"] = (window.getComputedStyle(document.body).fontFamily == value) ? "" : 
value;
+               nchanges++;
+       }
+
+       value = document.body ? document.body.style.fontFamily : "";
+       if (force || value != EvoEditor.formattingState.bodyFontFamily) {
+               EvoEditor.formattingState.bodyFontFamily = value;
+               changes["bodyFontFamily"] = value;
                nchanges++;
        }
 
        value = computedStyle ? computedStyle.color : "";
-       if (value == "-webkit-standard")
-               value = "";
        if (force || value != EvoEditor.formattingState.fgColor) {
                EvoEditor.formattingState.fgColor = value;
                changes["fgColor"] = value;
@@ -1153,6 +1159,39 @@ EvoEditor.SetBodyAttribute = function(name, value)
        }
 }
 
+EvoEditor.SetBodyFontName = function(name)
+{
+       var record;
+
+       record = EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "setBodyFontName", document.body, 
document.body, EvoEditor.CLAIM_CONTENT_FLAG_NONE);
+
+       try {
+               if (record) {
+                       record.attrName = "style";
+                       record.beforeValue = document.body.getAttribute("style");
+                       record.apply = EvoEditor.applySetBodyAttribute;
+               }
+
+               if (name)
+                       document.body.style.fontFamily = name;
+               else
+                       document.body.style.fontFamily = "";
+
+               if (record) {
+                       record.attrValue = document.body.getAttribute("style");
+
+                       if (record.attrValue == record.beforeValue)
+                               record.ignore = true;
+               }
+       } finally {
+               EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "setBodyFontName");
+               EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
+
+               if (!record || !record.ignore)
+                       EvoEditor.EmitContentChanged();
+       }
+}
+
 EvoEditor.initializeContent = function()
 {
        if (document.body) {
diff --git a/src/e-util/e-content-editor.c b/src/e-util/e-content-editor.c
index 0aa44acdfa..db4f5bc617 100644
--- a/src/e-util/e-content-editor.c
+++ b/src/e-util/e-content-editor.c
@@ -330,22 +330,6 @@ e_content_editor_default_init (EContentEditorInterface *iface)
                        G_PARAM_READWRITE |
                        G_PARAM_STATIC_STRINGS));
 
-       /**
-        * EContentEditor:monospaced
-        *
-        * Holds whether current selection or letter at current cursor position
-        * is monospaced.
-        */
-       g_object_interface_install_property (
-               iface,
-               g_param_spec_boolean (
-                       "monospaced",
-                       NULL,
-                       NULL,
-                       FALSE,
-                       G_PARAM_READWRITE |
-                       G_PARAM_STATIC_STRINGS));
-
        /**
         * EContentEditor:strikethrough
         *
@@ -1184,48 +1168,6 @@ e_content_editor_is_italic (EContentEditor *editor)
        return value;
 }
 
-/**
- * e_content_editor_set_monospaced:
- * @editor: an #EContentEditor
- * @monospaced: %TRUE to enable monospaced, %FALSE to disable
- *
- * Changes monospaced formatting of current selection or letter
- * at current cursor position.
- *
- * Since: 3.22
- **/
-void
-e_content_editor_set_monospaced (EContentEditor *editor,
-                                gboolean monospaced)
-{
-       g_return_if_fail (E_IS_CONTENT_EDITOR (editor));
-
-       g_object_set (G_OBJECT (editor), "monospaced", monospaced, NULL);
-}
-
-/**
- * e_content_editor_is_monospaced:
- * @editor: an #EContentEditor
- *
- * Returns whether current selection or letter at current cursor position
- * is monospaced.
- *
- * Returns: %TRUE when selection is monospaced, %FALSE otherwise.
- *
- * Since: 3.22
- **/
-gboolean
-e_content_editor_is_monospaced (EContentEditor *editor)
-{
-       gboolean value = FALSE;
-
-       g_return_val_if_fail (E_IS_CONTENT_EDITOR (editor), FALSE);
-
-       g_object_get (G_OBJECT (editor), "monospaced", &value, NULL);
-
-       return value;
-}
-
 /**
  * e_content_editor_set_strikethrough:
  * @editor: an #EContentEditor
@@ -3348,6 +3290,35 @@ e_content_editor_page_get_visited_link_color (EContentEditor *editor,
        return iface->page_get_visited_link_color (editor, value);
 }
 
+void
+e_content_editor_page_set_font_name (EContentEditor *editor,
+                                    const gchar *value)
+{
+       EContentEditorInterface *iface;
+
+       g_return_if_fail (E_IS_CONTENT_EDITOR (editor));
+
+       iface = E_CONTENT_EDITOR_GET_IFACE (editor);
+       g_return_if_fail (iface != NULL);
+       g_return_if_fail (iface->page_set_font_name != NULL);
+
+       iface->page_set_font_name (editor, value);
+}
+
+const gchar *
+e_content_editor_page_get_font_name (EContentEditor *editor)
+{
+       EContentEditorInterface *iface;
+
+       g_return_val_if_fail (E_IS_CONTENT_EDITOR (editor), NULL);
+
+       iface = E_CONTENT_EDITOR_GET_IFACE (editor);
+       g_return_val_if_fail (iface != NULL, NULL);
+       g_return_val_if_fail (iface->page_get_font_name != NULL, NULL);
+
+       return iface->page_get_font_name (editor);
+}
+
 /* uri could be NULL -> removes the current image */
 void
 e_content_editor_page_set_background_image_uri (EContentEditor *editor,
diff --git a/src/e-util/e-content-editor.h b/src/e-util/e-content-editor.h
index d96170cffb..84892846de 100644
--- a/src/e-util/e-content-editor.h
+++ b/src/e-util/e-content-editor.h
@@ -295,6 +295,9 @@ struct _EContentEditorInterface {
 
        void            (*page_get_visited_link_color)  (EContentEditor *editor,
                                                         GdkRGBA *value);
+       void            (*page_set_font_name)           (EContentEditor *editor,
+                                                        const gchar *value);
+       const gchar *   (*page_get_font_name)           (EContentEditor *editor);
 
        void            (*page_set_background_image_uri)
                                                        (EContentEditor *editor,
@@ -517,9 +520,6 @@ gboolean    e_content_editor_is_bold        (EContentEditor *editor);
 void           e_content_editor_set_italic     (EContentEditor *editor,
                                                 gboolean italic);
 gboolean       e_content_editor_is_italic      (EContentEditor *editor);
-void           e_content_editor_set_monospaced (EContentEditor *editor,
-                                                gboolean monospaced);
-gboolean       e_content_editor_is_monospaced (EContentEditor *editor);
 void           e_content_editor_set_strikethrough
                                                (EContentEditor *editor,
                                                 gboolean strikethrough);
@@ -894,6 +894,12 @@ void               e_content_editor_page_set_visited_link_color
 void           e_content_editor_page_get_visited_link_color
                                                (EContentEditor *editor,
                                                 GdkRGBA *value);
+void           e_content_editor_page_set_font_name
+                                               (EContentEditor *editor,
+                                                const gchar *value);
+
+const gchar *  e_content_editor_page_get_font_name
+                                               (EContentEditor *editor);
 
 void           e_content_editor_page_set_background_image_uri
                                                (EContentEditor *editor,
diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c
index 742c457558..73339af93a 100644
--- a/src/e-util/e-html-editor-actions.c
+++ b/src/e-util/e-html-editor-actions.c
@@ -1494,14 +1494,6 @@ static GtkToggleActionEntry html_toggle_entries[] = {
          NULL,
          FALSE },
 
-       { "monospaced",
-         "stock_text-monospaced",
-         N_("_Plain Text"),
-         "<Control>t",
-         N_("Plain Text"),
-         NULL,
-         FALSE },
-
        { "strikethrough",
          "format-text-strikethrough",
          N_("_Strikethrough"),
@@ -2208,6 +2200,20 @@ editor_actions_init (EHTMLEditor *editor)
        gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
 }
 
+static gboolean
+e_html_editor_content_editor_font_name_to_combo_box (GBinding *binding,
+                                                    const GValue *from_value,
+                                                    GValue *to_value,
+                                                    gpointer user_data)
+{
+       gchar *id = NULL;
+
+       id = e_html_editor_until_dup_font_id (GTK_COMBO_BOX (g_binding_get_target (binding)), 
g_value_get_string (from_value));
+       g_value_take_string (to_value, id ? id : g_strdup (""));
+
+       return TRUE;
+}
+
 void
 editor_actions_bind (EHTMLEditor *editor)
 {
@@ -2280,10 +2286,6 @@ editor_actions_bind (EHTMLEditor *editor)
                cnt_editor, "italic",
                ACTION (ITALIC), "active",
                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
-       e_binding_bind_property (
-               cnt_editor, "monospaced",
-               ACTION (MONOSPACED), "active",
-               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
        e_binding_bind_property (
                cnt_editor, "strikethrough",
                ACTION (STRIKETHROUGH), "active",
@@ -2292,6 +2294,13 @@ editor_actions_bind (EHTMLEditor *editor)
                cnt_editor, "underline",
                ACTION (UNDERLINE), "active",
                G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
+       e_binding_bind_property_full (
+               cnt_editor, "font-name",
+               editor->priv->font_name_combo_box, "active-id",
+               G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL,
+               e_html_editor_content_editor_font_name_to_combo_box,
+               NULL,
+               NULL, NULL);
 
        /* Cannot use binding, due to subscript and superscript being mutually exclusive */
        g_signal_connect_object (ACTION (SUBSCRIPT), "toggled",
diff --git a/src/e-util/e-html-editor-actions.h b/src/e-util/e-html-editor-actions.h
index 7ea6286d55..ecb5922c7c 100644
--- a/src/e-util/e-html-editor-actions.h
+++ b/src/e-util/e-html-editor-actions.h
@@ -113,8 +113,6 @@
        E_HTML_EDITOR_ACTION ((editor), "mode-html")
 #define E_HTML_EDITOR_ACTION_MODE_PLAIN(editor) \
        E_HTML_EDITOR_ACTION ((editor), "mode-plain")
-#define E_HTML_EDITOR_ACTION_MONOSPACED(editor) \
-       E_HTML_EDITOR_ACTION ((editor), "monospaced")
 #define E_HTML_EDITOR_ACTION_PASTE(editor) \
        E_HTML_EDITOR_ACTION ((editor), "paste")
 #define E_HTML_EDITOR_ACTION_PASTE_QUOTE(editor) \
diff --git a/src/e-util/e-html-editor-manager.ui b/src/e-util/e-html-editor-manager.ui
index 2110cd01a2..8c50ff8ec1 100644
--- a/src/e-util/e-html-editor-manager.ui
+++ b/src/e-util/e-html-editor-manager.ui
@@ -53,8 +53,6 @@
       <menuitem action='mode-plain'/>
       <separator/>
       <menu action='font-style-menu'>
-        <menuitem action='monospaced'/>
-        <separator/>
         <menuitem action='bold'/>
         <menuitem action='italic'/>
         <menuitem action='underline'/>
@@ -130,7 +128,6 @@
   </toolbar>
   <toolbar name='html-toolbar'>
     <separator/>
-    <toolitem action='monospaced'/>
     <toolitem action='bold'/>
     <toolitem action='italic'/>
     <toolitem action='underline'/>
diff --git a/src/e-util/e-html-editor-page-dialog.c b/src/e-util/e-html-editor-page-dialog.c
index e86f2c9ee7..a870be1046 100644
--- a/src/e-util/e-html-editor-page-dialog.c
+++ b/src/e-util/e-html-editor-page-dialog.c
@@ -27,6 +27,7 @@
 #include "e-color-combo.h"
 #include "e-misc-utils.h"
 #include "e-dialog-widgets.h"
+#include "e-html-editor-private.h"
 
 #define E_HTML_EDITOR_PAGE_DIALOG_GET_PRIVATE(obj) \
        (G_TYPE_INSTANCE_GET_PRIVATE \
@@ -38,6 +39,8 @@ struct _EHTMLEditorPageDialogPrivate {
        GtkWidget *visited_link_color_picker;
        GtkWidget *background_color_picker;
 
+       GtkWidget *text_font_name_combo;
+
        GtkWidget *background_template_combo;
        GtkWidget *background_image_filechooser;
 
@@ -206,6 +209,18 @@ html_editor_page_dialog_set_background_color (EHTMLEditorPageDialog *dialog)
        e_content_editor_page_set_background_color (cnt_editor, &rgba);
 }
 
+static void
+html_editor_page_dialog_set_text_font_name (EHTMLEditorPageDialog *dialog)
+{
+       EHTMLEditor *editor;
+       EContentEditor *cnt_editor;
+
+       editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
+       cnt_editor = e_html_editor_get_content_editor (editor);
+
+       e_content_editor_page_set_font_name (cnt_editor, gtk_combo_box_get_active_id (GTK_COMBO_BOX 
(dialog->priv->text_font_name_combo)));
+}
+
 static void
 html_editor_page_dialog_set_background_from_template (EHTMLEditorPageDialog *dialog)
 {
@@ -286,7 +301,7 @@ html_editor_page_dialog_show (GtkWidget *widget)
        EContentEditor *cnt_editor;
        EHTMLEditorPageDialog *dialog;
        GdkRGBA rgba;
-       gchar *uri;
+       gchar *uri, *font_name;
 
        dialog = E_HTML_EDITOR_PAGE_DIALOG (widget);
        editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog));
@@ -331,6 +346,11 @@ html_editor_page_dialog_show (GtkWidget *widget)
        e_color_combo_set_current_color (
                E_COLOR_COMBO (dialog->priv->background_color_picker), &rgba);
 
+       font_name = e_html_editor_until_dup_font_id (GTK_COMBO_BOX (dialog->priv->text_font_name_combo),
+               e_content_editor_page_get_font_name (cnt_editor));
+       gtk_combo_box_set_active_id (GTK_COMBO_BOX (dialog->priv->text_font_name_combo), font_name ? 
font_name : "");
+       g_free (font_name);
+
        GTK_WIDGET_CLASS (e_html_editor_page_dialog_parent_class)->show (widget);
 }
 
@@ -368,15 +388,19 @@ e_html_editor_page_dialog_init (EHTMLEditorPageDialog *dialog)
        GtkBox *box;
        GtkGrid *grid, *main_layout;
        GtkWidget *widget;
+       PangoAttrList *bold;
        gint ii;
 
        dialog->priv = E_HTML_EDITOR_PAGE_DIALOG_GET_PRIVATE (dialog);
 
        main_layout = e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog));
 
+       bold = pango_attr_list_new ();
+       pango_attr_list_insert (bold, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+
        /* == Colors == */
-       widget = gtk_label_new ("");
-       gtk_label_set_markup (GTK_LABEL (widget), _("<b>Colors</b>"));
+       widget = gtk_label_new (_("Colors"));
+       gtk_label_set_attributes (GTK_LABEL (widget), bold);
        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
        gtk_grid_attach (main_layout, widget, 0, 0, 1, 1);
 
@@ -446,16 +470,42 @@ e_html_editor_page_dialog_init (EHTMLEditorPageDialog *dialog)
                GTK_LABEL (widget), dialog->priv->background_color_picker);
        gtk_grid_attach (grid, widget, 0, 3, 1, 1);
 
-       /* == Background Image == */
-       widget = gtk_label_new ("");
-       gtk_label_set_markup (GTK_LABEL (widget), _("<b>Background Image</b>"));
+       /* == Text == */
+
+       widget = gtk_label_new (_("Text"));
+       gtk_label_set_attributes (GTK_LABEL (widget), bold);
        gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
        gtk_grid_attach (main_layout, widget, 0, 2, 1, 1);
 
        grid = GTK_GRID (gtk_grid_new ());
        gtk_grid_set_row_spacing (grid, 5);
        gtk_grid_set_column_spacing (grid, 5);
-       gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 4, 1, 1);
+       gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 3, 1, 1);
+       gtk_widget_set_margin_left (GTK_WIDGET (grid), 10);
+
+       widget = e_html_editor_util_create_font_name_combo ();
+       g_signal_connect_swapped (
+               widget, "notify::active-id",
+               G_CALLBACK (html_editor_page_dialog_set_text_font_name), dialog);
+       gtk_grid_attach (grid, widget, 1, 0, 1, 1);
+       dialog->priv->text_font_name_combo = widget;
+
+       widget = gtk_label_new_with_mnemonic (_("_Font Name:"));
+       gtk_label_set_justify (GTK_LABEL (widget), GTK_JUSTIFY_RIGHT);
+       gtk_label_set_mnemonic_widget (
+               GTK_LABEL (widget), dialog->priv->text_font_name_combo);
+       gtk_grid_attach (grid, widget, 0, 0, 1, 1);
+
+       /* == Background Image == */
+       widget = gtk_label_new (_("Background Image"));
+       gtk_label_set_attributes (GTK_LABEL (widget), bold);
+       gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5);
+       gtk_grid_attach (main_layout, widget, 0, 4, 1, 1);
+
+       grid = GTK_GRID (gtk_grid_new ());
+       gtk_grid_set_row_spacing (grid, 5);
+       gtk_grid_set_column_spacing (grid, 5);
+       gtk_grid_attach (main_layout, GTK_WIDGET (grid), 0, 5, 1, 1);
        gtk_widget_set_margin_left (GTK_WIDGET (grid), 10);
 
        /* Template */
@@ -503,6 +553,8 @@ e_html_editor_page_dialog_init (EHTMLEditorPageDialog *dialog)
        gtk_box_reorder_child (box, widget, 0);
 
        gtk_widget_show_all (GTK_WIDGET (main_layout));
+
+       pango_attr_list_unref (bold);
 }
 
 GtkWidget *
diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h
index d65e565837..95bc87ab6e 100644
--- a/src/e-util/e-html-editor-private.h
+++ b/src/e-util/e-html-editor-private.h
@@ -82,6 +82,7 @@ struct _EHTMLEditorPrivate {
        GtkWidget *mode_combo_box;
        GtkWidget *size_combo_box;
        GtkWidget *style_combo_box;
+       GtkWidget *font_name_combo_box;
        GtkWidget *scrolled_window;
 
        GtkWidget *emoji_chooser;
@@ -104,6 +105,10 @@ void               editor_actions_update_spellcheck_languages_menu
                                                 const gchar * const *languages);
 const gchar *  e_html_editor_get_content_editor_name
                                                (EHTMLEditor *editor);
+GtkWidget *    e_html_editor_util_create_font_name_combo
+                                               (void);
+gchar *                e_html_editor_until_dup_font_id (GtkComboBox *combo_box,
+                                                const gchar *font_name);
 
 G_END_DECLS
 
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 00ebe50b2d..8846ea638f 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -95,6 +95,134 @@ G_DEFINE_TYPE_WITH_CODE (
                E_TYPE_ALERT_SINK,
                e_html_editor_alert_sink_init))
 
+/* See: https://www.w3schools.com/cssref/css_websafe_fonts.asp */
+static struct _SupportedFonts {
+       const gchar *display_name;
+       const gchar *css_value;
+} supported_fonts[] = {
+       { "Georgia", "Georgia, serif" },
+       { "Palatino", "\"Palatino Linotype\", \"Book Antiqua\", Palatino, serif" },
+       { "Times New Roman", "\"Times New Roman\", Times, serif" },
+       { "Arial", "Arial, Helvetica, sans-serif" },
+       { "Arial Black", "\"Arial Black\", Gadget, sans-serif" },
+       { "Comic Sans MS", "\"Comic Sans MS\", cursive, sans-serif" },
+       { "Impact", "Impact, Charcoal, sans-serif" },
+       { "Lucida Sans", "\"Lucida Sans Unicode\", \"Lucida Grande\", sans-serif" },
+       { "Tahoma", "Tahoma, Geneva, sans-serif" },
+       { "Trebuchet MS", "\"Trebuchet MS\", Helvetica, sans-serif" },
+       { "Verdana", "Verdana, Geneva, sans-serif" },
+       { "Monospace", "monospace" },
+       { "Courier New", "\"Courier New\", Courier, monospace" },
+       { "Lucida Console", "\"Lucida Console\", Monaco, monospace" }
+};
+
+GtkWidget *
+e_html_editor_util_create_font_name_combo (void)
+{
+       GtkComboBoxText *combo_box;
+       gint ii;
+
+       combo_box = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new ());
+
+       gtk_combo_box_text_append (combo_box, "", _("Default"));
+
+       for (ii = 0; ii < G_N_ELEMENTS (supported_fonts); ii++) {
+               gtk_combo_box_text_append (combo_box, supported_fonts[ii].css_value, 
supported_fonts[ii].display_name);
+       }
+
+       return GTK_WIDGET (combo_box);
+}
+
+gchar *
+e_html_editor_until_dup_font_id (GtkComboBox *combo_box,
+                                const gchar *font_name)
+{
+       GtkTreeModel *model;
+       GtkTreeIter iter;
+       GSList *free_str = NULL;
+       gchar *id = NULL, **variants;
+       gint id_column, ii;
+
+       g_return_val_if_fail (GTK_IS_COMBO_BOX_TEXT (combo_box), NULL);
+
+       if (!font_name || !*font_name)
+               return NULL;
+
+       for (ii = 0; ii < G_N_ELEMENTS (supported_fonts); ii++) {
+               if (camel_strcase_equal (supported_fonts[ii].css_value, font_name))
+                       return g_strdup (font_name);
+       }
+
+       id_column = gtk_combo_box_get_id_column (combo_box);
+       model = gtk_combo_box_get_model (combo_box);
+
+       if (gtk_tree_model_get_iter_first (model, &iter)) {
+               do {
+                       gchar *stored_id = NULL;
+
+                       gtk_tree_model_get (model, &iter, id_column, &stored_id, -1);
+
+                       if (stored_id && *stored_id) {
+                               if (camel_strcase_equal (stored_id, font_name)) {
+                                       id = stored_id;
+                                       break;
+                               }
+
+                               free_str = g_slist_prepend (free_str, stored_id);
+                       } else {
+                               g_free (stored_id);
+                       }
+               } while (gtk_tree_model_iter_next (model, &iter));
+       }
+
+       if (!id) {
+               GHashTable *known_fonts;
+               GSList *free_strv = NULL, *link;
+
+               known_fonts = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
+
+               for (link = free_str; link; link = g_slist_next (link)) {
+                       gchar *stored_id = link->data;
+
+                       variants = g_strsplit (stored_id, ",", -1);
+                       for (ii = 0; variants[ii]; ii++) {
+                               if (variants[ii][0] &&
+                                   !g_hash_table_contains (known_fonts, variants[ii])) {
+                                       g_hash_table_insert (known_fonts, variants[ii], stored_id);
+                               }
+                       }
+
+                       free_strv = g_slist_prepend (free_strv, variants);
+               }
+
+               variants = g_strsplit (font_name, ",", -1);
+               for (ii = 0; variants[ii]; ii++) {
+                       if (variants[ii][0]) {
+                               const gchar *stored_id;
+
+                               stored_id = g_hash_table_lookup (known_fonts, variants[ii]);
+                               if (stored_id) {
+                                       id = g_strdup (stored_id);
+                                       break;
+                               }
+                       }
+               }
+
+               if (!id) {
+                       gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo_box), font_name, variants[0]);
+                       id = g_strdup (font_name);
+               }
+
+               g_hash_table_destroy (known_fonts);
+               g_slist_free_full (free_strv, (GDestroyNotify) g_strfreev);
+               g_strfreev (variants);
+       }
+
+       g_slist_free_full (free_str, g_free);
+
+       return id;
+}
+
 /* Action callback for context menu spelling suggestions.
  * XXX This should really be in e-html-editor-actions.c */
 static void
@@ -793,6 +921,15 @@ html_editor_constructed (GObject *object)
        priv->size_combo_box = g_object_ref (widget);
        gtk_widget_show_all (GTK_WIDGET (tool_item));
 
+       tool_item = gtk_tool_item_new ();
+       widget = e_html_editor_util_create_font_name_combo ();
+       gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE);
+       gtk_container_add (GTK_CONTAINER (tool_item), widget);
+       gtk_widget_set_tooltip_text (widget, _("Font Name"));
+       gtk_toolbar_insert (toolbar, tool_item, 0);
+       priv->font_name_combo_box = g_object_ref (widget);
+       gtk_widget_show_all (GTK_WIDGET (tool_item));
+
        g_signal_connect_after (object, "realize", G_CALLBACK (html_editor_realize), NULL);
 }
 
@@ -825,6 +962,7 @@ html_editor_dispose (GObject *object)
        g_clear_object (&priv->bg_color_combo_box);
        g_clear_object (&priv->mode_combo_box);
        g_clear_object (&priv->size_combo_box);
+       g_clear_object (&priv->font_name_combo_box);
        g_clear_object (&priv->style_combo_box);
 
        /* Chain up to parent's dispose() method. */
diff --git a/src/e-util/test-html-editor-units-utils.c b/src/e-util/test-html-editor-units-utils.c
index a0c72ed4f7..609cfd0a56 100644
--- a/src/e-util/test-html-editor-units-utils.c
+++ b/src/e-util/test-html-editor-units-utils.c
@@ -878,6 +878,21 @@ test_utils_execute_action (TestFixture *fixture,
        return TRUE;
 }
 
+static gboolean
+test_utils_set_font_name (TestFixture *fixture,
+                         const gchar *font_name)
+{
+       EContentEditor *cnt_editor;
+
+       g_return_val_if_fail (fixture != NULL, FALSE);
+       g_return_val_if_fail (E_IS_HTML_EDITOR (fixture->editor), FALSE);
+
+       cnt_editor = e_html_editor_get_content_editor (fixture->editor);
+       e_content_editor_set_font_name (cnt_editor, font_name);
+
+       return TRUE;
+}
+
 /* Expects only the part like "undo" [ ":" number ] */
 static gint
 test_utils_maybe_extract_undo_number (const gchar *command)
@@ -922,6 +937,7 @@ test_utils_pick_undo_content (const GSList *undo_stack,
 
    command   = actioncmd ; Execute an action
              / modecmd   ; Change editor mode to HTML or Plain Text
+             / fnmcmd    ; Set font name
              / seqcmd    ; Sequence of special key strokes
              / typecmd   ; Type a text
              / undocmd   ; Undo/redo commands
@@ -929,7 +945,9 @@ test_utils_pick_undo_content (const GSList *undo_stack,
 
    actioncmd = "action:" name
 
-   actioncmd = "mode:" ("html" / "plain")
+   modecmd   = "mode:" ("html" / "plain")
+
+   fnmcmd    = "font-name:" name
 
    seqcmd    = "seq:" sequence
 
@@ -996,6 +1014,8 @@ test_utils_process_commands (TestFixture *fixture,
                                success = FALSE;
                                g_warning ("%s: Unknown mode '%s'", G_STRFUNC, mode_change);
                        }
+               } else if (g_str_has_prefix (command, "font-name:")) {
+                       success = test_utils_set_font_name (fixture, command + 10);
                } else if (g_str_has_prefix (command, "seq:")) {
                        success = test_utils_process_sequence (fixture, command + 4);
                } else if (g_str_has_prefix (command, "type:")) {
diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c
index 7df77430c7..41e4bb793b 100644
--- a/src/e-util/test-html-editor-units.c
+++ b/src/e-util/test-html-editor-units.c
@@ -157,7 +157,7 @@ test_style_monospace_selection (TestFixture *fixture)
                "mode:html\n"
                "type:some monospace text\n"
                "seq:hCrcrCSrsc\n"
-               "action:monospaced\n",
+               "font-name:monospace\n",
                HTML_PREFIX "<div>some <font face=\"monospace\">monospace</font> text</div>" HTML_SUFFIX,
                "some monospace text\n"))
                g_test_fail ();
@@ -169,9 +169,9 @@ test_style_monospace_typed (TestFixture *fixture)
        if (!test_utils_run_simple_test (fixture,
                "mode:html\n"
                "type:some \n"
-               "action:monospaced\n"
+               "font-name:monospace\n"
                "type:monospace\n"
-               "action:monospaced\n"
+               "font-name:\n"
                "type: text\n",
                HTML_PREFIX "<div>some <font face=\"monospace\">monospace</font> text</div>" HTML_SUFFIX,
                "some monospace text\n"))
@@ -2342,7 +2342,7 @@ test_undo_style (TestFixture *fixture)
                "undo:drop\n" /* drop the save 2 */
                "undo:undo:14\n"
 
-               "action:monospaced\n"
+               "font-name:monospace\n"
                "type:monospaced\n"
                "undo:save\n" /* 2 */
                "undo:undo:11\n"
@@ -2353,7 +2353,7 @@ test_undo_style (TestFixture *fixture)
                "undo:undo:11\n"
                "type:monospaced\n"
                "seq:CSlsc\n"
-               "action:monospaced\n"
+               "font-name:monospace\n"
                "undo:save\n" /* 2 */
                "undo:undo:11\n"
                "undo:test:2\n"
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index f2510283d7..1a50733a84 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -60,7 +60,6 @@ enum {
        PROP_FONT_SIZE,
        PROP_INDENTED,
        PROP_ITALIC,
-       PROP_MONOSPACED,
        PROP_STRIKETHROUGH,
        PROP_SUBSCRIPT,
        PROP_SUPERSCRIPT,
@@ -108,6 +107,7 @@ struct _EWebKitEditorPrivate {
        GdkRGBA theme_vlink_color;
 
        gchar *font_name;
+       gchar *body_font_name;
 
        guint font_size;
 
@@ -160,12 +160,11 @@ static const GdkRGBA transparent = { 0, 0, 0, 0 };
 typedef enum {
        E_WEBKIT_EDITOR_STYLE_NONE              = 0,
        E_WEBKIT_EDITOR_STYLE_IS_BOLD           = 1 << 0,
-       E_WEBKIT_EDITOR_STYLE_IS_ITALIC = 1 << 1,
+       E_WEBKIT_EDITOR_STYLE_IS_ITALIC         = 1 << 1,
        E_WEBKIT_EDITOR_STYLE_IS_UNDERLINE      = 1 << 2,
        E_WEBKIT_EDITOR_STYLE_IS_STRIKETHROUGH  = 1 << 3,
-       E_WEBKIT_EDITOR_STYLE_IS_MONOSPACE      = 1 << 4,
-       E_WEBKIT_EDITOR_STYLE_IS_SUBSCRIPT      = 1 << 5,
-       E_WEBKIT_EDITOR_STYLE_IS_SUPERSCRIPT    = 1 << 6
+       E_WEBKIT_EDITOR_STYLE_IS_SUBSCRIPT      = 1 << 4,
+       E_WEBKIT_EDITOR_STYLE_IS_SUPERSCRIPT    = 1 << 5
 } EWebKitEditorStyleFlags;
 
 typedef void (*PostReloadOperationFunc) (EWebKitEditor *wk_editor, gpointer data, 
EContentEditorInsertContentFlags flags);
@@ -602,20 +601,6 @@ formatting_changed_cb (WebKitUserContentManager *manager,
        }
        g_clear_object (&jsc_value);
 
-       changed = FALSE;
-       jsc_value = jsc_value_object_get_property (jsc_params, "fontFamily");
-       if (jsc_value && jsc_value_is_string (jsc_value)) {
-               gchar *value = jsc_value_to_string (jsc_value);
-
-               if (g_strcmp0 (value, wk_editor->priv->font_name) != 0) {
-                       update_style_flag (E_WEBKIT_EDITOR_STYLE_IS_MONOSPACE, g_strcmp0 (value, "monospace") 
== 0);
-                       changed = TRUE;
-               }
-
-               g_free (value);
-       }
-       g_clear_object (&jsc_value);
-
        wk_editor->priv->temporary_style_flags = wk_editor->priv->style_flags;
 
        #undef update_style_flag
@@ -653,6 +638,19 @@ formatting_changed_cb (WebKitUserContentManager *manager,
        if (changed || forced)
                g_object_notify (object, "font-name");
 
+       jsc_value = jsc_value_object_get_property (jsc_params, "bodyFontFamily");
+       if (jsc_value && jsc_value_is_string (jsc_value)) {
+               gchar *value = jsc_value_to_string (jsc_value);
+
+               if (g_strcmp0 (value, wk_editor->priv->body_font_name) != 0) {
+                       g_free (wk_editor->priv->body_font_name);
+                       wk_editor->priv->body_font_name = value;
+               } else {
+                       g_free (value);
+               }
+       }
+       g_clear_object (&jsc_value);
+
        if (webkit_editor_update_color_value (jsc_params, "fgColor", &wk_editor->priv->font_color) || forced)
                g_object_notify (object, "font-color");
 
@@ -1517,6 +1515,28 @@ webkit_editor_page_get_visited_link_color (EContentEditor *editor,
        }
 }
 
+static void
+webkit_editor_page_set_font_name (EContentEditor *editor,
+                                 const gchar *value)
+{
+       EWebKitEditor *wk_editor = E_WEBKIT_EDITOR (editor);
+
+       e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
+               "EvoEditor.SetBodyFontName(%s);",
+               value ? value : "");
+}
+
+static const gchar *
+webkit_editor_page_get_font_name (EContentEditor *editor)
+{
+       EWebKitEditor *wk_editor = E_WEBKIT_EDITOR (editor);
+
+       if (!wk_editor->priv->html_mode)
+               return NULL;
+
+       return wk_editor->priv->body_font_name;
+}
+
 static void
 get_color_from_context (GtkStyleContext *context,
                         const gchar *name,
@@ -3777,7 +3797,9 @@ webkit_editor_set_font_name (EWebKitEditor *wk_editor,
 {
        g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
 
-       webkit_web_view_execute_editing_command_with_argument (WEBKIT_WEB_VIEW (wk_editor), "FontName", 
value);
+       e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
+               "EvoEditor.SetFontName(%s);",
+               value ? value : "");
 }
 
 static const gchar *
@@ -3785,6 +3807,9 @@ webkit_editor_get_font_name (EWebKitEditor *wk_editor)
 {
        g_return_val_if_fail (E_IS_WEBKIT_EDITOR (wk_editor), NULL);
 
+       if (!wk_editor->priv->html_mode)
+               return NULL;
+
        return wk_editor->priv->font_name;
 }
 
@@ -3875,11 +3900,6 @@ webkit_editor_set_style_flag (EWebKitEditor *wk_editor,
        case E_WEBKIT_EDITOR_STYLE_IS_STRIKETHROUGH:
                webkit_web_view_execute_editing_command (WEBKIT_WEB_VIEW (wk_editor), "Strikethrough");
                break;
-       case E_WEBKIT_EDITOR_STYLE_IS_MONOSPACE:
-               e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
-                       "EvoEditor.SetFontName(%s);",
-                       do_set ? "monospace" : "");
-               break;
        case E_WEBKIT_EDITOR_STYLE_IS_SUBSCRIPT:
                webkit_web_view_execute_editing_command (WEBKIT_WEB_VIEW (wk_editor), "Subscript");
                break;
@@ -5334,6 +5354,7 @@ webkit_editor_finalize (GObject *object)
        g_clear_object (&priv->cancellable);
        g_clear_error (&priv->last_error);
 
+       g_free (priv->body_font_name);
        g_free (priv->font_name);
 
        /* Chain up to parent's finalize() method. */
@@ -5415,13 +5436,6 @@ webkit_editor_set_property (GObject *object,
                                g_value_get_boolean (value));
                        return;
 
-               case PROP_MONOSPACED:
-                       webkit_editor_set_style_flag (
-                               E_WEBKIT_EDITOR (object),
-                               E_WEBKIT_EDITOR_STYLE_IS_MONOSPACE,
-                               g_value_get_boolean (value));
-                       return;
-
                case PROP_STRIKETHROUGH:
                        webkit_editor_set_style_flag (
                                E_WEBKIT_EDITOR (object),
@@ -5610,14 +5624,6 @@ webkit_editor_get_property (GObject *object,
                                        E_WEBKIT_EDITOR_STYLE_IS_ITALIC));
                        return;
 
-               case PROP_MONOSPACED:
-                       g_value_set_boolean (
-                               value,
-                               webkit_editor_get_style_flag (
-                                       E_WEBKIT_EDITOR (object),
-                                       E_WEBKIT_EDITOR_STYLE_IS_MONOSPACE));
-                       return;
-
                case PROP_STRIKETHROUGH:
                        g_value_set_boolean (
                                value,
@@ -6391,8 +6397,6 @@ e_webkit_editor_class_init (EWebKitEditorClass *class)
                object_class, PROP_INDENTED, "indented");
        g_object_class_override_property (
                object_class, PROP_ITALIC, "italic");
-       g_object_class_override_property (
-               object_class, PROP_MONOSPACED, "monospaced");
        g_object_class_override_property (
                object_class, PROP_STRIKETHROUGH, "strikethrough");
        g_object_class_override_property (
@@ -6527,6 +6531,7 @@ e_webkit_editor_init (EWebKitEditor *wk_editor)
 
        wk_editor->priv->font_color = NULL;
        wk_editor->priv->background_color = NULL;
+       wk_editor->priv->body_font_name = NULL;
        wk_editor->priv->font_name = NULL;
        wk_editor->priv->font_size = E_CONTENT_EDITOR_FONT_SIZE_NORMAL;
        wk_editor->priv->block_format = E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH;
@@ -6629,6 +6634,8 @@ e_webkit_editor_content_editor_init (EContentEditorInterface *iface)
        iface->page_get_link_color = webkit_editor_page_get_link_color;
        iface->page_set_visited_link_color = webkit_editor_page_set_visited_link_color;
        iface->page_get_visited_link_color = webkit_editor_page_get_visited_link_color;
+       iface->page_set_font_name = webkit_editor_page_set_font_name;
+       iface->page_get_font_name = webkit_editor_page_get_font_name;
        iface->page_set_background_image_uri = webkit_editor_page_set_background_image_uri;
        iface->page_get_background_image_uri = webkit_editor_page_get_background_image_uri;
        iface->on_page_dialog_open = webkit_editor_on_page_dialog_open;


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