[evolution] Bug 744849 - Insert->Emoticon deletes text before cursor



commit 8ae0b622cd150cde7b661b3bccace30a2eb22de8
Author: Tomas Popela <tpopela redhat com>
Date:   Fri Feb 20 14:03:34 2015 +0100

    Bug 744849 - Insert->Emoticon deletes text before cursor
    
    The problem was that it was expecting that the newly inserted smiley
    was written (and not inserted through the picker). So we have to
    remember if the smiley was written or not. Another problem was that we
    were checking just the first character of the written smiley
    (typically just colon). I also rewrote the string manipulations around
    the smileys into DOM operations.

 e-util/e-html-editor-view.c |   86 ++++++++++++++++++++++++++----------------
 1 files changed, 53 insertions(+), 33 deletions(-)
---
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index c6eeafe..6363b52 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -104,6 +104,7 @@ struct _EHTMLEditorViewPrivate {
        gboolean remove_initial_input_line;
        gboolean return_key_pressed;
        gboolean space_key_pressed;
+       gboolean smiley_written;
 
        GHashTable *old_settings;
 
@@ -1432,14 +1433,14 @@ emoticon_load_context_free (LoadContext *load_context)
 static void
 emoticon_insert_span (EHTMLEditorView *view,
                       EEmoticon *emoticon,
-                      const gchar *html)
+                      WebKitDOMElement *span)
 {
        EHTMLEditorSelection *selection;
        gboolean misplaced_selection = FALSE, empty = FALSE;
-       gchar *final_html, *node_text = NULL, *content;
+       gchar *node_text = NULL, *content;
        const gchar *emoticon_start;
        WebKitDOMDocument *document;
-       WebKitDOMElement *span, *selection_start_marker, *selection_end_marker;
+       WebKitDOMElement *selection_start_marker, *selection_end_marker;
        WebKitDOMNode *node, *insert_before, *prev_sibling, *next_sibling;
        WebKitDOMNode *selection_end_marker_parent;
        WebKitDOMRange *range;
@@ -1521,11 +1522,6 @@ emoticon_insert_span (EHTMLEditorView *view,
        empty = !*content || (g_strcmp0 (content, UNICODE_ZERO_WIDTH_SPACE) == 0);
        g_free (content);
 
-       /* &#8203 == UNICODE_ZERO_WIDTH_SPACE */
-       final_html = g_strdup_printf ("%s%s", html, empty ? "&#8203;" : "");
-
-       span = webkit_dom_document_create_element (document, "SPAN", NULL);
-
        if (misplaced_selection) {
                /* Insert smiley and selection markers after it */
                webkit_dom_node_insert_before (
@@ -1553,26 +1549,31 @@ emoticon_insert_span (EHTMLEditorView *view,
                                NULL));
        }
 
-       webkit_dom_html_element_set_outer_html (
-               WEBKIT_DOM_HTML_ELEMENT (span), final_html, NULL);
+       /* &#8203 == UNICODE_ZERO_WIDTH_SPACE */
+       if (empty)
+               webkit_dom_html_element_insert_adjacent_html (
+                       WEBKIT_DOM_HTML_ELEMENT (span), "afterend", "&#8203;", NULL);
 
-       if (node_text) {
+       /* Remove the text that represents the text version of smiley that was
+        * written into the composer. */
+       if (node_text && view->priv->smiley_written) {
                emoticon_start = g_utf8_strrchr (
                        node_text, -1, g_utf8_get_char (emoticon->text_face));
-               if (emoticon_start) {
+               /* Check if the written smiley is really the one that we inserted. */
+               if (emoticon_start && g_str_has_prefix (emoticon_start, emoticon->text_face)) {
                        webkit_dom_character_data_delete_data (
                                WEBKIT_DOM_CHARACTER_DATA (node),
                                g_utf8_strlen (node_text, -1) - strlen (emoticon_start),
                                strlen (emoticon->text_face),
                                NULL);
                }
+               view->priv->smiley_written = FALSE;
        }
 
        e_html_editor_selection_restore (selection);
 
        e_html_editor_view_set_changed (view, TRUE);
 
-       g_free (final_html);
        g_free (node_text);
 }
 
@@ -1585,11 +1586,13 @@ emoticon_read_async_cb (GFile *file,
        EEmoticon *emoticon = load_context->emoticon;
        GError *error = NULL;
        gboolean html_mode;
-       gchar *html, *mime_type;
+       gchar *mime_type;
        gchar *base64_encoded, *output, *data;
        GFileInputStream *input_stream;
        GOutputStream *output_stream;
        gssize size;
+       WebKitDOMElement *wrapper, *image, *smiley_text;
+       WebKitDOMDocument *document;
 
        input_stream = g_file_read_finish (file, result, &error);
        g_return_if_fail (!error && input_stream);
@@ -1611,22 +1614,34 @@ emoticon_read_async_cb (GFile *file,
 
        html_mode = e_html_editor_view_get_html_mode (view);
 
+       document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
        /* Insert span with image representation and another one with text
         * represetation and hide/show them dependant on active composer mode */
-       html = g_strdup_printf (
-               "<span class=\"-x-evo-smiley-wrapper -x-evo-resizable-wrapper\">"
-               "<img src=\"%s\" alt=\"%s\" x-evo-smiley=\"%s\" "
-               "class=\"-x-evo-smiley-img\" data-inline data-name=\"%s\"%s/>"
-               "<span class=\"-x-evo-smiley-text\"%s>%s</span></span>",
-               output, emoticon ? emoticon->text_face : "",
-               emoticon->icon_name, load_context->name,
-               html_mode ? "" : " style=\"display: none;\"",
-               html_mode ? " style=\"display: none;\"" : "",
-               emoticon ? emoticon->text_face : "");
-
-       emoticon_insert_span (view, emoticon, html);
-
-       g_free (html);
+       wrapper = webkit_dom_document_create_element (document, "SPAN", NULL);
+       webkit_dom_element_set_attribute (
+               wrapper, "class", "-x-evo-smiley-wrapper -x-evo-resizable-wrapper", NULL);
+
+       image = webkit_dom_document_create_element (document, "IMG", NULL);
+       webkit_dom_element_set_attribute (image, "src", output, NULL);
+       webkit_dom_element_set_attribute (image, "alt", emoticon->text_face, NULL);
+       webkit_dom_element_set_attribute (image, "-x-evo-smiley", emoticon->icon_name, NULL);
+       webkit_dom_element_set_attribute (image, "class", "-x-evo-smiley-img", NULL);
+       if (!html_mode)
+               webkit_dom_element_set_attribute (image, "style", "display: none;", NULL);
+       webkit_dom_node_append_child (
+               WEBKIT_DOM_NODE (wrapper), WEBKIT_DOM_NODE (image), NULL);
+
+       smiley_text = webkit_dom_document_create_element (document, "SPAN", NULL);
+       webkit_dom_element_set_attribute (smiley_text, "class", "-x-evo-smiley-text", NULL);
+       if (html_mode)
+               webkit_dom_element_set_attribute (smiley_text, "style", "display: none;", NULL);
+       webkit_dom_html_element_set_inner_text (
+               WEBKIT_DOM_HTML_ELEMENT (smiley_text), emoticon->text_face, NULL);
+       webkit_dom_node_append_child (
+               WEBKIT_DOM_NODE (wrapper), WEBKIT_DOM_NODE (smiley_text), NULL);
+
+       emoticon_insert_span (view, emoticon, wrapper);
+
        g_free (base64_encoded);
        g_free (output);
        g_free (mime_type);
@@ -1661,16 +1676,19 @@ e_html_editor_view_insert_smiley (EHTMLEditorView *view,
                                   EEmoticon *emoticon)
 {
        GFile *file;
-       gchar *html, *filename_uri;
+       gchar *filename_uri;
        LoadContext *load_context;
 
        if (e_html_editor_view_get_unicode_smileys (view)) {
-               html = g_strdup_printf ("<span>%s</span>",
-                       emoticon->unicode_character);
+               WebKitDOMDocument *document;
+               WebKitDOMElement *wrapper;
 
-               emoticon_insert_span (view, emoticon, html);
+               document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
+               wrapper = webkit_dom_document_create_element (document, "SPAN", NULL);
+               webkit_dom_html_element_set_inner_text (
+                       WEBKIT_DOM_HTML_ELEMENT (wrapper), emoticon->unicode_character, NULL);
 
-               g_free (html);
+               emoticon_insert_span (view, emoticon, wrapper);
        } else {
                filename_uri = e_emoticon_get_uri (emoticon);
                g_return_if_fail (filename_uri != NULL);
@@ -1751,6 +1769,7 @@ html_editor_view_check_magic_smileys (EHTMLEditorView *view,
 
                emoticon = (e_emoticon_chooser_lookup_emoticon (
                        emoticons_icon_names[-state - 1]));
+               view->priv->smiley_written = TRUE;
                e_html_editor_view_insert_smiley (view, (EEmoticon *) emoticon);
        }
 
@@ -7748,6 +7767,7 @@ e_html_editor_view_init (EHTMLEditorView *view)
        view->priv->convert_in_situ = FALSE;
        view->priv->return_key_pressed = FALSE;
        view->priv->space_key_pressed = FALSE;
+       view->priv->smiley_written = FALSE;
 
        g_object_set (
                G_OBJECT (settings),


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