Esempio n. 1
1
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);
}
Esempio n. 2
0
/**
 * 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;
}
Esempio n. 3
0
/**
 * 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);
	}
}
Esempio n. 5
0
// 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);
    }
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/**
 * 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));
    }
}
Esempio n. 9
0
File: dom.c Progetto: uggedal/vimb
/**
 * 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;
}
Esempio n. 10
0
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");
}
Esempio n. 11
0
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);
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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);
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
File: dom.c Progetto: b80905/vimb
/**
 * 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;
}
Esempio n. 20
0
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 (&paragraphs);

	e_editor_dom_force_spell_check_in_viewport (editor_page);
	e_editor_page_unblock_selection_changed (editor_page);
}
Esempio n. 21
0
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;
}