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); }
static void html_editor_image_dialog_hide (GtkWidget *widget) { EHTMLEditorImageDialogPrivate *priv; EHTMLEditorViewHistoryEvent *ev; priv = E_HTML_EDITOR_IMAGE_DIALOG_GET_PRIVATE (widget); ev = priv->history_event; if (ev) { EHTMLEditorImageDialog *dialog; EHTMLEditor *editor; EHTMLEditorSelection *selection; EHTMLEditorView *view; dialog = E_HTML_EDITOR_IMAGE_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->image), FALSE); 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); } g_object_unref (priv->image); priv->image = NULL; GTK_WIDGET_CLASS (e_html_editor_image_dialog_parent_class)->hide (widget); }
gboolean e_composer_paste_text (EMsgComposer *composer, GtkClipboard *clipboard) { EHTMLEditor *editor; EHTMLEditorView *view; EHTMLEditorSelection *editor_selection; gchar *text; g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE); if (!(text = gtk_clipboard_wait_for_text (clipboard))) return FALSE; editor = e_msg_composer_get_editor (composer); view = e_html_editor_get_view (editor); editor_selection = e_html_editor_view_get_selection (view); /* If WebView doesn't have focus, focus it */ if (!gtk_widget_has_focus (GTK_WIDGET (view))) gtk_widget_grab_focus (GTK_WIDGET (view)); e_html_editor_selection_insert_text (editor_selection, text); g_free (text); return TRUE; }
static void html_editor_link_dialog_remove_link (EHTMLEditorLinkDialog *dialog) { EHTMLEditor *editor; EHTMLEditorView *view; EHTMLEditorSelection *selection; 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); e_html_editor_selection_unlink (selection); gtk_widget_hide (GTK_WIDGET (dialog)); }
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); }
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); }
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_hrule_dialog_show (GtkWidget *widget) { EHTMLEditorHRuleDialog *dialog; EHTMLEditor *editor; EHTMLEditorSelection *selection; EHTMLEditorView *view; WebKitDOMDocument *document; 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); if (!e_html_editor_view_is_undo_redo_in_progress (view)) { EHTMLEditorViewHistoryEvent *ev; ev = g_new0 (EHTMLEditorViewHistoryEvent, 1); ev->type = HISTORY_HRULE_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); if (dialog->priv->hr_element) ev->data.dom.from = webkit_dom_node_clone_node ( WEBKIT_DOM_NODE (dialog->priv->hr_element), FALSE); else ev->data.dom.from = NULL; dialog->priv->history_event = ev; } if (!dialog->priv->hr_element) { WebKitDOMElement *selection_start, *parent, *rule; document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); e_html_editor_selection_save (selection); selection_start = webkit_dom_document_get_element_by_id ( document, "-x-evo-selection-start-marker"); parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_start)); rule = webkit_dom_document_create_element (document, "HR", NULL); /* Insert horizontal rule into body below the caret */ webkit_dom_node_insert_before ( webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (parent)), WEBKIT_DOM_NODE (rule), webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (parent)), NULL); e_html_editor_selection_restore (selection); dialog->priv->hr_element = WEBKIT_DOM_HTMLHR_ELEMENT (rule); /* For new rule reset the values to default */ gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->width_edit), 100.0); gtk_combo_box_set_active_id ( GTK_COMBO_BOX (dialog->priv->unit_combo), "units-percent"); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->priv->size_edit), 2.0); gtk_combo_box_set_active_id ( GTK_COMBO_BOX (dialog->priv->alignment_combo), "left"); gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (dialog->priv->shaded_check), FALSE); html_editor_hrule_dialog_set_alignment (dialog); html_editor_hrule_dialog_set_size (dialog); html_editor_hrule_dialog_set_alignment (dialog); html_editor_hrule_dialog_set_shading (dialog); e_html_editor_view_set_changed (view, TRUE); } else { html_editor_hrule_dialog_get_alignment (dialog); html_editor_hrule_dialog_get_size (dialog); html_editor_hrule_dialog_get_width (dialog); html_editor_hrule_dialog_get_shading (dialog); } /* Chain up to parent implementation */ GTK_WIDGET_CLASS (e_html_editor_hrule_dialog_parent_class)->show (widget); }
gboolean e_composer_paste_image (EMsgComposer *composer, GtkClipboard *clipboard) { EHTMLEditor *editor; EHTMLEditorView *html_editor_view; EAttachmentStore *store; EAttachmentView *view; GdkPixbuf *pixbuf = NULL; gchar *filename = NULL; gchar *uri = NULL; gboolean success = FALSE; GError *error = NULL; g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE); g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE); view = e_msg_composer_get_attachment_view (composer); store = e_attachment_view_get_store (view); /* Extract the image data from the clipboard. */ pixbuf = gtk_clipboard_wait_for_image (clipboard); g_return_val_if_fail (pixbuf != NULL, FALSE); /* Reserve a temporary file. */ filename = e_mktemp (NULL); if (filename == NULL) { g_set_error ( &error, G_FILE_ERROR, g_file_error_from_errno (errno), "Could not create temporary file: %s", g_strerror (errno)); goto exit; } /* Save the pixbuf as a temporary file in image/png format. */ if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL)) goto exit; /* Convert the filename to a URI. */ uri = g_filename_to_uri (filename, NULL, &error); if (uri == NULL) goto exit; /* In HTML mode, paste the image into the message body. * In text mode, add the image to the attachment store. */ editor = e_msg_composer_get_editor (composer); html_editor_view = e_html_editor_get_view (editor); if (e_html_editor_view_get_html_mode (html_editor_view)) { EHTMLEditorSelection *selection; selection = e_html_editor_view_get_selection (html_editor_view); e_html_editor_selection_insert_image (selection, uri); e_html_editor_selection_scroll_to_caret (selection); } else { EAttachment *attachment; attachment = e_attachment_new_for_uri (uri); e_attachment_store_add_attachment (store, attachment); e_attachment_load_async ( attachment, (GAsyncReadyCallback) e_attachment_load_handle_error, composer); g_object_unref (attachment); } success = TRUE; exit: if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); } g_object_unref (pixbuf); g_free (filename); g_free (uri); return success; }
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)); }