[evolution/449-support-markdown-in-composer: 14/15] EMarkdownEditor: Implement more EContentEditor methods
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/449-support-markdown-in-composer: 14/15] EMarkdownEditor: Implement more EContentEditor methods
- Date: Tue, 8 Feb 2022 09:51:57 +0000 (UTC)
commit da1f2a6097cabf7bc43e9625783b6a9f25e70a43
Author: Milan Crha <mcrha redhat com>
Date: Mon Feb 7 16:06:58 2022 +0100
EMarkdownEditor: Implement more EContentEditor methods
Also do related changes in the EHTMLEdtior and the EMsgComposer.
src/composer/e-msg-composer.c | 4 +-
src/e-util/e-content-editor.c | 52 ++++++++
src/e-util/e-content-editor.h | 6 +-
src/e-util/e-html-editor.c | 69 +++++++++-
src/e-util/e-markdown-editor.c | 290 +++++++++++++++++++++++++++++++++++++++--
src/e-util/e-markdown-editor.h | 4 +
6 files changed, 410 insertions(+), 15 deletions(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index cea20f8cc1..97cbdfd933 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -2764,11 +2764,11 @@ msg_composer_key_press_event (GtkWidget *widget,
}
if (event->keyval == GDK_KEY_Tab && gtk_widget_is_focus (input_widget)) {
- gtk_widget_grab_focus (GTK_WIDGET (cnt_editor));
+ e_content_editor_grab_focus (cnt_editor);
return TRUE;
}
- if (gtk_widget_is_focus (GTK_WIDGET (cnt_editor))) {
+ if (e_content_editor_is_focus (cnt_editor)) {
if (event->keyval == GDK_KEY_ISO_Left_Tab) {
gboolean view_processed = FALSE;
diff --git a/src/e-util/e-content-editor.c b/src/e-util/e-content-editor.c
index 73c9b7018c..61971e6867 100644
--- a/src/e-util/e-content-editor.c
+++ b/src/e-util/e-content-editor.c
@@ -666,6 +666,58 @@ e_content_editor_supports_mode (EContentEditor *editor,
iface->supports_mode (editor, mode);
}
+/**
+ * e_content_editor_grab_focus:
+ * @editor: an #EContentEditor
+ *
+ * A method to grab focus on the @editor. This is an optional method,
+ * the default implementation calls gtk_widget_grab_focus().
+ *
+ * Since: 3.44
+ **/
+void
+e_content_editor_grab_focus (EContentEditor *editor)
+{
+ EContentEditorInterface *iface;
+
+ g_return_if_fail (E_IS_CONTENT_EDITOR (editor));
+
+ iface = E_CONTENT_EDITOR_GET_IFACE (editor);
+ g_return_if_fail (iface != NULL);
+
+ if (iface->grab_focus)
+ iface->grab_focus (editor);
+ else
+ gtk_widget_grab_focus (GTK_WIDGET (editor));
+}
+
+/**
+ * e_content_editor_is_focus:
+ * @editor: an #EContentEditor
+ *
+ * Returns, whether the @editor is focused. This is an optional method,
+ * the default implementation calls gtk_widget_is_focus().
+ *
+ * Returns: whether the @editor is focused
+ *
+ * Since: 3.44
+ **/
+gboolean
+e_content_editor_is_focus (EContentEditor *editor)
+{
+ EContentEditorInterface *iface;
+
+ g_return_val_if_fail (E_IS_CONTENT_EDITOR (editor), FALSE);
+
+ iface = E_CONTENT_EDITOR_GET_IFACE (editor);
+ g_return_val_if_fail (iface != NULL, FALSE);
+
+ if (iface->is_focus)
+ return iface->is_focus (editor);
+ else
+ return gtk_widget_is_focus (GTK_WIDGET (editor));
+}
+
ESpellChecker *
e_content_editor_ref_spell_checker (EContentEditor *editor)
{
diff --git a/src/e-util/e-content-editor.h b/src/e-util/e-content-editor.h
index 193dd4a164..487e45ab66 100644
--- a/src/e-util/e-content-editor.h
+++ b/src/e-util/e-content-editor.h
@@ -428,9 +428,11 @@ struct _EContentEditorInterface {
gboolean (*supports_mode) (EContentEditor *editor,
EContentEditorMode mode);
+ void (*grab_focus) (EContentEditor *editor);
+ gboolean (*is_focus) (EContentEditor *editor);
/* padding for future expansion */
- gpointer reserved[19];
+ gpointer reserved[17];
};
/* Properties */
@@ -439,6 +441,8 @@ ESpellChecker * e_content_editor_ref_spell_checker
(EContentEditor *editor);
gboolean e_content_editor_supports_mode (EContentEditor *editor,
EContentEditorMode mode);
+void e_content_editor_grab_focus (EContentEditor *editor);
+gboolean e_content_editor_is_focus (EContentEditor *editor);
gboolean e_content_editor_is_malfunction (EContentEditor *editor);
gboolean e_content_editor_can_cut (EContentEditor *editor);
gboolean e_content_editor_can_copy (EContentEditor *editor);
diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c
index 8a74a8bdcf..8c5c4003ab 100644
--- a/src/e-util/e-html-editor.c
+++ b/src/e-util/e-html-editor.c
@@ -1527,6 +1527,56 @@ e_html_editor_register_content_editor (EHTMLEditor *editor,
}
}
+static void
+e_html_editor_update_content_on_mode_change_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GWeakRef *weak_ref = user_data;
+ EContentEditorContentHash *content_hash;
+ EContentEditor *cnt_editor;
+ EHTMLEditor *editor;
+
+ g_return_if_fail (E_IS_CONTENT_EDITOR (source_object));
+ g_return_if_fail (weak_ref != NULL);
+
+ editor = g_weak_ref_get (weak_ref);
+
+ e_weak_ref_free (weak_ref);
+
+ if (!editor)
+ return;
+
+ cnt_editor = E_CONTENT_EDITOR (source_object);
+ content_hash = e_content_editor_get_content_finish (cnt_editor, result, NULL);
+
+ if (content_hash) {
+ gpointer text;
+
+ text = e_content_editor_util_get_content_data (content_hash,
E_CONTENT_EDITOR_GET_TO_SEND_HTML);
+
+ if (editor->priv->mode == E_CONTENT_EDITOR_MODE_HTML && text) {
+ e_content_editor_insert_content (editor->priv->use_content_editor, text,
+ E_CONTENT_EDITOR_INSERT_CONVERT |
+ E_CONTENT_EDITOR_INSERT_TEXT_HTML |
+ E_CONTENT_EDITOR_INSERT_REPLACE_ALL);
+ } else {
+ text = e_content_editor_util_get_content_data (content_hash,
E_CONTENT_EDITOR_GET_TO_SEND_PLAIN);
+
+ if (text) {
+ e_content_editor_insert_content (editor->priv->use_content_editor, text,
+ E_CONTENT_EDITOR_INSERT_CONVERT |
+ E_CONTENT_EDITOR_INSERT_TEXT_PLAIN |
+ E_CONTENT_EDITOR_INSERT_REPLACE_ALL);
+ }
+ }
+
+ e_content_editor_util_free_content_hash (content_hash);
+ }
+
+ g_object_unref (editor);
+}
+
/**
* e_html_editor_get_mode:
* @editor: an #EHTMLEditor
@@ -1570,11 +1620,24 @@ e_html_editor_set_mode (EHTMLEditor *editor,
if (cnt_editor) {
if (cnt_editor != editor->priv->use_content_editor) {
- if (editor->priv->use_content_editor)
+ gboolean is_focused = FALSE;
+
+ if (editor->priv->use_content_editor) {
+ is_focused = e_content_editor_is_focus (editor->priv->use_content_editor);
+
+ e_content_editor_get_content (editor->priv->use_content_editor,
+ E_CONTENT_EDITOR_GET_TO_SEND_HTML |
E_CONTENT_EDITOR_GET_TO_SEND_PLAIN,
+ "localhost", NULL,
+ e_html_editor_update_content_on_mode_change_cb,
+ e_weak_ref_new (editor));
+
gtk_widget_hide (GTK_WIDGET (editor->priv->use_content_editor));
+ }
+
+ gtk_widget_show (GTK_WIDGET (cnt_editor));
- if (cnt_editor)
- gtk_widget_show (GTK_WIDGET (cnt_editor));
+ if (is_focused)
+ e_content_editor_grab_focus (cnt_editor);
}
editor->priv->mode = mode;
diff --git a/src/e-util/e-markdown-editor.c b/src/e-util/e-markdown-editor.c
index e0909add2a..84a51c5252 100644
--- a/src/e-util/e-markdown-editor.c
+++ b/src/e-util/e-markdown-editor.c
@@ -36,8 +36,7 @@ struct _EMarkdownEditorPrivate {
gboolean can_undo;
gboolean changed;
EContentEditorMode mode;
- gboolean spell_check_enabled;
- ESpellChecker *spell_check;
+ ESpellChecker *spell_checker; /* this is not used internally */
EThreeState start_bottom;
EThreeState top_signature;
};
@@ -89,6 +88,65 @@ enum {
static guint signals[LAST_SIGNAL];
+typedef void (* AsyncCallback) (EMarkdownEditor *self,
+ gpointer user_data);
+
+typedef struct _AsyncData {
+ EMarkdownEditor *self;
+ AsyncCallback callback;
+ gpointer user_data;
+} AsyncData;
+
+static AsyncData *
+async_data_new (EMarkdownEditor *self,
+ AsyncCallback callback,
+ gpointer user_data)
+{
+ AsyncData *data;
+
+ data = g_slice_new (AsyncData);
+ data->self = g_object_ref (self);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static void
+async_data_free (gpointer ptr)
+{
+ AsyncData *data = ptr;
+
+ if (data) {
+ g_clear_object (&data->self);
+ g_slice_free (AsyncData, data);
+ }
+}
+
+static gboolean
+e_markdown_editor_call_async_cb (gpointer user_data)
+{
+ AsyncData *data = user_data;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+ g_return_val_if_fail (data->callback != NULL, FALSE);
+
+ data->callback (data->self, data->user_data);
+
+ return FALSE;
+}
+
+static void
+e_markdown_editor_call_async (EMarkdownEditor *self,
+ AsyncCallback callback,
+ gpointer user_data)
+{
+ g_timeout_add_full (G_PRIORITY_HIGH, 1,
+ e_markdown_editor_call_async_cb,
+ async_data_new (self, callback, user_data),
+ async_data_free);
+}
+
static gboolean
e_markdown_editor_supports_mode (EContentEditor *cnt_editor,
EContentEditorMode mode)
@@ -100,11 +158,53 @@ e_markdown_editor_supports_mode (EContentEditor *cnt_editor,
mode == E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
}
+static void
+e_markdown_editor_grab_focus (EContentEditor *cnt_editor)
+{
+ EMarkdownEditor *self = E_MARKDOWN_EDITOR (cnt_editor);
+
+ gtk_widget_grab_focus (GTK_WIDGET (self->priv->text_view));
+}
+
+static gboolean
+e_markdown_editor_is_focus (EContentEditor *cnt_editor)
+{
+ EMarkdownEditor *self = E_MARKDOWN_EDITOR (cnt_editor);
+
+ return gtk_widget_is_focus (GTK_WIDGET (self->priv->text_view));
+}
+
+typedef struct _InitAsyncData {
+ EContentEditorInitializedCallback callback;
+ gpointer user_data;
+} InitAsyncData;
+
+static void
+e_markdown_editor_initialize_done (EMarkdownEditor *self,
+ gpointer user_data)
+{
+ InitAsyncData *data = user_data;
+
+ g_return_if_fail (data != NULL);
+ g_return_if_fail (data->callback != NULL);
+
+ data->callback (E_CONTENT_EDITOR (self), data->user_data);
+
+ g_slice_free (InitAsyncData, data);
+}
+
static void
e_markdown_editor_initialize (EContentEditor *cnt_editor,
EContentEditorInitializedCallback callback,
gpointer user_data)
{
+ InitAsyncData *data;
+
+ data = g_slice_new (InitAsyncData);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ e_markdown_editor_call_async (E_MARKDOWN_EDITOR (cnt_editor), e_markdown_editor_initialize_done,
data);
}
static gboolean
@@ -123,6 +223,47 @@ e_markdown_editor_insert_content (EContentEditor *cnt_editor,
const gchar *content,
EContentEditorInsertContentFlags flags)
{
+ EMarkdownEditor *self;
+ gchar *text = NULL;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (cnt_editor));
+ g_return_if_fail (content != NULL);
+
+ self = E_MARKDOWN_EDITOR (cnt_editor);
+
+ if ((flags & E_CONTENT_EDITOR_INSERT_TEXT_HTML) != 0) {
+ text = e_markdown_util_html_to_text (content, -1);
+ content = text;
+ }
+
+ if ((flags & E_CONTENT_EDITOR_INSERT_REPLACE_ALL) != 0) {
+ e_markdown_editor_set_text (self, content);
+ } else if ((flags & E_CONTENT_EDITOR_INSERT_QUOTE_CONTENT) != 0) {
+ GtkTextBuffer *text_buffer;
+ GString *quoted;
+ gint ii;
+
+ quoted = g_string_sized_new (strlen (content) + 4);
+ g_string_append (quoted, "> ");
+ g_string_append (quoted, content);
+
+ for (ii = 0; ii < quoted->len; ii++) {
+ if (quoted->str[ii] == '\n' && ii + 1 < quoted->len)
+ g_string_insert (quoted, ii + 1, "> ");
+ }
+
+ text_buffer = gtk_text_view_get_buffer (self->priv->text_view);
+ gtk_text_buffer_insert_at_cursor (text_buffer, quoted->str, -1);
+
+ g_string_free (quoted, TRUE);
+ } else {
+ GtkTextBuffer *text_buffer;
+
+ text_buffer = gtk_text_view_get_buffer (self->priv->text_view);
+ gtk_text_buffer_insert_at_cursor (text_buffer, content, -1);
+ }
+
+ g_free (text);
}
static void
@@ -133,6 +274,78 @@ e_markdown_editor_get_content (EContentEditor *cnt_editor,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ GTask *task;
+ EContentEditorContentHash *content_hash;
+
+ content_hash = e_content_editor_util_new_content_hash ();
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_HTML) != 0 ||
+ (flags & E_CONTENT_EDITOR_GET_TO_SEND_HTML) != 0) {
+ gchar *html;
+
+ html = e_markdown_editor_dup_html (E_MARKDOWN_EDITOR (cnt_editor));
+
+ if (html) {
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_HTML) != 0 &&
+ (flags & E_CONTENT_EDITOR_GET_TO_SEND_HTML) != 0) {
+ e_content_editor_util_put_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_RAW_BODY_HTML, html);
+ e_content_editor_util_take_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_TO_SEND_HTML, html, g_free);
+ } else if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_HTML) != 0) {
+ e_content_editor_util_take_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_RAW_BODY_HTML, html, g_free);
+ } else {
+ e_content_editor_util_take_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_TO_SEND_HTML, html, g_free);
+ }
+ }
+ }
+
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN) != 0 ||
+ (flags & E_CONTENT_EDITOR_GET_RAW_DRAFT) != 0 ||
+ (flags & E_CONTENT_EDITOR_GET_TO_SEND_PLAIN) != 0) {
+ gchar *text;
+
+ text = e_markdown_editor_dup_text (E_MARKDOWN_EDITOR (cnt_editor));
+
+ if (text) {
+ gint n_formats = ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN) != 0 ? 1 : 0) +
+ ((flags & E_CONTENT_EDITOR_GET_RAW_DRAFT) != 0 ? 1 : 0) +
+ ((flags & E_CONTENT_EDITOR_GET_TO_SEND_PLAIN) != 0 ? 1 : 0);
+
+ if (n_formats == 1) {
+ EContentEditorGetContentFlags format;
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN) != 0)
+ format = E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN;
+ else if ((flags & E_CONTENT_EDITOR_GET_RAW_DRAFT) != 0)
+ format = E_CONTENT_EDITOR_GET_RAW_DRAFT;
+ else
+ format = E_CONTENT_EDITOR_GET_TO_SEND_PLAIN;
+
+ e_content_editor_util_take_content_data (content_hash,
+ format, text, g_free);
+ } else {
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN) != 0)
+ e_content_editor_util_put_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_RAW_BODY_PLAIN, text);
+
+ if ((flags & E_CONTENT_EDITOR_GET_RAW_DRAFT) != 0)
+ e_content_editor_util_put_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_RAW_DRAFT, text);
+
+ if ((flags & E_CONTENT_EDITOR_GET_TO_SEND_PLAIN) != 0)
+ e_content_editor_util_put_content_data (content_hash,
+ E_CONTENT_EDITOR_GET_TO_SEND_PLAIN, text);
+
+ g_free (text);
+ }
+ }
+ }
+
+ task = g_task_new (cnt_editor, cancellable, callback, user_data);
+ g_task_set_source_tag (task, e_markdown_editor_get_content);
+ g_task_return_pointer (task, content_hash, (GDestroyNotify) e_content_editor_util_free_content_hash);
+ g_object_unref (task);
}
static EContentEditorContentHash *
@@ -140,7 +353,9 @@ e_markdown_editor_get_content_finish (EContentEditor *cnt_editor,
GAsyncResult *result,
GError **error)
{
- return NULL;
+ g_return_val_if_fail (g_task_is_valid (result, cnt_editor), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
}
static gboolean
@@ -228,15 +443,16 @@ e_markdown_editor_set_mode (EMarkdownEditor *self,
static gboolean
e_markdown_editor_get_spell_check_enabled (EMarkdownEditor *self)
{
- return self->priv->spell_check_enabled;
+ return e_spell_text_view_get_enabled (self->priv->text_view);
}
static void
e_markdown_editor_set_spell_check_enabled (EMarkdownEditor *self,
gboolean value)
{
- if ((self->priv->spell_check_enabled ? 1 : 0) != (value ? 1 : 0)) {
- self->priv->spell_check_enabled = value;
+ gboolean spell_check_enabled = e_markdown_editor_get_spell_check_enabled (self);
+ if ((spell_check_enabled ? 1 : 0) != (value ? 1 : 0)) {
+ e_spell_text_view_set_enabled (self->priv->text_view, value);
g_object_notify (G_OBJECT (self), "spell-check-enabled");
}
}
@@ -244,7 +460,7 @@ e_markdown_editor_set_spell_check_enabled (EMarkdownEditor *self,
static ESpellChecker *
e_markdown_editor_get_spell_checker (EMarkdownEditor *self)
{
- return self->priv->spell_check;
+ return self->priv->spell_checker;
}
static EThreeState
@@ -1056,15 +1272,27 @@ e_markdown_editor_constructed (GObject *object)
e_signal_connect_notify_object (self->priv->text_view, "notify::editable", G_CALLBACK
(e_markdown_editor_notify_editable_cb), self, 0);
}
+static void
+e_markdown_editor_dispose (GObject *object)
+{
+ EMarkdownEditor *self = E_MARKDOWN_EDITOR (object);
+
+ g_clear_object (&self->priv->spell_checker);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_markdown_editor_parent_class)->dispose (object);
+}
+
static void
e_markdown_editor_class_init (EMarkdownEditorClass *klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
- object_class->constructed = e_markdown_editor_constructed;
object_class->get_property = e_markdown_editor_get_property;
object_class->set_property = e_markdown_editor_set_property;
+ object_class->constructed = e_markdown_editor_constructed;
+ object_class->dispose = e_markdown_editor_dispose;
g_object_class_override_property (object_class, PROP_IS_MALFUNCTION, "is-malfunction");
g_object_class_override_property (object_class, PROP_CAN_COPY, "can-copy");
@@ -1117,6 +1345,8 @@ static void
e_markdown_editor_content_editor_init (EContentEditorInterface *iface)
{
iface->supports_mode = e_markdown_editor_supports_mode;
+ iface->grab_focus = e_markdown_editor_grab_focus;
+ iface->is_focus = e_markdown_editor_is_focus;
iface->initialize = e_markdown_editor_initialize;
iface->is_ready = e_markdown_editor_is_ready;
iface->update_styles = e_markdown_editor_update_styles;
@@ -1138,7 +1368,7 @@ e_markdown_editor_content_editor_init (EContentEditorInterface *iface)
iface->find = e_markdown_editor_find;
iface->replace = e_markdown_editor_replace;
iface->replace_all = e_markdown_editor_replace_all;
- iface->get_current_signature_uid = e_markdown_editor_get_current_signature_uid;
+ iface->get_current_signature_uid = e_markdown_editor_get_current_signature_uid;
iface->insert_signature = e_markdown_editor_insert_signature;*/
}
@@ -1147,6 +1377,7 @@ e_markdown_editor_init (EMarkdownEditor *self)
{
self->priv = e_markdown_editor_get_instance_private (self);
+ self->priv->spell_checker = e_spell_checker_new ();
self->priv->mode = E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT;
self->priv->start_bottom = E_THREE_STATE_INCONSISTENT;
self->priv->top_signature = E_THREE_STATE_INCONSISTENT;
@@ -1200,6 +1431,28 @@ e_markdown_editor_get_action_toolbar (EMarkdownEditor *self)
return self->priv->action_toolbar;
}
+/**
+ * e_markdown_editor_set_text:
+ * @self an #EMarkdownEditor
+ * @text: text to set
+ *
+ * Sets the @text as the editor content.
+ *
+ * Since: 3.44
+ **/
+void
+e_markdown_editor_set_text (EMarkdownEditor *self,
+ const gchar *text)
+{
+ GtkTextBuffer *buffer;
+
+ g_return_if_fail (E_IS_MARKDOWN_EDITOR (self));
+ g_return_if_fail (text != NULL);
+
+ buffer = gtk_text_view_get_buffer (self->priv->text_view);
+ gtk_text_buffer_set_text (buffer, text, -1);
+}
+
/**
* e_markdown_editor_dup_text:
* @self: an #EMarkdownEditor
@@ -1302,3 +1555,22 @@ e_markdown_util_text_to_html (const gchar *plain_text,
return NULL;
#endif
}
+
+/**
+ * e_markdown_util_html_to_text:
+ * @html: a text in HTML
+ * @length: length of the @html, or -1 when it's nul-terminated
+ *
+ * Convert @html into the markdown text.
+ *
+ * Returns: (transfer full) (nullable): HTML converted into markdown.
+ * Free the string with g_free(), when no longer needed.
+ *
+ * Since: 3.44
+ **/
+gchar *
+e_markdown_util_html_to_text (const gchar *html,
+ gssize length)
+{
+ return NULL;
+}
diff --git a/src/e-util/e-markdown-editor.h b/src/e-util/e-markdown-editor.h
index 0cacea1493..a24e5f67eb 100644
--- a/src/e-util/e-markdown-editor.h
+++ b/src/e-util/e-markdown-editor.h
@@ -51,11 +51,15 @@ GType e_markdown_editor_get_type (void) G_GNUC_CONST;
GtkWidget * e_markdown_editor_new (void);
GtkTextView * e_markdown_editor_get_text_view (EMarkdownEditor *self);
GtkToolbar * e_markdown_editor_get_action_toolbar (EMarkdownEditor *self);
+void e_markdown_editor_set_text (EMarkdownEditor *self,
+ const gchar *text);
gchar * e_markdown_editor_dup_text (EMarkdownEditor *self);
gchar * e_markdown_editor_dup_html (EMarkdownEditor *self);
gchar * e_markdown_util_text_to_html (const gchar *plain_text,
gssize length);
+gchar * e_markdown_util_html_to_text (const gchar *html,
+ gssize length);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]