summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2017-11-27 04:17:36 +0100
committerMatthias Clasen <mclasen@redhat.com>2017-11-29 23:03:33 -0500
commit3d4743ee62673415d3872d215fa472e883f5158f (patch)
treee94af811040dee9b612fb32ca78c9ec0cab92700 /gtk
parent138abdbc475f90b5d731d3a27c12f8649837ad6d (diff)
downloadgtk+-3d4743ee62673415d3872d215fa472e883f5158f.tar.gz
textview: Remove serialization API
It's unused. Plain text is not using that framework, neither is in-process same-display transmission. So it was only useful for sharing text with custom tags across applications, and nobody is doing that.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkclipboard.c185
-rw-r--r--gtk/gtkclipboard.h8
-rw-r--r--gtk/gtkselection.c132
-rw-r--r--gtk/gtkselection.h11
-rw-r--r--gtk/gtktextbuffer.c123
-rw-r--r--gtk/gtktextbufferrichtext.c830
-rw-r--r--gtk/gtktextbufferrichtext.h138
-rw-r--r--gtk/gtktextbufferserialize.c1804
-rw-r--r--gtk/gtktextbufferserialize.h41
-rw-r--r--gtk/gtktextview.c67
-rw-r--r--gtk/meson.build3
12 files changed, 6 insertions, 3337 deletions
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 3af47c8458..9571edf939 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -207,7 +207,6 @@
#include <gtk/gtkstyleprovider.h>
#include <gtk/gtkswitch.h>
#include <gtk/gtktextbuffer.h>
-#include <gtk/gtktextbufferrichtext.h>
#include <gtk/gtktextchild.h>
#include <gtk/gtktextiter.h>
#include <gtk/gtktextmark.h>
diff --git a/gtk/gtkclipboard.c b/gtk/gtkclipboard.c
index 20222259df..8ace68dfef 100644
--- a/gtk/gtkclipboard.c
+++ b/gtk/gtkclipboard.c
@@ -27,7 +27,6 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkselectionprivate.h"
-#include "gtktextbufferrichtext.h"
#include "gtkintl.h"
#include "gdk/gdk-private.h"
@@ -1065,80 +1064,6 @@ gtk_clipboard_request_text (GtkClipboard *clipboard,
info);
}
-static void
-request_rich_text_received_func (GtkClipboard *clipboard,
- GtkSelectionData *selection_data,
- gpointer data)
-{
- RequestRichTextInfo *info = data;
- guint8 *result = NULL;
- gsize length = 0;
-
- result = (guint8 *) gtk_selection_data_get_data (selection_data);
- length = gtk_selection_data_get_length (selection_data);
-
- info->current_atom++;
-
- if ((!result || length < 1) && (info->current_atom < info->n_atoms))
- {
- gtk_clipboard_request_contents (clipboard, info->atoms[info->current_atom],
- request_rich_text_received_func,
- info);
- return;
- }
-
- info->callback (clipboard, gtk_selection_data_get_target (selection_data),
- result, length,
- info->user_data);
- g_free (info->atoms);
- g_free (info);
-}
-
-/**
- * gtk_clipboard_request_rich_text:
- * @clipboard: a #GtkClipboard
- * @buffer: a #GtkTextBuffer
- * @callback: (scope async): a function to call when the text is received,
- * or the retrieval fails. (It will always be called one way or the other.)
- * @user_data: user data to pass to @callback.
- *
- * Requests the contents of the clipboard as rich text. When the rich
- * text is later received, @callback will be called.
- *
- * The @text parameter to @callback will contain the resulting rich
- * text if the request succeeded, or %NULL if it failed. The @length
- * parameter will contain @text’s length. This function can fail for
- * various reasons, in particular if the clipboard was empty or if the
- * contents of the clipboard could not be converted into rich text form.
- *
- * Since: 2.10
- **/
-void
-gtk_clipboard_request_rich_text (GtkClipboard *clipboard,
- GtkTextBuffer *buffer,
- GtkClipboardRichTextReceivedFunc callback,
- gpointer user_data)
-{
- RequestRichTextInfo *info;
-
- g_return_if_fail (clipboard != NULL);
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (callback != NULL);
-
- info = g_new (RequestRichTextInfo, 1);
- info->callback = callback;
- info->atoms = NULL;
- info->n_atoms = 0;
- info->current_atom = 0;
- info->user_data = user_data;
-
- info->atoms = gtk_text_buffer_get_deserialize_formats (buffer, &info->n_atoms);
-
- gtk_clipboard_request_contents (clipboard, info->atoms[info->current_atom],
- request_rich_text_received_func,
- info);
-}
-
static void
request_image_received_func (GtkClipboard *clipboard,
GtkSelectionData *selection_data,
@@ -1455,77 +1380,6 @@ gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
return results.data;
}
-static void
-clipboard_rich_text_received_func (GtkClipboard *clipboard,
- GdkAtom format,
- const guint8 *text,
- gsize length,
- gpointer data)
-{
- WaitResults *results = data;
-
- results->data = g_memdup (text, length);
- results->format = format;
- results->length = length;
- g_main_loop_quit (results->loop);
-}
-
-/**
- * gtk_clipboard_wait_for_rich_text:
- * @clipboard: a #GtkClipboard
- * @buffer: a #GtkTextBuffer
- * @format: (out): return location for the format of the returned data
- * @length: (out): return location for the length of the returned data
- *
- * Requests the contents of the clipboard as rich text. This function
- * waits for the data to be received using the main loop, so events,
- * timeouts, etc, may be dispatched during the wait.
- *
- * Returns: (nullable) (array length=length) (transfer full): a
- * newly-allocated binary block of data which must be
- * freed with g_free(), or %NULL if retrieving the
- * selection data failed. (This could happen for various
- * reasons, in particular if the clipboard was empty or
- * if the contents of the clipboard could not be
- * converted into text form.)
- *
- * Since: 2.10
- **/
-guint8 *
-gtk_clipboard_wait_for_rich_text (GtkClipboard *clipboard,
- GtkTextBuffer *buffer,
- GdkAtom *format,
- gsize *length)
-{
- WaitResults results;
-
- g_return_val_if_fail (clipboard != NULL, NULL);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (format != NULL, NULL);
- g_return_val_if_fail (length != NULL, NULL);
-
- results.data = NULL;
- results.loop = g_main_loop_new (NULL, TRUE);
-
- gtk_clipboard_request_rich_text (clipboard, buffer,
- clipboard_rich_text_received_func,
- &results);
-
- if (g_main_loop_is_running (results.loop))
- {
- gdk_threads_leave ();
- g_main_loop_run (results.loop);
- gdk_threads_enter ();
- }
-
- g_main_loop_unref (results.loop);
-
- *format = results.format;
- *length = results.length;
-
- return results.data;
-}
-
static void
clipboard_image_received_func (GtkClipboard *clipboard,
GdkPixbuf *pixbuf,
@@ -1745,45 +1599,6 @@ gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard)
}
/**
- * gtk_clipboard_wait_is_rich_text_available:
- * @clipboard: a #GtkClipboard
- * @buffer: a #GtkTextBuffer
- *
- * Test to see if there is rich text available to be pasted
- * This is done by requesting the TARGETS atom and checking
- * if it contains any of the supported rich text formats. This function
- * waits for the data to be received using the main loop, so events,
- * timeouts, etc, may be dispatched during the wait.
- *
- * This function is a little faster than calling
- * gtk_clipboard_wait_for_rich_text() since it doesn’t need to retrieve
- * the actual text.
- *
- * Returns: %TRUE is there is rich text available, %FALSE otherwise.
- *
- * Since: 2.10
- **/
-gboolean
-gtk_clipboard_wait_is_rich_text_available (GtkClipboard *clipboard,
- GtkTextBuffer *buffer)
-{
- GtkSelectionData *data;
- gboolean result = FALSE;
-
- g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
-
- data = gtk_clipboard_wait_for_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"));
- if (data)
- {
- result = gtk_selection_data_targets_include_rich_text (data, buffer);
- gtk_selection_data_free (data);
- }
-
- return result;
-}
-
-/**
* gtk_clipboard_wait_is_image_available:
* @clipboard: a #GtkClipboard
*
diff --git a/gtk/gtkclipboard.h b/gtk/gtkclipboard.h
index 0d353a4e3a..d69f41800d 100644
--- a/gtk/gtkclipboard.h
+++ b/gtk/gtkclipboard.h
@@ -229,11 +229,6 @@ void gtk_clipboard_request_text (GtkClipboard *clipboar
GtkClipboardTextReceivedFunc callback,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
-void gtk_clipboard_request_rich_text (GtkClipboard *clipboard,
- GtkTextBuffer *buffer,
- GtkClipboardRichTextReceivedFunc callback,
- gpointer user_data);
-GDK_AVAILABLE_IN_ALL
void gtk_clipboard_request_image (GtkClipboard *clipboard,
GtkClipboardImageReceivedFunc callback,
gpointer user_data);
@@ -270,9 +265,6 @@ cairo_surface_t * gtk_clipboard_wait_for_surface (GtkClipboard *clipboard);
GDK_AVAILABLE_IN_ALL
gboolean gtk_clipboard_wait_is_text_available (GtkClipboard *clipboard);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_clipboard_wait_is_rich_text_available (GtkClipboard *clipboard,
- GtkTextBuffer *buffer);
-GDK_AVAILABLE_IN_ALL
gboolean gtk_clipboard_wait_is_image_available (GtkClipboard *clipboard);
GDK_AVAILABLE_IN_ALL
gboolean gtk_clipboard_wait_is_uris_available (GtkClipboard *clipboard);
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index da5ed4855e..53603c60a1 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -86,7 +86,6 @@
#include "gtkmain.h"
#include "gtkdebug.h"
-#include "gtktextbufferrichtext.h"
#include "gtkintl.h"
#include "gdk-pixbuf/gdk-pixbuf.h"
@@ -287,50 +286,6 @@ gtk_content_formats_add_text_targets (GdkContentFormats *list)
}
/**
- * gtk_content_formats_add_rich_text_targets:
- * @list: a #GdkContentFormats
- * @deserializable: if %TRUE, then deserializable rich text formats
- * will be added, serializable formats otherwise.
- * @buffer: a #GtkTextBuffer.
- *
- * Appends the rich text targets registered with
- * gtk_text_buffer_register_serialize_format() or
- * gtk_text_buffer_register_deserialize_format() to the target list. All
- * targets are added with the same @info.
- *
- * Since: 2.10
- **/
-GdkContentFormats *
-gtk_content_formats_add_rich_text_targets (GdkContentFormats *list,
- gboolean deserializable,
- GtkTextBuffer *buffer)
-{
- GdkContentFormatsBuilder *builder;
- GdkAtom *atoms;
- gint n_atoms;
- gint i;
-
- g_return_val_if_fail (list != NULL, NULL);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
-
- builder = gdk_content_formats_builder_new ();
- gdk_content_formats_builder_add_formats (builder, list);
- gdk_content_formats_unref (list);
-
- if (deserializable)
- atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
- else
- atoms = gtk_text_buffer_get_serialize_formats (buffer, &n_atoms);
-
- for (i = 0; i < n_atoms; i++)
- gdk_content_formats_builder_add_mime_type (builder, atoms[i]);
-
- g_free (atoms);
-
- return gdk_content_formats_builder_free (builder);
-}
-
-/**
* gtk_content_formats_add_image_targets:
* @list: a #GdkContentFormats
* @writable: whether to add only targets for which GTK+ knows
@@ -1783,56 +1738,6 @@ gtk_targets_include_text (GdkAtom *targets,
}
/**
- * gtk_targets_include_rich_text:
- * @targets: (array length=n_targets): an array of #GdkAtoms
- * @n_targets: the length of @targets
- * @buffer: a #GtkTextBuffer
- *
- * Determines if any of the targets in @targets can be used to
- * provide rich text.
- *
- * Returns: %TRUE if @targets include a suitable target for rich text,
- * otherwise %FALSE.
- *
- * Since: 2.10
- **/
-gboolean
-gtk_targets_include_rich_text (GdkAtom *targets,
- gint n_targets,
- GtkTextBuffer *buffer)
-{
- GdkAtom *rich_targets;
- gint n_rich_targets;
- gint i, j;
- gboolean result = FALSE;
-
- g_return_val_if_fail (targets != NULL || n_targets == 0, FALSE);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
-
- init_atoms ();
-
- rich_targets = gtk_text_buffer_get_deserialize_formats (buffer,
- &n_rich_targets);
-
- for (i = 0; i < n_targets; i++)
- {
- for (j = 0; j < n_rich_targets; j++)
- {
- if (targets[i] == rich_targets[j])
- {
- result = TRUE;
- goto done;
- }
- }
- }
-
- done:
- g_free (rich_targets);
-
- return result;
-}
-
-/**
* gtk_selection_data_targets_include_text:
* @selection_data: a #GtkSelectionData object
*
@@ -1864,43 +1769,6 @@ gtk_selection_data_targets_include_text (const GtkSelectionData *selection_data)
}
/**
- * gtk_selection_data_targets_include_rich_text:
- * @selection_data: a #GtkSelectionData object
- * @buffer: a #GtkTextBuffer
- *
- * Given a #GtkSelectionData object holding a list of targets,
- * determines if any of the targets in @targets can be used to
- * provide rich text.
- *
- * Returns: %TRUE if @selection_data holds a list of targets,
- * and a suitable target for rich text is included,
- * otherwise %FALSE.
- *
- * Since: 2.10
- **/
-gboolean
-gtk_selection_data_targets_include_rich_text (const GtkSelectionData *selection_data,
- GtkTextBuffer *buffer)
-{
- GdkAtom *targets;
- gint n_targets;
- gboolean result = FALSE;
-
- g_return_val_if_fail (selection_data != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
-
- init_atoms ();
-
- if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
- {
- result = gtk_targets_include_rich_text (targets, n_targets, buffer);
- g_free (targets);
- }
-
- return result;
-}
-
-/**
* gtk_targets_include_image:
* @targets: (array length=n_targets): an array of #GdkAtoms
* @n_targets: the length of @targets
diff --git a/gtk/gtkselection.h b/gtk/gtkselection.h
index d597871964..3f0d69b7b4 100644
--- a/gtk/gtkselection.h
+++ b/gtk/gtkselection.h
@@ -39,10 +39,6 @@ G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
GdkContentFormats * gtk_content_formats_add_text_targets (GdkContentFormats *list) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_ALL
-GdkContentFormats * gtk_content_formats_add_rich_text_targets (GdkContentFormats *list,
- gboolean deserializable,
- GtkTextBuffer *buffer) G_GNUC_WARN_UNUSED_RESULT;
-GDK_AVAILABLE_IN_ALL
GdkContentFormats * gtk_content_formats_add_image_targets (GdkContentFormats *list,
gboolean writable) G_GNUC_WARN_UNUSED_RESULT;
GDK_AVAILABLE_IN_ALL
@@ -132,9 +128,6 @@ gboolean gtk_selection_data_get_targets (const GtkSelectionData *selec
GDK_AVAILABLE_IN_ALL
gboolean gtk_selection_data_targets_include_text (const GtkSelectionData *selection_data);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_selection_data_targets_include_rich_text (const GtkSelectionData *selection_data,
- GtkTextBuffer *buffer);
-GDK_AVAILABLE_IN_ALL
gboolean gtk_selection_data_targets_include_image (const GtkSelectionData *selection_data,
gboolean writable);
GDK_AVAILABLE_IN_ALL
@@ -143,10 +136,6 @@ GDK_AVAILABLE_IN_ALL
gboolean gtk_targets_include_text (GdkAtom *targets,
gint n_targets);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_targets_include_rich_text (GdkAtom *targets,
- gint n_targets,
- GtkTextBuffer *buffer);
-GDK_AVAILABLE_IN_ALL
gboolean gtk_targets_include_image (GdkAtom *targets,
gint n_targets,
gboolean writable);
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 010219452a..c55b895a5d 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -33,7 +33,6 @@
#include "gtkmarshalers.h"
#include "gtktextbuffer.h"
#include "gtktextbufferprivate.h"
-#include "gtktextbufferrichtext.h"
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
#include "gtktexttagprivate.h"
@@ -644,9 +643,6 @@ gtk_text_buffer_init (GtkTextBuffer *buffer)
buffer->priv = gtk_text_buffer_get_instance_private (buffer);
buffer->priv->clipboard_contents_buffers = NULL;
buffer->priv->tag_table = NULL;
-
- /* allow copying of arbiatray stuff in the internal rich text format */
- gtk_text_buffer_register_serialize_tagset (buffer, NULL);
}
static void
@@ -3222,21 +3218,6 @@ clipboard_get_selection_cb (GtkClipboard *clipboard,
(void*)&buffer,
sizeof (buffer));
}
- else if (gtk_selection_data_targets_include_rich_text (selection_data, buffer))
- {
- guint8 *str;
- gsize len;
-
- str = gtk_text_buffer_serialize (buffer, buffer,
- gtk_selection_data_get_target (selection_data),
- &start, &end, &len);
-
- gtk_selection_data_set (selection_data,
- gtk_selection_data_get_target (selection_data),
- 8, /* bytes */
- str, len);
- g_free (str);
- }
else if (gtk_selection_data_targets_include_text (selection_data))
{
gchar *str;
@@ -3291,28 +3272,6 @@ clipboard_get_contents_cb (GtkClipboard *clipboard,
(void*)&contents,
sizeof (contents));
}
- else if (gtk_selection_data_targets_include_rich_text (selection_data, contents))
- {
- GtkTextBuffer *clipboard_source_buffer;
- GtkTextIter start, end;
- guint8 *str;
- gsize len;
-
- clipboard_source_buffer = g_object_get_data (G_OBJECT (contents),
- "gtk-text-buffer-clipboard-source");
-
- gtk_text_buffer_get_bounds (contents, &start, &end);
-
- str = gtk_text_buffer_serialize (clipboard_source_buffer, contents,
- gtk_selection_data_get_target (selection_data),
- &start, &end, &len);
-
- gtk_selection_data_set (selection_data,
- gtk_selection_data_get_target (selection_data),
- 8, /* bytes */
- str, len);
- g_free (str);
- }
else
{
gchar *str;
@@ -3515,58 +3474,6 @@ restore_iter (const GtkTextIter *iter,
#endif
static void
-clipboard_rich_text_received (GtkClipboard *clipboard,
- GdkAtom format,
- const guint8 *text,
- gsize length,
- gpointer data)
-{
- ClipboardRequest *request_data = data;
- GtkTextIter insert_point;
- gboolean retval = TRUE;
- GError *error = NULL;
-
- if (text != NULL && length > 0)
- {
- if (request_data->interactive)
- gtk_text_buffer_begin_user_action (request_data->buffer);
-
- pre_paste_prep (request_data, &insert_point);
-
- if (!request_data->interactive ||
- gtk_text_iter_can_insert (&insert_point,
- request_data->default_editable))
- {
- retval = gtk_text_buffer_deserialize (request_data->buffer,
- request_data->buffer,
- format,
- &insert_point,
- text, length,
- &error);
- }
-
- if (!retval)
- {
- g_warning ("error pasting: %s\n", error->message);
- g_clear_error (&error);
- }
-
- if (request_data->interactive)
- gtk_text_buffer_end_user_action (request_data->buffer);
-
- emit_paste_done (request_data->buffer, clipboard);
-
- if (retval)
- return;
- }
-
- /* Request the text selection instead */
- gtk_clipboard_request_text (clipboard,
- clipboard_text_received,
- data);
-}
-
-static void
paste_from_buffer (GtkClipboard *clipboard,
ClipboardRequest *request_data,
GtkTextBuffer *src_buffer,
@@ -3646,22 +3553,10 @@ clipboard_clipboard_buffer_received (GtkClipboard *clipboard,
}
else
{
- if (gtk_clipboard_wait_is_rich_text_available (clipboard,
- request_data->buffer))
- {
- /* Request rich text */
- gtk_clipboard_request_rich_text (clipboard,
- request_data->buffer,
- clipboard_rich_text_received,
- data);
- }
- else
- {
- /* Request the text selection instead */
- gtk_clipboard_request_text (clipboard,
- clipboard_text_received,
- data);
- }
+ /* Request the text selection instead */
+ gtk_clipboard_request_text (clipboard,
+ clipboard_text_received,
+ data);
}
}
@@ -4016,10 +3911,6 @@ gtk_text_buffer_get_target_list (GtkTextBuffer *buffer,
else
target_list = gdk_content_formats_new (NULL, 0);
- target_list = gtk_content_formats_add_rich_text_targets (target_list,
- deserializable,
- buffer);
-
target_list = gtk_content_formats_add_text_targets (target_list);
return target_list;
@@ -4224,8 +4115,7 @@ gtk_text_buffer_end_user_action (GtkTextBuffer *buffer)
* This function returns the list of targets this text buffer can
* provide for copying and as DND source. The targets in the list are
* added with @info values from the #GtkTextBufferTargetInfo enum,
- * using gdk_content_formats_add_rich_text_targets() and
- * gdk_content_formats_add_text_targets().
+ * using gdk_content_formats_add_text_targets().
*
* Returns: (transfer none): the #GdkContentFormats
*
@@ -4254,8 +4144,7 @@ gtk_text_buffer_get_copy_target_list (GtkTextBuffer *buffer)
* This function returns the list of targets this text buffer supports
* for pasting and as DND destination. The targets in the list are
* added with @info values from the #GtkTextBufferTargetInfo enum,
- * using gtk_content_formats_add_rich_text_targets() and
- * gtk_content_formats_add_text_targets().
+ * using gtk_content_formats_add_text_targets().
*
* Returns: (transfer none): the #GdkContentFormats
*
diff --git a/gtk/gtktextbufferrichtext.c b/gtk/gtktextbufferrichtext.c
deleted file mode 100644
index 4286d8b846..0000000000
--- a/gtk/gtktextbufferrichtext.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/* gtkrichtext.c
- *
- * Copyright (C) 2006 Imendio AB
- * Contact: Michael Natterer <mitch@imendio.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "gtktextbufferrichtext.h"
-#include "gtktextbufferserialize.h"
-#include "gtkintl.h"
-
-
-typedef struct
-{
- gchar *mime_type;
- gboolean can_create_tags;
- GdkAtom atom;
- gpointer function;
- gpointer user_data;
- GDestroyNotify user_data_destroy;
-} GtkRichTextFormat;
-
-
-static GList * register_format (GList *formats,
- const gchar *mime_type,
- gpointer function,
- gpointer user_data,
- GDestroyNotify user_data_destroy,
- GdkAtom *atom);
-static GList * unregister_format (GList *formats,
- GdkAtom atom);
-static GdkAtom * get_formats (GList *formats,
- gint *n_formats);
-static void free_format (GtkRichTextFormat *format);
-static void free_format_list (GList *formats);
-static GQuark serialize_quark (void);
-static GQuark deserialize_quark (void);
-
-
-/**
- * gtk_text_buffer_register_serialize_format:
- * @buffer: a #GtkTextBuffer
- * @mime_type: the format’s mime-type
- * @function: the serialize function to register
- * @user_data: @function’s user_data
- * @user_data_destroy: a function to call when @user_data is no longer needed
- *
- * This function registers a rich text serialization @function along with
- * its @mime_type with the passed @buffer.
- *
- * Returns: (transfer none): the #GdkAtom that corresponds to the
- * newly registered format’s mime-type.
- *
- * Since: 2.10
- **/
-GdkAtom
-gtk_text_buffer_register_serialize_format (GtkTextBuffer *buffer,
- const gchar *mime_type,
- GtkTextBufferSerializeFunc function,
- gpointer user_data,
- GDestroyNotify user_data_destroy)
-{
- GList *formats;
- GdkAtom atom;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (mime_type != NULL && *mime_type != '\0', NULL);
- g_return_val_if_fail (function != NULL, NULL);
-
- formats = g_object_steal_qdata (G_OBJECT (buffer), serialize_quark ());
-
- formats = register_format (formats, mime_type,
- (gpointer) function,
- user_data, user_data_destroy,
- &atom);
-
- g_object_set_qdata_full (G_OBJECT (buffer), serialize_quark (),
- formats, (GDestroyNotify) free_format_list);
-
- g_object_notify (G_OBJECT (buffer), "copy-target-list");
-
- return atom;
-}
-
-/**
- * gtk_text_buffer_register_serialize_tagset:
- * @buffer: a #GtkTextBuffer
- * @tagset_name: (allow-none): an optional tagset name, on %NULL
- *
- * This function registers GTK+’s internal rich text serialization
- * format with the passed @buffer. The internal format does not comply
- * to any standard rich text format and only works between #GtkTextBuffer
- * instances. It is capable of serializing all of a text buffer’s tags
- * and embedded pixbufs.
- *
- * This function is just a wrapper around
- * gtk_text_buffer_register_serialize_format(). The mime type used
- * for registering is “application/x-gtk-text-buffer-rich-text”, or
- * “application/x-gtk-text-buffer-rich-text;format=@tagset_name” if a
- * @tagset_name was passed.
- *
- * The @tagset_name can be used to restrict the transfer of rich text
- * to buffers with compatible sets of tags, in order to avoid unknown
- * tags from being pasted. It is probably the common case to pass an
- * identifier != %NULL here, since the %NULL tagset requires the
- * receiving buffer to deal with with pasting of arbitrary tags.
- *
- * Returns: (transfer none): the #GdkAtom that corresponds to the
- * newly registered format’s mime-type.
- *
- * Since: 2.10
- **/
-GdkAtom
-gtk_text_buffer_register_serialize_tagset (GtkTextBuffer *buffer,
- const gchar *tagset_name)
-{
- gchar *mime_type;
- GdkAtom format;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (tagset_name == NULL || *tagset_name != '\0', NULL);
-
- if (tagset_name)
- {
- mime_type = g_strconcat ("application/x-gtk-text-buffer-rich-text;format=",
- tagset_name,
- NULL);
- }
- else
- {
- mime_type = g_strdup ("application/x-gtk-text-buffer-rich-text");
- }
-
- format = gtk_text_buffer_register_serialize_format (buffer, mime_type,
- _gtk_text_buffer_serialize_rich_text,
- NULL, NULL);
-
- g_free (mime_type);
-
- return format;
-}
-
-/**
- * gtk_text_buffer_register_deserialize_format:
- * @buffer: a #GtkTextBuffer
- * @mime_type: the format’s mime-type
- * @function: the deserialize function to register
- * @user_data: @function’s user_data
- * @user_data_destroy: a function to call when @user_data is no longer needed
- *
- * This function registers a rich text deserialization @function along with
- * its @mime_type with the passed @buffer.
- *
- * Returns: (transfer none): the #GdkAtom that corresponds to the
- * newly registered format’s mime-type.
- *
- * Since: 2.10
- **/
-GdkAtom
-gtk_text_buffer_register_deserialize_format (GtkTextBuffer *buffer,
- const gchar *mime_type,
- GtkTextBufferDeserializeFunc function,
- gpointer user_data,
- GDestroyNotify user_data_destroy)
-{
- GList *formats;
- GdkAtom atom;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (mime_type != NULL && *mime_type != '\0', NULL);
- g_return_val_if_fail (function != NULL, NULL);
-
- formats = g_object_steal_qdata (G_OBJECT (buffer), deserialize_quark ());
-
- formats = register_format (formats, mime_type,
- (gpointer) function,
- user_data, user_data_destroy,
- &atom);
-
- g_object_set_qdata_full (G_OBJECT (buffer), deserialize_quark (),
- formats, (GDestroyNotify) free_format_list);
-
- g_object_notify (G_OBJECT (buffer), "paste-target-list");
-
- return atom;
-}
-
-/**
- * gtk_text_buffer_register_deserialize_tagset:
- * @buffer: a #GtkTextBuffer
- * @tagset_name: (allow-none): an optional tagset name, on %NULL
- *
- * This function registers GTK+’s internal rich text serialization
- * format with the passed @buffer. See
- * gtk_text_buffer_register_serialize_tagset() for details.
- *
- * Returns: (transfer none): the #GdkAtom that corresponds to the
- * newly registered format’s mime-type.
- *
- * Since: 2.10
- **/
-GdkAtom
-gtk_text_buffer_register_deserialize_tagset (GtkTextBuffer *buffer,
- const gchar *tagset_name)
-{
- gchar *mime_type;
- GdkAtom format;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (tagset_name == NULL || *tagset_name != '\0', NULL);
-
- if (tagset_name)
- {
- mime_type = g_strconcat ("application/x-gtk-text-buffer-rich-text;format=",
- tagset_name,
- NULL);
- }
- else
- {
- mime_type = g_strdup ("application/x-gtk-text-buffer-rich-text");
- }
-
- format = gtk_text_buffer_register_deserialize_format (buffer, mime_type,
- _gtk_text_buffer_deserialize_rich_text,
- NULL, NULL);
-
- g_free (mime_type);
-
- return format;
-}
-
-/**
- * gtk_text_buffer_unregister_serialize_format:
- * @buffer: a #GtkTextBuffer
- * @format: a #GdkAtom representing a registered rich text format.
- *
- * This function unregisters a rich text format that was previously
- * registered using gtk_text_buffer_register_serialize_format() or
- * gtk_text_buffer_register_serialize_tagset()
- *
- * Since: 2.10
- **/
-void
-gtk_text_buffer_unregister_serialize_format (GtkTextBuffer *buffer,
- GdkAtom format)
-{
- GList *formats;
-
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (format != NULL);
-
- formats = g_object_steal_qdata (G_OBJECT (buffer), serialize_quark ());
-
- formats = unregister_format (formats, format);
-
- g_object_set_qdata_full (G_OBJECT (buffer), serialize_quark (),
- formats, (GDestroyNotify) free_format_list);
-
- g_object_notify (G_OBJECT (buffer), "copy-target-list");
-}
-
-/**
- * gtk_text_buffer_unregister_deserialize_format:
- * @buffer: a #GtkTextBuffer
- * @format: a #GdkAtom representing a registered rich text format.
- *
- * This function unregisters a rich text format that was previously
- * registered using gtk_text_buffer_register_deserialize_format() or
- * gtk_text_buffer_register_deserialize_tagset().
- *
- * Since: 2.10
- **/
-void
-gtk_text_buffer_unregister_deserialize_format (GtkTextBuffer *buffer,
- GdkAtom format)
-{
- GList *formats;
-
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (format != NULL);
-
- formats = g_object_steal_qdata (G_OBJECT (buffer), deserialize_quark ());
-
- formats = unregister_format (formats, format);
-
- g_object_set_qdata_full (G_OBJECT (buffer), deserialize_quark (),
- formats, (GDestroyNotify) free_format_list);
-
- g_object_notify (G_OBJECT (buffer), "paste-target-list");
-}
-
-/**
- * gtk_text_buffer_deserialize_set_can_create_tags:
- * @buffer: a #GtkTextBuffer
- * @format: a #GdkAtom representing a registered rich text format
- * @can_create_tags: whether deserializing this format may create tags
- *
- * Use this function to allow a rich text deserialization function to
- * create new tags in the receiving buffer. Note that using this
- * function is almost always a bad idea, because the rich text
- * functions you register should know how to map the rich text format
- * they handler to your text buffers set of tags.
- *
- * The ability of creating new (arbitrary!) tags in the receiving buffer
- * is meant for special rich text formats like the internal one that
- * is registered using gtk_text_buffer_register_deserialize_tagset(),
- * because that format is essentially a dump of the internal structure
- * of the source buffer, including its tag names.
- *
- * You should allow creation of tags only if you know what you are
- * doing, e.g. if you defined a tagset name for your application
- * suite’s text buffers and you know that it’s fine to receive new
- * tags from these buffers, because you know that your application can
- * handle the newly created tags.
- *
- * Since: 2.10
- **/
-void
-gtk_text_buffer_deserialize_set_can_create_tags (GtkTextBuffer *buffer,
- GdkAtom format,
- gboolean can_create_tags)
-{
- GList *formats;
- GList *list;
- gchar *format_name;
-
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (format != NULL);
-
- formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
-
- for (list = formats; list; list = list->next)
- {
- GtkRichTextFormat *fmt = list->data;
-
- if (fmt->atom == format)
- {
- fmt->can_create_tags = can_create_tags ? TRUE : FALSE;
- return;
- }
- }
-
- format_name = gdk_atom_name (format);
- g_warning ("%s: \"%s\" is not registered as deserializable format "
- "with text buffer %p",
- G_STRFUNC, format_name ? format_name : "not a GdkAtom", buffer);
- g_free (format_name);
-}
-
-/**
- * gtk_text_buffer_deserialize_get_can_create_tags:
- * @buffer: a #GtkTextBuffer
- * @format: a #GdkAtom representing a registered rich text format
- *
- * This functions returns the value set with
- * gtk_text_buffer_deserialize_set_can_create_tags()
- *
- * Returns: whether deserializing this format may create tags
- *
- * Since: 2.10
- **/
-gboolean
-gtk_text_buffer_deserialize_get_can_create_tags (GtkTextBuffer *buffer,
- GdkAtom format)
-{
- GList *formats;
- GList *list;
- gchar *format_name;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
- g_return_val_if_fail (format != NULL, FALSE);
-
- formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
-
- for (list = formats; list; list = list->next)
- {
- GtkRichTextFormat *fmt = list->data;
-
- if (fmt->atom == format)
- {
- return fmt->can_create_tags;
- }
- }
-
- format_name = gdk_atom_name (format);
- g_warning ("%s: \"%s\" is not registered as deserializable format "
- "with text buffer %p",
- G_STRFUNC, format_name ? format_name : "not a GdkAtom", buffer);
- g_free (format_name);
-
- return FALSE;
-}
-
-/**
- * gtk_text_buffer_get_serialize_formats:
- * @buffer: a #GtkTextBuffer
- * @n_formats: (out): return location for the number of formats
- *
- * This function returns the rich text serialize formats registered
- * with @buffer using gtk_text_buffer_register_serialize_format() or
- * gtk_text_buffer_register_serialize_tagset()
- *
- * Returns: (array length=n_formats) (transfer container): an array of
- * #GdkAtoms representing the registered formats.
- *
- * Since: 2.10
- **/
-GdkAtom *
-gtk_text_buffer_get_serialize_formats (GtkTextBuffer *buffer,
- gint *n_formats)
-{
- GList *formats;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (n_formats != NULL, NULL);
-
- formats = g_object_get_qdata (G_OBJECT (buffer), serialize_quark ());
-
- return get_formats (formats, n_formats);
-}
-
-/**
- * gtk_text_buffer_get_deserialize_formats:
- * @buffer: a #GtkTextBuffer
- * @n_formats: (out): return location for the number of formats
- *
- * This function returns the rich text deserialize formats registered
- * with @buffer using gtk_text_buffer_register_deserialize_format() or
- * gtk_text_buffer_register_deserialize_tagset()
- *
- * Returns: (array length=n_formats) (transfer container): an array of
- * #GdkAtoms representing the registered formats.
- *
- * Since: 2.10
- **/
-GdkAtom *
-gtk_text_buffer_get_deserialize_formats (GtkTextBuffer *buffer,
- gint *n_formats)
-{
- GList *formats;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
- g_return_val_if_fail (n_formats != NULL, NULL);
-
- formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
-
- return get_formats (formats, n_formats);
-}
-
-/**
- * gtk_text_buffer_serialize:
- * @register_buffer: the #GtkTextBuffer @format is registered with
- * @content_buffer: the #GtkTextBuffer to serialize
- * @format: the rich text format to use for serializing
- * @start: start of block of text to serialize
- * @end: end of block of test to serialize
- * @length: (out): return location for the length of the serialized data
- *
- * This function serializes the portion of text between @start
- * and @end in the rich text format represented by @format.
- *
- * @formats to be used must be registered using
- * gtk_text_buffer_register_serialize_format() or
- * gtk_text_buffer_register_serialize_tagset() beforehand.
- *
- * Returns: (array length=length) (transfer full): the serialized
- * data, encoded as @format
- *
- * Since: 2.10
- **/
-guint8 *
-gtk_text_buffer_serialize (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GdkAtom format,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gsize *length)
-{
- GList *formats;
- GList *list;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (register_buffer), NULL);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (content_buffer), NULL);
- g_return_val_if_fail (format != NULL, NULL);
- g_return_val_if_fail (start != NULL, NULL);
- g_return_val_if_fail (end != NULL, NULL);
- g_return_val_if_fail (length != NULL, NULL);
-
- *length = 0;
-
- formats = g_object_get_qdata (G_OBJECT (register_buffer),
- serialize_quark ());
-
- for (list = formats; list; list = list->next)
- {
- GtkRichTextFormat *fmt = list->data;
-
- if (fmt->atom == format)
- {
- GtkTextBufferSerializeFunc function = fmt->function;
-
- return function (register_buffer, content_buffer,
- start, end, length, fmt->user_data);
- }
- }
-
- return NULL;
-}
-
-/**
- * gtk_text_buffer_deserialize:
- * @register_buffer: the #GtkTextBuffer @format is registered with
- * @content_buffer: the #GtkTextBuffer to deserialize into
- * @format: the rich text format to use for deserializing
- * @iter: insertion point for the deserialized text
- * @data: (array length=length): data to deserialize
- * @length: length of @data
- * @error: return location for a #GError
- *
- * This function deserializes rich text in format @format and inserts
- * it at @iter.
- *
- * @formats to be used must be registered using
- * gtk_text_buffer_register_deserialize_format() or
- * gtk_text_buffer_register_deserialize_tagset() beforehand.
- *
- * Returns: %TRUE on success, %FALSE otherwise.
- *
- * Since: 2.10
- **/
-gboolean
-gtk_text_buffer_deserialize (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GdkAtom format,
- GtkTextIter *iter,
- const guint8 *data,
- gsize length,
- GError **error)
-{
- GList *formats;
- GList *l;
-
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (register_buffer), FALSE);
- g_return_val_if_fail (GTK_IS_TEXT_BUFFER (content_buffer), FALSE);
- g_return_val_if_fail (format != NULL, FALSE);
- g_return_val_if_fail (iter != NULL, FALSE);
- g_return_val_if_fail (data != NULL, FALSE);
- g_return_val_if_fail (length > 0, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- formats = g_object_get_qdata (G_OBJECT (register_buffer), deserialize_quark ());
-
- for (l = formats; l; l = l->next)
- {
- GtkRichTextFormat *fmt = l->data;
-
- if (fmt->atom == format)
- {
- GtkTextBufferDeserializeFunc function = fmt->function;
- gboolean success;
- GSList *split_tags;
- GSList *list;
- GtkTextMark *left_end = NULL;
- GtkTextMark *right_start = NULL;
- GSList *left_start_list = NULL;
- GSList *right_end_list = NULL;
-
- /* We don't want the tags that are effective at the insertion
- * point to affect the pasted text, therefore we remove and
- * remember them, so they can be re-applied left and right of
- * the inserted text after pasting
- */
- split_tags = gtk_text_iter_get_tags (iter);
-
- list = split_tags;
- while (list)
- {
- GtkTextTag *tag = list->data;
-
- list = list->next;
-
- /* If a tag starts at the insertion point, ignore it
- * because it doesn't affect the pasted text
- */
- if (gtk_text_iter_starts_tag (iter, tag))
- split_tags = g_slist_remove (split_tags, tag);
- }
-
- if (split_tags)
- {
- /* Need to remember text marks, because text iters
- * don't survive pasting
- */
- left_end = gtk_text_buffer_create_mark (content_buffer,
- NULL, iter, TRUE);
- right_start = gtk_text_buffer_create_mark (content_buffer,
- NULL, iter, FALSE);
-
- for (list = split_tags; list; list = list->next)
- {
- GtkTextTag *tag = list->data;
- GtkTextIter *backward_toggle = gtk_text_iter_copy (iter);
- GtkTextIter *forward_toggle = gtk_text_iter_copy (iter);
- GtkTextMark *left_start = NULL;
- GtkTextMark *right_end = NULL;
-
- gtk_text_iter_backward_to_tag_toggle (backward_toggle, tag);
- left_start = gtk_text_buffer_create_mark (content_buffer,
- NULL,
- backward_toggle,
- FALSE);
-
- gtk_text_iter_forward_to_tag_toggle (forward_toggle, tag);
- right_end = gtk_text_buffer_create_mark (content_buffer,
- NULL,
- forward_toggle,
- TRUE);
-
- left_start_list = g_slist_prepend (left_start_list, left_start);
- right_end_list = g_slist_prepend (right_end_list, right_end);
-
- gtk_text_buffer_remove_tag (content_buffer, tag,
- backward_toggle,
- forward_toggle);
-
- gtk_text_iter_free (forward_toggle);
- gtk_text_iter_free (backward_toggle);
- }
-
- left_start_list = g_slist_reverse (left_start_list);
- right_end_list = g_slist_reverse (right_end_list);
- }
-
- success = function (register_buffer, content_buffer,
- iter, data, length,
- fmt->can_create_tags,
- fmt->user_data,
- error);
-
- if (!success && error != NULL && *error == NULL)
- g_set_error (error, 0, 0,
- _("Unknown error when trying to deserialize %s"),
- gdk_atom_name (format));
-
- if (split_tags)
- {
- GSList *left_list;
- GSList *right_list;
- GtkTextIter left_e;
- GtkTextIter right_s;
-
- /* Turn the remembered marks back into iters so they
- * can by used to re-apply the remembered tags
- */
- gtk_text_buffer_get_iter_at_mark (content_buffer,
- &left_e, left_end);
- gtk_text_buffer_get_iter_at_mark (content_buffer,
- &right_s, right_start);
-
- for (list = split_tags,
- left_list = left_start_list,
- right_list = right_end_list;
- list && left_list && right_list;
- list = list->next,
- left_list = left_list->next,
- right_list = right_list->next)
- {
- GtkTextTag *tag = list->data;
- GtkTextMark *left_start = left_list->data;
- GtkTextMark *right_end = right_list->data;
- GtkTextIter left_s;
- GtkTextIter right_e;
-
- gtk_text_buffer_get_iter_at_mark (content_buffer,
- &left_s, left_start);
- gtk_text_buffer_get_iter_at_mark (content_buffer,
- &right_e, right_end);
-
- gtk_text_buffer_apply_tag (content_buffer, tag,
- &left_s, &left_e);
- gtk_text_buffer_apply_tag (content_buffer, tag,
- &right_s, &right_e);
-
- gtk_text_buffer_delete_mark (content_buffer, left_start);
- gtk_text_buffer_delete_mark (content_buffer, right_end);
- }
-
- gtk_text_buffer_delete_mark (content_buffer, left_end);
- gtk_text_buffer_delete_mark (content_buffer, right_start);
-
- g_slist_free (split_tags);
- g_slist_free (left_start_list);
- g_slist_free (right_end_list);
- }
-
- return success;
- }
- }
-
- g_set_error (error, 0, 0,
- _("No deserialize function found for format %s"),
- gdk_atom_name (format));
-
- return FALSE;
-}
-
-
-/* private functions */
-
-static GList *
-register_format (GList *formats,
- const gchar *mime_type,
- gpointer function,
- gpointer user_data,
- GDestroyNotify user_data_destroy,
- GdkAtom *atom)
-{
- GtkRichTextFormat *format;
-
- *atom = gdk_atom_intern (mime_type, FALSE);
-
- formats = unregister_format (formats, *atom);
-
- format = g_slice_new0 (GtkRichTextFormat);
-
- format->mime_type = g_strdup (mime_type);
- format->can_create_tags = FALSE;
- format->atom = *atom;
- format->function = function;
- format->user_data = user_data;
- format->user_data_destroy = user_data_destroy;
-
- return g_list_append (formats, format);
-}
-
-static GList *
-unregister_format (GList *formats,
- GdkAtom atom)
-{
- GList *list;
-
- for (list = formats; list; list = list->next)
- {
- GtkRichTextFormat *format = list->data;
-
- if (format->atom == atom)
- {
- free_format (format);
-
- return g_list_delete_link (formats, list);
- }
- }
-
- return formats;
-}
-
-static GdkAtom *
-get_formats (GList *formats,
- gint *n_formats)
-{
- GdkAtom *array;
- GList *list;
- gint i;
-
- *n_formats = g_list_length (formats);
- array = g_new0 (GdkAtom, *n_formats);
-
- for (list = formats, i = 0; list; list = list->next, i++)
- {
- GtkRichTextFormat *format = list->data;
-
- array[i] = format->atom;
- }
-
- return array;
-}
-
-static void
-free_format (GtkRichTextFormat *format)
-{
- if (format->user_data_destroy)
- format->user_data_destroy (format->user_data);
-
- g_free (format->mime_type);
- g_slice_free (GtkRichTextFormat, format);
-}
-
-static void
-free_format_list (GList *formats)
-{
- g_list_free_full (formats, (GDestroyNotify) free_format);
-}
-
-static GQuark
-serialize_quark (void)
-{
- static GQuark quark = 0;
-
- if (! quark)
- quark = g_quark_from_static_string ("gtk-text-buffer-serialize-formats");
-
- return quark;
-}
-
-static GQuark
-deserialize_quark (void)
-{
- static GQuark quark = 0;
-
- if (! quark)
- quark = g_quark_from_static_string ("gtk-text-buffer-deserialize-formats");
-
- return quark;
-}
diff --git a/gtk/gtktextbufferrichtext.h b/gtk/gtktextbufferrichtext.h
deleted file mode 100644
index ecc11001b7..0000000000
--- a/gtk/gtktextbufferrichtext.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* gtkrichtext.h
- *
- * Copyright (C) 2006 Imendio AB
- * Contact: Michael Natterer <mitch@imendio.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_TEXT_BUFFER_RICH_TEXT_H__
-#define __GTK_TEXT_BUFFER_RICH_TEXT_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktextbuffer.h>
-
-G_BEGIN_DECLS
-
-/**
- * GtkTextBufferSerializeFunc:
- * @register_buffer: the #GtkTextBuffer for which the format is registered
- * @content_buffer: the #GtkTextBuffer to serialize
- * @start: start of the block of text to serialize
- * @end: end of the block of text to serialize
- * @length: Return location for the length of the serialized data
- * @user_data: user data that was specified when registering the format
- *
- * A function that is called to serialize the content of a text buffer.
- * It must return the serialized form of the content.
- *
- * Returns: (nullable): a newly-allocated array of guint8 which contains
- * the serialized data, or %NULL if an error occurred
- */
-typedef guint8 * (* GtkTextBufferSerializeFunc) (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gsize *length,
- gpointer user_data);
-
-/**
- * GtkTextBufferDeserializeFunc:
- * @register_buffer: the #GtkTextBuffer the format is registered with
- * @content_buffer: the #GtkTextBuffer to deserialize into
- * @iter: insertion point for the deserialized text
- * @data: (array length=length): data to deserialize
- * @length: length of @data
- * @create_tags: %TRUE if deserializing may create tags
- * @user_data: user data that was specified when registering the format
- * @error: return location for a #GError
- *
- * A function that is called to deserialize rich text that has been
- * serialized with gtk_text_buffer_serialize(), and insert it at @iter.
- *
- * Returns: %TRUE on success, %FALSE otherwise
- */
-typedef gboolean (* GtkTextBufferDeserializeFunc) (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GtkTextIter *iter,
- const guint8 *data,
- gsize length,
- gboolean create_tags,
- gpointer user_data,
- GError **error);
-
-GDK_AVAILABLE_IN_ALL
-GdkAtom gtk_text_buffer_register_serialize_format (GtkTextBuffer *buffer,
- const gchar *mime_type,
- GtkTextBufferSerializeFunc function,
- gpointer user_data,
- GDestroyNotify user_data_destroy);
-GDK_AVAILABLE_IN_ALL
-GdkAtom gtk_text_buffer_register_serialize_tagset (GtkTextBuffer *buffer,
- const gchar *tagset_name);
-
-GDK_AVAILABLE_IN_ALL
-GdkAtom gtk_text_buffer_register_deserialize_format (GtkTextBuffer *buffer,
- const gchar *mime_type,
- GtkTextBufferDeserializeFunc function,
- gpointer user_data,
- GDestroyNotify user_data_destroy);
-GDK_AVAILABLE_IN_ALL
-GdkAtom gtk_text_buffer_register_deserialize_tagset (GtkTextBuffer *buffer,
- const gchar *tagset_name);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_unregister_serialize_format (GtkTextBuffer *buffer,
- GdkAtom format);
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_unregister_deserialize_format (GtkTextBuffer *buffer,
- GdkAtom format);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_deserialize_set_can_create_tags (GtkTextBuffer *buffer,
- GdkAtom format,
- gboolean can_create_tags);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_text_buffer_deserialize_get_can_create_tags (GtkTextBuffer *buffer,
- GdkAtom format);
-
-GDK_AVAILABLE_IN_ALL
-GdkAtom * gtk_text_buffer_get_serialize_formats (GtkTextBuffer *buffer,
- gint *n_formats);
-GDK_AVAILABLE_IN_ALL
-GdkAtom * gtk_text_buffer_get_deserialize_formats (GtkTextBuffer *buffer,
- gint *n_formats);
-
-GDK_AVAILABLE_IN_ALL
-guint8 * gtk_text_buffer_serialize (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GdkAtom format,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gsize *length);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_text_buffer_deserialize (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GdkAtom format,
- GtkTextIter *iter,
- const guint8 *data,
- gsize length,
- GError **error);
-
-G_END_DECLS
-
-#endif /* __GTK_TEXT_BUFFER_RICH_TEXT_H__ */
diff --git a/gtk/gtktextbufferserialize.c b/gtk/gtktextbufferserialize.c
deleted file mode 100644
index 5df71c6ff2..0000000000
--- a/gtk/gtktextbufferserialize.c
+++ /dev/null
@@ -1,1804 +0,0 @@
-/* gtktextbufferserialize.c
- *
- * Copyright (C) 2001 Havoc Pennington
- * Copyright (C) 2004 Nokia Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* FIXME: We should use other error codes for the
- * parts that deal with the format errors
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "gdk-pixbuf/gdk-pixdata.h"
-#include "gtktextbufferserialize.h"
-#include "gtktexttagprivate.h"
-#include "gtkintl.h"
-
-
-typedef struct
-{
- GString *tag_table_str;
- GString *text_str;
- GHashTable *tags;
- GtkTextIter start, end;
-
- gint n_pixbufs;
- GList *pixbufs;
- gint tag_id;
- GHashTable *tag_id_tags;
-} SerializationContext;
-
-static gchar *
-serialize_value (GValue *value)
-{
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- if (g_value_type_transformable (value->g_type, G_TYPE_STRING))
- {
- GValue text_value = G_VALUE_INIT;
- gchar *tmp;
-
- g_value_init (&text_value, G_TYPE_STRING);
- g_value_transform (value, &text_value);
-
- tmp = g_markup_escape_text (g_value_get_string (&text_value), -1);
- g_value_unset (&text_value);
-
- return tmp;
- }
- else
- {
- g_warning ("Type %s is not serializable", g_type_name (value->g_type));
- }
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- return NULL;
-}
-
-static gboolean
-deserialize_value (const gchar *str,
- GValue *value)
-{
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- if (g_value_type_transformable (G_TYPE_STRING, value->g_type))
- {
- GValue text_value = G_VALUE_INIT;
- gboolean retval;
-
- g_value_init (&text_value, G_TYPE_STRING);
- g_value_set_static_string (&text_value, str);
-
- retval = g_value_transform (&text_value, value);
- g_value_unset (&text_value);
-
- return retval;
- }
- else if (value->g_type == G_TYPE_BOOLEAN)
- {
- gboolean v;
-
- v = strcmp (str, "TRUE") == 0;
-
- g_value_set_boolean (value, v);
-
- return TRUE;
- }
- else if (value->g_type == G_TYPE_INT)
- {
- gchar *tmp;
- int v;
-
- errno = 0;
- v = g_ascii_strtoll (str, &tmp, 10);
-
- if (errno || tmp == NULL || tmp == str)
- return FALSE;
-
- g_value_set_int (value, v);
-
- return TRUE;
- }
- else if (value->g_type == G_TYPE_DOUBLE)
- {
- gchar *tmp;
- gdouble v;
-
- v = g_ascii_strtod (str, &tmp);
-
- if (tmp == NULL || tmp == str)
- return FALSE;
-
- g_value_set_double (value, v);
-
- return TRUE;
- }
- else if (G_VALUE_HOLDS_ENUM (value))
- {
- GEnumClass *class = G_ENUM_CLASS (g_type_class_peek (value->g_type));
- GEnumValue *enum_value;
-
- enum_value = g_enum_get_value_by_name (class, str);
-
- if (enum_value)
- {
- g_value_set_enum (value, enum_value->value);
- return TRUE;
- }
-
- return FALSE;
- }
- else
- {
- g_warning ("Type %s can not be deserialized", g_type_name (value->g_type));
- }
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- return FALSE;
-}
-
-/* Checks if a param is set, or if it's the default value */
-static gboolean
-is_param_set (GObject *object,
- GParamSpec *pspec,
- GValue *value)
-{
- gboolean is_set;
- gchar *is_set_name;
-
- is_set_name = g_strdup_printf ("%s-set", pspec->name);
-
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (object), is_set_name) == NULL)
- {
- g_free (is_set_name);
- return FALSE;
- }
- else
- {
- g_object_get (object, is_set_name, &is_set, NULL);
-
- if (!is_set)
- {
- g_free (is_set_name);
- return FALSE;
- }
-
- g_free (is_set_name);
-
- g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-
- g_object_get_property (object, pspec->name, value);
-
- if (g_param_value_defaults (pspec, value))
- {
- g_value_unset (value);
-
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static void
-serialize_tag (gpointer key,
- gpointer data,
- gpointer user_data)
-{
- SerializationContext *context = user_data;
- GtkTextTag *tag = data;
- gchar *tag_name;
- gint tag_id;
- GParamSpec **pspecs;
- guint n_pspecs;
- int i;
-
- g_string_append (context->tag_table_str, " <tag ");
-
- /* Handle anonymous tags */
- if (tag->priv->name)
- {
- tag_name = g_markup_escape_text (tag->priv->name, -1);
- g_string_append_printf (context->tag_table_str, "name=\"%s\"", tag_name);
- g_free (tag_name);
- }
- else
- {
- tag_id = GPOINTER_TO_INT (g_hash_table_lookup (context->tag_id_tags, tag));
-
- g_string_append_printf (context->tag_table_str, "id=\"%d\"", tag_id);
- }
-
- g_string_append_printf (context->tag_table_str, " priority=\"%d\">\n", tag->priv->priority);
-
- /* Serialize properties */
- pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (tag), &n_pspecs);
-
- for (i = 0; i < n_pspecs; i++)
- {
- GValue value = G_VALUE_INIT;
- gchar *tmp, *tmp2;
-
- if (!(pspecs[i]->flags & G_PARAM_READABLE) ||
- !(pspecs[i]->flags & G_PARAM_WRITABLE))
- continue;
-
- if (!is_param_set (G_OBJECT (tag), pspecs[i], &value))
- continue;
-
- /* Now serialize the attr */
- tmp2 = serialize_value (&value);
-
- if (tmp2)
- {
- tmp = g_markup_escape_text (pspecs[i]->name, -1);
- g_string_append_printf (context->tag_table_str, " <attr name=\"%s\" ", tmp);
- g_free (tmp);
-
- tmp = g_markup_escape_text (g_type_name (pspecs[i]->value_type), -1);
- g_string_append_printf (context->tag_table_str, "type=\"%s\" value=\"%s\" />\n", tmp, tmp2);
-
- g_free (tmp);
- g_free (tmp2);
- }
-
- g_value_unset (&value);
- }
-
- g_free (pspecs);
-
- g_string_append (context->tag_table_str, " </tag>\n");
-}
-
-static void
-serialize_tags (SerializationContext *context)
-{
- g_string_append (context->tag_table_str, " <text_view_markup>\n");
- g_string_append (context->tag_table_str, " <tags>\n");
- g_hash_table_foreach (context->tags, serialize_tag, context);
- g_string_append (context->tag_table_str, " </tags>\n");
-}
-
-static void
-find_list_delta (GSList *old_list,
- GSList *new_list,
- GList **added,
- GList **removed)
-{
- GSList *tmp;
- GList *tmp_added, *tmp_removed;
-
- tmp_added = NULL;
- tmp_removed = NULL;
-
- /* Find added tags */
- tmp = new_list;
- while (tmp)
- {
- if (!g_slist_find (old_list, tmp->data))
- tmp_added = g_list_prepend (tmp_added, tmp->data);
-
- tmp = tmp->next;
- }
-
- *added = tmp_added;
-
- /* Find removed tags */
- tmp = old_list;
- while (tmp)
- {
- if (!g_slist_find (new_list, tmp->data))
- tmp_removed = g_list_prepend (tmp_removed, tmp->data);
-
- tmp = tmp->next;
- }
-
- /* We reverse the list here to match the xml semantics */
- *removed = g_list_reverse (tmp_removed);
-}
-
-static void
-serialize_section_header (GString *str,
- const gchar *name,
- gint length)
-{
- g_return_if_fail (strlen (name) == 26);
-
- g_string_append (str, name);
-
- g_string_append_c (str, length >> 24);
-
- g_string_append_c (str, (length >> 16) & 0xff);
- g_string_append_c (str, (length >> 8) & 0xff);
- g_string_append_c (str, length & 0xff);
-}
-
-static void
-serialize_text (GtkTextBuffer *buffer,
- SerializationContext *context)
-{
- GtkTextIter iter, old_iter;
- GSList *tag_list, *new_tag_list;
- GSList *active_tags;
-
- g_string_append (context->text_str, "<text>");
-
- iter = context->start;
- tag_list = NULL;
- active_tags = NULL;
-
- do
- {
- GList *added, *removed;
- GList *tmp;
- gchar *tmp_text, *escaped_text;
-
- new_tag_list = gtk_text_iter_get_tags (&iter);
- find_list_delta (tag_list, new_tag_list, &added, &removed);
-
- /* Handle removed tags */
- for (tmp = removed; tmp; tmp = tmp->next)
- {
- GtkTextTag *tag = tmp->data;
-
- /* Only close the tag if we didn't close it before (by using
- * the stack logic in the while() loop below)
- */
- if (g_slist_find (active_tags, tag))
- {
- g_string_append (context->text_str, "</apply_tag>");
-
- /* Drop all tags that were opened after this one (which are
- * above this on in the stack)
- */
- while (active_tags->data != tag)
- {
- added = g_list_prepend (added, active_tags->data);
- active_tags = g_slist_remove (active_tags, active_tags->data);
- g_string_append_printf (context->text_str, "</apply_tag>");
- }
-
- active_tags = g_slist_remove (active_tags, active_tags->data);
- }
- }
-
- /* Handle added tags */
- for (tmp = added; tmp; tmp = tmp->next)
- {
- GtkTextTag *tag = tmp->data;
- gchar *tag_name;
-
- /* Add it to the tag hash table */
- g_hash_table_insert (context->tags, tag, tag);
-
- if (tag->priv->name)
- {
- tag_name = g_markup_escape_text (tag->priv->name, -1);
-
- g_string_append_printf (context->text_str, "<apply_tag name=\"%s\">", tag_name);
- g_free (tag_name);
- }
- else
- {
- gpointer tag_id;
-
- /* We've got an anonymous tag, find out if it's been
- used before */
- if (!g_hash_table_lookup_extended (context->tag_id_tags, tag, NULL, &tag_id))
- {
- tag_id = GINT_TO_POINTER (context->tag_id++);
-
- g_hash_table_insert (context->tag_id_tags, tag, tag_id);
- }
-
- g_string_append_printf (context->text_str, "<apply_tag id=\"%d\">", GPOINTER_TO_INT (tag_id));
- }
-
- active_tags = g_slist_prepend (active_tags, tag);
- }
-
- g_slist_free (tag_list);
- tag_list = new_tag_list;
-
- g_list_free (added);
- g_list_free (removed);
-
- old_iter = iter;
-
- /* Now try to go to either the next tag toggle, or if a pixbuf appears */
- while (TRUE)
- {
- gunichar ch = gtk_text_iter_get_char (&iter);
-
- if (ch == 0xFFFC)
- {
- GdkPixbuf *pixbuf = gtk_text_iter_get_pixbuf (&iter);
-
- if (pixbuf)
- {
- /* Append the text before the pixbuf */
- tmp_text = gtk_text_iter_get_slice (&old_iter, &iter);
- escaped_text = g_markup_escape_text (tmp_text, -1);
- g_free (tmp_text);
-
- /* Forward so we don't get the 0xfffc char */
- gtk_text_iter_forward_char (&iter);
- old_iter = iter;
-
- g_string_append (context->text_str, escaped_text);
- g_free (escaped_text);
-
- g_string_append_printf (context->text_str, "<pixbuf index=\"%d\" />", context->n_pixbufs);
-
- context->n_pixbufs++;
- context->pixbufs = g_list_prepend (context->pixbufs, pixbuf);
- }
- }
- else if (ch == 0)
- {
- break;
- }
- else
- gtk_text_iter_forward_char (&iter);
-
- if (gtk_text_iter_toggles_tag (&iter, NULL))
- break;
- }
-
- /* We might have moved too far */
- if (gtk_text_iter_compare (&iter, &context->end) > 0)
- iter = context->end;
-
- /* Append the text */
- tmp_text = gtk_text_iter_get_slice (&old_iter, &iter);
- escaped_text = g_markup_escape_text (tmp_text, -1);
- g_free (tmp_text);
-
- g_string_append (context->text_str, escaped_text);
- g_free (escaped_text);
- }
- while (!gtk_text_iter_equal (&iter, &context->end));
-
- g_slist_free (tag_list);
-
- /* Close any open tags */
- for (tag_list = active_tags; tag_list; tag_list = tag_list->next)
- g_string_append (context->text_str, "</apply_tag>");
-
- g_slist_free (active_tags);
- g_string_append (context->text_str, "</text>\n</text_view_markup>\n");
-}
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-static void
-serialize_pixbufs (SerializationContext *context,
- GString *text)
-{
- GList *list;
-
- for (list = context->pixbufs; list != NULL; list = list->next)
- {
- GdkPixbuf *pixbuf = list->data;
- GdkPixdata pixdata;
- guint8 *tmp;
- guint len;
-
- gdk_pixdata_from_pixbuf (&pixdata, pixbuf, FALSE);
- tmp = gdk_pixdata_serialize (&pixdata, &len);
-
- serialize_section_header (text, "GTKTEXTBUFFERPIXBDATA-0001", len);
- g_string_append_len (text, (gchar *) tmp, len);
- g_free (tmp);
- }
-}
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-guint8 *
-_gtk_text_buffer_serialize_rich_text (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gsize *length,
- gpointer user_data)
-{
- SerializationContext context;
- GString *text;
-
- context.tags = g_hash_table_new (NULL, NULL);
- context.text_str = g_string_new (NULL);
- context.tag_table_str = g_string_new (NULL);
- context.start = *start;
- context.end = *end;
- context.n_pixbufs = 0;
- context.pixbufs = NULL;
- context.tag_id = 0;
- context.tag_id_tags = g_hash_table_new (NULL, NULL);
-
- /* We need to serialize the text before the tag table so we know
- what tags are used */
- serialize_text (content_buffer, &context);
- serialize_tags (&context);
-
- text = g_string_new (NULL);
- serialize_section_header (text, "GTKTEXTBUFFERCONTENTS-0001",
- context.tag_table_str->len + context.text_str->len);
-
- g_string_append_len (text, context.tag_table_str->str, context.tag_table_str->len);
- g_string_append_len (text, context.text_str->str, context.text_str->len);
-
- context.pixbufs = g_list_reverse (context.pixbufs);
- serialize_pixbufs (&context, text);
-
- g_hash_table_destroy (context.tags);
- g_list_free (context.pixbufs);
- g_string_free (context.text_str, TRUE);
- g_string_free (context.tag_table_str, TRUE);
- g_hash_table_destroy (context.tag_id_tags);
-
- *length = text->len;
-
- return (guint8 *) g_string_free (text, FALSE);
-}
-
-typedef enum
-{
- STATE_START,
- STATE_TEXT_VIEW_MARKUP,
- STATE_TAGS,
- STATE_TAG,
- STATE_ATTR,
- STATE_TEXT,
- STATE_APPLY_TAG,
- STATE_PIXBUF
-} ParseState;
-
-typedef struct
-{
- gchar *text;
- GdkPixbuf *pixbuf;
- GSList *tags;
-} TextSpan;
-
-typedef struct
-{
- GtkTextTag *tag;
- gint prio;
-} TextTagPrio;
-
-typedef struct
-{
- GSList *states;
-
- GList *headers;
-
- GtkTextBuffer *buffer;
-
- /* Tags that are defined in <tag> elements */
- GHashTable *defined_tags;
-
- /* Tags that are anonymous */
- GHashTable *anonymous_tags;
-
- /* Tag name substitutions */
- GHashTable *substitutions;
-
- /* Current tag */
- GtkTextTag *current_tag;
-
- /* Priority of current tag */
- gint current_tag_prio;
-
- /* Id of current tag */
- gint current_tag_id;
-
- /* Tags and their priorities */
- GList *tag_priorities;
-
- GSList *tag_stack;
-
- GList *spans;
-
- gboolean create_tags;
-
- gboolean parsed_text;
- gboolean parsed_tags;
-} ParseInfo;
-
-static void
-set_error (GError **err,
- GMarkupParseContext *context,
- int error_domain,
- int error_code,
- const char *format,
- ...) G_GNUC_PRINTF (5, 6);
-
-static void
-set_error (GError **err,
- GMarkupParseContext *context,
- int error_domain,
- int error_code,
- const char *format,
- ...)
-{
- int line, ch;
- va_list args;
- char *str;
-
- g_markup_parse_context_get_position (context, &line, &ch);
-
- va_start (args, format);
- str = g_strdup_vprintf (format, args);
- va_end (args);
-
- g_set_error (err, error_domain, error_code,
- ("Line %d character %d: %s"),
- line, ch, str);
-
- g_free (str);
-}
-
-static void
-push_state (ParseInfo *info,
- ParseState state)
-{
- info->states = g_slist_prepend (info->states, GINT_TO_POINTER (state));
-}
-
-static void
-pop_state (ParseInfo *info)
-{
- g_return_if_fail (info->states != NULL);
-
- info->states = g_slist_remove (info->states, info->states->data);
-}
-
-static ParseState
-peek_state (ParseInfo *info)
-{
- g_return_val_if_fail (info->states != NULL, STATE_START);
-
- return GPOINTER_TO_INT (info->states->data);
-}
-
-#define ELEMENT_IS(name) (strcmp (element_name, (name)) == 0)
-
-
-static gboolean
-check_id_or_name (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gint *id,
- const gchar **name,
- GError **error)
-{
- gboolean has_id = FALSE;
- gboolean has_name = FALSE;
- int i;
-
- *id = 0;
- *name = NULL;
-
- for (i = 0; attribute_names[i] != NULL; i++)
- {
- if (strcmp (attribute_names[i], "name") == 0)
- {
- *name = attribute_values[i];
-
- if (has_id)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Both “id” and “name” were found on the <%s> element"),
- element_name);
- return FALSE;
- }
-
- if (has_name)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("The attribute “%s” was found twice on the <%s> element"),
- "name", element_name);
- return FALSE;
- }
-
- has_name = TRUE;
- }
- else if (strcmp (attribute_names[i], "id") == 0)
- {
- gchar *tmp;
-
- if (has_name)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Both “id” and “name” were found on the <%s> element"),
- element_name);
- return FALSE;
- }
-
- if (has_id)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("The attribute “%s” was found twice on the <%s> element"),
- "id", element_name);
- return FALSE;
- }
-
- has_id = TRUE;
-
- /* Try parsing the integer */
- tmp = NULL;
- errno = 0;
- *id = g_ascii_strtoll (attribute_values[i], &tmp, 10);
-
- if (errno || tmp == attribute_values[i])
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("<%s> element has invalid ID “%s”"), element_name, attribute_values[i]);
- return FALSE;
- }
- }
- }
-
- if (!has_id && !has_name)
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("<%s> element has neither a “name” nor an “id” attribute"), element_name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-typedef struct
-{
- const char *name;
- const char **retloc;
-} LocateAttr;
-
-static gboolean
-locate_attributes (GMarkupParseContext *context,
- const char *element_name,
- const char **attribute_names,
- const char **attribute_values,
- gboolean allow_unknown_attrs,
- GError **error,
- const char *first_attribute_name,
- const char **first_attribute_retloc,
- ...)
-{
- va_list args;
- const char *name;
- const char **retloc;
- int n_attrs;
-#define MAX_ATTRS 24
- LocateAttr attrs[MAX_ATTRS];
- gboolean retval;
- int i;
-
- g_return_val_if_fail (first_attribute_name != NULL, FALSE);
- g_return_val_if_fail (first_attribute_retloc != NULL, FALSE);
-
- retval = TRUE;
-
- n_attrs = 1;
- attrs[0].name = first_attribute_name;
- attrs[0].retloc = first_attribute_retloc;
- *first_attribute_retloc = NULL;
-
- va_start (args, first_attribute_retloc);
-
- name = va_arg (args, const char*);
- retloc = va_arg (args, const char**);
-
- while (name != NULL)
- {
- g_return_val_if_fail (retloc != NULL, FALSE);
-
- g_assert (n_attrs < MAX_ATTRS);
-
- attrs[n_attrs].name = name;
- attrs[n_attrs].retloc = retloc;
- n_attrs += 1;
- *retloc = NULL;
-
- name = va_arg (args, const char*);
- retloc = va_arg (args, const char**);
- }
-
- va_end (args);
-
- if (!retval)
- return retval;
-
- i = 0;
- while (attribute_names[i])
- {
- int j;
- gboolean found;
-
- found = FALSE;
- j = 0;
- while (j < n_attrs)
- {
- if (strcmp (attrs[j].name, attribute_names[i]) == 0)
- {
- retloc = attrs[j].retloc;
-
- if (*retloc != NULL)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Attribute “%s” repeated twice on the same <%s> element"),
- attrs[j].name, element_name);
- retval = FALSE;
- goto out;
- }
-
- *retloc = attribute_values[i];
- found = TRUE;
- }
-
- ++j;
- }
-
- if (!found && !allow_unknown_attrs)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Attribute “%s” is invalid on <%s> element in this context"),
- attribute_names[i], element_name);
- retval = FALSE;
- goto out;
- }
-
- ++i;
- }
-
- out:
- return retval;
-}
-
-static gboolean
-check_no_attributes (GMarkupParseContext *context,
- const char *element_name,
- const char **attribute_names,
- const char **attribute_values,
- GError **error)
-{
- if (attribute_names[0] != NULL)
- {
- set_error (error, context,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Attribute “%s” is invalid on <%s> element in this context"),
- attribute_names[0], element_name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static GtkTextTag *
-tag_exists (GMarkupParseContext *context,
- const gchar *name,
- gint id,
- ParseInfo *info,
- GError **error)
-{
- GtkTextTagTable *tag_table;
- const gchar *real_name;
-
- tag_table = gtk_text_buffer_get_tag_table (info->buffer);
-
- if (info->create_tags)
- {
- /* If we have an anonymous tag, just return it directly */
- if (!name)
- return g_hash_table_lookup (info->anonymous_tags,
- GINT_TO_POINTER (id));
-
- /* First, try the substitutions */
- real_name = g_hash_table_lookup (info->substitutions, name);
-
- if (real_name)
- return gtk_text_tag_table_lookup (tag_table, real_name);
-
- /* Next, try the list of defined tags */
- if (g_hash_table_lookup (info->defined_tags, name) != NULL)
- return gtk_text_tag_table_lookup (tag_table, name);
-
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Tag “%s” has not been defined."), name);
-
- return NULL;
- }
- else
- {
- GtkTextTag *tag;
-
- if (!name)
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Anonymous tag found and tags can not be created."));
- return NULL;
- }
-
- tag = gtk_text_tag_table_lookup (tag_table, name);
-
- if (tag)
- return tag;
-
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Tag “%s” does not exist in buffer and tags can not be created."), name);
-
- return NULL;
- }
-}
-
-typedef struct
-{
- const gchar *id;
- gint length;
- const gchar *start;
-} Header;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-static GdkPixbuf *
-get_pixbuf_from_headers (GList *headers,
- int id,
- GError **error)
-{
- Header *header;
- GdkPixdata pixdata;
- GdkPixbuf *pixbuf;
-
- header = g_list_nth_data (headers, id);
-
- if (!header)
- return NULL;
-
- if (!gdk_pixdata_deserialize (&pixdata, header->length,
- (const guint8 *) header->start, error))
- return NULL;
-
- pixbuf = gdk_pixbuf_from_pixdata (&pixdata, TRUE, error);
-
- return pixbuf;
-}
-G_GNUC_END_IGNORE_DEPRECATIONS
-
-static void
-parse_apply_tag_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const gchar *name, *priority;
- gint id;
- GtkTextTag *tag;
-
- g_assert (peek_state (info) == STATE_TEXT ||
- peek_state (info) == STATE_APPLY_TAG);
-
- if (ELEMENT_IS ("apply_tag"))
- {
- if (!locate_attributes (context, element_name, attribute_names, attribute_values, TRUE, error,
- "priority", &priority, NULL))
- return;
-
- if (!check_id_or_name (context, element_name, attribute_names, attribute_values,
- &id, &name, error))
- return;
-
-
- tag = tag_exists (context, name, id, info, error);
-
- if (!tag)
- return;
-
- info->tag_stack = g_slist_prepend (info->tag_stack, tag);
-
- push_state (info, STATE_APPLY_TAG);
- }
- else if (ELEMENT_IS ("pixbuf"))
- {
- int int_id;
- GdkPixbuf *pixbuf;
- TextSpan *span;
- const gchar *pixbuf_id;
-
- if (!locate_attributes (context, element_name, attribute_names, attribute_values, FALSE, error,
- "index", &pixbuf_id, NULL))
- return;
-
- int_id = atoi (pixbuf_id);
- pixbuf = get_pixbuf_from_headers (info->headers, int_id, error);
-
- span = g_slice_new0 (TextSpan);
- span->pixbuf = pixbuf;
- span->tags = NULL;
-
- info->spans = g_list_prepend (info->spans, span);
-
- if (!pixbuf)
- return;
-
- push_state (info, STATE_PIXBUF);
- }
- else
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <%s>"),
- element_name, peek_state(info) == STATE_TEXT ? "text" : "apply_tag");
-}
-
-static void
-parse_attr_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const gchar *name, *type, *value;
- GType gtype;
- GValue gvalue = G_VALUE_INIT;
- GParamSpec *pspec;
-
- g_assert (peek_state (info) == STATE_TAG);
-
- if (ELEMENT_IS ("attr"))
- {
- if (!locate_attributes (context, element_name, attribute_names, attribute_values, FALSE, error,
- "name", &name, "type", &type, "value", &value, NULL))
- return;
-
- gtype = g_type_from_name (type);
-
- if (gtype == G_TYPE_INVALID)
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("“%s” is not a valid attribute type"), type);
- return;
- }
-
- if (!(pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info->current_tag), name)))
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("“%s” is not a valid attribute name"), name);
- return;
- }
-
- g_value_init (&gvalue, gtype);
-
- if (!deserialize_value (value, &gvalue))
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("“%s” could not be converted to a value of type “%s” for attribute “%s”"),
- value, type, name);
- return;
- }
-
- if (g_param_value_validate (pspec, &gvalue))
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("“%s” is not a valid value for attribute “%s”"),
- value, name);
- g_value_unset (&gvalue);
- return;
- }
-
- g_object_set_property (G_OBJECT (info->current_tag),
- name, &gvalue);
-
- g_value_unset (&gvalue);
-
- push_state (info, STATE_ATTR);
- }
- else
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <%s>"),
- element_name, "tag");
- }
-}
-
-
-static gchar *
-get_tag_name (ParseInfo *info,
- const gchar *tag_name)
-{
- GtkTextTagTable *tag_table;
- gchar *name;
- gint i;
-
- name = g_strdup (tag_name);
-
- if (!info->create_tags)
- return name;
-
- i = 0;
- tag_table = gtk_text_buffer_get_tag_table (info->buffer);
-
- while (gtk_text_tag_table_lookup (tag_table, name) != NULL)
- {
- g_free (name);
- name = g_strdup_printf ("%s-%d", tag_name, ++i);
- }
-
- if (i != 0)
- {
- g_hash_table_insert (info->substitutions, g_strdup (tag_name), g_strdup (name));
- }
-
- return name;
-}
-
-static void
-parse_tag_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- ParseInfo *info,
- GError **error)
-{
- const gchar *name, *priority;
- gchar *tag_name;
- gint id;
- gint prio;
- gchar *tmp;
-
- g_assert (peek_state (info) == STATE_TAGS);
-
- if (ELEMENT_IS ("tag"))
- {
- if (!locate_attributes (context, element_name, attribute_names, attribute_values, TRUE, error,
- "priority", &priority, NULL))
- return;
-
- if (!check_id_or_name (context, element_name, attribute_names, attribute_values,
- &id, &name, error))
- return;
-
- if (name)
- {
- if (g_hash_table_lookup (info->defined_tags, name) != NULL)
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Tag “%s” already defined"), name);
- return;
- }
- }
-
- tmp = NULL;
- errno = 0;
- prio = g_ascii_strtoll (priority, &tmp, 10);
-
- if (errno || tmp == priority)
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Tag “%s” has invalid priority “%s”"), name, priority);
- return;
- }
-
- if (name)
- {
- tag_name = get_tag_name (info, name);
- info->current_tag = gtk_text_tag_new (tag_name);
- g_free (tag_name);
- }
- else
- {
- info->current_tag = gtk_text_tag_new (NULL);
- info->current_tag_id = id;
- }
-
- info->current_tag_prio = prio;
-
- push_state (info, STATE_TAG);
- }
- else
- {
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <%s>"),
- element_name, "tags");
- }
-}
-
-static void
-start_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
-
- switch (peek_state (info))
- {
- case STATE_START:
- if (ELEMENT_IS ("text_view_markup"))
- {
- if (!check_no_attributes (context, element_name,
- attribute_names, attribute_values, error))
- return;
-
- push_state (info, STATE_TEXT_VIEW_MARKUP);
- break;
- }
- else
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Outermost element in text must be <text_view_markup> not <%s>"),
- element_name);
- break;
- case STATE_TEXT_VIEW_MARKUP:
- if (ELEMENT_IS ("tags"))
- {
- if (info->parsed_tags)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("A <%s> element has already been specified"), "tags");
- return;
- }
-
- if (!check_no_attributes (context, element_name,
- attribute_names, attribute_values, error))
- return;
-
- push_state (info, STATE_TAGS);
- break;
- }
- else if (ELEMENT_IS ("text"))
- {
- if (info->parsed_text)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("A <%s> element has already been specified"), "text");
- return;
- }
- else if (!info->parsed_tags)
- {
- set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("A <text> element can’t occur before a <tags> element"));
- return;
- }
-
- if (!check_no_attributes (context, element_name,
- attribute_names, attribute_values, error))
- return;
-
- push_state (info, STATE_TEXT);
- break;
- }
- else
- set_error (error, context,
- G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
- _("Element <%s> is not allowed below <%s>"),
- element_name, "text_view_markup");
- break;
- case STATE_TAGS:
- parse_tag_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_TAG:
- parse_attr_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_TEXT:
- case STATE_APPLY_TAG:
- parse_apply_tag_element (context, element_name,
- attribute_names, attribute_values,
- info, error);
- break;
- case STATE_ATTR:
- case STATE_PIXBUF:
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static gint
-sort_tag_prio (TextTagPrio *a,
- TextTagPrio *b)
-{
- if (a->prio < b->prio)
- return -1;
- else if (a->prio > b->prio)
- return 1;
- else
- return 0;
-}
-
-static void
-end_element_handler (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
- gchar *tmp;
- GList *list;
-
- switch (peek_state (info))
- {
- case STATE_TAGS:
- pop_state (info);
- g_assert (peek_state (info) == STATE_TEXT_VIEW_MARKUP);
-
- info->parsed_tags = TRUE;
-
- /* Sort list and add the tags */
- info->tag_priorities = g_list_sort (info->tag_priorities,
- (GCompareFunc)sort_tag_prio);
- list = info->tag_priorities;
- while (list)
- {
- TextTagPrio *prio = list->data;
-
- if (info->create_tags)
- gtk_text_tag_table_add (gtk_text_buffer_get_tag_table (info->buffer),
- prio->tag);
-
- g_object_unref (prio->tag);
- prio->tag = NULL;
-
- list = list->next;
- }
-
- break;
- case STATE_TAG:
- pop_state (info);
- g_assert (peek_state (info) == STATE_TAGS);
-
- if (info->current_tag->priv->name)
- {
- /* Add tag to defined tags hash */
- tmp = g_strdup (info->current_tag->priv->name);
- g_hash_table_insert (info->defined_tags,
- tmp, tmp);
- }
- else
- {
- g_hash_table_insert (info->anonymous_tags,
- GINT_TO_POINTER (info->current_tag_id),
- info->current_tag);
- }
-
- if (info->create_tags)
- {
- TextTagPrio *prio;
-
- /* add the tag to the list */
- prio = g_slice_new0 (TextTagPrio);
- prio->prio = info->current_tag_prio;
- prio->tag = info->current_tag;
-
- info->tag_priorities = g_list_prepend (info->tag_priorities, prio);
- }
-
- info->current_tag = NULL;
- break;
- case STATE_ATTR:
- pop_state (info);
- g_assert (peek_state (info) == STATE_TAG);
- break;
- case STATE_APPLY_TAG:
- pop_state (info);
- g_assert (peek_state (info) == STATE_APPLY_TAG ||
- peek_state (info) == STATE_TEXT);
-
- /* Pop tag */
- info->tag_stack = g_slist_delete_link (info->tag_stack,
- info->tag_stack);
-
- break;
- case STATE_TEXT:
- pop_state (info);
- g_assert (peek_state (info) == STATE_TEXT_VIEW_MARKUP);
-
- info->spans = g_list_reverse (info->spans);
- info->parsed_text = TRUE;
- break;
- case STATE_TEXT_VIEW_MARKUP:
- pop_state (info);
- g_assert (peek_state (info) == STATE_START);
- break;
- case STATE_PIXBUF:
- pop_state (info);
- g_assert (peek_state (info) == STATE_APPLY_TAG ||
- peek_state (info) == STATE_TEXT);
- break;
- case STATE_START:
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static gboolean
-all_whitespace (const char *text,
- int text_len)
-{
- const char *p;
- const char *end;
-
- p = text;
- end = text + text_len;
-
- while (p != end)
- {
- if (!g_ascii_isspace (*p))
- return FALSE;
-
- p = g_utf8_next_char (p);
- }
-
- return TRUE;
-}
-
-static void
-text_handler (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **error)
-{
- ParseInfo *info = user_data;
- TextSpan *span;
-
- if (all_whitespace (text, text_len) &&
- peek_state (info) != STATE_TEXT &&
- peek_state (info) != STATE_APPLY_TAG)
- return;
-
- if (peek_state (info) == STATE_TEXT ||
- peek_state (info) == STATE_APPLY_TAG)
- {
- if (text_len == 0)
- return;
-
- span = g_slice_new0 (TextSpan);
- span->text = g_strndup (text, text_len);
- span->tags = g_slist_copy (info->tag_stack);
-
- info->spans = g_list_prepend (info->spans, span);
- }
-}
-
-static void
-parse_info_init (ParseInfo *info,
- GtkTextBuffer *buffer,
- gboolean create_tags,
- GList *headers)
-{
- info->states = g_slist_prepend (NULL, GINT_TO_POINTER (STATE_START));
-
- info->create_tags = create_tags;
- info->headers = headers;
- info->defined_tags = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- info->substitutions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- info->anonymous_tags = g_hash_table_new_full (NULL, NULL, NULL, NULL);
- info->tag_stack = NULL;
- info->spans = NULL;
- info->parsed_text = FALSE;
- info->parsed_tags = FALSE;
- info->current_tag = NULL;
- info->current_tag_prio = -1;
- info->tag_priorities = NULL;
-
- info->buffer = buffer;
-}
-
-static void
-text_span_free (TextSpan *span)
-{
- g_free (span->text);
- g_slist_free (span->tags);
- g_slice_free (TextSpan, span);
-}
-
-static void
-parse_info_free (ParseInfo *info)
-{
- GList *list;
-
- g_slist_free (info->tag_stack);
- g_slist_free (info->states);
-
- g_hash_table_destroy (info->substitutions);
- g_hash_table_destroy (info->defined_tags);
-
- if (info->current_tag)
- g_object_unref (info->current_tag);
-
- list = info->spans;
- while (list)
- {
- text_span_free (list->data);
-
- list = list->next;
- }
- g_list_free (info->spans);
-
- list = info->tag_priorities;
- while (list)
- {
- TextTagPrio *prio = list->data;
-
- if (prio->tag)
- g_object_unref (prio->tag);
- g_slice_free (TextTagPrio, prio);
-
- list = list->next;
- }
- g_list_free (info->tag_priorities);
-
-}
-
-static void
-insert_text (ParseInfo *info,
- GtkTextIter *iter)
-{
- GtkTextIter start_iter;
- GtkTextMark *mark;
- GList *tmp;
- GSList *tags;
-
- start_iter = *iter;
-
- mark = gtk_text_buffer_create_mark (info->buffer, "deserialize_insert_point",
- &start_iter, TRUE);
-
- tmp = info->spans;
- while (tmp)
- {
- TextSpan *span = tmp->data;
-
- if (span->text)
- gtk_text_buffer_insert (info->buffer, iter, span->text, -1);
- else
- {
- gtk_text_buffer_insert_pixbuf (info->buffer, iter, span->pixbuf);
- g_object_unref (span->pixbuf);
- }
- gtk_text_buffer_get_iter_at_mark (info->buffer, &start_iter, mark);
-
- /* Apply tags */
- tags = span->tags;
- while (tags)
- {
- GtkTextTag *tag = tags->data;
-
- gtk_text_buffer_apply_tag (info->buffer, tag,
- &start_iter, iter);
-
- tags = tags->next;
- }
-
- gtk_text_buffer_move_mark (info->buffer, mark, iter);
-
- tmp = tmp->next;
- }
-
- gtk_text_buffer_delete_mark (info->buffer, mark);
-}
-
-
-
-static int
-read_int (const guchar *start)
-{
- int result;
-
- result =
- start[0] << 24 |
- start[1] << 16 |
- start[2] << 8 |
- start[3];
-
- return result;
-}
-
-static gboolean
-header_is (Header *header,
- const gchar *id)
-{
- return (strncmp (header->id, id, strlen (id)) == 0);
-}
-
-static GList *
-read_headers (const gchar *start,
- gint len,
- GError **error)
-{
- int i = 0;
- int section_len;
- Header *header;
- GList *headers = NULL;
- GList *l;
-
- while (i < len)
- {
- if (i + 30 >= len)
- goto error;
-
- if (strncmp (start + i, "GTKTEXTBUFFERCONTENTS-0001", 26) == 0 ||
- strncmp (start + i, "GTKTEXTBUFFERPIXBDATA-0001", 26) == 0)
- {
- section_len = read_int ((const guchar *) start + i + 26);
-
- if (i + 30 + section_len > len)
- goto error;
-
- header = g_slice_new0 (Header);
- header->id = start + i;
- header->length = section_len;
- header->start = start + i + 30;
-
- i += 30 + section_len;
-
- headers = g_list_prepend (headers, header);
- }
- else
- break;
- }
-
- return g_list_reverse (headers);
-
- error:
- for (l = headers; l != NULL; l = l->next)
- {
- header = l->data;
- g_slice_free (Header, header);
- }
-
- g_list_free (headers);
-
- g_set_error_literal (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Serialized data is malformed"));
-
- return NULL;
-}
-
-static gboolean
-deserialize_text (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- const gchar *text,
- gint len,
- gboolean create_tags,
- GError **error,
- GList *headers)
-{
- GMarkupParseContext *context;
- ParseInfo info;
- gboolean retval = FALSE;
-
- static const GMarkupParser rich_text_parser = {
- start_element_handler,
- end_element_handler,
- text_handler,
- NULL,
- NULL
- };
-
- parse_info_init (&info, buffer, create_tags, headers);
-
- context = g_markup_parse_context_new (&rich_text_parser,
- 0, &info, NULL);
-
- if (!g_markup_parse_context_parse (context,
- text,
- len,
- error))
- goto out;
-
- if (!g_markup_parse_context_end_parse (context, error))
- goto out;
-
- retval = TRUE;
-
- /* Now insert the text */
- insert_text (&info, iter);
-
- out:
- parse_info_free (&info);
-
- g_markup_parse_context_free (context);
-
- return retval;
-}
-
-gboolean
-_gtk_text_buffer_deserialize_rich_text (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GtkTextIter *iter,
- const guint8 *text,
- gsize length,
- gboolean create_tags,
- gpointer user_data,
- GError **error)
-{
- GList *headers;
- GList *l;
- Header *header;
- gboolean retval;
-
- headers = read_headers ((gchar *) text, length, error);
-
- if (!headers)
- return FALSE;
-
- header = headers->data;
- if (!header_is (header, "GTKTEXTBUFFERCONTENTS-0001"))
- {
- g_set_error_literal (error,
- G_MARKUP_ERROR,
- G_MARKUP_ERROR_PARSE,
- _("Serialized data is malformed. First section isn’t GTKTEXTBUFFERCONTENTS-0001"));
-
- retval = FALSE;
- goto out;
- }
-
- retval = deserialize_text (content_buffer, iter,
- header->start, header->length,
- create_tags, error, headers->next);
-
- out:
- for (l = headers; l != NULL; l = l->next)
- {
- header = l->data;
- g_slice_free (Header, header);
- }
-
- g_list_free (headers);
-
- return retval;
-}
diff --git a/gtk/gtktextbufferserialize.h b/gtk/gtktextbufferserialize.h
deleted file mode 100644
index 4a183b62cf..0000000000
--- a/gtk/gtktextbufferserialize.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* gtktextbufferserialize.h
- *
- * Copyright (C) 2004 Nokia Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_TEXT_BUFFER_SERIALIZE_H__
-#define __GTK_TEXT_BUFFER_SERIALIZE_H__
-
-#include <gtk/gtktextbuffer.h>
-
-guint8 * _gtk_text_buffer_serialize_rich_text (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- const GtkTextIter *start,
- const GtkTextIter *end,
- gsize *length,
- gpointer user_data);
-
-gboolean _gtk_text_buffer_deserialize_rich_text (GtkTextBuffer *register_buffer,
- GtkTextBuffer *content_buffer,
- GtkTextIter *iter,
- const guint8 *data,
- gsize length,
- gboolean create_tags,
- gpointer user_data,
- GError **error);
-
-
-#endif /* __GTK_TEXT_BUFFER_SERIALIZE_H__ */
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index ec423d1e62..d774f390b4 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -42,7 +42,6 @@
#include "gtkseparatormenuitem.h"
#include "gtksettings.h"
#include "gtkselectionprivate.h"
-#include "gtktextbufferrichtext.h"
#include "gtktextdisplayprivate.h"
#include "gtktextiterprivate.h"
#include "gtkimmulticontext.h"
@@ -7882,31 +7881,6 @@ gtk_text_view_drag_data_get (GtkWidget *widget,
(void*)&buffer,
sizeof (buffer));
}
- else if (gtk_selection_data_targets_include_rich_text (selection_data, buffer))
- {
- GtkTextIter start;
- GtkTextIter end;
- guint8 *str = NULL;
- gsize len;
-
- if (gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
- {
- /* Extract the selected text */
- str = gtk_text_buffer_serialize (buffer, buffer,
- gtk_selection_data_get_target (selection_data),
- &start, &end,
- &len);
- }
-
- if (str)
- {
- gtk_selection_data_set (selection_data,
- gtk_selection_data_get_target (selection_data),
- 8, /* bytes */
- (guchar *) str, len);
- g_free (str);
- }
- }
else
{
GtkTextIter start;
@@ -8177,29 +8151,7 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
if (gtk_text_buffer_get_tag_table (src_buffer) !=
gtk_text_buffer_get_tag_table (buffer))
{
- /* try to find a suitable rich text target instead */
- GdkAtom *atoms;
- gint n_atoms;
- GdkContentFormats *dnd_formats, *buffer_formats;
- const char *target = NULL;
-
copy_tags = FALSE;
-
- atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
- buffer_formats = gdk_content_formats_new (atoms, n_atoms);
- dnd_formats = gdk_drag_context_get_formats (context);
-
- gdk_content_formats_match (dnd_formats, buffer_formats, NULL, &target);
-
- gdk_content_formats_unref (buffer_formats);
- g_free (atoms);
-
- if (target != NULL)
- {
- gtk_drag_get_data (widget, context, target, time);
- gtk_text_buffer_end_user_action (buffer);
- return;
- }
}
if (gtk_text_buffer_get_selection_bounds (src_buffer,
@@ -8224,25 +8176,6 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
}
}
}
- else if (gtk_selection_data_get_length (selection_data) > 0 &&
- gtk_selection_data_targets_include_rich_text (selection_data, buffer))
- {
- gboolean retval;
- GError *error = NULL;
-
- retval = gtk_text_buffer_deserialize (buffer, buffer,
- gtk_selection_data_get_target (selection_data),
- &drop_point,
- (guint8 *) gtk_selection_data_get_data (selection_data),
- gtk_selection_data_get_length (selection_data),
- &error);
-
- if (!retval)
- {
- g_warning ("error pasting: %s", error->message);
- g_clear_error (&error);
- }
- }
else
insert_text_data (text_view, &drop_point, selection_data);
diff --git a/gtk/meson.build b/gtk/meson.build
index c961f294b0..090f891541 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -312,8 +312,6 @@ gtk_public_sources = files([
'gtktextattributes.c',
'gtktextbtree.c',
'gtktextbuffer.c',
- 'gtktextbufferrichtext.c',
- 'gtktextbufferserialize.c',
'gtktextchild.c',
'gtktextdisplay.c',
'gtktexthandle.c',
@@ -554,7 +552,6 @@ gtk_public_headers = files([
'gtkswitch.h',
'gtktestutils.h',
'gtktextbuffer.h',
- 'gtktextbufferrichtext.h',
'gtktextchild.h',
'gtktextiter.h',
'gtktextmark.h',