]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktextbufferrichtext.c
Revert "combobox: Don't special-case RTL child positions anymore"
[~andy/gtk] / gtk / gtktextbufferrichtext.c
index 12cb00b3b8b2338391a81fca141cdf4d7e634cb3..2c5d228daede2130bd328ebb33d55ec57f2c7322 100644 (file)
@@ -14,9 +14,7 @@
  * 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
@@ -25,7 +23,6 @@
 
 #include "gtktextbufferrichtext.h"
 #include "gtktextbufferserialize.h"
-#include "gtkalias.h"
 #include "gtkintl.h"
 
 
@@ -62,13 +59,13 @@ static GQuark    deserialize_quark (void);
  * @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
+ * @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.
+ * This function registers a rich text serialization @function along with
+ * its @mime_type with the passed @buffer.
  *
- * Return value: the #GdkAtom that corresponds to the newly registered
- *               format's mime-type.
+ * Return value: (transfer none): the #GdkAtom that corresponds to the
+ *               newly registered format's mime-type.
  *
  * Since: 2.10
  **/
@@ -104,28 +101,28 @@ gtk_text_buffer_register_serialize_format (GtkTextBuffer              *buffer,
 /**
  * gtk_text_buffer_register_serialize_tagset:
  * @buffer: a #GtkTextBuffer
- * @tagset_name: an optional tagset name, on %NULL
+ * @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
+ * 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
+ * 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.
+ * "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
+ * 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.
  *
- * Return value: the #GdkAtom that corresponds to the newly registered
- *               format's mime-type.
+ * Return value: (transfer none): the #GdkAtom that corresponds to the
+ *               newly registered format's mime-type.
  *
  * Since: 2.10
  **/
@@ -159,14 +156,14 @@ gtk_text_buffer_register_serialize_tagset (GtkTextBuffer *buffer,
  * @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
+ * @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.
+ * This function registers a rich text deserialization @function along with
+ * its @mime_type with the passed @buffer.
  *
- * Return value: the #GdkAtom that corresponds to the newly registered
- *               format's mime-type.
+ * Return value: (transfer none): the #GdkAtom that corresponds to the
+ *               newly registered format's mime-type.
  *
  * Since: 2.10
  **/
@@ -202,14 +199,14 @@ gtk_text_buffer_register_deserialize_format (GtkTextBuffer                *buffe
 /**
  * gtk_text_buffer_register_deserialize_tagset:
  * @buffer: a #GtkTextBuffer
- * @tagset_name: an optional tagset name, on %NULL
+ * @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
+ * format with the passed @buffer. See
  * gtk_text_buffer_register_serialize_tagset() for details.
  *
- * Return value: the #GdkAtom that corresponds to the newly registered
- *               format's mime-type.
+ * Return value: (transfer none): the #GdkAtom that corresponds to the
+ *               newly registered format's mime-type.
  *
  * Since: 2.10
  **/
@@ -275,7 +272,7 @@ gtk_text_buffer_unregister_serialize_format (GtkTextBuffer *buffer,
  *
  * 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()
+ * gtk_text_buffer_register_deserialize_tagset().
  *
  * Since: 2.10
  **/
@@ -406,11 +403,11 @@ gtk_text_buffer_deserialize_get_can_create_tags (GtkTextBuffer *buffer,
  * @n_formats: 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
+ * with @buffer using gtk_text_buffer_register_serialize_format() or
  * gtk_text_buffer_register_serialize_tagset()
  *
- * Return value: an array of #GdkAtom<!-- -->s representing the registered
- *               formats.
+ * Return value: (array length=n_formats) (transfer container): an array of
+ *               #GdkAtom<!-- -->s representing the registered formats.
  *
  * Since: 2.10
  **/
@@ -434,11 +431,11 @@ gtk_text_buffer_get_serialize_formats (GtkTextBuffer *buffer,
  * @n_formats: 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
+ * with @buffer using gtk_text_buffer_register_deserialize_format() or
  * gtk_text_buffer_register_deserialize_tagset()
  *
- * Return value: an array of #GdkAtom<!-- -->s representing the registered
- *               formats.
+ * Return value: (array length=n_formats) (transfer container): an array of
+ *               #GdkAtom<!-- -->s representing the registered formats.
  *
  * Since: 2.10
  **/
@@ -458,21 +455,22 @@ gtk_text_buffer_get_deserialize_formats (GtkTextBuffer *buffer,
 
 /**
  * gtk_text_buffer_serialize:
- * @register_buffer: the #GtkTextBuffer %format is registered with
+ * @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: 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.
+ * This function serializes the portion of text between @start
+ * and @end in the rich text format represented by @format.
  *
- * %format<!-- -->s to be used must be registered using
+ * @format<!-- -->s to be used must be registered using
  * gtk_text_buffer_register_serialize_format() or
  * gtk_text_buffer_register_serialize_tagset() beforehand.
  *
- * Return value: the serialized data, encoded as %format
+ * Return value: (array length=length) (transfer full): the serialized
+ *               data, encoded as @format
  *
  * Since: 2.10
  **/
@@ -516,19 +514,19 @@ gtk_text_buffer_serialize (GtkTextBuffer     *register_buffer,
 }
 
 /**
- * gtk_text_buffer_serialize:
- * @register_buffer: the #GtkTextBuffer %format is registered with
+ * 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: data to deserialize
- * @length: length of %data
- * @error: return loaction for a #GError
+ * @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.
+ * This function deserializes rich text in format @format and inserts
+ * it at @iter.
  *
- * %format<!-- -->s to be used must be registered using
+ * @format<!-- -->s to be used must be registered using
  * gtk_text_buffer_register_deserialize_format() or
  * gtk_text_buffer_register_deserialize_tagset() beforehand.
  *
@@ -567,6 +565,78 @@ gtk_text_buffer_deserialize (GtkTextBuffer  *register_buffer,
         {
           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 = g_slist_next (list);
+
+              /*  If a tag begins at the insertion point, ignore it
+               *  because it doesn't affect the pasted text
+               */
+              if (gtk_text_iter_begins_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 = g_slist_next (list))
+                {
+                  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,
@@ -579,6 +649,57 @@ gtk_text_buffer_deserialize (GtkTextBuffer  *register_buffer,
                          _("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 = g_slist_next (list),
+                     left_list = g_slist_next (left_list),
+                     right_list = g_slist_next (right_list))
+                {
+                  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;
         }
     }
@@ -674,8 +795,7 @@ free_format (GtkRichTextFormat *format)
 static void
 free_format_list (GList *formats)
 {
-  g_list_foreach (formats, (GFunc) free_format, NULL);
-  g_list_free (formats);
+  g_list_free_full (formats, (GDestroyNotify) free_format);
 }
 
 static GQuark
@@ -699,6 +819,3 @@ deserialize_quark (void)
 
   return quark;
 }
-
-#define __GTK_TEXT_BUFFER_RICH_TEXT_C__
-#include "gtkaliasdef.c"