static void composer_move_caret (EMsgComposer *composer) { EHTMLEditor *editor; EHTMLEditorView *view; EHTMLEditorSelection *editor_selection; GSettings *settings; gboolean start_bottom, top_signature; gboolean is_message_from_draft; gboolean is_message_from_edit_as_new; gboolean has_paragraphs_in_body = TRUE; WebKitDOMDocument *document; WebKitDOMElement *element, *signature; WebKitDOMHTMLElement *body; WebKitDOMNodeList *list; /* When there is an option composer-reply-start-bottom set we have * to move the caret between reply and signature. */ settings = e_util_ref_settings ("org.gnome.evolution.mail"); start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom"); g_object_unref (settings); editor = e_msg_composer_get_editor (composer); view = e_html_editor_get_view (editor); editor_selection = e_html_editor_view_get_selection (view); is_message_from_draft = e_html_editor_view_is_message_from_draft (view); is_message_from_edit_as_new = e_html_editor_view_is_message_from_edit_as_new (view); top_signature = use_top_signature (composer) && !is_message_from_edit_as_new && !composer->priv->is_from_new_message; document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); body = webkit_dom_document_get_body (document); webkit_dom_element_set_attribute ( WEBKIT_DOM_ELEMENT (body), "data-message", "", NULL); /* If editing message as new don't handle with caret */ if (is_message_from_edit_as_new || is_message_from_draft) { if (is_message_from_edit_as_new) webkit_dom_element_set_attribute ( WEBKIT_DOM_ELEMENT (body), "data-edit-as-new", "", NULL); if (is_message_from_edit_as_new && !is_message_from_draft) { element = WEBKIT_DOM_ELEMENT (body); e_html_editor_selection_block_selection_changed (editor_selection); goto move_caret; } else e_html_editor_selection_scroll_to_caret (editor_selection); return; } e_html_editor_selection_block_selection_changed (editor_selection); /* When the new message is written from the beginning - note it into body */ if (composer->priv->is_from_new_message) webkit_dom_element_set_attribute ( WEBKIT_DOM_ELEMENT (body), "data-new-message", "", NULL); list = webkit_dom_document_get_elements_by_class_name (document, "-x-evo-paragraph"); signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL); /* Situation when wrapped paragraph is just in signature and not in message body */ if (webkit_dom_node_list_get_length (list) == 1) if (signature && webkit_dom_element_query_selector (signature, ".-x-evo-paragraph", NULL)) has_paragraphs_in_body = FALSE; /* * * Keeping Signatures in the beginning of composer * ------------------------------------------------ * * Purists are gonna blast me for this. * But there are so many people (read Outlook users) who want this. * And Evo is an exchange-client, Outlook-replacement etc. * So Here it goes :( * * -- Sankar * */ if (signature && top_signature) { WebKitDOMElement *spacer; spacer = prepare_top_signature_spacer (editor_selection, document); webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (spacer), webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (signature)), NULL); } if (webkit_dom_node_list_get_length (list) == 0) has_paragraphs_in_body = FALSE; element = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start"); if (!signature) { if (start_bottom) { if (!element) { element = prepare_paragraph (editor_selection, document); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } } else element = WEBKIT_DOM_ELEMENT (body); g_object_unref (list); goto move_caret; } if (!has_paragraphs_in_body) { element = prepare_paragraph (editor_selection, document); if (top_signature) { if (start_bottom) { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } else { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } } else { if (start_bottom) webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); else element = WEBKIT_DOM_ELEMENT (body); } } else { if (!element && top_signature) { element = prepare_paragraph (editor_selection, document); if (start_bottom) { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } else { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } } else if (element && top_signature && !start_bottom) { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } else if (element && start_bottom) { /* Leave it how it is */ } else element = WEBKIT_DOM_ELEMENT (body); } g_object_unref (list); move_caret: if (element) { WebKitDOMDOMSelection *dom_selection; WebKitDOMDOMWindow *dom_window; WebKitDOMRange *range; dom_window = webkit_dom_document_get_default_view (document); dom_selection = webkit_dom_dom_window_get_selection (dom_window); range = webkit_dom_document_create_range (document); webkit_dom_range_select_node_contents ( range, WEBKIT_DOM_NODE (element), NULL); webkit_dom_range_collapse (range, TRUE, NULL); webkit_dom_dom_selection_remove_all_ranges (dom_selection); webkit_dom_dom_selection_add_range (dom_selection, range); g_clear_object (&dom_selection); g_clear_object (&dom_window); g_clear_object (&range); if (start_bottom) e_html_editor_selection_scroll_to_caret (editor_selection); } if (start_bottom) g_signal_connect ( view, "size-allocate", G_CALLBACK (composer_size_allocate_cb), NULL); e_html_editor_view_force_spell_check_in_viewport (view); e_html_editor_selection_unblock_selection_changed (editor_selection); }
/** * e_html_editor_dom_node_find_parent_element: * @node: Start node * @tagname: Tag name of element to search * * Recursively searches for first occurance of element with given @tagname * that is parent of given @node. * * Returns: A #WebKitDOMElement with @tagname representing parent of @node or * @NULL when @node has no parent with given @tagname. When @node matches @tagname, * then the @node is returned. */ WebKitDOMElement * e_html_editor_dom_node_find_parent_element (WebKitDOMNode *node, const gchar *tagname) { gint taglen = strlen (tagname); while (node) { if (WEBKIT_DOM_IS_ELEMENT (node)) { gchar *node_tagname; node_tagname = webkit_dom_element_get_tag_name ( WEBKIT_DOM_ELEMENT (node)); if (node_tagname && (strlen (node_tagname) == taglen) && (g_ascii_strncasecmp (node_tagname, tagname, taglen) == 0)) { g_free (node_tagname); return WEBKIT_DOM_ELEMENT (node); } g_free (node_tagname); } node = WEBKIT_DOM_NODE (webkit_dom_node_get_parent_element (node)); } return NULL; }
/** * e_html_editor_dom_node_find_child_element: * @node: Start node * @tagname: Tag name of element to search. * * Recursively searches for first occurrence of element with given @tagname that * is a child of @node. * * Returns: A #WebKitDOMElement with @tagname representing a child of @node or * @NULL when @node has no child with given @tagname. When @node matches @tagname, * then the @node is returned. */ WebKitDOMElement * e_html_editor_dom_node_find_child_element (WebKitDOMNode *node, const gchar *tagname) { WebKitDOMNode *start_node = node; gint taglen = strlen (tagname); do { if (WEBKIT_DOM_IS_ELEMENT (node)) { gchar *node_tagname; node_tagname = webkit_dom_element_get_tag_name ( WEBKIT_DOM_ELEMENT (node)); if (node_tagname && (strlen (node_tagname) == taglen) && (g_ascii_strncasecmp (node_tagname, tagname, taglen) == 0)) { g_free (node_tagname); return WEBKIT_DOM_ELEMENT (node); } g_free (node_tagname); } if (webkit_dom_node_has_child_nodes (node)) { node = webkit_dom_node_get_first_child (node); } else if (webkit_dom_node_get_next_sibling (node)) { node = webkit_dom_node_get_next_sibling (node); } else { node = webkit_dom_node_get_parent_node (node); } } while (!webkit_dom_node_is_same_node (node, start_node)); return NULL; }
static void html_editor_image_dialog_set_height_units (EHTMLEditorImageDialog *dialog) { gint requested; gulong natural; gint height = -1; natural = webkit_dom_html_image_element_get_natural_height ( dialog->priv->image); requested = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->priv->height_edit)); switch (gtk_combo_box_get_active ( GTK_COMBO_BOX (dialog->priv->height_units))) { case 0: /* px */ if (gtk_widget_is_sensitive (dialog->priv->height_edit)) { height = requested * natural * 0.01; } else { height = natural; } webkit_dom_element_remove_attribute ( WEBKIT_DOM_ELEMENT (dialog->priv->image), "style"); gtk_widget_set_sensitive (dialog->priv->height_edit, TRUE); break; case 1: /* percent */ if (gtk_widget_is_sensitive (dialog->priv->height_edit)) { height = (((gdouble) requested) / natural) * 100; } else { height = 100; } webkit_dom_element_remove_attribute ( WEBKIT_DOM_ELEMENT (dialog->priv->image), "style"); gtk_widget_set_sensitive (dialog->priv->height_edit, TRUE); break; case 2: /* follow */ webkit_dom_element_set_attribute ( WEBKIT_DOM_ELEMENT (dialog->priv->image), "style", "height: auto;", NULL); gtk_widget_set_sensitive (dialog->priv->height_edit, FALSE); break; } if (height != -1) { gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->height_edit), height); } }
// document_scroll_cb is called when the document is scrolled, and updates // the main processes knowledge of the document. static void document_scroll_cb(WebKitDOMEventTarget *target, WebKitDOMEvent *event, gpointer user_data) { Exten *exten = user_data; WebKitDOMDocument *dom = WEBKIT_DOM_DOCUMENT(target); WebKitDOMElement *e = NULL; if(dom != NULL) { e = WEBKIT_DOM_ELEMENT(webkit_dom_document_get_body(dom)); } // Check for current scroll position. If it has changed, signal DBus. if(e != NULL) { glong top = webkit_dom_element_get_scroll_top(e); glong height = webkit_dom_element_get_scroll_height(e); if(top != exten->last_top || height != exten->last_height) { exten->last_top = top; exten->last_height = height; vertical_position_changed(exten->page_id, top, height, exten); } } if(dom != NULL) { e = webkit_dom_document_get_active_element(dom); } }
gboolean e_editor_selection_get_superscript (EEditorSelection *selection) { WebKitDOMNode *node; WebKitDOMRange *range; g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), FALSE); range = editor_selection_get_current_range (selection); node = webkit_dom_range_get_common_ancestor_container (range, NULL); while (node) { gchar *tag_name; tag_name = webkit_dom_element_get_tag_name (WEBKIT_DOM_ELEMENT (node)); if (g_ascii_strncasecmp (tag_name, "sup", 3) == 0) { g_free (tag_name); break; } g_free (tag_name); node = webkit_dom_node_get_parent_node (node); } return (node != NULL); }
static gboolean get_has_style (EEditorSelection *selection, const gchar *style_tag) { WebKitDOMNode *node; WebKitDOMElement *element; WebKitDOMRange *range; gboolean result; gint tag_len; range = editor_selection_get_current_range (selection); if (!range) return FALSE; node = webkit_dom_range_get_start_container (range, NULL); if (!WEBKIT_DOM_IS_ELEMENT (node)) element = webkit_dom_node_get_parent_element (node); else element = WEBKIT_DOM_ELEMENT (node); tag_len = strlen (style_tag); result = FALSE; while (!result && element) { gchar *element_tag; element_tag = webkit_dom_element_get_tag_name (element); result = ((tag_len == strlen (element_tag)) && (g_ascii_strncasecmp (element_tag, style_tag, tag_len) == 0)); /* Special case: <blockquote type=cite> marks quotation, while * just <blockquote> is used for indentation. If the <blockquote> * has type=cite, then ignore it */ if (result && g_ascii_strncasecmp (element_tag, "blockquote", 10) == 0) { if (webkit_dom_element_has_attribute (element, "type")) { gchar *type; type = webkit_dom_element_get_attribute ( element, "type"); if (g_ascii_strncasecmp (type, "cite", 4) == 0) { result = FALSE; } g_free (type); } } g_free (element_tag); if (result) { break; } element = webkit_dom_node_get_parent_element ( WEBKIT_DOM_NODE (element)); } return result; }
/** * Callback called when the document is scrolled. */ static void on_document_scroll(WebKitDOMEventTarget *target, WebKitDOMEvent *event, WebKitWebPage *page) { WebKitDOMDocument *doc; if (WEBKIT_DOM_IS_DOM_WINDOW(target)) { g_object_get(target, "document", &doc, NULL); } else { /* target is a doc document */ doc = WEBKIT_DOM_DOCUMENT(target); } if (doc) { WebKitDOMElement *body, *de; glong max = 0, scrollTop, scrollHeight, clientHeight; guint percent = 0; de = webkit_dom_document_get_document_element(doc); if (!de) { return; } body = WEBKIT_DOM_ELEMENT(webkit_dom_document_get_body(doc)); if (!body) { return; } scrollTop = webkit_dom_element_get_scroll_top(body); if (scrollTop) { clientHeight = webkit_dom_element_get_client_height(WEBKIT_DOM_ELEMENT(de)); scrollHeight = webkit_dom_element_get_scroll_height(body); /* Get the maximum scrollable page size. This is the size of the whole * document - height of the viewport. */ max = scrollHeight - clientHeight ; if (max) { percent = (guint)(0.5 + (scrollTop * 100 / max)); } } dbus_emit_signal("VerticalScroll", g_variant_new("(ttq)", webkit_web_page_get_id(page), max, percent)); } }
/** * Set focus to the first found editable element and returns if a element was * found to focus. */ gboolean dom_focus_input(WebKitWebView *view) { gboolean found = false; WebKitDOMNode *html, *node; WebKitDOMDocument *doc; WebKitDOMDOMWindow *win; WebKitDOMNodeList *list; WebKitDOMXPathNSResolver *resolver; WebKitDOMXPathResult* result; doc = webkit_web_view_get_dom_document(view); win = webkit_dom_document_get_default_view(doc); list = webkit_dom_document_get_elements_by_tag_name(doc, "html"); if (!list) { return false; } html = webkit_dom_node_list_item(list, 0); resolver = webkit_dom_document_create_ns_resolver(doc, html); if (!resolver) { return false; } result = webkit_dom_document_evaluate( doc, "//input[not(@type) or @type='text' or @type='password']|//textarea", html, resolver, 0, NULL, NULL ); if (!result) { return false; } while ((node = webkit_dom_xpath_result_iterate_next(result, NULL))) { if (element_is_visible(win, WEBKIT_DOM_ELEMENT(node))) { webkit_dom_element_focus(WEBKIT_DOM_ELEMENT(node)); found = true; break; } } g_object_unref(list); return found; }
gboolean e_html_editor_node_is_selection_position_node (WebKitDOMNode *node) { WebKitDOMElement *element; if (!node || !WEBKIT_DOM_IS_ELEMENT (node)) return FALSE; element = WEBKIT_DOM_ELEMENT (node); return element_has_id (element, "-x-evo-selection-start-marker") || element_has_id (element, "-x-evo-selection-end-marker"); }
const gchar * e_editor_selection_get_font_name (EEditorSelection *selection) { WebKitDOMNode *node; WebKitDOMRange *range; WebKitDOMCSSStyleDeclaration *css; g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), NULL); range = editor_selection_get_current_range (selection); node = webkit_dom_range_get_common_ancestor_container (range, NULL); g_free (selection->priv->font_family); css = webkit_dom_element_get_style (WEBKIT_DOM_ELEMENT (node)); selection->priv->font_family = webkit_dom_css_style_declaration_get_property_value (css, "fontFamily"); return selection->priv->font_family; }
static void html_editor_image_dialog_set_src (EHTMLEditorImageDialog *dialog) { EHTMLEditor *editor; EHTMLEditorSelection *editor_selection; EHTMLEditorView *view; gchar *uri; editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); view = e_html_editor_get_view (editor); editor_selection = e_html_editor_view_get_selection (view); uri = gtk_file_chooser_get_uri ( GTK_FILE_CHOOSER (dialog->priv->file_chooser)); e_html_editor_selection_replace_image_src ( editor_selection, WEBKIT_DOM_ELEMENT (dialog->priv->image), uri); g_free (uri); }
const gchar * e_editor_selection_get_background_color (EEditorSelection *selection) { WebKitDOMNode *ancestor; WebKitDOMRange *range; WebKitDOMCSSStyleDeclaration *css; g_return_val_if_fail (E_IS_EDITOR_SELECTION (selection), NULL); range = editor_selection_get_current_range (selection); ancestor = webkit_dom_range_get_common_ancestor_container (range, NULL); css = webkit_dom_element_get_style (WEBKIT_DOM_ELEMENT (ancestor)); selection->priv->background_color = webkit_dom_css_style_declaration_get_property_value ( css, "background-color"); return selection->priv->background_color; }
WebKitDOMNode * e_html_editor_get_parent_block_node_from_child (WebKitDOMNode *node) { WebKitDOMNode *parent = node; if (!WEBKIT_DOM_IS_ELEMENT (parent) || e_html_editor_node_is_selection_position_node (parent)) parent = webkit_dom_node_get_parent_node (parent); if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-temp-text-wrapper") || element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quoted") || element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quote-character") || element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-signature") || WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (parent) || element_has_tag (WEBKIT_DOM_ELEMENT (parent), "b") || element_has_tag (WEBKIT_DOM_ELEMENT (parent), "i") || element_has_tag (WEBKIT_DOM_ELEMENT (parent), "u")) parent = webkit_dom_node_get_parent_node (parent); if (element_has_class (WEBKIT_DOM_ELEMENT (parent), "-x-evo-quoted")) parent = webkit_dom_node_get_parent_node (parent); return parent; }
static void html_editor_image_dialog_show (GtkWidget *widget) { EHTMLEditorImageDialog *dialog; EHTMLEditor *editor; EHTMLEditorSelection *selection; EHTMLEditorView *view; WebKitDOMElement *link; gchar *tmp; glong val; dialog = E_HTML_EDITOR_IMAGE_DIALOG (widget); if (!dialog->priv->image) { return; } editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); view = e_html_editor_get_view (editor); selection = e_html_editor_view_get_selection (view); if (!e_html_editor_view_is_undo_redo_in_progress (view)) { EHTMLEditorViewHistoryEvent *ev; ev = g_new0 (EHTMLEditorViewHistoryEvent, 1); ev->type = HISTORY_IMAGE_DIALOG; e_html_editor_selection_get_selection_coordinates ( selection, &ev->before.start.x, &ev->before.start.y, &ev->before.end.x, &ev->before.end.y); ev->data.dom.from = webkit_dom_node_clone_node ( WEBKIT_DOM_NODE (dialog->priv->image), FALSE); dialog->priv->history_event = ev; } tmp = webkit_dom_element_get_attribute ( WEBKIT_DOM_ELEMENT (dialog->priv->image), "data-uri"); if (tmp && *tmp) { gtk_file_chooser_set_uri ( GTK_FILE_CHOOSER (dialog->priv->file_chooser), tmp); gtk_widget_set_sensitive ( GTK_WIDGET (dialog->priv->file_chooser), TRUE); } else { gtk_file_chooser_set_uri ( GTK_FILE_CHOOSER (dialog->priv->file_chooser), ""); gtk_widget_set_sensitive ( GTK_WIDGET (dialog->priv->file_chooser), FALSE); } g_free (tmp); tmp = webkit_dom_html_image_element_get_alt (dialog->priv->image); gtk_entry_set_text (GTK_ENTRY (dialog->priv->description_edit), tmp ? tmp : ""); g_free (tmp); val = webkit_dom_html_image_element_get_width (dialog->priv->image); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->width_edit), val); gtk_combo_box_set_active_id ( GTK_COMBO_BOX (dialog->priv->width_units), "units-px"); val = webkit_dom_html_image_element_get_height (dialog->priv->image); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->height_edit), val); gtk_combo_box_set_active_id ( GTK_COMBO_BOX (dialog->priv->height_units), "units-px"); tmp = webkit_dom_html_image_element_get_border (dialog->priv->image); gtk_combo_box_set_active_id ( GTK_COMBO_BOX (dialog->priv->alignment), (tmp && *tmp) ? tmp : "bottom"); g_free (tmp); val = webkit_dom_html_image_element_get_hspace (dialog->priv->image); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->x_padding_edit), val); val = webkit_dom_html_image_element_get_vspace (dialog->priv->image); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->y_padding_edit), val); link = e_html_editor_dom_node_find_parent_element ( WEBKIT_DOM_NODE (dialog->priv->image), "A"); if (link) { tmp = webkit_dom_html_anchor_element_get_href ( WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link)); gtk_entry_set_text (GTK_ENTRY (dialog->priv->url_edit), tmp); g_free (tmp); } /* Chain up to parent implementation */ GTK_WIDGET_CLASS (e_html_editor_image_dialog_parent_class)->show (widget); }
static void html_editor_link_dialog_ok (EHTMLEditorLinkDialog *dialog) { EHTMLEditor *editor; EHTMLEditorView *view; EHTMLEditorSelection *selection; WebKitDOMDocument *document; WebKitDOMDOMWindow *dom_window; WebKitDOMDOMSelection *dom_selection; WebKitDOMRange *range; WebKitDOMElement *link; editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); view = e_html_editor_get_view (editor); selection = e_html_editor_view_get_selection (view); document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); dom_window = webkit_dom_document_get_default_view (document); dom_selection = webkit_dom_dom_window_get_selection (dom_window); g_object_unref (dom_window); if (!dom_selection || (webkit_dom_dom_selection_get_range_count (dom_selection) == 0)) { gtk_widget_hide (GTK_WIDGET (dialog)); g_object_unref (dom_selection); return; } range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL); link = e_html_editor_dom_node_find_parent_element ( webkit_dom_range_get_start_container (range, NULL), "A"); if (!link) { if ((webkit_dom_range_get_start_container (range, NULL) != webkit_dom_range_get_end_container (range, NULL)) || (webkit_dom_range_get_start_offset (range, NULL) != webkit_dom_range_get_end_offset (range, NULL))) { WebKitDOMDocumentFragment *fragment; fragment = webkit_dom_range_extract_contents (range, NULL); link = e_html_editor_dom_node_find_child_element ( WEBKIT_DOM_NODE (fragment), "A"); webkit_dom_range_insert_node ( range, WEBKIT_DOM_NODE (fragment), NULL); webkit_dom_dom_selection_set_base_and_extent ( dom_selection, webkit_dom_range_get_start_container (range, NULL), webkit_dom_range_get_start_offset (range, NULL), webkit_dom_range_get_end_container (range, NULL), webkit_dom_range_get_end_offset (range, NULL), NULL); } else { WebKitDOMNode *node; /* get element that was clicked on */ node = webkit_dom_range_get_common_ancestor_container (range, NULL); if (node && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) { link = e_html_editor_dom_node_find_parent_element (node, "A"); if (link && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link)) link = NULL; } else link = WEBKIT_DOM_ELEMENT (node); } } if (link) { webkit_dom_html_anchor_element_set_href ( WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link), gtk_entry_get_text (GTK_ENTRY (dialog->priv->url_edit))); webkit_dom_html_element_set_inner_html ( WEBKIT_DOM_HTML_ELEMENT (link), gtk_entry_get_text (GTK_ENTRY (dialog->priv->label_edit)), NULL); } else { gchar *text; /* Check whether a text is selected or not */ text = webkit_dom_range_get_text (range); if (text && *text) { e_html_editor_selection_create_link ( selection, gtk_entry_get_text ( GTK_ENTRY (dialog->priv->url_edit))); } else { gchar *html = g_strdup_printf ( "<a href=\"%s\">%s</a>", gtk_entry_get_text ( GTK_ENTRY (dialog->priv->url_edit)), gtk_entry_get_text ( GTK_ENTRY (dialog->priv->label_edit))); e_html_editor_view_exec_command ( view, E_HTML_EDITOR_VIEW_COMMAND_INSERT_HTML, html); g_free (html); } g_free (text); } g_object_unref (range); g_object_unref (dom_selection); gtk_widget_hide (GTK_WIDGET (dialog)); }
static void html_editor_link_dialog_show (GtkWidget *widget) { EHTMLEditor *editor; EHTMLEditorView *view; EHTMLEditorLinkDialog *dialog; WebKitDOMDocument *document; WebKitDOMDOMWindow *dom_window; WebKitDOMDOMSelection *dom_selection; WebKitDOMRange *range; WebKitDOMElement *link; dialog = E_HTML_EDITOR_LINK_DIALOG (widget); editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); view = e_html_editor_get_view (editor); document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); dom_window = webkit_dom_document_get_default_view (document); dom_selection = webkit_dom_dom_window_get_selection (dom_window); g_object_unref (dom_window); /* Reset to default values */ gtk_entry_set_text (GTK_ENTRY (dialog->priv->url_edit), "http://"); gtk_entry_set_text (GTK_ENTRY (dialog->priv->label_edit), ""); gtk_widget_set_sensitive (dialog->priv->label_edit, TRUE); gtk_widget_set_sensitive (dialog->priv->remove_link_button, TRUE); dialog->priv->label_autofill = TRUE; /* No selection at all */ if (!dom_selection || webkit_dom_dom_selection_get_range_count (dom_selection) < 1) { gtk_widget_set_sensitive (dialog->priv->remove_link_button, FALSE); goto chainup; } range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL); link = e_html_editor_dom_node_find_parent_element ( webkit_dom_range_get_start_container (range, NULL), "A"); if (!link) { if ((webkit_dom_range_get_start_container (range, NULL) != webkit_dom_range_get_end_container (range, NULL)) || (webkit_dom_range_get_start_offset (range, NULL) != webkit_dom_range_get_end_offset (range, NULL))) { WebKitDOMDocumentFragment *fragment; fragment = webkit_dom_range_clone_contents (range, NULL); link = e_html_editor_dom_node_find_child_element ( WEBKIT_DOM_NODE (fragment), "A"); } else { WebKitDOMNode *node; node = webkit_dom_range_get_common_ancestor_container (range, NULL); if (node && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) { link = e_html_editor_dom_node_find_parent_element (node, "A"); if (link && !WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (link)) link = NULL; } else link = WEBKIT_DOM_ELEMENT (node); } } if (link) { gchar *href, *text; href = webkit_dom_html_anchor_element_get_href ( WEBKIT_DOM_HTML_ANCHOR_ELEMENT (link)); text = webkit_dom_html_element_get_inner_text ( WEBKIT_DOM_HTML_ELEMENT (link)); gtk_entry_set_text ( GTK_ENTRY (dialog->priv->url_edit), href); gtk_entry_set_text ( GTK_ENTRY (dialog->priv->label_edit), text); g_free (text); g_free (href); } else { gchar *text; text = webkit_dom_range_get_text (range); if (text && *text) { gtk_entry_set_text ( GTK_ENTRY (dialog->priv->label_edit), text); gtk_widget_set_sensitive ( dialog->priv->label_edit, FALSE); gtk_widget_set_sensitive ( dialog->priv->remove_link_button, FALSE); } g_free (text); } g_object_unref (range); chainup: g_object_unref (dom_selection); /* Chain up to parent implementation */ GTK_WIDGET_CLASS (e_html_editor_link_dialog_parent_class)->show (widget); }
static void composer_load_signature_cb (EMailSignatureComboBox *combo_box, GAsyncResult *result, EMsgComposer *composer) { GString *html_buffer = NULL; gchar *contents = NULL; gsize length = 0; const gchar *active_id; gboolean top_signature, is_html, html_mode; gboolean start_bottom, is_message_from_edit_as_new; GError *error = NULL; EHTMLEditor *editor; EHTMLEditorView *view; WebKitDOMDocument *document; WebKitDOMElement *element = NULL; WebKitDOMNodeList *signatures; gulong list_length, ii; GSettings *settings; e_mail_signature_combo_box_load_selected_finish ( combo_box, result, &contents, &length, &is_html, &error); /* FIXME Use an EAlert here. */ if (error != NULL) { g_warning ("%s: %s", G_STRFUNC, error->message); g_error_free (error); goto exit; } if (composer->priv->ignore_next_signature_change) { composer->priv->ignore_next_signature_change = FALSE; goto exit; } editor = e_msg_composer_get_editor (composer); view = e_html_editor_get_view (editor); is_message_from_edit_as_new = e_html_editor_view_is_message_from_edit_as_new (view); /* "Edit as New Message" sets is_message_from_edit_as_new. * Always put the signature at the bottom for that case. */ top_signature = use_top_signature (composer) && !is_message_from_edit_as_new && !composer->priv->is_from_new_message; settings = e_util_ref_settings ("org.gnome.evolution.mail"); start_bottom = g_settings_get_boolean (settings, "composer-reply-start-bottom"); g_object_unref (settings); document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); html_mode = e_html_editor_view_get_html_mode (view); if (contents == NULL) goto insert; /* If inserting HTML signature in plain text composer we have to convert it. */ if (is_html && !html_mode) { WebKitDOMElement *tmp_element; gchar *inner_text; tmp_element = webkit_dom_document_create_element (document, "div", NULL); webkit_dom_html_element_set_inner_html ( WEBKIT_DOM_HTML_ELEMENT (tmp_element), contents, NULL); inner_text = webkit_dom_html_element_get_inner_text ( WEBKIT_DOM_HTML_ELEMENT (tmp_element)); g_free (contents); contents = inner_text ? g_strstrip (inner_text) : g_strdup (""); is_html = FALSE; } if (!is_html) { gchar *html; html = camel_text_to_html (contents, 0, 0); if (html) { g_free (contents); contents = html; length = strlen (contents); } } /* Generate HTML code for the signature. */ html_buffer = g_string_sized_new (1024); /* The combo box active ID is the signature's ESource UID. */ active_id = gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)); g_string_append_printf ( html_buffer, "<SPAN class=\"-x-evo-signature\" id=\"1\" name=\"%s\">", (active_id != NULL) ? active_id : ""); if (!is_html) g_string_append (html_buffer, "<PRE>"); /* The signature dash convention ("-- \n") is specified * in the "Son of RFC 1036", section 4.3.2. * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html */ if (add_signature_delimiter (composer)) { const gchar *delim; const gchar *delim_nl; if (is_html) { delim = "-- <BR>"; delim_nl = "\n-- <BR>"; } else { delim = "-- \n"; delim_nl = "\n-- \n"; } /* Skip the delimiter if the signature already has one. */ if (g_ascii_strncasecmp (contents, delim, strlen (delim)) == 0) ; /* skip */ else if (e_util_strstrcase (contents, delim_nl) != NULL) ; /* skip */ else g_string_append (html_buffer, delim); } g_string_append_len (html_buffer, contents, length); if (!is_html) g_string_append (html_buffer, "</PRE>"); g_string_append (html_buffer, "</SPAN>"); g_free (contents); insert: /* Remove the old signature and insert the new one. */ signatures = webkit_dom_document_get_elements_by_class_name ( document, "-x-evo-signature-wrapper"); list_length = webkit_dom_node_list_get_length (signatures); for (ii = 0; ii < list_length; ii++) { WebKitDOMNode *wrapper, *signature; gchar *id; wrapper = webkit_dom_node_list_item (signatures, ii); signature = webkit_dom_node_get_first_child (wrapper); /* When we are editing a message with signature, we need to unset the * active signature id as if the signature in the message was edited * by the user we would discard these changes. */ if (composer->priv->set_signature_from_message && (is_message_from_edit_as_new || e_html_editor_view_is_message_from_draft (view))) { if (composer->priv->check_if_signature_is_changed) { if (html_buffer && *html_buffer->str) { gchar *body_signature_text, *signature_text; element = webkit_dom_document_create_element (document, "div", NULL); webkit_dom_html_element_set_inner_html ( WEBKIT_DOM_HTML_ELEMENT (element), html_buffer->str, NULL); body_signature_text = webkit_dom_html_element_get_inner_text ( WEBKIT_DOM_HTML_ELEMENT (signature)); signature_text = webkit_dom_html_element_get_inner_text ( WEBKIT_DOM_HTML_ELEMENT (element)); /* Signature in the body is different than the one with the * same id, so set the active signature to None and leave * the signature that is in the body. */ if (g_strcmp0 (body_signature_text, signature_text) != 0) { gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); composer->priv->ignore_next_signature_change = TRUE; } g_free (body_signature_text); g_free (signature_text); } else { gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0); composer->priv->ignore_next_signature_change = TRUE; } composer->priv->check_if_signature_is_changed = FALSE; composer->priv->set_signature_from_message = FALSE; } else { gchar *name; /* Load the signature and check if is it the same * as the signature in body or the user previously * changed it. */ name = webkit_dom_element_get_attribute (WEBKIT_DOM_ELEMENT (signature), "name"); gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), name); g_free (name); composer->priv->check_if_signature_is_changed = TRUE; } g_object_unref (wrapper); g_object_unref (signatures); g_object_unref (composer); return; } id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (signature)); if (id && (strlen (id) == 1) && (*id == '1')) { /* If the top signature was set we have to remove the NL * that was inserted after it */ if (top_signature) { WebKitDOMElement *spacer; spacer = webkit_dom_document_query_selector ( document, ".-x-evo-top-signature-spacer", NULL); if (spacer) remove_node_if_empty (WEBKIT_DOM_NODE (spacer)); } /* We have to remove the div containing the span with signature */ remove_node (wrapper); g_object_unref (wrapper); g_free (id); break; } g_object_unref (wrapper); g_free (id); } g_object_unref (signatures); if (html_buffer != NULL) { if (*html_buffer->str) { WebKitDOMHTMLElement *body; body = webkit_dom_document_get_body (document); if (!element) { element = webkit_dom_document_create_element (document, "DIV", NULL); webkit_dom_html_element_set_inner_html ( WEBKIT_DOM_HTML_ELEMENT (element), html_buffer->str, NULL); } webkit_dom_element_set_class_name (element, "-x-evo-signature-wrapper"); if (top_signature) { WebKitDOMNode *child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)); if (start_bottom) { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), child, NULL); } else { /* When we are using signature on top the caret * should be before the signature */ webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), child, NULL); } } else { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } } g_string_free (html_buffer, TRUE); } if (is_html && html_mode) e_html_editor_view_fix_file_uri_images (view); composer_move_caret (composer); exit: /* Make sure the flag will be unset and won't influence user's choice */ composer->priv->set_signature_from_message = FALSE; g_object_unref (composer); }
/** * Find the first editable element and set the focus on it and enter input * mode. * Returns true if there was an editable element focused. */ gboolean dom_focus_input(Document *doc) { WebKitDOMNode *html, *node; WebKitDOMDOMWindow *win; WebKitDOMNodeList *list; WebKitDOMXPathNSResolver *resolver; WebKitDOMXPathResult* result; Document *frame_doc; guint i, len; win = webkit_dom_document_get_default_view(doc); list = webkit_dom_document_get_elements_by_tag_name(doc, "html"); if (!list) { return false; } html = webkit_dom_node_list_item(list, 0); g_object_unref(list); resolver = webkit_dom_document_create_ns_resolver(doc, html); if (!resolver) { return false; } /* Use translate to match xpath expression case insensitive so that also * intput filed of type="TEXT" are matched. */ result = webkit_dom_document_evaluate( doc, "//input[not(@type) " "or translate(@type,'ETX','etx')='text' " "or translate(@type,'ADOPRSW','adoprsw')='password' " "or translate(@type,'CLOR','clor')='color' " "or translate(@type,'ADET','adet')='date' " "or translate(@type,'ADEIMT','adeimt')='datetime' " "or translate(@type,'ACDEILMOT','acdeilmot')='datetime-local' " "or translate(@type,'AEILM','aeilm')='email' " "or translate(@type,'HMNOT','hmnot')='month' " "or translate(@type,'BEMNRU','bemnru')='number' " "or translate(@type,'ACEHRS','acehrs')='search' " "or translate(@type,'ELT','elt')='tel' " "or translate(@type,'EIMT','eimt')='time' " "or translate(@type,'LRU','lru')='url' " "or translate(@type,'EKW','ekw')='week' " "]|//textarea", html, resolver, 5, NULL, NULL ); if (!result) { return false; } while ((node = webkit_dom_xpath_result_iterate_next(result, NULL))) { if (element_is_visible(win, WEBKIT_DOM_ELEMENT(node))) { vb_enter('i'); webkit_dom_element_focus(WEBKIT_DOM_ELEMENT(node)); return true; } } /* Look for editable elements in frames too. */ list = webkit_dom_document_get_elements_by_tag_name(doc, "iframe"); len = webkit_dom_node_list_get_length(list); for (i = 0; i < len; i++) { node = webkit_dom_node_list_item(list, i); frame_doc = webkit_dom_html_iframe_element_get_content_document(WEBKIT_DOM_HTML_IFRAME_ELEMENT(node)); /* Stop on first frame with focused element. */ if (dom_focus_input(frame_doc)) { g_object_unref(list); return true; } } g_object_unref(list); return false; }
static void move_caret_after_signature_inserted (EEditorPage *editor_page) { WebKitDOMDocument *document; WebKitDOMElement *element, *signature; WebKitDOMHTMLElement *body; WebKitDOMNodeList *paragraphs = NULL; gboolean top_signature; gboolean start_bottom; gboolean has_paragraphs_in_body = TRUE; g_return_if_fail (E_IS_EDITOR_PAGE (editor_page)); document = e_editor_page_get_document (editor_page); top_signature = use_top_signature (); start_bottom = start_typing_at_bottom (); body = webkit_dom_document_get_body (document); e_editor_page_block_selection_changed (editor_page); paragraphs = webkit_dom_document_query_selector_all (document, "[data-evo-paragraph]", NULL); signature = webkit_dom_document_query_selector (document, ".-x-evo-signature-wrapper", NULL); /* Situation when wrapped paragraph is just in signature and not in message body */ if (webkit_dom_node_list_get_length (paragraphs) == 1) { WebKitDOMNode *node; node = webkit_dom_node_list_item (paragraphs, 0); if (signature && webkit_dom_element_query_selector (signature, "[data-evo-paragraph]", NULL)) has_paragraphs_in_body = FALSE; /* Don't take the credentials into account. */ if (!webkit_dom_node_get_previous_sibling (node) && !element_has_id (WEBKIT_DOM_ELEMENT (node), "-x-evo-input-start")) has_paragraphs_in_body = FALSE; } /* * * Keeping Signatures in the beginning of composer * ------------------------------------------------ * * Purists are gonna blast me for this. * But there are so many people (read Outlook users) who want this. * And Evo is an exchange-client, Outlook-replacement etc. * So Here it goes :( * * -- Sankar * */ if (signature && top_signature) { WebKitDOMElement *spacer; spacer = prepare_top_signature_spacer (editor_page); webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (spacer), webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (signature)), NULL); } if (webkit_dom_node_list_get_length (paragraphs) == 0) has_paragraphs_in_body = FALSE; element = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start"); if (!signature) { if (start_bottom) { if (!element) { element = e_editor_dom_prepare_paragraph (editor_page, FALSE); webkit_dom_element_set_id (element, "-x-evo-input-start"); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } } else element = WEBKIT_DOM_ELEMENT (body); goto move_caret; } /* When there is an option composer-reply-start-bottom set we have * to move the caret between reply and signature. */ if (!has_paragraphs_in_body) { element = e_editor_dom_prepare_paragraph (editor_page, FALSE); webkit_dom_element_set_id (element, "-x-evo-input-start"); if (top_signature) { if (start_bottom) { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } else { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } } else { if (start_bottom) webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); else element = WEBKIT_DOM_ELEMENT (body); } } else { if (!element && top_signature) { element = e_editor_dom_prepare_paragraph (editor_page, FALSE); webkit_dom_element_set_id (element, "-x-evo-input-start"); if (start_bottom) { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), NULL); } else { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } } else if (element && top_signature && !start_bottom) { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (signature), NULL); } else if (element && start_bottom) { /* Leave it how it is */ } else element = WEBKIT_DOM_ELEMENT (body); } move_caret: if (element) { WebKitDOMDOMSelection *dom_selection = NULL; WebKitDOMDOMWindow *dom_window = NULL; WebKitDOMRange *range = NULL; dom_window = webkit_dom_document_get_default_view (document); dom_selection = webkit_dom_dom_window_get_selection (dom_window); range = webkit_dom_document_create_range (document); webkit_dom_range_select_node_contents ( range, WEBKIT_DOM_NODE (element), NULL); webkit_dom_range_collapse (range, TRUE, NULL); webkit_dom_dom_selection_remove_all_ranges (dom_selection); webkit_dom_dom_selection_add_range (dom_selection, range); g_clear_object (&dom_selection); g_clear_object (&dom_window); g_clear_object (&range); } if (start_bottom) e_editor_dom_scroll_to_caret (editor_page); g_clear_object (¶graphs); e_editor_dom_force_spell_check_in_viewport (editor_page); e_editor_page_unblock_selection_changed (editor_page); }
gchar * e_composer_dom_insert_signature (EEditorPage *editor_page, const gchar *content, gboolean is_html, const gchar *id, gboolean *set_signature_from_message, gboolean *check_if_signature_is_changed, gboolean *ignore_next_signature_change) { WebKitDOMDocument *document; WebKitDOMElement *signature_to_insert; WebKitDOMElement *insert_signature_in = NULL; WebKitDOMElement *signature_wrapper = NULL; WebKitDOMElement *element, *converted_signature = NULL; WebKitDOMHTMLElement *body; WebKitDOMHTMLCollection *signatures = NULL; gchar *new_signature_id = NULL; gchar *signature_text = NULL; gboolean top_signature, html_mode; gulong ii; g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), NULL); g_return_val_if_fail (set_signature_from_message != NULL, NULL); g_return_val_if_fail (check_if_signature_is_changed != NULL, NULL); g_return_val_if_fail (ignore_next_signature_change != NULL, NULL); document = e_editor_page_get_document (editor_page); body = webkit_dom_document_get_body (document); /* "Edit as New Message" sets is_message_from_edit_as_new. * Always put the signature at the bottom for that case. */ top_signature = use_top_signature (); html_mode = e_editor_page_get_html_mode (editor_page); /* Create the DOM signature that is the same across all types of signatures. */ signature_to_insert = webkit_dom_document_create_element (document, "span", NULL); webkit_dom_element_set_class_name (signature_to_insert, "-x-evo-signature"); /* The combo box active ID is the signature's ESource UID. */ webkit_dom_element_set_id (signature_to_insert, id); insert_signature_in = signature_to_insert; /* The signature has no content usually it means it is set to None. */ if (!(content && *content)) goto insert; if (!is_html) { gchar *html; html = camel_text_to_html (content, 0, 0); if (html) { signature_text = html; } else signature_text = g_strdup (content); insert_signature_in = webkit_dom_document_create_element (document, "pre", NULL); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (signature_to_insert), WEBKIT_DOM_NODE (insert_signature_in), NULL); } else signature_text = g_strdup (content); /* If inserting HTML signature in the plain text composer we have to convert it. */ if (is_html && !html_mode && !strstr (signature_text, "data-evo-signature-plain-text-mode")) { gchar *inner_text; /* Save the converted signature to avoid parsing it later again * while inserting it into the view. */ converted_signature = webkit_dom_document_create_element (document, "pre", NULL); webkit_dom_element_set_inner_html (converted_signature, signature_text, NULL); e_editor_dom_convert_element_from_html_to_plain_text (editor_page, converted_signature); inner_text = webkit_dom_html_element_get_inner_text (WEBKIT_DOM_HTML_ELEMENT (converted_signature)); g_free (signature_text); signature_text = inner_text ? g_strstrip (inner_text) : g_strdup (""); /* because of the -- \n check */ is_html = FALSE; } /* The signature dash convention ("-- \n") is specified * in the "Son of RFC 1036", section 4.3.2. * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html */ if (add_signature_delimiter ()) { const gchar *delim; const gchar *delim_nl; if (is_html) { delim = "-- <BR>"; delim_nl = "\n-- <BR>"; } else { delim = "-- \n"; delim_nl = "\n-- \n"; } /* Skip the delimiter if the signature already has one. */ if (g_ascii_strncasecmp (signature_text, delim, strlen (delim)) == 0) ; /* skip */ else if (e_util_strstrcase (signature_text, delim_nl) != NULL) ; /* skip */ else { WebKitDOMElement *pre_delimiter; pre_delimiter = webkit_dom_document_create_element (document, "pre", NULL); /* Always use the HTML delimiter as we are never in anything * like a strict plain text mode. */ webkit_dom_element_set_inner_html (pre_delimiter, "-- <br>", NULL); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (insert_signature_in), WEBKIT_DOM_NODE (pre_delimiter), NULL); } } if (converted_signature) { WebKitDOMNode *node; while ((node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (converted_signature)))) webkit_dom_node_append_child ( WEBKIT_DOM_NODE (insert_signature_in), node, NULL); remove_node (WEBKIT_DOM_NODE (converted_signature)); } else webkit_dom_element_insert_adjacent_html ( insert_signature_in, "beforeend", signature_text, NULL); element = webkit_dom_element_query_selector ( insert_signature_in, "[data-evo-signature-plain-text-mode]", NULL); if (element) webkit_dom_element_remove_attribute ( element, "data-evo-signature-plain-text-mode"); g_free (signature_text); insert: /* Remove the old signature and insert the new one. */ signatures = webkit_dom_document_get_elements_by_class_name_as_html_collection ( document, "-x-evo-signature-wrapper"); for (ii = webkit_dom_html_collection_get_length (signatures); ii--;) { WebKitDOMNode *wrapper, *signature; wrapper = webkit_dom_html_collection_item (signatures, ii); signature = webkit_dom_node_get_first_child (wrapper); /* Old messages will have the signature id in the name attribute, correct it. */ element_rename_attribute (WEBKIT_DOM_ELEMENT (signature), "name", "id"); /* When we are editing a message with signature, we need to unset the * active signature id as if the signature in the message was edited * by the user we would discard these changes. */ if (*set_signature_from_message && content) { if (*check_if_signature_is_changed) { /* Normalize the signature that we want to insert as the one in the * message already is normalized. */ webkit_dom_node_normalize (WEBKIT_DOM_NODE (signature_to_insert)); if (!webkit_dom_node_is_equal_node (WEBKIT_DOM_NODE (signature_to_insert), signature)) { /* Signature in the body is different than the one with the * same id, so set the active signature to None and leave * the signature that is in the body. */ new_signature_id = g_strdup ("none"); *ignore_next_signature_change = TRUE; } *check_if_signature_is_changed = FALSE; *set_signature_from_message = FALSE; } else { /* Load the signature and check if is it the same * as the signature in body or the user previously * changed it. */ new_signature_id = webkit_dom_element_get_id (WEBKIT_DOM_ELEMENT (signature)); *check_if_signature_is_changed = TRUE; } g_clear_object (&signatures); return new_signature_id; } /* If the top signature was set we have to remove the newline * that was inserted after it */ if (top_signature) { WebKitDOMElement *spacer; spacer = webkit_dom_document_query_selector ( document, ".-x-evo-top-signature-spacer", NULL); if (spacer) remove_node_if_empty (WEBKIT_DOM_NODE (spacer)); } /* Leave just one signature wrapper there as it will be reused. */ if (ii != 0) { remove_node (wrapper); } else { remove_node (signature); signature_wrapper = WEBKIT_DOM_ELEMENT (wrapper); } } if (signature_wrapper) { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (signature_wrapper), WEBKIT_DOM_NODE (signature_to_insert), NULL); /* Insert a spacer below the top signature */ if (top_signature && content) { WebKitDOMElement *spacer; spacer = prepare_top_signature_spacer (editor_page); webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (spacer), webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (signature_wrapper)), NULL); } } else { signature_wrapper = webkit_dom_document_create_element (document, "div", NULL); webkit_dom_element_set_class_name (signature_wrapper, "-x-evo-signature-wrapper"); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (signature_wrapper), WEBKIT_DOM_NODE (signature_to_insert), NULL); if (top_signature) { WebKitDOMNode *child; child = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)); if (start_typing_at_bottom ()) { webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (signature_wrapper), child, NULL); } else { /* When we are using signature on top the caret * should be before the signature */ webkit_dom_node_insert_before ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (signature_wrapper), child, NULL); } } else { webkit_dom_node_append_child ( WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (signature_wrapper), NULL); } move_caret_after_signature_inserted (editor_page); } g_clear_object (&signatures); if (is_html && html_mode) e_editor_dom_fix_file_uri_images (editor_page); /* Make sure the flag will be unset and won't influence user's choice */ *set_signature_from_message = FALSE; return NULL; }