3 * Copyright (C) 2006 Imendio AB
4 * Contact: Michael Natterer <mitch@imendio.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
26 #include "gtktextbufferrichtext.h"
27 #include "gtktextbufferserialize.h"
34 gboolean can_create_tags;
38 GDestroyNotify user_data_destroy;
42 static GList * register_format (GList *formats,
43 const gchar *mime_type,
46 GDestroyNotify user_data_destroy,
48 static GList * unregister_format (GList *formats,
50 static GdkAtom * get_formats (GList *formats,
52 static void free_format (GtkRichTextFormat *format);
53 static void free_format_list (GList *formats);
54 static GQuark serialize_quark (void);
55 static GQuark deserialize_quark (void);
59 * gtk_text_buffer_register_serialize_format:
60 * @buffer: a #GtkTextBuffer
61 * @mime_type: the format's mime-type
62 * @function: the serialize function to register
63 * @user_data: %function's user_data
64 * @user_data_destroy: a function to call when @user_data is no longer needed
66 * This function registers a rich text serialization @function along with
67 * its @mime_type with the passed @buffer.
69 * Return value: (transfer none): the #GdkAtom that corresponds to the
70 * newly registered format's mime-type.
75 gtk_text_buffer_register_serialize_format (GtkTextBuffer *buffer,
76 const gchar *mime_type,
77 GtkTextBufferSerializeFunc function,
79 GDestroyNotify user_data_destroy)
84 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), GDK_NONE);
85 g_return_val_if_fail (mime_type != NULL && *mime_type != '\0', GDK_NONE);
86 g_return_val_if_fail (function != NULL, GDK_NONE);
88 formats = g_object_steal_qdata (G_OBJECT (buffer), serialize_quark ());
90 formats = register_format (formats, mime_type,
92 user_data, user_data_destroy,
95 g_object_set_qdata_full (G_OBJECT (buffer), serialize_quark (),
96 formats, (GDestroyNotify) free_format_list);
98 g_object_notify (G_OBJECT (buffer), "copy-target-list");
104 * gtk_text_buffer_register_serialize_tagset:
105 * @buffer: a #GtkTextBuffer
106 * @tagset_name: (allow-none): an optional tagset name, on %NULL
108 * This function registers GTK+'s internal rich text serialization
109 * format with the passed @buffer. The internal format does not comply
110 * to any standard rich text format and only works between #GtkTextBuffer
111 * instances. It is capable of serializing all of a text buffer's tags
112 * and embedded pixbufs.
114 * This function is just a wrapper around
115 * gtk_text_buffer_register_serialize_format(). The mime type used
116 * for registering is "application/x-gtk-text-buffer-rich-text", or
117 * "application/x-gtk-text-buffer-rich-text;format=@tagset_name" if a
118 * @tagset_name was passed.
120 * The @tagset_name can be used to restrict the transfer of rich text
121 * to buffers with compatible sets of tags, in order to avoid unknown
122 * tags from being pasted. It is probably the common case to pass an
123 * identifier != %NULL here, since the %NULL tagset requires the
124 * receiving buffer to deal with with pasting of arbitrary tags.
126 * Return value: (transfer none): the #GdkAtom that corresponds to the
127 * newly registered format's mime-type.
132 gtk_text_buffer_register_serialize_tagset (GtkTextBuffer *buffer,
133 const gchar *tagset_name)
135 gchar *mime_type = "application/x-gtk-text-buffer-rich-text";
138 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), GDK_NONE);
139 g_return_val_if_fail (tagset_name == NULL || *tagset_name != '\0', GDK_NONE);
143 g_strdup_printf ("application/x-gtk-text-buffer-rich-text;format=%s",
146 format = gtk_text_buffer_register_serialize_format (buffer, mime_type,
147 _gtk_text_buffer_serialize_rich_text,
157 * gtk_text_buffer_register_deserialize_format:
158 * @buffer: a #GtkTextBuffer
159 * @mime_type: the format's mime-type
160 * @function: the deserialize function to register
161 * @user_data: @function's user_data
162 * @user_data_destroy: a function to call when @user_data is no longer needed
164 * This function registers a rich text deserialization @function along with
165 * its @mime_type with the passed @buffer.
167 * Return value: (transfer none): the #GdkAtom that corresponds to the
168 * newly registered format's mime-type.
173 gtk_text_buffer_register_deserialize_format (GtkTextBuffer *buffer,
174 const gchar *mime_type,
175 GtkTextBufferDeserializeFunc function,
177 GDestroyNotify user_data_destroy)
182 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), GDK_NONE);
183 g_return_val_if_fail (mime_type != NULL && *mime_type != '\0', GDK_NONE);
184 g_return_val_if_fail (function != NULL, GDK_NONE);
186 formats = g_object_steal_qdata (G_OBJECT (buffer), deserialize_quark ());
188 formats = register_format (formats, mime_type,
190 user_data, user_data_destroy,
193 g_object_set_qdata_full (G_OBJECT (buffer), deserialize_quark (),
194 formats, (GDestroyNotify) free_format_list);
196 g_object_notify (G_OBJECT (buffer), "paste-target-list");
202 * gtk_text_buffer_register_deserialize_tagset:
203 * @buffer: a #GtkTextBuffer
204 * @tagset_name: (allow-none): an optional tagset name, on %NULL
206 * This function registers GTK+'s internal rich text serialization
207 * format with the passed @buffer. See
208 * gtk_text_buffer_register_serialize_tagset() for details.
210 * Return value: (transfer none): the #GdkAtom that corresponds to the
211 * newly registered format's mime-type.
216 gtk_text_buffer_register_deserialize_tagset (GtkTextBuffer *buffer,
217 const gchar *tagset_name)
219 gchar *mime_type = "application/x-gtk-text-buffer-rich-text";
222 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), GDK_NONE);
223 g_return_val_if_fail (tagset_name == NULL || *tagset_name != '\0', GDK_NONE);
227 g_strdup_printf ("application/x-gtk-text-buffer-rich-text;format=%s",
230 format = gtk_text_buffer_register_deserialize_format (buffer, mime_type,
231 _gtk_text_buffer_deserialize_rich_text,
241 * gtk_text_buffer_unregister_serialize_format:
242 * @buffer: a #GtkTextBuffer
243 * @format: a #GdkAtom representing a registered rich text format.
245 * This function unregisters a rich text format that was previously
246 * registered using gtk_text_buffer_register_serialize_format() or
247 * gtk_text_buffer_register_serialize_tagset()
252 gtk_text_buffer_unregister_serialize_format (GtkTextBuffer *buffer,
257 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
258 g_return_if_fail (format != GDK_NONE);
260 formats = g_object_steal_qdata (G_OBJECT (buffer), serialize_quark ());
262 formats = unregister_format (formats, format);
264 g_object_set_qdata_full (G_OBJECT (buffer), serialize_quark (),
265 formats, (GDestroyNotify) free_format_list);
267 g_object_notify (G_OBJECT (buffer), "copy-target-list");
271 * gtk_text_buffer_unregister_deserialize_format:
272 * @buffer: a #GtkTextBuffer
273 * @format: a #GdkAtom representing a registered rich text format.
275 * This function unregisters a rich text format that was previously
276 * registered using gtk_text_buffer_register_deserialize_format() or
277 * gtk_text_buffer_register_deserialize_tagset().
282 gtk_text_buffer_unregister_deserialize_format (GtkTextBuffer *buffer,
287 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
288 g_return_if_fail (format != GDK_NONE);
290 formats = g_object_steal_qdata (G_OBJECT (buffer), deserialize_quark ());
292 formats = unregister_format (formats, format);
294 g_object_set_qdata_full (G_OBJECT (buffer), deserialize_quark (),
295 formats, (GDestroyNotify) free_format_list);
297 g_object_notify (G_OBJECT (buffer), "paste-target-list");
301 * gtk_text_buffer_deserialize_set_can_create_tags:
302 * @buffer: a #GtkTextBuffer
303 * @format: a #GdkAtom representing a registered rich text format
304 * @can_create_tags: whether deserializing this format may create tags
306 * Use this function to allow a rich text deserialization function to
307 * create new tags in the receiving buffer. Note that using this
308 * function is almost always a bad idea, because the rich text
309 * functions you register should know how to map the rich text format
310 * they handler to your text buffers set of tags.
312 * The ability of creating new (arbitrary!) tags in the receiving buffer
313 * is meant for special rich text formats like the internal one that
314 * is registered using gtk_text_buffer_register_deserialize_tagset(),
315 * because that format is essentially a dump of the internal structure
316 * of the source buffer, including its tag names.
318 * You should allow creation of tags only if you know what you are
319 * doing, e.g. if you defined a tagset name for your application
320 * suite's text buffers and you know that it's fine to receive new
321 * tags from these buffers, because you know that your application can
322 * handle the newly created tags.
327 gtk_text_buffer_deserialize_set_can_create_tags (GtkTextBuffer *buffer,
329 gboolean can_create_tags)
335 g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
336 g_return_if_fail (format != GDK_NONE);
338 formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
340 for (list = formats; list; list = g_list_next (list))
342 GtkRichTextFormat *fmt = list->data;
344 if (fmt->atom == format)
346 fmt->can_create_tags = can_create_tags ? TRUE : FALSE;
351 format_name = gdk_atom_name (format);
352 g_warning ("%s: \"%s\" is not registered as deserializable format "
353 "with text buffer %p",
354 G_STRFUNC, format_name ? format_name : "not a GdkAtom", buffer);
355 g_free (format_name);
359 * gtk_text_buffer_deserialize_get_can_create_tags:
360 * @buffer: a #GtkTextBuffer
361 * @format: a #GdkAtom representing a registered rich text format
363 * This functions returns the value set with
364 * gtk_text_buffer_deserialize_set_can_create_tags()
366 * Return value: whether deserializing this format may create tags
371 gtk_text_buffer_deserialize_get_can_create_tags (GtkTextBuffer *buffer,
378 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
379 g_return_val_if_fail (format != GDK_NONE, FALSE);
381 formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
383 for (list = formats; list; list = g_list_next (list))
385 GtkRichTextFormat *fmt = list->data;
387 if (fmt->atom == format)
389 return fmt->can_create_tags;
393 format_name = gdk_atom_name (format);
394 g_warning ("%s: \"%s\" is not registered as deserializable format "
395 "with text buffer %p",
396 G_STRFUNC, format_name ? format_name : "not a GdkAtom", buffer);
397 g_free (format_name);
403 * gtk_text_buffer_get_serialize_formats:
404 * @buffer: a #GtkTextBuffer
405 * @n_formats: return location for the number of formats
407 * This function returns the rich text serialize formats registered
408 * with @buffer using gtk_text_buffer_register_serialize_format() or
409 * gtk_text_buffer_register_serialize_tagset()
411 * Return value: (array length=n_formats) (transfer container): an array of
412 * #GdkAtom<!-- -->s representing the registered formats.
417 gtk_text_buffer_get_serialize_formats (GtkTextBuffer *buffer,
422 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
423 g_return_val_if_fail (n_formats != NULL, NULL);
425 formats = g_object_get_qdata (G_OBJECT (buffer), serialize_quark ());
427 return get_formats (formats, n_formats);
431 * gtk_text_buffer_get_deserialize_formats:
432 * @buffer: a #GtkTextBuffer
433 * @n_formats: return location for the number of formats
435 * This function returns the rich text deserialize formats registered
436 * with @buffer using gtk_text_buffer_register_deserialize_format() or
437 * gtk_text_buffer_register_deserialize_tagset()
439 * Return value: (array length=n_formats) (transfer container): an array of
440 * #GdkAtom<!-- -->s representing the registered formats.
445 gtk_text_buffer_get_deserialize_formats (GtkTextBuffer *buffer,
450 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
451 g_return_val_if_fail (n_formats != NULL, NULL);
453 formats = g_object_get_qdata (G_OBJECT (buffer), deserialize_quark ());
455 return get_formats (formats, n_formats);
459 * gtk_text_buffer_serialize:
460 * @register_buffer: the #GtkTextBuffer @format is registered with
461 * @content_buffer: the #GtkTextBuffer to serialize
462 * @format: the rich text format to use for serializing
463 * @start: start of block of text to serialize
464 * @end: end of block of test to serialize
465 * @length: return location for the length of the serialized data
467 * This function serializes the portion of text between @start
468 * and @end in the rich text format represented by @format.
470 * @format<!-- -->s to be used must be registered using
471 * gtk_text_buffer_register_serialize_format() or
472 * gtk_text_buffer_register_serialize_tagset() beforehand.
474 * Return value: (array length=length) (transfer full): the serialized
475 * data, encoded as @format
480 gtk_text_buffer_serialize (GtkTextBuffer *register_buffer,
481 GtkTextBuffer *content_buffer,
483 const GtkTextIter *start,
484 const GtkTextIter *end,
490 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (register_buffer), NULL);
491 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (content_buffer), NULL);
492 g_return_val_if_fail (format != GDK_NONE, NULL);
493 g_return_val_if_fail (start != NULL, NULL);
494 g_return_val_if_fail (end != NULL, NULL);
495 g_return_val_if_fail (length != NULL, NULL);
499 formats = g_object_get_qdata (G_OBJECT (register_buffer),
502 for (list = formats; list; list = g_list_next (list))
504 GtkRichTextFormat *fmt = list->data;
506 if (fmt->atom == format)
508 GtkTextBufferSerializeFunc function = fmt->function;
510 return function (register_buffer, content_buffer,
511 start, end, length, fmt->user_data);
519 * gtk_text_buffer_deserialize:
520 * @register_buffer: the #GtkTextBuffer @format is registered with
521 * @content_buffer: the #GtkTextBuffer to deserialize into
522 * @format: the rich text format to use for deserializing
523 * @iter: insertion point for the deserialized text
524 * @data: (array length=length): data to deserialize
525 * @length: length of @data
526 * @error: return location for a #GError
528 * This function deserializes rich text in format @format and inserts
531 * @format<!-- -->s to be used must be registered using
532 * gtk_text_buffer_register_deserialize_format() or
533 * gtk_text_buffer_register_deserialize_tagset() beforehand.
535 * Return value: %TRUE on success, %FALSE otherwise.
540 gtk_text_buffer_deserialize (GtkTextBuffer *register_buffer,
541 GtkTextBuffer *content_buffer,
551 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (register_buffer), FALSE);
552 g_return_val_if_fail (GTK_IS_TEXT_BUFFER (content_buffer), FALSE);
553 g_return_val_if_fail (format != GDK_NONE, FALSE);
554 g_return_val_if_fail (iter != NULL, FALSE);
555 g_return_val_if_fail (data != NULL, FALSE);
556 g_return_val_if_fail (length > 0, FALSE);
557 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
559 formats = g_object_get_qdata (G_OBJECT (register_buffer),
560 deserialize_quark ());
562 for (list = formats; list; list = g_list_next (list))
564 GtkRichTextFormat *fmt = list->data;
566 if (fmt->atom == format)
568 GtkTextBufferDeserializeFunc function = fmt->function;
572 GtkTextMark *left_end = NULL;
573 GtkTextMark *right_start = NULL;
574 GSList *left_start_list = NULL;
575 GSList *right_end_list = NULL;
577 /* We don't want the tags that are effective at the insertion
578 * point to affect the pasted text, therefore we remove and
579 * remember them, so they can be re-applied left and right of
580 * the inserted text after pasting
582 split_tags = gtk_text_iter_get_tags (iter);
587 GtkTextTag *tag = list->data;
589 list = g_slist_next (list);
591 /* If a tag begins at the insertion point, ignore it
592 * because it doesn't affect the pasted text
594 if (gtk_text_iter_begins_tag (iter, tag))
595 split_tags = g_slist_remove (split_tags, tag);
600 /* Need to remember text marks, because text iters
601 * don't survive pasting
603 left_end = gtk_text_buffer_create_mark (content_buffer,
605 right_start = gtk_text_buffer_create_mark (content_buffer,
608 for (list = split_tags; list; list = g_slist_next (list))
610 GtkTextTag *tag = list->data;
611 GtkTextIter *backward_toggle = gtk_text_iter_copy (iter);
612 GtkTextIter *forward_toggle = gtk_text_iter_copy (iter);
613 GtkTextMark *left_start = NULL;
614 GtkTextMark *right_end = NULL;
616 gtk_text_iter_backward_to_tag_toggle (backward_toggle, tag);
617 left_start = gtk_text_buffer_create_mark (content_buffer,
622 gtk_text_iter_forward_to_tag_toggle (forward_toggle, tag);
623 right_end = gtk_text_buffer_create_mark (content_buffer,
628 left_start_list = g_slist_prepend (left_start_list, left_start);
629 right_end_list = g_slist_prepend (right_end_list, right_end);
631 gtk_text_buffer_remove_tag (content_buffer, tag,
635 gtk_text_iter_free (forward_toggle);
636 gtk_text_iter_free (backward_toggle);
639 left_start_list = g_slist_reverse (left_start_list);
640 right_end_list = g_slist_reverse (right_end_list);
643 success = function (register_buffer, content_buffer,
645 fmt->can_create_tags,
649 if (!success && error != NULL && *error == NULL)
650 g_set_error (error, 0, 0,
651 _("Unknown error when trying to deserialize %s"),
652 gdk_atom_name (format));
661 /* Turn the remembered marks back into iters so they
662 * can by used to re-apply the remembered tags
664 gtk_text_buffer_get_iter_at_mark (content_buffer,
666 gtk_text_buffer_get_iter_at_mark (content_buffer,
667 &right_s, right_start);
669 for (list = split_tags,
670 left_list = left_start_list,
671 right_list = right_end_list;
672 list && left_list && right_list;
673 list = g_slist_next (list),
674 left_list = g_slist_next (left_list),
675 right_list = g_slist_next (right_list))
677 GtkTextTag *tag = list->data;
678 GtkTextMark *left_start = left_list->data;
679 GtkTextMark *right_end = right_list->data;
683 gtk_text_buffer_get_iter_at_mark (content_buffer,
684 &left_s, left_start);
685 gtk_text_buffer_get_iter_at_mark (content_buffer,
686 &right_e, right_end);
688 gtk_text_buffer_apply_tag (content_buffer, tag,
690 gtk_text_buffer_apply_tag (content_buffer, tag,
693 gtk_text_buffer_delete_mark (content_buffer, left_start);
694 gtk_text_buffer_delete_mark (content_buffer, right_end);
697 gtk_text_buffer_delete_mark (content_buffer, left_end);
698 gtk_text_buffer_delete_mark (content_buffer, right_start);
700 g_slist_free (split_tags);
701 g_slist_free (left_start_list);
702 g_slist_free (right_end_list);
709 g_set_error (error, 0, 0,
710 _("No deserialize function found for format %s"),
711 gdk_atom_name (format));
717 /* private functions */
720 register_format (GList *formats,
721 const gchar *mime_type,
724 GDestroyNotify user_data_destroy,
727 GtkRichTextFormat *format;
729 *atom = gdk_atom_intern (mime_type, FALSE);
731 formats = unregister_format (formats, *atom);
733 format = g_new0 (GtkRichTextFormat, 1);
735 format->mime_type = g_strdup (mime_type);
736 format->can_create_tags = FALSE;
737 format->atom = *atom;
738 format->function = function;
739 format->user_data = user_data;
740 format->user_data_destroy = user_data_destroy;
742 return g_list_append (formats, format);
746 unregister_format (GList *formats,
751 for (list = formats; list; list = g_list_next (list))
753 GtkRichTextFormat *format = list->data;
755 if (format->atom == atom)
757 free_format (format);
759 return g_list_delete_link (formats, list);
767 get_formats (GList *formats,
774 *n_formats = g_list_length (formats);
775 array = g_new0 (GdkAtom, *n_formats);
777 for (list = formats, i = 0; list; list = g_list_next (list), i++)
779 GtkRichTextFormat *format = list->data;
781 array[i] = format->atom;
788 free_format (GtkRichTextFormat *format)
790 if (format->user_data_destroy)
791 format->user_data_destroy (format->user_data);
793 g_free (format->mime_type);
798 free_format_list (GList *formats)
800 g_list_foreach (formats, (GFunc) free_format, NULL);
801 g_list_free (formats);
805 serialize_quark (void)
807 static GQuark quark = 0;
810 quark = g_quark_from_static_string ("gtk-text-buffer-serialize-formats");
816 deserialize_quark (void)
818 static GQuark quark = 0;
821 quark = g_quark_from_static_string ("gtk-text-buffer-deserialize-formats");