static void html_editor_hrule_dialog_hide (GtkWidget *widget) { EHTMLEditorHRuleDialogPrivate *priv; EHTMLEditorViewHistoryEvent *ev; priv = E_HTML_EDITOR_HRULE_DIALOG_GET_PRIVATE (widget); ev = priv->history_event; if (ev) { EHTMLEditorHRuleDialog *dialog; EHTMLEditor *editor; EHTMLEditorSelection *selection; EHTMLEditorView *view; dialog = E_HTML_EDITOR_HRULE_DIALOG (widget); 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); ev->data.dom.to = webkit_dom_node_clone_node ( WEBKIT_DOM_NODE (priv->hr_element), FALSE); if (!webkit_dom_node_is_equal_node (ev->data.dom.from, ev->data.dom.to)) { e_html_editor_selection_get_selection_coordinates ( selection, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, &ev->after.end.y); e_html_editor_view_insert_new_history_event (view, ev); if (!ev->data.dom.from) g_object_unref (priv->hr_element); } else { g_object_unref (ev->data.dom.from); g_object_unref (ev->data.dom.to); g_free (ev); } } priv->hr_element = NULL; GTK_WIDGET_CLASS (e_html_editor_hrule_dialog_parent_class)->hide (widget); }
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; }
void e_editor_selection_wrap_lines (EEditorSelection *selection) { WebKitDOMRange *range; WebKitDOMNode *node, *start_node; WebKitDOMDocument *document; WebKitDOMElement *element; WebKitDOMDocumentFragment *fragment; gint len; gchar *html; g_return_if_fail (E_IS_EDITOR_SELECTION (selection)); document = webkit_web_view_get_dom_document (selection->priv->webview); range = editor_selection_get_current_range (selection); /* Extend the range to include entire nodes */ webkit_dom_range_select_node_contents ( range, webkit_dom_range_get_common_ancestor_container (range, NULL), NULL); /* Copy the selection from DOM, wrap the lines and then paste it back * using the DOM command which will overwrite the selection, and * record it as an undoable action */ fragment = webkit_dom_range_clone_contents (range, NULL); node = WEBKIT_DOM_NODE (fragment); start_node = node; len = 0; while (node) { /* Find nearest text node */ if (webkit_dom_node_get_node_type (node) != 3) { 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 { if (webkit_dom_node_is_equal_node (node, start_node)) { break; } node = webkit_dom_node_get_parent_node (node); if (node) { node = webkit_dom_node_get_next_sibling (node); } } continue; } /* If length of this node + what we already have is still less * then 71 characters, then just join it and continue to next * node */ if ((webkit_dom_character_data_get_length ( (WebKitDOMCharacterData *) node) + len) < WORD_WRAP_LENGTH) { len += webkit_dom_character_data_get_length ( (WebKitDOMCharacterData *) node); } else { gint offset; /* Find where we can line-break the node so that it * effectively fills the rest of current row */ offset = find_where_to_break_line (node, WORD_WRAP_LENGTH - len); if (offset > 0) { /* Split the node and append <BR> tag to it */ webkit_dom_text_split_text ( (WebKitDOMText *) node, len + offset, NULL); element = webkit_dom_document_create_element ( document, "BR", NULL); /* WebKit throws warning when ref_child is NULL */ if (webkit_dom_node_get_next_sibling (node)) { webkit_dom_node_insert_before ( webkit_dom_node_get_parent_node (node), WEBKIT_DOM_NODE (element), webkit_dom_node_get_next_sibling (node), NULL); } else { webkit_dom_node_append_child ( webkit_dom_node_get_parent_node (node), WEBKIT_DOM_NODE (element), NULL); } len = 0; } } /* Skip to next node */ if (webkit_dom_node_get_next_sibling (node)) { node = webkit_dom_node_get_next_sibling (node); } else { if (webkit_dom_node_is_equal_node (node, start_node)) { break; } node = webkit_dom_node_get_parent_node (node); if (node) { node = webkit_dom_node_get_next_sibling (node); } } } /* Create a wrapper DIV and put the processed content into it */ element = webkit_dom_document_create_element (document, "DIV", NULL); webkit_dom_node_append_child ( WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (start_node), NULL); /* Get HTML code of the processed content */ html = webkit_dom_html_element_get_inner_html ( WEBKIT_DOM_HTML_ELEMENT (element)); /* Overwrite the current selection be the processed content, so that * "UNDO" and "REDO" buttons work as expected */ e_editor_selection_insert_html (selection, html); g_free (html); }