diff options
Diffstat (limited to 'gtk/gtktextbufferrichtext.c')
-rw-r--r-- | gtk/gtktextbufferrichtext.c | 830 |
1 files changed, 0 insertions, 830 deletions
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; -} |