[evolution/webkit-composer: 192/231] Implement auto-wrapping of text for normal styled paragraphs.
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit-composer: 192/231] Implement auto-wrapping of text for normal styled paragraphs.
- Date: Fri, 13 Sep 2013 14:22:06 +0000 (UTC)
commit 9d99e13689304cf8073aaf569e6d30abe74ddee0
Author: Tomas Popela <tpopela redhat com>
Date: Wed May 29 14:38:19 2013 +0200
Implement auto-wrapping of text for normal styled paragraphs.
Implement auto-wrapping of text for normal styled paragraphs. Also new
entry in Composer preferences was added to let user change the number of
characters for wrapping.
composer/e-composer-private.c | 121 ++++--
data/org.gnome.evolution.mail.gschema.xml.in | 5 +
e-util/e-editor-actions.c | 2 +-
e-util/e-editor-selection.c | 603 +++++++++++++++++++++++---
e-util/e-editor-selection.h | 4 +-
e-util/e-editor-widget.c | 158 ++++++-
e-util/e-editor-widget.h | 2 +
mail/mail-config.ui | 52 +++-
modules/mail/em-composer-prefs.c | 6 +
9 files changed, 827 insertions(+), 126 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index ae5a87c..99f39a4 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -28,6 +28,8 @@
/* Initial height of the picture gallery. */
#define GALLERY_INITIAL_HEIGHT 150
+#define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
+
static void
composer_setup_charset_menu (EMsgComposer *composer)
{
@@ -604,6 +606,13 @@ e_composer_paste_text (EMsgComposer *composer,
editor_selection = e_editor_widget_get_selection (editor_widget);
e_editor_selection_insert_text (editor_selection, text);
+ e_editor_widget_check_magic_links (editor_widget, FALSE);
+
+ if (e_editor_selection_get_block_format (editor_selection) ==
+ E_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH) {
+ e_editor_selection_wrap_lines (editor_selection, TRUE, NULL);
+ }
+
g_free (text);
return TRUE;
@@ -775,8 +784,11 @@ composer_move_caret (EMsgComposer *composer)
EEditorWidget *editor_widget;
WebKitDOMDocument *document;
WebKitDOMDOMWindow *window;
- WebKitDOMElement *br_bottom;
WebKitDOMDOMSelection *dom_selection;
+ WebKitDOMElement *input_start;
+ WebKitDOMNodeList *list;
+ WebKitDOMNodeList *blockquotes;
+ WebKitDOMElement *element;
GSettings *settings;
gboolean start_bottom;
@@ -794,33 +806,74 @@ composer_move_caret (EMsgComposer *composer)
body = webkit_dom_document_get_body (document);
new_range = webkit_dom_document_create_range (document);
- if (start_bottom) {
- WebKitDOMNodeList *blockquotes;
+ /* If we were just changing composer mode we don't want to insert
+ * new div and we want to set caret to the beginning */
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-changing-mode");
+ if (element) {
+ webkit_dom_node_remove_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ NULL);
- blockquotes = webkit_dom_document_get_elements_by_tag_name (document, "blockquote");
- if (webkit_dom_node_list_get_length (blockquotes) != 0) {
- /* Move caret between reply and signature. */
- new_range = webkit_dom_document_create_range (document);
+ if (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))) {
webkit_dom_range_select_node_contents (new_range,
WEBKIT_DOM_NODE (
- webkit_dom_node_get_next_sibling (webkit_dom_node_list_item
(blockquotes, 0))
- ), NULL);
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+ NULL);
webkit_dom_range_collapse (new_range, TRUE, NULL);
- } else {
- br_bottom = webkit_dom_document_get_element_by_id (document, "-x-evolution-br-reply");
+ webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+ webkit_dom_dom_selection_add_range (dom_selection, new_range);
+ }
+ return;
+ }
+
+ list = webkit_dom_document_get_elements_by_class_name (document, "-x-evo-paragraph");
+ blockquotes = webkit_dom_document_get_elements_by_tag_name (document, "blockquote");
- if (!br_bottom) {
- WebKitDOMElement *br;
+ if (webkit_dom_node_list_get_length (list) == 0) {
+ element = webkit_dom_document_create_element (document, "DIV", NULL);
+ webkit_dom_element_set_class_name (WEBKIT_DOM_ELEMENT (element), "-x-evo-paragraph");
+ webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-input-start");
+ webkit_dom_html_element_set_inner_html (WEBKIT_DOM_HTML_ELEMENT (element),
UNICODE_HIDDEN_SPACE, NULL);
+ }
- br = webkit_dom_document_create_element (document, "BR", NULL);
- webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (br),
"-x-evolution-br-reply");
- webkit_dom_node_append_child (WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (br),
NULL);
- br_bottom = webkit_dom_document_get_element_by_id (document,
"-x-evolution-br-reply");
+ if (start_bottom) {
+ if (webkit_dom_node_list_get_length (blockquotes) != 0) {
+ if (webkit_dom_node_list_get_length (list) == 0) {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ webkit_dom_node_get_next_sibling (
+ webkit_dom_node_list_item (blockquotes, 0)),
+ NULL);
}
+ input_start = webkit_dom_document_get_element_by_id (document, "-x-evo-input-start");
- webkit_dom_range_select_node_contents (new_range, WEBKIT_DOM_NODE (br_bottom), NULL);
+ /* Move caret between reply and signature. */
+ if (input_start)
+ webkit_dom_range_select_node_contents (new_range, WEBKIT_DOM_NODE
(input_start), NULL);
webkit_dom_range_collapse (new_range, FALSE, NULL);
+ } else {
+ if (webkit_dom_node_list_get_length (list) == 0) {
+ if (webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)))
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+ NULL);
+ else
+ webkit_dom_node_append_child (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+
+ webkit_dom_range_select_node_contents (new_range,
+ WEBKIT_DOM_NODE (
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+ NULL);
+ webkit_dom_range_collapse (new_range, TRUE, NULL);
}
g_signal_connect (
@@ -828,18 +881,29 @@ composer_move_caret (EMsgComposer *composer)
G_CALLBACK (composer_size_allocate_cb), NULL);
} else {
/* Move caret on the beginning of message */
- if (!webkit_dom_document_get_element_by_id (document, "-x-evolution-br-reply")) {
- WebKitDOMElement *br;
-
- br = webkit_dom_document_create_element (document, "BR", NULL);
- webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (br),
"-x-evolution-br-reply");
- webkit_dom_node_insert_before (WEBKIT_DOM_NODE (body), WEBKIT_DOM_NODE (br),
webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), NULL);
+ if (webkit_dom_node_list_get_length (list) == 0) {
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (element),
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)),
+ NULL);
+
+ if (webkit_dom_node_list_get_length (blockquotes) != 0) {
+ WebKitDOMElement *br = webkit_dom_document_create_element (document, "BR",
NULL);
+
+ webkit_dom_node_insert_before (
+ WEBKIT_DOM_NODE (body),
+ WEBKIT_DOM_NODE (br),
+ webkit_dom_node_get_next_sibling (
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+ NULL);
+ }
}
webkit_dom_range_select_node_contents (new_range,
WEBKIT_DOM_NODE (
- webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))
- ), NULL);
+ webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body))),
+ NULL);
webkit_dom_range_collapse (new_range, TRUE, NULL);
}
@@ -959,10 +1023,6 @@ insert:
editor_widget = e_editor_get_editor_widget (editor);
selection = e_editor_widget_get_selection (editor_widget);
- /* This prevents our command before/after callbacks from
- * screwing around with the signature as we insert it. */
- composer->priv->in_signature_insert = TRUE;
-
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (editor_widget));
window = webkit_dom_document_get_default_view (document);
dom_selection = webkit_dom_dom_window_get_selection (window);
@@ -1020,7 +1080,6 @@ insert:
}
composer_move_caret (composer);
- composer->priv->in_signature_insert = FALSE;
exit:
g_object_unref (composer);
diff --git a/data/org.gnome.evolution.mail.gschema.xml.in b/data/org.gnome.evolution.mail.gschema.xml.in
index f504fe7..c8b8d56 100644
--- a/data/org.gnome.evolution.mail.gschema.xml.in
+++ b/data/org.gnome.evolution.mail.gschema.xml.in
@@ -168,6 +168,11 @@
<_summary>Enable developer mode</_summary>
<_description>Enables some hidden actions and tools aimed for development and debugging.</_description>
</key>
+ <key name="composer-word-wrap-length" type="i">
+ <default>71</default>
+ <_summary>Number of characters for wrapping</_summary>
+ <_description>Will autowrap lines after given number of characters.</_description>
+ </key>
<key name="drag-and-drop-save-file-format" type="s">
<default>'mbox'</default>
<_summary>Save file format for drag-and-drop operation</_summary>
diff --git a/e-util/e-editor-actions.c b/e-util/e-editor-actions.c
index 3ff1023..df2c3d4 100644
--- a/e-util/e-editor-actions.c
+++ b/e-util/e-editor-actions.c
@@ -881,7 +881,7 @@ static void
action_wrap_lines_cb (GtkAction *action,
EEditor *editor)
{
- e_editor_selection_wrap_lines (editor->priv->selection);
+ e_editor_selection_wrap_lines (editor->priv->selection, FALSE, NULL);
}
static void
diff --git a/e-util/e-editor-selection.c b/e-util/e-editor-selection.c
index 811a1d6..f9ec0c8 100644
--- a/e-util/e-editor-selection.c
+++ b/e-util/e-editor-selection.c
@@ -39,8 +39,6 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_EDITOR_SELECTION, EEditorSelectionPrivate))
-#define WORD_WRAP_LENGTH 71
-
#define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
/**
@@ -62,6 +60,8 @@ struct _EEditorSelectionPrivate {
gchar *font_family;
gulong selection_offset;
+
+ gint word_wrap_length;
};
enum {
@@ -792,7 +792,14 @@ e_editor_selection_class_init (EEditorSelectionClass *class)
static void
e_editor_selection_init (EEditorSelection *selection)
{
+ GSettings *g_settings;
+
selection->priv = E_EDITOR_SELECTION_GET_PRIVATE (selection);
+
+ g_settings = g_settings_new ("org.gnome.evolution.mail");
+ selection->priv->word_wrap_length = g_settings_get_int (g_settings, "composer-word-wrap-length");
+ g_object_unref (g_settings);
+
}
/**
@@ -2222,15 +2229,136 @@ e_editor_selection_insert_image (EEditorSelection *selection,
g_object_unref (editor_widget);
}
+static void
+clear_caret_position_marker (EEditorSelection *selection)
+{
+ EEditorWidget *widget;
+ WebKitDOMDocument *document;
+ WebKitDOMElement *element;
+
+ g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+ widget = e_editor_selection_ref_editor_widget (selection);
+ g_return_if_fail (widget != NULL);
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position");
+
+ if (element) {
+ webkit_dom_node_remove_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+
+ g_object_unref (widget);
+}
+
+static void
+save_caret_position (EEditorSelection *selection)
+{
+ EEditorWidget *widget;
+ WebKitDOMDocument *document;
+ WebKitDOMElement *element;
+ WebKitDOMNode *split_node;
+ WebKitDOMNode *start_offset_node;
+ WebKitDOMRange *range;
+ gulong start_offset;
+
+ g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+ widget = e_editor_selection_ref_editor_widget (selection);
+ g_return_if_fail (widget != NULL);
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+ clear_caret_position_marker (selection);
+
+ range = editor_selection_get_current_range (selection);
+
+ start_offset = webkit_dom_range_get_start_offset (range, NULL);
+ start_offset_node = webkit_dom_range_get_end_container (range, NULL);
+
+ element = webkit_dom_document_create_element (document, "SPAN", NULL);
+ webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-caret-position");
+ webkit_dom_html_element_set_inner_html (WEBKIT_DOM_HTML_ELEMENT (element), "*", NULL);
+
+ if (WEBKIT_DOM_IS_TEXT (start_offset_node)) {
+ WebKitDOMText *split_text;
+
+ split_text = webkit_dom_text_split_text (
+ WEBKIT_DOM_TEXT (start_offset_node),
+ start_offset, NULL);
+ split_node = WEBKIT_DOM_NODE (split_text);
+ } else {
+ split_node = start_offset_node;
+ }
+
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (start_offset_node),
+ WEBKIT_DOM_NODE (element),
+ split_node,
+ NULL);
+
+ g_object_unref (widget);
+}
+
+static void
+restore_caret_position (EEditorSelection *selection)
+{
+ EEditorWidget *widget;
+ WebKitDOMDocument *document;
+ WebKitDOMDOMWindow *window;
+ WebKitDOMDOMSelection *window_selection;
+ WebKitDOMElement *element;
+
+ g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+ widget = e_editor_selection_ref_editor_widget (selection);
+ g_return_if_fail (widget != NULL);
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+ window = webkit_dom_document_get_default_view (document);
+ window_selection = webkit_dom_dom_window_get_selection (window);
+ element = webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position");
+
+ if (element) {
+ WebKitDOMRange *new_range;
+
+ window = webkit_dom_document_get_default_view (document);
+ window_selection = webkit_dom_dom_window_get_selection (window);
+ new_range = webkit_dom_document_create_range (document);
+
+ webkit_dom_range_select_node_contents (
+ new_range, WEBKIT_DOM_NODE (element), NULL);
+ webkit_dom_range_collapse (new_range, FALSE, NULL);
+ webkit_dom_dom_selection_remove_all_ranges (window_selection);
+ webkit_dom_dom_selection_add_range (window_selection, new_range);
+
+ webkit_dom_node_remove_child (
+ webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+
+ g_object_unref (widget);
+}
+
static gint
find_where_to_break_line (WebKitDOMNode *node,
- gint max_len)
+ gint max_len,
+ gint word_wrap_length)
{
gchar *str, *text_start;
gunichar uc;
- gint pos, last_space;
+ gint pos;
+ gint last_space = 0;
+ gint length;
+ gint ret_val = 0;
+ gchar* position;
- text_start = webkit_dom_text_get_whole_text ((WebKitDOMText *) node);
+ text_start = webkit_dom_character_data_get_data (WEBKIT_DOM_CHARACTER_DATA (node));
+ length = g_utf8_strlen (text_start, -1);
pos = 0;
last_space = 0;
@@ -2247,9 +2375,21 @@ find_where_to_break_line (WebKitDOMNode *node,
}
/* If last_space is zero then the word is longer than
- * WORD_WRAP_LENGTH characters, so continue untill we find
+ * word_wrap_length characters, so continue untill we find
* a space */
if ((pos > max_len) && (last_space > 0)) {
+ if (last_space > word_wrap_length) {
+ g_free (text_start);
+ return last_space;
+ }
+ if (last_space > max_len) {
+ if (g_unichar_isspace (g_utf8_get_char (text_start)))
+ ret_val = 1;
+
+ g_free (text_start);
+
+ return ret_val;
+ }
g_free (text_start);
return last_space;
}
@@ -2262,57 +2402,124 @@ find_where_to_break_line (WebKitDOMNode *node,
str = g_utf8_next_char (str);
} while (*str);
+ position = g_utf8_offset_to_pointer (text_start, max_len);
+
+ if (g_unichar_isspace (g_utf8_get_char (position))) {
+ ret_val = max_len + 1;
+ } else {
+ if (last_space < max_len) {
+ ret_val = last_space;
+ } else {
+ if (length > word_wrap_length)
+ ret_val = last_space;
+ else
+ ret_val = 0;
+ }
+ }
+
g_free (text_start);
- return max_len;
+
+ return ret_val;
}
-/**
- * e_editor_selection_wrap_lines:
- * @selection: an #EEditorSelection
- *
- * Wraps all lines in current selection to be 71 characters long.
- */
-void
-e_editor_selection_wrap_lines (EEditorSelection *selection)
+static void
+wrap_lines (EEditorSelection *selection,
+ WebKitWebView *web_view,
+ gboolean jump_to_previous_line,
+ gboolean remove_all_br,
+ gint word_wrap_length)
{
- EEditorWidget *editor_widget;
- WebKitWebView *web_view;
- WebKitDOMRange *range;
+ WebKitDOMDocumentFragment *fragment;
WebKitDOMNode *node, *start_node;
WebKitDOMDocument *document;
WebKitDOMElement *element;
- WebKitDOMDocumentFragment *fragment;
- gint len;
+ WebKitDOMNodeList *wrap_br;
+ gint len, ii, br_count;
gchar *html;
+ gulong length_left;
- g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
-
- editor_widget = e_editor_selection_ref_editor_widget (selection);
- g_return_if_fail (editor_widget != NULL);
-
- web_view = WEBKIT_WEB_VIEW (editor_widget);
+ document = webkit_web_view_get_dom_document (web_view);
- /* When there is nothing selected, we select the whole document */
- if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
- EEditorWidgetCommand command;
- command = E_EDITOR_WIDGET_COMMAND_SELECT_ALL;
- e_editor_widget_exec_command (editor_widget, command, NULL);
+ fragment = webkit_dom_range_clone_contents (
+ editor_selection_get_current_range (selection),
+ NULL);
+
+ /* Select all BR elements or just ours that are used for wrapping.
+ * We are not removing user BR elements when this function is activated
+ * from Format->Wrap Lines action */
+ wrap_br = webkit_dom_document_fragment_query_selector_all (
+ fragment,
+ (remove_all_br) ? "br" : "br.-x-evo-wrap-br",
+ NULL);
+
+ /* And remove them */
+ br_count = webkit_dom_node_list_get_length (wrap_br);
+ for (ii = br_count; ii > 0; ii--) {
+ WebKitDOMNode *br = webkit_dom_node_list_item (wrap_br, ii);
+ webkit_dom_node_remove_child (
+ webkit_dom_node_get_parent_node (br), br, NULL);
}
- document = webkit_web_view_get_dom_document (web_view);
- range = editor_selection_get_current_range (selection);
-
- /* Copy the selection from DOM, wrap the lines and then paste it back
- * using the DOM command which will overwrite the selection, and
- * record it as an undoable action */
- fragment = webkit_dom_range_clone_contents (range, NULL);
node = WEBKIT_DOM_NODE (fragment);
start_node = node;
len = 0;
while (node) {
- /* Find nearest text node */
- if (webkit_dom_node_get_node_type (node) != 3) {
+ if (WEBKIT_DOM_IS_TEXT (node)) {
+ if (jump_to_previous_line) {
+ /* If we need to jump to the previous line (e.g. Backspace pressed
+ * on the beginning of line we need to remove last character on
+ * the line that is above that line */
+ WebKitDOMNode *next_sibling = webkit_dom_node_get_next_sibling (node);
+
+ if (WEBKIT_DOM_IS_HTML_ELEMENT (next_sibling) &&
+ (g_strcmp0 (webkit_dom_html_element_get_id (WEBKIT_DOM_HTML_ELEMENT
(next_sibling)),
+ "-x-evo-caret-position")) == 0) {
+
+ webkit_dom_character_data_delete_data (
+ WEBKIT_DOM_CHARACTER_DATA (node),
+ webkit_dom_character_data_get_length
(WEBKIT_DOM_CHARACTER_DATA (node)) - 1,
+ 1, NULL);
+ }
+ }
+
+ /* If there is temporary hidden space we remove it */
+ if (strstr (webkit_dom_node_get_text_content (node), UNICODE_HIDDEN_SPACE))
+ webkit_dom_character_data_delete_data (
+ WEBKIT_DOM_CHARACTER_DATA (node), 0, 1, NULL);
+ } else {
+ /* If element is ANCHOR we wrap it separately */
+ if (WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT (node)) {
+ glong anchor_length;
+
+ anchor_length = g_utf8_strlen (webkit_dom_node_get_text_content (node), -1);
+ if (len + anchor_length > word_wrap_length) {
+ element = webkit_dom_document_create_element (
+ document, "BR", NULL);
+ webkit_dom_element_set_class_name (element, "-x-evo-wrap-br");
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ node,
+ NULL);
+ len = anchor_length;
+ } else
+ len += anchor_length;
+
+ node = webkit_dom_node_get_next_sibling (node);
+ continue;
+ }
+ /* When we are not removing user-entered BR elements (lines wrapped by user),
+ * we need to skip those elements */
+ if (!remove_all_br && g_strcmp0 (webkit_dom_node_get_local_name (node), "br") == 0) {
+ if (!g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT
(node)), "-x-evo-wrap-br") == 0) {
+ len = 0;
+ node = webkit_dom_node_get_next_sibling (node);
+ continue;
+ }
+ }
+
+ /* Find nearest text node */
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)) {
@@ -2331,47 +2538,76 @@ e_editor_selection_wrap_lines (EEditorSelection *selection)
}
/* If length of this node + what we already have is still less
- * then 71 characters, then just join it and continue to next
+ * then word_wrap_length characters, then just join it and continue to next
* node */
- if ((webkit_dom_character_data_get_length (
- (WebKitDOMCharacterData *) node) + len) < WORD_WRAP_LENGTH) {
-
- len += webkit_dom_character_data_get_length (
- (WebKitDOMCharacterData *) node);
+ length_left = webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA (node));
+ if ((length_left + len) < word_wrap_length) {
+ len += length_left;
} else {
- gint offset;
-
- /* Find where we can line-break the node so that it
- * effectively fills the rest of current row */
- offset = find_where_to_break_line (node, WORD_WRAP_LENGTH - len);
-
- if (offset > 0) {
- /* Split the node and append <BR> tag to it */
- webkit_dom_text_split_text (
- (WebKitDOMText *) node, len + offset, NULL);
-
- element = webkit_dom_document_create_element (
- document, "BR", NULL);
-
- /* WebKit throws warning when ref_child is NULL */
- if (webkit_dom_node_get_next_sibling (node)) {
- webkit_dom_node_insert_before (
- webkit_dom_node_get_parent_node (node),
- WEBKIT_DOM_NODE (element),
- webkit_dom_node_get_next_sibling (node),
- NULL);
+ gint offset = 0;
+
+ /* wrap until we have something */
+ while ((length_left + len) > word_wrap_length) {
+ /* Find where we can line-break the node so that it
+ * effectively fills the rest of current row */
+ offset = find_where_to_break_line (node, word_wrap_length - len,
word_wrap_length);
+
+ element = webkit_dom_document_create_element (document, "BR", NULL);
+ webkit_dom_element_set_class_name (element, "-x-evo-wrap-br");
+
+ if (offset > 0 && offset <= word_wrap_length) {
+ if (offset != length_left) {
+ webkit_dom_text_split_text (
+ WEBKIT_DOM_TEXT (node), offset, NULL);
+ }
+ if (webkit_dom_node_get_next_sibling (node)) {
+ WebKitDOMNode *nd = webkit_dom_node_get_next_sibling (node);
+ nd = webkit_dom_node_get_next_sibling (node);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ nd,
+ NULL);
+ } else {
+ webkit_dom_node_append_child (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+ } else if (offset > word_wrap_length) {
+ if (offset != length_left) {
+ webkit_dom_text_split_text (
+ WEBKIT_DOM_TEXT (node), offset + 1, NULL);
+ }
+ if (webkit_dom_node_get_next_sibling (node)) {
+ WebKitDOMNode *nd = webkit_dom_node_get_next_sibling (node);
+ nd = webkit_dom_node_get_next_sibling (node);
+ webkit_dom_node_insert_before (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ nd,
+ NULL);
+ } else {
+ webkit_dom_node_append_child (
+ webkit_dom_node_get_parent_node (node),
+ WEBKIT_DOM_NODE (element),
+ NULL);
+ }
+ len = 0;
+ break;
} else {
- webkit_dom_node_append_child (
+ webkit_dom_node_insert_before (
webkit_dom_node_get_parent_node (node),
WEBKIT_DOM_NODE (element),
+ node,
NULL);
}
-
+ length_left = webkit_dom_character_data_get_length (WEBKIT_DOM_CHARACTER_DATA
(node));
len = 0;
}
+ len += length_left - offset;
}
-
/* Skip to next node */
if (webkit_dom_node_get_next_sibling (node)) {
node = webkit_dom_node_get_next_sibling (node);
@@ -2390,17 +2626,240 @@ e_editor_selection_wrap_lines (EEditorSelection *selection)
/* Create a wrapper DIV and put the processed content into it */
element = webkit_dom_document_create_element (document, "DIV", NULL);
webkit_dom_node_append_child (
- WEBKIT_DOM_NODE (element), WEBKIT_DOM_NODE (start_node), NULL);
+ WEBKIT_DOM_NODE (element),
+ WEBKIT_DOM_NODE (start_node),
+ NULL);
/* Get HTML code of the processed content */
html = webkit_dom_html_element_get_inner_html (
- WEBKIT_DOM_HTML_ELEMENT (element));
+ WEBKIT_DOM_HTML_ELEMENT (element));
/* Overwrite the current selection be the processed content, so that
* "UNDO" and "REDO" buttons work as expected */
e_editor_selection_insert_html (selection, html);
g_free (html);
+}
+
+static gboolean
+check_if_previously_wrapped (WebKitDOMDocument *document)
+{
+ WebKitDOMNode *sibling;
+ sibling = WEBKIT_DOM_NODE (webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position"));
+
+ while (sibling) {
+ if (sibling && WEBKIT_DOM_IS_ELEMENT (sibling)) {
+ if (g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (sibling)),
"-x-evo-wrap-br") == 0) {
+ return TRUE;
+ }
+ }
+ sibling = webkit_dom_node_get_next_sibling (sibling);
+ }
+ return FALSE;
+}
+
+/**
+ * e_editor_selection_wrap_lines:
+ * @selection: an #EEditorSelection
+ * @while_typing: If true this function is capable to wrap while typing
+ * @event: GdkEventKey of pressed key - can be NULL
+ *
+ * Wraps all lines in current selection to be 71 characters long.
+ */
+void
+e_editor_selection_wrap_lines (EEditorSelection *selection,
+ gboolean while_typing,
+ GdkEventKey *event)
+{
+ EEditorWidget *editor_widget;
+ WebKitWebView *web_view;
+ WebKitDOMRange *range;
+ WebKitDOMDocument *document;
+ WebKitDOMDOMWindow *window;
+ WebKitDOMDOMSelection *window_selection;
+ gboolean adding = FALSE;
+ gboolean return_pressed = FALSE;
+ gboolean jump_to_previous_line = FALSE;
+ gboolean previously_wrapped = FALSE;
+
+ g_return_if_fail (E_IS_EDITOR_SELECTION (selection));
+
+ editor_widget = e_editor_selection_ref_editor_widget (selection);
+ g_return_if_fail (editor_widget != NULL);
+
+ if (event != NULL) {
+ if ((event->keyval == GDK_KEY_Return) ||
+ (event->keyval == GDK_KEY_Linefeed) ||
+ (event->keyval == GDK_KEY_KP_Enter)) {
+
+ return_pressed = TRUE;
+ }
+
+ if (return_pressed || (event->keyval == GDK_KEY_space))
+ adding = TRUE;
+ }
+
+ web_view = WEBKIT_WEB_VIEW (editor_widget);
+ document = webkit_web_view_get_dom_document (web_view);
+ window = webkit_dom_document_get_default_view (document);
+
+ if (while_typing) {
+ WebKitDOMNode *end_container;
+ WebKitDOMNode *parent;
+ gulong start_offset;
+
+ /* We need to save caret position and restore it after
+ * wrapping the selection, but we need to save it before we
+ * start to modify selection */
+ range = editor_selection_get_current_range (selection);
+ save_caret_position (selection);
+
+ start_offset = webkit_dom_range_get_start_offset (range, NULL);
+ /* Extend the range to include entire nodes */
+ webkit_dom_range_select_node_contents (
+ range,
+ webkit_dom_range_get_common_ancestor_container (range, NULL),
+ NULL);
+
+ window_selection = webkit_dom_dom_window_get_selection (window);
+
+ end_container = webkit_dom_range_get_end_container (range, NULL);
+
+ previously_wrapped = check_if_previously_wrapped (document);
+
+ /* Wrap only text surrounded in DIV and P tags */
+ parent = webkit_dom_node_get_parent_node(end_container);
+ if (WEBKIT_DOM_IS_HTML_DIV_ELEMENT (parent) || WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT (parent))
{
+ webkit_dom_element_set_class_name (WEBKIT_DOM_ELEMENT (parent), "-x-evo-paragraph");
+ } else {
+ /* If Return is pressed we need to select element above caret */
+ if (return_pressed) {
+ WebKitDOMNode *position = WEBKIT_DOM_NODE
(webkit_dom_document_get_element_by_id (document, "-x-evo-caret-position"));
+ end_container = webkit_dom_node_get_previous_sibling (position);
+ }
+ else {
+ /* When some weird element is selected, return */
+ clear_caret_position_marker (selection);
+ return;
+ }
+ }
+
+ if (previously_wrapped) {
+ /* Modifying previously wrapped line */
+
+ /* If we are on the beginning of line we need to remember it */
+ if (!adding && start_offset > selection->priv->word_wrap_length)
+ jump_to_previous_line = TRUE;
+
+ webkit_dom_dom_selection_select_all_children (
+ window_selection,
+ webkit_dom_node_get_parent_node (end_container),
+ NULL);
+
+ webkit_dom_range_select_node_contents (
+ range,
+ webkit_dom_node_get_parent_node (end_container),
+ NULL);
+ } else {
+ if (adding && return_pressed) {
+ /* If return is pressed end_container is already set
+ * to parent (DIV or P) */
+ webkit_dom_dom_selection_select_all_children (
+ window_selection,
+ end_container,
+ NULL);
+ } else {
+ webkit_dom_dom_selection_select_all_children (
+ window_selection,
+ webkit_dom_node_get_parent_node (end_container),
+ NULL);
+ }
+
+ /* If there is less than word_wrap_length characters do nothing */
+ if (g_utf8_strlen (e_editor_selection_get_string (selection), -1) <
selection->priv->word_wrap_length) {
+ if (return_pressed) {
+ webkit_dom_dom_selection_collapse_to_end (window_selection, NULL);
+ clear_caret_position_marker (selection);
+ webkit_dom_dom_selection_modify (window_selection, "move", "forward",
"character");
+ } else {
+ restore_caret_position (selection);
+ }
+ return;
+ }
+
+ if (return_pressed)
+ /* If return is pressed end_container is already set
+ * to parent (DIV or P) */
+ webkit_dom_range_select_node_contents (
+ range,
+ end_container,
+ NULL);
+ else
+ webkit_dom_range_select_node_contents (
+ range,
+ webkit_dom_node_get_parent_node (end_container),
+ NULL);
+
+ if (!adding && start_offset > selection->priv->word_wrap_length)
+ jump_to_previous_line = TRUE;
+ }
+
+ wrap_lines (selection, web_view, jump_to_previous_line,
+ FALSE, selection->priv->word_wrap_length);
+ } else {
+ /* When there is nothing selected, we select and wrap everything
+ * that is not containing signature */
+ if (g_strcmp0 (e_editor_selection_get_string (selection), "") == 0) {
+ WebKitDOMNodeList *list;
+ WebKitDOMNode *signature = NULL;
+ gint ii;
+
+ window_selection = webkit_dom_dom_window_get_selection (window);
+
+ /* Check if signature is presented in editor */
+ list = webkit_dom_document_get_elements_by_class_name (document,
"-x-evolution-signature");
+ if (webkit_dom_node_list_get_length (list) > 0)
+ signature = webkit_dom_node_list_item (list, 0);
+
+ if (signature) {
+ list = webkit_dom_document_query_selector_all (document, "div, pre, p", NULL);
+
+ for (ii = 0; ii < webkit_dom_node_list_get_length (list); ii++) {
+ WebKitDOMNode *node;
+ node = webkit_dom_node_list_item (list, ii);
+
+ /* Select elements that actualy have some text content */
+ if (g_utf8_strlen (webkit_dom_node_get_text_content (node), -1) == 0)
+ continue;
+
+ if (!webkit_dom_node_contains (node, signature)
+ && !webkit_dom_node_contains (signature, node)) {
+ webkit_dom_dom_selection_select_all_children (
+ window_selection,
+ node,
+ NULL);
+ wrap_lines (selection, web_view, jump_to_previous_line,
+ FALSE, selection->priv->word_wrap_length);
+ }
+ }
+ } else {
+ /* Select all */
+ EEditorWidgetCommand command;
+ command = E_EDITOR_WIDGET_COMMAND_SELECT_ALL;
+ e_editor_widget_exec_command (editor_widget, command, NULL);
+ wrap_lines (selection, web_view, jump_to_previous_line,
+ FALSE, selection->priv->word_wrap_length);
+ }
+ }
+ }
+
+ /* We have to move caret on position where it was before modifying the text */
+ if (return_pressed) {
+ clear_caret_position_marker (selection);
+ /* If Return is pressed we need to move the caret again below the text */
+ webkit_dom_dom_selection_modify (window_selection, "move", "forward", "character");
+ } else
+ restore_caret_position (selection);
g_object_unref (editor_widget);
}
diff --git a/e-util/e-editor-selection.h b/e-util/e-editor-selection.h
index ff4ab30..ae4834a 100644
--- a/e-util/e-editor-selection.h
+++ b/e-util/e-editor-selection.h
@@ -154,7 +154,9 @@ void e_editor_selection_insert_image (EEditorSelection *selection,
const gchar *image_uri);
void e_editor_selection_insert_text (EEditorSelection *selection,
const gchar *plain_text);
-void e_editor_selection_wrap_lines (EEditorSelection *selection);
+void e_editor_selection_wrap_lines (EEditorSelection *selection,
+ gboolean while_typing,
+ GdkEventKey *event);
void e_editor_selection_save (EEditorSelection *selection);
void e_editor_selection_restore (EEditorSelection *selection);
void e_editor_selection_move (EEditorSelection *selection,
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index c637fc9..069ad43 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -35,6 +35,16 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_EDITOR_WIDGET, EEditorWidgetPrivate))
+#define UNICODE_HIDDEN_SPACE "\xe2\x80\x8b"
+
+#define URL_PATTERN \
+ "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?" \
+ "[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)" \
+ "[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\?" \
+ "?(?:[\\-\\+=&;% \\ \\w]*)#?(?:[\\.\\!\\/\\\\w]*))?)"
+
+#define URL_PATTERN_SPACE URL_PATTERN "\\s"
+
/**
* EEditorWidget:
*
@@ -304,7 +314,8 @@ static const gchar *emoticons_icon_names[] = {
static void
editor_widget_check_magic_links (EEditorWidget *widget,
- WebKitDOMRange *range)
+ WebKitDOMRange *range,
+ gboolean include_space)
{
gchar *node_text;
gchar **urls;
@@ -313,11 +324,6 @@ editor_widget_check_magic_links (EEditorWidget *widget,
gint start_pos_url, end_pos_url;
WebKitDOMNode *node;
- const gchar *url_pattern = "((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?"
- "[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)"
- "[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%\\/\\.\\w\\-]*)?\\?"
- "?(?:[\\-\\+=&;% \\ \\w]*)#?(?:[\\.\\!\\/\\\\w]*))?)\\s";
-
node = webkit_dom_range_get_end_container (range, NULL);
if (!WEBKIT_DOM_IS_TEXT (node))
@@ -327,7 +333,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
if (!node_text || !g_utf8_validate (node_text, -1, NULL))
return;
- regex = g_regex_new (url_pattern, 0, 0, NULL);
+ regex = g_regex_new (include_space ? URL_PATTERN_SPACE : URL_PATTERN, 0, 0, NULL);
if (!regex) {
g_free (node_text);
@@ -355,7 +361,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
url_start = url_end - url_length;
/* Remove space on end */
- url = g_utf8_substring (urls[0], 0, url_length - 1);
+ url = g_utf8_substring (urls[0], 0, include_space ? url_length - 1 : url_length);
/* Select the link and put it inside <A> */
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
@@ -364,7 +370,7 @@ editor_widget_check_magic_links (EEditorWidget *widget,
webkit_dom_dom_selection_set_base_and_extent (
selection, webkit_dom_range_get_end_container (range, NULL),
- url_end - 1, webkit_dom_range_get_end_container (range, NULL),
+ include_space ? url_end - 1 : url_end, webkit_dom_range_get_end_container (range,
NULL),
url_start, NULL);
if (g_str_has_prefix (url, "www"))
@@ -900,7 +906,16 @@ editor_widget_key_release_event (GtkWidget *widget,
editor_widget_check_magic_smileys (editor_widget, range);
}
- editor_widget_check_magic_links (editor_widget, range);
+ if (event->keyval == GDK_KEY_space) {
+ editor_widget_check_magic_links (editor_widget, range, TRUE);
+ }
+
+ if ((event->keyval == GDK_KEY_Return) ||
+ (event->keyval == GDK_KEY_Linefeed) ||
+ (event->keyval == GDK_KEY_KP_Enter)) {
+
+ editor_widget_check_magic_links (editor_widget, range, FALSE);
+ }
if ((event->keyval == GDK_KEY_Control_L) ||
(event->keyval == GDK_KEY_Control_R)) {
@@ -908,6 +923,18 @@ editor_widget_key_release_event (GtkWidget *widget,
editor_widget_set_links_active (editor_widget, FALSE);
}
+ if ((event->keyval == GDK_KEY_space) ||
+ (event->keyval == GDK_KEY_Delete) ||
+ (event->keyval == GDK_KEY_Return) ||
+ (event->keyval == GDK_KEY_Linefeed) ||
+ (event->keyval == GDK_KEY_KP_Enter) ||
+ (event->keyval == GDK_KEY_BackSpace)) {
+
+ EEditorSelection *selection;
+ selection = e_editor_widget_get_selection (editor_widget);
+ if (e_editor_selection_get_block_format (selection) ==
E_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH)
+ e_editor_selection_wrap_lines (selection, TRUE, event);
+ }
/* Chain up to parent's key_release_event() method. */
return GTK_WIDGET_CLASS (e_editor_widget_parent_class)->
key_release_event (widget, event);
@@ -1429,6 +1456,8 @@ void
e_editor_widget_set_html_mode (EEditorWidget *widget,
gboolean html_mode)
{
+ gboolean changing = FALSE;
+
g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
/* If toggling from HTML to plain text mode, ask user first */
@@ -1459,11 +1488,16 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
/* Nothing has changed, but notify anyway */
g_object_notify (G_OBJECT (widget), "html-mode");
return;
+ } else {
+ changing = TRUE;
}
gtk_widget_destroy (dialog);
}
+ if (html_mode)
+ changing = TRUE;
+
if (html_mode == widget->priv->html_mode)
return;
@@ -1488,6 +1522,13 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED,
0);
+ if (changing) {
+ gchar *tmp;
+ tmp = g_strconcat (html, "<span id=\"-x-evo-changing-mode\"></span>", NULL);
+ g_free (html);
+ html = tmp;
+ }
+
e_editor_widget_set_text_html (widget, html);
g_free (plain_text);
@@ -1497,8 +1538,16 @@ e_editor_widget_set_html_mode (EEditorWidget *widget,
plain = e_editor_widget_get_text_plain (widget);
- if (*plain)
+ if (*plain) {
+ if (changing) {
+ gchar *tmp;
+ tmp = g_strconcat (plain, UNICODE_HIDDEN_SPACE, NULL);
+ g_free (plain);
+ plain = tmp;
+ }
+
e_editor_widget_set_text_plain (widget, plain);
+ }
g_free (plain);
}
@@ -1666,7 +1715,7 @@ process_elements (WebKitDOMNode *node,
WebKitDOMCSSStyleDeclaration *style;
gchar *display, *tagname;
gulong ii, length;
- GRegex *regex;
+ GRegex *regex, *regex_hidden_space;
document = webkit_dom_node_get_owner_document (node);
window = webkit_dom_document_get_default_view (document);
@@ -1702,9 +1751,14 @@ process_elements (WebKitDOMNode *node,
}
}
+ /* Skip signature */
+ if (g_strcmp0 (webkit_dom_element_get_class_name (WEBKIT_DOM_ELEMENT (node)),
"-x-evolution-signature") == 0)
+ return;
+
nodes = webkit_dom_node_get_child_nodes (node);
length = webkit_dom_node_list_get_length (nodes);
regex = g_regex_new ("\x9", 0, 0, NULL);
+ regex_hidden_space = g_regex_new (UNICODE_HIDDEN_SPACE, 0, 0, NULL);
for (ii = 0; ii < length; ii++) {
WebKitDOMNode *child;
@@ -1718,12 +1772,19 @@ process_elements (WebKitDOMNode *node,
/* Replace tabs with 4 whitespaces, otherwise they got
* replaced by single whitespace */
content = g_regex_replace (
- regex, tmp, -1, 0, " ",
- 0, NULL);
+ regex, tmp, -1, 0, " ",
+ 0, NULL);
+
+ content = g_regex_replace (
+ regex_hidden_space, content, -1, 0, "", 0, NULL);
g_string_append (buffer, content);
g_free (tmp);
g_free (content);
+ } else {
+ if (g_strcmp0 (webkit_dom_node_get_local_name (child), "br") == 0) {
+ g_string_append (buffer, "\n");
+ }
}
if (webkit_dom_node_has_child_nodes (child)) {
@@ -1731,12 +1792,9 @@ process_elements (WebKitDOMNode *node,
}
}
- if (g_strcmp0 (display, "block") == 0 && g_strcmp0 (tagname, "BODY") != 0) {
- g_string_append (buffer, "\n");
- }
-
g_free (display);
g_regex_unref (regex);
+ g_regex_unref (regex_hidden_space);
}
/**
@@ -1757,7 +1815,7 @@ e_editor_widget_get_text_plain (EEditorWidget *widget)
GString *plain_text;
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
- body = (WebKitDOMNode *) webkit_dom_document_get_body (document);
+ body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
plain_text = g_string_sized_new (1024);
process_elements (body, plain_text);
@@ -1787,8 +1845,39 @@ static void
do_set_text_plain (EEditorWidget *widget,
gpointer data)
{
+ gboolean changing = FALSE;
+ const gchar *ptr;
+ gchar *data_copy = NULL;
+
+ if (strstr (data, UNICODE_HIDDEN_SPACE)) {
+ g_utf8_strncpy (data_copy, data, g_utf8_strlen (data, -1) - 1);
+ ptr = data_copy;
+ changing = TRUE;
+ } else {
+ ptr = data;
+ }
+
e_editor_widget_exec_command (
- widget, E_EDITOR_WIDGET_COMMAND_INSERT_TEXT, data);
+ widget, E_EDITOR_WIDGET_COMMAND_INSERT_TEXT, ptr);
+
+ if (changing) {
+ WebKitDOMDocument *document;
+ WebKitDOMNode *body;
+ WebKitDOMElement *element;
+
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (widget));
+ body = WEBKIT_DOM_NODE (webkit_dom_document_get_body (document));
+
+ element = webkit_dom_document_create_element (document, "SPAN", NULL);
+ webkit_dom_html_element_set_id (WEBKIT_DOM_HTML_ELEMENT (element), "-x-evo-changing-mode");
+
+ webkit_dom_node_append_child (
+ body,
+ WEBKIT_DOM_NODE (element),
+ NULL);
+
+ g_free (data_copy);
+ }
}
/**
@@ -2044,6 +2133,14 @@ e_editor_widget_update_fonts (EEditorWidget *widget)
pango_font_description_free (vw);
}
+/**
+ * e_editor_widget_get_element_under_mouse_click:
+ * @widget: an #EEditorWidget
+ *
+ * Returns DOM element, that was clicked on.
+ *
+ * Returns: DOM element on that was clicked.
+ */
WebKitDOMElement *
e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget)
{
@@ -2051,3 +2148,24 @@ e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget)
return widget->priv->element_under_mouse;
}
+
+/**
+ * e_editor_widget_check_magic_links
+ * @widget: an #EEditorWidget
+ * @include_space: If TRUE the pattern for link expects space on end
+ *
+ * Check if actual selection in given editor is link. If so, it is surrounded
+ * with ANCHOR element.
+ */
+void
+e_editor_widget_check_magic_links (EEditorWidget *widget,
+ gboolean include_space)
+{
+ WebKitDOMRange *range;
+
+ g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
+
+ range = editor_widget_get_dom_range (widget);
+ editor_widget_check_magic_links (widget, range, include_space);
+}
+
diff --git a/e-util/e-editor-widget.h b/e-util/e-editor-widget.h
index e2831ad..42c598b 100644
--- a/e-util/e-editor-widget.h
+++ b/e-util/e-editor-widget.h
@@ -110,6 +110,8 @@ void e_editor_widget_update_fonts (EEditorWidget *widget);
WebKitDOMElement *
e_editor_widget_get_element_under_mouse_click (EEditorWidget *widget);
+void e_editor_widget_check_magic_links (EEditorWidget *widget,
+ gboolean while_typing);
G_END_DECLS
#endif /* E_EDITOR_WIDGET_H */
diff --git a/mail/mail-config.ui b/mail/mail-config.ui
index f26c0f6..49042dc 100644
--- a/mail/mail-config.ui
+++ b/mail/mail-config.ui
@@ -175,6 +175,13 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
+ <object class="GtkAdjustment" id="adjustment7">
+ <property name="upper">200</property>
+ <property name="lower">31</property>
+ <property name="value">71</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
<object class="GtkNotebook" id="composer_toplevel">
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -280,6 +287,49 @@
</packing>
</child>
<child>
+ <object class="GtkHBox" id="hboxWrapCharactersCount">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="lblWordWrapLength">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Number of characters for word
w_rapping:</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spinWordWrapLength">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="max_length">3</property>
+ <property name="adjustment">adjustment7</property>
+ <property name="caps_lock_warning">False</property>
+ <property name="numeric">True</property>
+ <property name="update_policy">if-valid</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkHBox" id="hboxComposerCharset">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -306,7 +356,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">4</property>
+ <property name="position">5</property>
</packing>
</child>
</object>
diff --git a/modules/mail/em-composer-prefs.c b/modules/mail/em-composer-prefs.c
index 1a2bf1c..d584ec2 100644
--- a/modules/mail/em-composer-prefs.c
+++ b/modules/mail/em-composer-prefs.c
@@ -339,6 +339,12 @@ em_composer_prefs_construct (EMComposerPrefs *prefs,
widget, "active",
G_SETTINGS_BIND_DEFAULT);
+ widget = e_builder_get_widget (prefs->builder, "spinWordWrapLength");
+ g_settings_bind (
+ settings, "composer-word-wrap-length",
+ widget, "value",
+ G_SETTINGS_BIND_DEFAULT);
+
widget = e_builder_get_widget (prefs->builder, "chkOutlookFilenames");
g_settings_bind (
settings, "composer-outlook-filenames",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]