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);
}
Beispiel #2
0
	/* we got the DOM API we need */
int
focus_input_document(struct tab *t, WebKitDOMDocument *doc)
{
	WebKitDOMNodeList	*input = NULL, *textarea = NULL;
	WebKitDOMNode		*n;
	char			*es;
	int			i, rv = 0 /* not found */;

	WebKitDOMHTMLTextAreaElement	*ta;
	WebKitDOMHTMLInputElement	*in;

	/* we are deliberately ignoring tab index! */

	/* try input first */
	input = webkit_dom_document_get_elements_by_tag_name(doc, "input");
	for (i = 0; i < webkit_dom_node_list_get_length(input); i++) {
		n = webkit_dom_node_list_item(input, i);
		in = (WebKitDOMHTMLInputElement*)n;
		g_object_get(G_OBJECT(in), "type", &es, (char *)NULL);
		if ((!g_str_equal("text", es) && !g_str_equal("password",es)) ||
		    webkit_dom_html_input_element_get_disabled(in)) {
			/* skip not text */
			g_free(es);
			continue;
		}
		webkit_dom_element_focus((WebKitDOMElement*)in);
		g_free(es);
		rv = 1; /* found */
		goto done;
	}

	/* now try textarea */
	textarea = webkit_dom_document_get_elements_by_tag_name(doc, "textarea");
	for (i = 0; i < webkit_dom_node_list_get_length(textarea); i++) {
		n = webkit_dom_node_list_item(textarea, i);
		ta = (WebKitDOMHTMLTextAreaElement*)n;
		if (webkit_dom_html_text_area_element_get_disabled(ta)) {
			/* it is hidden so skip */
			continue;
		}
		webkit_dom_element_focus((WebKitDOMElement*)ta);
		rv = 1; /* found */
		goto done;
	}
done:
	if (input)
		g_object_unref(input);
	if (textarea)
		g_object_unref(textarea);

	return (rv);
}
Beispiel #3
0
static void test_dom_document_get_elements_by_tag_name(DomDocumentFixture* fixture, gconstpointer data)
{
    g_assert(fixture);
    WebKitWebView* view = (WebKitWebView*)fixture->webView;
    g_assert(view);
    WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
    g_assert(document);
    WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "li");
    g_assert(list);
    gulong length = webkit_dom_node_list_get_length(list);
    g_assert_cmpint(length, ==, 3);

    guint i;

    for (i = 0; i < length; i++) {
        WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
        g_assert(item);
        WebKitDOMElement* element = (WebKitDOMElement*)item;
        g_assert(element);
        g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "LI");
        WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element;
        char* n = g_strdup_printf("%d", i+1);
        g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, n);
        g_free(n);
    }

    g_object_unref(list);
}
Beispiel #4
0
static void test_dom_node_hierarchy_navigation(DomNodeFixture* fixture, gconstpointer data)
{
    WebKitDOMDocument* document;
    WebKitDOMHTMLHeadElement* head;
    WebKitDOMHTMLBodyElement* body;
    WebKitDOMNodeList* list;
    WebKitDOMNode* ptr;
    gulong i, length;

    document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
    g_assert(document);
    g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
    head = webkit_dom_document_get_head(document);
    g_assert(head);
    g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(head));

    /* Title, head's child */
    g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(head)));
    list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(head));
    g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
    ptr = webkit_dom_node_list_item(list, 0);
    g_assert(ptr);
    g_assert(WEBKIT_DOM_IS_HTML_TITLE_ELEMENT(ptr));
    g_object_unref(list);

    /* Body, Head sibling */
    ptr = webkit_dom_node_get_next_sibling(WEBKIT_DOM_NODE(head));
    g_assert(ptr);
    body = WEBKIT_DOM_HTML_BODY_ELEMENT(ptr);
    g_assert(WEBKIT_DOM_IS_HTML_BODY_ELEMENT(body));

    /* There is no third sibling */
    ptr = webkit_dom_node_get_next_sibling(ptr);
    g_assert(ptr == NULL);

    /* Body's previous sibling is Head */
    ptr = webkit_dom_node_get_previous_sibling(WEBKIT_DOM_NODE(body));
    g_assert(ptr);
    g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(ptr));

    /* Body has 3 children */
    g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
    list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
    length = webkit_dom_node_list_get_length(list);
    g_assert_cmpint(length, ==, 3);

    /* The three of them are P tags */
    for (i = 0; i < length; i++) {
        ptr = webkit_dom_node_list_item(list, i);
        g_assert(ptr);
        g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(ptr));
    }

    /* Go backwards */
    for (i = 0; ptr; ptr = webkit_dom_node_get_previous_sibling(ptr), i++)
        /* Nothing */;

    g_assert_cmpint(i, ==, 3);
    g_object_unref(list);
}
Beispiel #5
0
// frame_document_loaded watches signals emitted from the given document.
static void
frame_document_loaded(WebKitDOMDocument *doc,
                      Exten             *exten)
{
    // Track document, and don't register multiple times.
    if(!g_hash_table_add(exten->registered_documents, doc)) {
        return;
    }
    WebKitDOMEventTarget *target = WEBKIT_DOM_EVENT_TARGET(
            webkit_dom_document_get_default_view(doc));
    // listen for focus changes
    webkit_dom_event_target_add_event_listener(
            target,
            "blur",
            G_CALLBACK(active_element_change_cb),
            true,
            exten);
    webkit_dom_event_target_add_event_listener(
            target,
            "focus",
            G_CALLBACK(active_element_change_cb),
            true,
            exten);

    // listen for resource loads.
    webkit_dom_event_target_add_event_listener(
            target,
            "beforeload",
            G_CALLBACK(adblock_before_load_cb),
            true,
            exten);

    // Scan for existing iframes, and add them as new frames.
    WebKitDOMNodeList *nodes = webkit_dom_document_get_elements_by_tag_name(
            WEBKIT_DOM_DOCUMENT(doc),
            "IFRAME");
    gulong i;
    gulong len;
    if(nodes == NULL) {
        len = 0;
    } else {
        len = webkit_dom_node_list_get_length(nodes);
    }
    for(i = 0; i < len; i++) {
        WebKitDOMDocument *subdoc =
            webkit_dom_html_iframe_element_get_content_document(
                    WEBKIT_DOM_HTML_IFRAME_ELEMENT(
                        webkit_dom_node_list_item(nodes, i)));
        frame_document_loaded(subdoc, exten);
    }
    // Element hider
    inject_adblock_css(doc, exten);
}
static gint
get_caret_position (EHTMLEditorView *view)
{
	WebKitDOMDocument *document;
	WebKitDOMDOMWindow *window;
	WebKitDOMDOMSelection *selection;
	WebKitDOMRange *range;
	gint range_count;
	WebKitDOMNodeList *nodes;
	gulong ii, length;

	document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
	window = webkit_dom_document_get_default_view (document);
	selection = webkit_dom_dom_window_get_selection (window);

	if (webkit_dom_dom_selection_get_range_count (selection) < 1)
		return 0;

	range = webkit_dom_dom_selection_get_range_at (selection, 0, NULL);
	range_count = 0;
	nodes = webkit_dom_node_get_child_nodes (
		webkit_dom_node_get_parent_node (
			webkit_dom_dom_selection_get_anchor_node (
				selection)));
	length = webkit_dom_node_list_get_length (nodes);
	for (ii = 0; ii < length; ii++) {
		WebKitDOMNode *node;

		node = webkit_dom_node_list_item (nodes, ii);
		if (webkit_dom_node_is_same_node (
			node, webkit_dom_dom_selection_get_anchor_node (selection))) {

			break;
		} else if (WEBKIT_DOM_IS_TEXT (node)) {
			gchar *text = webkit_dom_node_get_text_content (node);
			range_count += strlen (text);
			g_free (text);
		}
	}

	g_object_unref (nodes);
	return webkit_dom_range_get_start_offset (range, NULL) + range_count;
}
Beispiel #7
0
static gulong
walk_dom (WebKitDOMNode *node) {
    WebKitDOMNodeList *list;
    gulong i, length, count;

    if (! webkit_dom_node_has_child_nodes(node)) {
        return 1;
    }

    list = webkit_dom_node_get_child_nodes(node);
    length = webkit_dom_node_list_get_length(list);
    count = 1;
    for (i = 0; i < length; ++i) {
        WebKitDOMNode *child_node;
        child_node = webkit_dom_node_list_item(list, i);
        count += walk_dom(child_node);
    }
    g_object_unref(list);

    return count;
}
Beispiel #8
0
gchar *
e_composer_dom_get_raw_body_content_without_signature (EEditorPage *editor_page)
{
	WebKitDOMDocument *document;
	WebKitDOMNodeList *list = NULL;
	GString* content;
	gulong ii, length;

	g_return_val_if_fail (E_IS_EDITOR_PAGE (editor_page), NULL);

	document = e_editor_page_get_document (editor_page);

	content = g_string_new (NULL);

	list = webkit_dom_document_query_selector_all (
		document, "body > *:not(.-x-evo-signature-wrapper)", NULL);
	length = webkit_dom_node_list_get_length (list);
	for (ii = 0; ii < length; ii++) {
		WebKitDOMNode *node = webkit_dom_node_list_item (list, ii);

		if (!WEBKIT_DOM_IS_HTML_QUOTE_ELEMENT (node)) {
			gchar *text;

			text = webkit_dom_html_element_get_inner_text (WEBKIT_DOM_HTML_ELEMENT (node));
			g_string_append (content, text);
			g_free (text);

			if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (node))
				g_string_append (content, "\n");
			else
				g_string_append (content, " ");
		}
	}
	g_clear_object (&list);

	return g_string_free (content, FALSE);
}
Beispiel #9
0
static void test_dom_document_get_elements_by_class_name(DomDocumentFixture* fixture, gconstpointer data)
{
    g_assert(fixture);
    WebKitWebView* view = (WebKitWebView*)fixture->webView;
    g_assert(view);
    WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
    g_assert(document);
    WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_class_name(document, "test");
    g_assert(list);
    gulong length = webkit_dom_node_list_get_length(list);
    g_assert_cmpint(length, ==, 2);

    guint i;

    for (i = 0; i < length; i++) {
        WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
        g_assert(item);
        WebKitDOMElement* element = (WebKitDOMElement*)item;
        g_assert(element);
        g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV");
    }

    g_object_unref(list);
}
Beispiel #10
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);
}
Beispiel #11
0
Datei: dom.c Projekt: 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;
}
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);
}
Beispiel #13
0
int
focus_input(struct tab *t)
{
	WebKitDOMDocument	*doc;
	WebKitDOMNode		*n;
	WebKitDOMNodeList	*fl = NULL, *ifl = NULL;
	int			i, fl_count, ifl_count, rv = 0;

	WebKitDOMHTMLFrameElement	*frame;
	WebKitDOMHTMLIFrameElement	*iframe;

	/*
	 * Here is what we are doing:
	 * See if we got frames or iframes
	 *
	 * if we do focus on input or textarea in frame or in iframe
	 *
	 * if we find nothing or there are no frames focus on first input or
	 * text area
	 */

	doc = webkit_web_view_get_dom_document(t->wv);

	/* get frames */
	fl = webkit_dom_document_get_elements_by_tag_name(doc, "frame");
	fl_count = webkit_dom_node_list_get_length(fl);

	/* get iframes */
	ifl = webkit_dom_document_get_elements_by_tag_name(doc, "iframe");
	ifl_count = webkit_dom_node_list_get_length(ifl);

	/* walk frames and look for a text input */
	for (i = 0; i < fl_count; i++) {
		n = webkit_dom_node_list_item(fl, i);
		frame = (WebKitDOMHTMLFrameElement*)n;
		doc = webkit_dom_html_frame_element_get_content_document(frame);

		if (focus_input_document(t, doc)) {
			rv = 1;
			goto done;
		}
	}

	/* walk iframes and look for a text input */
	for (i = 0; i < ifl_count; i++) {
		n = webkit_dom_node_list_item(ifl, i);
		iframe = (WebKitDOMHTMLIFrameElement*)n;
		doc = webkit_dom_html_iframe_element_get_content_document(iframe);

		if (focus_input_document(t, doc)) {
			rv = 1;
			goto done;
		}
	}

	/* if we made it here nothing got focused so use normal heuristic */
	if (focus_input_document(t, webkit_web_view_get_dom_document(t->wv))) {
		rv = 1;
		goto done;
	}
done:
	if (fl)
		g_object_unref(fl);
	if (ifl)
		g_object_unref(ifl);

	return (rv);
}